1.Long参数的传递
假设一个native函数中参数是long类型,比如这样
在编译成arm32的SO时,一定概率会被转成两个int.
long a = 0x1000L → int a1 = 0,int a2 = 0x1000
在Unidbg主动调用时,一定要记得处理,否则会出问题.这是一个常见问题,JAVA层传入的时间戳,常常就是jlong.
处理办法有2
1是按照SO的情况,传给它两个int
2是按照传入诸如 long tm= 1621265630L;
的标准写法,Unidbg自动帮我们分割成两个
2.jbytearray 怎么查看
更宽泛的问法是,有个jobject对象,想查看它的内容,最常见的就是jbyteArray
Frida中可以这么操作
hexdump(ptr(Java.vm.tryGetEnv().getByteArrayElements(args[0])))
Unidbg中当然也可以,以hookZz中为例
public void preCall(Emulator<?> emulator, HookZzArm32RegisterContext ctx, HookEntryInfo info) {
UnidbgPointer jbytearrayptr = ctx.getPointerArg(2);DvmObject<?> dvmbytes = vm.getObject(jbytearrayptr.toIntPeer());// 取出bytebyte[] result = (byte[]) dvmbytes.getValue();// 转换成String 或者按需转成其他System.out.println(new String(result));
};
3.std::string 的读写
public String readStdString(Pointer strptr){
Boolean isTiny = (strptr.getByte(0) & 1) == 0;if(isTiny){
return strptr.getString(1);}return strptr.getPointer(emulator.getPointerSize()* 2L).getString(0);
}public void writeStdString(Pointer strptr, String content){
Boolean isTiny = (strptr.getByte(0) & 1) == 0;if(isTiny){
strptr.write(1, content.getBytes(StandardCharsets.UTF_8), 0, content.length());}strptr.getPointer(emulator.getPointerSize()* 2L).write(0, content.getBytes(StandardCharsets.UTF_8), 0, content.length());
};
4.TraceCode为什么trace不到module init中的指令
是因为traceCode的执行时机晚了,load library在它前面…只需要确认module base 和module size后,将emulator.traceCode写在loadlibrary前面即可.
5.HOOK 框架使用问题
Unidbg支持了数个Hook框架,HookZz和Dobby就是其中两个.有人会困惑,HookZz不就是Dobby前身吗,两者不是一个东西吗?为什么要说两个Hook框架?
这其实是有原因的,Unidbg作者在注释中写道:HookZz在arm32位上支持较好,Dobby在64位上支持较好.(因此将两者,或者说Dobby以及其前身HookZz作为两个独立Hook工具)