注意:Unidbg会根据第二个参数类的包名进行匹配JNI方法,所以此处的this对象所属类的包名应该与目标函数相匹配
参数二是方法的签名,根据参数二找到对应的函数来执行。假设此时的this对象所属类的包名为:com.kanxue.test2,那此时就会调用:
当我们想执行SO中任意函数时,我们也可以通过地址来进行调用
当入参为非指针和Number类型,都需要将对象先添加到VM,才能够在VM中使用这些对象
当返回值为对象时,此时的Number为该对象在VM中的hash值,需要通过vm.getObject()将对象取出进行使用,例:
如:
这种函数我们来看一下我们该如何进行主动执行
HookZz为Dobby的前身,32位模式下推荐使用HookZz
64位模式下推荐使用Dobby
不支持
xHook框架实现原理本身就存在局限性,只能够hook符号表函数,所以这里只是提供一种思路,可以学习一下这种hook的实现思路
DvmObject<?> obj
=
ProxyDvmObject.createObject(vm, this);
DvmObject<?> obj
=
ProxyDvmObject.createObject(vm, this);
boolean result
=
obj.callJniMethodBoolean(emulator,
"jnitest(Ljava/lang/String;)Z"
,
str
);
boolean result
=
obj.callJniMethodBoolean(emulator,
"jnitest(Ljava/lang/String;)Z"
,
str
);
jboolean Java_com_kanxue_test2_jnitest(JNIEnv
*
env, jobject thiz, jstring
str
);
jboolean Java_com_kanxue_test2_jnitest(JNIEnv
*
env, jobject thiz, jstring
str
);
/
/
获取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());
/
/
获取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());
DvmObject<?>
object
=
vm.getObject(numbers[
0
].intValue());
String result
=
(String)
object
.getValue();
DvmObject<?>
object
=
vm.getObject(numbers[
0
].intValue());
String result
=
(String)
object
.getValue();
void md5(const uint8_t
*
initial_msg, size_t initial_len, uint8_t
*
digest);
void md5(const uint8_t
*
initial_msg, size_t initial_len, uint8_t
*
digest);
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"
);
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"
);
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
));
}
});
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
));
}
});
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);
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
);
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)