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