加密算法很简单,只是对每个字节进行异或一下 。
这里是为了简单,所以就用了很简单的加密算法,其实为了增加破解难度,我们应该使用更高效的加密算法,同时最好将加密操作放到native层去做 。
这里需要两个输入文件:
- 源程序APK文件:SourceApk.apk
- 壳程序的DEX文件:SourceApk.dex
第一个文件就是源程序项目编译之后的APK文件,第二个文件是下面要讲的第三个项目:壳程序项目中的classes.dex文件,修改名称之后得到 。3.壳程序项目:PackApk

文章插图
先来了解一下壳程序项目的工作:
- 通过反射置换android.app.ActivityThread中的mClassLoader为加载解密出APK的DexClassLoader,该DexClassLoader一方面加载了源程序,另一方面以原mClassLoader为父节点,这就保证即加载了源程序,又没有放弃原先加载的资源与系统代码 。关于这部分内容不了解的可以看一下Android动态加载之免安装运行程序这篇文章 。
- 找到源程序的Application,通过反射建立并运行 。这里需要注意的是,我们现在是加载一个完整的APK,让他运行起来 。一个APK运行的时候都是有一个Application对象的,这个也是一个程序运行之后的全局类,所以我们必须找到解密之后的源程序APK的Application类,运行它的onCreate方法,这样源程序APK才开始它的运行生命周期 。后面会说如何得到源程序APK的Application类:使用meta标签进行设置 。
下面看一下整体流程:

文章插图
下面看一下代码: ProxyApplication.java
- 得到壳程序APK中的DEX文件,然后从这个文件中得到源程序APK进行解密、加载
// 这是context赋值@Overrideprotected void attachBaseContext(Context base) { super.attachBaseContext(base); try { // 创建两个文件夹payload_odex、payload_lib,私有的,可写的文件目录 File odex = this.getDir("payload_odex", MODE_PRIVATE); File libs = this.getDir("payload_lib", MODE_PRIVATE); odexPath = odex.getAbsolutePath(); libPath = libs.getAbsolutePath(); apkFileName = odex.getAbsolutePath() + "/payload.apk"; File dexFile = new File(apkFileName); Log.i("demo", "apk size:"+dexFile.length()); if (!dexFile.exists()) { dexFile.createNewFile(); //在payload_odex文件夹内,创建payload.apk // 读取程序classes.dex文件 byte[] dexdata = https://www.isolves.com/it/cxkf/ydd/Android/2019-09-04/this.readDexFileFromApk();// 分离出解壳后的apk文件已用于动态加载 this.splitPayLoadFromDex(dexdata); } // 配置动态加载环境 Object currentActivityThread = RefInvoke.invokeStaticMethod( "android.app.ActivityThread", "currentActivityThread", new Class[] {}, new Object[] {});//获取主线程对象String packageName = this.getPackageName();//当前apk的包名 ArrayMap mPackages = (ArrayMap) RefInvoke.getFieldOjbect( "android.app.ActivityThread", currentActivityThread, "mPackages"); WeakReference wr = (WeakReference) mPackages.get(packageName); // 创建被加壳apk的DexClassLoader对象 加载apk内的类和本地代码(c/c++代码) DexClassLoader dLoader = new DexClassLoader(apkFileName, odexPath, libPath, (ClassLoader) RefInvoke.getFieldOjbect( "android.app.LoadedApk", wr.get(), "mClassLoader")); //把当前进程的mClassLoader设置成了被加壳apk的DexClassLoader RefInvoke.setFieldOjbect("android.app.LoadedApk", "mClassLoader", wr.get(), dLoader);Log.i("demo","classloader:"+dLoader); try{ Object actObj = dLoader.loadClass("com.example.sourceapk.MainActivity"); Log.i("demo", "actObj:"+actObj); }catch(Exception e){ Log.i("demo", "activity:"+Log.getStackTraceString(e)); } } catch (Exception e) { Log.i("demo", "error:"+Log.getStackTraceString(e)); e.printStackTrace(); }}这里需要注意的一个问题,就是我们需要找到一个时机,就是在壳程序还没有运行起来的时候,来加载源程序的APK,执行它的onCreate方法,那么这个时机不能太晚,不然的话,就是运行壳程序,而不是源程序了 。查看源码我们知道 。Application中有一个方法:attachBaseContext这个方法,它在Application的onCreate方法执行前就会执行了,所以我们的工作就需要在这里进行 。A) 从APK中获取到DEX文件
/** * 从apk包里面获取dex文件内容(byte) * @return * @throws IOException */private byte[] readDexFileFromApk() throws IOException { ByteArrayOutputStream dexByteArrayOutputStream = new ByteArrayOutputStream(); ZipInputStream localZipInputStream = new ZipInputStream( new BufferedInputStream(new FileInputStream( this.getApplicationInfo().sourceDir))); while (true) { ZipEntry localZipEntry = localZipInputStream.getNextEntry(); if (localZipEntry == null) { localZipInputStream.close(); break; } if (localZipEntry.getName().equals("classes.dex")) { byte[] arrayOfByte = new byte[1024]; while (true) { int i = localZipInputStream.read(arrayOfByte); if (i == -1) break; dexByteArrayOutputStream.write(arrayOfByte, 0, i); } } localZipInputStream.closeEntry(); } localZipInputStream.close(); return dexByteArrayOutputStream.toByteArray();}
推荐阅读
-
安心生活研究所|都是苦行僧般的自律,郭麒麟196斤旧照曝光:所有光鲜背后
-
家养酢浆草,从播种到开花,只需要学会2点,花朵挤满花盆!
-
『西安信达会计』如何懂得对财务信息进行有效地鉴别?
-
-
凤凰金融,京东理财这些互联网理财产品收益还行,那么问题是风险何如
-
女人|它是穷人的燕窝,3元钱就能煮一大锅,女人常喝,40岁还是少女
-
交谈技巧有哪些 交谈技巧有哪些失败案例并说明原因分析
-
TVB老戏骨蒋志光承认离巢,最后库存剧将播,离巢后最想做一件事
-
『女排』巅峰时选择退役、嫁给了1米85的富二代老公,1米9的最美女排队长如今怎么样了?
-
asp.net core源码如何实现监听Http请求,分析Kestrel看一下过程
-
-
-
-
-
历史之奇闻|等到70高龄才造反,他到底在怕什么?,司马懿熬死了曹家3代人
-
日本|为什么日本癌症死亡率低,存活率高?预防癌症,有哪些妙招?
-
高通|损失的何止547亿!高通两次发声,这结果特朗普没想到!
-
「古镇」江苏一古镇沦为空城:玩一圈得重复收费6次,现人去楼空没人愿去
-
「科技外援队」三星详细介绍Galaxy Z Flip的面板小屏幕功能
-
许晴|3位至今都没人娶的女星,被称为“绝色美人”,娶到就是血赚啊