Android逆向学习|对ARM指令的一次学习
吾爱破解教程链接《教我兄弟学Android逆向08 IDA爆破签名验证》
前言
IDA pro我之前接触过,但用它修改指令和数据还是第一次。通过上一篇教程,我知道了用ida修改so文件,实际上就是修改数据对应的HEX值。比如将hello 52pojie修改为hello world,就是将其对应的16进制修改。而在这篇爆破签名验证的教程中,需要我去修改CPU指令。原理和修改数据相同,也是修改指令对应的hex值,但不是字符串转换那么简单了。
对ARM架构的CPU简单介绍
在开始之前有必要了解一下ARM架构CPU的知识。我们都知道pc领域cpu的老大是Intel,而移动设备cpu老大就是ARM。不同的cpu架构对应不同的指令集。Intel和ARM两大阵营还可以再细分。Intel的架构中x86
代表32位cpu,x86_64
代表64位的cpu,x86汇编语言学习最为普遍。ARM架构也有32位和64位之分。
在此例中,我们使用apktool对app进行反编译,lib下得到三个包含so的文件夹。
1 | armeabi : 32位 arm cpu 库,几乎所有手机都支持 |
这三个版本的库在指令上有多差别。作为初学者,我们选择 armeabi 下的 libJniTest.so 库作为研究对象,便于在网上查找资料。
Google一开始就没把筹码都压在ARM上,Android1.6开始Dalvik虚拟机提供对x86的支持。Android4.1加入了对MIPS的支持。
修改指令:将 BNE 改为 BEQ
根据教程一步步操作,来到了最关键的地方
1 | cmp 是比较两个数是否相等 |
搞清楚了逻辑,那么爆破这个apk的签名其实就是把 BNE loc_F62
改为 BEQ loc_F62
,即签名一致则跳转到 loc_F62退出程序,我们的签名和作者签名一定不同,所以程序不会直接退出,爆破成功。
选中BNE指令来到hex dump视图,对应的16进制为10D1
查看下方的BEQ指令来到hex dump视图,对应的16进制为09D0
原教程中说将10D1改为10D0即完成了BNE到BEQ的修改,但是为什么这样修改呢?
深入问题
在《计算机组成原理》和《汇编语言》中,我们知道了计算机指令的组成
1 | 一条指令(32位) = 操作码(前16位):操作数(后16位) |
操作码代表做哪些运算,例如:ADD、MOV、B 等等
操作数就代表被操作的数据,即可以是数据也可以是地址。
回到此例中
1 | BNE loc_F62 对应机器码 10 D1 对应二进制 0001 0000 1101 0001 |
哪几位对应指令,哪几位对应数据呢?我们再往下看。
查询arm的官方指令手册可以知道B(跳转指令的用法)
1 | B指令 |
再对照条件码表
我们可以得到指令对应的机器码
1 | BNE 1101 0001 |
这样一看就清晰明了了,此例中对应的二进制居然是数据在前,指令在后的。故修改时应将1101 0001
改为1101 0000
即为D1
改为D0
cpu指令必然是操作码在前,数据在后。只不过是ida hex视图显示下,16进制高位在右,低位在左。所以看起来是反过来了,但实际上书写的时候操作码是在高位的。所有的16进制编辑器都是这样显示的。
结论
ida pro 反汇编 Android SO库(armeabi版本) ,一条汇编指令如果由4个十六进制数组成的,so库的指令格式如下:
1 | 一条SO的汇编指令(16位) = 操作码(前8位) :操作数(后8位) |
修改后即可绕过签名验证
后续作业绕过登录验证的代码也在so中,修改思路大致相同,同样是更改判断语句的条件。
总结
对arm的原生逆向比对smali的逆向要困难的多。理解各种指令的使用方法才能更好的理解程序并做出修改。
Arm指令转16进制速查可使用Arm汇编指令转机器码网站:http://armconverter.com/但是ida pro反编译SO库用的是 Thumb-2 指令集,这个指令集是 arm 指令集的子集。转码网站似乎不在支持Thumb-2指令集,只有一个Thumb选项,和ida pro反编译的内容略有差别。
参考资料
https://www.52pojie.cn/thread-732955-1-1.html
《Android软件安全与逆向分析》
https://blog.csdn.net/fuchaosz/article/details/104804026
感谢CSDN博主“梧桐那时雨”的文章,我十分敬佩他对问题钻研的态度