文章目錄
- 一、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);
}
}