Skip to content

Commit 99c2900

Browse files
committed
Add an interface for setting dynamic libraries that need to be ignored globally.
1 parent e3f291c commit 99c2900

12 files changed

Lines changed: 147 additions & 2 deletions

File tree

bytehook/src/main/cpp/bh_core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,12 @@ int bh_core_unhook(bytehook_stub_t stub, uintptr_t caller_addr)
202202
return status_code;
203203
}
204204

205+
int bh_core_add_ignore(const char *caller_path_name)
206+
{
207+
int r = bh_elf_manager_add_ignore(bh_core.elf_mgr, caller_path_name);
208+
return 0 == r ? 0 : BYTEHOOK_STATUS_CODE_IGNORE;
209+
}
210+
205211
void bh_core_set_debug(bool debug)
206212
{
207213
bh_log_set_debug(debug);

bytehook/src/main/cpp/bh_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ bytehook_stub_t bh_core_hook_all(
7373

7474
int bh_core_unhook(bytehook_stub_t stub, uintptr_t caller_addr);
7575

76+
int bh_core_add_ignore(const char *caller_path_name);
77+
7678
void bh_core_set_debug(bool debug);
7779

7880
void *bh_core_get_prev_func(void *func);

bytehook/src/main/cpp/bh_elf_manager.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@
4242
#include "bh_log.h"
4343
#include "bh_dl_monitor.h"
4444

45+
// block list
46+
typedef struct bh_elf_manager_block
47+
{
48+
char *caller_path_name;
49+
TAILQ_ENTRY(bh_elf_manager_block,) link;
50+
} bh_elf_manager_block_t;
51+
typedef TAILQ_HEAD(bh_elf_manager_block_list, bh_elf_manager_block,) bh_elf_manager_block_list_t;
52+
4553
// RB-tree for ELF info (bh_elf_t)
4654
static __inline__ int bh_elf_cmp(bh_elf_t *a, bh_elf_t *b)
4755
{
@@ -63,6 +71,8 @@ struct bh_elf_manager
6371
size_t elfs_cnt;
6472
bh_elf_list_t abandoned_elfs;
6573
pthread_rwlock_t elfs_lock;
74+
bh_elf_manager_block_list_t blocklist;
75+
pthread_mutex_t blocklist_lock;
6676
};
6777
#pragma clang diagnostic pop
6878

@@ -76,10 +86,75 @@ bh_elf_manager_t *bh_elf_manager_create(void)
7686
self->elfs_cnt = 0;
7787
TAILQ_INIT(&self->abandoned_elfs);
7888
pthread_rwlock_init(&self->elfs_lock, NULL);
89+
TAILQ_INIT(&self->blocklist);
90+
pthread_mutex_init(&self->blocklist_lock, NULL);
7991

8092
return self;
8193
}
8294

95+
int bh_elf_manager_add_ignore(bh_elf_manager_t *self, const char *caller_path_name)
96+
{
97+
bh_elf_manager_block_t *block;
98+
if(NULL == (block = calloc(1, sizeof(bh_elf_t)))) return -1;
99+
if(NULL == (block->caller_path_name = strdup(caller_path_name)))
100+
{
101+
free(block);
102+
return -1;
103+
}
104+
105+
bh_elf_manager_block_t *tmp;
106+
pthread_mutex_lock(&self->blocklist_lock);
107+
TAILQ_FOREACH(tmp, &self->blocklist, link)
108+
{
109+
if(0 == strcmp(tmp->caller_path_name, caller_path_name))
110+
break;
111+
}
112+
if(NULL == tmp)
113+
{
114+
TAILQ_INSERT_TAIL(&self->blocklist, block, link);
115+
block = NULL;
116+
}
117+
pthread_mutex_unlock(&self->blocklist_lock);
118+
119+
if(NULL != block)
120+
{
121+
free(block->caller_path_name);
122+
free(block);
123+
}
124+
return 0;
125+
}
126+
127+
static bool bh_elf_manager_check_ignore(bh_elf_manager_t *self, const char *caller_path_name)
128+
{
129+
bool result = true;
130+
pthread_mutex_lock(&self->blocklist_lock);
131+
132+
bh_elf_manager_block_t *tmp;
133+
TAILQ_FOREACH(tmp, &self->blocklist, link)
134+
{
135+
if('/' == caller_path_name[0] && '/' != tmp->caller_path_name[0])
136+
{
137+
if(bh_util_ends_with(caller_path_name, tmp->caller_path_name))
138+
goto ignore;
139+
}
140+
else if('/' != caller_path_name[0] && '/' == tmp->caller_path_name[0])
141+
{
142+
if(bh_util_ends_with(tmp->caller_path_name, caller_path_name))
143+
goto ignore;
144+
}
145+
else
146+
{
147+
if(0 == strcmp(caller_path_name, tmp->caller_path_name))
148+
goto ignore;
149+
}
150+
}
151+
result = false;
152+
153+
ignore:
154+
pthread_mutex_unlock(&self->blocklist_lock);
155+
return result;
156+
}
157+
83158
static int bh_elf_manager_iterate_cb(struct dl_phdr_info *info, size_t size, void *arg)
84159
{
85160
(void)size;
@@ -91,6 +166,7 @@ static int bh_elf_manager_iterate_cb(struct dl_phdr_info *info, size_t size, voi
91166
// ignore invalid or unwanted ELF
92167
if(bh_util_ends_with(info->dlpi_name, BH_CONST_BASENAME_BYTEHOOK)) return 0;
93168
if(!bh_util_ends_with(info->dlpi_name, BH_CONST_BASENAME_APP_PROCESS) && !bh_util_ends_with(info->dlpi_name, ".so")) return 0;
169+
if(bh_elf_manager_check_ignore(self, info->dlpi_name)) return 0;
94170

95171
bh_elf_t elf_key = {.pathname = info->dlpi_name};
96172
bh_elf_t *elf = RB_FIND(bh_elf_tree, &self->elfs, &elf_key);

bytehook/src/main/cpp/bh_elf_manager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ typedef struct bh_elf_manager bh_elf_manager_t;
2929

3030
bh_elf_manager_t *bh_elf_manager_create(void);
3131

32+
int bh_elf_manager_add_ignore(bh_elf_manager_t *self, const char *caller_path_name);
33+
3234
typedef void (*bh_elf_manager_post_add_cb_t)(bh_elf_t *elf, void *arg);
3335
void bh_elf_manager_refresh(bh_elf_manager_t *self, bool sync_clean, bh_elf_manager_post_add_cb_t cb, void *cb_arg);
3436

bytehook/src/main/cpp/bh_jni.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,23 @@ static jint bh_jni_init(JNIEnv *env, jobject thiz, jint mode, jboolean debug)
3636
return bytehook_init((int)mode, (bool)debug);
3737
}
3838

39+
static jint bh_jni_add_ignore(JNIEnv *env, jobject thiz, jstring caller_path_name)
40+
{
41+
(void)env;
42+
(void)thiz;
43+
44+
int r = BYTEHOOK_STATUS_CODE_IGNORE;
45+
if(!caller_path_name) return r;
46+
47+
const char *c_caller_path_name;
48+
if(NULL == (c_caller_path_name = (*env)->GetStringUTFChars(env, caller_path_name, 0))) goto clean;
49+
r = bytehook_add_ignore(c_caller_path_name);
50+
51+
clean:
52+
if(caller_path_name && c_caller_path_name) (*env)->ReleaseStringUTFChars(env, caller_path_name, c_caller_path_name);
53+
return r;
54+
}
55+
3956
static void bh_jni_set_debug(JNIEnv *env, jobject thiz, jboolean debug)
4057
{
4158
(void)env;
@@ -91,6 +108,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,
91108

92109
JNINativeMethod m[] = {
93110
{"nativeInit", "(IZ)I", (void *)bh_jni_init},
111+
{"nativeAddIgnore", "(Ljava/lang/String;)I", (void *)bh_jni_add_ignore},
94112
{"nativeSetDebug", "(Z)V", (void *)bh_jni_set_debug},
95113
{"nativeGetRecords", "(I)Ljava/lang/String;", (void *)bh_jni_get_records},
96114
{"nativeGetArch", "()Ljava/lang/String;", (void *)bh_jni_get_arch}

bytehook/src/main/cpp/bytehook.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ int bytehook_unhook(bytehook_stub_t stub)
9898
return bh_core_unhook(stub, (uintptr_t)caller_addr);
9999
}
100100

101+
int bytehook_add_ignore(const char *caller_path_name)
102+
{
103+
return bh_core_add_ignore(caller_path_name);
104+
}
105+
101106
void bytehook_set_debug(bool debug)
102107
{
103108
bh_core_set_debug(debug);

bytehook/src/main/cpp/include/bytehook.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#define BYTEHOOK_STATUS_CODE_CFI_HOOK_FAILED 22
7373
#define BYTEHOOK_STATUS_CODE_ORIG_ADDR 23
7474
#define BYTEHOOK_STATUS_CODE_INITERR_CFI 24
75+
#define BYTEHOOK_STATUS_CODE_IGNORE 25
7576
#define BYTEHOOK_STATUS_CODE_MAX 255
7677

7778
#define BYTEHOOK_MODE_AUTOMATIC 0
@@ -124,6 +125,8 @@ bytehook_stub_t bytehook_hook_all(
124125

125126
int bytehook_unhook(bytehook_stub_t stub);
126127

128+
int bytehook_add_ignore(const char *caller_path_name);
129+
127130
void bytehook_set_debug(bool debug);
128131

129132
// get operation records

bytehook/src/main/java/com/bytedance/android/bytehook/ByteHook.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2020-present, ByteDance, Inc.
1+
// Copyright (c) 2020-2021 ByteDance, Inc.
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining a copy
44
// of this software and associated documentation files (the "Software"), to deal
@@ -71,6 +71,13 @@ public static synchronized int init(Config config) {
7171
return initStatus;
7272
}
7373

74+
public static int addIgnore(String callerPathName) {
75+
if (initStatus == 0) {
76+
return nativeAddIgnore(callerPathName);
77+
}
78+
return initStatus;
79+
}
80+
7481
public static int getInitErrno() {
7582
return initStatus;
7683
}
@@ -237,6 +244,8 @@ public enum RecordItem {
237244

238245
private static native int nativeInit(int mode, boolean debug);
239246

247+
private static native int nativeAddIgnore(String callerPathName);
248+
240249
private static native void nativeSetDebug(boolean debug);
241250

242251
private static native String nativeGetRecords(int itemFlags);

bytehook/src/main/java/com/bytedance/android/bytehook/ILibLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2020-present, ByteDance, Inc.
1+
// Copyright (c) 2020-2021 ByteDance, Inc.
22
//
33
// Permission is hereby granted, free of charge, to any person obtaining a copy
44
// of this software and associated documentation files (the "Software"), to deal

doc/java_manual.zh-CN.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,12 @@ public static void setDebug(boolean debug);
9393
* 可以通过 `setDebug()` 随时开启 / 关闭 ByteHook 的调试日志。
9494
* 调试日志输出到 logcat,tag为:`bytehook_tag`
9595
* 使用默认参数初始化时,ByteHook 默认关闭调试日志。
96+
97+
## 增加全局忽略的动态库
98+
99+
```java
100+
public static int addIgnore(String callerPathName);
101+
```
102+
103+
* 返回 `0` 表示成功,`非 0` 表示失败。
104+
* 我们可能需要全局的忽略某些动态库,例如某些来自第三方的加固过的动态库,可能包含某些未知的防护错误,对这些动态库执行 hook 可能引起未知的问题。包括 ByteHook 内部对 `dlopen``dlclose` 的 hook 也不能进行。这时候你可以把这些动态库加入到 ignored 列表中。

0 commit comments

Comments
 (0)