[原创]360加固之onCreate函数还原并重打包
断断续续弄360的壳子搞了个把月,把这次的成果分享给大家。。。
在还原之前,我们需要一份360加固的指令映射表,感谢https://bbs.pediy.com/thread-222412.htm这篇文章提供的指令映射表,我对这个表进行了补全,包含所有的Dalvik opcode
struct DexCode {
u2 registersSize;
u2 insSize;
u2 outsSize;
u2 triesSize;
u4 debugInfoOff;
u4 insnsSize;
u2 insns[1];
};
对于native onCreate函数的DexCode,前0x10个字节没有加密, 后面的insns被360加密了,我们需要做的就是将insns指令还原,
加密的insns指令以及解码insns指令的key值都是通过parse_tree这个函数得到的,其中第一个参数是一个全局变量,第二个参数是"类名->方法名"

虽然可以手动改变第二个参数为不同类的onCreate方法,来获取不同方法的加密指令insns,但是我分析的样本是360自家的一个App,共有49个native onCreate函数,手动弄很麻烦,
手动调用parse_tree函数
还原的核心思路就是手动调用parse_tree函数,
由于parse_tree函数是在360的第二个so里面,而且是通过内存加载的方式来加载这个so,这里我们来进行“
二阶Hook
” 获取parse_tree函数地址
首先Hook dlopen函数得到libjiagu.so的基址,在new_dlopen函数中内存加载函数soMemLoader

在new_soMemLoader函数中,调用完原始函数后,表示第二个so已经内存加载完成,并且初始化了init和init_array函数,根据偏移获取parse_tree函数地址,获取第一个参数使用全局变量,但是我们需要保证这个全局变量指向的内容是初始化了的,所以我们可以继续在这里Hook JNI_OnLoad函数,等JNI_OnLoad执行完以后,保证全局变量所在的内存数据是正确的。

在new_JNI_OnLoad函数中,当JNI_OnLoad函数执行完以后,就开始还原所有的onCreate函数了。


手动调用parse_tree函数进行解密

还原过程中有几个坑需要注意
1.Try/Catch的处理

2.packed-switch,sparsed-switch,fill-data指令的处理

修复之后jeb和jadx可以完美地反编译onCreate函数了。
重打包
原始的Application其实保存在strEntryApplication = "com.qihoo360.crypt.entryRunApplication",在JNI_OnLoad中动态修改为原始的Application了,com/stub/StubApp的strEntryApplication成员
替换为com.qihoo.root.AuthApp

一般第一个activity都没变,但是我这个样本的启动activity不是原始的dex,而是360自带的一个dex,将类"com/stub/stub01/StartActivity"的成员mEntryActivity替换为com.qihoo.root.SplashActivity

还有一些小细节懒得说了。
不过360最新的dex vmp好像没用指令映射表,本文的方法应该可以适用最新版本以前的。。。
