程序從入口點 401280 開始執(zhí)行代碼
[esp 28ff8c ebp 28ff94]
push ebp [esp=28ff88 ebp=28ff94 在棧中保存了調(diào)用子程序前的?;?28ff94]
mov ebp,esp [把現(xiàn)在的棧頂 28ff88 設(shè)置為新的棧基址,方便通過ebp來調(diào)用變量參數(shù),并且可以通過 mov esp,ebp 平衡棧.]
sub esp,8 [棧指針向上(較低的地址)移動8字節(jié)的內(nèi)容空間]
mov dword ptr ss:[esp],1 [向上一步的空間寫入8字節(jié)長度的數(shù)字1]
call dword ptr ds:[&msvcrt.__set_app_type] [獲得數(shù)據(jù)段地址的值,并call到這個地址(子函數(shù))call = push eip jmp]
Kernel32.BaseThreadInitThunk
mov edi,edi [沒有什么意義,可以用來 inline hook,以及作為熱補(bǔ)丁用的,配合上面的5個nop]
push ebp
mov ebp,esp [保存調(diào)用函數(shù)之前的?;?設(shè)置本函數(shù)的棧基址 esp-4]
push dword ptr ss:[ebp+8] [call push用了4字節(jié), push ebp用了4字節(jié),所以要到call前壓棧的參數(shù)的話,需要加8字節(jié),將得到的參數(shù)1壓棧]
call msvcrt.75f31585 [應(yīng)該是調(diào)到msvcrt中的一個函數(shù)]
msvcrt.75f31585
mov edi,edi [不用說了吧]
push ebp
mov ebp,esp [這兩句就算是標(biāo)準(zhǔn)代碼了,設(shè)置當(dāng)前棧基址]
push 0 [入?yún)
call dword ptr ds:[<&API-MS-Win-Core-L...>] [從數(shù)據(jù)段獲取call地址 KernelBa.GetModuleHandleW(獲取模塊句柄)]
mov edi,edi
push ebp
mov ebp,esp
cmp dword ptr ss:[ebp+8],0 [參數(shù)為0,0表示獲取的是當(dāng)前模塊]
jnz short KernelBa.75b710ad [判斷參數(shù)是否為0,如果不是0就短跳到執(zhí)行 75b70e41 函數(shù),這里的參數(shù)為0,所以不用跳]
mov eax,dword ptr fs:[18] [得到的是線程的關(guān)鍵信息 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 [恢復(fù)函數(shù)開始時的ebp]
retn 4 [先 pop ip返回到了call dword ptr ds:[<&API-MS-Win-Core-L...>] 的下一行,然后 sp 加對應(yīng)的值,因為之前 push 了一個參數(shù)(pop=esp+4),所以這里 sp 要加 4,使之棧平衡]
test eax,eax [and , 不覆蓋 eax, 影響]
je msvcrt.75f41dd1 [判斷返回結(jié)果是否為零,如果為零跳到這里,表示沒有獲取到模塊]
push eax [將結(jié)果壓棧 400000]
call msvcrt.75f315ca [執(zhí)行子函數(shù),參數(shù)400000]
msvcrt.75f315ca
push c [第2個參數(shù)壓棧]
push msvcrt.75f31628 [第1個參數(shù),好像是call之前的模塊基址?]
call msvcrt.75f29836 [執(zhí)行子函數(shù)]
msvcrt.75f29836
push msvcrt.75f48cd5 [?]
push dword ptr fs:[0] [指向當(dāng)前線程的結(jié)構(gòu)化異常處理結(jié)構(gòu)(SEH) 28ffc4(ds: ff ff ff ff)]
mov eax,dword ptr ss:[esp+10] [棧指針移動10字節(jié)后的地址的值存入 eax(c)]
mov dword prt ss:[esp+10],ebp [將ebp覆蓋第2個參數(shù)c (28ff6c)]
lea ebp,dword ptr ss:[esp+10] [將存有ebp內(nèi)容的地址保存到ebp]
sub esp,eax [段指針減少12字節(jié)]
push ebx [第4個參數(shù) 7efde000 壓棧]
push esi [第3個參數(shù) 0 壓棧]
push edi [第2個參數(shù) 0 壓棧]
mov eax,dword ptr ds:[75fc060c] [第1個參數(shù)應(yīng)該是調(diào)用系統(tǒng)函數(shù),地址是 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字節(jié))]
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 ,因為這個地方的值已經(jīng)重新入棧]
lea eax,dword ptr ss:[ebp-10] [得到棧地址 28ff50,下面就是 75f48cd5 ,子函數(shù)剛開始時壓棧的值]
mov dword prt fs:[0],eax [當(dāng)前線程的結(jié)構(gòu)化異常處理結(jié)構(gòu)(SEH) 28ffc4 變?yōu)?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 結(jié)果為 0]
mov edx,5a4d [DOS頭]
cmp word ptr ds:[ecx],dx [判斷文件開頭是否是 4d5a ,PE文件判斷]
jnz short msvcrt.75f31612 [如果不為零則跳轉(zhuǎn)異常處理,這里是正常]
mov edx,dword ptr ds:[ecx+3c] [80 -> edx PE文件相對文件的偏移]
test edx,edx [判斷是否是0]
jl short msvcrt.75f31612 [這里表示如果結(jié)果是負(fù)數(shù)就跳異常處理]
cmp edx,10000000 [80-10000000]
jnb short msvcrt.75f31612 [這里表示如果結(jié)果不小于就跳異常處理]
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則跳轉(zhuǎn)處理]
mov dword ptr ss:[ebp-4],-2 [應(yīng)該是參數(shù)?(fffffffe)]
call msvcrt.75f2987b [子函數(shù)跳轉(zhuǎn)]
msvcrt.75f2987b
mov ecx,dword ptr ss:[ebp-10] [第4個參數(shù) 異常處理結(jié)構(gòu)地址的指針]
mov dword ptr fs:[0],ecx [不能直接段寄存器傳值,所以使用ecx]
pop ecx [異常處理結(jié)構(gòu)地址的指針]
pop edi [第4個參數(shù)出棧]
pop edi [第3個參數(shù)出棧 0]
pop esi [第2個參數(shù)出棧 0]
pop ebx [第1個參數(shù)出棧 7efde000]
mov esp,ebp [將棧偏移設(shè)置為 KernelBa.GetModuleHandleW(獲取模塊句柄) 時候的棧頂,為返回做準(zhǔn)備]
pop ebp [恢復(fù) ebp]
push ecx [將結(jié)果壓棧 75f3161e,因為之前出棧了]
retn [然后跳到這個地址,這個地址就是 call msvcrt.75f2987b 下一行代碼的地址]
retn 4 [返回到msvcrt.75f315ca]
test eax,eax [判斷返回值是否是0 PE文件判斷函數(shù)的返回值]
je msvcrt.75f41dd1 [如果是0則調(diào)到這里,提示非PE文件,應(yīng)該吧]
movzx eax,word ptr ds:[eax+5c] [40013c的值 0300 擴(kuò)展為 00000003 并賦值給 eax (3 console)]
cmp ax,2 [3-2=1]
je msvcrt.75f300f1 [如果是 winGUI系統(tǒng),則跳]
cmp ax,3 [是否是命令行程序]
jnz msvcrt.75f41dd1 [如果也不是命令行系統(tǒng),則跳]
xor eax,eax [清零]
inc eax [eax+1]
pop ebp [回復(fù)?;穄
retn [返回到 msvcrt.75f31585]
pop ecx [ecx=1]
mov dword ptr ds:[75fc0030],eax [1賦值到數(shù)據(jù)段]
pop ebp [28ff88 程序 1280 push ebp 后 mov ebp,esp 后的值]
retn [返回程序空間,執(zhí)行第6行代碼]
call 401150 [程序內(nèi)調(diào)用子函數(shù)]
401150
push ebp
mov ebp,esp
push ebx [7efde000 線程關(guān)鍵信息]
sub esp,24 [36字節(jié)空間]
mov dword ptr ss:[esp],未命名1.00401000 [在棧頂放入401000]
call [設(shè)置異常捕獲函數(shù) 4018e4]
004018e4
jmp dword ptr ds:[&KERNEL32.SetUnhandledExceptionFilter] [跳轉(zhuǎn)到這個函數(shù)的實現(xiàn)過程]
KERNEL32.SetUnhandledExceptionFilter
mov edi,edi
push ebp
mov ebp,esp [設(shè)置新的棧頂,函數(shù)進(jìn)入子函數(shù)時push ebp后的 esp]
sub esp,220 [為什么移動這么大的距離?]
push ebx [7efde000 線程關(guān)鍵信息]
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 [設(shè)置新的棧頂]
sub esp,2c [移動2c距離]
push esi [401000壓棧]
push edi [0壓棧]
push 1c [1c(28)壓棧]
lea eax,dword ptr ss:[ebp-2c] [開始的esp偏移,用于接收VirtualQueryEx函數(shù)返回的信息,雖然返回的機(jī)構(gòu)大小是1c]
push eax [28fce4棧偏移]
push dword ptr ss:[ebp+8] [ebp+ 獲得參數(shù)1(401000)到局部變量]
call 75D0444F= [查詢地址空間中內(nèi)存地址的信息]
查詢地址空間中內(nèi)存地址的信息 kernel32的導(dǎo)入函數(shù)
jmp dword ptr ds:[&API-MS-Win-Core-Memory-L1-1-0.VirtualQuery] [KernelBa.VirtualQuery]
mov edi,edi
push ebp
mov ebp,esp [設(shè)置新的棧頂]
push dword ptr ss:[ebp+10] [1c MEMORY_BASIC_INFORMATION結(jié)構(gòu)的大小]
push dword ptr ss:[ebp+c] [28fce4棧偏移 指向MEMORY_BASIC_INFORMATION結(jié)構(gòu)的指針]
push dword ptr ss:[ebp+8] [401000 查詢內(nèi)存的地址]
push -1 [參數(shù)1為-1,共4個參數(shù) 進(jìn)程句柄]
call KernelBa.VirtualQueryEx [查詢地址空間中內(nèi)存地址的信息]
KernelBa.VirtualQueryEx
mov edi,edi
push ebp
mov ebp,esp
lea eax,dword ptr ss:[ebp+14] [獲得第4個參數(shù)的地址 28fcc4 給 eax 保存有結(jié)構(gòu)的大小]
push eax [地址壓棧 存儲該函數(shù)處理 返回 的信息的長度的ULONG的地址]
push dword ptr ss:[ebp+14] [值壓棧,局部變量 結(jié)構(gòu)體大小 Buffer的最大長度]
push dword ptr ss:[ebp+10] [用于存儲獲取到的內(nèi)存信息的結(jié)構(gòu)地址]
push 0 [查詢內(nèi)存信息的類別]
push dword ptr ss:[ebp+c] [查詢內(nèi)存的地址 401000]
push dword ptr ss:[ebp+8] [進(jìn)程句柄 -1]
call dword ptr ds:[<&ntdll.NtQueryVirtualMemory>] [查詢指定進(jìn)程的某個虛擬地址控件所在的內(nèi)存對象的一些信息]
ntdll.NtQueryVirtualMemory
mov eax,20
xor ecx,ecx [清零]
lea edx,dword ptr ss:[esp+4] [獲得返回地址]
call dword ptr fs:[c0] [線程 的 TEB結(jié)構(gòu) WOW32Reserved 7efdd0c0 -> 741f2320]
jmp far 0033:741f271e [長跳轉(zhuǎn),不理解]
77ae01c4 RtlUserThreadStart
mov dwrod ptr ss:[esp+4],eax [將程序入口地址 401280 寫入]
...沒了,程序顯示了 helloworld ,處于等待哦 getchar() 但是我在程序輸入任意字符后就跳到
77aefcb2 了,然后就顯示已終止 OD顯示 ERR0R_FILE_NOT_FOUND LASTERR 2
調(diào)用鏈:
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