bytedance / bhook

:fire: ByteHook is an Android PLT hook library which supports armeabi-v7a, arm64-v8a, x86 and x86_64.
https://github.com/bytedance/bhook/tree/main/doc#readme
MIT License
2.05k stars 315 forks source link

请问安卓9的open函数hook不到是什么原因。同样代码安卓10是没有问题的。 #16

Closed LeeKasm closed 2 years ago

LeeKasm commented 2 years ago

Android层测试代码: File file = new File("/storage/emulated/0/1.txt"); try { FileInputStream fileInputStream = new FileInputStream(file); byte[] buf = new byte[(int)file.length()]; fileInputStream.read(buf); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); }

c层hook代码: bytehook_hook_single("libjavacore.so", NULL, "open", open_proxy, open_hooked_callback, NULL); bytehook_hook_single("libjavacore.so", NULL, "stat", stat_proxy, stat_hooked_callback, NULL); bytehook_hook_single("libjavacore.so", NULL, "read", read_proxy_auto, read_hooked_callback, NULL);

安卓9的回调显示hook成功了。 bytehook_tag: >>>>> hooked. stub: c6b93ac0, status: 0, caller_path_name: /system/lib/libjavacore.so, sym_name: open, new_func: c5e08ebd, prev_func: e756aefd, arg: 0 安卓10的回调也类似。 bytehook_tag: >>>>> hooked. stub: ba5d3480, status: 0, caller_path_name: /apex/com.android.runtime/lib/libjavacore.so, sym_name: open, new_func: c04afebd, prev_func: edaa2299, arg: 0 但是实际测试中在open入口打印,只有安卓10的设备有响应。 LOG("open hooked path(\"%s\")", pathname);

caikelun commented 2 years ago

如果要处理兼容性,需要hook:open,__open_real,__open_2。 可以参考bytehook的sample app:https://github.com/bytedance/bhook/blob/main/bytehook_sample/src/main/cpp/hacker.c#L152

LeeKasm commented 2 years ago

您误会了,在此之前我都尝试过了,是不行的。 这可能是个bug,上一条是为了简化现象说的不够具体。

__open_real在API17之后已经不用了,在安卓9上应该不用_open_real。

if __ANDROID_API >= 17 && BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED

return __open_2(pathname, flags);

else

return __open_real(pathname, flags);

endif

除了open,stat等函数在安卓9上也hook不到,意外的是read却可以。

LeeKasm commented 2 years ago

另外需要明确的是hook自己写的so库是没有这个问题的。目前发现的仅仅是安卓9 libjavacore.so库下libcore_io_Linux.cpp的open hook不到。

caikelun commented 2 years ago
  1. 可以反编译一下被hook的so,看看源码中对应位置最后调用了什么函数,以及怎么调用的。
  2. 可以动态调试一下,确认下程序流程确实走到了你预期的位置。
LeeKasm commented 2 years ago

您好,下面说的可能不完全正确但是应该方向大差不差,根据您的建议我反编译了libjavacore.so,确实存在open函数。

在安卓9中Java层的FileInputStream类实例化时对文件打开, 调用 libcore.io.IoBridge.open(String path, int flags), 进而调用了native方法libcore.io.Linux.open(String path, int flags, int mode), 随后进入底层libjavacore.so中libcore_io_Linux.cpp的Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode)。

我用xhook验证,hook libjavacore.so的open可以打印出信息,也说明open函数是在这个so中。 但是用bhook虽然hook到了但是无打印结果,应该是没hook上。

caikelun commented 2 years ago

您好,下面说的可能不完全正确但是应该方向大差不差,根据您的建议我反编译了libjavacore.so,确实存在open函数。

在安卓9中Java层的FileInputStream类实例化时对文件打开, 调用 libcore.io.IoBridge.open(String path, int flags), 进而调用了native方法libcore.io.Linux.open(String path, int flags, int mode), 随后进入底层libjavacore.so中libcore_io_Linux.cpp的Linux_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode)。

我用xhook验证,hook libjavacore.so的open可以打印出信息,也说明open函数是在这个so中。 但是用bhook虽然hook到了但是无打印结果,应该是没hook上。

收到,感谢反馈,我调试一下。。。 能问下你的android 9设备的机型吗?

LeeKasm commented 2 years ago

您好,我用的两个设备分别是: HUAWEI Mate9,型号:MHA-AL00,版本号:9.1.0.231; HUAWEI MediaPad M5 lite 10,型号:BAH2-AL10,版本号:9.1.0.170;

caikelun commented 2 years ago

@LeeKasm 我在“HUAWEI Mate9,型号:MHA-AL00”上试了下,bhook和xhook hook libjavacore.so 的open都是成功的,但是java层执行你贴的FileInputStream逻辑,都无法走到proxy函数中。你可以再用xhook确认下。

另外,你可以动态调试确认下FileInputStream流程确实会走到open?可以用inlinehook确认下,或者直接用frida之类的工具。

LeeKasm commented 2 years ago

我重新测试了下,您说的对,确实是我把几个设备搞混了。 安卓9走的libopenjdk.so,安卓10是走的libjavacore.so。 抱歉因为我的调试失误给您强行加了波班😀

zhbzhbzhbz commented 2 years ago

Android层测试代码: File file = new File("/storage/emulated/0/1.txt"); try { FileInputStream fileInputStream = new FileInputStream(file); byte[] buf = new byte[(int)file.length()]; fileInputStream.read(buf); fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); }

c层hook代码: bytehook_hook_single("libjavacore.so", NULL, "open", open_proxy, open_hooked_callback, NULL); bytehook_hook_single("libjavacore.so", NULL, "stat", stat_proxy, stat_hooked_callback, NULL); bytehook_hook_single("libjavacore.so", NULL, "read", read_proxy_auto, read_hooked_callback, NULL);

安卓9的回调显示hook成功了。 bytehook_tag: >>>>> hooked. stub: c6b93ac0, status: 0, caller_path_name: /system/lib/libjavacore.so, sym_name: open, new_func: c5e08ebd, prev_func: e756aefd, arg: 0 安卓10的回调也类似。 bytehook_tag: >>>>> hooked. stub: ba5d3480, status: 0, caller_path_name: /apex/com.android.runtime/lib/libjavacore.so, sym_name: open, new_func: c04afebd, prev_func: edaa2299, arg: 0 但是实际测试中在open入口打印,只有安卓10的设备有响应。 LOG("open hooked path("%s")", pathname);

@LeeKasm 求问您方便分享下您hook read和write的代码么~ C语言小白想参考下

LeeKasm commented 2 years ago

@zhbzhbzhbz

bytehook_hook_single("libjavacore.so", NULL, "read", (void *) my_read, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "pread64", (void *) my_pread64, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "readv", (void *) my_readv, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "write", (void *) my_write, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "pwrite64", (void *) my_pwrite64, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "writev", (void *) my_writev, NULL, NULL);
zhbzhbzhbz commented 2 years ago

@zhbzhbzhbz

bytehook_hook_single("libjavacore.so", NULL, "read", (void *) my_read, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "pread64", (void *) my_pread64, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "readv", (void *) my_readv, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "write", (void *) my_write, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "pwrite64", (void *) my_pwrite64, NULL, NULL);
bytehook_hook_single("libjavacore.so", NULL, "writev", (void *) my_writev, NULL, NULL);

谢谢!!!

zhbzhbzhbz commented 1 year ago

如果要处理兼容性,需要hook:open,__open_real,__open_2。 可以参考bytehook的sample app:https://github.com/bytedance/bhook/blob/main/bytehook_sample/src/main/cpp/hacker.c#L152

最近发现,c语言下的open(path, O_RDONLY);会触发open2或者open_real,只使用open确实会拦截不到