這裡就以Win2K,Ollydbg尋找System cleaner(4.90 build 122) OEP為例:
新版的ASPR最早讓我發現異樣的就是用IsDebuggerPresent來檢查是否在被除錯,Ollydbg裡下斷點IsDebuggerPresent..經過一系列Shift+F9後斷點來到IsDebuggerPresent的函式里:
77E6F4E9 > 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
77E6F4EF 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
77E6F4F2 0FB640 02 MOVZX EAX,BYTE PTR DS:[EAX+2]
77E6F4F6 C3 RETN
此函式利用eax返回值,1被除錯,0否..執行到MOVZX EAX,BYTE PTR DS:[EAX+2],看一下DS:[EAX+2]所指記憶體區域,把記憶體中的數值改為0(必須),同時eax也返回了0.
繼續Shift+F9,經過十數個後就來到這裡(當中會發現ASPR比以前的access memory錯誤還多了一些Int3):
01363D5F 3100 XOR DWORD PTR DS:[EAX],EAX <-----Ollydbg停在這裡
01363D61 64:8F05 00000000 POP DWORD PTR FS:[0] <-----我們在這裡下斷點
01363D68 58 POP EAX
01363D69 833D BC7E3601 00 CMP DWORD PTR DS:[1367EBC],0
01363D70 74 14 JE SHORT 01363D86
01363D72 6A 0C PUSH 0C
01363D74 B9 BC7E3601 MOV ECX,1367EBC
01363D79 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
01363D7C BA 04000000 MOV EDX,4
01363D81 E8 8ED2FFFF CALL 01361014
01363D86 FF75 FC PUSH DWORD PTR SS:[EBP-4]
01363D89 FF75 F8 PUSH DWORD PTR SS:[EBP-8]
01363D8C 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]
01363D8F 8338 00 CMP DWORD PTR DS:[EAX],0
01363D92 74 02 JE SHORT 01363D96
01363D94 FF30 PUSH DWORD PTR DS:[EAX]
01363D96 FF75 F0 PUSH DWORD PTR SS:[EBP-10]
01363D99 FF75 EC PUSH DWORD PTR SS:[EBP-14]
01363D9C C3 RETN
01363D9D 5F POP EDI
01363D9E 5E POP ESI
01363D9F 5B POP EBX
01363DA0 8BE5 MOV ESP,EBP
01363DA2 5D POP EBP
01363DA3 C3 RETN
Shift+F9,ollydbg就停在我們的斷點上..接下去已經沒多少路了,手動吧.F8一直到Retn,然後就在這裡:
01379330 68 D3F8FD02 PUSH 2FDF8D3
01379335 B4 4F MOV AH,4F
01379337 5B POP EBX
01379338 66:81D3 27F5 ADC BX,0F527
0137933D E8 09000000 CALL 0137934B <------F7進去
接著一直到:
013793EA 5B POP EBX
013793EB 81C7 5075A77E ADD EDI,7EA77550
013793F1 E8 0B000000 CALL 01379401 <------F7進去
接下去小心一點,用ollydbg的trace eip很快就能返回程式的領空,首先就是停在這裡:
00407278 $-FF25 2CF35600 JMP DWORD PTR DS:[56F32C] <-----我們停在這裡
0040727E 8BC0 MOV EAX,EAX
00407280 $-FF25 28F35600 JMP DWORD PTR DS:[56F328]
00407286 8BC0 MOV EAX,EAX
00407288 $-FF25 24F35600 JMP DWORD PTR DS:[56F324]
0040728E 8BC0 MOV EAX,EAX
00407290 $-FF25 20F35600 JMP DWORD PTR DS:[56F320]
對於1.2x和大多數的1.3+來說,trace eip停下來就是OEP裡,但新版本可以看到明顯不一樣,F7跟進去,這裡有一個技巧,如果發現停下來的程式碼都是DB FF之類的,大多數情況下選擇右鍵選單中的analysis/analyze code就可以看到正常的code.有時也不行,下面會看到
01361504 55 PUSH EBP
01361505 8BEC MOV EBP,ESP
01361507 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8]
0136150A 85C0 TEST EAX,EAX
0136150C 75 13 JNZ SHORT 01361521
0136150E 813D 70793601 00>CMP DWORD PTR DS:[1367970],400000 ASCII "MZP"
01361518 75 07 JNZ SHORT 01361521
0136151A A1 70793601 MOV EAX,DWORD PTR DS:[1367970]
0136151F EB 06 JMP SHORT 01361527
01361521 50 PUSH EAX
01361522 E8 853FFFFF CALL 013554AC JMP to kernel32.GetModuleHandleA
01361527 5D POP EBP
01361528 C2 0400 RETN 4
看到上面兩個指令是不是很心動...繼續走
0040734D . A3 68B65600 MOV DWORD PTR DS:[56B668],EAX <-----看到40734d這個EIP麼,很重要
00407352 . A1 68B65600 MOV EAX,DWORD PTR DS:[56B668]
00407357 . A3 D8205600 MOV DWORD PTR DS:[5620D8],EAX
0040735C . 33C0 XOR EAX,EAX
0040735E . A3 DC205600 MOV DWORD PTR DS:[5620DC],EAX
00407363 . 33C0 XOR EAX,EAX
00407365 . A3 E0205600 MOV DWORD PTR DS:[5620E0],EAX
0040736A . E8 C1FFFFFF CALL SystemCl.00407330
0040736F . BA D4205600 MOV EDX,SystemCl.005620D4
00407374 . 8BC3 MOV EAX,EBX
00407376 . E8 75D8FFFF CALL SystemCl.00404BF0
0040737B . 5B POP EBX
0040737C . C3 RETN
繼續走,會停在
005613EB E8 DB E8
005613EC 4C DB 4C CHAR 'L'
005613ED 5F DB 5F CHAR '_'
005613EE EA DB EA
005613EF FF DB FF
005613F0 FF DB FF <----我們停在這裡
005613F1 15 DB 15
005613F2 84A15600 DD SystemCl.0056A184
005613F6 E8 DB E8
005613F7 BD DB BD
005613F8 39 DB 39 CHAR '9'
005613F9 EA DB EA
005613FA FF DB FF
這裡就不用analyse了,檢查了也沒用...但分析一下上面的binary ,什麼意思呢?反彙編一下就知道了
005613EB E8 4C5FEAFF CALL SystemCl.0040734D
005613F0 FF15 84A15600 CALL DWORD PTR DS:[56A184] SystemCl.005608F0
005613F6 E8 BD39EAFF CALL SystemCl.00404DB8
看到了麼,最上面那個cALL我們已經執行過了,很顯然,aSPR更狡猾了,直接在殼裡執行了第一個cALL,所以oep就在第一個CALL位置:5613EB
剩下要做的工作就是恢復11個STOLEN BYTES,分析一下剛才走過的程式就可以得到,還有IAT,這些就不在這裡詳述了
這篇東西是在下午上班時抽空半小時寫的...若有錯誤,請多多包涵...