我假设读者已经非常熟悉detours,阅读此文只是为了增强对detours的理解以及为了实现x64 hook。有关detours原理部分不再多讲。

X86 Kernel Hook
早些年,我把detours1.5移植到x86核心层,工作的不错,我一直用它来hook系统一些内部函数,有时候也用来hook IoCreateFile这类导出函数。让detours1.5在核心工作稳定并不是一件困难的事情。可能有些c/c++的麻烦,但是很快就可以解决。唯一需要注意的地方是detours1.5用VirtualProtect来让内存READ_WRITE_EXECUTE,在核心层有2种方法,第一种是群众所喜闻乐见的清除cr0,第二种是在核心层通过调用native api做VirtualProtect的事情。
detours的方法对比import/export方法有一些很明显的好处,其最大的好处是可以用来hook内部函数。而且由于hook的方法是直接修改函数体,所以不管调用者怎么玩花样,都很难绕过hook。
detours的缺点主要如下:
1,detours x86无法hook小于5字节的函数
2,detours x86需要一个完备的反汇编器和解释器,实际上detours代码中并不包含这个,因此,如果需要写一个函数阻止他人hook,可以这么写:
  proc near
      xor eax,eax
      jeax 1
      int 3
      ... // do something
    proc end
注意到这里的这个jmp,因为eax肯定为0,所以该int3不会被调用,而被detours过的代码则很可能走到int3上去了,为了让detours的代码不走到int3,detours必须能够解析出前面3行代码的意思,并且修正jeax 1为jeax 1+(trampoline-function)。用类似的技术,也可以欺骗detours。
3,detours x86无法处理如下函数:
  proc near
flag: ... // 函数前5个字节
    .... //do something
    jmp flag
    .... // do something
    proc end
该函数执行体中有一个jmp,跳到前5个字节。可是被detours过之后,该函数的前5个字节被修改了,而且改成了jmp trampoline。为了能够让detours可以处理此操作,必须反汇编解析整个函数体,用2种所描述的方法修改jmp flag。

综上述,detours思路很好,但是存在缺陷,要搞定这些缺陷,需要完整反汇编器。

X64 Kernel Hook
最近有一个需求要在x64下实现类似的hook模块,我找到了detours2.1,给MS发了email,MS的答复是,包含64bit的detours2.1,需要10000 USD。
于是我就删掉了MS的email,开始自己动手来做这个事情了。我大致说一下原理和需要注意的地方。

x64 hook和x86 hook的原理相似,都是修改原函数的首地址。不同的是,x64下不存在
jmp 64_address这种指令,x86下要跨4G跳转,必须是jmp [64_address],对应的汇编码不再是e9 xxxxxxxx,而是ff15 [xxxxxxxx],其中xxxxxxxx保存的是一个64_address。注意xxxxxxxx依然是32位,所以,该内存也必须和function处于同一个4G。

这个限制对于普通的代码编译来说,并不存在太大的问题,因为很少有exe超过4G的。所以编译器生成的代码依然使用e9 xxxxxxxx。对于import的dll来说,通常都是call [xxxxxxxx],以前是这样,现在还是这样,不同的是,[xxxxxxxx]以前指向32位的地址,现在指向64位的地址。这样一来,dll加载的位置和exe所在的位置不在同一个4G也没有关系了。

对于detours来说,受上面所述特性影响的是,trampoline通常位于heap memory/nonpaged pool,new_function位于我们自己所写代码的dll/driver中,old_function位于我们所需要hook的那个模块中。这里面存在一个基本矛盾是,new_function通常和old_function分别处于2个不同dll或者.sys中,系统很可能把他们加载到了距离很远的空间中,也即abs(new_function-old_function)>4G。这样一来,就无法使用e9 xxxxxxxx,而必须使用ff15 [xxxxxxxx]了,而且xxxxxxxx是一个32的偏移,所以[xxxxxxxx]还不能位于我们的dll/sys中。

根据以上的分析,最后可以得出如下算法:
1,找到需要hook的函数地址
2,解析从函数起始地址开始,至少6+8=14个字节的代码。代码不能断开。以上2个过程和detourx86一样,不同的是,detoursx86之需要e9 xxxxxxxx,也就是说只需要5个字节,而我们必须用ff15 [xxxxxxxx]。如果函数体小于14个字节,这意味着该函书无法detours。
不过函数体小于14字节多半是因为里面执行了一个call或者jmp,那么解析该代码,把函数起始地址设置为jmp之后的地址,重新进行2过程。
3,把这14或者15,16...个字节拷贝到预先分配的一块内存中,我们叫它trampoline。
4,把前6个字节改为ff15 [0],也即ff15 00000000
5,在随后的8个字节中保存new_function的起始地址
6,修正trampoline中的14字节的代码,如果里面有jmp,call等跳转语句,修改偏移量,这时候通常又需要跨4G的跳转,那么按照上面的方法修改之,trampoline的字节数可能会增加。
7,在trampoline的代码之后,插入ff15 [0],并且在随后的8个字节中填充old_function+14。

trampoline可以预先分配一个100字节的buffer,初始化全部填充为nop,在进行7的时候,可以从trampoline的底部,也即100-14的位置开始填入ff,15,00,00,00,00, 64_bit_old_function+14(15,16...)。

以上算法的缺点和x86 detours的缺点一样,第一条为无法hook函数体小于14字节的函数。

14个字节相当大,有时候这个缺陷不可忍受,为此,介绍一种更为肮脏的手段。

代码加载到内存中时,通常有很多废空间,也即,在这些空间中,只有nop,或者永远不会执行。用IDA可以找到这些空间。如果能够找到足够大到,以至于可以保存一个64位地址的空间的话,那么可以只修改前5个字节为jmp [xxxxxxxx],同时只拷贝5个字节到trampoline。trampoline的底部14个字节照旧。

以上就是x64下的detours过程。

有一个x64下需要注意的问题,vc8不支持x64下的_asm关键字,所以
_asm{
cli
mov eax,cr0
and eax,not 1000h
mov cr0,eax }不能再用
取而代之的是
_disable();
uint64 cr0=__readcr0();
cr0 &= 0xfffffffffffeffff;
__writecr0(cr0);
当然还可以继续用native api,不过以上方法简洁而且为广大群众所喜闻乐见。有关于_disable等函数,请查阅新版msdn。

至于IA64,我对此一无所知。

顺便说几点:
1,EM64T的cpu上可以run win64os,但是,不知为何,vmware无法在EM64T的cpu上install/run win64os。而amd64 cpu上即便安装的是win32 os,也可以在其上的vmware里install/run win64os。
2,softice已经停止开发,而且不支持x64,只有virtual模式才支持。鉴于其已经停止开发,建议大家都使用windbg。
3,idapro 5.0反汇编x64的代码,错误百出,一团乱麻,基本上需要先U再C。

因为14字节的限制太大,以至于始终觉得不爽。后来想到了一个解决方案。

假设原函数是old_func,新函数是new_func,那么分配trampoline的时候,用某些技术方法,限定分配出的内存和old_func在同一个4G。可以通过VirtualAlloc实现,具体方法可以是多次改变第一个参数,调用VirtualAlloc,直到返回值不为NULL为止。

这样一来,detours的逻辑改变为:

1,首先把old_func的前5个字节拷贝到trampoline+14,然后修改为jmp offset,也即e9 trampoline-5-old
2,trampoline的前6字节为ff15 [0],接下来的8个字节为new_func_address
3,trampoline+14+5之后的5个字节为jmp (trampoline+14+5+5 - (old_func_addr+5))

这样调用old的时候,会首先执行jmp offset到trampoline,trampoline又jmp到了new_func,new_func调用old的时候,会直接跳到trampoline+14处,执行原来的前5个字节,然后再jmp会原函数体。

如此,一切都完美了 :)

64位系统的Detours相关推荐

  1. vc++64位系统下long的长度为4个字节_64位系统究竟牛逼在哪里?

    想必大家都遇到过这样的问题:安装某个软件的时候,出现提示选择32位版本还是64位版本?我们也可以查看自己的电脑是32位还是64位系统. Windows Linux 大家可能知道32位和64位和系统有关 ...

  2. 树莓派64位系统_树莓派4b+Ubuntu server+Nextcloud搭建私人云盘(1):准备系统

    最近剁手买了一个4G版本的树莓派4b,并配了64g tf卡.我打算用它来搭建一个自己的私人服务器. 需求:树莓派4b+一部本地电脑+网线+路由器+一部有公网ip的云主机 首先,我们先到官方下载Ubun ...

  3. oracle c 64位系统时间戳,64位系统时间的AOI 架构(64Bit Interpreted AOI)

    原标题:64位系统时间的AOI 架构(64Bit Interpreted AOI) 本文档目的: 有些客户需要在人机界面上显示SOE的时间戳,但是不利用报警事件里的控件来显示,有时候用的HMI还不是F ...

  4. 明明是 64 位系统,为什么python sys.platform 显示 win 32 ?

    明明是 64 位系统,为什么 sys.platform 显示 win 32 ? 在python中: >>>import sys >>>print(sys.platf ...

  5. 【转】将 Linux 应用程序移植到 64 位系统上

    原文网址:http://www.ibm.com/developerworks/cn/linux/l-port64.html 随着 64 位体系结构的普及,针对 64 位系统准备好您的 Linux® 软 ...

  6. 把ePO4.5或者4.6从32位迁移到64位系统

    环境总结: 客户现在的环境是ePO4.5安装在32位的WS2003R2上,想实现的效果是迁移到ePO4.6并且运行在WS2008R2上(只有64位系统). 使用声明: 1.期望目标读者是网络管理员和e ...

  7. 关于Windows 7的64位系统不兼容某些控件的问题

    我的问题是vsflex7.ocx 不能在64位系统下运行,导致软件的一个涉及到这个控件的功能出错. 如下: 解决的办法基本思路是把这个控件注册一下.然后就可以了. 就是这个控件: 目录中没有自己下载个 ...

  8. 32位系统 和 64位系统 C 程序中 为什么 指针的内存大小的不一样

    以下均为自己猜想: 32位系统是因为有32根地址总线 ,64位系统由64根地址总线 所以从根本上有了32位和64位的系统的根本区别 指针就是地址,所不管什么类型的指针在32位的系统上,就是一个32位的 ...

  9. 64位php oracle,64位系统无法加载PHP的oracle扩展问题

    最开始以为64位系统,用64位的客户端,就是那个instantclient 可是安好以后加载不了,换成32位的就行了,估计是因为我的apache是32位的,它就只能加载32位扩展吧. 附带oracle ...

最新文章

  1. (传送门)Ubuntu 常用软件安装
  2. 扇区、磁盘块、页、页框、缓冲区之间的关系!
  3. Android 文本实现跑马灯效果 用自带的TextView控件
  4. 凄怆与悲凉(灾区现场最新照片)
  5. Android中如何下载文件并显示下载进度
  6. 批量替换 MySQL 指定字段中的字符串
  7. android layout(l, t, r, b);,服务器里的a,t,l,r,b是什么意思? Android编程中关于layout(l,t,r,b)函数的问题...
  8. html5视频播放器隐藏控制,HTML5 video标签(播放器)学习笔记(二):播放控制
  9. Oracle(二)单行函数
  10. java利用数组随机抽取幸运观众_java利用数组随机抽取幸运观众
  11. Django中的ORM进阶操作
  12. Centos 6.5 Tengine 安装流程
  13. Apache Oozie Installation
  14. mysql中的rman备份与恢复_RMAN备份与恢复总汇
  15. 小行星项目第2部分测试驱动开发
  16. ps怎么缩放图层大小_Photoshop如何调整图层大小?PS调整图层大小快捷键
  17. 办公:office办公软件Excel表格的打印技巧
  18. 阿里云 禁用密码登录
  19. 年前辞职,年后找工作
  20. (转)一共81个,开源大数据处理工具汇总

热门文章

  1. android手机邮件6,Android手机邮箱设置详细教程
  2. Unsupervised Domain Adaption of Object Detectors : A Survey
  3. ElasticSearch(7.2.2)-搜索的简单使⽤
  4. 背景与字体的搭配经验
  5. html怎样添加excel表格,html 使用 excel表格数据类型-如何给html页面添加excel表格
  6. 渠道分析 之 渠道分析的价值 -3
  7. 多项式插值中的一些定理证明
  8. 新人如何利用今日头条自媒体平台赚钱?月收入轻松过万
  9. 【产业互联网周报】2019年我国软件业务收入71768亿元,同比增15.4%;亚马逊、谷歌先后发布财报,披露云计算业务增长...
  10. 代理平台kb-proxy:注册与登录【三】