天天看點

【Android 逆向】ART 函數抽取加殼 ④ ( 對 libc.so#execve 函數進行内聯 HOOK 操作 )

文章目錄

  • ​​一、對 libc.so#execve 函數進行内聯 HOOK 操作​​

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

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

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

一、對 libc.so#execve 函數進行内聯 HOOK 操作

要 HOOK libc 函數庫 中的 exec_utils.cc#execve 函數 , 首先要查找到 libc 庫的基位址 , 然後查找 exec_utils.cc#execve 函數的位址 ;

execve 函數 定義在 bionic/libc/include/unistd.h 中 , 在 exec_utils.cc 中進行調用 ;

使用 在 ​​【Android 逆向】ART 函數抽取加殼 ③ ( 禁用 dex2oat 操作 HOOK 點介紹 | 內建 InLineHook )​​ 部落格中繼承的 InLineHook 函數庫 實作上述 native 中的 HOOK 操作 ;

首先 , 調用 hook\dlfcn\dlfcn_compat.h 中的 dlopen_compat 函數 , 傳入 libc 庫的檔案名即 " libc.so " 作為第一個參數 , 傳入 RTLD_NOW 作為第二個參數作為标志位 , 該函數的原型如下 :

void *dlopen_compat(const char *filename, int flags);      
該操作也可以使用 dlopen 函數 , 這裡對該函數進行封裝 , 是因為在 Android 7.0 之後 , 這些函數都受 命名空間限制

然後 , 調用 hook\dlfcn\dlfcn_compat.h 中的 dlsym_compat 函數 查找 exec_utils.cc#execve 函數 在 " libc.so " 函數庫 中的位址 , 第一個參數是 " libc.so " 函數庫的基位址 , 第二個參數是函數名稱即 " execve " , 該函數的原型如下 :

void *dlsym_compat(void *handle, const char *symbol);      
該操作也可以使用 dlsym 函數 , 這裡對該函數進行封裝 , 是因為在 Android 7.0 之後 , 這些函數都受 命名空間 限制 , 對于某些函數庫可能執行失敗 ;

再後 , 注冊内聯 HOOK 操作 , 調用 " hook\include\inlineHook.h " 中定義的 " registerInlineHook " 函數

  • uint32_t target_addr 參數 : execve 函數在 " libc.so " 函數庫中的位址 ;
  • uint32_t new_addr 參數 : HOOK 後要替換的函數位址 , 使用自定義的函數替代原函數執行 ;
  • uint32_t **proto_addr 參數 : 儲存原函數位址 , 用于在新函數中調用原函數 , 實作代理模式 ;
enum ele7en_status registerInlineHook(uint32_t target_addr, uint32_t new_addr, uint32_t **proto_addr);      

最後 , 執行内聯 HOOK 操作 , 注冊完畢後 , 調用 " hook\include\inlineHook.h " 中定義的 " inlineUnHook " 函數 , 傳入被 HOOK 的函數位址 , 也就是 exec_utils.cc#execve 函數在 " libc.so " 函數庫中的位址 ;

enum ele7en_status inlineUnHook(uint32_t target_addr);      

執行成功 , 該函數傳回 0 , 失敗傳回其它值 ;

// 導入 inLineHook 頭檔案
extern "C" {
    #include "hook/dlfcn/dlfcn_compat.h"
    #include "hook/include/inlineHook.h"
}

// 注冊執行 Hook 操作
void hookLibc() {
    // 查找 libc.so 函數庫的基位址
    void *libc_addr = dlopen_compat("libc.so", RTLD_NOW);
    // 查找 execve 在 libc.so 函數庫的偏移位址 
    void *execve_addr = dlsym_compat(libc_addr, "execve");
    
    // 位址不為空才能向後執行
    if (execve_addr != NULL) {
        // 注冊内聯 Hook 函數 , 傳入參數 
        // ① execve 在 libc.so 函數庫的偏移位址 , 
        // ② 自己實作的 myexecve 函數 
        // ③ Android 自帶的原始的 execve 函數位址
        // 傳回 0 即注冊成功 
        if (ELE7EN_OK == registerInlineHook((uint32_t) execve_addr, (uint32_t) myexecve,
                                            (uint32_t **) &android_execve)) {
            // 正式執行 Hook 操作 
            if (ELE7EN_OK == inlineHook((uint32_t) execve_addr)) {
                LOGD("Hook Success");
            } else {
                LOGD("Hook Fail");
            }
        }
    }
}