刚在看一个拥有传值的API时(什么是传值?就是API参数有__out属性的),想到这么一个猥琐的方法,也真的实现了,觉得蛮新奇蛮好玩的,分享给大家,代码如下:
代码:
.386 .model flat, stdcall option casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定义 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib .data fmt db "%s",0 msgtxt db "我怎么被执行了?",0 .code New_OEP: invoke MessageBox,0,addr msgtxt,0,0 invoke ExitProcess,0 start proc local @temp mov @temp,New_OEP lea ecx,[esp-3*4-4] invoke wsprintf,ecx,addr fmt,addr @temp start endp end start
PS(以下内容均为之后添加):中间有个小错误,就是mov @temp,New_OEP 新地址被存放里,因为数值是倒过来存放的,所以例子中的00401000在内存中是00 10 40 00 存放的,首字节变成了0,wsprintf 只会覆盖一个0到返回地址,正确的方式应该是在"New_OEP:"前面加上一句nop,使最地位地址不为0!
注意,请不要把这个代码当成是溢出利用,完全是两回事!!
C++版:
代码:
#include <Windows.h> __declspec(naked) void test() { MessageBoxA(0,"为什么我被执行了?",0,0); } int main() { LPSTR outb; DWORD addr = (DWORD)(LPDWORD)test; __asm{ lea ecx,[esp-3*4-4] mov outb,ecx } wsprintfA(outb,"%s",&addr); return 0; }
代码:
#include <Windows.h> __declspec(naked) void test() { MessageBoxA(0,"为什么我被执行了?",0,0); } int main() { LPSTR retaddr; DWORD addr = (DWORD)(LPDWORD)test; __asm{ lea ecx,[esp-4*4-4] mov retaddr,ecx } strncpy_s(retaddr,4,(char *)&addr,4);//这个不会溢出了吧~ return 0; }