程序从入口点 401280 开始执行代码
[esp 28ff8c ebp 28ff94]
push ebp [esp=28ff88 ebp=28ff94 在栈中保存了调用子程序前的栈基址 28ff94]
mov ebp,esp [把现在的栈顶 28ff88 设置为新的栈基址,方便通过ebp来调用变量参数,并且可以通过 mov esp,ebp 平衡栈.]
sub esp,8 [栈指针向上(较低的地址)移动8字节的内容空间]
mov dword ptr ss:[esp],1 [向上一步的空间写入8字节长度的数字1]
call dword ptr ds:[&msvcrt.__set_app_type] [获得数据段地址的值,并call到这个地址(子函数)call = push eip jmp]
Kernel32.BaseThreadInitThunk
mov edi,edi [没有什么意义,可以用来 inline hook,以及作为热补丁用的,配合上面的5个nop]
push ebp
mov ebp,esp [保存调用函数之前的栈基址,设置本函数的栈基址 esp-4]
push dword ptr ss:[ebp+8] [call push用了4字节, push ebp用了4字节,所以要到call前压栈的参数的话,需要加8字节,将得到的参数1压栈]
call msvcrt.75f31585 [应该是调到msvcrt中的一个函数]
msvcrt.75f31585
mov edi,edi [不用说了吧]
push ebp
mov ebp,esp [这两句就算是标准代码了,设置当前栈基址]
push 0 [入参]
call dword ptr ds:[<&API-MS-Win-Core-L...>] [从数据段获取call地址 KernelBa.GetModuleHandleW(获取模块句柄)]
mov edi,edi
push ebp
mov ebp,esp
cmp dword ptr ss:[ebp+8],0 [参数为0,0表示获取的是当前模块]
jnz short KernelBa.75b710ad [判断参数是否为0,如果不是0就短跳到执行 75b70e41 函数,这里的参数为0,所以不用跳]
mov eax,dword ptr fs:[18] [得到的是线程的关键信息 7efdd000]
mov eax,dword ptr ds:[eax+30] [得到 7efdd030 地址的值 00 e0 fd 7e(7efde000)]
mov eax,dword ptr ds:[eax+8] [得到 7efde008 的值 00 00 04 00(400000) 程序的入口点]
jmp short KernelBa.75b710c4 [无条件短跳]
[这里] pop ebp [恢复函数开始时的ebp]
retn 4 [先 pop ip返回到了call dword ptr ds:[<&API-MS-Win-Core-L...>] 的下一行,然后 sp 加对应的值,因为之前 push 了一个参数(pop=esp+4),所以这里 sp 要加 4,使之栈平衡]
test eax,eax [and , 不覆盖 eax, 影响]
je msvcrt.75f41dd1 [判断返回结果是否为零,如果为零跳到这里,表示没有获取到模块]
push eax [将结果压栈 400000]
call msvcrt.75f315ca [执行子函数,参数400000]
msvcrt.75f315ca
push c [第2个参数压栈]
push msvcrt.75f31628 [第1个参数,好像是call之前的模块基址?]
call msvcrt.75f29836 [执行子函数]
msvcrt.75f29836
push msvcrt.75f48cd5 [?]
push dword ptr fs:[0] [指向当前线程的结构化异常处理结构(SEH) 28ffc4(ds: ff ff ff ff)]
mov eax,dword ptr ss:[esp+10] [栈指针移动10字节后的地址的值存入 eax(c)]
mov dword prt ss:[esp+10],ebp [将ebp覆盖第2个参数c (28ff6c)]
lea ebp,dword ptr ss:[esp+10] [将存有ebp内容的地址保存到ebp]
sub esp,eax [段指针减少12字节]
push ebx [第4个参数 7efde000 压栈]
push esi [第3个参数 0 压栈]
push edi [第2个参数 0 压栈]
mov eax,dword ptr ds:[75fc060c] [第1个参数应该是调用系统函数,地址是 af9a2329]
xor dword ptr ss:[ebp-4],eax [75f31628 xor af9a2329 (ebp-4=da693501)]
xor eax,ebp [af9a2329 xor 0028ff60 (eax=afb2dc49)]
push eax [压栈]
mov dword ptr ss:[ebp-18],esp [将栈顶指针保存到这里(24字节)]
push dword ptr ss:[ebp-8] [返回地址 75f315d6 压栈]
mov eax,dword ptr ss:[ebp-4] [da693501 -> eax,就是第1个xor算出来的值]
mov dword ptr ss:[ebp-4],-2 [将-2(fffffffe)放到这里]
mov dword ptr ss:[ebp-8],eax [将 75f315d6 变成 da693501 ,因为这个地方的值已经重新入栈]
lea eax,dword ptr ss:[ebp-10] [得到栈地址 28ff50,下面就是 75f48cd5 ,子函数刚开始时压栈的值]
mov dword prt fs:[0],eax [当前线程的结构化异常处理结构(SEH) 28ffc4 变为 28ff50 在地址 7fedd000]
retn [pop 75f315d6 ip 返回]
xor eax,eax [清零]
mov ecx,dword ptr ss:[ebp+8] [400000 -> ecx]
test ecx,ecx [判断是否为0]
je short msvcrt.75f31619 [为0就跳]
cmp ecx,-1 [判断是否是-1]
je short msvcrt.75f31619 [为-1还是跳]
and dword ptr ss:[ebp-4],eax [fffffffe and 0 结果为 0]
mov edx,5a4d [DOS头]
cmp word ptr ds:[ecx],dx [判断文件开头是否是 4d5a ,PE文件判断]
jnz short msvcrt.75f31612 [如果不为零则跳转异常处理,这里是正常]
mov edx,dword ptr ds:[ecx+3c] [80 -> edx PE文件相对文件的偏移]
test edx,edx [判断是否是0]
jl short msvcrt.75f31612 [这里表示如果结果是负数就跳异常处理]
cmp edx,10000000 [80-10000000]
jnb short msvcrt.75f31612 [这里表示如果结果不小于就跳异常处理]
lea eax,dword ptr ds:[ecx+edx] [获得PE头所在地址 400080 -> eax]
mov dword ptr ss:[ebp-1c],eax [将400080放到栈中]
cmp dword ptr ds:[eax],4550 [判断是否是字符串 PE]
jnz msvcrt.75f68095 [如果不是PE则跳转处理]
mov dword ptr ss:[ebp-4],-2 [应该是参数?(fffffffe)]
call msvcrt.75f2987b [子函数跳转]
msvcrt.75f2987b
mov ecx,dword ptr ss:[ebp-10] [第4个参数 异常处理结构地址的指针]
mov dword ptr fs:[0],ecx [不能直接段寄存器传值,所以使用ecx]
pop ecx [异常处理结构地址的指针]
pop edi [第4个参数出栈]
pop edi [第3个参数出栈 0]
pop esi [第2个参数出栈 0]
pop ebx [第1个参数出栈 7efde000]
mov esp,ebp [将栈偏移设置为 KernelBa.GetModuleHandleW(获取模块句柄) 时候的栈顶,为返回做准备]
pop ebp [恢复 ebp]
push ecx [将结果压栈 75f3161e,因为之前出栈了]
retn [然后跳到这个地址,这个地址就是 call msvcrt.75f2987b 下一行代码的地址]
retn 4 [返回到msvcrt.75f315ca]
test eax,eax [判断返回值是否是0 PE文件判断函数的返回值]
je msvcrt.75f41dd1 [如果是0则调到这里,提示非PE文件,应该吧]
movzx eax,word ptr ds:[eax+5c] [40013c的值 0300 扩展为 00000003 并赋值给 eax (3 console)]
cmp ax,2 [3-2=1]
je msvcrt.75f300f1 [如果是 winGUI系统,则跳]
cmp ax,3 [是否是命令行程序]
jnz msvcrt.75f41dd1 [如果也不是命令行系统,则跳]
xor eax,eax [清零]
inc eax [eax+1]
pop ebp [回复栈基址]
retn [返回到 msvcrt.75f31585]
pop ecx [ecx=1]
mov dword ptr ds:[75fc0030],eax [1赋值到数据段]
pop ebp [28ff88 程序 1280 push ebp 后 mov ebp,esp 后的值]
retn [返回程序空间,执行第6行代码]
call 401150 [程序内调用子函数]
401150
push ebp
mov ebp,esp
push ebx [7efde000 线程关键信息]
sub esp,24 [36字节空间]
mov dword ptr ss:[esp],未命名1.00401000 [在栈顶放入401000]
call [设置异常捕获函数 4018e4]
004018e4
jmp dword ptr ds:[&KERNEL32.SetUnhandledExceptionFilter] [跳转到这个函数的实现过程]
KERNEL32.SetUnhandledExceptionFilter
mov edi,edi
push ebp
mov ebp,esp [设置新的栈顶,函数进入子函数时push ebp后的 esp]
sub esp,220 [为什么移动这么大的距离?]
push ebx [7efde000 线程关键信息]
push esi [0]
mov esi,dword ptr ss:[ebp+8] [401000 程序入口点]
test esi,esi [esi 是否是0 程序入口地址]
je Kernel32.75d089be [如果是0,则跳到异常处理?]
lea eax,dword ptr ss:[ebp-220] [获得移动前的栈偏移地址 28fd28]
push eax [压栈 28fd28 栈顶]
push esi [压栈 程序入口]
call Kernel32.75d0888e [子程序处理]
mov edi,edi
push ebp
mov ebp,esp [设置新的栈顶]
sub esp,2c [移动2c距离]
push esi [401000压栈]
push edi [0压栈]
push 1c [1c(28)压栈]
lea eax,dword ptr ss:[ebp-2c] [开始的esp偏移,用于接收VirtualQueryEx函数返回的信息,虽然返回的机构大小是1c]
push eax [28fce4栈偏移]
push dword ptr ss:[ebp+8] [ebp+ 获得参数1(401000)到局部变量]
call 75D0444F= [查询地址空间中内存地址的信息]
查询地址空间中内存地址的信息 kernel32的导入函数
jmp dword ptr ds:[&API-MS-Win-Core-Memory-L1-1-0.VirtualQuery] [KernelBa.VirtualQuery]
mov edi,edi
push ebp
mov ebp,esp [设置新的栈顶]
push dword ptr ss:[ebp+10] [1c MEMORY_BASIC_INFORMATION结构的大小]
push dword ptr ss:[ebp+c] [28fce4栈偏移 指向MEMORY_BASIC_INFORMATION结构的指针]
push dword ptr ss:[ebp+8] [401000 查询内存的地址]
push -1 [参数1为-1,共4个参数 进程句柄]
call KernelBa.VirtualQueryEx [查询地址空间中内存地址的信息]
KernelBa.VirtualQueryEx
mov edi,edi
push ebp
mov ebp,esp
lea eax,dword ptr ss:[ebp+14] [获得第4个参数的地址 28fcc4 给 eax 保存有结构的大小]
push eax [地址压栈 存储该函数处理 返回 的信息的长度的ULONG的地址]
push dword ptr ss:[ebp+14] [值压栈,局部变量 结构体大小 Buffer的最大长度]
push dword ptr ss:[ebp+10] [用于存储获取到的内存信息的结构地址]
push 0 [查询内存信息的类别]
push dword ptr ss:[ebp+c] [查询内存的地址 401000]
push dword ptr ss:[ebp+8] [进程句柄 -1]
call dword ptr ds:[<&ntdll.NtQueryVirtualMemory>] [查询指定进程的某个虚拟地址控件所在的内存对象的一些信息]
ntdll.NtQueryVirtualMemory
mov eax,20
xor ecx,ecx [清零]
lea edx,dword ptr ss:[esp+4] [获得返回地址]
call dword ptr fs:[c0] [线程 的 TEB结构 WOW32Reserved 7efdd0c0 -> 741f2320]
jmp far 0033:741f271e [长跳转,不理解]
77ae01c4 RtlUserThreadStart
mov dwrod ptr ss:[esp+4],eax [将程序入口地址 401280 写入]
...没了,程序显示了 helloworld ,处于等待哦 getchar() 但是我在程序输入任意字符后就跳到
77aefcb2 了,然后就显示已终止 OD显示 ERR0R_FILE_NOT_FOUND LASTERR 2
调用链:
1280->
128d call -> 75f32804
75f3280c call -> msvcrt.75f31585
75f3158c call -> KernelBa.GetModuleHandleW
75f31592 -> msvcrt.75f315ca
75f315d2 call -> msvcrt.75f29836
75f31619 call -> msvcrt.75f2987b
retn ->msvct.75f3161e
75F315C4 -> 75F32811
1293 call -> 1150
18e4 jmp -> KERNEL32.SetUnhandledExceptionFilter
75d087e9 call -> Kernel32.75d0888e
call 75D0444F -> KernelBa.VirtualQuery
call KernelBa.VirtualQueryEx
call ntdll.NtQueryVirtualMemory
call -> ntdll.741f2320