查看原文
其他

ART下Hook系统函数修改内存中指定方法的运行指令逻辑案例分享

mb_atbohrok 看雪学院 2021-03-07
本文为看雪论坛优秀文章
看雪论坛作者ID:mb_atbohrok



前言


APK案例来自看雪安卓高研2w班3月份测试题目。


APP使用了数字壳加固,主要知识点是ART下免root权限动态修改dex指令,这也是ART下二代壳类函数指令抽取壳的实现原理;相比于dalvik下的类指令抽取壳实现更为巧妙简洁,dalvik下实现类函数指令抽取的原理需要进行繁琐的步骤如解析dex在内存中的映射等。


通过本案例能够了解到ART下巧妙的抽取壳实现原理。


一、脱壳和初步逻辑分析


脱壳使用基于Android 8.0的FART,一波带走,如下图所示, dump出8个dex如下图,简单修复一下2236852_dexfile_execute.dex的 magic 即可使用jadx打开查看dex逻辑。




可以在 jadx 中看到当check函数返回True时候则就成功了,因为 onCreate 被壳native 了,看不到逻辑,大概猜测就是在输入框输入flag点击按钮触发onClick中调用check返回True即可。




分析一下check函数,check函数首先是调用copyAssetAndWrite 复制了Assets中的 a.bin 到 CacheDir,然后调用testDexClassLoader,返回testDexClassLoader的返回值,为True就能得到flag了。



testDexClassLoader 调用 DexClassLoader 打开 a.bin 加载了插件类 com.kanxue.test02.TestClass,接着调用了类中的 testcontent,传进去的参数为我们输入的字符串。


那就可以说明a.bin是一个dex文件,加载里边的com.kanxue.test02.TestClass并调用testcontent函数,返回testcontent的返回值,也就是说testcontent返回值为True时候即可。





二、GET flag


那就先分析a.bin这个dex文件吧,可以看到,当传进来的字符串做md5后等于zipCode时候,返回True,这尼玛这个逻辑明显永远不可能返回True。



把所有函数和人都怀疑了一遍,之后想起我在使用FART时候并未触发onClick函数(包括FART主动调用),这也就是说这8个dex没有一个是a.bin的内存dump,挨个确认了确实如此。


重新回到FART的dump目录中,发现现在是9个dex文件,也就是新增的一个是a.bin的内存dump。

拉下来看看,发现和a.bin的不一样。zipCode变成了一串hash了。这个hash也就是kanxue的MD5。




关掉程序重新打开,输入 kanxue ,点击按钮,打印了Congratulations!,也就是我们获取到了flag为 kanxue,接着输入第二次kanxue但提示sorry,这也就是为什么要关掉程序重新打开,原理未深究。

猜测是因为第二次onClick执行testDexClassLoader加载插件类时候,因插件类已被加载到了内存而不能二次加载导致抛出异常返回了False(未验证的想法)。

下面将进行由zipCode变为md5("kanxue")的原理分析,这也是本篇文章的重点。



三、Hook系统函数修改内存中指定方法的运行指令逻辑


使用IDA打开lib下的so文件进行原理分析。


首先MainActivity中的native函数ccccccc首先调用了ddddd()函数:




ddddd()函数首先使用j_dlopen_compat函数,接着就是hook了libc中的execve函数, registerInlineHook参数为:

1、原始函数地址
2、hook的新函数地址
3、原始函数的二级指针

    


当Android7.0或以上时候进入j_fake_dlsym() fake_dlopen(),这也是为什么我使用基于安卓8.0的FART的原因。



整个函数ddddd()函数最终目的是hook execve使得dex2oat失败,从而使得加载的插件类dex不会被优化,变为oat文件之后我们动态修改的dex中的smali指令流就无效,所有hook execve禁用dex2oat是关键步骤。


进入下一个逻辑eeeee(), eeeeee()函数跟ddddd()函数类似,在/proc/self/maps中找到libart.so的内存进而hook art::ClassLinker::LoadMethod函数(上面一大串字符是其导出函数) ,registerInlineHook参数为

1、原始函数地址
2、hook的新函数地址
3、原始函数的二级指针






在Hook了LoadMethod之后,在加载插件类中的testcontent方法时候做了手脚。


下面图片可以看到 ART的LoadMethod的函数的参数,其中dst参数是类方法的指针,通过其就能拿到类函数的CodeItem的Offset。




但在本案例,在myloadmethod中,使用了a2也就是dex_file参数。




通过dex_file 把zipCode的字符串索引改变为0x01e1即 md5("kanxue")的字符串索引,所愿也就造成了dex运行逻辑的修改。





后语


在本案例较为完整的还原了抽取指令壳对抽空的类函数的还原修复。

同时hanbingle老师为了减低分析难度,并未加ollvm,这是一个难得的学习ART下二代抽取类壳的案例。




- End -





看雪ID:mb_atbohrok

https://bbs.pediy.com/user-880355.htm 

*本文由看雪论坛 mb_atbohrok 原创,转载请注明来自看雪社区。



推荐文章++++

手把手教你入门V8漏洞利用

Android微信逆向--实现发朋友圈动态

病毒样本半感染型分析的方法

对宝马车载apps协议的逆向分析研究

x86_64架构下的函数调用及栈帧原理


好书推荐





公众号ID:ikanxue
官方微博:看雪安全
商务合作:wsc@kanxue.com



“阅读原文”一起来充电吧!

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存