老殼petite不完全分析
0040D042 > B8 00D04000 MOV EAX,Notepad.0040D000 ;最後一節的起始地址
0040D047 68 4C584000 PUSH Notepad.0040584C ;異常處理例程
0040D04C 64:FF35 0000000>PUSH DWORD PTR FS:[0]
0040D053 64:8925 0000000>MOV DWORD PTR FS:[0],ESP ;建立異常處理鏈
0040D05A 66:9C PUSHFW ;這裏入棧2字節
0040D05C 60 PUSHAD ;入棧32字節
0040D05D 50 PUSH EAX ;入棧4字節
0040D05E 68 00004000 PUSH Notepad.00400000 ;IMAGEBASE 入棧4字節 一共入棧了2A H字節數 後面需要用到
0040D063 8B3C24 MOV EDI,DWORD PTR SS:[ESP] ;IMAGEBASE 送EDI
0040D066 8B30 MOV ESI,DWORD PTR DS:[EAX] ;[40d000]裏存放的是USER32.DLL的IMAGE_IMPORT_DESCRIPTOR結構相對於最後一節的偏移2B4H
0040D068 66:81C7 8007 ADD DI,780 ;將要存放導入表部分內容的地址[400780]
0040D06D 8D7406 08 LEA ESI,DWORD PTR DS:[ESI+EAX+8]
0040D071 8938 MOV DWORD PTR DS:[EAX],EDI
0040D073 8B5E 10 MOV EBX,DWORD PTR DS:[ESI+10] ;得到VirtualProtect的地址 是在導入表中得到的
0040D076 50 PUSH EAX
0040D077 56 PUSH ESI
0040D078 6A 02 PUSH 2
0040D07A 68 80080000 PUSH 880
0040D07F 57 PUSH EDI
0040D080 6A 12 PUSH 12
0040D082 6A 06 PUSH 6
0040D084 56 PUSH ESI ;&oldProtect
0040D085 6A 04 PUSH 4 ;PAGE_READWRITE
0040D087 68 80080000 PUSH 880 ;size
0040D08C 57 PUSH EDI ;起始地址IMAGEBASE
0040D08D FFD3 CALL EBX ;修改內存屬性爲 PAGE_READWRITE // kernel32.VirtualProtect
0040D08F 83EE 08 SUB ESI,8
0040D092 59 POP ECX
0040D093 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI];複製導入表中函數地址
0040D095 59 POP ECX
0040D096 66:83C7 68 ADD DI,68
0040D09A 81C6 B6000000 ADD ESI,0B6
0040D0A0 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI];複製導入表中DLL名稱
0040D0A2 FFD3 CALL EBX ;修改屬性爲只讀
0040D0A4 58 POP EAX
從40D1B8開始的數據類似一個數據結構
struct _PETITE
{
+0 dd number;number的最高位爲1的話 則低位字 爲複製數據的DWORD數目
+4 dd start;複製數據的原始內存RVA 複製的數據其實就是壓縮後的數據 (由於DF置位 複製是從後往前的)
+8 dd target;複製數據的目的內存RVA
+c dd start2;壓縮數據的起始內存RVA 這個字段+IMAGEBASE後 實際上就是target複製完後EDI-4(就是複製後的數據的起始內存)
+10 dd ?? ;跟壓縮算法有關 估計類似 解壓過程 中循環的 次數 不熟悉壓縮算法
+14 dd target2;壓縮數據的目的內存RVA 這個字段+IMAGEBASE後 就是start複製完後ESI-4(複製前的數據起始內存)
+18 dd xx
}PETITE, *PPETITE;
0040D0A5 8D90 B8010000 LEA EDX,DWORD PTR DS:[EAX+1B8]
0040D0AB 8B0A MOV ECX,DWORD PTR DS:[EDX] ;[40D1B8] PETITE.number
0040D0AD 0FBAF1 1F BTR ECX,1F ;測試最高位 並清零
0040D0B1 73 16 JNB SHORT Notepad.0040D0C9
0040D0B3 8B0424 MOV EAX,DWORD PTR SS:[ESP] ;IMAGEBASE
0040D0B6 FD STD ;標誌位置位
0040D0B7 8BF0 MOV ESI,EAX
0040D0B9 8BF8 MOV EDI,EAX
0040D0BB 0372 04 ADD ESI,DWORD PTR DS:[EDX+4] ;PETITE.start
0040D0BE 037A 08 ADD EDI,DWORD PTR DS:[EDX+8] ;PETITE.target
0040D0C1 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0040D0C3 83C2 0C ADD EDX,0C
0040D0C6 FC CLD
0040D0C7 ^ EB E2 JMP SHORT Notepad.0040D0AB
0040D0C9 83C2 10 ADD EDX,10
0040D0CC 8B5A F4 MOV EBX,DWORD PTR DS:[EDX-C] ;PETITE.??
0040D0CF 85DB TEST EBX,EBX
0040D0D1 ^ 74 D8 JE SHORT Notepad.0040D0AB
0040D0D3 8B0424 MOV EAX,DWORD PTR SS:[ESP]
0040D0D6 8B7A F8 MOV EDI,DWORD PTR DS:[EDX-8] ;PETITE.target2
0040D0D9 03F8 ADD EDI,EAX
0040D0DB 52 PUSH EDX
0040D0DC 8D3401 LEA ESI,DWORD PTR DS:[ECX+EAX]
0040D0DF EB 17 JMP SHORT Notepad.0040D0F8
0040D0E1 58 POP EAX
0040D0E2 58 POP EAX
0040D0E3 58 POP EAX
0040D0E4 5A POP EDX
0040D0E5 ^ 74 C4 JE SHORT Notepad.0040D0AB
0040D0E7 ^ E9 1CFFFFFF JMP Notepad.0040D008
0040D0EC 02D2 ADD DL,DL
0040D0EE 75 07 JNZ SHORT Notepad.0040D0F7
0040D0F0 8A16 MOV DL,BYTE PTR DS:[ESI]
0040D0F2 83EE FF SUB ESI,-1
0040D0F5 12D2 ADC DL,DL
0040D0F7 C3 RETN
0040D0F8 81FB 00000100 CMP EBX,10000 ;
0040D0FE 73 0E JNB SHORT Notepad.0040D10E
0040D100 68 60C0FFFF PUSH -3FA0
0040D105 68 60FCFFFF PUSH -3A0
0040D10A B6 05 MOV DH,5
0040D10C EB 22 JMP SHORT Notepad.0040D130
0040D10E 81FB 00000400 CMP EBX,40000
0040D114 73 0E JNB SHORT Notepad.0040D124
0040D116 68 8081FFFF PUSH FFFF8180
0040D11B 68 80F9FFFF PUSH -680
0040D120 B6 07 MOV DH,7
0040D122 EB 0C JMP SHORT Notepad.0040D130
0040D124 68 0083FFFF PUSH FFFF8300
0040D129 68 00FBFFFF PUSH -500
0040D12E B6 08 MOV DH,8
0040D130 6A 00 PUSH 0
0040D132 32D2 XOR DL,DL
0040D134 4B DEC EBX ;PETITE.?? 自減 (猜測 循環次數爲PETITE.??/4)
0040D135 A4 MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ;解壓開始 PETITE結構共有2個 解壓2次 最後這裏觸發一個異常
第一次解壓起始地址40AF2C 目的地址爲407C04
第二次解壓起始地址404448 目的地址爲401000
整個過程其實就是把壓縮後的數據 複製到一塊內存區 解壓後再複製回來
兩次解壓將PE文件的 第一個節和第2個節 解壓完 然後觸發異常 轉到異常
處理例程
第一次異常處理
0040584C E8 4F000000 CALL Notepad.004058A0
004058A0 33C0 XOR EAX,EAX ;EAX置0
004058A2 5E POP ESI ;405851
004058A3 64:8B18 MOV EBX,DWORD PTR FS:[EAX] ;FS:[0] Ptr32 _EXCEPTION_REGISTRATION_RECORD
004058A6 8B1B MOV EBX,DWORD PTR DS:[EBX] ;_EXCEPTION_REGISTRATION_RECORD.Next
;這裏是找到第一次異常處理鏈堆棧
004058A8 8D63 D6 LEA ESP,DWORD PTR DS:[EBX-2A] ;重置ESP 注意這裏的2A與開始的入棧的2A H對應
004058AB 5D POP EBP ;取出IMAGEBASE -4 H
004058AC 8D8E BD020000 LEA ECX,DWORD PTR DS:[ESI+2BD] ;新的異常處理例程地址
004058B2 894B 04 MOV DWORD PTR DS:[EBX+4],ECX ;直接寫到了第一次異常發生前的_EXCEPTION_REGISTRATION_RECORD.Handler
004058B5 64:891D 0000000>MOV DWORD PTR FS:[0],EBX ;新的異常處理建立
004058BC 8B3C24 MOV EDI,DWORD PTR SS:[ESP] ;最後一節的起始VA
004058BF 81C7 39000000 ADD EDI,39 ;
004058C5 6A 0E PUSH 0E
004058C7 59 POP ECX
004058C8 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ;複製從405851開始的14個字節到 40D039處 執行完畢後EDI = 40D047
004058CA FF33 PUSH DWORD PTR DS:[EBX] ; 異常處理鏈的尾端的 _EXCEPTION_REGISTRATION_RECORD.Next
004058CC 56 PUSH ESI
004058CD 57 PUSH EDI ;三次PUSH +c H
004058CE 8DB7 71010000 LEA ESI,DWORD PTR DS:[EDI+171] ;ESI = 40D1B8 正好到了PETITE結構
004058D4 8BCE MOV ECX,ESI
004058D6 2BCF SUB ECX,EDI
004058D8 F3:AA REP STOS BYTE PTR ES:[EDI] ;內存以0填充 執行完畢後 EDI = ESI
004058DA 60 PUSHAD ;+ 20 H
004058DB 66:9C PUSHFW
004058DD 0FBA3C24 08 BTC DWORD PTR SS:[ESP],8 ;位測試並取反 傳說中的單步異常 設置TF位
004058E2 66:9D POPFW
004058E4 5B POP EBX ;
004058E5 5A POP EDX ;單步異常
004058E6 64:8F05 0000000>POP DWORD PTR FS:[0]
第二次異常處理
00405B0E 33C0 XOR EAX,EAX
00405B10 64:8B18 MOV EBX,DWORD PTR FS:[EAX] ;FS[0] Ptr32 _EXCEPTION_REGISTRATION_RECORD
00405B13 8B1B MOV EBX,DWORD PTR DS:[EBX] ;_EXCEPTION_REGISTRATION_RECORD.Next
;這裏找到建立第二次異常鏈後的堆棧
00405B15 8D63 AE LEA ESP,DWORD PTR DS:[EBX-52] ;兩次異常處理鏈 52H = 2AH -4H + 0CH +20H 定位到了異常鏈建立好後
;pushad後的 堆棧
00405B18 61 POPAD
00405B19 833E 00 CMP DWORD PTR DS:[ESI],0
00405B1C ^ 0F84 C2FDFFFF JE Notepad.004058E4
00405B22 0FBA26 1F BT DWORD PTR DS:[ESI],1F ;測試最高位PETITE.number
00405B26 73 05 JNB SHORT Notepad.00405B2D ;CF 爲0 則跳
00405B28 83C6 0C ADD ESI,0C
00405B2B ^ EB EC JMP SHORT Notepad.00405B19
00405B2D 8B7E 08 MOV EDI,DWORD PTR DS:[ESI+8] ;PETITE.target2
00405B30 03FD ADD EDI,EBP ;定位到解壓後的節中
00405B32 8B4E 0C MOV ECX,DWORD PTR DS:[ESI+C] ;PETITE.xx
00405B35 D1F9 SAR ECX,1
00405B37 51 PUSH ECX
00405B38 72 15 JB SHORT Notepad.00405B4F
00405B3A 037E 04 ADD EDI,DWORD PTR DS:[ESI+4] ;PETITE.??(從這段代碼看 ??可能還是解壓後有效數據的大小 ?)
00405B3D C1F9 02 SAR ECX,2
00405B40 33C0 XOR EAX,EAX
00405B42 F3:AB REP STOS DWORD PTR ES:[EDI] ;清0 字節數爲PETITE.xx/2(XX看來跟解壓後的無效數據大小有關 ?)
00405B44 59 POP ECX
00405B45 83E1 03 AND ECX,3
00405B48 F3:AA REP STOS BYTE PTR ES:[EDI]
00405B4A 83C6 10 ADD ESI,10
00405B4D ^ EB CA JMP SHORT Notepad.00405B19
;下面就是最後的修正算法了 挺複雜的
00405B4F 8B5E 04 MOV EBX,DWORD PTR DS:[ESI+4] ;PETITE.??
00405B52 83EB 06 SUB EBX,6 ;PETITE.??-6
00405B55 33D2 XOR EDX,EDX
00405B57 ^ 72 E1 JB SHORT Notepad.00405B3A
00405B59 8A043A MOV AL,BYTE PTR DS:[EDX+EDI]
00405B5C 3C E8 CMP AL,0E8 ;E8和E9是CALL和JMP的機器碼 開始修正操作數
00405B5E 74 0E JE SHORT Notepad.00405B6E
00405B60 3C E9 CMP AL,0E9
00405B62 74 0A JE SHORT Notepad.00405B6E
00405B64 3C 0F CMP AL,0F ;0F80 - 0F8F 查的書上 似乎都是段內跳轉指令的機器碼 修改跳轉指令的操作數
00405B66 74 12 JE SHORT Notepad.00405B7A
00405B68 42 INC EDX
00405B69 83EB 01 SUB EBX,1
00405B6C ^ EB E9 JMP SHORT Notepad.00405B57
00405B6E 29543A 01 SUB DWORD PTR DS:[EDX+EDI+1],EDX ;如果是MOV指令 就把後面的操作數機器碼 - MOV指令機器碼相對於解密起始處的偏 移
00405B72 83C2 05 ADD EDX,5
00405B75 83EB 05 SUB EBX,5
00405B78 ^ EB DD JMP SHORT Notepad.00405B57
00405B7A 8A443A 01 MOV AL,BYTE PTR DS:[EDX+EDI+1]
00405B7E 3C 80 CMP AL,80
00405B80 ^ 72 E6 JB SHORT Notepad.00405B68
00405B82 3C 8F CMP AL,8F
00405B84 ^ 77 E2 JA SHORT Notepad.00405B68
00405B86 29543A 02 SUB DWORD PTR DS:[EDX+EDI+2],EDX ;如果是段內跳轉指令就把
00405B8A 83C2 06 ADD EDX,6
00405B8D 83EB 06 SUB EBX,6
00405B90 ^ EB C5 JMP SHORT Notepad.00405B57
00405B92 59 POP ECX
00405B93 5E POP ESI
00405B94 FD STD
00405B95 33C0 XOR EAX,EAX
00405B97 B9 56030000 MOV ECX,356
00405B9C E8 43B98624 CALL 24C714E4 ;解密後 從這裏F7(解密後 這個CALL的轉移地址要變的)
整個算法描述 有點囉嗦:如果碰到CALL和JMP指令或者段內轉移指令 就把它們的操作數機器碼 減去 本身相對於解密起始處的偏移
0040D039 5F POP EDI ; Notepad.00405BA1
0040D03A F3:AA REP STOS BYTE PTR ES:[EDI]
0040D03C 61 POPAD
0040D03D 66:9D POPFW
0040D03F 83C4 08 ADD ESP,8
0040D042 >- E9 8540FFFF JMP Notepad.004010CC ; 哈哈 回到加殼後的入口點地址 跳到OEP
總結:整個脫殼過程中 數據複製2次 解壓2次 解密一次 2次異常 而且 關鍵跳 就在處EP
快速脫殼 除了最後一次異常法還可以 用多次內存斷點 或者 直接在 載入後的入口點下個硬件執行斷點F9就可以了
http://www.namipan.com/d/ef1b6e368177df074308b74ac4b4f8e0d417e4a7c2450000
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.