From 7f3f6ee5585f71efac2658c355d0d8fc52dcce26 Mon Sep 17 00:00:00 2001 From: xupengying Date: Thu, 31 Oct 2024 13:21:58 +0800 Subject: [PATCH] feat: major changes --- README.md | 6 +- README.zh-CN.md | 6 +- app/build.gradle | 2 +- app/src/main/cpp/CMakeLists.txt | 2 +- app/src/main/cpp/hookee/arch/arm/t16.S | 10 + app/src/main/cpp/hookee/hookee.h | 1 + app/src/main/cpp/unittest/unittest.c | 66 ++ app/src/main/cpp/unittest/unittest_jni.c | 28 +- .../shadowhook/sample/MainActivity.java | 13 +- .../shadowhook/sample/NativeHandler.java | 4 +- app/src/main/res/layout/activity_main.xml | 6 +- build.gradle | 12 +- doc/manual.md | 60 ++ doc/manual.zh-CN.md | 56 ++ gradle/wrapper/gradle-wrapper.properties | 2 +- shadowhook/src/main/cpp/CMakeLists.txt | 10 +- shadowhook/src/main/cpp/arch/arm/sh_inst.c | 12 + shadowhook/src/main/cpp/arch/arm/sh_inst.h | 2 + shadowhook/src/main/cpp/arch/arm/sh_t16.c | 4 +- shadowhook/src/main/cpp/arch/arm64/sh_inst.c | 10 + shadowhook/src/main/cpp/arch/arm64/sh_inst.h | 2 + shadowhook/src/main/cpp/common/bytesig.c | 57 +- shadowhook/src/main/cpp/common/bytesig.h | 5 +- shadowhook/src/main/cpp/common/sh_config.h | 2 +- shadowhook/src/main/cpp/common/sh_errno.c | 6 +- shadowhook/src/main/cpp/common/sh_sig.h | 3 +- shadowhook/src/main/cpp/common/sh_trampo.c | 82 +- shadowhook/src/main/cpp/common/sh_trampo.h | 8 +- shadowhook/src/main/cpp/common/sh_util.c | 26 +- shadowhook/src/main/cpp/common/sh_util.h | 23 +- shadowhook/src/main/cpp/include/shadowhook.h | 14 +- shadowhook/src/main/cpp/nothing/sh_nothing.c | 4 + shadowhook/src/main/cpp/sh_exit.c | 47 +- shadowhook/src/main/cpp/sh_exit.h | 1 + shadowhook/src/main/cpp/sh_hub.c | 73 +- shadowhook/src/main/cpp/sh_hub.h | 6 +- shadowhook/src/main/cpp/sh_linker.c | 762 ++++++++++++++---- shadowhook/src/main/cpp/sh_linker.h | 18 +- shadowhook/src/main/cpp/sh_safe.c | 8 +- shadowhook/src/main/cpp/sh_safe.h | 1 + shadowhook/src/main/cpp/sh_switch.c | 40 +- shadowhook/src/main/cpp/sh_switch.h | 2 + shadowhook/src/main/cpp/sh_task.c | 162 ++-- shadowhook/src/main/cpp/sh_task.h | 2 + shadowhook/src/main/cpp/shadowhook.c | 50 +- shadowhook/src/main/cpp/shadowhook.map.txt | 5 + systest/build.gradle | 2 +- systest/src/main/cpp/CMakeLists.txt | 2 +- systest/src/main/cpp/systest.c | 62 +- .../bytedance/shadowhook/systest/SysTest.java | 2 +- 50 files changed, 1320 insertions(+), 469 deletions(-) create mode 100644 shadowhook/src/main/cpp/nothing/sh_nothing.c diff --git a/README.md b/README.md index 2c13fb1..df3be7f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ShadowHook ![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat) -![](https://img.shields.io/badge/release-1.0.10-red.svg?style=flat) +![](https://img.shields.io/badge/release-1.1.1-red.svg?style=flat) ![](https://img.shields.io/badge/Android-4.1%20--%2015-blue.svg?style=flat) ![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a-blue.svg?style=flat) @@ -49,7 +49,7 @@ android { } dependencies { - implementation 'com.bytedance.android:shadowhook:1.0.10' + implementation 'com.bytedance.android:shadowhook:1.1.1' } ``` @@ -102,6 +102,7 @@ If you are using ShadowHook in an SDK project, you may need to avoid packaging l android { packagingOptions { exclude '**/libshadowhook.so' + exclude '**/libshadowhook_nothing.so' } } ``` @@ -112,6 +113,7 @@ On the other hand, if you are using ShadowHook in an APP project, you may need t android { packagingOptions { pickFirst '**/libshadowhook.so' + pickFirst '**/libshadowhook_nothing.so' } } ``` diff --git a/README.zh-CN.md b/README.zh-CN.md index 7d6c887..3cdbeca 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,7 +1,7 @@ # ShadowHook ![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat) -![](https://img.shields.io/badge/release-1.0.10-red.svg?style=flat) +![](https://img.shields.io/badge/release-1.1.1-red.svg?style=flat) ![](https://img.shields.io/badge/Android-4.1%20--%2015-blue.svg?style=flat) ![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a-blue.svg?style=flat) @@ -49,7 +49,7 @@ android { } dependencies { - implementation 'com.bytedance.android:shadowhook:1.0.10' + implementation 'com.bytedance.android:shadowhook:1.1.1' } ``` @@ -102,6 +102,7 @@ android { android { packagingOptions { exclude '**/libshadowhook.so' + exclude '**/libshadowhook_nothing.so' } } ``` @@ -112,6 +113,7 @@ android { android { packagingOptions { pickFirst '**/libshadowhook.so' + pickFirst '**/libshadowhook_nothing.so' } } ``` diff --git a/app/build.gradle b/app/build.gradle index 512d7ac..70becbc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -45,7 +45,7 @@ android { } packagingOptions { jniLibs { - pickFirsts += ['**/libshadowhook.so'] + pickFirsts += ['**/libshadowhook.so', '**/libshadowhook_nothing.so'] } if (rootProject.ext.useASAN) { doNotStrip "**/*.so" diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index ccd6d9b..3df9deb 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.22.1) +cmake_minimum_required(VERSION 3.30.5) project(app) enable_language(ASM) diff --git a/app/src/main/cpp/hookee/arch/arm/t16.S b/app/src/main/cpp/hookee/arch/arm/t16.S index ff104da..c99d464 100644 --- a/app/src/main/cpp/hookee/arch/arm/t16.S +++ b/app/src/main/cpp/hookee/arch/arm/t16.S @@ -209,6 +209,16 @@ ENTRY_GLOBAL_THUMB(test_t16_it_t1_case2) bx lr END(test_t16_it_t1_case2) +ENTRY_GLOBAL_THUMB(test_t16_it_t1_case3) + cmp r0, r0 // Compare r0 with 0 + itete ne // If-Then-Else-Then-Else block for Not Equal + addne r1, r1, #1 // If r0 != 0, add 1 to r1 + addeq r2, r2, #2 // If r0 == 0, add 2 to r2 + subne r3, r3, #3 // If r0 != 0, subtract 3 from r3 + moveq r4, #4 // If r0 == 0, move 4 to r4 + b test_t16_helper_global +END(test_t16_it_t1_case3) + ENTRY_HIDDEN_THUMB(test_t16_helper_hidden_tail) add r0, r0, r1 diff --git a/app/src/main/cpp/hookee/hookee.h b/app/src/main/cpp/hookee/hookee.h index c336a7c..8e976a5 100644 --- a/app/src/main/cpp/hookee/hookee.h +++ b/app/src/main/cpp/hookee/hookee.h @@ -41,6 +41,7 @@ int test_t16_cbnz_t1(int a, int b); int test_t16_cbnz_t1_fixaddr(int a, int b); int test_t16_it_t1_case1(int a, int b); int test_t16_it_t1_case2(int a, int b); +int test_t16_it_t1_case3(int a, int b); int test_t32_helper_global(int a, int b); int test_t32_b_t3(int a, int b); diff --git a/app/src/main/cpp/unittest/unittest.c b/app/src/main/cpp/unittest/unittest.c index 0b721cb..1b2954a 100644 --- a/app/src/main/cpp/unittest/unittest.c +++ b/app/src/main/cpp/unittest/unittest.c @@ -223,6 +223,55 @@ static int hook_dlopen(int api_level) { return result; } +#define SH_LINKER_SYM_CALL_CONSTRUCTORS_L "__dl__ZN6soinfo16CallConstructorsEv" +#define SH_LINKER_SYM_CALL_DESTRUCTORS_L "__dl__ZN6soinfo15CallDestructorsEv" +#define SH_LINKER_SYM_CALL_CONSTRUCTORS_M "__dl__ZN6soinfo17call_constructorsEv" +#define SH_LINKER_SYM_CALL_DESTRUCTORS_M "__dl__ZN6soinfo16call_destructorsEv" + +typedef void (*linker_proxy_soinfo_call_ctors_t)(void *); +static linker_proxy_soinfo_call_ctors_t linker_orig_soinfo_call_ctors; +static void linker_proxy_soinfo_call_ctors(void *soinfo) { + if (SHADOWHOOK_IS_SHARED_MODE) + SHADOWHOOK_CALL_PREV(linker_proxy_soinfo_call_ctors, linker_proxy_soinfo_call_ctors_t, soinfo); + else + linker_orig_soinfo_call_ctors(soinfo); + + if (SHADOWHOOK_IS_SHARED_MODE) SHADOWHOOK_POP_STACK(); +} + +typedef void (*linker_proxy_soinfo_call_dtors_t)(void *); +static linker_proxy_soinfo_call_dtors_t linker_orig_soinfo_call_dtors; +static void linker_proxy_soinfo_call_dtors(void *soinfo) { + if (SHADOWHOOK_IS_SHARED_MODE) + SHADOWHOOK_CALL_PREV(linker_proxy_soinfo_call_dtors, linker_proxy_soinfo_call_dtors_t, soinfo); + else + linker_orig_soinfo_call_dtors(soinfo); + + if (SHADOWHOOK_IS_SHARED_MODE) SHADOWHOOK_POP_STACK(); +} + +static int hook_call_ctors_dtors(int api_level) { + static int result = -1; + static bool hooked = false; + + if (hooked) return result; + hooked = true; + + void *stub_ctors = shadowhook_hook_sym_name( + LINKER_BASENAME, + api_level >= __ANDROID_API_M__ ? SH_LINKER_SYM_CALL_CONSTRUCTORS_M : SH_LINKER_SYM_CALL_CONSTRUCTORS_L, + (void *)linker_proxy_soinfo_call_ctors, (void **)&linker_orig_soinfo_call_ctors); + int errno_ctors = shadowhook_get_errno(); + void *stub_dtors = shadowhook_hook_sym_name( + LINKER_BASENAME, + api_level >= __ANDROID_API_M__ ? SH_LINKER_SYM_CALL_DESTRUCTORS_M : SH_LINKER_SYM_CALL_DESTRUCTORS_L, + (void *)linker_proxy_soinfo_call_dtors, (void **)&linker_orig_soinfo_call_dtors); + int errno_dtors = shadowhook_get_errno(); + + result = (NULL != stub_ctors && NULL != stub_dtors && 0 == errno_ctors && 0 == errno_dtors) ? 0 : -1; + return result; +} + // end of - hooking dlopen() or do_dlopen() /////////////////////////////////////////////////////////////////////////// @@ -270,6 +319,7 @@ PROXY(t16_cbnz_t1) PROXY(t16_cbnz_t1_fixaddr) PROXY(t16_it_t1_case1) PROXY(t16_it_t1_case2) +PROXY(t16_it_t1_case3) PROXY(t32_b_t3) PROXY(t32_b_t4) @@ -398,6 +448,13 @@ static int unittest_hook(int api_level) { return -1; } + if (api_level >= __ANDROID_API_L__) { + if (0 != hook_call_ctors_dtors(api_level)) { + LOG("hook soinfo::call_constructors() and get soinfo::call_destructors() FAILED"); + return -1; + } + } + #if defined(__arm__) HOOK(t16_b_t1); @@ -454,6 +511,7 @@ static int unittest_hook(int api_level) { HOOK(a32_ldr_lit_a1_case2); HOOK(a32_ldr_reg_a1_case1); HOOK(a32_ldr_reg_a1_case2); + HOOK(t16_it_t1_case3); #elif defined(__aarch64__) @@ -538,6 +596,7 @@ int unittest_unhook(void) { UNHOOK(t16_cbnz_t1_fixaddr); UNHOOK(t16_it_t1_case1); UNHOOK(t16_it_t1_case2); + UNHOOK(t16_it_t1_case3); UNHOOK(t32_b_t3); UNHOOK(t32_b_t4); @@ -644,6 +703,7 @@ int unittest_run(bool hookee2_loaded) { RUN(t16_cbnz_t1_fixaddr); RUN(t16_it_t1_case1); RUN(t16_it_t1_case2); + RUN(t16_it_t1_case3); LOG(DELIMITER, "TEST INST T32"); RUN(t32_b_t3); @@ -731,6 +791,12 @@ int unittest_run(bool hookee2_loaded) { RUN_WITH_DLSYM(libhookee2.so, hook_before_dlopen_2); } + LOG(DELIMITER, "TEST - dlopen"); + void *handle = dlopen("libc.so", RTLD_NOW); + dlclose(handle); + handle = dlopen("libshadowhook_nothing.so", RTLD_NOW); + dlclose(handle); + return 0; } diff --git a/app/src/main/cpp/unittest/unittest_jni.c b/app/src/main/cpp/unittest/unittest_jni.c index a99d552..d2ebd45 100644 --- a/app/src/main/cpp/unittest/unittest_jni.c +++ b/app/src/main/cpp/unittest/unittest_jni.c @@ -21,6 +21,7 @@ // Created by Kelun Cai (caikelun@bytedance.com) on 2021-04-11. +#include #include #include #include @@ -34,6 +35,8 @@ #define HACKER_JNI_VERSION JNI_VERSION_1_6 #define HACKER_JNI_CLASS_NAME "com/bytedance/shadowhook/sample/NativeHandler" +static void *hookee2_handle = NULL; + static int unittest_jni_hook_sym_addr(JNIEnv *env, jobject thiz, jint api_level) { (void)env; (void)thiz; @@ -55,11 +58,28 @@ static int unittest_jni_unhook(JNIEnv *env, jobject thiz) { return unittest_unhook(); } -static int unittest_jni_run(JNIEnv *env, jobject thiz, jboolean hookee2_loaded) { +static int unittest_jni_run(JNIEnv *env, jobject thiz) { + (void)env; + (void)thiz; + + return unittest_run(NULL != hookee2_handle); +} + +static void unittest_jni_dlopen(JNIEnv *env, jobject thiz) { (void)env; (void)thiz; - return unittest_run(hookee2_loaded); + if (NULL == hookee2_handle) hookee2_handle = dlopen("libhookee2.so", RTLD_NOW); +} + +static void unittest_jni_dlclose(JNIEnv *env, jobject thiz) { + (void)env; + (void)thiz; + + if (NULL != hookee2_handle) { + dlclose(hookee2_handle); + hookee2_handle = NULL; + } } static void unittest_jni_dump_records(JNIEnv *env, jobject thiz, jstring pathname) { @@ -95,7 +115,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { JNINativeMethod m[] = {{"nativeHookSymAddr", "(I)I", (void *)unittest_jni_hook_sym_addr}, {"nativeHookSymName", "(I)I", (void *)unittest_jni_hook_sym_name}, {"nativeUnhook", "()I", (void *)unittest_jni_unhook}, - {"nativeRun", "(Z)I", (void *)unittest_jni_run}, + {"nativeDlopen", "()V", (void *)unittest_jni_dlopen}, + {"nativeDlclose", "()V", (void *)unittest_jni_dlclose}, + {"nativeRun", "()I", (void *)unittest_jni_run}, {"nativeDumpRecords", "(Ljava/lang/String;)V", (void *)unittest_jni_dump_records}}; if (0 != (*env)->RegisterNatives(env, cls, m, sizeof(m) / sizeof(m[0]))) return JNI_ERR; diff --git a/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java b/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java index e4840d4..28326c0 100644 --- a/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java +++ b/app/src/main/java/com/bytedance/shadowhook/sample/MainActivity.java @@ -68,16 +68,19 @@ public void onClick(View v) { findViewById(R.id.unitTestLoad).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - if(!hookee2Loaded) { - hookee2Loaded = true; - System.loadLibrary("hookee2"); - } + NativeHandler.nativeDlopen(); + } + }); + + findViewById(R.id.unitTestUnload).setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + NativeHandler.nativeDlclose(); } }); findViewById(R.id.unitTestRun).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - NativeHandler.nativeRun(hookee2Loaded); + NativeHandler.nativeRun(); } }); diff --git a/app/src/main/java/com/bytedance/shadowhook/sample/NativeHandler.java b/app/src/main/java/com/bytedance/shadowhook/sample/NativeHandler.java index 578b621..9958e72 100644 --- a/app/src/main/java/com/bytedance/shadowhook/sample/NativeHandler.java +++ b/app/src/main/java/com/bytedance/shadowhook/sample/NativeHandler.java @@ -27,6 +27,8 @@ public class NativeHandler { public static native int nativeHookSymAddr(int apiLevel); public static native int nativeHookSymName(int apiLevel); public static native int nativeUnhook(); - public static native int nativeRun(boolean hookee2Loaded); + public static native void nativeDlopen(); + public static native void nativeDlclose(); + public static native int nativeRun(); public static native void nativeDumpRecords(String pathname); } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 8df8bd8..b9e27bb 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -34,7 +34,11 @@