Slow update of Unidbg documents (2)

Slow update of Unidbg documents (2)

CallMethod

Execute JNI function

  • Create a VM object, which is equivalent to the instance object of the class that calls the native function in the Java layer
DvmObject<?> obj = ProxyDvmObject.createObject(vm, this);

Note: Unidbg will match the JNI method according to the package name of the second parameter class, so the package name of the class to which this object belongs here should match the target function

  • Use this object to call the JNI method
boolean result = obj.callJniMethodBoolean(emulator, "jnitest(Ljava/lang/String;)Z", str);

The second parameter is the signature of the method, and the corresponding function is found to execute according to the second parameter. Assuming that the package name of the class to which this object belongs at this time is: com.kanxue.test2, then it will be called at this time:

jboolean  Java_com_kanxue_test2_jnitest(JNIEnv *env, jobject thiz, jstring str);

execute any function

When we want to execute any function in SO, we can also call it by address

//获取JNIEnv *
Pointer jniEnv = vm.getJNIEnv();

//创建jobject对象
DvmObject<?> thiz = vm.resolveClass("com.kanxue.test2").newObject(null);

//准备入参
List<Object> args = new ArrayList<>();
args.add(jniEnv);
args.add(vm.addLocalObject(thiz));
args.add(vm.addLocalObject(new StringObject(vm,"XuE")));

//根据地址调用
Number[] numbers = module.callFunction(emulator, 0x9180 + 1, args.toArray());
System.out.println(numbers[0].intValue());

When the input parameters are non-pointer and Number types, you need to add the objects to the VM before you can use these objects in the VM. When the
return value is an object, the Number at this time is the hash value of the object in the VM, which needs to be passed vm.getObject() takes the object out for use, for example:

DvmObject<?> object = vm.getObject(numbers[0].intValue());
String result = (String) object.getValue();

Execute the function whose return value is passed by the parameter pointer

like:

void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);

Let's take a look at how we can actively execute this function

String initial = "unidbg";
int initial_length = initial.length();

//开辟一块的空间来存放第一个参数
MemoryBlock initial_msg = emulator.getMemory().malloc(initial_length+1, false);
UnidbgPointer initial_msg_ptr=initial_msg.getPointer();

//将参数1写入
initial_msg_ptr.write(initial.getBytes());

//开辟一块16字节的空间来存放第三个参数
MemoryBlock digest = emulator.getMemory().malloc(16, false);
UnidbgPointer digest_ptr=digest.getPointer();

//准备参数
 List<Object> args = new ArrayList<>();
args.add(initial_msg);
args.add(initial_length);
args.add(digest_ptr);
//执行
module.callFunction(emulator, 0x7A8D + 1, args.toArray());

//打印结果
Inspector.inspect(digest_ptr.getByteArray(0, 0x10), "digest");

Hook

HookZz

HookZz is the predecessor of Dobby, it is recommended to use HookZz in 32-bit mode

wrap

HookZz hook = HookZz.getInstance(emulator);
hook.wrap(module.base + 0xC09D, new WrapCallback<RegisterContext>() {
    
    
    @Override
    public void preCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {
    
    
        Pointer input = ctx.getPointerArg(0);
        System.out.println(input.getString(0));
    }

    @Override
    public void postCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {
    
    
        Pointer result = ctx.getPointerArg(0);
        System.out.println(result.getString(0));
    }
});

replace

HookZz hook = HookZz.getInstance(emulator);
hook.replace(module.base + 0x1C61, new ReplaceCallback() {
    
    
    @Override
    public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
    
    
        emulator.getBackend().reg_write(Unicorn.UC_ARM_REG_R0,1);
        return HookStatus.RET(emulator,context.getLR());
    }

    @Override
    public void postCall(Emulator<?> emulator, HookContext context) {
    
    
        System.out.println("postCall!");
        super.postCall(emulator, context);
    }
},true);

instrument

HookZz hook = HookZz.getInstance(emulator);
hook.instrument(module.base + 0x1C61, new InstrumentCallback<RegisterContext>() {
    
    
    @Override
    public void dbiCall(Emulator<?> emulator, RegisterContext ctx, HookEntryInfo info) {
    
    
        System.out.println(ctx.getIntArg(0));
    }
});

Dobby

Dobby is recommended for 64-bit mode

replace

Dobby dobby = Dobby.getInstance(emulator);
dobby.replace(module.base+0xAC90, new ReplaceCallback() {
    
    
    
    @Override
    public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
    
    
        Pointer result = context.getPointerArg(0);
        System.out.println("input:" + result.getString(0));
        return super.onCall(emulator, context, originFunction);
    }

    @Override
    public void postCall(Emulator<?> emulator, HookContext context) {
    
    
        super.postCall(emulator, context);
    }
},true);

wrap

not support

xHook

The implementation principle of the xHook framework itself has limitations, and it can only hook symbol table functions, so here is just a way of thinking, you can learn about the implementation of this hook

IxHook hook = XHookImpl.getInstance(emulator);
hook.register("libutility.so", "free", new ReplaceCallback() {
    
    
    @Override
    public HookStatus onCall(Emulator<?> emulator, HookContext context, long originFunction) {
    
    
        System.out.println("free called!");
        return HookStatus.RET(emulator,context.getLR());
    }
});
//使hook生效
hook.refresh();

Guess you like

Origin blog.csdn.net/u010559109/article/details/120947321