天天看點

【Android 逆向】ART 函數抽取加殼 ⑤ ( unistd.h#execve 函數分析 | 使用自定義的 myexecve 函數替換 libc.so#execve 函數 )

文章目錄

  • ​​一、bionic/libc/include/unistd.h#execve 函數分析​​
  • ​​二、使用自定義的 myexecve 函數替換 libc.so#execve 函數​​

  • ​​【Android 逆向】ART 函數抽取加殼 ① ( ART 下的函數抽取恢複時機 | 禁用 dex2oat 機制源碼分析 )​​
  • ​​【Android 逆向】ART 函數抽取加殼 ② ( 禁用 dex2oat 簡介 | TurboDex 中禁用 dex2oat 參考示例 )​​

兩篇部落格中 , 簡單介紹了 禁用 dex2oat 機制 的原理 , 下面開始 實作 dex2oat 禁用功能 ;

在 ​​【Android 逆向】ART 函數抽取加殼 ③ ( 禁用 dex2oat 操作 HOOK 點介紹 | 內建 InLineHook )​​ 部落格中 , 介紹了 HOOK 點 , 以及 內建 HOOK C 代碼的庫 InLineHook ;

在 ​​【Android 逆向】ART 函數抽取加殼 ④ ( 對 libc.so#execve 函數進行内聯 HOOK 操作 )​​ 部落格中 , 對 libc.so#execve 函數 進行了 内聯 HOOK 操作

本篇部落格實作 自定義的 myexecve 函數 替換 libc.so#execve 函數 ;

一、bionic/libc/include/unistd.h#execve 函數分析

libc.so#execve 函數 定義在 Android 源碼的 " bionic/libc/include/unistd.h "

int execv(const char* __path, char* const* __argv);
int execvp(const char* __file, char* const* __argv);
int execvpe(const char* __file, char* const* __argv, char* const* __envp) __INTRODUCED_IN(21);
// ★ 此處為 execve 函數原型
int execve(const char* __file, char* const* __argv, char* const* __envp);      

源碼位址 : ​​http://androidxref.com/8.0.0_r4/xref/bionic/libc/include/unistd.h​​

" int execve(const char* __file, char* const* __argv, char* const* __envp); " 函數解析 :

  • const char* __file 參數 : 表示要運作的 二進制程式檔案路徑 , 這裡指的是 Dex 位元組碼檔案路徑 , 如果要攔截 指定路徑中的位元組碼檔案不進行 OAT 優化

二、使用自定義的 myexecve 函數替換 libc.so#execve 函數

在 部落格中 , 介紹了調用 " hook\include\inlineHook.h " 中定義的 " registerInlineHook " 函數注冊被 Hook 的函數 , 其原型如下 :

enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr);      

​uint32_t target_addr​

​​ 參數是 execve 函數在 libc.so 的位址 , ​

​uint32_t new_addr​

​​ 參數是自定義替換 execve 函數執行的函數位址 , ​

​uint32_t **proto_addr​

​ 參數是 execve 原函數的位址 ;

首先 , 定義一個函數指針變量 , 接收

" int execve(const char* __file, char* const* __argv, char* const* __envp); " 函數

的位址 , 之後如果需要真實調用時需要用到 ;

const char* __file, char* const* __argv, char* const* __envp);

定義指針 , 指向一個函數 , 函數的參數是 ​

​const char* __file, char* const* __argv, char* const* __envp​

​​ , 傳回值是 ​

​int​

​ 類型 ;

該函數指針在進行 " hook\include\inlineHook.h " 中定義的 " registerInlineHook " 函數時 被指派 ;

複雜函數指針參考部落格 ​​【C 語言】指針 與 數組 ( 指針 | 數組 | 指針運算 | 數組通路方式 | 字元串 | 指針數組 | 數組指針 | 多元數組 | 多元指針 | 數組參數 | 函數指針 | 複雜指針解讀) 六. 函數指針 3. 解讀 複雜的 指針聲明 ( 難點 重點 | ①找出中心辨別符 ②先右 後左 看 确定類型 提取 ③ 繼續分析 左右看 … )​​ 進行分析 ;

複雜指針閱讀技巧 ( 主要是 區分 函數指針 和 數組指針 ) 右左法則 :

  • 1.最裡層标示符 : 先找到最裡層的圓括号中的标示符;
數組指針和函數指針的标示符 ( 指針變量名 ) 都在中間的圓括号中, 是以該步驟先找到指針變量名
  • 2.右左看 : 先往右看, 再往左看 ;
  • 3.确定類型 : 遇到 圓括号 “()” 或者 方括号 “[]” 确定部分類型, 調轉方向 ; 遇到 * 說明是指針 , 每次确定完一個類型 , 将該類型提取出來 , 分析剩下的 ;

一種可能性 :

int (*) [5] , 遇到中括号說明是數組指針類型,

int(*)(int, int) , 遇到圓括号 說明是函數指針類型 ;

  • 4.重複 2 , 3 步驟 : 一直重複, 直到 指針 閱讀結束 ;

然後 , 定義 自定義的 execve 函數 , 用于 替換 Android 自帶的 execve 函數

  • 這裡将需要攔截的位元組碼都放在 dex2oat 目錄中 , 檢測到 dex2oat 目錄 , 就退出 ;
  • 不需要攔截的 , 直接調用原函數執行 ;
// 用于接收 Android 自帶的 execve 函數
int (*android_execve)(const char *__file, char *const *__argv, char *const *__envp);

// 自定義的 execve 函數 , 用于替換 Android 自帶的 execve 函數
// 主要用于攔截 dex2oat 位元組碼檔案
int myexecve(const char *__file, char *const *__argv, char *const *__envp) {
    // 這裡将需要攔截的位元組碼都放在 dex2oat 目錄中
    if (strstr(__file, "dex2oat")) {
        return 0;
    } else {
        // 不需要攔截的 , 直接調用原函數執行 
        return android_execve(__file, __argv, __envp);
    }
}      
上一篇: 春天