自己实现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\n");
 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\n");
13           char *errstr;  
14           errstr = dlerror();
15           if (errstr != NULL)
16                 printf ("A dynamic linking error occurred: (%s)\n", errstr);
17       } else {
18           printf("Lib loaded, getting dlysm\n");
19           void* initializer = dlsym(sdl_library,"JNI_OnLoad");
20           if (initializer == NULL) {
21               // report error ...   printf("Unable to get address of JNI_OnLoad\n");
22               char *errstr;
23               errstr = dlerror();
24               if (errstr != NULL)
25                     printf ("A dynamic linking error occurred: (%s)\n", errstr);
26           } else {
27               // cast initializer to its proper type and use
28               printf("calling get process\n");
29               //asm("BKPT #0");
30               pt2Function = initializer;
31               printf("got get process, setting up\n");
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/进行翻译。

posted @ 2017-05-19 11:35  bamb00  阅读(1509)  评论(0编辑  收藏  举报