进程内的API hooking一般有两种:patch Import Table,将主程序的输入函数的入口地址改成你自己的,几年前的病毒和木马爱用,相对简单一些;一种就是detours和不少木马的direct function entry point patching,通过查找对应DLL的输出函数表得到API的起始点,然后简单地反汇编和判断一下,一般保留开始的5个byte(也可能更多),然后从起始点改成JUMP(E9 xxxx xxxx)到你的函数点去执行。所以如果原来的API还不到5个字节,你是没法改它的,否则你如何JUMP?
Direct function entry point patching(detours只是里面的一种)有它的先天缺陷,不能patch一些和同步有关的API,比如WaitForSingleObject(Ex) / WaitForMultipleObjects(Ex),否则会死锁。不信?你试试。原因?不知道。
iterasm MACRO n
lea edx, [eax+(1 SHL n)]
lea ebx, [eax+(2 SHL n)]
shl edx, n
mov esi, ecx
sub ecx, edx
cmovnc eax, ebx
cmovc ecx, esi
ENDM
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 4
;============================
isqrt proc arg:DWORD
mov ecx, [esp+4] ; arg
push ebx ; save as per calling convention
push esi ; save as per calling convention
xor eax, eax ; 2*root
; iteration 15
mov ebx, 2 SHL 15
mov esi, ecx
sub ecx, 1 SHL 30
cmovnc eax, ebx
cmovc ecx, esi
iterasm 14
iterasm 13
iterasm 12
iterasm 11
iterasm 10
iterasm 9
iterasm 8
iterasm 7
iterasm 6
iterasm 5
iterasm 4
iterasm 3
iterasm 2
iterasm 1
; iteration 0
mov edx, 1
mov ebx, 2
add edx, eax
add ebx, eax
sub ecx, edx
cmovnc eax, ebx
shr eax, 1
mov esi, [esp] ; restore as per calling convention
mov ebx, [esp+4] ; restore as per calling convention
add esp, 8 ; remove temp variables
ret 4 ; pop one DWORD arg and return
isqrt endp
;======================================
我看到的就是一个JUMP,干嘛要填这些指令?不明白你的问题。
再追,你会看到上述指令。至于为什么,这是align产生的效果,我猜东西放整齐、规则,总是好取好放。
至于为什么这样替换,这是老外的回答:
"Interesting that they chose an instruction like "mov edi, edi" instead of just
two NOPs. Then again, you need a two-byte instruction to make sure no thread is
about to execute NOP#2 when the jump-destination is written."
我没搞懂。
最初由 sixL 发布 "Interesting that they chose an instruction like "mov edi, edi" instead of just two NOPs. Then again, you need a two-byte instruction to make sure no thread is about to execute NOP#2 when the jump-destination is written." 我没搞懂。