Android安全-SO动态库注入
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
關(guān)于這方面技術(shù),網(wǎng)上已經(jīng)有大把的實(shí)現(xiàn)。在此,我只是記錄下自己的學(xué)習(xí)過程。
0x1 原理
????所謂的SO注入就是將代碼拷貝到目標(biāo)進(jìn)程中,并結(jié)合函數(shù)重定向等其他技術(shù),最終達(dá)到監(jiān)控或改變目標(biāo)進(jìn)程行為的目的。Android是基于Linux內(nèi)核的操作系統(tǒng),而在Linux下SO注入基本是基于調(diào)試API函數(shù)ptrace實(shí)現(xiàn)的,同樣Android的SO注入也是基于ptrace函數(shù),要完成注入還需獲取root權(quán)限。
0x2 流程
????注入過程如下:
????????0x01 獲取目標(biāo)進(jìn)程的pid,關(guān)聯(lián)目標(biāo)進(jìn)程;
????????0x02 獲取并保存目標(biāo)進(jìn)程寄存器值;
????????0x03 獲取目標(biāo)進(jìn)程的dlopen,dlsym函數(shù)的絕對地址;
????????0x04 獲取并保存目標(biāo)進(jìn)程的堆棧,設(shè)置dlopen函數(shù)的相關(guān)參數(shù),將要注入的SO的絕對路徑壓棧;
????????0x05 調(diào)用dlopen函數(shù);
????????0x06 調(diào)用dlsym函數(shù),獲取SO中要執(zhí)行的函數(shù)地址;
????????0x07 調(diào)用要執(zhí)行的函數(shù);
????????0x08 恢復(fù)目標(biāo)進(jìn)程的堆棧,恢復(fù)目標(biāo)進(jìn)程寄存器值,解除關(guān)聯(lián),完成SO動(dòng)態(tài)庫注入;
????????(注:實(shí)際上,0x06和0x07并不屬于SO動(dòng)態(tài)庫注入的步驟,然而僅僅注入是完全沒有意義的,通常我們需要執(zhí)行SO中的函數(shù))
0x3 實(shí)現(xiàn)
????0x01 獲取目標(biāo)進(jìn)程的pid,關(guān)聯(lián)目標(biāo)進(jìn)程:
????????通過遍歷查找/proc/pid/cmdline文件中是否含有目標(biāo)進(jìn)程名process_name,若有則進(jìn)程名對應(yīng)的進(jìn)程號即為pid。接著,直接調(diào)用函數(shù)ptrace_attach(pid)即可完成關(guān)聯(lián)。
????0x02 獲取并保存目標(biāo)進(jìn)程寄存器值:
????? ? 直接調(diào)用ptrace(PTRACE_GETREGS, pid, NULL, &saved_regs),當(dāng)然saved_regs要定義為全局變量。
????0x03 獲取目標(biāo)進(jìn)程的dlopen,dlsym函數(shù)的絕對地址:
????????大概思路是這樣的:首先通過遍歷/proc/pid/maps文件分別得到本進(jìn)程中dlopen函數(shù)所在動(dòng)態(tài)庫的基地址local_module_base和目標(biāo)進(jìn)程dlopen函數(shù)所在動(dòng)態(tài)庫的基地址remote_module_base,接著獲取本進(jìn)程dlopen函數(shù)的絕對地址local_addr =?(void*)dlopen。需要明白的是,不同進(jìn)程中相同的動(dòng)態(tài)庫中的同一個(gè)函數(shù)的偏移地址一定是一樣的,所以目標(biāo)進(jìn)程dlopen函數(shù)的絕對地址為:local_addr - local_module_base +?remote_module_base。dlsym同理,不再詳述。
????0x04 獲取并保存目標(biāo)進(jìn)程的堆棧,設(shè)置dlopen函數(shù)的相關(guān)參數(shù),將要注入的SO的絕對路徑壓棧:
????????當(dāng)我們的要執(zhí)行的函數(shù)的某些參數(shù)需要壓入堆棧的時(shí)候,就需要提前保存堆棧狀態(tài),調(diào)用ptrace_readdata(pid, (void *)regs.ARM_sp, (void *)sbuf, sizeof(sbuf)),其中sbuf為char數(shù)組,用來存放堆棧。調(diào)用ptrace_writedata(pid, (void *)regs.ARM_sp, (void *)so_path, strlen(so_path) + 1),其中so_path為SO的絕對路徑。函數(shù)傳參規(guī)則:前四個(gè)參數(shù)分別由寄存器r0、r1、r2、r3存放,超過四個(gè)參數(shù)則壓入堆棧。
????0x05 調(diào)用dlopen函數(shù):
????????參數(shù)設(shè)置好后,設(shè)置ARM_pc = dlopen_addr,?ARM_lr = 0。調(diào)用ptrace_setregs(pid, regs)寫入修改后的寄存器值,調(diào)用ptrace_continue( pid )使目標(biāo)進(jìn)程繼續(xù)運(yùn)行。(注:dlopen_addr為0x03獲取到的目標(biāo)進(jìn)程dlopen函數(shù)的絕對地址,ARM_lr = 0的目的在于當(dāng)目標(biāo)進(jìn)程執(zhí)行完dlopen函數(shù),使目標(biāo)進(jìn)程發(fā)生異常,從而讓本進(jìn)程重新獲得控制權(quán))
????0x06 調(diào)用dlsym函數(shù),獲取SO中要執(zhí)行的函數(shù)地址:
????????實(shí)現(xiàn)方式與調(diào)用dlopen函數(shù)類似,不再詳述。
????0x07 調(diào)用要執(zhí)行的函數(shù):
????????實(shí)現(xiàn)方式與調(diào)用dlopen函數(shù)類似,不再詳述。
? ??0x08 恢復(fù)目標(biāo)進(jìn)程的堆棧,恢復(fù)目標(biāo)進(jìn)程寄存器值,解除關(guān)聯(lián),完成SO動(dòng)態(tài)庫注入:
????????調(diào)用ptrace_writedata(pid, (uint8_t *)saved_regs.ARM_sp, (uint8_t *)sbuf, sizeof(sbuf))恢復(fù)堆棧,調(diào)用ptrace_setregs(pid, &saved_regs)恢復(fù)寄存器值,調(diào)用ptrace_detach(pid)解除關(guān)聯(lián),完成SO動(dòng)態(tài)庫注入。
0x4 代碼
????貼一下主要邏輯代碼:
pid_t?pid?=?find_pid_of("xxx"); ptrace_attach(pid); uint32_t?*inject_so_of(pid_t?pid,?const?char?*so_path)?{int?status?=?0;struct?pt_regs?regs;memcpy(®s,?&saved_regs,?sizeof(regs));ptrace_readdata(pid,?(void?*)regs.ARM_sp,?(void?*)sbuf,?sizeof(sbuf));ptrace_writedata(pid,?(void?*)regs.ARM_sp,?(void?*)so_path,?strlen(so_path)?+?1);uint32_t?parameters[2];parameters[0]?=?regs.ARM_sp;parameters[1]?=?RTLD_NOW;if?(?ptrace_call(pid,?find_dlopen_addr(pid),?parameters,?2,?®s?)?==?-1?)DPRINTF("dlopen?error\n");ptrace_getregs(pid,?®s);uint32_t?r0?=?regs.ARM_r0;DPRINTF("[+2]\t注入動(dòng)態(tài)庫成功,返回的句柄為:?%x\n",?r0);ptrace_setregs(pid,?&saved_regs);ptrace_writedata(pid,?(uint8_t?*)saved_regs.ARM_sp,?(uint8_t?*)sbuf,?sizeof(sbuf));ptrace_detach(pid);return?(uint32_t?*)r0; }
0x5 參考
? ? 玩轉(zhuǎn)ptrace:http://blog.csdn.net/sealyao/article/details/6710772
????《轉(zhuǎn)載》linux動(dòng)態(tài)庫注入:http://blog.chinaunix.net/uid-7247280-id-2060516.html
????發(fā)個(gè)Android平臺上的注入代碼:http://bbs.pediy.com/showthread.php?t=141355
轉(zhuǎn)載于:https://my.oschina.net/u/1777508/blog/664025
總結(jié)
以上是生活随笔為你收集整理的Android安全-SO动态库注入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决 error: command 's
- 下一篇: 黑马Android全套视频无加密完整版