av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

android的got表HOOK實(shí)現(xiàn)代碼

瀏覽:3日期:2023-12-08 17:05:10
概述

對(duì)于android的so文件的hook根據(jù)ELF文件特性分為:Got表hook、Sym表hook和inline hook等。全局符號(hào)表(GOT表)hook,它是通過(guò)解析SO文件,將待hook函數(shù)在got表的地址替換為自己函數(shù)的入口地址,這樣目標(biāo)進(jìn)程每次調(diào)用待hook函數(shù)時(shí),實(shí)際上是執(zhí)行了我們自己的函數(shù)。

Androd so注入和函數(shù)Hook(基于got表)的步驟:

1.ptrace附加目標(biāo)pid進(jìn)程;2.在目標(biāo)pid進(jìn)程中,查找內(nèi)存空間(用于存放被注入的so文件的路徑和so中被調(diào)用的函數(shù)的名稱或者shellcode);3.調(diào)用目標(biāo)pid進(jìn)程中的dlopen、dlsym等函數(shù),用于加載so文件實(shí)現(xiàn)Android so的注入和函數(shù)的Hook;4.釋放附加的目標(biāo)pid進(jìn)程和卸載注入的so文件。

具體代碼實(shí)現(xiàn)

以下以fopen函數(shù)進(jìn)行g(shù)ot hook為例。

//獲取模塊地址功能實(shí)現(xiàn)void* getModuleBase(pid_t pid, const char* module_name){ FILE* fp; long address = 0; char* pch; char filename[32]; char line[1024]; // 格式化字符串得到 '/proc/pid/maps' if(pid < 0){snprintf(filename, sizeof(filename), '/proc/self/maps'); }else{snprintf(filename, sizeof(filename), '/proc/%d/maps', pid); } // 打開(kāi)文件/proc/pid/maps,獲取指定pid進(jìn)程加載的內(nèi)存模塊信息 fp = fopen(filename, 'r'); if(fp != NULL){// 每次一行,讀取文件 /proc/pid/maps中內(nèi)容while(fgets(line, sizeof(line), fp)){ // 查找指定的so模塊 if(strstr(line, module_name)){// 分割字符串pch = strtok(line, '-');// 字符串轉(zhuǎn)長(zhǎng)整形address = strtoul(pch, NULL, 16); }break; }} } fclose(fp); return (void*)address;}

//hook fopen進(jìn)行實(shí)現(xiàn)//(libxxxx.so文件是ELF32文件)#define LIBPATH '/data/app-lib/com.xxxx/libxxxx.so'int hookFopen(){ // 獲取目標(biāo)pid中'/data/app-lib/com.xxxx/libxxxx.so'模塊的加載地址 void* base_addr = getModuleBase(getpid(), LIBPATH ); // 保存Hook目標(biāo)函數(shù)的原始調(diào)用地址 old_fopen = fopen; int fd; // 用open打開(kāi)內(nèi)存模塊文件'/data/app-lib/com.xxxx/libxxxx.so' fd = open(LIB_PATH, O_RDONLY); if(-1 == fd){return -1; } // elf32文件的文件頭結(jié)構(gòu)體Elf32_Ehdr Elf32_Ehdr ehdr; // 讀取elf32格式的文件'/data/app-lib/com.xxxx/libxxxx.so'的文件頭信息 read(fd, &ehdr, sizeof(Elf32_Ehdr)); // elf32文件中節(jié)區(qū)表信息結(jié)構(gòu)的文件偏移 unsigned long shdr_addr = ehdr.e_shoff; // elf32文件中節(jié)區(qū)表信息結(jié)構(gòu)的數(shù)量 int shnum = ehdr.e_shnum; // elf32文件中每個(gè)節(jié)區(qū)表信息結(jié)構(gòu)中的單個(gè)信息結(jié)構(gòu)的大小(描述每個(gè)節(jié)區(qū)的信息的結(jié)構(gòu)體的大小) int shent_size = ehdr.e_shentsize; // elf32文件節(jié)區(qū)表中每個(gè)節(jié)區(qū)的名稱存放的節(jié)區(qū)名稱字符串表,在節(jié)區(qū)表中的序號(hào)index unsigned long stridx = ehdr.e_shstrndx; Elf32_Shdr shdr; lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET); // 讀取elf32文件中的描述每個(gè)節(jié)區(qū)的信息的結(jié)構(gòu)體(這里是保存elf32文件的每個(gè)節(jié)區(qū)的名稱字符串的) read(fd, &shdr, shent_size); // 為保存elf32文件的所有的節(jié)區(qū)的名稱字符串申請(qǐng)內(nèi)存空間 char * string_table = (char *)malloc(shdr.sh_size); // 定位到具體存放elf32文件的所有的節(jié)區(qū)的名稱字符串的文件偏移處 lseek(fd, shdr.sh_offset, SEEK_SET); read(fd, string_table, shdr.sh_size); lseek(fd, shdr_addr, SEEK_SET); int i; uint32_t out_addr = 0; uint32_t out_size = 0; uint32_t got_item = 0; int32_t got_found = 0; // 循環(huán)遍歷elf32文件的節(jié)區(qū)表(描述每個(gè)節(jié)區(qū)的信息的結(jié)構(gòu)體) for(i = 0; i<shnum; i++){// 依次讀取節(jié)區(qū)表中每個(gè)描述節(jié)區(qū)的信息的結(jié)構(gòu)體read(fd, &shdr, shent_size);// 判斷當(dāng)前節(jié)區(qū)描述結(jié)構(gòu)體描述的節(jié)區(qū)是否是SHT_PROGBITS類型//類型為SHT_PROGBITS的.got節(jié)區(qū)包含全局偏移表if(shdr.sh_type == SHT_PROGBITS){ // 獲取節(jié)區(qū)的名稱字符串在保存所有節(jié)區(qū)的名稱字符串段.shstrtab中的序號(hào) int name_idx = shdr.sh_name; // 判斷節(jié)區(qū)的名稱是否為'.got.plt'或者'.got' if(strcmp(&(string_table[name_idx]), '.got.plt') == 0|| strcmp(&(string_table[name_idx]), '.got') == 0){// 獲取節(jié)區(qū)'.got'或者'.got.plt'在內(nèi)存中實(shí)際數(shù)據(jù)存放地址out_addr = base_addr + shdr.sh_addr;// 獲取節(jié)區(qū)'.got'或者'.got.plt'的大小out_size = shdr.sh_size;int j = 0;// 遍歷節(jié)區(qū)'.got'或者'.got.plt'獲取保存的全局的函數(shù)調(diào)用地址for(j = 0; j<out_size; j += 4){ // 獲取節(jié)區(qū)'.got'或者'.got.plt'中的單個(gè)函數(shù)的調(diào)用地址 got_item = *(uint32_t*)(out_addr + j); // 判斷節(jié)區(qū)'.got'或者'.got.plt'中函數(shù)調(diào)用地址是否是將要被Hook的目標(biāo)函數(shù)地址 if(got_item == old_fopen){got_found = 1;// 獲取當(dāng)前內(nèi)存分頁(yè)的大小uint32_t page_size = getpagesize();// 獲取內(nèi)存分頁(yè)的起始地址(需要內(nèi)存對(duì)齊)uint32_t entry_page_start = (out_addr + j) & (~(page_size - 1)); // 修改內(nèi)存屬性為可讀可寫可執(zhí)行if(mprotect((uint32_t*)entry_page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC) == -1){ return -1;} // Hook的函數(shù),是我們自己定義的函數(shù)got_item = new_fopen; // 進(jìn)行恢復(fù)內(nèi)存屬性為可讀可執(zhí)行if(mprotect((uint32_t*)entry_page_start, page_size, PROT_READ | PROT_EXEC) == -1){ return -1;}break; // 目標(biāo)函數(shù)的調(diào)用地址已經(jīng)被Hook了 }else if(got_item == new_fopen){break; }}// 對(duì)目標(biāo)函數(shù)HOOk成功,跳出循環(huán)if(got_found) break; }} } free(string_table); close(fd);}

到此這篇關(guān)于android的got表HOOK實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)android HOOK實(shí)現(xiàn)got表內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 国内外成人免费视频 | 天天射天天操天天干 | 国产精品久久久久久久久借妻 | 日韩午夜精品 | 日韩在线一区二区 | 亚洲成人精品一区 | 日韩一区三区 | 国产三级免费观看 | 欧美成人极品 | 亚洲免费精品视频 | 黄色一级大片在线免费看国产一 | 国产农村妇女aaaaa视频 | 日韩精品免费视频 | 中文字幕播放 | 成年人小视频 | 国产日韩精品视频 | 午夜视频一区 | 一道本在线观看 | 九色自拍| 久久久高清| 不卡在线视频 | 成人在线免费看 | 日韩欧美国产精品 | 人人澡人人干 | 福利网站在线观看 | 国产91丝袜在线播放 | 日韩伦理在线观看 | 男男巨肉啪啪动漫3d | 五月婷婷婷 | 午夜精品视频 | 日韩高清一区 | 色77777 | 久久国产综合 | 人人综合网 | 亚洲精品自拍视频 | 五月天一区二区三区 | 一区二区三区四区视频在线观看 | 男女操操操 | 日韩欧美网站 | 欧美xxxx性 | 日韩av在线一区二区 |