先分析,再脫殼(二) (13千字)

看雪資料發表於2003-09-04

第二部分 脫殼
#################################################################################################
脫殼過程,已經有了前面的分析,這裡儘量簡化操作:
用OD載入,來到入口點:
00611F19 > EB 20            JMP SHORT DreamRo.00611F3B
... ...
00611F3B  9C              PUSHFD
... ...
00611F54  9D              POPFD
00611F55  ^E9 73A1FFFF      JMP DreamRo.0060C0CD
游標在定611F55這行上F4,再F7,來到這裡:
0060C0CD  60              PUSHAD
0060C0CE  E8 00000000      CALL DreamRo.0060C0D3
0060C0D3  5D              POP EBP
0060C0D4  81ED D3000000    SUB EBP,0D3
0060C0DA  8DB5 EA000000    LEA ESI,DWORD PTR SS:[EBP+EA]
0060C0E0  55              PUSH EBP
0060C0E1  56              PUSH ESI
0060C0E2  81C5 24100000    ADD EBP,1024
0060C0E8  55              PUSH EBP
0060C0E9  C3              RETN
0060C0EA  C6              ???
0060C0EB  B3 D7            MOV BL,0D7
游標在定60C0EB這行上F4,來到這裡:
0060C0EB  5D              POP EBP
0060C0EC  8B45 00          MOV EAX,DWORD PTR SS:[EBP]
... ...
0060C141  C640 01 10      MOV BYTE PTR DS:[EAX+1],10
0060C145  FFE2            JMP EDX
游標在定60C145B這行上F4,再F7,來到這裡:
00340000  E8 24000000      CALL 00340029
00340005  8B4424 04        MOV EAX,DWORD PTR SS:[ESP+4]
00340009  8B00            MOV EAX,DWORD PTR DS:[EAX]
0034000B  3D 04000080      CMP EAX,80000004
00340010  75 08            JNZ SHORT 0034001A
00340012  8B6424 08        MOV ESP,DWORD PTR SS:[ESP+8]
00340016  EB 04            JMP SHORT 0034001C
00340018  58              POP EAX
00340019  EB 0C            JMP SHORT 00340027
...  ...
一直向下翻到這裡:
00343533  3D 940000C0      CMP EAX,C0000094
00343538  75 2A            JNZ SHORT 00343564
0034353A  C702 00000000    MOV DWORD PTR DS:[EDX],0
00343540  FF81 B8000000    INC DWORD PTR DS:[ECX+B8]
00343546  33C0            XOR EAX,EAX
00343548  2141 04          AND DWORD PTR DS:[ECX+4],EAX
0034354B  2141 08          AND DWORD PTR DS:[ECX+8],EAX
0034354E  2141 0C          AND DWORD PTR DS:[ECX+C],EAX
00343551  2141 10          AND DWORD PTR DS:[ECX+10],EAX
00343554  8161 14 F00FFFFF AND DWORD PTR DS:[ECX+14],FFFF0FF0
0034355B  8161 18 00DC0000 AND DWORD PTR DS:[ECX+18],0DC00
00343562  EB 6E            JMP SHORT 003435D2
在34353A這行F2下一個斷點,再F9執行,斷下來後清掉此斷點,向下翻到這裡:
003436A6  8BFC            MOV EDI,ESP
003436A8  8DA5 FC314000    LEA ESP,DWORD PTR SS:[EBP+4031FC]
003436AE  B9 FB180000      MOV ECX,18FB
003436B3  B8 A4ABA45B      MOV EAX,5BA4ABA4
003436B8  BB BDD89800      MOV EBX,98D8BD
003436BD  BE D5260000      MOV ESI,26D5
003436C2  33D2            XOR EDX,EDX
003436C4  F7E6            MUL ESI
003436C6  05 78563412      ADD EAX,12345678
003436CB  83D2 00          ADC EDX,0
003436CE  F7F3            DIV EBX
003436D0  58              POP EAX
003436D1  32C2            XOR AL,DL
003436D3  50              PUSH EAX
003436D4  4C              DEC ESP
003436D5  8BC2            MOV EAX,EDX
003436D7  ^E2 E9            LOOPD SHORT 003436C2
003436D9  C9              LEAVE
003436DA  6BDB CD          IMUL EBX,EBX,-33
在3436A6這行F2下一個斷點,再F9執行,斷下來後清掉此斷點,
游標定在3436D9按F4來到這裡:
003436D9  8BE7            MOV ESP,EDI
003436DB  8DB5 FD314000    LEA ESI,DWORD PTR SS:[EBP+4031FD]
003436E1  B9 03000000      MOV ECX,3
003436E6  EB 07            JMP SHORT 003436EF
游標定在34397E按F4來到這裡:
0034397E  87E6            XCHG ESI,ESP
00343980  6A 04            PUSH 4
00343982  68 00100000      PUSH 1000
00343987  68 00200000      PUSH 2000
0034398C  6A 00            PUSH 0
0034398E  FF95 09324000    CALL DWORD PTR SS:[EBP+403209]

下面我們要開始修改程式碼了,目的是去掉API重定位,便於以後的IAT重建,
首先注意下面這段程式碼,我打算先從這裡入手:
00343B6A  8B0A            MOV ECX,DWORD PTR DS:[EDX]          ;重定位處理開始
00343B6C  81E1 FFFFFF7F    AND ECX,7FFFFFFF
00343B72  51              PUSH ECX                            ;函式數目
00343B73  52              PUSH EDX
00343B74  C1E1 05          SHL ECX,5                          ;每個函式佔用32位元組重定位空間
00343B77  6A 04            PUSH 4
00343B79  68 00100000      PUSH 1000
00343B7E  51              PUSH ECX
00343B7F  6A 00            PUSH 0
00343B81  8D85 BD1D4000    LEA EAX,DWORD PTR SS:[EBP+401DBD]  ;=343B94
00343B87  50              PUSH EAX
00343B88  8B85 09324000    MOV EAX,DWORD PTR SS:[EBP+403209]  ;VirtualAlloc
00343B8E  E9 98080000      JMP 0034442B
00343B93  E8              DB E8
00343B94  8985 4D324000    MOV DWORD PTR SS:[EBP+40324D],EAX  ;為第一層重定位分配的空間
00343B9A  5A              POP EDX
00343B9B  59              POP ECX
00343B9C  50              PUSH EAX
00343B9D  51              PUSH ECX
00343B9E  2BBD 0D324000    SUB EDI,DWORD PTR SS:[EBP+40320D]  ;BASE ADDRESS
00343BA4  83FF FF          CMP EDI,-1
00343BA7  74 15            JE SHORT 00343BBE
00343BA9  03BD 0D324000    ADD EDI,DWORD PTR SS:[EBP+40320D]
00343BAF  EB 09            JMP SHORT 00343BBA
00343BB1  8907            MOV DWORD PTR DS:[EDI],EAX          ;往IAT中填充第一層重定位的函式地址
00343BB3  83C0 20          ADD EAX,20
00343BB6  83C7 04          ADD EDI,4
00343BB9  49              DEC ECX
00343BBA  0BC9            OR ECX,ECX
00343BBC  ^75 F3            JNZ SHORT 00343BB1
00343BBE  59              POP ECX
00343BBF  58              POP EAX
00343BC0  8BF8            MOV EDI,EAX
00343BC2  57              PUSH EDI
00343BC3  51              PUSH ECX
00343BC4  EB 2D            JMP SHORT 00343BF3
00343BC6  8D47 1C          LEA EAX,DWORD PTR DS:[EDI+1C]      ;REAL_PROC_ADDR
00343BC9  66:C707 FF35    MOV WORD PTR DS:[EDI],35FF          ;PUSH DWORD PTR [REAL_PROC_ADDR]
00343BCE  C747 06 81342400 MOV DWORD PTR DS:[EDI+6],243481    ;XOR DWORD PTR [ESP],XORKEY
00343BD5  8947 02          MOV DWORD PTR DS:[EDI+2],EAX        ;RET
00343BD8  C647 0D C3      MOV BYTE PTR DS:[EDI+D],0C3        ;
00343BDC  52              PUSH EDX
00343BDD  0F31            RDTSC
00343BDF  32E0            XOR AH,AL
00343BE1  C1C8 08          ROR EAX,8
00343BE4  02E0            ADD AH,AL
00343BE6  C1C8 08          ROR EAX,8
00343BE9  32E0            XOR AH,AL
00343BEB  8947 09          MOV DWORD PTR DS:[EDI+9],EAX        ;XORKEY
00343BEE  5A              POP EDX
00343BEF  83C7 20          ADD EDI,20
00343BF2  49              DEC ECX
00343BF3  0BC9            OR ECX,ECX
00343BF5  ^75 CF            JNZ SHORT 00343BC6                  ;上面一段是FILL REDIR CODE
00343BF7  59              POP ECX
00343BF8  5F              POP EDI
00343BF9  83C2 04          ADD EDX,4
00343BFC  51              PUSH ECX
00343BFD  0FB602          MOVZX EAX,BYTE PTR DS:[EDX]
00343C00  0BC0            OR EAX,EAX
00343C02  75 2D            JNZ SHORT 00343C31

用F4執行到343B9C這行,開始修改程式碼,目的就是跳過第一層重定位,修改後的效果是這樣的:
00343B9C  EB 5B            JMP SHORT 00343BF9

在程式碼視窗內按Ctrl+G,輸入343C22,看到這兩行程式碼:
00343C22  3347 06          XOR EAX,DWORD PTR DS:[EDI+6]
00343C25  8947 1C          MOV DWORD PTR DS:[EDI+1C],EAX
把它們修改為:
00343C22  8907            MOV DWORD PTR DS:[EDI],EAX          ;把API函式地址添入原始IAT
00343C24  90              NOP                                ;這個是IMPORT BY ORD的
00343C25  90              NOP
00343C26  90              NOP
00343C27  90              NOP

在程式碼視窗內按Ctrl+G,輸入343C5F,看到這兩行程式碼:
00343C5E  52              PUSH EDX
00343C5F  52              PUSH EDX
00343C60  8D85 EF344000    LEA EAX,DWORD PTR SS:[EBP+4034EF]
把它們修改為:
00343C5E  E9 3A020000      JMP 00343E9D                        ;跳過SDK的函式處理
00343C63  90              NOP
00343C64  90              NOP
00343C65  90              NOP


在程式碼視窗內按Ctrl+G,輸入343EB2,看到這兩行程式碼:
00343EB2  8B9D E1364000    MOV EBX,DWORD PTR SS:[EBP+4036E1]
00343EB8  039D E5364000    ADD EBX,DWORD PTR SS:[EBP+4036E5]
把它們修改為:
00343EB2  8907            MOV DWORD PTR DS:[EDI],EAX          ;把API函式地址添入原始IAT
00343EB4  90              NOP                                ;這個是IMPORT BY NAME的
00343EB5  EB 5E            JMP SHORT 00343F15                  ;跳過第二層重定位
00343EB7  90              NOP

還要改一下這裡:
00343F1D  83C7 20          ADD EDI,20
改為:
00343F1D  83C7 04          ADD EDI,4                          ;調整IAT指標

接下來要注意下面的陷阱:
00344124  64:FF35 30000000 PUSH DWORD PTR FS:[30]              ;NT
0034412B  58              POP EAX                            ;pointer to PEB
0034412C  0FB658 02        MOVZX EBX,BYTE PTR DS:[EAX+2]
00344130  0ADB            OR BL,BL                            ;檢測應用程式級debugger,用OD跟蹤一定要注意這裡
00344132  0F85 9F130000    JNZ 003454D7                        ;這裡是本殼中唯一對OllyDBG有威脅的地方
00344138  EB 2A            JMP SHORT 00344164
用F4執行到344130這行,把BL暫存器清零,

下面對HOOK_CALL程式碼進行修改,直接解密,修復原始程式碼,關鍵程式碼是下面幾行:
00344255  0385 0D324000    ADD EAX,DWORD PTR SS:[EBP+40320D]
0034425B  2B85 29324000    SUB EAX,DWORD PTR SS:[EBP+403229]
00344261  8BDE            MOV EBX,ESI
00344263  2BD8            SUB EBX,EAX
00344265  8958 FC          MOV DWORD PTR DS:[EAX-4],EBX
00344268  66:C740 FA 90E8  MOV WORD PTR DS:[EAX-6],0E890
把它們修改為:
00344255  8B5F 04          MOV EBX,DWORD PTR DS:[EDI+4]        ;這幾行解密演算法來自3445B5處的分析
00344258  81C3 CA0D0BF6    ADD EBX,F60B0DCA                    ;CRC_KEY,來自3443B2處的計算結果
0034425E  2BD8            SUB EBX,EAX                        ;
00344260  F7D3            NOT EBX                            ;
00344262  C1C3 10          ROL EBX,10                          ;
00344265  8958 FC          MOV DWORD PTR DS:[EAX-4],EBX        ;
00344268  66:C740 FA FF25  MOV WORD PTR DS:[EAX-6],25FF        ;恢復為原始的JMP DWORD PTR [XXXXXXXX]

接下來有個DELPHI的MAINFORM必須要處理一下,因為現在它位於殼所分配的空間內,我們DUMP時會丟失掉,脫殼後就會出問題。
003442A4  8B85 59324000    MOV EAX,DWORD PTR SS:[EBP+403259]  ;這裡是對DELPHI的MAINFORM的處理
003442AA  0BC0            OR EAX,EAX                          ;其實就是把MAINFORM從原始碼區搬到了殼裡
003442AC  74 3F            JE SHORT 003442ED                  ;只需調整一下首指標就行了
003442AE  8DB5 2E164000    LEA ESI,DWORD PTR SS:[EBP+40162E]
003442B4  03F0            ADD ESI,EAX                        ;
003442B6  8B1E            MOV EBX,DWORD PTR DS:[ESI]          ;MAINFORM的原始參考RVA
003442B8  039D 0D324000    ADD EBX,DWORD PTR SS:[EBP+40320D]  ;BASE ADDRESS
003442BE  C706 00000000    MOV DWORD PTR DS:[ESI],0
003442C4  83C6 04          ADD ESI,4                          ;MAINFORM的現在的地址
003442C7  8933            MOV DWORD PTR DS:[EBX],ESI          ;把MAINFORM的現在的地址添到其參考位置
當執行到這裡時,ESI=348306,從ESI往後看資料區,容易看出一直到34921C都應該是FORM的資料,長度為0F17位元組,
我們再從EBX=4F96C4往後看資料區,到4FAA36處的有一個A6,再往下直到4FB94C都是0,A6與ESI處資料的第一位元組吻合,
長度也都是0F17位元組,可以判斷出4FAA36處就應該是MAINFORM的原始位置,因此做如下修改:
003442C7  BF 36AA4F00      MOV EDI,4FAA36                      ;FORM的原始地址
003442CC  893B            MOV DWORD PTR DS:[EBX],EDI          ;添入FORM的參考指標
003442CE  B9 170F0000      MOV ECX,0F17                        ;FORM 長度
003442D3  F3:A4            REP MOVSB                          ;移回原始位置
003442D5  EB 16            JMP SHORT 003442ED
003442D7  90              NOP
003442D8  90              NOP
003442D9  90              NOP
003442DA  90              NOP

接下來把ANTI DUMP處理掉,2000下是這裡:
00344311  64:FF35 30000000 PUSH DWORD PTR FS:[30]
00344318  58              POP EAX
00344319  85C0            TEST EAX,EAX
0034431B  78 0F            JS SHORT 0034432C
0034431D  8B40 0C          MOV EAX,DWORD PTR DS:[EAX+C]
00344320  8B40 0C          MOV EAX,DWORD PTR DS:[EAX+C]
00344323  C740 20 00100000 MOV DWORD PTR DS:[EAX+20],1000      ;ANTI DUMP,改為NOP
0034432A  EB 39            JMP SHORT 00344365

從下面這裡我們F7就來到OEP了:
0034442A  C3              RETN                                ;TO OEP

看看OEP處的程式碼:
0050CB6C  FFD7            CALL EDI
0050CB6E  58              POP EAX
把這兩行程式碼改成:
0050CB6C  55              PUSH EBP
0050CB6D  8BEC            MOV EBP,ESP
到此就算大功告成了。

後面工作大家就可以按個自習慣做了,我是用OD的PLUGINS的OllyDump先生成DUMP.EXE
然後執行Import REConstructor v1.6F,Attach到我們的程式上
OEP:0010CB6C
RVA:0018B1B8  SIZE:000007E0
去掉Add new section選項,輸入RVA:0018B998,這樣生成的檔案更精練一些,不過要算好空間,有把握才行
點Get Imports按鈕,一切OK
再Fix Dump,完全搞定了。

要想做錦上添花,還可以減肥,把殼所在的最後一個SECTION去掉,需要手工修復以下TLS,還要把被搬到殼中的幾個資源
放到合適的位置上,這個我就懶得敘述了。
#################################################################################################

後記:
#################################################################################################
我還是不要裝糊塗的好,脫到最後,我也知道殼是誰做的了,裡面有一句資訊:i am xxxxx,do not unpack me,please.
不好意思了,望兄弟不要介意。
#################################################################################################
iPB/heXer
03.09.04

相關文章