1 背景
OLLVM(Obfuscator-LLVM)是瑞士西部应用科技大学安全实验室于2010年6月份发起的一个项目,该项目旨在提供一套开源的针对LLVM的代码混淆工具,通过代码混淆和防篡改来提高软件安全性。github上地址是https://github.com/obfuscator-llvm/obfuscator,只不过仅更新到4.0版本,2017年开始就没在更新。
本文使用到如下工具及软件:010 Editor、IDA Pro、4.8.10版本的最右APK
2 分析过程
2.1 静态分析so文件
2.1.1 IDA静态分析so文件
首先,解压apk文件,提取出lib目录下的libnet_crypto.so文件并用IDA打开,待其加载完成后查看一下字符串窗口的.data区,发现基本都是混淆加密的,如图1所示。
在Exports中搜索JNI_OnLoad函数,查看伪代码未发现混淆处理,导入jni.h头文件后修改变量类型和名称,最终得到图2中JNI_OnLoad的代码。
双击RegisterNatives函数的第三个参数off_17D010,进入.data区,如图3所示。
常规思路是应该会出现Java层方法、签名和so层方法的对应关系,结果翻车了。
接下来调转思路,尝试还原被OLLVM加密混淆的字符串信息。
2.1.2 010 Editor静态分析so文件
将libnet_crypto.so文件拖进010 Editor中,主要分析数据区域。第一个是程序头,在这里无需过多关注,第二个和第三个Loadable Segment才是是关注重点,第二个是只读的,那么根据so文件需要对字符串进行加解密的过程,因此可以判断IDA编译出的混淆字符串属于第三个区域,如图4所示。
然而,这部分的数据p_data是被混淆过的,如图5所示。
此处灵光一闪,对于这个so的还原,就需要dump出解密后的数据,将数据复制到原加密数据位置,这样就完成对字符串解密。
结合so文件的加载过程,dump的位置可能在JNI_onload、init、init_array,这就需要尝试了。
2.2 动态调试so文件
2.2.1 IDA动态调试so文件
动态调试,老套路了,依次按下列命令执行即可
./as -p 10001
adb forward tcp:10001 tcp:10001
adb shell am start -D -n cn.xiaochuankeji.tieba/cn.xiaochuankeji.tieba.ui.base.SplashActivity
打开IDA,填写主机号127.0.0.1,端口号10001,选择进程,双击进来,勾选三项
好巧不巧,在ctrl+s并搜索libnet_crypto.so,发现so文件已经被加载进去了😄😄😄,如图6所示。
那就这样吧,直接搜索dump内存中解密的字符串数据。依次点击File->script command,然后输入下列命令,替换初始地址和结束地址。
1 | static main(void) { |
2.2.2 010 Editor分析dump出来的so文件
使用010 Editor打开libnet_crypto_dumpdata.so文件,发现里面的字符串都是解密的,如图7所示。
libnet_crypto.so中的.data区中存放加密数据,可以与libnet_crypto_dumpdata.so文件对比一下。
因为libnet_crypto_dumpdata.so是从内存中dump出来的,地址应该等于libnet_crypto.so中的基地址+偏移量,所以两文件前六行基本一致。第3、7、B、F列均为固定值,第0、4、8、C列内容一样。
复制libnet_crypto_dumpdata.so文件中解密后的数据,即0070h到10DFh,然后将数据粘贴到libnet_crypto.so中的.data区的对应位置处,即光标放到17C070h处,粘贴即可,如图9所示。
2.3 字符串还原成功
最后,打开IDA查看修复后的so文件中RegisterNatives的Java层方法、签名和so层方法的对应关系,如图10所示。
3 总结
本文中的方法仅适用在内存中解密状态的情况,如果是在使用时解密,解密后再清除,需要使用动态调试。
4 参考文献
[1]https://mp.weixin.qq.com/s/TfF-xcqH--9Hv5JQ-LI3dQ
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。