最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2021年08月14日 15:40:16   作者:小道安全  
對于android的so文件的hook根據(jù)ELF文件特性分為:Got表hook、Sym表hook和inline hook等。今天通過本文給大家介紹android HOOK實(shí)現(xiàn)got表的實(shí)例代碼,需要的朋友參考下吧

概述

對于android的so文件的hook根據(jù)ELF文件特性分為:Got表hook、Sym表hook和inline hook等。
全局符號表(GOT表)hook,它是通過解析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);
    }

    // 打開文件/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)長整形
                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打開內(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ū)表中的序號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ū)的名稱字符串申請內(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中的序號
            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)存分頁的大小
                        uint32_t page_size = getpagesize();
                        // 獲取內(nèi)存分頁的起始地址(需要內(nèi)存對齊)
                        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;
                    }
                }
                // 對目標(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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android自定義View實(shí)現(xiàn)繪制虛線的方法詳解

    Android自定義View實(shí)現(xiàn)繪制虛線的方法詳解

    這篇文章主要給大家介紹了Android自定義View實(shí)現(xiàn)繪制虛線的方法,在繪制過程中走了一些彎路才實(shí)現(xiàn)了虛線的效果,所以想著總結(jié)分享出來,方便有需要的朋友和自己在需要的時(shí)候參考學(xué)習(xí),下面來一起看看吧。
    2017-04-04
  • android handler.post和handler.sendMessage的區(qū)別和聯(lián)系

    android handler.post和handler.sendMessage的區(qū)別和聯(lián)系

    handler.post和handler.sendMessage本質(zhì)上是沒有區(qū)別的,都是發(fā)送一個(gè)消息到消息隊(duì)列中,而且消息隊(duì)列和handler都是依賴于同一個(gè)線程的。接下來通過本文給大家分享android handler.post和handler.sendMessage的區(qū)別和聯(lián)系,一起看看吧
    2017-08-08
  • android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法

    android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法

    這篇文章主要介紹了android studio使用SQLiteOpenHelper()建立數(shù)據(jù)庫的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • flutter 輸入框組件TextField的實(shí)現(xiàn)代碼

    flutter 輸入框組件TextField的實(shí)現(xiàn)代碼

    這篇文章主要介紹了flutter 輸入框組件TextField的實(shí)現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Android開發(fā)之splash界面下詳解及實(shí)例

    Android開發(fā)之splash界面下詳解及實(shí)例

    這篇文章主要介紹了 Android開發(fā)之splash界面下詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程分析

    Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程分析

    這篇文章主要介紹了Android6.0開發(fā)中屏幕旋轉(zhuǎn)原理與流程,結(jié)合實(shí)例形式詳細(xì)分析了Android6.0屏幕旋轉(zhuǎn)的原理與相關(guān)實(shí)現(xiàn)流程,并附帶了Android動態(tài)開啟與禁用屏幕旋轉(zhuǎn)的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2017-11-11
  • Android中的popupwindow進(jìn)入和退出的動畫效果

    Android中的popupwindow進(jìn)入和退出的動畫效果

    這篇文章主要介紹了Android中的popupwindow進(jìn)入和退出的動畫,需要的朋友可以參考下
    2017-04-04
  • 詳解Flutter中StatefulBuilder組件的使用

    詳解Flutter中StatefulBuilder組件的使用

    StatefulBuilder小部件可以在這些區(qū)域的狀態(tài)發(fā)生變化時(shí)僅重建某些小區(qū)域而無需付出太多努力。本文將來詳細(xì)講講它的使用,需要的可以參考一下
    2022-05-05
  • Android Studio中的Gradle依賴深入講解

    Android Studio中的Gradle依賴深入講解

    Android Studio由于使用了gradle的進(jìn)行項(xiàng)目構(gòu)建,使我們開發(fā)app方便很多,下面這篇文章主要給大家介紹了關(guān)于Android Studio中Gradle依賴的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2018-09-09
  • android播放視頻時(shí)在立體聲與單聲道之間切換無變化原因分析及解決

    android播放視頻時(shí)在立體聲與單聲道之間切換無變化原因分析及解決

    使用第三方視頻播放器,有立體聲與單聲道之間切換,發(fā)現(xiàn)切換后無作用,原因是由于在HAL層默認(rèn)沒有處理上層發(fā)的stereo 轉(zhuǎn)mono的命令,具體的解決方法如下
    2013-06-06

最新評論

扎兰屯市| 沐川县| 宜昌市| 八宿县| 突泉县| 手机| 专栏| 类乌齐县| 微博| 芦山县| 汉寿县| 明光市| 崇阳县| 黑河市| 聂拉木县| 朝阳县| 铜梁县| 西华县| 鹤庆县| 武义县| 瑞丽市| 高唐县| 偃师市| 德江县| 浦城县| 廉江市| 盘山县| 尉氏县| 靖安县| 江永县| 凌海市| 疏附县| 兰坪| 开原市| 吴桥县| 凤凰县| 万全县| 外汇| 临邑县| 三亚市| 定安县|