这两者是不一致的,hot-patching 是有条件的,而 Detours 的条件更加宽松。 hot-patching 要求函数的开始有足够的空间执行 跳转指令,而 Detours 则要求整个函数的大小,至少能够装下跳转指令。 如果 可以 hot-patching ,那就可以不用 Detours ,因为 Detours 需要保存开始的被覆盖的指令。至少需要创建代码段,Detours 需要解析开始代码,知道第一个跳转指令大小之外的第一个代码的开始,一边保存被覆盖的代码和跳转回来的位置。相对于比较复杂。 所以,如果你确认你的代码都是可以 hot-patching 的,那么就不需要 Detours 。 但是 hot-patching 是有条件的,需要开始有空白的代码,一边写入跳转指令。 所以 微软在她们的 API 之前,添加一个著名的指令 mov edi,edi 。这条指令没有任何意义,但是可以被 短跳转指令覆盖,她们都是两个字节的指令。这样函数就可以被旁路了。 如果你需要长跳转,那么先来短跳转,跳转到这个指令的上面的 5 字节去。而这个 5 个字节正好可以在进行一次长跳转。 这就是为什么在 mov edi,edi 之前可以看到 5 个 nop 指令。 这就是为什么函数开始是 mov edi,edi 和她上面有 5 个 nop 指令了,这就是为 hot-patching 准备的。当你使用 VC 编译的时候,在代码生成的属性里,使用创建可热修补映像的时候,就可以满足 hot-patching 的要求了。 至于为什么使用 mov edi,edi 而不适用两个 nop,传说是因为 mov 效率比较高的原因。而 mov 指令上面的 5 个字节是 nop ,是因为这 5 个 nop 指令从不指令, API 函数都是从 mov edi,edi 开始执行的。 |
|