Skip to content

Commit 96eec1c

Browse files
更换hook方式为uprobe
1 parent a45f502 commit 96eec1c

File tree

6 files changed

+90
-45
lines changed

6 files changed

+90
-45
lines changed

README.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,12 @@
33

44

55
# 如何使用?
6-
在要进行trace的手游的私有目录(即/data/data/包名/files/)下创建test_trace.txt文件,并向其中输入要trace的类名即可,类名的获取以PtraceIl2cppDumper这个项目dump下来的为准,输入样例如:echo "test_clazz_name" >> test_trace.txt, 推荐使用echo向文件输入要trace的类,程序是默认定时获取test_trace.txt文件的最后一行的内容来作为类名进行trace。然后再通过任意ptrace注入器将本项目编译生成的so注入至游戏进程后可在logcat中使用Test-Log进行过滤查看结果。
6+
首先要成功加载[Kernel-Trace](https://github.com/AndroidReverser-Test/Kernel-Trace)项目提供的kpm模块。
7+
然后在要进行trace的手游的私有目录(即/data/data/包名/files/)下创建test_trace.txt文件,并向其中输入要trace的类名即可,类名的获取以[PtraceIl2cppDumper](https://github.com/AndroidReverser-Test/PtraceIl2cppDumper)这个项目dump下来的为准,输入样例如:echo "test_clazz_name" >> test_trace.txt, 推荐使用echo向文件输入要trace的类,程序是默认定时获取test_trace.txt文件的最后一行的内容来作为类名进行trace。然后再通过任意ptrace注入器将本项目编译生成的so注入至游戏进程后,查看[Kernel-Trace](https://github.com/AndroidReverser-Test/Kernel-Trace)的输出即可获取trace结果。
78

89
# 如何构建
910
克隆本项目后,使用androidStudio打开,然后等待项目配置自动完成,之后在本项目目录下使用gradlew :app:externalNativeBuildRelease命令进行编译,编译完成后会在<项目目录>\app\build\intermediates\cmake\release\obj\arm64-v8a下生成相应so文件。
1011

11-
# 已知的问题
12-
部分游戏可能会在trace时崩溃,这与hook框架有关
13-
1412

1513
# 感谢
16-
[Zygisk-Il2CppDumper](https://github.com/Perfare/Zygisk-Il2CppDumper)
17-
[Dobby](https://github.com/jmpews/Dobby)
18-
[Android_InlineHook](https://github.com/zhuotong/Android_InlineHook)
14+
[Zygisk-Il2CppDumper](https://github.com/Perfare/Zygisk-Il2CppDumper)

app/build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,4 @@ android {
4545
}
4646

4747
dependencies {
48-
implementation("io.github.vvb2060.ndk:dobby:+")
4948
}

app/src/main/cpp/CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,10 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
3737
il2cpp_trace.cpp
3838
${xdl-src})
3939

40-
find_package(dobby REQUIRED CONFIG)
41-
4240

4341
# Specifies libraries CMake should link to your target library. You
4442
# can link libraries from various origins, such as libraries defined in this
4543
# build script, prebuilt third-party libraries, or Android system libraries.
4644
target_link_libraries(${CMAKE_PROJECT_NAME}
4745
# List libraries link to the target library
48-
dobby::dobby
4946
log)

app/src/main/cpp/il2cpp_trace.cpp

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include <map>
88
#include "log.h"
99
#include "xdl.h"
10-
#include "dobby.h"
10+
#include "uprobe_trace_user.h"
1111
#include "il2cpp_trace.h"
1212

1313
#define DO_API(r, n, p) r (*n) p
@@ -17,8 +17,8 @@
1717
#undef DO_API
1818

1919
char data_dir_path[PATH_MAX];
20+
char module_path[PATH_MAX];
2021
static uint64_t il2cpp_base = 0;
21-
uint64_t funaddrs[MAX_HOOK_FUN_NUM];
2222
int hook_fun_num=0;
2323
std::map<long,std::string> fun_name_dict;
2424

@@ -47,7 +47,9 @@ int init_il2cpp_fun(){
4747
Dl_info dlInfo;
4848
if (dladdr((void *) il2cpp_capture_memory_snapshot, &dlInfo)) {
4949
il2cpp_base = reinterpret_cast<uint64_t>(dlInfo.dli_fbase);
50+
strcpy(module_path,dlInfo.dli_fname);
5051
LOGD("il2cpp_base: 0x%llx", il2cpp_base);
52+
LOGD("module_path: %s", module_path);
5153
}
5254
}
5355
return flag;
@@ -93,42 +95,35 @@ char *get_trace_info(char *trace_file_path){
9395
return last_line;
9496
}
9597

96-
void trace_call_back(RegisterContext *ctx, const HookEntryInfo *info){
97-
long fun_offset = (uint64_t)info->target_address-il2cpp_base;
98-
LOGD("%s is calling,offset:0x%llx",fun_name_dict[fun_offset].c_str(),fun_offset);
99-
return;
100-
}
101-
102-
void check_fun_instruction(){
103-
for (int i = 0; i < hook_fun_num; i++) {
104-
uint32_t *fun_instructions = static_cast<uint32_t *>((void *)funaddrs[i]);
105-
if(fun_instructions[1]==0xd65f03c0){//RET
106-
LOGW("pass hook fun 0x%llx",funaddrs[i]-il2cpp_base);
107-
funaddrs[i] = 0;
108-
}
109-
}
110-
LOGD("check all fun instruction");
111-
}
98+
//void check_fun_instruction(){
99+
// for (int i = 0; i < hook_fun_num; i++) {
100+
// uint32_t *fun_instructions = static_cast<uint32_t *>((void *)funaddrs[i]);
101+
// if(fun_instructions[1]==0xd65f03c0){//RET
102+
// LOGW("pass hook fun 0x%llx",funaddrs[i]-il2cpp_base);
103+
// funaddrs[i] = 0;
104+
// }
105+
// }
106+
// LOGD("check all fun instruction");
107+
//}
112108

113109
void hook_all_fun(){
114-
for (int i = 0; i < hook_fun_num; i++) {
115-
if(funaddrs[i]==0){
116-
continue;
117-
}
118-
// LOGD("fun 0x%llx hook",funaddrs[i]-il2cpp_base);
119-
if(DobbyInstrument((void *)funaddrs[i], trace_call_back)!=0){
120-
LOGD("fun 0x%llx hook error",funaddrs[i]-il2cpp_base);
110+
for (auto it = fun_name_dict.begin(); it != fun_name_dict.end(); ++it) {
111+
unsigned long fun_offset = it->first;
112+
std::string fun_name = it->second;
113+
int set_uprobe_ret = set_fun_info2(fun_offset,(char*)fun_name.c_str());
114+
if(set_uprobe_ret!=SET_TRACE_SUCCESS){
115+
LOGE("set uprobe in fun_name:%s,fun_offset:0x%llx",fun_name.c_str(),fun_offset);
121116
}
122-
123117
}
124-
LOGD("success hook all fun");
118+
LOGD("success hook fun num:%d",hook_fun_num);
125119
}
126120

127121
void clear_all_hook(){
128-
for (int i = 0; i < hook_fun_num; i++) {
129-
DobbyDestroy ((void *)funaddrs[i]);
122+
int clear_ret = clear_all_uprobes();
123+
if(clear_ret!=SET_TRACE_SUCCESS){
124+
LOGE("clear all uprobes error");
130125
}
131-
LOGD("success clear all fun");
126+
LOGD("success clear all uprobes");
132127
hook_fun_num = 0;
133128
fun_name_dict.clear();
134129
}
@@ -138,7 +133,7 @@ void check_all_methods(void *klass,char *clazzName) {
138133
long fun_offset;
139134
while (auto method = il2cpp_class_get_methods(klass, &iter)) {
140135
//TODO attribute
141-
if (method->methodPointer && hook_fun_num<MAX_HOOK_FUN_NUM) {
136+
if (method->methodPointer && hook_fun_num<MAX_HOOK_NUM) {
142137
fun_offset = (uint64_t)method->methodPointer - il2cpp_base;
143138
if(fun_name_dict.find(fun_offset) != fun_name_dict.end()){
144139
continue;
@@ -148,7 +143,6 @@ void check_all_methods(void *klass,char *clazzName) {
148143
snprintf(full_name,MAX_FULL_NAME_LEN,"%s::%s",clazzName,method_name);
149144
std::string mfull_name(full_name);
150145
fun_name_dict[fun_offset]=mfull_name;
151-
funaddrs[hook_fun_num] = (uint64_t)method->methodPointer;
152146
hook_fun_num++;
153147
}
154148
}
@@ -171,6 +165,16 @@ void start_trace(char* data_dir_path){
171165
}
172166
LOGD("success get il2cpp api fun");
173167

168+
int set_module_base_ret = set_module_base(il2cpp_base);
169+
int set_target_file_ret = set_target_file(module_path);
170+
int set_target_uid_ret = set_target_uid(getuid());
171+
172+
if (set_module_base_ret!=SET_TRACE_SUCCESS || set_target_file_ret!=SET_TRACE_SUCCESS || set_target_uid_ret!=SET_TRACE_SUCCESS){
173+
LOGE("init uprobe hook error");
174+
return;
175+
}
176+
LOGD("init uprobe hook success");
177+
174178

175179
strcpy(trace_file_path,data_dir_path);
176180
strcat(trace_file_path,"/files/test_trace.txt");
@@ -200,7 +204,7 @@ void start_trace(char* data_dir_path){
200204
}
201205
for (int i = 0; i < all_type_infos_count; ++i) {
202206
if(strcmp(all_type_infos[i].name,tmp_info)==0){
203-
if(hook_fun_num==MAX_HOOK_FUN_NUM){
207+
if(hook_fun_num==MAX_HOOK_NUM){
204208
break;
205209
}
206210
LOGD("trace %s",all_type_infos[i].name);

app/src/main/cpp/il2cpp_trace.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include <stdint.h>
55

66
#define MAX_FULL_NAME_LEN 200
7-
#define MAX_HOOK_FUN_NUM 10000
87

98
struct Il2CppMetadataField
109
{
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#include <sys/syscall.h>
2+
#include <unistd.h>
3+
4+
5+
#define TRACE_FLAG 511
6+
#define MAX_HOOK_NUM 1000
7+
#define SET_TRACE_SUCCESS 1000
8+
#define SET_TRACE_ERROR 1001
9+
10+
enum trace_info {
11+
SET_TARGET_FILE,
12+
SET_MODULE_BASE,
13+
SET_FUN_INFO,
14+
SET_TARGET_UID,
15+
CLEAR_UPROBE,
16+
};
17+
18+
// unsigned long start, size_t len, unsigned char *vec
19+
20+
int set_module_base(unsigned long module_base){
21+
int ret = syscall(__NR_mincore,module_base,TRACE_FLAG+SET_MODULE_BASE,"");
22+
return ret;
23+
}
24+
25+
int set_target_uid(uid_t uid){
26+
int ret = syscall(__NR_mincore,uid,TRACE_FLAG+SET_TARGET_UID,"");
27+
return ret;
28+
}
29+
30+
int set_target_file(char* file_name){
31+
int ret = syscall(__NR_mincore,0,TRACE_FLAG+SET_TARGET_FILE,file_name);
32+
return ret;
33+
}
34+
35+
int set_fun_info(unsigned long fun_offset,char *fun_name){
36+
int ret = syscall(__NR_mincore,fun_offset,TRACE_FLAG+SET_FUN_INFO,fun_name);
37+
return ret;
38+
}
39+
40+
//set_fun_info函数设置成功但失效的情况下再用这个函数
41+
//,最好在一个程序内不要与set_fun_info函数同时使用
42+
int set_fun_info2(unsigned long fun_offset,char *fun_name){
43+
int ret = syscall(__NR_mincore,fun_offset-0x1000,TRACE_FLAG+SET_FUN_INFO,fun_name);
44+
return ret;
45+
}
46+
47+
int clear_all_uprobes(){
48+
int ret = syscall(__NR_mincore,0,TRACE_FLAG+CLEAR_UPROBE,"");
49+
return ret;
50+
}

0 commit comments

Comments
 (0)