zoukankan      html  css  js  c++  java
  • 自己实现so加载器

      在进行安全研究中,我们需要经常使用ida等工具对app的so进行动态调试。这其中遇到的最大问题可能就是app加了反调试、反root等保护手段对应用运行环境进行检测,而这些手段往往是在我们附加进程之前就已经加载了的,所以不能通过ida等调试工具直接附加进程的方式来调试这些so,因而需要我们自己实现加载器来加载目标so文件。

    下面就是我们写的一个简单的加载器代码:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <dlfcn.h>
     4 
     5 int main(){
     6       printf("Loading libs
    ");
     7       int (*pt2Function)(void) = NULL;
     8       //pointer to a void function - change this to match method sig
     9       void* sdl_library = dlopen("/system/libtarget.so", RTLD_LAZY);
    10       if (sdl_library == NULL) {
    11           // report error ...
    12           printf("Unable to load library
    ");
    13           char *errstr;  
    14           errstr = dlerror();
    15           if (errstr != NULL)
    16                 printf ("A dynamic linking error occurred: (%s)
    ", errstr);
    17       } else {
    18           printf("Lib loaded, getting dlysm
    ");
    19           void* initializer = dlsym(sdl_library,"JNI_OnLoad");
    20           if (initializer == NULL) {
    21               // report error ...   printf("Unable to get address of JNI_OnLoad
    ");
    22               char *errstr;
    23               errstr = dlerror();
    24               if (errstr != NULL)
    25                     printf ("A dynamic linking error occurred: (%s)
    ", errstr);
    26           } else {
    27               // cast initializer to its proper type and use
    28               printf("calling get process
    ");
    29               //asm("BKPT #0");
    30               pt2Function = initializer;
    31               printf("got get process, setting up
    ");
    32               printf("Ok, lets Calling the function");
    33               int result = pt2Function();
    34               printf("Result of call is %d", result);
    35               //asm("BKPT #0");
    36           }
    37       }
    38       return 0;
    39 }

      从代码中可知,我们的目标是JNI_Onload函数,这是因为反调试和系统环境检测功能代码往往是在JNI_Onload函数中设置的。我们可以控制该函数指针指向任意so文件的导出函数然后调用它。

      这个代码可以在任意标准Linux系统下编译运行。我们使用dlopen()函数动态加载library库,dlsym()函数控制指针指向我们需要测试的导出函数,然后直接调用目标函数,传递任意参数给它,以便跟踪执行流程,甚至进行fuzz,漏洞利用。
      要对上述代码进行编译,还需编写Android.mk文件:

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS) 
    # give module name
    LOCAL_MODULE := soloader 
    # list your C files to compile
    LOCAL_SRC_FILES := soloader.c 
    # Build executables instead of a library for android.
    include $(BUILD_EXECUTABLE)

      通过Android studio创建Android工程,将soloader.c和Android.mk文件置于src/mian/jni目录下,通过ndk-build进行编译,然后在/libs/armeabi目录下就可以找到编译好的soloader了。然后通过adb命令push到/system目录(需要先remount),就可以执行了。

       本文根据https://www.trustwave.com/Resources/SpiderLabs-Blog/Custom-Native-Library-Loader-for-Android/进行翻译。

  • 相关阅读:
    Linux下semaphore的使用 进程间互斥的一个好方法
    CURL编程:什么是NonASCII平台,如何取得页面的charset
    C++中的重载(Overload), 覆盖(Override)和隐藏(Hide)
    system调用虽然用了exec,但是fd, signal这些还是会保留父进程的,be careful
    addr2line,可以根据一个地址打印出对应的代码行
    POSIX Threads Programming 阅读笔记(来自劳伦斯利物浦实验室的文章)
    [Gammu]setlocale和bindtextdomain函数的用法
    常用编码
    用PL/SQL画直方图
    窗体的关闭
  • 原文地址:https://www.cnblogs.com/goodhacker/p/6877526.html
Copyright © 2011-2022 走看看