首页
社区
课程
招聘
[原创]Android-SO复杂VMP的分析思路
发表于: 1天前 848

[原创]Android-SO复杂VMP的分析思路

1天前
848

之前分享过:[原创]Android-ARM64的VMP分析和还原,里面的样本比较简单,IDA按F5可以直接看到伪代码。

金罡大佬分享了复杂的样本:[原创]用魔法打败魔法:互联网大厂虚拟机分析还原,F5没办法直接看到伪代码,文章里面对vm_entry进行patch,让IDA顺利进行反编译。

简单的简单大佬分享了[原创] VMP攻略笔记,里面更是进一步对最复杂vm_interpreter进行patch,大大提升了分析的效率。

可惜的是,两位大佬分享的更多是VMP的分析结论,VMP的分析思路较少。而这篇文章主要补充两点:1、结合两位大佬的文章,猜测一下大佬对VMP的分析思路;2、进一步优化patch,在IDA上能直观看到:只有一个主分发器switch,并且case直接对应handle。

先找到VMP的入口:vm_entry

正常写代码:caller(调用者)和callee(被调用者)

因为同一个函数可能被多个函数调用,当callee(被调用者)被虚拟化,一般不会修改多个caller(调用者),而只是修改一个callee(被调用者)本身。

换句话说,被虚拟化的函数,内部所有逻辑变成只跳转到虚拟机入口vm_entry。

利用这个特点,可以定位虚拟机入口:vm_entry

1、只有一个函数调用

2、调用完恢复栈帧

3、紧接着直接RET

此外,对于大型一些的apk,同一个vm_entry很可能被多个地方调用,因此加上规则:

4、调用vm_entry次数多

按照上面的规则,可以写对应的脚本:

看下调用的地方,确实类似:vm_entry(vinsts, args); 

进入sub_1313F0,会发现不是一个正常的函数。

明明调用sub_1313F0的地方有传递多个参数,但sub_1313F0内部没看到参数。

这就意味着ida的反编译识别有问题,在这里被加了对抗手段。

看下sub_1313F0具体的汇编

sub_25D00的核心作用正是根据传入的索引值,动态修改返回地址,实现跳转。

用公式表达就是:目标地址 = 返回地址 + *(返回地址 + 索引 × 4)

简单说,这里通过间接跳转的方式,让ida反编译失效。

对应的,我们可以写一个脚本,让间接跳转变成直接跳转:

效果如下:

但是这个时候按F5还是反编译出错

需要把patch的结果保存到so,然后重新加载so到IDA里面进行完整分析:

具体步骤:工具栏:Edit -> Patch program -> Apply patches to input file ...

图片描述

图片描述

退出当前ida,重新加载so,就可看到正常的vm_entry:sub_1313F0

图片描述

而这个函数的逻辑比较简单

封装可变参数:pVA,得到返回结果pResult,然后传给sub_131680

图片描述

进入sub_131680,IDA能正常反编译,但这个函数比较大,以结果为导向,直接看pResult是怎么处理的。

从截图可以看出,pResult没有做额外处理,而是直接传给sub_138518,并且直接返回。所以sub_131680这个函数是vm_ready:只是做一些准备,还没真正进行虚拟代码的解释运行。

图片描述

进入sub_138518,提示13CEF4不是有效的基本块

图片描述

跳到13CEF4,可以看到13CEF4是一个数据,而不是基本块,并且被引用 XREF

图片描述

查看13CEF4引用,发现是在.data.rel.ro,这里一般存放的是函数指针或者虚函数表而ida根据这个规则,会对里面的地址识别成指向可以执行代码的基本块但13CEF4实际上是数据块,导致ida进行F5反编译的时候出错

图片描述

而修改的办法就是把指向13CEF4改为指向一个新地址,让13CEF4不会被识别成代码,这里直接上简单的简单大佬的脚本:

修改之后,效果如下:

图片描述

而sub_138518就可以按F5进行反编译,结果如下:

图片描述

伪代码可以看出这个函数比较简单,只有两个case。但是从CFG图上看这个函数,会发现实际上很复杂。

图片描述

进一步跟踪switch和case的逻辑,从汇编可以看出这里是特殊的二级跳转表switch,不是普通的一级跳转表switch。普通的一级跳转表switch,对应的case是从0、1、2...连续的。而特殊的两级跳转表switch一般是为了解决稀疏的 case 值,也就是case间隔比较大的情况。

并且这个二级跳转表还不是固定同一个位置,而是分散开被多处引用

图片描述

因此,这里遇到两个麻烦的问题:

对于这个问题,简单的简单大佬的解决思路如下:

第3步类似inline hook,构建一段新的ifelse基本块,然后原地址JMP过去因为第2步拦截多个地址,并且对应的case有多个,导致ifelse基本块也要多个

这个思路确实解决了上面的问题1,让IDA反编译出完整的函数。但问题2还是存在,毕竟是多个地方加上各种跳转。

为了方便后续的分析,可以进一步优化,更解决问题2。对应的思路如下:

简单来说就是:

可以看出,case不是连续的

缺失的case默认指向0

模拟一级跳转表switch的汇编,创建一个新的分发器:

其中

等价

从下往上找到:BR->LDR->LDR->ADD

把一开始的case存入X16,然后两条LDR都NOP掉,之后直接跳到分发器

参考前面说的,保存patch到so,退出重新加载so。会发现这个时候IDA依旧反编译有问题,需要手动调整一下。

进入0x144220,改成成数组:

图片描述

图片描述

图片描述

进入0x1443A0,手动设置成switch:

图片描述


[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 1天前 被GhHei编辑 ,原因: 微调
收藏
免费 69
支持
分享
最新回复 (24)
雪    币: 87
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
666
1天前
0
雪    币: 3029
活跃值: (6768)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
牛逼
1天前
0
雪    币: 1736
活跃值: (1865)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
666666
1天前
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
感谢分享
1天前
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
感谢分享
23小时前
0
雪    币: 396
活跃值: (3393)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
感谢分享
23小时前
0
雪    币: 1
活跃值: (1315)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
6
22小时前
0
雪    币: 6481
活跃值: (6325)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
66
22小时前
0
雪    币: 9994
活跃值: (7856)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
10
写太多我怕律师函警告
21小时前
0
雪    币: 104
活跃值: (7947)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
tql
21小时前
0
雪    币: 4477
活跃值: (3715)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
简单的简单 写太多我怕律师函警告[em_071]
没事,前面的大佬写更多
21小时前
0
雪    币: 1
活跃值: (203)
能力值: ( LV2,RANK:11 )
在线值:
发帖
回帖
粉丝
13
mark
21小时前
0
雪    币: 1532
活跃值: (4078)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
14
偷偷学一手
20小时前
0
雪    币: 293
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
566666666666
20小时前
0
雪    币: 610
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
6666666
19小时前
0
雪    币: 3630
活跃值: (8663)
能力值: ( LV7,RANK:102 )
在线值:
发帖
回帖
粉丝
17

看看高手是怎么分析的,其实这种BR似乎可以试试BinaryNinja,效果好很多

最后于 19小时前 被fjqisba编辑 ,原因:
19小时前
0
雪    币: 4477
活跃值: (3715)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
18
fjqisba 看看高手是怎么分析的,其实这种BR似乎可以试试BinaryNinja,效果好很多
改天试试~
16小时前
0
雪    币: 3386
活跃值: (4384)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
过来瞧瞧
13小时前
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
66
5小时前
0
雪    币: 216
活跃值: (2771)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
666
5小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
666
2小时前
0
雪    币: 5893
活跃值: (10332)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
火钳刘明
2小时前
0
雪    币: 429
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24
6666
1小时前
0
雪    币: 1883
活跃值: (1887)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
感谢分享
50分钟前
0
游客
登录 | 注册 方可回帖
返回