[原创]利用Triton 污点分析识别垃圾指令
2023-6-19 23:46 4386
此样本主要使用间接跳转
可以利用unicorn模拟执行来确定x13的值,然后修改成直接跳转或者条件跳转,
本文的重点不在这里,不在多叙。本文的重点是如何识别这些垃圾指令,
因为光恢复它的跳转,ida还是不能反编译,它指令膨胀的非常严重,将max_func_size设置成4096也不行,所以对于BR x13这种指令,需要识别x13是由哪些指令生成的,将这些指令全部nop掉,才能减少方法的size。
如上图,代码中的所有跳转全部为BR指令,包括条件跳转和直接跳转,其中还包括不透明谓词
一种是自下而上进行活跃变量分析,将BR x8 patch成b 0x1000后,将x8认为是不活跃变量,然后就可以进行活跃变量分析,然后根据ud链,找到定义x8的地方,将这个定义也删除掉。这个定义语句也会使用到变量,此时它使用到的变量也属于不活跃变量,所以可以继续向上分析,这种方式只是我理论想出来的,并没有实践
第二种是我用到的方法,污点分析,将mov x8,0x234234,这种指令的x8定义为污染源,然后向下分析,将污染过得指令全部nop掉。我觉得这种方式处理起来比较简单,对于br,bl这种跳转语句不执行,还有return块也不执行,这样就可以把整个方法当做一个巨大的代码块,由上而下的执行,将特征指令会赋值的寄存器设置成污染源,这样也可以处理这种特殊情况,在方法序言处将一个常数写入栈,在后面的代码块中从栈里面读取这个值,再使用计算,这个可以避免自己再做上下文的分析,污点分析能直接定位到。
github地址https://github.com/JonathanSalwan/Triton.git
这个工具很强大,有污点分析和符号执行两个功能,我这次只使用到了它的污点分析功能
安装 pip install tritondse
1 2 3 4 5 6 7 8 9 10 |
|
还是利用上面的那段代码,执行完1E7D00后,将w8寄存器设置为污染源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
其中的大部分代码都是模板代码,主要有用的是这两句代码,将w8设置为污染源
1 2 |
|
看下效果
在1e7d68处使用到了w8,并且将cpsr污染了,所以下一句cset指令也是污染的,
继续向下分析,可以看到间接引用w8寄存器的指令都识别出来了。
注意1e7d94处,虽然x13寄存器是被污染的,但是这条指令并没有被污染。
Triton将这种问题留给我们自己来处理,就是如果寄存器是被污染的,那么需要我们根据实际情况,来决定是否将寄存器指向的内存污染掉,上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
这个脚本多了这几句代码
1 2 |
|
作用也很简单,执行完这句代码后,将x13指向的内存也污染掉
看下效果
可以看到又多识别出来一些垃圾指令
那我们继续分别将代码块开始的几个寄存器,w8,w9,w10,w11,w12都给污染掉,上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|
看下效果
可以看到又多识别了一些垃圾指令。
还有一种特殊的栈变量,比如1E7D34处的指令,这种如何识别呢,其实在最开始已经谈到过这种情况的处理方式,这种栈变量的赋值方式一般是在方法序言处
在这里给x4赋值
在这里写到栈上
所以我们可以在0x1E4DB8处,将x4寄存器也给污染掉,上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
|
这个脚本相比之前多了这几句代码,目的是跳过所有的跳转指令,将整个方法当成一个方法块来处理,这样会简单很多,此处我没有处理ret代码块,实际使用中,还需要跳过ret代码块,不然运行过程中pc会跑飞
1 |
|
在这里将x4寄存器和它指向的内存污染掉
1 2 3 |
|
看下效果
可以看到将对栈变量的处理也识别到了。
其实讲到这里已经差不多了,剩下的就是全局扫描识别mov adrp 这种指令,当然需要过滤掉其中的正常指令,然后适配上面的代码,就可以将大部分的垃圾指令识别到,然后nop掉。对于强迫症患者来说,也是一个福音。
代码就不上传了,文章中的代码运行应该都没问题
最后于 2023-6-20 22:43 被普通人张三编辑 ,原因:
返回