【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )
文章目錄
- 一、準備 mmap 函數的參數
- 二、mmap 函數遠程調用
一、準備 mmap 函數的參數
上一篇博客 【Android 逆向】Android 進程注入工具開發 ( 注入代碼分析 | 遠程調用 目標進程中 libc.so 動態庫中的 mmap 函數 一 | mmap 函數簡介 ) 中介紹了 mmap 函數 ;
mmap 函數的函數原型如下 :
<sys/mman.h> void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset); int munmap(void* start,size_t length);mmap 函數參數含義 :
- void* start : 如果為 0 就是讓系統自動分配 , 如果不為 0 , 則由用戶指定分配的地址 ;
- size_t length : 申請分配內存的大小 ;
- int prot : 內存保護標志 , 如 PROT_READ | PROT_WRITE | PROT_EXEC , 表示 可讀 | 可寫 | 可執行 ;
- int flags : 映射對象類型標志位標志位 , 如 MAP_ANONYMOUS | MAP_PRIVATE , 表示 匿名 | 私有 ;
- int fd : 文件描述符 ; 沒有設置為 0 ;
- off_t offset : 被映射對象的起點偏移量 , 一般設置 0 ;
將 mmap 的參數放到 parameters 數組中 , 之后要將該地址傳遞給遠程進程的 ESP 寄存器 , 用于指定
long parameters[10];/* 下面是遠程調用 mmap 函數分配棧內存信息 *//* call mmap 調用 mmap 函數傳入的參數 */parameters[0] = 0; // addr 地址讓系統分配 , 也可以指定內存地址parameters[1] = 0x4000; // size 分配的內存大小 0x4000 字節 , 也就是 16KB , mmap 函數的參數胡parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC; // prot 可讀 | 可寫 | 可執行 parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE; // flags 匿名 | 私有 parameters[4] = 0; //fd 文件描述符 parameters[5] = 0; //offset 偏移量二、mmap 函數遠程調用
由于遠程調用涉及到寄存器的操作 , 因此 arm 架構 與 x86 架構的 遠程調用是不同的 , 本次開發的是 x86 架構下的遠程調用 ;
首先 , 將 mmap 函數執行的參數 , 寫出到遠程進程的內存中 , 調用 ptrace_writedata 方法 , 寫出內存數據 ;
/* 設置 ESP 棧指針寄存器 */regs->esp -= (num_params) * sizeof(long);/* 將 long* params 參數寫出到 pid 對應的遠程進程中 , 然后將寫出后數據的首地址 , 設置到 pid_t pid 進程號對應的遠程進程的 ESP 寄存器中 , 設置的數據長度 4 字節 */ptrace_writedata(pid, (uint8_t*)(void*)regs->esp, (uint8_t*)params, (num_params) * sizeof(long));此外還要在棧中設置一個 0 地址 , 為了保證遠程進程執行完畢后 , 自動訪問 0 地址 , 導致崩潰 , 這樣調試程序就可以收回控制權 ; 參考 【Android 逆向】Android 進程注入工具開發 ( EIP 寄存器指向 dlopen 函數 | ESP 寄存器指向棧內存 | 調試程序收回目標進程控制權 ) 博客 ;
/* 設置一個 0 地址 */long tmp_addr = 0x00;/* 設置 0 地址的作用是 保證 遠程進程 訪問該 0 地址 導致崩潰 , 調試工具收回進程控制權 */regs->esp -= sizeof(long);ptrace_writedata(pid, (uint8_t*)(regs->esp), (uint8_t*)&tmp_addr, sizeof(tmp_addr));然后 , 設置 遠程進程 的 EIP 寄存器 , 指定執行哪個函數 , 這個 函數地址 是在 【Android 逆向】Android 進程注入工具開發 ( 注入代碼分析 | 獲取 遠程 目標進程 中的 /system/lib/libc.so 動態庫中的 mmap 函數地址 ) 博客中獲取的 mmap 函數地址 ;
/* 設置 EIP 寄存器值 , 存儲 CPU 下一條將要執行的指令 */regs->eip = addr;/* 設置 pid 遠程進程的寄存器值 */if (ptrace_setregs(pid, regs) == -1|| ptrace_continue(pid) == -1) {printf("error\n");return -1;}最后 , 調用 ptrace_continue 方法 , 執行該 mmap 函數 ;
ptrace_continue(pid)mmap 函數遠程調用 完整代碼 :
#elif defined(__i386__) long ptrace_call(pid_t pid, uint32_t addr, long* params, uint32_t num_params, struct user_regs_struct* regs) {/* 參數說明 : */if (num_params > 0 && (params != NULL)) {/* 設置 ESP 棧指針寄存器 */regs->esp -= (num_params) * sizeof(long);/* 將 long* params 參數寫出到 pid 對應的遠程進程中 , 然后將寫出后數據的首地址 , 設置到 pid_t pid 進程號對應的遠程進程的 ESP 寄存器中 , 設置的數據長度 4 字節 */ptrace_writedata(pid, (uint8_t*)(void*)regs->esp, (uint8_t*)params, (num_params) * sizeof(long));}/* 設置一個 0 地址 */long tmp_addr = 0x00;/* 設置 0 地址的作用是 保證 遠程進程 訪問該 0 地址 導致崩潰 , 調試工具收回進程控制權 */regs->esp -= sizeof(long);ptrace_writedata(pid, (uint8_t*)(regs->esp), (uint8_t*)&tmp_addr, sizeof(tmp_addr));/* 設置 EIP 寄存器值 , 存儲 CPU 下一條將要執行的指令 */regs->eip = addr;/* 設置 pid 遠程進程的寄存器值 */if (ptrace_setregs(pid, regs) == -1|| ptrace_continue(pid) == -1) {printf("error\n");return -1;}/* 等待遠程調用執行完畢 */int stat = 0;waitpid(pid, &stat, WUNTRACED);while (stat != 0xb7f) {if (ptrace_continue(pid) == -1) {printf("error\n");return -1;}waitpid(pid, &stat, WUNTRACED);}return 0; }總結
以上是生活随笔為你收集整理的【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 逆向】Android
- 下一篇: 【Android 逆向】Android