.386
.Model Flat, StdCall
Option Casemap :None
Include windows.inc
Include user32.inc
Include kernel32.inc
IncludeLib user32.lib
IncludeLib kernel32.lib
.DATA
szDllKernel db 'user32.dll',0
szMessageBox db 'MessageBoxA',0
.DATA?
lpMessageBox dd ?
.CODE
START:
invoke GetModuleHandle,addr szDllKernel
mov ebx,eax
invoke GetProcAddress,ebx,offset szMessageBox
mov lpMessageBox,eax
push MB_OK
push 0
push 0
push 0
mov EAX,offset _END
push EAX
jmp lpMessageBox
_END:
invoke ExitProcess,0
END START
看出点什么了吗?我把CALL变成了PUSH和JMP两个指令
了解调用过程的人都知道CALL指令就是先把下一条指令地址压栈然后在用JMP跳转到函数入口处,那我们的解决办法就出来了,我们可以自己完成这个调用动作,先把下一条指令压栈
.CODE
START:
invoke GetModuleHandle,addr szDllKernel
mov ebx,eax
invoke GetProcAddress,ebx,offset szMessageBox
mov lpMessageBox,eax
push MB_OK
push 0
push 0
push 0
mov EAX,offset _END
push EAX
;添加的代码开始
mov edi,edi
push ebp
mov ebp,esp
add lpMessageBox,5
;添加的代码结束
jmp lpMessageBox
_END:
invoke ExitProcess,0
END START
把目标API的前几行代码在自己程序里实现,然后在跳转到API函数中去继续运行。比如我是把MessageBox的前3行代码在自己的程序里实现,然后在条到MessageBox的第4行里继续运行。
这样跳转到目标入口地址就不是API函数的入口了