逆向时如何在启动时加载自己添加的代码
现在的App中包含两三个dex已经不是很平常的事了。
我们解开App的代码后,如何方便的把我们的代码添加进去并顺利加载呢?
特别是想启动时就加载。
方法一:偷梁换柱
程序启动时只能加载第一个Dex中的类。那么我们就把代码放到smali文件夹中。
但是因为一个dex包只能包含65536个method,一般情况下smali文件夹中剩余的method空位一般不多了(因为是以类为单位,所以方法不会恰好65536个)。如果我们的代码方法数只有一两个还有可能不超,重新打包成功,否则智能把一些代码移到后面的smali_class*目录里面。这时要确保移出的类不在启动时用到,对逆向工程人员无疑是个挑战。
方法二:在代码全部装载后再启动代码
把代码放在最后一个smali_class目录里面,或再添加一个smali_class目录。然后再Application类完成所有的dex装载后插入我们的启动代码。
这个时候如果我们在Applicationd类中插入代码来启动我们的代码,App启动后仍然会提示找不到我们代码中的类。
这是因为Application类中引用了我们的代码类,但我们的代码类在最后一个dex中,类启动时是找不到我们的类的,到执行加载代码时,虽然理论上可以找到累了,但是Application类已加载解析过了,这是不会再去加载我们的类了,所以会报NoSuchClass异常。
因为Android系统的多样性和可定制性,Android虚拟机在验证类的时候没有JDK虚拟机那么严格,验证失败的类仍然可以加载执行,所以出现验证错误时,Application类仍然继续加载执行,直到遇到类找不到才退出。
所以我们就需要让Application来重新去查找加载我们的代码类。
这可以通过反射机制来实现。
1 | Clazz c = Class.forName('foo.bar'); |
为什么不放在第一个Activity里面,放在Activity里面加载,可以不用反射机制,但是App有多种启动方式,同时每次启动时先调用的Activity也可能不同,代码会更复杂一些。代码混淆后找到第一个启动的activity费的功夫也会更多一点。