加密算法很简单,只是对每个字节进行异或一下 。
这里是为了简单,所以就用了很简单的加密算法,其实为了增加破解难度,我们应该使用更高效的加密算法,同时最好将加密操作放到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();}
推荐阅读
-
小南花园个体■心事重重,喜鹊展翅飞,痴心彼此,重拾前缘再爱一次,下个星期
-
生肖运势每日说|天赐大吉兆,横财滚滚来,咸鱼翻身的生肖,6月26号起贵人帮衬
-
菲常视界出品|请正视一下汽车保值率!汽车保值率是购车考虑因素之一
-
-
文娱汇聚|女明星当中的”富婆“,在她面前都不算啥!
-
『科技微看点』塞宾智麦体验报告:Vlog达人神器还是徒有虚名?深度体验给你
-
-
EDGM|EDGM2-3不敌LGD,创KPL新连败纪录,17连败已“超越”AG!
-
-
-
农村小小薇|新农合上涨到280块,有4种人不需要交,快看看有你嘛?,2020年
-
生肖|“永远不变心”的4大生肖,对妻子很衷心,生活一直很幸福
-
云南网|11月1日零时起,云南展开第七次全国人口普查工作
-
「惠威」惠威AW-71S真无线耳机评测:S升级版 惠威的这个“S”带来了什么?
-
星晖杂谈|真正为林黛玉着想的人是紫鹃,一片冰心在玉壶
-
-
人民日报再论就业观引网友热议,“三代同企”的世袭制已是毒瘤!
-
周杰伦的歌是我们的青春?每个人的青春里都有一首周杰伦
-
-
无题中表示相思离别之痛苦的诗句?才别离又相思的诗句