最近在分析某app的网络通信逻辑,其中的加密解密都在so中完成,且有签名校验,抠取so到写的demo中运行会crash。
好吧,使用IDA打开so,发现了签名校验逻辑:
checkApp(env, context)
其中使用jni获取签名进行校验。
我把目标放到了这个函数上,通过上下文发现,只要让其返回固定的值就可以了。
为了观察SP的值变化,先把SP的值显示出来: Options -> General -> Disassembly -> Display disassembly line parts(右上角) -> Stack pointer(勾上)
现在看看破解前的汇编代码:
构建栈帧
从图中可以看出,栈深度因为一些push操作在增大。
销毁栈帧
对应的销毁是上述的逆向操作。
为了让这个函数直接返回固定的值,我决定将0x00007D46开始的指令替换为销毁栈帧的指令。
在IDA的Hex View-1中进行二进制的修改后,在进入f5页面,结果是:
checkApp(int a1, int a2,int a3,int a4,int a5)
{
return a5;
}
ok,原来的校验逻辑没有了,但返回值不是固定的值。
将movs R0,R5
改成: movs R0,#0
即可。
如何知道movs R0,#0
是多少呢?
我对于二进制不熟悉,但是可以在现有的代码中找找,于是找到一处movs R2,#0
的代码,试试将二进制的值适当调整一下,成功获取到movs R0,#0
的二进制值。
后来发现了一个不错的网站,可以做这个转化:http://armconverter.com/
修改后再使用IDA进入f5页面,结果是:
checkApp(int a1, int a2)
{
return 0;
}
ok,得到要的结果了,将so放入自己的demo中,成功执行,不再crash。