如何hook dlopen和dlsym底层函数

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);
}

效果图

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值