如果想要在unidbg中修改程序的逻辑代码,那么可以利用Patch技术。
接下来将图3—19中地址为0x3E8的ADDS指令修改为SUBS指令,也就是将原函数的绝对值相加功能改为绝对值相减功能。可以通过https://armconverter.com/来将汇编指令转换为机器码,得到D01A,如图3—23所示。
在MainActivity.java中添加patch()方法。
图3—23 将汇编指令转换为机器码
public void patch(){
//module.base+0x3E8得到内存中相应的地址,获得指向该地址的指针
UnidbgPointer pointer=UnidbgPointer.pointer(emulator,module.base+0x3E8);
byte[]code=new byte[]{(byte)0xd0,0x1a};
pointer.write(code);
}
在unidbg中,可以借助UnidbgPointer封装的API来读写内存,也可以通过传入地址来获得一个指针,进而对该内存进行读写操作。
此处便通过指针来将相应的机器码写入内存,达到Patch的效果。通过UnidbgPointer.write()写入两个指令字节,将ADDS指令修改为SUBS指令。
在main()方法中添加mainActivity.patch()方法调用,运行成功后的结果如图3—24所示,值变为了-1。
图3—24 通过机器码Patch运行结果
但是,每次手动将汇编指令转换为机器码比较麻烦,可以借助Keystone来将汇编指令自动转换为机器码,再进行Patch。
编写patch2()方法,代码如下:
public void patch2(){
UnidbgPointer pointer=UnidbgPointer.pointer(emulator,module.base+0x3E8);
//指定架构和模式实例化一个Keystone对象
Keystone keystone=new Keystone(KeystoneArchitecture.Arm,KeystoneMode.
ArmThumb);
//要修改的汇编指令
String s="subs r0,r2,r3";
//获得机器码字节数组
byte[]machineCode=keystone.assemble(s).getMachineCode();
pointer.write(machineCode);
}
该代码只是将人工转换机器码的工作交给了Keystone来做。首先实例化一个keystone对象,传入架构为Arm、模式为ArmThumb。然后使用keystone.assemble(s).getMachineCode()将汇编指令转换为机器码字节数组来进行Patch操作。
在main()方法中调用上述方法,运行结果如图3—25所示。
图3—25 通过汇编指令Patch运行结果