Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移

admin 2024年4月24日00:50:09评论2 views字数 4595阅读15分19秒阅读模式

背景

学习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, {
            onEnterfunction (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));
                    
                }
            },
            onLeavefunction (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;
}

charread_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。Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移跳进去偏移地址中,汇编视图。Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移伪代码:Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移在函数头,按下x,交叉引用,跳到被调用地方:Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移源代码逻辑:Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移和源代码逻辑对上了。

原文始发于微信公众号(安全后厨):Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月24日00:50:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Android逆向分析64——Android逆向系统中定位某个so创建线程函数的偏移https://cn-sec.com/archives/2684707.html

发表评论

匿名网友 填写信息