ASPACK外殼一點分析

看雪資料發表於2004-08-12

【目    標】:隨便抓了個ASPACK2.12加的DLL來看看而已
【工    具】:Olydbg1.1,lordpe,imp.
【任    務】:ASPACK2.12的粗略反向(可惜壓縮部分沒有去反)
【操作平臺】:WINXP pro sp1 
【作    者】:loveboom[DFCG][FCG][US]
【例項下載】: 點選下載(或滑鼠右鍵另存為)
【簡要說明】:這麼久沒寫任何東西也不說什麼好,煩人的事太多,也嚴重懷疑自己不懂怎麼脫殼了?其它的東西也不想說太多,這篇文章也是斷斷繼繼寫出來的。如有什麼不足之處,請多指教。
【詳細過程】:
也沒什麼特別的設定,因為是PACKER來的,所以不用擔心你的OD掛的.用OD載入,然後分析之.
1001F001 >  60              PUSHAD                                   ; 殼入口
1001F002    E8 03000000     CALL cesi.1001F00A
1001F007    90              NOP                                      ; 花指令,nop掉
1001F008    EB 04           JMP SHORT cesi.1001F00E
1001F00A    5D              POP EBP
1001F00B    45              INC EBP
1001F00C    55              PUSH EBP
1001F00D    C3              RETN
1001F00E    E8 01000000     CALL cesi.1001F014
1001F013    90              NOP                                      ; 花指令
1001F014    5D              POP EBP                                  ; 這裡就相關於mov ebp,[esp]
1001F015    BB EDFFFFFF     MOV EBX,-13
1001F01A    03DD            ADD EBX,EBP
1001F01C    81EB 00F00100   SUB EBX,1F000                            ; 這幾步運算就是計算當然段的IMAGEBASE
1001F022    83BD 22040000 0>CMP DWORD PTR SS:[EBP+422],0             ; 比較[EBP+422]處有沒有東西,如果有就掉去結束處
1001F029    899D 22040000   MOV DWORD PTR SS:[EBP+422],EBX           ; 這裡給[EBP+422]賦上當前段的CODEBASE
1001F02F    0F85 65030000   JNZ cesi.1001F39A                        ; 如果已經解壓完畢就準備跳去oep處了
1001F035    8D85 2E040000   LEA EAX,DWORD PTR SS:[EBP+42E]           ; 把kernel32.dll賦值給eax,用於後面的取API函式
1001F03B    50              PUSH EAX
1001F03C    FF95 4D0F0000   CALL DWORD PTR SS:[EBP+F4D]              ; 這裡就是GetModuleHandleA,用來取kernel32.dll的BASE
1001F042    8985 26040000   MOV DWORD PTR SS:[EBP+426],EAX           ; 把Module Base放到[ebp+426]處
1001F048    8BF8            MOV EDI,EAX                              ; 同時把BASE移入edi中,這裡取出的BASE==77E40000
1001F04A    8D5D 5E         LEA EBX,DWORD PTR SS:[EBP+5E]            ; [ebp+5E]處存放了VirtualAlloc
1001F04D    53              PUSH EBX                                 ; 字串地址入棧
1001F04E    50              PUSH EAX                                 ; base入棧
1001F04F    FF95 490F0000   CALL DWORD PTR SS:[EBP+F49]              ; 這裡GetProcAddress取VirtualAlloc的地址
1001F055    8985 4D050000   MOV DWORD PTR SS:[EBP+54D],EAX           ; 取出的地址入[EBP+54D]處
1001F05B    8D5D 6B         LEA EBX,DWORD PTR SS:[EBP+6B]            ; 取VirtualFree字串
1001F05E    53              PUSH EBX                                 ; 字串地址入棧
1001F05F    57              PUSH EDI                                 ; BASE入棧,準備取VirtualFree的地址了
1001F060    FF95 490F0000   CALL DWORD PTR SS:[EBP+F49]              ; GetProcAddress取VirtualFree的地址
1001F066    8985 51050000   MOV DWORD PTR SS:[EBP+551],EAX           ; 取到的地址入[EBP+551]處
1001F06C    8D45 77         LEA EAX,DWORD PTR SS:[EBP+77]            ; 看到上面ebp的值了吧,也就eax=1001f013+77
1001F06F    FFE0            JMP EAX                                  ; 這裡就是跳去1001f08A的說
1001F071    56              PUSH ESI
1001F072    6972 74 75616C4>IMUL ESI,DWORD PTR DS:[EDX+74],416C6175
1001F079    6C              INS BYTE PTR ES:[EDI],DX                 ; I/O command
1001F07A    6C              INS BYTE PTR ES:[EDI],DX                 ; I/O command
1001F07B    6F              OUTS DX,DWORD PTR ES:[EDI]               ; I/O command
1001F07C    6300            ARPL WORD PTR DS:[EAX],AX
1001F07E    56              PUSH ESI
1001F07F    6972 74 75616C4>IMUL ESI,DWORD PTR DS:[EDX+74],466C6175
1001F086    72 65           JB SHORT cesi.1001F0ED
1001F088    90              NOP
1001F089    90              NOP
1001F08A    8B9D 31050000   MOV EBX,DWORD PTR SS:[EBP+531]           ; 測試[EBP+531]處有沒有資料
1001F090    0BDB            OR EBX,EBX
1001F092    74 0A           JE SHORT cesi.1001F09E                   ; 如果還沒有資料的話就跳
1001F094    8B03            MOV EAX,DWORD PTR DS:[EBX]
1001F096    8785 35050000   XCHG DWORD PTR SS:[EBP+535],EAX
1001F09C    8903            MOV DWORD PTR DS:[EBX],EAX
1001F09E    8DB5 69050000   LEA ESI,DWORD PTR SS:[EBP+569]           ; 取text段的開始地址1000(Voffset)
1001F0A4    833E 00         CMP DWORD PTR DS:[ESI],0                 ; 比較[EBP+569]這個地址中有沒有資料,這個程式裡為1000
1001F0A7    0F84 21010000   JE cesi.1001F1CE                         ; 如果沒有資料就跳,下面準備申請空間了
1001F0AD    6A 04           PUSH 4                                   ; /Protect = PAGE_READWRITE
1001F0AF    68 00100000     PUSH 1000                                ; |AllocationType = MEM_COMMIT
1001F0B4    68 00180000     PUSH 1800                                ; |Size = 1800 (6144.)
1001F0B9    6A 00           PUSH 0                                   ; |Address = NULL
1001F0BB    FF95 4D050000   CALL DWORD PTR SS:[EBP+54D]              ; \VirtualAlloc
1001F0C1    8985 56010000   MOV DWORD PTR SS:[EBP+156],EAX           ; 上面自動分配後的地址為BC0000把這個地址儲存在[EBP+156]


1001F0C7    8B46 04         MOV EAX,DWORD PTR DS:[ESI+4]             ; 取text段的大小入EAX中
1001F0CA    05 0E010000     ADD EAX,10E                              ; 準備申請一個大小為text段大小+10E的空間(也就是申請一個

大小為A10E的空間)
1001F0CF    6A 04           PUSH 4                                   ; /Protect = PAGE_READWRITE
1001F0D1    68 00100000     PUSH 1000                                ; |AllocationType = MEM_COMMIT
1001F0D6    50              PUSH EAX                                 ; |Size = A10E (41230.)
1001F0D7    6A 00           PUSH 0                                   ; |Address = NULL(也就是自動分配)
1001F0D9    FF95 4D050000   CALL DWORD PTR SS:[EBP+54D]              ; \VirtualAlloc
1001F0DF    8985 52010000   MOV DWORD PTR SS:[EBP+152],EAX           ; 申請到的開始地址入[EBP+152]處(BD0000)
1001F0E5    56              PUSH ESI                                 ; /Address = ESI的地址裡儲存了text段的開始Voffset和Size
1001F0E6    8B1E            MOV EBX,DWORD PTR DS:[ESI]               ; |           把text段的Voffset入ebx
1001F0E8    039D 22040000   ADD EBX,DWORD PTR SS:[EBP+422]           ; |           用text段的開始地址加上當前段的CODEBASE

(100000000)
1001F0EE    FFB5 56010000   PUSH DWORD PTR SS:[EBP+156]              ; |VAddress1 = 第一次申請的空間開始地址入棧
1001F0F4    FF76 04         PUSH DWORD PTR DS:[ESI+4]                ; |Size1 = text段的Size入棧
1001F0F7    50              PUSH EAX                                 ; |ViAddress2 = 第二次申請的空間地址入棧
1001F0F8    53              PUSH EBX                                 ; |Size2 = EBX入棧(10001000)??
1001F0F9    E8 6E050000     CALL cesi.1001F66C                       ; \Function
1001F0F9    E8 6E050000     CALL cesi.1001F66C                       ; 這裡進去就是解壓程式碼的了
1001F0FE    B3 01           MOV BL,1
1001F100    80FB 00         CMP BL,0
......
1001F189    5E              POP ESI
1001F18A    68 00800000     PUSH 8000                                ; 這裡開始釋放剛才申請的空間
1001F18F    6A 00           PUSH 0
1001F191    FFB5 52010000   PUSH DWORD PTR SS:[EBP+152]
1001F197    FF95 51050000   CALL DWORD PTR SS:[EBP+551]              ; VirtualFree
1001F19D    83C6 08         ADD ESI,8
1001F1A0    833E 00         CMP DWORD PTR DS:[ESI],0
1001F1A3  ^ 0F85 1EFFFFFF   JNZ cesi.1001F0C7                        ; 這裡回去繼續迴圈
1001F1A9    68 00800000     PUSH 8000
1001F1AE    6A 00           PUSH 0
1001F1B0    FFB5 56010000   PUSH DWORD PTR SS:[EBP+156]              ; 這裡釋放第一次申請的空間
1001F1B6    FF95 51050000   CALL DWORD PTR SS:[EBP+551]              ; VirtualFree
......
1001F1CE    8B95 22040000   MOV EDX,DWORD PTR SS:[EBP+422]           ; 當前段的IMAGEBASE
1001F1D4    8B85 2D050000   MOV EAX,DWORD PTR SS:[EBP+52D]           ; 程式原來的IMAGEBASE
1001F1DA    2BD0            SUB EDX,EAX                              ; 相減
1001F1DC    74 79           JE SHORT cesi.1001F257                   ; 這裡判斷要不要重定位,如果不需要重定位就跳,
1001F1DE    8BC2            MOV EAX,EDX                              ; 這裡準備處理重定位
1001F1E0    C1E8 10         SHR EAX,10
1001F1E3    33DB            XOR EBX,EBX
1001F1E5    8BB5 39050000   MOV ESI,DWORD PTR SS:[EBP+539]           ; 重定位表段的開始地址1E000
1001F1EB    03B5 22040000   ADD ESI,DWORD PTR SS:[EBP+422]           ; 轉換成RVA
1001F1F1    833E 00         CMP DWORD PTR DS:[ESI],0                 ; [ESI]裡儲存了Size,如果重定位表處理完畢就跳去處理輸入


1001F1F4    74 61           JE SHORT cesi.1001F257
......
1001F24C    66:830E FF      OR WORD PTR DS:[ESI],0FFFF               ; 這裡要處理了,NOP掉就不會處理
1001F250    83C6 02         ADD ESI,2
1001F253  ^ E2 B4           LOOPD SHORT cesi.1001F209                ; 這裡回去迴圈處理
1001F255  ^ EB 9A           JMP SHORT cesi.1001F1F1
1001F257    8B95 22040000   MOV EDX,DWORD PTR SS:[EBP+422]
1001F25D    8BB5 41050000   MOV ESI,DWORD PTR SS:[EBP+541]           ; [EBP+541]記錄了重定位表的結束位置
......
1001F278    BE 70C30000     MOV ESI,0C370                            ; 把輸入表的VA入esi
1001F27D    8B95 22040000   MOV EDX,DWORD PTR SS:[EBP+422]
1001F283    03F2            ADD ESI,EDX                              ; 輸入表的VA轉成RVA
1001F285    8B46 0C         MOV EAX,DWORD PTR DS:[ESI+C]             ; 判斷有沒有輸入表
1001F288    85C0            TEST EAX,EAX
1001F28A    0F84 0A010000   JE cesi.1001F39A                         ; 如果沒有找到就OVER了
1001F290    03C2            ADD EAX,EDX
1001F292    8BD8            MOV EBX,EAX                              ; 取到第一個DLL的的名稱入ebx
1001F294    50              PUSH EAX                                 ; /pModule = "SlsApi.dll"
1001F295    FF95 4D0F0000   CALL DWORD PTR SS:[EBP+F4D]              ; \GetModuleHandleA
1001F29B    85C0            TEST EAX,EAX                             ; 取得BASE為3B0000
1001F29D    75 07           JNZ SHORT cesi.1001F2A6                  ; 如果已經獲取成功就跳去下一步,如果失敗就載入這個dll
1001F29F    53              PUSH EBX                                 ; /FileName ="SlsApi.dll"
1001F2A0    FF95 510F0000   CALL DWORD PTR SS:[EBP+F51]              ; \LoadLibraryA
1001F2A6    8985 45050000   MOV DWORD PTR SS:[EBP+545],EAX           ; 取出的值入[EBP+545]=(3B0000)
......
1001F2F5    53              PUSH EBX                                  ; /ProcNameOrOrdinal = #11
1001F2F6    FFB5 45050000   PUSH DWORD PTR SS:[EBP+545]               ; |hModule = 003B0000 (slsapi)
1001F2FC    FF95 490F0000   CALL DWORD PTR SS:[EBP+F49]               ; \GetProcAddress
1001F302    85C0            TEST EAX,EAX
1001F304    5B              POP EBX
1001F305    75 6F           JNZ SHORT cesi.1001F376                   ; 獲取成功就跳下去
上面跳到這裡了:

1001F376    8907            MOV DWORD PTR DS:[EDI],EAX                ; 這裡把上面獲取到的API填充進去
1001F378    8385 49050000 0>ADD DWORD PTR SS:[EBP+549],4              ; 值加4
1001F37F  ^ E9 32FFFFFF     JMP cesi.1001F2B6                         ; 這裡迴圈回去繼續取相關API
1001F384    8906            MOV DWORD PTR DS:[ESI],EAX
.......
1001F395    E9 EBFEFFFF     JMP cesi.1001F285
1001F39A    B8 4BA00000     MOV EAX,0A04B                            ; 這裡把OEP的VA傳到EAX中
1001F39F    50              PUSH EAX
1001F3A0    0385 22040000   ADD EAX,DWORD PTR SS:[EBP+422]
1001F3A6    59              POP ECX                                  ; 再把程式的OEP的VA傳入ECX中
1001F3A7    0BC9            OR ECX,ECX
1001F3A9    8985 A8030000   MOV DWORD PTR SS:[EBP+3A8],EAX           ; 程式的OEP地址(RVA)入[ebp+3A8]
1001F3AF    61              POPAD
1001F3B0    75 08           JNZ SHORT cesi.1001F3BA                  ; 如果得到OEP的VA為空的就主不跳也就OVER了
1001F3B2    B8 01000000     MOV EAX,1                                ; 如果OEP為空就OVER了
1001F3B7    C2 0C00         RETN 0C                                  ; 感覺有點多餘上面都已經給EAX賦值了,這幾步有必要嗎?
1001F3BA    68 4BA00010     PUSH cesi.1000A04B                       ; 轉去OEP
1001F3BF    C3              RETN

分析出來了,怎麼修復輸入表和重定位表我也就不多說了,準備回家睡覺.

Greetz:

Fly,Jingulong,yock,tDasm,David,ahao,vcasm,UFO(brother),alan(sister),all of my friends and you!
                            
                            By loveboom[DFCG][FCG][US]
                            Email:bmd2chen@tom.com

相關文章