PesPin 1.0外殼簡略分析

看雪資料發表於2004-09-25

【目    標】: PeSpin 1.0主程式
【工    具】:Olydbg1.1
【任    務】:抓它的衣服個光光.哈哈
【操作平臺】:WINXP pro sp1 
【作    者】:loveboom[DFCG][FCG][US]
【相關連結】: http://pespin.w.interia.pl/(作者的官方站點)
【簡要說明】:不知不覺就過了這麼久了,很久沒寫什麼文章。看到別的朋友們在不斷的進步,我都感覺自己是不是真的老了哦:-).寫這篇文章也算是給大家中秋節的一個禮物吧,祝大家中秋快樂!身體健康!工作順利!!
【詳細過程】:
設定沒什麼特別,因為這次想稍微看細一點,所以是慢慢的來跟。開啟全部的異常就行了。
00410087 >  90              NOP                                      ; EP,殼入口,是垃圾程式碼,所以我直接nop掉它了
00410088    90              NOP
00410089    90              NOP
0041008A    60              PUSHAD
0041008B    E8 00000000     CALL 00410090
00410090    8B1C24          MOV EBX,DWORD PTR SS:[ESP]               ; 這裡就就是pop ebx
00410093    83C3 12         ADD EBX,12
00410096    812B E8B10600   SUB DWORD PTR DS:[EBX],6B1E8             ; 這裡開始就動態改變程式碼
0041009C    FE4B FD         DEC BYTE PTR DS:[EBX-3]
0041009F    812C24 E02A4000 SUB DWORD PTR SS:[ESP],00402AE0
004100A6    DC9E 83B17501   FCOMP QWORD PTR DS:[ESI+175B183]
004100AC    90              NOP
004100AD    8173 04 D77AF72>XOR DWORD PTR DS:[EBX+4],2FF77AD7        ; 又是動態生成程式碼
004100B4    8173 19 770043B>XOR DWORD PTR DS:[EBX+19],B7430077
004100BB    81C3 28000000   ADD EBX,28
004100C1    F9              STC                                      ; 設定C標誌
004100C2    FFE3            JMP EBX
004100C4    C9              LEAVE
004100C5    C2 0800         RETN 8
004100C8    90              NOP
004100C9    90              NOP
004100CA    72 01           JB SHORT 004100CD                        ; 其實就是jmp xxx,因為上面已經設定了C標誌
004100CC    90              NOP
004100CD    5D              POP EBP
004100CE    33C9            XOR ECX,ECX
004100D0    41              INC ECX
004100D1    E2 17           LOOPD SHORT 004100EA
004100D3   /EB 07           JMP SHORT 004100DC
004100D5   |90              NOP
004100D6   |EB 01           JMP SHORT 004100D9
004100D8   |90              NOP
004100D9   |EB 0D           JMP SHORT 004100E8
004100DB   |90              NOP
004100DC   \E8 01000000     CALL 004100E2
004100E1    90              NOP
004100E2    5A              POP EDX
004100E3    83EA 0B         SUB EDX,0B
004100E6    FFE2            JMP EDX                                  ; 這個殼裡好多這樣的東西哦
004100F1    8B95 D2424000   MOV EDX,DWORD PTR SS:[EBP+4042D2]        ; [EBP+4042D2]=4042d2+d5b0處存放的就是程式的IMGBASE
004100F7    8B42 3C         MOV EAX,DWORD PTR DS:[EDX+3C]            ; 這裡不就是取PE所以在的地方+3C
004100FA    03C2            ADD EAX,EDX                              ; 相加後就是PE檔案的開始處了
004100FC    8985 DC424000   MOV DWORD PTR SS:[EBP+4042DC],EAX        ; PE檔案開始處4000D0處入[EBP+4042DC]處
00410102    EB 02           JMP SHORT 00410106
00410104    90              NOP
00410105    90              NOP
00410106    F9              STC                                      ; 這裡也是明顯的變形jmp
00410107    72 08           JB SHORT 00410111
00410109    73 0E           JNB SHORT 00410119
0041010B    F9              STC
0041010C    830424 17       ADD DWORD PTR SS:[ESP],17
00410110    C3              RETN
00410111    E8 04000000     CALL 0041011A
00410116    90              NOP
00410117    F5              CMC
00410118    73 11           JNB SHORT 0041012B                       ; 又是一堆垃圾程式碼
0041011A    EB 06           JMP SHORT 00410122
0041011C    90              NOP
0041011D  ^ 72 ED           JB SHORT 0041010C
0041011F    1F              POP DS                                   ; Modification of segment register
00410120    EB 07           JMP SHORT 00410129
00410122    F5              CMC                                      ; 這裡也就是清除c標誌,所以下面也不會跳(實際是取反)
00410123    72 0E           JB SHORT 00410133
00410125    F5              CMC                                      ; 再次取反,這次下面就會跳了
00410126  ^ 72 F8           JB SHORT 00410120
00410128    90              NOP
00410129  ^ EB EC           JMP SHORT 00410117
0041012B    830424 07       ADD DWORD PTR SS:[ESP],7
0041012F    F5              CMC
00410130    FF3424          PUSH DWORD PTR SS:[ESP]                  ; PESpin.0041011D
00410133    C3              RETN

00410134    41              INC ECX
00410135    C1E1 07         SHL ECX,7
00410138    8B0C01          MOV ECX,DWORD PTR DS:[ECX+EAX]           ; 取code段的start address
0041013B    03CA            ADD ECX,EDX                              ; ecx就是儲存CODE段的開始RVA
……
0041014E    8B59 10         MOV EBX,DWORD PTR DS:[ECX+10]
00410151    03DA            ADD EBX,EDX
00410153    8B1B            MOV EBX,DWORD PTR DS:[EBX]
00410155    899D F0424000   MOV DWORD PTR SS:[EBP+4042F0],EBX        ; [EBP+4042F0]存放MessageBox的地址?
0041015B    53              PUSH EBX
0041015C    8F85 94414000   POP DWORD PTR SS:[EBP+404194]            ; [EBP+404194]存放MessageBox的地址?
00410162    BB E1000000     MOV EBX,0E1
00410167    B9 8C0B0000     MOV ECX,0B8C                             ; 傳入要解壓的SIZE
0041016C    8DBD 80434000   LEA EDI,DWORD PTR SS:[EBP+404380]
00410172    4F              DEC EDI
00410173    EB 01           JMP SHORT 00410176
00410175    90              NOP
00410176    301C39          XOR BYTE PTR DS:[ECX+EDI],BL             ; 從4124BB處開始解壓大小為0b8c的程式碼,是向上解壓
00410179    FECB            DEC BL
0041017B  ^ E2 F9           LOOPD SHORT 00410176
……
00410180    68 CB000000     PUSH 0CB
00410185    59              POP ECX                                  ; mov ecx,0cb
00410186    8DBD 404E4000   LEA EDI,DWORD PTR SS:[EBP+404E40]        ; 把剛才解壓後的起始地址41192F傳人EDI
……
0041019D    C00C39 02       ROR BYTE PTR DS:[ECX+EDI],2              ; 41192f+0CB=4124bb(上面的結束地址)處的值ror 2
004101A1  ^ E2 FA           LOOPD SHORT 0041019D                     ; 這裡再次從4124BB處解壓大小為0CB的程式碼
……
004101A1  ^\E2 FA           LOOPD SHORT 0041019D                       ; 這裡再次從4124BB處解壓大小為0CB的程式碼
004101A3    E8 02000000     CALL 004101AA                              ; 到這裡還是隻解壓殼的部分程式碼
004101A8    90              NOP
004101A9    90              NOP
004101AA    5A              POP EDX                                    ; mov edx,401A8
004101AB    8D85 FD685600   LEA EAX,DWORD PTR SS:[EBP+5668FD]          ; [EBP+5668FD]=D5B0+5668FD=573EAD地址入eax中
004101B1    BB 54130B00     MOV EBX,0B1354
004101B6    D1E3            SHL EBX,1
004101B8    2BC3            SUB EAX,EBX
004101BA    FFE0            JMP EAX                                    ; PESpin.00411805
……
00411820    66:813F 4D5A    CMP WORD PTR DS:[EDI],5A4D                 ; 這裡透過迴圈找kernel32.dll的KERNEL BASE(77e410000)
00411825    75 11           JNZ SHORT 00411838                         ; 如果找到了就不跳
00411827    0FB757 3C       MOVZX EDX,WORD PTR DS:[EDI+3C]
0041182B    66:F7C2 00F8    TEST DX,0F800                              ; 比較KERBASE+3C處是不是0f800
00411830    75 06           JNZ SHORT 00411838                         ; 如果不是就跳,這裡沒有跳
00411832    3B7C3A 34       CMP EDI,DWORD PTR DS:[EDX+EDI+34]
00411836    74 08           JE SHORT 00411840                          ; 這裡再次判斷KERNEL32.DLL的imgbase對不對
00411838    81EF 00000100   SUB EDI,10000                              ; UNICODE "ALLUSERSPROFILE=D:\Documents and Settings\All Users"
0041183E  ^ EB E0           JMP SHORT 00411820
00411840    97              XCHG EAX,EDI                               ; 如果找到就把EAX和edi的值互換一下
00411857    50              PUSH EAX                                   ; push KERNEL BASE
00411858    8785 F4424000   XCHG DWORD PTR SS:[EBP+4042F4],EAX         ; 把KERNEL BASE儲存到[EBP+4042F4]=4118A4處.
0041185E    016C24 04       ADD DWORD PTR SS:[ESP+4],EBP
00411862    8D85 FB9883EB   LEA EAX,DWORD PTR SS:[EBP+EB8398FB]
00411868    8D80 BDAABC14   LEA EAX,DWORD PTR DS:[EAX+14BCAABD]        ; 411968
0041186E    EB 01           JMP SHORT 00411871
00411870    90              NOP
00411871    FFD0            CALL EAX                                   ; 這裡也就是CALL 411968,這裡進去就是透過迴圈的方法來獲取KERNEL32.DLL的輸出表來找到所要用到的輸出函式。
我們進去看看:
0041196E    8BF0            MOV ESI,EAX
00411970    0340 3C         ADD EAX,DWORD PTR DS:[EAX+3C]            ; e_lfanew
00411973    8B40 78         MOV EAX,DWORD PTR DS:[EAX+78]            ; RVA Export Table
00411976    03C6            ADD EAX,ESI                              ; 輸出表的位置的RVA=6D040
00411978    FF70 20         PUSH DWORD PTR DS:[EAX+20]               ; 定位AddressofName=6DF20
0041197B    5B              POP EBX
0041197C    03DE            ADD EBX,ESI
0041197E    FF70 18         PUSH DWORD PTR DS:[EAX+18]               ; NumberofNames ==03AE
00411981    8F85 46444000   POP DWORD PTR SS:[EBP+404446]            ; MOV [ebp+404446],03AE(4119F6)
00411987    FF70 24         PUSH DWORD PTR DS:[EAX+24]               ; AddressOfNameOrdianls=6EDD8
0041198A    5A              POP EDX                                  ; mov edx,addressofnameordinals
0041198B    03D6            ADD EDX,ESI                              ; 轉換成VA
0041198D    FF70 1C         PUSH DWORD PTR DS:[EAX+1C]               ; AddressOfFunctions=6D068
00411990    59              POP ECX                                  ; mov ecx,AddressOfFunctions
00411991    03CE            ADD ECX,ESI
00411993    898D 36444000   MOV DWORD PTR SS:[EBP+404436],ECX        ; 儲存AddressOfFunctions到[EBP+404436]處
00411999    83EF 05         SUB EDI,5
0041199C    83C7 05         ADD EDI,5
0041199F    833F 00         CMP DWORD PTR DS:[EDI],0                 ; 如果取完了就跳
004119A2    74 71           JE SHORT 00411A15
004119A4    8A07            MOV AL,BYTE PTR DS:[EDI]
004119A6    8885 1D444000   MOV BYTE PTR SS:[EBP+40441D],AL
004119AC    FF77 01         PUSH DWORD PTR DS:[EDI+1]
……
004119C6    8B3B            MOV EDI,DWORD PTR DS:[EBX]               ; AddressOfNames儲存到EDI中
004119C8    03FE            ADD EDI,ESI
……
00411A00    5B              POP EBX
00411A01    0BC0            OR EAX,EAX                               ; 判斷取出的結果是為為空,如果為空就跳
00411A03    74 12           JE SHORT 00411A17
00411A05    EB 01           JMP SHORT 00411A08
00411A07    90              NOP
00411A08    8038 CC         CMP BYTE PTR DS:[EAX],0CC                ; 判斷我們有沒有在相關api處下cc斷點
00411A0B    75 03           JNZ SHORT 00411A10
00411A0D    8028 00         SUB BYTE PTR DS:[EAX],0                  ; 如果發現你在相關的API處下斷了,就把應該放的API地址給清0
00411A10    8947 01         MOV DWORD PTR DS:[EDI+1],EAX             ; 如果沒有就從4118b4處開始寫入相關的AP
00411A13  ^ EB 87           JMP SHORT 0041199C
00411A15    0BC0            OR EAX,EAX
00411A17    EB 01           JMP SHORT 00411A1A                       ; 取完後返回去了
00411A19    90              NOP
00411A1A    C3              RETN
這裡取了這麼幾個API:
kernel32.LoadLibraryA
kernel32.ExitProcess
kernel32.GetProcAddress
kernel32.VirtualProtect
kernel32.CloseHandle
kernel32.VirtualAlloc
kernel32.VirtualFree
kernel32.CreateFileA
kernel32.ReadFile
kernel32.GetTickCount
kernel32.GetModuleHandleA
kernel32.CreateThread
kernel32.Sleep
kernel32.GetCurrentProcessId
kernel32.OpenProcess
kernel32.TerminateProcess
kernel32.GetFileSize
kernel32.GetModuleFileNameA
……
00411F25    301F            XOR BYTE PTR DS:[EDI],BL                   ; 從4102C4處開始向下解壓大小為421的程式碼
00411F27    47              INC EDI
00411F28  ^ E2 F1           LOOPD SHORT 00411F1B
00411F2A    830424 05       ADD DWORD PTR SS:[ESP],5
00411F2E    C3              RETN                                       ; 解壓後跳去解壓後的地址4102c4
……
004102F7    53              PUSH EBX                                   ; 這裡準備異常,EBX就是完全地方
004102F8    50              PUSH EAX
……
00410301    B9 13000000     MOV ECX,13
00410306    E8 00000000     CALL 0041030B
0041030B    5F              POP EDI
0041030C    83EF 0A         SUB EDI,0A
0041030F    BE 54194100     MOV ESI,00411954
00410314    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]      ; 把411954處的程式碼複製13個到410301開始的地方
…….
00410334    5B              POP EBX                                  ; mov ebx,410334
00410335    81C3 1E000000   ADD EBX,1E                               ; ebx=410334+1e
0041033B    8DB5 502A4000   LEA ESI,DWORD PTR SS:[EBP+402A50]        ; mov esi,410000
00410341    68 FF000000     PUSH 0FF
00410346    56              PUSH ESI
00410347    6A 00           PUSH 0
00410349    53              PUSH EBX                                 ; push 410351
0041034A    FFA5 59434000   JMP DWORD PTR SS:[EBP+404359]            ; GetModuleFileNameA
這裡也就是:
0012FF94   00410351  /CALL to GetModuleFileNameA
0012FF98   00000000  |hModule = NULL
0012FF9C   00410000  |PathBuffer = PESpin.00410000
0012FFA0   000000FF  \BufSize = FF (255.)
410000處存放path,取出程式的完整路徑和程式名,結果存放在410000處。
00410358    81C3 22000000   ADD EBX,22                               ; 比較有意思殼呼叫API的都用這種方式,這裡運算後的值就是等下要返回的地址
0041035E    6A 00           PUSH 0
00410360    68 80000000     PUSH 80
00410365    6A 03           PUSH 3
00410367    6A 00           PUSH 0
00410369    6A 01           PUSH 1
0041036B    68 00000080     PUSH 80000000
00410370    56              PUSH ESI
00410371    53              PUSH EBX
00410372  - FFA5 27434000   JMP DWORD PTR SS:[EBP+404327]            ; CreateFileA
我這裡是這樣的:
0012FF84   00410378  /CALL to CreateFileA
0012FF88   00410000  |FileName = "G:\ctools\加殼\PesPin1.0\PESpin.exe"
0012FF8C   80000000  |Access = GENERIC_READ
0012FF90   00000001  |ShareMode = FILE_SHARE_READ
0012FF94   00000000  |pSecurity = NULL
0012FF98   00000003  |Mode = OPEN_EXISTING
0012FF9C   00000080  |Attributes = NORMAL
0012FFA0   00000000  \hTemplateFile = NULL
00410378    E8 01000000     CALL 0041037E
0041037D    90              NOP
0041037E    5A              POP EDX
0041037F    81C2 1A000000   ADD EDX,1A                               ; 這裡又來了,又是用這種方法來呼叫API
00410385    8985 2C4F4000   MOV DWORD PTR SS:[EBP+404F2C],EAX        ; 把CreateFileA後返回的值傳入[EBP+4042C]處
0041038B    93              XCHG EAX,EBX
0041038C    6A 00           PUSH 0
0041038E    53              PUSH EBX                                 ; push 檔案的控制程式碼
0041038F    52              PUSH EDX                                 ; 這裡是要返回的地址
00410390  - FFA5 54434000   JMP DWORD PTR SS:[EBP+404354]            ; GetFileSize

0012FF98   00410397  /CALL to GetFileSize
0012FF9C   00000038  |hFile = 00000038 (window)
0012FFA0   00000000  \pFileSizeHigh = NULL

00410397    E8 01000000     CALL 0041039D
0041039C    90              NOP
0041039D    5A              POP EDX
0041039E    81C2 23000000   ADD EDX,23                               ; CALL API後要返回的地址,4103bf
004103A4    8BD8            MOV EBX,EAX                              ; 檔案大小入EBX中
004103A6    53              PUSH EBX
004103A7    8F85 384F4000   POP DWORD PTR SS:[EBP+404F38]            ; 也就把檔案大小B600存入[EBP+404F38]中
004103AD    6A 04           PUSH 4
004103AF    68 00300000     PUSH 3000
004103B4    50              PUSH EAX
004103B5    6A 00           PUSH 0
004103B7    52              PUSH EDX
004103B8    FFA5 1D434000   JMP DWORD PTR SS:[EBP+40431D]            ; 這裡開始分配一個檔案大小的空間

0012FF90   004103BF  /CALL to VirtualAlloc
0012FF94   00000000  |Address = NULL
0012FF98   0000B600  |Size = B600 (46592.)
0012FF9C   00003000  |AllocationType = MEM_COMMIT|MEM_RESERVE
0012FFA0   00000004  \Protect = PAGE_READWRITE
申請返回的地址是:003E0000.
004103BF    50              PUSH EAX
004103C0    8F85 D8424000   POP DWORD PTR SS:[EBP+4042D8]            ; [EBP+4042D8]處儲存申請後的地址003E0000
004103C6    8D8D 384F4000   LEA ECX,DWORD PTR SS:[EBP+404F38]        ; 把檔案大小的地址傳入ecx中
004103CC    E8 01000000     CALL 004103D2
004103D1    90              NOP
004103D2    5A              POP EDX
004103D3    81C2 1C000000   ADD EDX,1C                               ; CALL API後要返回的地址4103ED
004103D9    6A 00           PUSH 0                                   ; 這裡開始透過ReadFile把檔案讀入剛才申請的地址003e0000處
004103DB    51              PUSH ECX
004103DC    53              PUSH EBX
004103DD    50              PUSH EAX
004103DE    FFB5 2C4F4000   PUSH DWORD PTR SS:[EBP+404F2C]
004103E4    52              PUSH EDX
004103E5    FFA5 2C434000   JMP DWORD PTR SS:[EBP+40432C]            ; ReadFile

 
004103ED    E8 01000000     CALL 004103F3
004103F2    90              NOP
004103F3    5A              POP EDX
004103F4    81C2 16000000   ADD EDX,16
004103FA    FFB5 2C4F4000   PUSH DWORD PTR SS:[EBP+404F2C]           ; push檔案號
00410400    52              PUSH EDX                                 ; push要返回的地址410408
00410401  - FFA5 18434000   JMP DWORD PTR SS:[EBP+404318]            ; 操作完成就CloseHandle了
00410407    90              NOP
00410408    FFB5 384F4000   PUSH DWORD PTR SS:[EBP+404F38]            ; 檔案大小入ecx了
0041040E    59              POP ECX
0041040F    81E9 111B0000   SUB ECX,1B11                              ; 用檔案大小b600-1b11=9AEF
00410415    8DBD D8424000   LEA EDI,DWORD PTR SS:[EBP+4042D8]
0041041B    8B3F            MOV EDI,DWORD PTR DS:[EDI]                ; 申請的地址3E0000入edi中
0041041D    8D85 0B616038   LEA EAX,DWORD PTR SS:[EBP+3860610B]
00410423    0BC0            OR EAX,EAX
00410425    75 19           JNZ SHORT 00410440                        ; 這裡實際也是一個jmp來的
00410447    2985 404F4000   SUB DWORD PTR SS:[EBP+404F40],EAX         ; 儲存hash值58873d42?? [EBP+404F40]= 58873d42
0041044D    E8 01000000     CALL 00410453
00410452    90              NOP
00410453    5A              POP EDX
00410454    81C2 1C000000   ADD EDX,1C
0041045A    68 00800000     PUSH 8000
0041045F    6A 00           PUSH 0
00410461    FFB5 D8424000   PUSH DWORD PTR SS:[EBP+4042D8]            ; push 003E0000
00410467    52              PUSH EDX                                  ; push返回地址41046E
00410468    FFA5 22434000   JMP DWORD PTR SS:[EBP+404322]             ; 這裡釋放剛才申請的空間003E0000
0041046E    BB 380D581C     MOV EBX,1C580D38                          ; 前的取出檔案操作的只是為了得到一個hash值??
……
00410492    64:8920         MOV DWORD PTR FS:[EAX],ESP               ; 有意思,這裡的異常,是透過call的那個esp值+ebp的
00410495    C1EB 02         SHR EBX,2                                ; 上面其實就是設定 SEH控制程式碼為4104ba
…….
004104BA    8B4424 04       MOV EAX,DWORD PTR SS:[ESP+4]             ; 這裡幾個是什麼作用我也不知道;-(
004104BE    8B4C24 0C       MOV ECX,DWORD PTR SS:[ESP+C]
004104C2    8B00            MOV EAX,DWORD PTR DS:[EAX]
004104C4    35 5B011238     XOR EAX,3812015B
004104C9    3D 5E0112F8     CMP EAX,F812015E
004104CE    75 0F           JNZ SHORT 004104DF                       ; 這裡不相等
004104D0    8181 B8000000 B>ADD DWORD PTR DS:[ECX+B8],18BF
004104DA    EB 27           JMP SHORT 00410503
004104DC    EB 01           JMP SHORT 004104DF
004104DE    90              NOP
004104DF    3D 460112F8     CMP EAX,F8120146                         ; EAX==F81201CF
004104E4    75 0C           JNZ SHORT 004104F2
004104E6    8181 B8000000 7>ADD DWORD PTR DS:[ECX+B8],172
004104F0    EB 11           JMP SHORT 00410503
004104F2    3D CF0112F8     CMP EAX,F81201CF
004104F7    75 0A           JNZ SHORT 00410503
004104F9    8181 B8000000 9>ADD DWORD PTR DS:[ECX+B8],1490
00410503    33C0            XOR EAX,EAX
00410505    C3              RETN
這裡再回到411931處
……
00411942    803B CC         CMP BYTE PTR DS:[EBX],0CC                ; 這裡判斷4104a4處有沒有下斷點
00411945    75 0B           JNZ SHORT 00411952                       ; 如果沒有就跳
00411947    81E4 FFFF0000   AND ESP,0FFFF
0041194D    E8 1A000000     CALL 0041196C
00411952  ^ FFE3            JMP EBX                                  ; 跳回去繼續執行
……
00410549    90              NOP
0041054A    51              PUSH ECX                                 ; push要解壓的section值,ECX==4
0041054B    0FA3C3          BT EBX,EAX                               ; 如果ebx內容為空就c標誌為0,否則CF=1,我們這裡EBX=7
0041054E    73 24           JNB SHORT 00410574                       ; 如果段不需要解壓就跳
00410550    52              PUSH EDX                                 ; 這裡開始解壓各個section的資料
00410551    8B7A 0C         MOV EDI,DWORD PTR DS:[EDX+C]             ; 第一次的結果:
00410554    03BD D2424000   ADD EDI,DWORD PTR SS:[EBP+4042D2]        ; 傳入要寫起始的地址401000
0041055A    8B4A 10         MOV ECX,DWORD PTR DS:[EDX+10]            ; 傳入要寫的程式碼SIZE==5200也就是解壓.text段的大小
0041055D    8B95 404F4000   MOV EDX,DWORD PTR SS:[EBP+404F40]        ; 這裡取出上面hash的值,傳入edx中
00410563    D1EA            SHR EDX,1
00410565    72 06           JB SHORT 0041056D
00410567    81F2 32AF43ED   XOR EDX,ED43AF32
0041056D    3017            XOR BYTE PTR DS:[EDI],DL
0041056F    47              INC EDI
00410570    49              DEC ECX
00410571  ^ E2 F0           LOOPD SHORT 00410563                     ; 這裡迴圈進行解壓程式碼
00410573    5A              POP EDX                                  ; 如果解壓到前一個section,的話,就指向下一個section
00410574    40              INC EAX
00410575    83C2 28         ADD EDX,28
00410578    59              POP ECX
00410579    EB 01           JMP SHORT 0041057C
0041057B    40              INC EAX
0041057C  ^ E2 CC           LOOPD SHORT 0041054A                     ; 這時迴圈回去
0041057E    838D 3A4E4000 0>OR DWORD PTR SS:[EBP+404E3A],0
00410585    74 0D           JE SHORT 00410594
00410587    8D85 DA4B4000   LEA EAX,DWORD PTR SS:[EBP+404BDA]
0041058D    2D D1030000     SUB EAX,3D1
00410592    FFD0            CALL EAX
00410594    68 19010000     PUSH 119
00410599    59              POP ECX
0041059A    8DBD BC4A4000   LEA EDI,DWORD PTR SS:[EBP+404ABC]        ; 從41206c處解壓大小為119的程式碼
004105A0    BA E9909E01     MOV EDX,19E90E9
004105A5    D1EA            SHR EDX,1
004105A7    73 06           JNB SHORT 004105AF
004105A9    81F2 32AF43ED   XOR EDX,ED43AF32
004105AF    3017            XOR BYTE PTR DS:[EDI],DL
004105B1    47              INC EDI                                  ; PESpin.00412070
004105B2  ^ E2 F1           LOOPD SHORT 004105A5                     ; 如果沒有解壓完成就跳回去解壓
004105B4    8D85 5C888D65   LEA EAX,DWORD PTR SS:[EBP+658D885C]
……
004105BF    D1E3            SHL EBX,1
004105C1    2BC3            SUB EAX,EBX
004105C3    50              PUSH EAX                                 ; 跳去已經解壓的地方41206c
004105C4    C3              RETN
……
0041206C   /EB 01           JMP SHORT 0041206F                       ; 解壓一段執行一段
0041206E   |90              NOP
0041206F   \8DBD 15304000   LEA EDI,DWORD PTR SS:[EBP+403015]        ; 又要解壓程式碼了,開始解壓地址4105c5
00412075    B9 20010000     MOV ECX,120                              ; 要解壓的程式碼大小為120
……
004120A4   /EB 01           JMP SHORT 004120A7
004120A6   |90              NOP
004120A7   \0AC0            OR AL,AL
004120A9    AA              STOS BYTE PTR ES:[EDI]
004120AA  ^ E2 D7           LOOPD SHORT 00412083                     ; 感覺這裡自己像是yoda's cryptor
解壓完後進入第三個異常.
…….
00412132    64:8923         MOV DWORD PTR FS:[EBX],ESP
00412135    FB              STI                                      ; 到了第三個異常
……
004120AA  ^\E2 D7           LOOPD SHORT 00412083                     ; 感覺這裡自己像是yoda's cryptor
004120AC    55              PUSH EBP
004120AD    9C              PUSHFD
004120AE    E8 77000000     CALL 0041212A
004120B3    90              NOP
004120B4    8B5424 08       MOV EDX,DWORD PTR SS:[ESP+8]             ; 直接在這裡下斷就行了
004120B4    8B5424 08       MOV EDX,DWORD PTR SS:[ESP+8]             ; 直接在這裡下斷就行了
004120B8    8B4424 0C       MOV EAX,DWORD PTR SS:[ESP+C]
004120BC    8142 04 3500000>ADD DWORD PTR DS:[EDX+4],35              ; 注意這裡,作者的異常都用這一招的,在目標地址裡的那個值處下斷
004120C3    81CA 29242123   OR EDX,23212429
004120C9    2BC9            SUB ECX,ECX
004120CB    2148 04         AND DWORD PTR DS:[EAX+4],ECX             ; 清除斷點
004120CE    2148 08         AND DWORD PTR DS:[EAX+8],ECX
004120D1    2148 0C         AND DWORD PTR DS:[EAX+C],ECX
004120D4    2148 10         AND DWORD PTR DS:[EAX+10],ECX
004120D7    8160 14 F00FFFF>AND DWORD PTR DS:[EAX+14],FFFF0FF0
004120DE    C740 18 5501000>MOV DWORD PTR DS:[EAX+18],155
004120E5    33C0            XOR EAX,EAX
004120E7    C3              RETN
……
004120E9    8B5424 08       MOV EDX,DWORD PTR SS:[ESP+8]
004120ED    8142 04 1B00000>ADD DWORD PTR DS:[EDX+4],1B              ; 這裡又異常了,看來作者也等不及了,哈哈
004120F4    EB 01           JMP SHORT 004120F7
……
00412142    8DBD 35314000   LEA EDI,DWORD PTR SS:[EBP+403135]        ; EDI=4106E5
00412148    B9 240C0000     MOV ECX,0C24                             ; 又準備從4106E5處解壓程式碼,大小為0C24
……
0041217C    AA              STOS BYTE PTR ES:[EDI]
0041217D  ^ E2 D7           LOOPD SHORT 00412156                     ; 如果沒有解壓完就跳回去
……
004105E1    68 07000000     PUSH 7
004105E6    5B              POP EBX                                  ; mov ebx,7
……
004105E7    25 25382C37     AND EAX,372C3825
又回來解密一層
00411D55    64:8923         MOV DWORD PTR FS:[EBX],ESP
00411D58    83E0 00         AND EAX,0
00411D5B    64:3343 30      XOR EAX,DWORD PTR FS:[EBX+30]            ; 暈哦,作者這裡連來幾個異常
一堆垃圾過後到第七個異常處
……
004104CE   /75 0F           JNZ SHORT 004104DF                       ; 這裡不相等
004104D0   |8181 B8000000 B>ADD DWORD PTR DS:[ECX+B8],18BF           ; 這裡再次改東西
記住改後的地址,然後在那個地址處下斷:
00411F81    2BC0            SUB EAX,EAX
00411F83    90              NOP
00411F84    90              NOP
00411F85    90              NOP
00411F86    90              NOP
00411F87    90              NOP
00411F88    90              NOP
00411F89    90              NOP
00411F8A    90              NOP
00411F8B    90              NOP
00411F8C    64:8F00         POP DWORD PTR FS:[EAX]
00411F8F    58              POP EAX
00411F90    5D              POP EBP
00411F91    8D85 35314000   LEA EAX,DWORD PTR SS:[EBP+403135]        ; mov EAX,4106E5
00411F97    68 240C0000     PUSH 0C24
00411F9C    59              POP ECX                                  ; mov ECX,0C24
00411F9D    68 9952B30E     PUSH 0EB35299
00411FA2    5A              POP EDX
00411FA3    D1EA            SHR EDX,1
00411FA5    73 06           JNB SHORT 00411FAD
00411FA7    81F2 32AF43ED   XOR EDX,ED43AF32                         ; 從4106E5 處解壓程式碼大小為0c24
00411FAD    3010            XOR BYTE PTR DS:[EAX],DL                 ; 這裡又解壓一層程式碼,tnnd壓的還真多
00411FAF    40              INC EAX
00411FB0  ^ E2 F1           LOOPD SHORT 00411FA3
00411FB2    2D 240C0000     SUB EAX,0C24
00411FB7    FFE0            JMP EAX                                  ; 解壓完後跳回去執行解壓後的程式碼
現在我會可以總結一下,在第七次異常後按CTRL+S找
SUB EAX,0C24
JMP EAX
處下斷就是了.
……
下慢慢跟,注意,過那jmp eax後就不要去除垃圾程式碼了,要不會異常的.
004122D6    B9 522D0000     MOV ECX,2D52                             ; 傳入將要VirutalAlloc的size 2D52
004122DB    8BD1            MOV EDX,ECX
004122DD    EB 07           JMP SHORT 004122E6
 
004122FA    96              XCHG EAX,ESI                             ; 分配出來的空間就是3E0000,把分配好的地址入esi中
004122FB    5A              POP EDX                                  ; 把要分配的大小2d52入edx中
004122FC    BF F0D30000     MOV EDI,0D3F0
00412301    81C7 00004000   ADD EDI,00400000
00412307    56              PUSH ESI                                 ; push 3E0000
00412308    57              PUSH EDI                                 ; push 40D3F0
00412309    E8 83E7FFFF     CALL 00410A91                            ; 解壓程式碼到剛才分配的空間裡,這就是真正的Depack了,aplib v0.36的解壓程式碼.
0041230E    91              XCHG EAX,ECX                             ; 把解壓的大小傳入ecx,用於下面的複製程式碼
0041230F    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
00412311    5F              POP EDI                                  ; 操作完畢還原edi和esi的值
00412312    5E              POP ESI
00412313    EB 01           JMP SHORT 00412316
00412315    90              NOP
00412316    68 00400000     PUSH 4000
0041231B    52              PUSH EDX
0041231C    56              PUSH ESI
0041231D    FF95 22434000   CALL DWORD PTR SS:[EBP+404322]           ; 解壓程式碼完畢後,再次釋放剛申請的空間
00412323    EB 01           JMP SHORT 00412326
00412325    90              NOP

 

00412335    8338 00         CMP DWORD PTR DS:[EAX],0                 ; 判斷412370裡面有沒有東西,沒有就跳
00412338    0F84 95000000   JE 004123D3
0041233E    B9 C09D0000     MOV ECX,9DC0                             ; push size 9dc0
00412343    6A 04           PUSH 4
00412345    68 00300000     PUSH 3000
0041234A    51              PUSH ECX
0041234B    6A 00           PUSH 0                                   ; 準備再次申請空間
0041234D    FF95 1D434000   CALL DWORD PTR SS:[EBP+40431D]           ; VirtualAlloc

0012FF8C   00412353  /CALL to VirtualAlloc from PESpin.0041234D
0012FF90   00000000  |Address = NULL
0012FF94   00009DC0  |Size = 9DC0 (40384.)
0012FF98   00003000  |AllocationType = MEM_COMMIT|MEM_RESERVE
0012FF9C   00000004  \Protect = PAGE_READWRITE
……
0041238A    03BD D2424000   ADD EDI,DWORD PTR SS:[EBP+4042D2]        ; 暈哦,又脫一層馬甲:-)
00412390    BE 00009000     MOV ESI,900000
00412395    56              PUSH ESI
00412396    57              PUSH EDI
00412397    E8 F5E6FFFF     CALL 00410A91                            ; 這裡又進行apLib解壓程式碼.
004123B6    8B8D 8F4D4000   MOV ECX,DWORD PTR SS:[EBP+404D8F]        ; 解壓完畢,再次釋放剛才的空間900000
004123BC    8B85 E14D4000   MOV EAX,DWORD PTR SS:[EBP+404DE1]
004123C2    0BC0            OR EAX,EAX
004123C4    74 0D           JE SHORT 004123D3
004123C6    68 00400000     PUSH 4000
004123CB    51              PUSH ECX                                 ; push size
004123CC    56              PUSH ESI                                 ; push address
004123CD    FF95 22434000   CALL DWORD PTR SS:[EBP+404322]           ; kernel32.VirtualFree
……
0012FF90   004123D3  /CALL to VirtualFree from PESpin.004123CD
0012FF94   00900000  |Address = 00900000
0012FF98   00009DC0  |Size = 9DC0 (40384.)
0012FF9C   00004000  \FreeType = MEM_DECOMMIT
……
0012FF88   00411C71  /CALL to VirtualProtect from PESpin.00411C6E
0012FF8C   004001C8  |Address = PESpin.004001C8
0012FF90   0000025C  |Size = 25C (604.)
0012FF94   00000040  |NewProtect = PAGE_EXECUTE_READWRITE
0012FF98   004124D8  \pOldProtect = PESpin.004124D8
透過VirtualProtect來把段改為可以讀寫執行的屬性.
00411C9D    C643 02 C3      MOV BYTE PTR DS:[EBX+2],0C3
00411CA1    53              PUSH EBX
再小心一點到最後一個異常:
0012FF94   0012FFE0  Pointer to next SEH record
0012FF98   00411CD6  SE handler
在411cd6處下斷:
00411CD6    2BDB            SUB EBX,EBX
00411CD8    8B6424 08       MOV ESP,DWORD PTR SS:[ESP+8]
00411CDC    64:8F03         POP DWORD PTR FS:[EBX]
……
00411D0F    B9 2E000000     MOV ECX,2E
00411D14    FF1401          CALL DWORD PTR DS:[ECX+EAX]              ; 這裡用GetTickCount不知道起什麼作用來的
00411D23    59              POP ECX                                  ; mov ECX,87
00411D24    66:35 4C50      XOR AX,504C
00411D28    66:05 8911      ADD AX,1189
00411D2C    AA              STOS BYTE PTR ES:[EDI]                   ; 到了這裡還要解壓程式碼
……
00410D3A    8000 81         ADD BYTE PTR DS:[EAX],81
00410D3D    E9 0F000000     JMP 00410D51                             ; 如果加殼時選擇了檢測測試器的話,這裡會跳去一個int3處
00410D42    C9              LEAVE
00410D43    E8 76000000     CALL 00410DBE
00410D48    0BC0            OR EAX,EAX                               ; PesPin到現在還不檢測OD的存在,不知道為什麼
00410D4A  ^ 74 ED           JE SHORT 00410D39                        ; 只是用了兩個int3來檢測SICE而已
00410D4C  - E9 7217FF35     JMP 364024C3
00410D51    EB 01           JMP SHORT 00410D54                       ; 加了或沒加檢測偵錯程式都一定會來這裡的.
00410D53    90              NOP
……
00410D54    68 B95734E1     PUSH E13457B9                            ; 這裡作者還要來騙一下我們
00410D59    EB 01           JMP SHORT 00410D5C
00410D5B    90              NOP
00410D5C    59              POP ECX                                  ; 這裡mov ECX,E1345789
00410D5D    90              NOP
……
00410D6E    81E9 B95734E1   SUB ECX,E13457B9                         ; 這裡又減回去,不就是白做了嘛.
00410D74    0BC9            OR ECX,ECX
00410D76    EB 01           JMP SHORT 00410D79
……
00410D79    9C              PUSHFD
00410D7A    C12C24 06       SHR DWORD PTR SS:[ESP],6
00410D7E    832424 01       AND DWORD PTR SS:[ESP],1
00410D82    50              PUSH EAX
00410D83    52              PUSH EDX
00410D84    B8 066F7579     MOV EAX,79756F06
00410D89    05 51918A86     ADD EAX,868A9151
00410D8E    F76424 08       MUL DWORD PTR SS:[ESP+8]                 ; 又是垃圾程式碼來的
00410D92    8D8428 F9374000 LEA EAX,DWORD PTR DS:[EAX+EBP+4037F9]
00410D99    894424 08       MOV DWORD PTR SS:[ESP+8],EAX
00410D9D    5A              POP EDX
00410D9E    58              POP EAX
00410D9F    8D6424 04       LEA ESP,DWORD PTR SS:[ESP+4]             ; 這裡我就有點搞不懂了,直接用jmp [esp]不行嗎?最多後面加一個add esp,4
00410DA3    FF6424 FC       JMP DWORD PTR SS:[ESP-4]                 ; 這不是浪費程式碼嗎?
……
00410E09   .  F685 3E4E4000 0>TEST BYTE PTR SS:[EBP+404E3E],1
00410E10   .  74 40           JE SHORT 00410E52
00410E12   .  BB 3C080000     MOV EBX,83C
00410E17   .  0BDB            OR EBX,EBX                                ;如果是VB的程式的話,殼就是mov ebx,0了
00410E19   .  74 37           JE SHORT 00410E52                        ;  這裡就是jmp來的,因為上面賦值了,所以這裡不可能跳的
00410E1B   .  2BC0            SUB EAX,EAX                              ;  eax清0
00410E1D   .  2185 E0424000   AND DWORD PTR SS:[EBP+4042E0],EAX
00410E23   .  E8 01000000     CALL 00410E29
00410E28   .  90              NOP
00410E29   $  59              POP ECX                                  ;  MOV ECX,410E28
00410E2A   .  6A 40           PUSH 40
00410E2C   .  68 00300000     PUSH 3000
00410E31   .  53              PUSH EBX                                 ;  PUSH SIZE 83C
00410E32   .  50              PUSH EAX
00410E33   .  8D6424 FC       LEA ESP,DWORD PTR SS:[ESP-4]
00410E37   .  81C1 23000000   ADD ECX,23
00410E3D   .  890C24          MOV DWORD PTR SS:[ESP],ECX               ;  PUSH ECX,也就是push 要返回的地址
00410E40   .- FFA5 1D434000   JMP DWORD PTR SS:[EBP+40431D]            ;  VirtualAlloc申請一個記憶體空間

0012FF90   00410E4B  /CALL to VirtualAlloc
0012FF94   00000000  |Address = NULL
0012FF98   0000083C  |Size = 83C (2108.)
0012FF9C   00003000  |AllocationType = MEM_COMMIT|MEM_RESERVE
0012FFA0   00000040  \Protect = PAGE_EXECUTE_READWRITE
……
00410E4B      50              PUSH EAX                                 ;  申請到的空間900000入棧
00410E4C      8F85 D8424000   POP DWORD PTR SS:[EBP+4042D8]            ;  MOV [EBP+4042D8],900000
00410E52      90              NOP                                      ;  MOV 410E19,900000
……
00410E66   .  E8 01000000     CALL 00410E6C
00410E6B   .  90              NOP
00410E6C   $  83C4 04         ADD ESP,4
00410E6F   .  8BB5 393B4000   MOV ESI,DWORD PTR SS:[EBP+403B39]        ;  輸入表RVA起始地址
00410E75   .  03B5 D2424000   ADD ESI,DWORD PTR SS:[EBP+4042D2]        ;  轉換為VA==40A160
00410E7B   .  90              NOP
……
00410E8C   .  3BB5 D2424000   CMP ESI,DWORD PTR SS:[EBP+4042D2]        ;  判斷輸入表的起始地址和ImageBase是否相等
00410E92   .  90              NOP
00410E93   .  90              NOP
00410E94   .  90              NOP
00410E9E   .  75 0F           JNZ SHORT 00410EAF                       ;  如果不相等則跳
00410EA0   .  90              NOP
00410EAF   >  817E 10 C8FB000>CMP DWORD PTR DS:[ESI+10],0FBC8          ;  比較ThunkRVA(A028)是否為0FBC8
00410EB6   . |9C              PUSHFD
00410EB7   . |EB 01           JMP SHORT 00410EBA
00410EB9     |90              NOP
00410EBA   > |C12C24 06       SHR DWORD PTR SS:[ESP],6
00410EBE   . |832424 01       AND DWORD PTR SS:[ESP],1
00410EC2   . |50              PUSH EAX                                 ;  保護好EAX
00410EC3   . |52              PUSH EDX
00410EC4   . |B8 9C7791BE     MOV EAX,BE91779C
00410EC9   . |05 798A6E41     ADD EAX,416E8A79
00410ECE   . |F76424 08       MUL DWORD PTR SS:[ESP+8]
00410ED2   . |8D8428 38394000 LEA EAX,DWORD PTR DS:[EAX+EBP+403938]
00410ED9   . |894424 08       MOV DWORD PTR SS:[ESP+8],EAX             ;  將要跳去的地方410EE8
00410EDD   . |5A              POP EDX
00410EDE   . |58              POP EAX                                  ;  還原現場
00410EDF      8D6424 04       LEA ESP,DWORD PTR SS:[ESP+4]             ;  又來讓我們的CPU加負擔了:-)
00410EE3   .  FF6424 FC       JMP DWORD PTR SS:[ESP-4]                 ;  jmp 410EE8
00410EE7      90              NOP
00410EE8   .  8B5E 0C         MOV EBX,DWORD PTR DS:[ESI+C]             ;  定位輸入表的NAME==A4C4
00410EEB   .  039D D2424000   ADD EBX,DWORD PTR SS:[EBP+4042D2]        ;  轉換成VA==40A4C4
00410EF1   .  8BFB            MOV EDI,EBX                              ;  把Name入EDI中
00410EF3   .  E8 6B0F0000     CALL 00411E63                            ;  取出NAME來,我們可以進去看看
00411E63  /$  57              PUSH EDI                                 ;  保護 EDI(Name的值)
00411E64  |>  800F 00         /OR BYTE PTR DS:[EDI],0                  ;  如果取完了Name就返回
00411E67  |.  74 16           |JE SHORT 00411E7F
00411E69  |.  90              |NOP
00411E6A  |.  90              |NOP
00411E6B  |.  90              |NOP
00411E6C  |.  90              |NOP
00411E6D  |.  90              |NOP
00411E6E  |.  90              |NOP
00411E6F  |.  90              |NOP
00411E70  |.  90              |NOP
00411E71  |.  90              |NOP
00411E72  |.  90              |NOP
00411E73  |.  90              |NOP
00411E74  |.  90              |NOP
00411E75  |.  90              |NOP
00411E76  |.  90              |NOP
00411E77  |.  90              |NOP
00411E78  |.  90              |NOP
00411E79  |.  90              |NOP
00411E7A  |.  F617            |NOT BYTE PTR DS:[EDI]                   ;  NAMAE就是透過取反來還原NAME
00411E7C  |.  47              |INC EDI
00411E7D  |.^ EB E5           \JMP SHORT 00411E64
00411E7F  |>  5F              POP EDI                                  ;  恢復現場
00411E80  \.  C3              RETN

00410EF8    E8 01000000       CALL 00410EFE
00410EFD    90                NOP
00410EFE    58                POP EAX                                  ; MOV EAX,410EFD
00410EFF    53                PUSH EBX                                 ; push NAME
00410F00    50                PUSH EAX
00410F01    FFB5 04434000     PUSH DWORD PTR SS:[EBP+404304]           ; push LoadLibraryA
00410F07    814424 04 1400000>ADD DWORD PTR SS:[ESP+4],14              ; push返回地址410EFD+14=410F11
00410F0F    C3                RETN
00410F10    90                NOP
00410F11    85C0              TEST EAX,EAX                             ; 這是個人覺得應該是BUG來的吧,怎麼不先GetModuleHandleA先呢
00410F13    0F84 31080000     JE 0041174A                              ; 如果載入失敗就去出錯的地方
00410F19    E8 01000000       CALL 00410F1F
00410F1E    90                NOP
00410F1F    59                POP ECX                                  ; MOV ECX,EIP-1
00410F20    50                PUSH EAX                                 ; PUSH hmodule
00410F21    51                PUSH ECX
00410F22    55                PUSH EBP
00410F23    810424 AE324000   ADD DWORD PTR SS:[ESP],004032AE          ; push 41085E
00410F2A    814424 04 2200000>ADD DWORD PTR SS:[ESP+4],22              ; 先進41085E然後返回到410F40處
00410F32    C3                RETN                                     ; 返回41085E處,進去後獲取相關DLL的輸出表資訊
……
00410862    5A                POP EDX                                  ; 把hmodule入edx中
00410863    41                INC ECX
00410864    51                PUSH ECX                                 ; push 410F41這裡改變後就是返回到410F41了
00410865    57                PUSH EDI                                 ; push Name
00410866    53                PUSH EBX
00410867    8995 31334000     MOV DWORD PTR SS:[EBP+403331],EDX        ; 把hmodule儲存到[EBP+403331]==4108E1處
0041086D    8BDA              MOV EBX,EDX
0041086F    0352 3C           ADD EDX,DWORD PTR DS:[EDX+3C]            ; 定位e_lfnew(定位pe頭)
00410872    FF72 7C           PUSH DWORD PTR DS:[EDX+7C]
00410875    8F85 29334000     POP DWORD PTR SS:[EBP+403329]            ; 輸出表的size入[EBP+403329](4108d9)處
0041087B    8B52 78           MOV EDX,DWORD PTR DS:[EDX+78]            ; 定位輸出表
0041087E    03D3              ADD EDX,EBX                              ; 把輸出表轉換成VA
00410880    52                PUSH EDX
00410881    8F85 25334000     POP DWORD PTR SS:[EBP+403325]            ; 輸出表起始地址入[EBP+403325](4108d5]處
00410887    90                NOP
00410887    90                NOP
00410888    90                NOP
00410889    90                NOP
0041088A    90                NOP
0041088B    90                NOP
0041088C    90                NOP
0041088D    90                NOP
0041088E    90                NOP
0041088F    90                NOP
00410890    FF72 20           PUSH DWORD PTR DS:[EDX+20]               ; AddressOfNames
00410893    5F                POP EDI
00410894    03FB              ADD EDI,EBX                              ; AddresOfNames轉換成VA
00410896    57                PUSH EDI
00410897    8F85 35334000     POP DWORD PTR SS:[EBP+403335]
0041089D    FF72 18           PUSH DWORD PTR DS:[EDX+18]               ; NumberOfNames
004108A0    8F85 E8334000     POP DWORD PTR SS:[EBP+4033E8]
004108A6    EB 01             JMP SHORT 004108A9
004108A8    90                NOP
004108A9    FF72 1C           PUSH DWORD PTR DS:[EDX+1C]               ; AddressofFunctions
004108AC    5F                POP EDI
004108AD    03FB              ADD EDI,EBX                              ; AddressOfFunctions轉為VA
004108AF    57                PUSH EDI
004108B0    8F85 39334000     POP DWORD PTR SS:[EBP+403339]            ; 輸出表的AddressOfFunctions 入[EBP+403339]
004108B6    FF72 24           PUSH DWORD PTR DS:[EDX+24]               ; AddressOfNamesOrdinals
004108B9    5F                POP EDI
004108BA    03FB              ADD EDI,EBX
004108BC    57                PUSH EDI
004108BD    8F85 2D334000     POP DWORD PTR SS:[EBP+40332D]            ; 輸出表的AddressOfNamesOrdinals 入[EBP+40332D](004108DD)
004108C3    FF72 10           PUSH DWORD PTR DS:[EDX+10]               ; nBase
004108C6    8F85 53334000     POP DWORD PTR SS:[EBP+403353]            ; 輸出表的Base  入[EBP+403353](00410903)
004108CC    EB 01             JMP SHORT 004108CF                       ; 獲取完畢回去操作
第一次是KERNEL32.DLL函式
輸出表的SIZE 00006B39入[EBP+403329](4108d9)
輸出表起始地址77EAD040入[EBP+403325](4108d5]
輸出表的AddressOfNames 77EAD2F0入[EBP+403335](4108E5)
輸出表的NumberOfNames 03AE入[EBP+4033E8](00410998)
輸出表的AddressOfFunctions 77EAD068入[EBP+403339](004108E9)
輸出表的AddressOfNamesOrdinals 77EAEDD8入[EBP+40332D](004108DD)
輸出表的Base 1 入[EBP+403353](00410903)

00410F41    2BD2              SUB EDX,EDX                              ; 清除EDX,這樣的方式不會改變標誌的
……
00410F70    800B 00           OR BYTE PTR DS:[EBX],0                   ; 取完那個DLL後就把函式再給清除掉
00410F73    74 0D             JE SHORT 00410F82                        ; 如果清完了就跳
00410F75    8813              MOV BYTE PTR DS:[EBX],DL
00410F77    C1C2 04           ROL EDX,4
00410F7A    90                NOP
00410F7B    90                NOP
00410F7C    90                NOP
00410F7D    43                INC EBX
00410F7E  ^ FF6424 FC         JMP DWORD PTR SS:[ESP-4]                 ; 這裡跳回去直到函式名已經清除完了
……
00410F83    8B56 10           MOV EDX,DWORD PTR DS:[ESI+10]            ; 把ThunkRVA入EDX中,並轉成VA
00410F86    0395 D2424000     ADD EDX,DWORD PTR SS:[EBP+4042D2]
00410F8C    830A 00           OR DWORD PTR DS:[EDX],0                  ; 判斷有沒有操作完相關的API,操作完了就跳
00410F8F    0F84 32010000     JE 004110C7
00410F95    90                NOP
00410F96    90                NOP
……
00410FB6    0385 D2424000     ADD EAX,DWORD PTR SS:[EBP+4042D2]        ; TunkValue轉換成VA
00410FBC    97                XCHG EAX,EDI                             ; ThunkVlue入edi,
00410FBD    68 7AF3D0F9       PUSH F9D0F37A
00410FC2    012C24            ADD DWORD PTR SS:[ESP],EBP
00410FC5    810424 B4466F06   ADD DWORD PTR SS:[ESP],66F46B4
00410FCC    68 D476630F       PUSH 0F6376D4
00410FD1    812C24 9643230F   SUB DWORD PTR SS:[ESP],0F234396
00410FD8    012C24            ADD DWORD PTR SS:[ESP],EBP
00410FDB    C3                RETN                                     ; 跳去填充API函式里,相當於我們的GetProcAddress
進入後發現和以前的版本沒什麼很大的變化.
……
004108F8    0BFF              OR EDI,EDI                               ; 判斷ThunkValue是不是為空,不是則跳
004108FA    75 19             JNZ SHORT 00410915
……
00410921    8B9D 35334000     MOV EBX,DWORD PTR SS:[EBP+403335]        ; 輸出表的AddresOfNames入EBX
00410927    8A47 FF           MOV AL,BYTE PTR DS:[EDI-1]
……
00410959    8B3B              MOV EDI,DWORD PTR DS:[EBX]               ; 迴圈搜尋相關DLL的輸出表
0041095B    03BD 31334000     ADD EDI,DWORD PTR SS:[EBP+403331]        ; 取出的輸出表轉換成VA
…….
00410964   /75 2C           JNZ SHORT 00410992
00410966   |E8 B0100000     CALL 00411A1B
0041096B   |3D F7DEBCA1     CMP EAX,A1BCDEF7
00410970   |75 20           JNZ SHORT 00410992
00410972   |8B85 2D334000   MOV EAX,DWORD PTR SS:[EBP+40332D]        ; 迴圈得到程式所要的API,找到後到這裡
00410978   |D1E1            SHL ECX,1
0041097A   |03C1            ADD EAX,ECX
0041097C   |0FB700          MOVZX EAX,WORD PTR DS:[EAX]
0041097F   |C1E0 02         SHL EAX,2
00410982   |0385 39334000   ADD EAX,DWORD PTR SS:[EBP+403339]
00410988   |8B00            MOV EAX,DWORD PTR DS:[EAX]
0041098A   |0385 31334000   ADD EAX,DWORD PTR SS:[EBP+403331]        ; 把API地址轉換成VA
00410990   |EB 10           JMP SHORT 004109A2
004109A2    8BBD 25334000   MOV EDI,DWORD PTR SS:[EBP+403325]
004109A8    3BC7            CMP EAX,EDI                              ; EAX就是取出的API了
004109AA    76 35           JBE SHORT 004109E1                       ; 這裡要跳了,要不然,殼還要"照顧"的
這裡改成:
004109AA   /EB 35           JMP SHORT 004109E1        
……..
004109E3    90              NOP
004109E4    894424 1C       MOV DWORD PTR SS:[ESP+1C],EAX            ; 這裡又我們透過跟蹤知道改成mov ss:[edx],eax就是傳入正確的API
所以這裡改成:
004109E4    36:8902         MOV DWORD PTR SS:[EDX],EAX            
004109E7    90              NOP

004109E8    61              POPAD
004109E9    FF0424          INC DWORD PTR SS:[ESP]                   ; 把上面要返回的地址+1(410FDF)
004109EC    0BC0            OR EAX,EAX
……
00411085    90              NOP
00411086    E8 ECF6FFFF     CALL 00410777
0041108B    0BE4            OR ESP,ESP
0041108D    90              NOP
0041108E    90              NOP
0041108F    90              NOP
0041109C    E8 51F9FFFF     CALL 004109F2                            ; 這裡進去將再改填充API
004110A1    90              NOP
跟進看看:
……
00410A0B    90              NOP
00410A0C    BF 96844000     MOV EDI,00408496                         ; 傳入Address
00410A11    EB 01           JMP SHORT 00410A14
00410A13    90              NOP
00410A14    B9 86010000     MOV ECX,186                              ; 傳入size
…….
00410A29    90              NOP
00410A2A    3917            CMP DWORD PTR DS:[EDI],EDX
00410A2C    74 0D           JE SHORT 00410A3B
00410A2E    47              INC EDI
00410A2F    EB 01           JMP SHORT 00410A32
00410A31    90              NOP
00410A32  ^ E2 F6           LOOPD SHORT 00410A2A
00410A34    EB 01           JMP SHORT 00410A37
00410A36    90              NOP
00410A37    8902            MOV DWORD PTR DS:[EDX],EAX               ; 這裡又想破壞輸入表,也nop掉
00410A39    EB 4E           JMP SHORT 00410A89
00410A3B    90              NOP
……
00410A5A    90              NOP
00410A5B    807F FF EA      CMP BYTE PTR DS:[EDI-1],0EA
00410A5F  ^ 75 D6           JNZ SHORT 00410A37
00410A61    90              NOP                                      ; 這裡要改成這樣子,傳入FF25
00410A62    90              NOP
00410A63    90              NOP
00410A64    90              NOP
00410A65    90              NOP                                      ; 因為加殼的時候殼把FF25改成了FFEA
00410A66    90              NOP
00410A67    90              NOP
00410A68    90              NOP
00410A69    90              NOP
00410A6A    FE4F FF         DEC BYTE PTR DS:[EDI-1]                  ; 這裡開始nop掉
00410A6D    83C7 04         ADD EDI,4
00410A70    2BC7            SUB EAX,EDI
00410A72    8947 FC         MOV DWORD PTR DS:[EDI-4],EAX
00410A75    EB 12           JMP SHORT 00410A89
改好後:
00410A5A    90              NOP
00410A5B    807F FF EA      CMP BYTE PTR DS:[EDI-1],0EA
00410A5F  ^ 75 D6           JNZ SHORT 00410A37
00410A61    66:C747 FE FF25 MOV WORD PTR DS:[EDI-2],25FF             ; 這裡要改成這樣子,傳入FF25
00410A67    90              NOP
00410A68    90              NOP
00410A69    90              NOP
00410A6A    90              NOP                                      ; 這裡開始nop掉
00410A6B    90              NOP
00410A6C    90              NOP
00410A6D    90              NOP
00410A6E    90              NOP
00410A6F    90              NOP
00410A70    90              NOP
00410A71    90              NOP
00410A72    90              NOP
00410A73    90              NOP
00410A74    90              NOP
00410A75    EB 12           JMP SHORT 00410A89
……
00410A83    90              NOP
00410A84    8907            MOV DWORD PTR DS:[EDI],EAX               ; 這裡也是破壞輸入表的,清除之
00410A86    EB 01           JMP SHORT 00410A89
好了,輸入表處理完畢,進入下一個環節,還原殼所抽的程式碼.
……
0041114B    90               NOP
0041114C    90               NOP
0041114D    F3:              PREFIX REP:                              ; 透過RDTSC檢測反跟蹤,這是最後一個反跟蹤了
0041114E    0F31             RDTSC
00411150    50               PUSH EAX
00411151    F3:              PREFIX REP:                              ; Superfluous prefix
00411152    0F31             RDTSC
00411154    EB 01            JMP SHORT 00411157
00411156    90               NOP
……
00411191    8D6424 04        LEA ESP,DWORD PTR SS:[ESP+4]
00411195    FF6424 FC        JMP DWORD PTR SS:[ESP-4]                 ; 如果沒發現就去正常執行程式處
00411199    90               NOP
0041119A    2200             AND AL,BYTE PTR DS:[EAX]
0041119C    0000             ADD BYTE PTR DS:[EAX],AL
0041119E    85C0             TEST EAX,EAX
004111A0    75 1F            JNZ SHORT 004111C1
004111A2    74 34            JE SHORT 004111D8
004111A4    F8               CLC
004111A5    83C9 FF          OR ECX,FFFFFFFF                          ; 發現的話到這裡就掛
004111A8    F3:AB            REP STOS DWORD PTR ES:[EDI]
004111AA    E8 1C000000      CALL 004111CB
……
004111CE    90               NOP
004111CF    90               NOP
004111D0    B8 7B4D5F0E      MOV EAX,0E5F4D7B                         ; 如果沒有發現跟蹤的話就跳到這裡
004111D5    90               NOP
……
004111FB   /74 45            JE SHORT 00411242
004111FD   |BE F4244100      MOV ESI,004124F4
00411202   |B9 5C020000      MOV ECX,25C                              ; 傳入SIZE也就是殼所抽的程式碼的大小
00411207   |51               PUSH ECX
00411208   |B0 3C            MOV AL,3C
0041120A   |304431 FF        XOR BYTE PTR DS:[ECX+ESI-1],AL           ; 還原殼所抽的程式碼,這個不是程式的入口那一點哦
0041120E   |90               NOP
0041120F   |90               NOP
00411210   |90               NOP
00411211   |90               NOP
00411212   |90               NOP
00411213   |90               NOP
00411214   |90               NOP
00411215   |90               NOP
00411216   |90               NOP
00411217   |90               NOP
00411218   |90               NOP
00411219   |90               NOP
0041121A   |004C31 FF        ADD BYTE PTR DS:[ECX+ESI-1],CL
0041121E  ^|E2 EA            LOOPD SHORT 0041120A
……
00411231    90               NOP
00411232    BF C8014000      MOV EDI,004001C8                         ; 這裡處理殼所抽的程式碼,俺是在這裡動的手腳,具體怎麼改我就不講,以免賣弄之嫌(看看我已經脫好的就怎麼怎麼改的).
00411237    90               NOP
00411238    90               NOP
00411239    90               NOP
0041123A    90               NOP
0041123B    90               NOP
0041123C    90               NOP
0041123D    90               NOP
0041123E    90               NOP
0041123F    90               NOP
00411240    F3:A4            REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>; 把程式碼放到PE HEADER部分,夠狠
……
00411279    61               POPAD                                    ; 解壓完畢,執行程式程式碼
0041127A    BA 0F5C8CCE      MOV EDX,CE8C5C0F                         ; 終於著陸了;-)
0041127F    EB 01            JMP SHORT 00411282
00411281    90               NOP
00411282    81F2 753DE58A    XOR EDX,8AE53D75

看看程式裡面的東西,哈哈,抽的不錯嘛,於是乎,動手亂寫一下修復指令碼.
……
var addr
var addrl
var addrt
var addrt1
var addr40
var addrt2

start:
  mov addr,4101c6        //寫的比較亂,但願你能看懂:-)


lbl1:                //修復程式碼一
  cmp addr,410430
  jae lbl2
  find addr,#E9#
  mov addr,$RESULT
  mov addrt,addr
  mov addrt1,addr
  mov addr40,addr
  sub addr40,10000
  add addr40,5
  dec addrt        
  inc addrt1
  mov addrt1,[addrt1]
  add addr40,addrt1
  mov addrl,addr40
  add addrt,5
  sub addrt,addrl
  mov addrt2,FFFFFFFF
  sub addrt2,addrt
  inc addr
  mov [addr],addrt2
 jmp lbl1

lbl2:                //修復程式碼二
  repl 401000,#E8??81FFFF#,#E8??810000#,8b24
  repl 401000,#E9??81FFFF#,#E9??810000#,8b24

  repl 401000,#E8??82FFFF#,#E8??820000#,8b24
  repl 401000,#E9??82FFFF#,#E9??820000#,8b24

  repl 401000,#E8??83FFFF#,#E8??830000#,8b24
  repl 401000,#E9??83FFFF#,#E9??830000#,8b24
  ret
 ret
好了,現在到了最後一步了,把jmp表全部下一個地址,也就是這樣子.
00408495      90            NOP
00408496   $- FF25 88A04000 JMP DWORD PTR DS:[<&kernel32.CloseHandle>;  kernel32.CloseHandle
0040849C   $- FF25 78A04000 JMP DWORD PTR DS:[<&kernel32.CopyFileA>] ;  kernel32.CopyFileA
好了,現在dump再用import REC修復一下輸入表就行了。至於stolencode可以找也可以不用,這麼簡單的幾行,我自己就不再補上去(要補也簡單,看一眼就知道怎麼改).
OK,殼到此脫完了,謝謝你能夠堅持把文章看完!
BTW:自己脫了後,看了一下FLY的已脫程式,感觸很深的,他真是頭大牛來的!努力向他學習才行.
因時間比較緊,發了幾天的時間才寫完了這篇文章.文章不足之處還請指正.


Greetz:

Fly,Jingulong,yock,tDasm,David,ahao,vcasm,UFO(brother),alan(sister),heXpe,hexer, all of my friends and you!
                            
Welcome to:
----====China Decrytpion Fans Cracking Group====----
http://www.chinadfcg.com
----====Free Cracking Group====----
http://www.fcgchina.com
----====Unpacking Sage(China Unpacking Group)====----

                            By loveboom[DFCG][FCG]
                            Email:bmd2chen#tom.com

相關文章