Skip to content

Commit 9ec0323

Browse files
committed
Add shadowhook_hook_func_addr.
1 parent 2630df0 commit 9ec0323

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+690
-366
lines changed

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ShadowHook
22

33
![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
4-
![](https://img.shields.io/badge/release-1.0.3-red.svg?style=flat)
4+
![](https://img.shields.io/badge/release-1.0.4-red.svg?style=flat)
55
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
66
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a-blue.svg?style=flat)
77

@@ -55,7 +55,7 @@ android {
5555
}
5656
5757
dependencies {
58-
implementation 'com.bytedance.android:shadowhook:1.0.3'
58+
implementation 'com.bytedance.android:shadowhook:1.0.4'
5959
}
6060
```
6161

@@ -143,6 +143,11 @@ public class MySdk {
143143
```C
144144
#include "shadowhook.h"
145145

146+
void *shadowhook_hook_func_addr(
147+
void *func_addr,
148+
void *new_addr,
149+
void **orig_addr);
150+
146151
void *shadowhook_hook_sym_addr(
147152
void *sym_addr,
148153
void *new_addr,
@@ -174,8 +179,9 @@ void *shadowhook_hook_sym_name_callback(
174179
int shadowhook_unhook(void *stub);
175180
```
176181
177-
* `shadowhook_hook_sym_addr`: hook a function address.
178-
* `shadowhook_hook_sym_name`: hook the symbol name of a function in a dynamic library.
182+
* `shadowhook_hook_func_addr`: hook a function (which has no symbol info in ELF) by absolute address.
183+
* `shadowhook_hook_sym_addr`: hook a function (which has symbol info in ELF) by absolute address.
184+
* `shadowhook_hook_sym_name`: hook a function by symbol name and ELF file name or path name.
179185
* `shadowhook_hook_sym_name_callback`: Similar to `shadowhook_hook_sym_name`, but the specified callback function will be called after the hook is completed.
180186
* `shadowhook_unhook`: unhook.
181187

README.zh-CN.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# ShadowHook
22

33
![](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)
4-
![](https://img.shields.io/badge/release-1.0.3-red.svg?style=flat)
4+
![](https://img.shields.io/badge/release-1.0.4-red.svg?style=flat)
55
![](https://img.shields.io/badge/Android-4.1%20--%2013-blue.svg?style=flat)
66
![](https://img.shields.io/badge/arch-armeabi--v7a%20%7C%20arm64--v8a-blue.svg?style=flat)
77

@@ -55,7 +55,7 @@ android {
5555
}
5656
5757
dependencies {
58-
implementation 'com.bytedance.android:shadowhook:1.0.3'
58+
implementation 'com.bytedance.android:shadowhook:1.0.4'
5959
}
6060
```
6161

@@ -143,6 +143,11 @@ public class MySdk {
143143
```C
144144
#include "shadowhook.h"
145145

146+
void *shadowhook_hook_func_addr(
147+
void *func_addr,
148+
void *new_addr,
149+
void **orig_addr);
150+
146151
void *shadowhook_hook_sym_addr(
147152
void *sym_addr,
148153
void *new_addr,
@@ -174,8 +179,9 @@ void *shadowhook_hook_sym_name_callback(
174179
int shadowhook_unhook(void *stub);
175180
```
176181
177-
* `shadowhook_hook_sym_addr`:hook 某个函数地址。
178-
* `shadowhook_hook_sym_name`:hook 某个动态库中的某个函数符号名。
182+
* `shadowhook_hook_func_addr`: 通过绝对地址 hook 一个在 ELF 中没有符号信息的函数。
183+
* `shadowhook_hook_sym_addr`:通过绝对地址 hook 一个在 ELF 中有符号信息的函数。
184+
* `shadowhook_hook_sym_name`:通过符号名和 ELF 的文件名或路径名 hook 一个函数。
179185
* `shadowhook_hook_sym_name_callback`:和 `shadowhook_hook_sym_name` 类似,但是会在 hook 完成后调用指定的回调函数。
180186
* `shadowhook_unhook`:unhook。
181187

app/build.gradle

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ android {
5353
}
5454

5555
dependencies {
56-
implementation 'androidx.appcompat:appcompat:1.4.1'
57-
implementation 'com.google.android.material:material:1.5.0'
58-
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
56+
implementation 'androidx.appcompat:appcompat:1.5.1'
57+
implementation 'com.google.android.material:material:1.7.0'
58+
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
5959

6060
if (rootProject.ext.dependencyOnLocalLibrary) {
6161
implementation project(':shadowhook')
@@ -66,13 +66,3 @@ dependencies {
6666
}
6767

6868
apply from: rootProject.file('gradle/sanitizer.gradle')
69-
70-
if (rootProject.ext.dependencyOnLocalLibrary) {
71-
tasks.whenTaskAdded { task ->
72-
if (task.name == 'preDebugBuild') {
73-
task.dependsOn(':shadowhook:prefabDebugConfigurePackage')
74-
} else if (task.name == 'preReleaseBuild') {
75-
task.dependsOn(':shadowhook:prefabReleaseConfigurePackage')
76-
}
77-
}
78-
}

app/src/main/cpp/CMakeLists.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.18.1)
1+
cmake_minimum_required(VERSION 3.22.1)
22
project(app)
33
enable_language(ASM)
44

@@ -14,25 +14,25 @@ endif()
1414
set(TARGET "hookee")
1515
file(GLOB SRC hookee/*.c hookee/arch/${ARCH}/*.S)
1616
add_library(${TARGET} SHARED ${SRC})
17-
target_compile_features(${TARGET} PUBLIC c_std_11)
18-
target_compile_options(${TARGET} PUBLIC -Weverything -Werror -Wno-unused-macros)
17+
target_compile_features(${TARGET} PUBLIC c_std_17)
18+
target_compile_options(${TARGET} PUBLIC -std=c17 -Weverything -Werror -Wno-unused-macros)
1919
target_include_directories(${TARGET} PUBLIC hookee)
2020
target_link_libraries(${TARGET} log)
2121

2222
# libhookee2.so
2323
set(TARGET "hookee2")
2424
file(GLOB SRC hookee2/*.c)
2525
add_library(${TARGET} SHARED ${SRC})
26-
target_compile_features(${TARGET} PUBLIC c_std_11)
27-
target_compile_options(${TARGET} PUBLIC -Weverything -Werror)
26+
target_compile_features(${TARGET} PUBLIC c_std_17)
27+
target_compile_options(${TARGET} PUBLIC -std=c17 -Weverything -Werror)
2828
target_include_directories(${TARGET} PUBLIC hookee2)
2929
target_link_libraries(${TARGET} log)
3030

3131
# libunittest.so
3232
set(TARGET "unittest")
3333
file(GLOB SRC unittest/*.c)
3434
add_library(${TARGET} SHARED ${SRC})
35-
target_compile_features(${TARGET} PUBLIC c_std_11)
36-
target_compile_options(${TARGET} PUBLIC -Weverything -Werror)
35+
target_compile_features(${TARGET} PUBLIC c_std_17)
36+
target_compile_options(${TARGET} PUBLIC -std=c17 -Weverything -Werror)
3737
target_include_directories(${TARGET} PUBLIC unittest hookee)
3838
target_link_libraries(${TARGET} log hookee shadowhook::shadowhook)

app/src/main/cpp/hookee/arch/arm/a32.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ ENTRY_GLOBAL_ARM(test_a32_helper_global)
2828
bx lr
2929
END(test_a32_helper_global)
3030

31+
// B A1, hidden function
32+
ENTRY_HIDDEN_ARM(test_hidden_func)
33+
cmp r0, r1
34+
bne test_a32_helper_hidden_tail
35+
bx lr
36+
END(test_hidden_func)
37+
3138
ENTRY_HIDDEN_ARM(test_a32_helper_hidden)
3239
add r0, r0, r1
3340
bx lr

app/src/main/cpp/hookee/arch/arm64/a64.S

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ ENTRY_GLOBAL_ARM(test_a64_helper_global)
2929
END(test_a64_helper_global)
3030

3131

32+
// B, hidden function
33+
ENTRY_HIDDEN_ARM(test_hidden_func)
34+
b test_a64_helper_global
35+
nop
36+
nop
37+
nop
38+
ret
39+
END(test_hidden_func)
40+
41+
3242
// B
3343
ENTRY_GLOBAL_ARM(test_a64_b)
3444
b test_a64_helper_global
@@ -310,4 +320,4 @@ END(test_a64_tbnz_fixaddr)
310320
ENTRY_HIDDEN_ARM(test_a64_helper_hidden_tail)
311321
add x0, x0, x1
312322
ret
313-
END(ttest_a64_helper_global_tail)
323+
END(test_a64_helper_global_tail)

app/src/main/cpp/hookee/hookee.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,14 @@ int test_hook_multi_times(int a, int b) {
9292
LOG("**> test_hook_multiple_times called");
9393
return a + b;
9494
}
95+
96+
void *get_hidden_func_addr(void) {
97+
#pragma clang diagnostic push
98+
#pragma clang diagnostic ignored "-Wpointer-arith"
99+
#if defined(__arm__)
100+
return (void *)test_a32_helper_global + 8;
101+
#elif defined(__aarch64__)
102+
return (void *)test_a64_helper_global + 8;
103+
#endif
104+
#pragma clang diagnostic pop
105+
}

app/src/main/cpp/hookee/hookee.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,5 @@ int test_recursion_1(int a, int b);
116116
int test_recursion_2(int a, int b);
117117

118118
int test_hook_multi_times(int a, int b);
119+
120+
void *get_hidden_func_addr(void);

app/src/main/cpp/unittest/unittest.c

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@
3737

3838
#pragma clang diagnostic push
3939
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
40-
#define LOG(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "shadowhook_tag", fmt, ##__VA_ARGS__)
41-
#pragma clang diagnostic pop
40+
#pragma clang diagnostic ignored "-Wunused-function"
41+
#pragma clang diagnostic ignored "-Wunused-variable"
4242

43+
#define LOG(fmt, ...) __android_log_print(ANDROID_LOG_INFO, "shadowhook_tag", fmt, ##__VA_ARGS__)
4344
#define DELIMITER ">>>>>>>>>>>>>>>>>>> %s >>>>>>>>>>>>>>>>>>>"
4445
#define TO_STR_HELPER(x) #x
4546
#define TO_STR(x) TO_STR_HELPER(x)
@@ -119,7 +120,7 @@ typedef int (*test_t)(int, int);
119120

120121
#define UNHOOK_WITH_TAG(inst, tag) \
121122
do { \
122-
if (NULL == stub_##inst##tag) return -1; \
123+
if (NULL == stub_##inst##tag) break; \
123124
int r_ = shadowhook_unhook(stub_##inst##tag); \
124125
stub_##inst##tag = NULL; \
125126
if (0 != r_) { \
@@ -225,6 +226,30 @@ static int hook_dlopen(int api_level) {
225226
// end of - hooking dlopen() or do_dlopen()
226227
///////////////////////////////////////////////////////////////////////////
227228

229+
///////////////////////////////////////////////////////////////////////////
230+
// hooking hidden function (without symbol info in ELF)
231+
232+
static test_t test_hidden_func = NULL;
233+
PROXY(hidden_func)
234+
235+
static void run_hidden_func(void) {
236+
if (NULL == test_hidden_func) test_hidden_func = (test_t)get_hidden_func_addr();
237+
RUN(hidden_func);
238+
}
239+
240+
static int hook_hidden_func(void) {
241+
if (NULL == test_hidden_func) test_hidden_func = (test_t)get_hidden_func_addr();
242+
if (NULL != stub_hidden_func) return -1;
243+
stub_hidden_func = shadowhook_hook_func_addr(
244+
(void *)test_hidden_func,
245+
SHADOWHOOK_IS_UNIQUE_MODE ? (void *)unique_proxy_hidden_func : (void *)shared_proxy_hidden_func,
246+
(void **)(&orig_hidden_func));
247+
return NULL == stub_hidden_func ? -1 : 0;
248+
}
249+
250+
// end of - hooking hidden function (without symbol info in ELF)
251+
///////////////////////////////////////////////////////////////////////////
252+
228253
///////////////////////////////////////////////////////////////////////////
229254
// (1) test proxy for instructions
230255

@@ -458,6 +483,13 @@ static int unittest_hook(int api_level) {
458483

459484
#endif
460485

486+
if (unittest_is_hook_addr) {
487+
if (0 != hook_hidden_func()) {
488+
LOG("hook hidden function FAILED");
489+
return -1;
490+
}
491+
}
492+
461493
if (SHADOWHOOK_IS_SHARED_MODE) {
462494
HOOK(recursion_1);
463495
HOOK(recursion_2);
@@ -574,6 +606,8 @@ int unittest_unhook(void) {
574606

575607
#endif
576608

609+
UNHOOK(hidden_func);
610+
577611
if (SHADOWHOOK_IS_SHARED_MODE) {
578612
UNHOOK(recursion_1);
579613
UNHOOK(recursion_2);
@@ -681,18 +715,23 @@ int unittest_run(bool hookee2_loaded) {
681715

682716
#endif
683717

718+
LOG(DELIMITER, "TEST - hidden function");
719+
run_hidden_func();
720+
684721
if (SHADOWHOOK_IS_SHARED_MODE) {
685-
LOG(DELIMITER, "TEST BIZ - recursion");
722+
LOG(DELIMITER, "TEST - recursion");
686723
RUN(recursion_1);
687-
LOG(DELIMITER, "TEST BIZ - hook multi times");
724+
LOG(DELIMITER, "TEST - hook multi times");
688725
RUN(hook_multi_times);
689726
}
690727

691728
if (hookee2_loaded) {
692-
LOG(DELIMITER, "TEST BIZ - hook before dlopen");
729+
LOG(DELIMITER, "TEST - hook before dlopen");
693730
RUN_WITH_DLSYM(libhookee2.so, hook_before_dlopen_1);
694731
RUN_WITH_DLSYM(libhookee2.so, hook_before_dlopen_2);
695732
}
696733

697734
return 0;
698735
}
736+
737+
#pragma clang diagnostic pop

app/src/main/cpp/unittest/unittest_jni.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
#include "shadowhook.h"
3232
#include "unittest.h"
3333

34+
#define HACKER_JNI_VERSION JNI_VERSION_1_6
35+
#define HACKER_JNI_CLASS_NAME "com/bytedance/shadowhook/sample/NativeHandler"
36+
3437
static int unittest_jni_hook_sym_addr(JNIEnv *env, jobject thiz, jint api_level) {
3538
(void)env;
3639
(void)thiz;
@@ -79,15 +82,15 @@ static void unittest_jni_dump_records(JNIEnv *env, jobject thiz, jstring pathnam
7982

8083
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
8184
(void)reserved;
82-
jint jni_version = JNI_VERSION_1_6;
8385

84-
JNIEnv *env;
8586
if (NULL == vm) return JNI_ERR;
86-
if (JNI_OK != (*vm)->GetEnv(vm, (void **)&env, jni_version)) return JNI_ERR;
87+
88+
JNIEnv *env;
89+
if (JNI_OK != (*vm)->GetEnv(vm, (void **)&env, HACKER_JNI_VERSION)) return JNI_ERR;
8790
if (NULL == env || NULL == *env) return JNI_ERR;
8891

89-
jclass cls = (*env)->FindClass(env, "com/bytedance/shadowhook/sample/NativeHandler");
90-
if (NULL == cls) return JNI_ERR;
92+
jclass cls;
93+
if (NULL == (cls = (*env)->FindClass(env, HACKER_JNI_CLASS_NAME))) return JNI_ERR;
9194

9295
JNINativeMethod m[] = {{"nativeHookSymAddr", "(I)I", (void *)unittest_jni_hook_sym_addr},
9396
{"nativeHookSymName", "(I)I", (void *)unittest_jni_hook_sym_name},
@@ -96,5 +99,5 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
9699
{"nativeDumpRecords", "(Ljava/lang/String;)V", (void *)unittest_jni_dump_records}};
97100
if (0 != (*env)->RegisterNatives(env, cls, m, sizeof(m) / sizeof(m[0]))) return JNI_ERR;
98101

99-
return jni_version;
102+
return HACKER_JNI_VERSION;
100103
}

0 commit comments

Comments
 (0)