背景
学习aosp12笔记,在系统中定位某个so创建线程函数的偏移。
环境
aosp12 pixel3 Ubuntu 20.0.4
frida定位so中线程创建位置
通常会使用以下这样脚本定位线程创建的位置:
function hook_pthread_create() {
var libcModule = Process.findModuleByName('libc.so');
if (libcModule) {
var pthread_create = new NativeFunction(
libcModule.findExportByName('pthread_create'),
'int', ['pointer', 'pointer', 'pointer', 'pointer']
);
Interceptor.attach(pthread_create, {
onEnter: function (args) {
var libModule = Process.findModuleByName('xxx.so');
if (libModule) {
// pthread_create 之前
console.log("pthread_create called with arguments:");
console.log("start_routine:", args[2]);
console.log("function at=>0x"+(args[2] - libModule.base).toString(16));
}
},
onLeave: function (retval) {
// pthread_create 之后
console.log("pthread_create returned:", retval);
if (retval.toInt32() === 0) {
console.log("Thread created successfully!");
} else {
console.log("Thread creation failed!");
}
}
});
}
}
pthread_create的函数原型:
int pthread_create(pthread_t* __pthread_ptr, pthread_attr_t const* __attr, void* (*__start_routine)(void*), void*);
使用案例:
pthread_t thread;
/**
* 四个参数:
* 1. 指向线程标识符的指针
* 2. 设置线程属性
* 3. 线程运行函数的起始地址
* 4. 运行函数的参数
*/
int result = pthread_create(&thread, nullptr,
reinterpret_cast<void *(*)(void *)>(test22222), nullptr);
第三个参数就是线程起来之后执行的函数
,也就是上面的args[2]
。
目的是拿到目标so的base,线程运行函数减去base得到偏移量。
在系统中实现这个找偏移量功能
线程创建的实现在这个位置aosp/bionic/libc/bionic/pthread_create.cpp
部分代码
int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
void* (*start_routine)(void*), void* arg) {
ErrnoRestorer errno_restorer;
pthread_attr_t thread_attr;
ScopedTrace trace("pthread_create");
if (attr == nullptr) {
pthread_attr_init(&thread_attr);
} else {
thread_attr = *attr;
attr = nullptr; // Prevent misuse below.
}
...
...
}
start_routine
就是线程跑的那个函数地址了。offset = start_routine - so_base
现在就差目标so的base address了。 在maps中读取目标so的base,目标so通过读取文件动态输入。
uintptr_t getbase(const char* library_name) {
FILE* maps = fopen("/proc/self/maps", "r");
if (!maps) {
return 0;
}
char line[1024];
uintptr_t base_address = 0;
while (fgets(line, sizeof(line), maps)) {
if (strstr(line, library_name) && strstr(line, " r-xp ")) {
if (sscanf(line, "%zx-", &base_address) == 1) {
fclose(maps);
return base_address;
}
}
}
fclose(maps);
return 0;
}
char* read_soname() {
const char* path = "/data/system/rom/soname";
FILE* so = fopen(path, "r");
if (!so) {
return NULL;
}
char line[64];
if (fgets(line, sizeof(line), so) == NULL) {
fclose(so);
return NULL;
}
fclose(so);
return strdup(line);
}
在需要监控的时候把so名字写入到/data/system/rom/soname
文件中。
pthread_create中打印offset。
// 目标so偏移量计算和打印
int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
void* (*start_routine)(void*), void* arg) {
ErrnoRestorer errno_restorer;
async_safe_format_log(4, "libccc", "start pthread_create = %p", start_routine);
async_safe_format_log(4, "libccc", "Creating thread with uid: %d", getuid());
char* target_so_name = read_soname();
if (target_so_name) {
async_safe_format_log(4, "libccc", "Creating thread with so: %s", target_so_name);
uintptr_t base_address = getbase(target_so_name);
if (base_address != 0) {
async_safe_format_log(4, "libccc", "Base address of so: %p", reinterpret_cast<void*>(base_address));
ptrdiff_t offset = reinterpret_cast<char*>(start_routine) - reinterpret_cast<char*>(base_address);
async_safe_format_log(4, "libccc", "Offset in so: %p", reinterpret_cast<void*>(static_cast<uintptr_t>(offset)));
} else {
async_safe_format_log(4, "libccc", "Could not find base address of so");
}
}
编译刷机,编写一个demo来测试,以下是logcat日志。
I/libccc: start pthread_create = 0x7a70bd7ca8
I/libccc: Creating thread with uid: 10097
I/libccc: Creating thread with so: libstalker.so
I/libccc: Base address of so: 0x7a70bc9000
I/libccc: Offset in so: 0xeca8
I/mytag: 我是被线程调用的函数
触发了特定so中线程创建逻辑后,在logcat中看到的日志。可以拿到创建线程在对应so中的偏移,在ida中直接跳到0xeca8
位置。快捷键g。跳进去偏移地址中,汇编视图。
伪代码:
在函数头,按下x,交叉引用,跳到被调用地方:
源代码逻辑:
和源代码逻辑对上了。
原文始发于微信公众号(安全后厨):Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论