Android so注入(inject)和Hook技術學習(二)——G
全域性符號表(GOT表)hook實際是透過解析SO檔案,將待hook函式在got表的地址替換為自己函式的入口地址,這樣目標程式每次呼叫待hook函式時,實際上是執行了我們自己的函式。
GOT表其實包含了匯入表和匯出表,匯出表指將當前動態庫的一些函式符號保留,供外部呼叫,匯入表中的函式實際是在該動態庫中呼叫外部的匯出函式。
這裡有幾個關鍵點要說明一下:
(1) so檔案的絕對路徑和載入到記憶體中的基址是可以透過 /proc/[pid]/maps 獲取到的。
(2) 修改匯入表的函式地址的時候需要修改頁的許可權,增加寫許可權即可。
(3) 一般的匯入表Hook是基於注入操作的,即把自己的程式碼注入到目標程式,本次例項重點講述Hook的實現,注入程式碼採用上節所有程式碼inject.c。
匯入表的hook有兩種方法,以hook fopen函式為例。
方法一:
透過解析elf格式,找出靜態的.got表的位置,並在記憶體中找到相應的.got表位置,這個時候記憶體中.got表儲存著匯入函式的地址,讀取目標函式地址,與.got表每一項函式入口地址進行匹配,找到的話就直接替換新的函式地址,這樣就完成了一次匯入表的Hook操作了。
hook流程如下圖所示:
圖1 匯入表Hook流程圖
具體程式碼實現如下:
entry.c:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 11 #define LOG_TAG "INJECT" 12 #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args) 13 14 //FILE *fopen(const char *filename, const char *modes) 15 FILE* (*old_fopen)(const char *filename, const char *modes); 16 FILE* new_fopen(const char *filename, const char *modes){ 17 LOGD("[+] New call fopen.n"); 18 if(old_fopen == -1){ 19 LOGD("error.n"); 20 } 21 return old_fopen(filename, modes); 22 } 23 24 void* get_module_base(pid_t pid, const char* module_name){ 25 FILE* fp; 26 long addr = 0; 27 char* pch; 28 char filename[32]; 29 char line[1024]; 30 31 // 格式化字串得到 "/proc/pid/maps" 32 if(pid 執行ndk-build編譯,得到libentry.so,push到/data/local/tmp目錄下,執行上節所得到的inject程式,得到如下結果,表明hook成功:
圖2.
方法二
透過分析program header table查詢got表。匯入表對應在動態連結段.got.plt(DT_PLTGOT)指向處,但是每項的資訊是和GOT表中的表項對應的,因此,在解析動態連結段時,需要解析DT_JMPREL、DT_SYMTAB,前者指向了每一個匯入表表項的偏移地址和相關資訊,包括在GOT表中偏移,後者為GOT表。
具體程式碼如下:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 11 #define LOG_TAG "INJECT" 12 #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args) 13 14 15 //FILE *fopen(const char *filename, const char *modes) 16 FILE* (*old_fopen)(const char *filename, const char *modes); 17 FILE* new_fopen(const char *filename, const char *modes){ 18 LOGD("[+] New call fopen.n"); 19 if(old_fopen == -1){ 20 LOGD("error.n"); 21 } 22 return old_fopen(filename, modes); 23 } 24 25 void* get_module_base(pid_t pid, const char* module_name){ 26 FILE* fp; 27 long addr = 0; 28 char* pch; 29 char filename[32]; 30 char line[1024]; 31 32 // 格式化字串得到 "/proc/pid/maps" 33 if(pid e_ident, "177ELF", 4) != 0) { 77 return 0; 78 } 79 80 Elf32_Phdr* phdr_table = (Elf32_Phdr*)(base_addr + header->e_phoff); 81 if (phdr_table == 0) 82 { 83 LOGD("[+] phdr_table address : 0"); 84 return 0; 85 } 86 size_t phdr_count = header->e_phnum; 87 LOGD("[+] phdr_count : %d", phdr_count); 88 89 90 //遍歷program header table,ptype等於PT_DYNAMIC即為dynameic,獲取到p_offset 91 unsigned long dynamicAddr = 0; 92 unsigned int dynamicSize = 0; 93 int j = 0; 94 for (j = 0; j > 8) & 0xffffff;150 Elf32_Sym* symTableIndex = (Elf32_Sym*)(number*16 + symTabOff + base_addr);151 char* funcName = (char*)(symTableIndex->st_name + strTabOff + base_addr);152 //LOGD("[+] Func Name : %s",funcName);153 if(memcmp(funcName, "fopen", 5) == 0)154 {155 // 獲取當前記憶體分頁的大小156 uint32_t page_size = getpagesize();157 // 獲取記憶體分頁的起始地址(需要記憶體對齊)158 uint32_t mem_page_start = (uint32_t)(((Elf32_Addr)rel_table[i].r_offset + base_addr)) & (~(page_size - 1));159 LOGD("[+] mem_page_start = %lx, page size = %lxn", mem_page_start, page_size);160 //void* pstart = (void*)MEM_PAGE_START(((Elf32_Addr)rel_table[i].r_offset + base_addr));161 mprotect((uint32_t)mem_page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);162 LOGD("[+] r_off : %x",rel_table[i].r_offset + base_addr);163 LOGD("[+] new_fopen : %x",new_fopen);164 *(unsigned int*)(rel_table[i].r_offset + base_addr) = new_fopen;165 }166 }167 168 return 0;169 }170 171 int hook_entry(char* a){172 LOGD("[+] Start hooking.n");173 hook_fopen();174 return 0;175 } 執行後的結果為:
圖3
參考文章:
http://gslab.qq.com/portal.php?mod=view&aid=169
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/36/viewspace-2804522/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Android日常學習:Android Hook技術小實踐AndroidHook
- 針對新型程式注入技術Ctrl-Inject原理分析
- Android hook 技術淺析AndroidHook
- 愛奇藝 Android PLT hook 技術分享AndroidHook
- 淺談API HOOK技術(二) (轉)APIHook
- Hook技術之Hook ActivityHook
- 學習ASM技術(二)--diskgroup管理ASM
- Vue.js 原始碼學習五 —— provide 和 inject 學習Vue.js原始碼IDE
- 最新二次注入攻擊和程式碼分析技術
- Android 安全研究 hook 神器frida學習(一)AndroidHook
- Android免清單註冊啟動Activity Hook技術AndroidHook
- React學習之HookReactHook
- 防病毒、駭客技術、網路安全技術的學習經驗、學習方法和學習網站學習網站
- Android技術棧(三)依賴注入技術的探討與實現Android依賴注入
- COM 程式注入技術
- iOS逆向 程式碼注入+HookiOSHook
- vue 3 學習筆記 (八)——provide 和 inject 用法及原理Vue筆記IDE
- docker技術學習Docker
- 如何學習技術?
- 學習ASM技術(五)--檔名和TemplateASM
- 淺談API HOOK技術(一) (轉)APIHook
- IOC注入技術之編譯時注入編譯
- 最新堆疊查詢注入攻擊和注入程式碼分析技術
- LTE-5G學習筆記12--5G 技術通俗講解筆記
- LTE-5G學習筆記7---5G技術考試必看筆記
- @Resource,@Autowired,@Inject3種注入方式詳解
- SQL 注入技術詳解SQL
- C# DLL注入技術C#
- iOS HOOK 注入與重簽名iOSHook
- 一起來學習 WebRTC (篇二) | 掘金技術徵文Web
- 會話技術 cookie和session 學習筆記會話CookieSession筆記
- 58和百姓網的技術學習
- 學習和使用技術的4種層次
- 學習和使用技術的四種層次
- 思考、學習新技術的原則和方式
- 如何學習新技術
- docker技術沙龍學習Docker
- 技術學習網站學習網站