论坛首页 逆向工程技术区 阅读主题

[原创]某企业壳逆向分析——从过检测到dex代码抽取还原

108 浏览 19 回复
#1 楼主 2026-06-01 21:09:09
这个壳子经常听人说,好像是frida检测特别厉害,据说国内许多银行类app都在用。逆向了一下发现非常简单,好在实现了第三代dex加固——代码抽取,刚好论坛里缺这方面的逆向帖子,这里简单补充一下。 ida打开后发现有一个init_proc,这个函数是最早执行的,早于init_array里的函数,一般包含代码解密之类的逻辑: 第一个函数没什么用,mmap了一块空间,第二个函数点进去: ida无法正常F5,是因为在代码里插入了数据: 不过无所谓,这部分主要是做了一下完整性检测,看看这部分代码有没有被篡改。核心是进入了sub_1095EC。sub_1095EC主要做了以下几件事:打开/proc/self/maps,定位到内存中的so的位置。将so中加密的数据先解压缩,再异或解密。将解密的数据回填到so内存。所以这个加固的so壳非常简单,只需要在sub_1095EC执行完后,从内存中dump出so的rx段,回填即可: 回填后可以发现这个加固很多符号名都没有去除,可以说做的相当简单。没有自定义linker,就是一个最简单的内存解密+原地回填。 so脱壳后查看一下Init_array,发现只是解密了一些字符串。查看JNI_OnLoad,没有混淆,除了注册一些native函数外,最主要的流程在key_func里: 这个加固没有ollvm混淆,脱壳后就和读源码一样容易。比较核心的流程如下:主要是通过openat访问/data/data/top.niunaijun.blackdexa32/.a和/data/data/top.niunaijun.blackdexa64/.a 如果存在就造crash退出: 根据配置决定是否开启检测,一般是开启,开启后会将检测函数包装在一个函数指针数组里,然后依次pthread_create: 检测函数都没有混淆,我们以其经常被讨论的frida检测为例: 主要有两种方式:1.首先在/proc/self/maps里检查匿名内存: 如果匿名内存是elf文件,在其内存区域全量扫描以下字符串:如果同时存在,则判定为frida。这是在检查frida的java-bridge特征,对于frida 16以下的版本有效,frida 17以上已经移除该特征。2.检查frida的DBUS协议:从20000端口检查到30000端口,如果有符合frida使用的DBUS协议的端口,则检查到。所以绕过方式只要避开20000-30000端口就行。3.退出函数n_event: 该加固检测到异常后会走统一的退出函数,第一个参数代表异常id,第二个参数是一个随机数,用于制造随机crash退出: 每一个id都对应一个异常,id表如下: 其他的检测就不再分析了,感兴趣可以自己分析,没有混淆,字符串是inline加密的,仅此而已。可以通过查看退出函数的交叉引用,快速定位到各个监测点: 至于绕过检测,只需要让这个退出函数不走crash分支即可。dex壳的知识点比较多,最核心的是dex文件相关的处理流程。简单来说,andorid会将dex文件整体加载进内存,直到程序需要使用一个类的时候,才会去解析其在dex文件中具体的实现。其中最核心的是一个类的代码,在dex文件中用code_item表示。在dex文件的class_defines里,包含每个class对应的method,每个method指向data区的CodeItem,codeitem包含了一个函数的所有dex字节码。如何在内存中获取到dex文件并进行修改?主要有两种方式:1.通过Class类的dexCache获取,这种方式可以获取指定类所在的dex文件:Java的CLass类包含了元素DexCache,DexCache包含了元素dexFile,通常为long,其值为dex文件在内存中的起始地址。任意给一个类比如com.example.bb,通过FindClass可以获取其对应的Class类。然后依次访问上述元素,可以拿到com.example.bb类所在的dex文件: 2.通过ClassLoader → DexPathList→ dexElements[] → DexFile → mCookie,获取所有已加载的dex文件。也可以主动构造dexfile,添加到dexElements元素列表里,这样就实现了主动加载一个dex文件。由于不同版本andorid的实现方式不同,所以要兼容各个版本的实现。主要是mCookie的类型在变。以上是关于dex加固加载的基础知识,接下来看看这个加固是如何加载dex的:首先通过dexcache的方式获取当前加载到内存的dex文件: 这个文件包含了壳的代码,和加密的原app的dex文件。通过dexdata0字符串,定位到内存中的加密数据: 例如0x44A0为加密数据的起始 接下来读取第0xc,0x10,0x14偏移处的3个4字节数,这些数是大端法表示的。


回复或点赞可查看完整内容

---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-291069.htm
#17 2026-06-01 21:09:09
tql
#18 2026-06-01 21:09:09
乐哥牛逼
#19 2026-06-01 21:09:09
王麻子本人

乐哥牛逼
给蛋总递茶
#20 2026-06-01 21:09:09
最后于 2026-4-30 23:46
被乐子人编辑

,原因:
‹ 上一页 1 2 下一页 ›

请登录后参与讨论

立即登录 注册账号