一種inlineHook檢測方案

定義

inlinehook是修改內存中的機器碼來實現hook的方式

我們用frida查看一個函數hook之前和hook之後的機器碼,這裏以open函數爲例:

let bytes_count = 32
let address = Module.getExportByName("libc.so","open")

let before = ptr(address)
console.log("")
console.log("[*] before hook: ")
console.log(hexdump(before, {
    offset: 0,
    length: bytes_count,
    header: true,
    ansi: true
  }));

let isOutput = false

Interceptor.attach(address, {
	onEnter:function(args){
        if(isOutput) return;
		let after = ptr(address)
        console.log("")
		console.log("[*] after hook: ")
        console.log(hexdump(after, {
            offset: 0,
            length: bytes_count,
            header: true,
            ansi: true
        }))
        isOutput = true
	},
	onLeave:function(retv){
	}
});

hook之前:

hook之後:

可見,hook之後,函數開頭的字節被修改了

思考

inlinehook只修改了內存中的機器碼,而內存中的機器碼是從文件加載而來的,所以我們可以將函數在內存中字節和本地對應的字節進行比較,如果不一致,那麼可以認爲內存中的字節被修改了,即被inlinehook了。

實現

#ifdef __LP64__
    const char *lib_path = "/system/lib64/libc.so";
#else
    const char *lib_path = "/system/lib/libc.so";
#endif
#define CMP_COUNT 8
    const char *sym_name = "open";

    struct local_dlfcn_handle *handle = static_cast<local_dlfcn_handle *>(local_dlopen(lib_path));

    off_t offset = local_dlsym(handle,sym_name);

    FILE *fp = fopen(lib_path,"rb");
    char file_bytes[CMP_COUNT] = {0};
    if(fp != NULL){
        fseek(fp,offset,SEEK_SET);
        fread(file_bytes,1,CMP_COUNT,fp);
        fclose(fp);
    }

    void *dl_handle = dlopen(lib_path,RTLD_NOW);
    void *sym = dlsym(dl_handle,sym_name);

    int is_hook = memcmp(file_bytes,sym,CMP_COUNT) != 0;

    local_dlclose(handle);
    dlclose(dl_handle);

    char text[128] = {0};
    snprintf(text,128,"Function \"%s\" is Hook: %s",sym_name,is_hook ? "true" : "false");

這裏local_開頭的函數是讀取本地符號偏移庫,庫代碼:https://github.com/luoyesiqiu/local_dlfcn

用frida hook測試demo:frida-trace -U -i "open" -f com.luoye.localdlfcn

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章