接下来如果你还继续保持对该api的拦截,则又该用WriteProcessMemory 来修改入口了,跟前面的恢复入口是一样的,只不过把szOldCode换成了szNewCode了而已。这样你又能对CreateFile继续拦截了。
好了,接下来该进行堆栈的清理了,也许你还要做点其他事情,尽管做去。但是清理堆栈是必须要做的,在函数结束的时候,因为在我们放任api恢复执行之后,他又return 到我们的函数中来了,这个时候的堆栈是什么样子呢?
|EDI| <---ESP
|ESI|
|EBX|
|局部变量|
|EBP| <---EBP
|api入口之后的第11个字节的指令的地址|
|00010000|
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|
我们的目标是把返回值记录下来放到EAX寄存器中去,把返回地址记录下来,同时把堆栈恢复成原来的样子。
首先我们恢复那些寄存器的值,接着释放局部变量,可以用mov esp, ebp.因为我们不清楚具体的局部变量分配了多少空间。所以使用这个方法。
__asm
{POP EDI
POP ESI
POP EBX //恢复那些寄存器
MOV EDX, [NextIpAddr]//把返回地址放到EDX中,因为待会儿 //EBX被恢复后,线程中的所有局部变量就不能正常使用了。
MOV EAX, [Retvalue]//返回值放到EAX中,当然也可以修改这个返回值
MOV ESP, EBP//清理局部变量
POP EBP//恢复EBP的值
ADD ESP, 28H //清理参数和返回地址,注意一共(7+1+1+1)*4
PUSH EDX //把返回地址压栈,这样栈中就只有这一个返回地址了,返回之后栈 //就空了
RET
}
这样,一切就完成了,堆栈恢复了应该有的