在这一阶段,我们首先将apk解压,会看到如下图的6个文件和目录。其中,我们需要修改的只有2个文件,分别是classes.dex和AndroidManifest.xml文件,其他文件和文件加都不需要改动。
首先,我们把解压后apk目录下原来的classes.dex文件替换成我们在0x02上一步合成的新的classes.dex文件。然后,由于我们程序运行的时候,首先加载的其实是壳程序里的ProxyApplication类。所以,我们需要修改AndroidManifest.xml文件,指定application为ProxyApplication,这样才能正常找到识别ProxyApplication类并运行壳程序。这里,需要注意的是。
完成上述两个文件的替换后,我们就重新打包apk并签名。到此,我们就完成了dex文件的整体加固。
0x04 运行壳程序加载原dex文件
通过上面3个步骤,我们了解了dex文件整体加固的流程。那么,当这个加固后的dex文件加载到Dalvik虚拟机中,它又是如何工作的呢?下面我们就来讲解下壳程序在这里面发挥的重要作用。
首先,Dalvik虚拟机会加载我们经过修改的新的classes.dex文件,并最先运行ProxyApplication类。在这个类里面,有2个关键的方法:attachBaseContext和onCreate方法。ProxyApplication显示运行attachBaseContext再运行onCreate方法。
在attachBaseContext方法里,主要做两个工作:
-
读取classes.dex文件末尾记录加密dex文件大小的数值,则加密dex文件在新classes.dex文件中的位置为:len(新classes.dex文件) – len(加密dex文件大小)。然后将加密的dex文件读取出来,加密并保存到资源目录下
-
然后使用自定义的DexClassLoader加载解密后的原dex文件
在onCreate方法中,主要做两个工作:
-
通过反射修改ActivityThread类,并将Application指向原dex文件中的Application
-
创建原Application对象,并调用原Application的onCreate方法启动原程序
具体的app启动过程可以回看第2章的内容。
====================================================================================
源程序我们使用NDK开发一个简单的demo,并在assets目录存放一个txt文件读取。这样,我们就可以得到跟10.1.1一样的文件结构,也可以检测下加固后的文件是否影响lib文件的和资源目录下文件的操作。
工程结构如下:
MyApplication.java关键代码:
-
public class MyApplication extends Application{
-
@Override
-
public void onCreate() {
-
// TODO Auto-generated method stub
-
super.onCreate();
-
}
-
@Override
-
protected void attachBaseContext(Context base) {
-
// TODO Auto-generated method stub
-
super.attachBaseContext(base);
-
}
-
}
MainActivity.java关键代码:
-
public class MainActivity extends Activity
-
{
-
/** Called when the activity is first created. */
-
public native void test();
-
@Override
-
public void onCreate(Bundle savedInstanceState)
-
{
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.main);
-
System.loadLibrary(“demo1”);
-
test();
-
Log.v(“demo”, getFromAssets(“