菜鸟笔记
提升您的技术认知

如何hook dlopen和dlsym底层函数-ag真人游戏

android 逆向分析过程有时候需要hook dlopen和dlsym函数,打印调用的库或者函数名。
利用cydia substrate的动态库,或者thomasking大大的elf-arm-hook-library 两个都行,但是cydia 支持x86的hook,模拟器hook 比较方便(个人见解)。
我用的是cydia 实现的hook。具体如下,

//substrate.cpp
void *(*msfindsymbol)(msimageref image, const char *name);
msimageref(*msgetimagebyname)(const char *file);
void(*msjavahookmethod)(jnienv *jni, jclass _class, jmethodid methodid, void *function, void **result);
void(*mshookfunction)(void *symbol, void *replace, void **result);
void(*msjavahookclassload)(jnienv *jni, const char *name, void(*callback)(jnienv *, jclass, void *), void *data);
__attribute__((__constructor__)) static void _msinitialize()
{
    void* handlesubdsub = dlopen("/system/lib/libsubstrate.so", rtld_now);
    void* handlesubdvm = dlopen("/system/lib/libsubstrate-dvm.so", rtld_now);
    if (handlesubdsub != null)
    {
        logd("***start dlsym methond***");
        msgetimagebyname = (msimageref(*)(const char *file))dlsym(handlesubdsub, "msgetimagebyname");
        msfindsymbol = (void*(*)(msimageref image, const char *name))dlsym(handlesubdsub, "msfindsymbol");
        mshookfunction = (void(*)(void *symbol, void *replace, void **result))dlsym(handlesubdsub, "mshookfunction");
        msjavahookclassload = (void(*)(jnienv *jni, const char *name, void(*callback)(jnienv *, jclass, void *), void *data))dlsym(handlesubdvm, "msjavahookclassload");
        msjavahookmethod = (void(*)(jnienv *jni, jclass _class, jmethodid methodid, void *function, void **result)) dlsym(handlesubdvm, "msjavahookmethod");
        logd("***end dlsym methond***");
    }
    else
    {
        loge("***open so file fail or can't find file!***");
    }
}

以上代码:可以不用安装cydia的apk,把libsubstrate.so、 libsubstrate-dvm.so 两个动态库复制到 /system/lib/目录下。 直接调用 相关函数,elf-arm-hook-library 也有同样的方法自己实现。
hook dlopen 函数 就要获取 函数的地址:

    //这个方法来自 android inject 用于获取地址
    void* get_module_base(int pid, const char* module_name)
{
    file *fp;
    long addr = 0;
    char *pch;
    char filename[32];
    char line[1024];
    if (pid < 0) {
        /* self process */
        snprintf(filename, sizeof(filename), "/proc/self/maps", pid);
    }
    else {
        snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
    }
    fp = fopen(filename, "r");
    if (fp != null) {
        while (fgets(line, sizeof(line), fp)) {
            if (strstr(line, module_name)) {
                pch = strtok(line, "-");
                addr = strtoul(pch, null, 16);
                if (addr == 0x8000)
                    addr = 0;
                break;
            }
        }
        fclose(fp);
    }
    return (void *)addr;
}
//这个方法来自 android inject 用于获取地址
void* get_remote_addr(int target_pid, const char* module_name, void* local_addr)
{
    void* local_handle, *remote_handle;
    local_handle = get_module_base(-1, module_name);
    remote_handle = get_module_base(target_pid, module_name);
    logi("[ ] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle);
    void * ret_addr = (void *)((uint32_t)local_addr   (uint32_t)remote_handle - (uint32_t)local_handle);
#if defined(__i386__)    
    if (!strcmp(module_name, "/system/lib/libc.so")) {
        ret_addr  = 2;
    }
#endif    
    return ret_addr;
}

hook方法

    //声明各个变量存放地址
    void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr;
    //获取dlopen地址
    dlopen_addr = get_remote_addr(getpid(), "/system/bin/linker", (void *)dlopen);
    logi("[ ] dlopen_addr: [%x]", dlopen_addr);
    //hook dlopen方法  下面方法类似
    mshookfunction((void*)dlopen_addr, (void*)newdlopen, (void**)&olddlopen);
    dlsym_addr = get_remote_addr(getpid(), "/system/bin/linker", (void *)dlsym);
    logi("[ ] dlsym_addr: [%x]", dlsym_addr);
    mshookfunction(dlsym_addr, (void*)newdlsym, (void**)&olddlsym);
    dlclose_addr = get_remote_addr(getpid(), "/system/bin/linker", (void *)dlclose);
    dlerror_addr = get_remote_addr(getpid(), "/system/bin/linker", (void *)dlerror);
//hook方法
void* (*olddlsym)(void*  handle, const char*  symbol);
void* newdlsym(void*  handle, const char*  symbol) {
    logd("the handle [0x%x] symbol name:%s",handle,symbol);
    return olddlsym(handle, symbol);
}
void* (*olddlopen)(const char* filename, int myflags);
void* newdlopen(const char* filename, int myflags) {
    logd("the dlopen name :%s",filename);
    return olddlopen(filename, myflags);
}
网站地图