zoukankan      html  css  js  c++  java
  • Android下so注入汇总

    /*
    *  作者:蟑螂一号
    *  原文链接:http://www.sanwho.com/133.html
    *  转载请注明出处
    */

    Android下so注入是基于ptrace系统调用,因此要想学会android下的so注入,首先需要了解ptrace的用法。

    ptrace用法可以参考博客:http://blog.sina.com.cn/s/blog_4ac74e9a0100n7w1.html,也可以在ubuntu下输入man ptrace命令,查看具体描述。

    android中进程系统调用劫持可参考博客:http://www.kanxue.com/bbs/showthread.php?t=180461,这是一个android简单的ptrace监控远程进程监控调用的例子。

    Android系统是基于Linux系统,在linux系统中可以通过ptrace系统调用实现进程注入。ptrace注入过程大致过程如下:

    (1)基于shellcode加载

    [1]编写shellcode,shellcode是使用汇编语言写一段汇编程序,该程序实现so库的加载、so库函数查找以及执行库中的函数。

    [2]通过远程进程pid,ATTACH到远程进程。

    [3]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。

    [4]获取远程进程系统调用mmap、dlopen、dlsym调用地址。

    [5]调用远程进程mmap分配一段存储空间,并在空间中写入shellcode、so库路径以及函数调用参数。

    [6]执行远程进程shellcode代码。

    [7]恢复远程进程寄存器。

    [8]detach远程进程。

    基于shellcode注入可看雪古河大哥写的libInject,网址: http://bbs.pediy.com/showthread.php?t=141355

    其中,dlopen和dlsym是用于打开动态链接库中的函数,将动态链接库中的函数或类导入到本程序中。

    dlopen函数定义:
      void * dlopen( const char * pathname, int mode );
      函数描述:
      dlopen()函数以指定模式打开指定的动态链接库文件,并返回一个句柄给dlsym()的调用进程。使用dlclose()来卸载打开的库。
    
    dlsym函数原型是
    
      void* dlsym(void* handle,const char* symbol)
    
      该函数在<dlfcn.h>文件中。
    
      handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用。

    (2)直接加载

    [1]通过远程进程pid,ATTACH到远程进程。

    [2]获取远程进程寄存器值,并保存,以便注入完成后恢复进程原有状态。

    [3]获取远程进程系统调用mmap、dlopen、dlsym调用地址。

    [4]调用远程进程mmap分配一段存储空间,并在空间中写入so库路径以及函数调用参数。

    [5]执行远程进程dlopen,加载so库。

    [6]执行远程进程dlsym,获取so库中需要执行的函数地址。

    [7]执行远程进程中的函数。

    [7]恢复远程进程寄存器。

    [8]DETACH远程进程。

    目前android  so注入的版本基本上都是基于古河大哥的libInject修改而来。关于so注入的项目,还可以参考洗大师的一个开源项目,网址:https://code.google.com/p/libandroidinjector/downloads/list。洗大师注入需要修改elf文件。

    提供一个方便测试so注入成功与否的小测试库,代码如下:

     1 #include <unstd.h>
     2  
     3 #include <stdio.h>
     4  
     5 #include <android/log.h>
     6  
     7 #define LOG_TAG    "test"
     8  
     9 __attribute__((constructor))   void   inject () {
    10  
    11 __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,"Hello,I am  injected.");
    12  
    13 }

    说明:若函数被设定为constructor属性,则该函数会在main()函数执行之前被自动的执行。因此,so注入测试中,只需注入以上代码编译的so库,无需调用注入so的相关函数,即可测试是否注入到远程进程。

    补充说明——实现方式

    转自:http://ele7enxxh.com/Android-Shared-Library-Injection.html

        0x01 获取目标进程的pid,关联目标进程:

            通过遍历查找/proc/pid/cmdline文件中是否含有目标进程名process_name,若有则进程名对应的进程号即为pid。接着,直接调用函数ptrace_attach(pid)即可完成关联。

        0x02 获取并保存目标进程寄存器值:

            直接调用ptrace(PTRACE_GETREGS, pid, NULL, &saved_regs),当然saved_regs要定义为全局变量。

        0x03 获取目标进程的dlopen,dlsym函数的绝对地址:

            大概思路是这样的:首先通过遍历/proc/pid/maps文件分别得到本进程中dlopen函数所在动态库的基地址local_module_base和目标进程dlopen函数所在动态库的基地址remote_module_base,接着获取本进程dlopen函数的绝对地址local_addr = (void*)dlopen。需要明白的是,不同进程中相同的动态库中的同一个函数的偏移地址一定是一样的,所以目标进程dlopen函数的绝对地址为:local_addr - local_module_base + remote_module_base。dlsym同理,不再详述。

        0x04 获取并保存目标进程的堆栈,设置dlopen函数的相关参数,将要注入的SO的绝对路径压栈:

            当我们的要执行的函数的某些参数需要压入堆栈的时候,就需要提前保存堆栈状态,调用ptrace_readdata(pid, (void *)regs.ARM_sp, (void *)sbuf, sizeof(sbuf)),其中sbuf为char数组,用来存放堆栈。调用ptrace_writedata(pid, (void *)regs.ARM_sp, (void *)so_path, strlen(so_path) + 1),其中so_path为SO的绝对路径。函数传参规则:前四个参数分别由寄存器r0、r1、r2、r3存放,超过四个参数则压入堆栈。

        0x05 调用dlopen函数:

            参数设置好后,设置ARM_pc = dlopen_addr, ARM_lr = 0。调用ptrace_setregs(pid, regs)写入修改后的寄存器值,调用ptrace_continue( pid )使目标进程继续运行。(注:dlopen_addr为0x03获取到的目标进程dlopen函数的绝对地址,ARM_lr = 0的目的在于当目标进程执行完dlopen函数,使目标进程发生异常,从而让本进程重新获得控制权)

        0x06 调用dlsym函数,获取SO中要执行的函数地址:

            实现方式与调用dlopen函数类似,不再详述。

        0x07 调用要执行的函数:

            实现方式与调用dlopen函数类似,不再详述。

        0x08 恢复目标进程的堆栈,恢复目标进程寄存器值,解除关联,完成SO动态库注入:

            调用ptrace_writedata(pid, (uint8_t *)saved_regs.ARM_sp, (uint8_t *)sbuf, sizeof(sbuf))恢复堆栈,调用ptrace_setregs(pid, &saved_regs)恢复寄存器值,调用ptrace_detach(pid)解除关联,完成SO动态库注入。

  • 相关阅读:
    [Vue warn]: Avoid mutating a prop directly since the value will be overwritten
    修改git地址
    Clipboard使用
    Electron as GUI of Python
    VUE AXIOS封装三
    Vue-Cli3/Webpack / i18n / image / CDN vue项目优化总结
    echarts 折线图点击高亮
    vue中 左侧导航条 多个toggleClass
    js中异常处理
    Element UI disableddate设置动态时间,结束日期不可大于开始日期以及时间点
  • 原文地址:https://www.cnblogs.com/goodhacker/p/3920365.html
Copyright © 2011-2022 走看看