iqiyi / xHook

🔥 A PLT hook library for Android native ELF.
Other
4.05k stars 752 forks source link

想问个项目中的代码问题 #100

Closed TUGOhost closed 1 year ago

TUGOhost commented 1 year ago

最近在借鉴xHook的代码来做got/plt hook的检测功能,但是对其中的一些代码一知半解,所以提个issue,希望有人能给个解答

代码行数: https://github.com/iqiyi/xHook/blob/master/libxhook/jni/xh_elf.c#L388

static int xh_elf_gnu_hash_lookup_def(xh_elf_t *self, const char *symbol, uint32_t *symidx)
{
    uint32_t hash = xh_elf_gnu_hash((uint8_t *)symbol);

    static uint32_t elfclass_bits = sizeof(ElfW(Addr)) * 8;
    size_t word = self->bloom[(hash / elfclass_bits) % self->bloom_sz];
    size_t mask = 0
        | (size_t)1 << (hash % elfclass_bits)
        | (size_t)1 << ((hash >> self->bloom_shift) % elfclass_bits);

    //if at least one bit is not set, this symbol is surely missing
    if((word & mask) != mask) return XH_ERRNO_NOTFND;

    //ignore STN_UNDEF
    uint32_t i = self->bucket[hash % self->bucket_cnt];
    if(i < self->symoffset) return XH_ERRNO_NOTFND;

    //loop through the chain
    while(1)
    {
        const char     *symname = self->strtab + self->symtab[i].st_name;
        const uint32_t  symhash = self->chain[i - self->symoffset];

        if((hash | (uint32_t)1) == (symhash | (uint32_t)1) && 0 == strcmp(symbol, symname))
        {
            *symidx = i;
            XH_LOG_INFO("found %s at symidx: %u (GNU_HASH DEF)\n", symbol, *symidx);
            return 0;
        }

        //chain ends with an element with the lowest bit set to 1
        if(symhash & (uint32_t)1) break;

        i++;
    }

    return XH_ERRNO_NOTFND;
}

不是很理解 if((word & mask) != mask) return XH_ERRNO_NOTFND;这行代码判断的依据是什么,因为在android 10上跑,debug发现会过不去这个判断,导致后面的步骤也不会进行


补下debug时的值

图片

word=13276616116733657225 mask=36028797555834880


还需要说明的是,就是测试的项目结构了

图片

其中hookee.c和hacker.c 分别来自于https://github.com/bytedance/bhook/blob/main/bytehook_sample/src/main/cpp/hookee.c 、 https://github.com/bytedance/bhook/blob/main/bytehook_sample/src/main/cpp/hookee.c

cmake也是参考https://github.com/bytedance/bhook/blob/main/bytehook_sample/src/main/cpp/CMakeLists.txt

会编译出三个so文件: 一个带有xhook代码的xhookdemo.so、一个got/plt hook攻击的hacker.so,一个被攻击的hookee.so,

在native-lib.c中调用xhook部分接口:

xh_core_register(".*/libhookee\.so$", "open");

我去掉了xhook的new_func和old_func参数,但这并不影响整体的运行,无非就是没办法实现原本xhook的hook,但是依旧会产生上面的问题,困惑这点,是不是因为这样测试导致的。

最终我要得到的是open函数的跳转地址,但是不管是是否被hook,该跳转地址获取的值都不会改变,即便我clear清除缓存。

TUGOhost commented 1 year ago

解决了,来总结下


问题的结论是,xhook并没有像bhook那样“智能”,open函数实际跳转的sym是__open_2,但是xhook是写死这个来做过滤的,导致没有找到symidx。

但是bhook就没有这样的问题,不过说不好,我写的攻击demo里也把__open_2也hook了。

还有就是为啥地址都一样,因为我去掉了symidx的获取,所以那个地址是got表的起始地址。