本帖最后由 hahhahah 于 2021-03-21 10:28 编辑
最近拿到一个某版本的某视频app的so,这个版本跟之前反ollvm混淆版本有所不同,于是拿JNI_OnLoad分析并记录一下 将样本放到IDA中看看JNI_OnLoad,如下
一眼看上去,貌似就是普通的ollvm混淆,但是我们先看看这个函数的结尾。
这很明显不是一个函数的结尾,跟进去sub_525A看看
这个也不像是一个函数,而且结尾用的是MOV PC,R1跳转,IDA根本不知道目的地是哪里。既然这样,模拟执行trace一下看看(具体方法见之前的的帖子),trace部分内容如下 ( libcms2.so[0xCBBCB000])[8F 46 ]0x00005264: MOV PC, R1 ;(R1=0xCBBD0270 ) ( libcms2.so[0xCBBCB000])[02 BC ]0x00005270: POP {R1} ;(SP=0x100FFF54 ) ( libcms2.so[0xCBBCB000])[11 E0 ]0x00005272: B #0XCBBD0298
先手动patch完之后再次打开IDA,可以见到MOV PC,R1指令实际上跳转到了0x00005270中,经过观察trace文件,发现该样本的所有类似BX xxx,MOV PC,xxx,实际上都仅仅是一个跳转,BX并没有起到X转换模式的作用,仅仅相当于一个B xxxx,所以我们可以通过分析trace文件,找到这类指令,统一patch成B 目标地址就行了,这样子IDA就能正常分析下去。
发现IDA无法分析JNI_Onload,是patch出了什么问题吗,我们在JNI_Onload按一下P,MakeFunction试试,发现报错如下 .text:0000505A: The function has undefined instruction/data at the specified address.
我们看到0000505A根本不是一条指令,为何会出现这种代码?往上看地址00005046,发现这里搞了个CBZ R1,loc_5058+2,故意跳到了一条指令的中间,这样子IDA肯定无法分析的,实际上如果这条指令条件是成立的话,原程序肯定也会崩溃,所以我们断定这条指令肯定不成立,处理的话直接NOP掉即可。其实这种手法在这个样本很多地方都有,后面通过脚本直接处理掉。 基本原理就是使用恒成立或者恒不成立的条件指令作为跳转,然后在另外一个不会执行的分支加入一些错误的指令让静态分析器出错,因为静态分析器遇到条件跳转指令会认为有两个分支,进入不执行的错误分支解析时候发现有不正常的指令,所以解析无法继续,这类混淆依然可以直接改成b xxxx直接去掉错误的分支,让IDA分析正常 来看看另外一个类似的混淆
我们看看loc_24A8,这个loc的代码是arm的,但是看上去非常奇怪,实际上loc_24A8是thumb的代码,造成loc_24A8被IDA识别arm的原因是loc_249E最后一条BX R1指令,R1为偶数,因此目的地被识别成arm模式,其实loc_249E根本不执行,只是用作欺骗IDA让目的块loc_24A8识别成arm。将loc_24A8改成thumb模式,代码是这样的
这里还看到一条SVC 0指令,说不定这么做是为了隐藏某个敏感的系统调用。 其实总结一下这些混淆不外乎几点 - 动态计算跳转的目的地址,使用IDA无法知道下一地址在哪里而导致cfg中断
- 使用恒成立/恒不成立的条件指令跳转,在另外一个分支上加上错误的指令干扰IDA分析
上述几点都可以通过trace修复,下面是修复脚本脚本链接(该下载链接在文中末尾隐藏内容中) 脚本的原理很简单 - 找到MOV PC,Rn, BX Rn这类指令,直接找他们的目的地址,以B 目的地址代替。这里要特殊处理一下BX Rn这类指令,在这个样本中,需要将上面一条指令NOP掉,比如看图二 loc_5252,需要将[ADDS R2, R2, R0] NOP掉,不这样处理的话,IDA依然会认为sub_525A是一个函数,这个应该是IDA识别函数的一个模式,被这个样本利用了
- 所有条件指令BNE,BGT等,如果整个trace过程中目的地址只有一个,则直接使用B 目的地址代替
下面是经过脚本处理后的JNI_Onload
真正的函数结尾
再经过ollvm反混淆后
版权声明:本文由 my1988 原创,欢迎分享本文,转载请保留出处
下方链接为所有附件和脚本链接下载地址:
游客你好,如果您要查看本帖隐藏链接需要登录才能查看,
请先登录
|