Ring3 下 API Inline Hook 优化方案探索与实现

本博文由CSDN博主zuishikonghuan所作,版权归zuishikonghuan所有,转载请注明出处:http://blog.csdn.net/zuishikonghuan/article/details/51302024

以前写过两篇“[Win32] API Hook(1)在32/64位系统上的实现”博客,介绍并给出了 API inline hook 代码,如下:
blog.csdn.net/zuishikonghuan/article/details/47976067
blog.csdn.net/zuishikonghuan/article/details/47979603
在这两篇博文中,我简要说了API inline hook的缺陷:

API inline hook的方法是修改API函数的前几个字节,让这几个字节执行无条件跳转指令,跳转到我们自己的函数里,这时候我们就可以根据参数进行一些判断,如果我们愿意放行,还可以恢复函数的前几字节并重新调用原函数,不愿意放行,就直接返回错误,Ring3级的进程保护就是这样实现的。
API inline hook在16位的系统上确实可以非常正常的工作,因为16位系统是单任务的!而如果是在32位的多任务抢占式操作系统上,系统可能会随时切换线程上下文,如果我们刚把函数前几个字节恢复了,系统突然把线程切换到了另一个线程,而那个线程又无巧不成书的调用了我们hook的这个函数,那么后果就是,出现了漏网之鱼!
而IAThook可以克服这个问题,但是IAThook的缺陷更是灾难性的!因为IAThook是通过修改导入地址表实现的,如果动态调用API,IAThook根本无法拦截。

当时我说这是一个小瑕疵,是的,在一些老系统(例如XP)上的确可以算是比较好的工作,但是现在看来,这个问题已经非常严重了,在Win8、8.1、10系统上,如果在explorer里Hook,会造成explorer特别容易崩溃!!(特别是 Hook NT Native API)

我希望找到新的解决方案,IAT HOOK 首先被否决了,因为 IAT HOOK 拦截不住 API 动态调用,在 Ring 0 中 Hook 更是行不通,因为在 amd64 平台上是有驱动程序强制签名的,买签名是很贵的,而且还不能干坏事。

那么我们就要认命吗?

于是我试图从 Inline Hook 的实现方法上找原因,这是我写的 Inline Hook 代码(x86 和 amd 64)

没错,原理就是修改要 Hook 函数的前几个字节,问题关键就在于,如何能避免还原时恢复函数的这几个字节呢?

        //进行 Inline Hook
        HMODULE hdll = LoadLibrary(TEXT("kernel32.dll"));
        addr = GetProcAddress(hdll, "OpenProcess");
        if (addr){
#ifdef _M_IX86
            code[0] = 0xe9;
            aint a = (aint)MyOpenProcess - (aint)addr - 5;
            RtlMoveMemory(code + 1, &a, 4);

            DWORD old;
            if (VirtualProtectEx(GetCurrentProcess(), addr, 5, PAGE_EXECUTE_READWRITE, &old)){
                RtlMoveMemory(oldcode, addr, 5);
                WriteProcessMemory(GetCurrentProcess(), addr, code, 5, NULL);
                VirtualProtectEx(GetCurrentProcess(), addr, 5, old, &old);
            }
#elif _M_X64
            code[0] = 0x48;
            code[1] = 0xB8;
            code[10] = 0x50;
            code[11] = 0xC3;
            aint a = (aint)MyOpenProcess;
            RtlMoveMemory(code + 2, &a, 8);

            DWORD old;
            if (VirtualProtectEx(GetCurrentProcess(), addr, 12, PAGE_EXECUTE_READWRITE, &old)){
                RtlMoveMemory(oldcode, addr, 12);
                WriteProcessMemory(GetCurrentProcess(), addr, code, 12, NULL);
                VirtualProtectEx(GetCurrentProcess(), addr, 12, old, &old);
            }
#endif
        }
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值