小資料:ASPr API修復

看雪資料發表於2004-07-02

小資料:ASPr API修復
kongfoo/2004.6.22

  ASPr處理後有部分API已經面目全非,手動分析會毫無頭緒,只能
靠經驗或外掛,下面記錄一下ASPr對一些API的處理,手動分析起來就
事半功倍了。

程式碼:
kernel32.GetCommandLineA: 00D9139C    6A 00           PUSH 0 00D9139E    E8 B53DFFFF     CALL 00D85158                            ; JMP to kernel32.GetModuleHandleA 00D913A3    FF35 E46CD900   PUSH DWORD PTR DS:[D96CE4] 00D913A9    58              POP EAX 00D913AA    8B05 F46CD900   MOV EAX,DWORD PTR DS:[D96CF4]  ==d96cf4放的是命令列引數 00D913B0    C3              RETN

  這個是比較簡單的,前面的都是煙霧彈,最後mov eax,[xx]實現了原
API的功能。
程式碼:
kernel32.GetModuleHandleA: 00D9133C    55              PUSH EBP 00D9133D    8BEC            MOV EBP,ESP 00D9133F    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8] 00D91342    85C0            TEST EAX,EAX 00D91344    75 07           JNZ SHORT 00D9134D 00D91346    A1 7869D900     MOV EAX,DWORD PTR DS:[D96978]  ==d96978放的是40000,哪麼這個是GetModuleHandleA的功能了 00D9134B    EB 06           JMP SHORT 00D91353 00D9134D    50              PUSH EAX 00D9134E    E8 053EFFFF     CALL 00D85158                            ; JMP to kernel32.GetModuleHandleA 00D91353    5D              POP EBP 00D91354    C2 0400         RETN 4

  這個也是根據返回值就能判斷出API的例子。
程式碼:
kernel32.GetProcAddress: 00D90EE8    55              PUSH EBP 00D90EE9    8BEC            MOV EBP,ESP 00D90EEB    8B55 0C         MOV EDX,DWORD PTR SS:[EBP+C] 00D90EEE    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8] 00D90EF1    8B0D 3C54D900   MOV ECX,DWORD PTR DS:[D9543C] 00D90EF7    8B09            MOV ECX,DWORD PTR DS:[ECX] 00D90EF9    3BC8            CMP ECX,EAX 00D90EFB    75 09           JNZ SHORT 00D90F06 00D90EFD    8B0495 5053D900 MOV EAX,DWORD PTR DS:[EDX*4+D95350] 00D90F04    EB 07           JMP SHORT 00D90F0D 00D90F06    52              PUSH EDX 00D90F07    50              PUSH EAX 00D90F08    E8 5342FFFF     CALL 00D85160                            ; JMP to kernel32.GetProcAddress 00D90F0D    5D              POP EBP 00D90F0E    C2 0800         RETN 8

  上面GetModuleHandleA的例子告訴我們這種情形的答案:GetProcAddress。
程式碼:
kernel32.GetVersion: 00D91358    6A 00           PUSH 0 00D9135A    E8 F93DFFFF     CALL 00D85158                            ; JMP to kernel32.GetModuleHandleA 00D9135F    FF35 E46CD900   PUSH DWORD PTR DS:[D96CE4]  ==d96ce4放的是版本資訊,API是GetVersion 00D91365    58              POP EAX 00D91366    C3              RETN

  這個和GetCommandLineA是一樣的了,根據返回值即可判斷出API。
程式碼:
kernel32.GetCurrentProcess: 00D91388    MOV EAX,[D96CE8]  ==d96ce8放的是-1 00D9138D    RETN

  這個是用外掛找出來的,積累經驗,(至少XP是)以-1作為當前程式控制程式碼的,
所以以後遇到這個情況就好處理了。
程式碼:
kernel32.LockResource: 00D913B4    55              PUSH EBP 00D913B5    8BEC            MOV EBP,ESP 00D913B7    8B05 F46CD900   MOV EAX,DWORD PTR DS:[D96CF4] 00D913BD    8B45 08         MOV EAX,DWORD PTR SS:[EBP+8] 00D913C0    5D              POP EBP 00D913C1    C2 0400         RETN 4

  這個是也用外掛找出來的,積累一下經驗。再看看原版LockResource的程式碼:
程式碼:
77E5C931 >  8B4424 04       MOV EAX,DWORD PTR SS:[ESP+4] 77E5C935    C2 0400         RETN 4

以上資料來自CrystalButton 1.40A ASP1.23RC1

==========================================
程式碼:
user32.CharNextA: 00970FE4    A1 60D0D677          MOV EAX,DWORD PTR DS:[77D6D060]  ==已經去掉花指令 00970FE9    F640 02 04           TEST BYTE PTR DS:[EAX+2],4 00970FED    56                   PUSH ESI 00970FEE    8B7424 08            MOV ESI,DWORD PTR SS:[ESP+8] 00970FF9  - 0F85 6F433D77        JNZ USER32.77D4536E 00970FFF    803E 00              CMP BYTE PTR DS:[ESI],0 0097100B  - 0F84 F5623A77        JE USER32.77D17306 00971011    46                   INC ESI 00971012    8BC6                 MOV EAX,ESI 00971014    5E                   POP ESI 00971019    68 0973D177          PUSH 77D17309  ==這種型別的API處理就最簡單了,根據這個地址就可以找到API 0097101E    C3                   RETN kernel32.GetModuleHandleA: 009712D4    837C24 04 00         CMP DWORD PTR SS:[ESP+4],0 009712E0  - 0F84 DB924E77        JE kernel32.77E5A5C1 009712E6    FF7424 04            PUSH DWORD PTR SS:[ESP+4] 009712EF    68 A79FE577          PUSH 77E59FA7 009712F8    55                   PUSH EBP 009712F9    8BEC                 MOV EBP,ESP 009712FB    51                   PUSH ECX 009712FC    51                   PUSH ECX 009712FD    56                   PUSH ESI 009712FE    64:A1 18000000       MOV EAX,DWORD PTR FS:[18] 00971304    FF75 08              PUSH DWORD PTR SS:[EBP+8] 00971307    8DB0 F80B0000        LEA ESI,DWORD PTR DS:[EAX+BF8] 0097130D    8D45 F8              LEA EAX,DWORD PTR SS:[EBP-8] 00971310    50                   PUSH EAX 00971315    68 15A8E577          PUSH 77E5A815 0097131A    C3                   RETN

  這個GetModuleHandleA和上面asp1.23rc1又有所不同,是將整API的程式碼
搬了過來,其處理API裡面的呼叫(CALL)方法很值得學習一下。
程式碼:
原API程式碼: 77E59F93 >  837C24 04 00         CMP DWORD PTR SS:[ESP+4],0 77E59F98    0F84 23060000        JE kernel32.77E5A5C1 77E59F9E    FF7424 04            PUSH DWORD PTR SS:[ESP+4] 77E59FA2    E8 55080000          CALL kernel32.77E5A7FC 77E59FA7    85C0                 TEST EAX,EAX 77E59FA9    74 08                JE SHORT kernel32.77E59FB3 77E59FAB    FF70 04              PUSH DWORD PTR DS:[EAX+4] 77E59FAE    E8 B0060000          CALL kernel32.GetModuleHandleW 77E59FB3    C2 0400              RETN 4 77E5A7FC    55                   PUSH EBP 77E5A7FD    8BEC                 MOV EBP,ESP 77E5A7FF    51                   PUSH ECX 77E5A800    51                   PUSH ECX 77E5A801    56                   PUSH ESI 77E5A802    64:A1 18000000       MOV EAX,DWORD PTR FS:[18] 77E5A808    FF75 08              PUSH DWORD PTR SS:[EBP+8] 77E5A80B    8DB0 F80B0000        LEA ESI,DWORD PTR DS:[EAX+BF8] 77E5A811    8D45 F8              LEA EAX,DWORD PTR SS:[EBP-8] 77E5A814    50                   PUSH EAX 77E5A815    FF15 8C10E477        CALL DWORD PTR DS:[<&ntdll.RtlInitAnsiSt>; ntdll.RtlInitAnsiString 77E5A81B    6A 00                PUSH 0 77E5A81D    8D45 F8              LEA EAX,DWORD PTR SS:[EBP-8] 77E5A820    50                   PUSH EAX 77E5A821    56                   PUSH ESI 77E5A822    FF15 1C61EB77        CALL DWORD PTR DS:[77EB611C]             ; ntdll.RtlAnsiStringToUnicodeString 77E5A828    85C0                 TEST EAX,EAX 77E5A82A    0F8C 19000200        JL kernel32.77E7A849 77E5A830    8BC6                 MOV EAX,ESI 77E5A832    5E                   POP ESI 77E5A833    C9                   LEAVE 77E5A834    C2 0400              RETN 4

以上資料來自asp1.3b的unpackme(notepad.exe)。這個版本的殼把FF15的CALL
都變成:
00401101    FF15 D80F9700        CALL DWORD PTR DS:[970FD8]

  CALL到殼申請的空間了,哪麼程式空間裡面就不需要有IAT資訊了,ImpREC
就會找不到IAT(提示Could not find anything good at this OEP)。

==============================================================
再來到asp1.4,殼把程式中的FF15 xxxxxxxx改成E8 xxxxxxxx xx,最後一個位元組
是隨機的。而且去偽API前還有一段程式碼:
程式碼:
00401268    E8 83FF8C00          CALL 00CD11F0 00CD11F0    BA 5A904800          MOV EDX,48905A 00CD11F5    BA D2E14400          MOV EDX,44E1D2 00CD11FA    58                   POP EAX 00CD11FB    83C0 01              ADD EAX,1 00CD11FE    50                   PUSH EAX 00CD11FF    68 800FCD00          PUSH 0CD0F80 00CD1204    C3                   RETN 00CD0F80    55                   PUSH EBP 00CD0F81    8BEC                 MOV EBP,ESP 00CD0F83    83EC 0C              SUB ESP,0C ......

  但具體對API的處理還是差不多。
================================
asp2.0a對FF15的處理既有1.3b的模式又有1.4的模式,但採用1.3b模式處理的
CALL和1.3b又有點不同。

  舉個例子:
1.3b:
call [900000] ==900000放的是9000xx(跟著900000)即偽API的地址。
        即所CALL的地址後面就是偽API程式碼,沒有偽API地址表。
call [9001ba] ==接著的一個CALL會是相隔比較遠的地址。

2.0a:
call [900000] ==900000是偽API地址表專案,有偽API地址表。
call [900004] ==接著的CALL的地址是地址表相應的專案。

相關文章