对程序调用API变形的一点认识

.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函数的入口了

发布了11 篇原创文章 · 获赞 3 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章