Alex-protect外殼完全分析【原創】
Alex-protect外殼完全分析
【目 標】:Alex-Protect v1.0 beta2
【工 具】:Olydbg1.1(diy版)、LORDPE、ImportREC1.6F
【任 務】:分析外殼
【操作平臺】:WinXP sp2
【作 者】: LOVEBOOM[DFCG][FCG][US]
【例項下載】: 點選下載
【簡要說明】: 快到聖誕節了,獻上文章一篇.這個殼不算強,不過花指令到不少。
【詳細過程】:
OD設定:開啟全部異常。我先自己寫了一個去花指令指令碼,方便我分析。因為殼後面分檢查程式碼,所以實際跟時可以不去掉垃圾程式碼的。
載入程式開始我們的旅程:
00438000 > 60 PUSHAD ; 保護現場
00438001 E8 00000000 CALL 00438006
00438006 5D POP EBP
00438007 81ED 06104000 SUB EBP,00401006 ; 取BASE=37000
…… ;這裡有一堆垃圾,我清除了先。
00438103 /E9 B3000000 JMP 004381BB ; 清完垃圾就直接到這裡了
……
004381BB 8B85 C4244000 MOV EAX,DWORD PTR SS:[EBP+4024C4] ; 把GetProcAddress的地址放到EAX中,用於後面的比較有沒有下CC斷
……
00438266 E8 46FFFFFF CALL 004381B1 ; 這裡進去就是比較有沒有在相關的api上下斷,第一次我們時去看看
進入後:
004381B1 8038 CC CMP BYTE PTR DS:[EAX],0CC ; 看到了吧,這裡比較相關API的第一位是否為CC,也就是判斷有沒有下斷
004381B4 74 01 JE SHORT 004381B7 ; 如果下斷了,就跳,也就over了
004381B6 C3 RETN
004381B7 F0:0FC7C8 LOCK CMPXCHG8B EAX
好了,知道情況後,後面的CALL 4381B1就不用再跟進去.
00438310 8B85 C8244000 MOV EAX,DWORD PTR SS:[EBP+4024C8] ; 比較GetModuleHandleA有沒有下斷
00438367 E8 45FEFFFF CALL 004381B1
……
00438411 8B85 CC244000 MOV EAX,DWORD PTR SS:[EBP+4024CC] ; 判斷LoadLibraryA有沒有下斷
00438417 E8 95FDFFFF CALL 004381B1 ; 同上,進去檢測
00438512 8B85 BC244000 MOV EAX,DWORD PTR SS:[EBP+4024BC] ; 判斷MessageBoxA
00438518 E8 94FCFFFF CALL 004381B1 ; 同上
……
004385C2 E8 35060000 CALL 00438BFC ; 這裡跟進
……
00438CA1 8D85 25244000 LEA EAX,DWORD PTR SS:[EBP+402425]
00438CA7 50 PUSH EAX
00438CA8 FF95 C8244000 CALL DWORD PTR SS:[EBP+4024C8] ; 獲取Kernel32的handle
00438CAE 8BF8 MOV EDI,EAX ; 獲取到的handle入edi
00438CB0 8D9D 3D244000 LEA EBX,DWORD PTR SS:[EBP+40243D] ; 把VirtualAlloc所在的地址傳遞到ebx中
00438CB6 53 PUSH EBX
00438CB7 50 PUSH EAX ; push handle
00438CB8 E8 B4030000 CALL 00439071
再跟進:
00439071 60 PUSHAD
00439072 8B5C24 24 MOV EBX,DWORD PTR SS:[ESP+24] ; handle 入ebx
0043911B 8B43 3C MOV EAX,DWORD PTR DS:[EBX+3C] ; 定位pe頭
004391C3 03C3 ADD EAX,EBX
004391C5 8B48 7C MOV ECX,DWORD PTR DS:[EAX+7C] ; Size Export Table入ecx(6c7b)
004391C8 E3 2F JECXZ SHORT 004391F9
004391CA 8B68 78 MOV EBP,DWORD PTR DS:[EAX+78] ; RVA Export table匯出表相對虛擬地址(262C)
004391CD 03EB ADD EBP,EBX
004391CF 8B4424 28 MOV EAX,DWORD PTR SS:[ESP+28]
004391D3 8B00 MOV EAX,DWORD PTR DS:[EAX]
004391D5 A9 0000FFFF TEST EAX,FFFF0000
004391DA 51 PUSH ECX
004391DB 74 21 JE SHORT 004391FE
004391DD 8B55 20 MOV EDX,DWORD PTR SS:[EBP+20]
004391E0 FC CLD
004391E1 03D3 ADD EDX,EBX
004391E3 33C0 XOR EAX,EAX
004391E5 8B4D 18 MOV ECX,DWORD PTR SS:[EBP+18]
004391E8 8BF3 MOV ESI,EBX
004391EA 8B7C24 2C MOV EDI,DWORD PTR SS:[ESP+2C]
004391EE 033482 ADD ESI,DWORD PTR DS:[EDX+EAX*4]
004391F1 A6 CMPS BYTE PTR DS:[ESI],BYTE PTR ES:[EDI]
004391F2 74 12 JE SHORT 00439206
004391F4 40 INC EAX
004391F5 49 DEC ECX
004391F6 ^ 75 F0 JNZ SHORT 004391E8 ; 透過遍歷的方法找到VirtualAlloc的地址
004391F8 59 POP ECX
004391F9 E9 7F010000 JMP 0043937D
004391FE 2B45 10 SUB EAX,DWORD PTR SS:[EBP+10]
00439201 E9 B5000000 JMP 004392BB
……
004392B2 8B55 24 MOV EDX,DWORD PTR SS:[EBP+24]
004392B5 03D3 ADD EDX,EBX
004392B7 0FB70442 MOVZX EAX,WORD PTR DS:[EDX+EAX*2]
004392BB 3B45 14 CMP EAX,DWORD PTR SS:[EBP+14]
004392BE ^ 0F83 35FFFFFF JNB 004391F9
004392C4 8B55 1C MOV EDX,DWORD PTR SS:[EBP+1C]
004392C7 03D3 ADD EDX,EBX
004392C9 031C82 ADD EBX,DWORD PTR DS:[EDX+EAX*4]
004392CC 8BC3 MOV EAX,EBX ; 獲取到的地址入eax
004392CE 90 NOP
00439373 2BDD SUB EBX,EBP
00439375 3BD9 CMP EBX,ECX
00439377 ^ 0F82 7CFEFFFF JB 004391F9
0043937D 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX ; 取出的值入[esp+c](7c809a81)
00439381 61 POPAD
00439382 C2 0800 RETN 8
出來後我們就可以知道:
CALL 00439071實際上就是 call GetProcAddress.
……
00438D62 E8 4AF4FFFF CALL 004381B1 ; 無聊,又進去檢查有沒有下斷
00438D67 8985 11244000 MOV DWORD PTR SS:[EBP+402411],EAX ; 取出VirtualAlloc的實際地址放到變數[EBP+402411]中
00438D6D 8D9D 4A244000 LEA EBX,DWORD PTR SS:[EBP+40244A]
00438D73 53 PUSH EBX ; /ProcNameOrOrdinal = "VirtualFree"
00438D74 57 PUSH EDI ; |hModule = 7C800000 (kernel32)
00438D75 E8 F7020000 CALL 00439071 ; \GetProcAddress
……
00438E1F E8 8DF3FFFF CALL 004381B1 ; 又是無聊的判斷
00438E24 8985 15244000 MOV DWORD PTR SS:[EBP+402415],EAX ; 取出VirtualFree地址放到變數[EBP+402415]處
00438E2A 8D9D 56244000 LEA EBX,DWORD PTR SS:[EBP+402456]
00438E30 53 PUSH EBX ; /ProcNameOrOrdinal = "GetstdHandle"
00438E31 57 PUSH EDI ; |hModule = 7C800000 (kernel32)
00438E32 E8 3A020000 CALL 00439071 ; \GetProcAddress
……
00438EDC E8 D0F2FFFF CALL 004381B1 ; 無聊判斷
00438EE1 8985 19244000 MOV DWORD PTR SS:[EBP+402419],EAX ; 取出GetStdHandle的地址放入變數[EBP+402419]處
00438EE7 8D9D 63244000 LEA EBX,DWORD PTR SS:[EBP+402463]
00438EED 53 PUSH EBX ; /ProcNameOrOrdinal = "CreateThread"
00438EEE 57 PUSH EDI ; |hModule = 7C800000 (kernel32)
00438EEF E8 7D010000 CALL 00439071 ; \GetProcAddress
……
00438F99 E8 13F2FFFF CALL 004381B1 ; 無聊的判斷
00438F9E 8985 21244000 MOV DWORD PTR SS:[EBP+402421],EAX ; 取出CreateThread的地址入變數[EBP+402421]處
00438FA4 8D85 32244000 LEA EAX,DWORD PTR SS:[EBP+402432] ; 準備獲取USER32.DLL中要用的API
00438FAA 50 PUSH EAX ; /FileName = "user32.dll"
00438FAB FF95 CC244000 CALL DWORD PTR SS:[EBP+4024CC] ; \LoadLibraryA
00438FB1 8BF8 MOV EDI,EAX ; 這個作者為了"節省"程式碼,不用GetModuleHandleA來判斷有沒有載入
00438FB3 8D9D 70244000 LEA EBX,DWORD PTR SS:[EBP+402470]
00438FB9 53 PUSH EBX ; /ProcNameOrOrdinal = "FindWindowA"
00438FBA 57 PUSH EDI ; |hModule = 77D10000 (USER32)
00438FBB E8 B1000000 CALL 00439071 ; \GetProcAddress
……
00439065 E8 47F1FFFF CALL 004381B1 ; 又一個無聊的判斷
0043906A 8985 1D244000 MOV DWORD PTR SS:[EBP+40241D],EAX ; 取出FindWindowA的地址入變數[EBP+40241D]處
00439070 C3 RETN ; 取完這麼幾個API後返回
……
004386BD 8D85 00104000 LEA EAX,DWORD PTR SS:[EBP+401000] ; EP(438000)入EAX
004386C3 B9 85130000 MOV ECX,1385 ; 這裡開始CRC前面的程式碼了檢查範圍是438000-439385(438000+1385)
004386C8 E8 E7040000 CALL 00438BB4 ; 這裡進去就是CRC(35FAFA4B,每次的值不同)
004386CD 8DBD 31254000 LEA EDI,DWORD PTR SS:[EBP+402531] ; [EBP+402531]=439531
004386D3 EB 01 JMP SHORT 004386D6
……
004386F7 8BC3 MOV EAX,EBX
004386F9 8B8D B5234000 MOV ECX,DWORD PTR SS:[EBP+4023B5] ; 準備解壓的大小(4B7)
004386FF 3007 XOR BYTE PTR DS:[EDI],AL ; 從439531處開始解壓下一段程式碼
00438701 47 INC EDI
00438702 49 DEC ECX
00438703 ^ 75 FA JNZ SHORT 004386FF ; 沒解壓完繼續
……
00438756 6A 04 PUSH 4 ; 解壓完準備分配空間
004388AE FF95 11244000 CALL DWORD PTR SS:[EBP+402411] ; VirtualAlloc
004388B4 8985 BD234000 MOV DWORD PTR SS:[EBP+4023BD],EAX ; 申請到的空間入[EBP+4023BD](3d0000)
……
0012FF84 004388B4 /CALL to VirtualAlloc from alexprot.004388AE
0012FF88 00000000 |Address = NULL
0012FF8C 0000EF74 |Size = EF74 (61300.)
0012FF90 00001000 |AllocationType = MEM_COMMIT
……
0043895F 8BF8 MOV EDI,EAX ; 申請到的地址放入EDI中EDI=3D0000
00438961 57 PUSH EDI ; 地址入棧
……
00438A07 8D85 31254000 LEA EAX,DWORD PTR SS:[EBP+402531] ; EAX=439531
00438A0D 50 PUSH EAX ; PUSH 439531
……
00438AB4 E8 4FF6FFFF CALL 00438108 ; apLib解壓程式碼
00438AB9 83C4 08 ADD ESP,8
……
00438BB2 - FFE7 JMP EDI ; 解壓完畢跳去已經解壓的程式碼處
……
003D0015 E8 88130000 CALL 003D13A2 ; 這裡進去看看
進來首先看到的就是清除斷點:
003D138B 8948 04 MOV DWORD PTR DS:[EAX+4],ECX ; 開始清除斷點
003D138E 8948 08 MOV DWORD PTR DS:[EAX+8],ECX
003D1391 8948 0C MOV DWORD PTR DS:[EAX+C],ECX
003D1394 8948 10 MOV DWORD PTR DS:[EAX+10],ECX
003D1397 C740 18 55010000 MOV DWORD PTR DS:[EAX+18],155
003D139E 59 POP ECX
003D139F 33C0 XOR EAX,EAX
003D13A1 C3 RETN
……
返回後,分析一下就會發現CALL 003D13A2就是清除斷點CALL.
003D001A 6A 04 PUSH 4
003D00C1 68 00100000 PUSH 1000
003D00C6 8B85 A1234000 MOV EAX,DWORD PTR SS:[EBP+4023A1] ; EAX=F0
003D0171 BB 4A000000 MOV EBX,4A
003D0176 F7E3 MUL EBX
003D0178 50 PUSH EAX ‘計算要申請空間的size
003D021E 6A 00 PUSH 0
003D0220 FF95 11244000 CALL DWORD PTR SS:[EBP+402411] ; VirtualAlloc
003D0226 8985 A5234000 MOV DWORD PTR SS:[EBP+4023A5],EAX ; 第二次申請的空間地址3E0000入[EBP+4023A5]
……
0012FF78 003D0226 /CALL to VirtualAlloc from 003D0220
0012FF7C 00000000 |Address = NULL
0012FF80 00004560 |Size = 4560 (17760.)
0012FF84 00001000 |AllocationType = MEM_COMMIT
……
003D02D1 8DB5 C1234000 LEA ESI,DWORD PTR SS:[EBP+4023C1] ; ESI=4393C1
003D02D7 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4] ; EAX=9BE8(text段的大小)
003D02DA 6A 04 PUSH 4
003D02DC 68 00100000 PUSH 1000
003D02E1 50 PUSH EAX
003D0387 6A 00 PUSH 0
003D0389 FF95 11244000 CALL DWORD PTR SS:[EBP+402411] ; VirtualAlloc
003D038F 8985 9D234000 MOV DWORD PTR SS:[EBP+40239D],EAX ; 第三次申請到的空間地址3F0000存放在[EBP+40239D]處
……
0012FF78 003D038F /CALL to VirtualAlloc from 003D0389
0012FF7C 00000000 |Address = NULL
0012FF80 00009BE8 |Size = 9BE8 (39912.)
0012FF84 00001000 |AllocationType = MEM_COMMIT
……
003D0395 56 PUSH ESI
003D0396 8B1E MOV EBX,DWORD PTR DS:[ESI] ; Voffset 1000
003D0398 039D 99234000 ADD EBX,DWORD PTR SS:[EBP+402399] ; 轉為VA(401000)
003D039E 50 PUSH EAX ; 剛才申請的空間入棧003D0444 53 PUSH EBX ; push Text section地址
003D0445 8D8D 08114000 LEA ECX,DWORD PTR SS:[EBP+401108] ; ECX=438108
003D044B FFD1 CALL ECX ; 這裡進去就是ApLib解壓text段
003D044D 83C4 08 ADD ESP,8
003D0450 8BC8 MOV ECX,EAX ; text段的大小9BE8入ECX
003D0452 8B3E MOV EDI,DWORD PTR DS:[ESI] ; text段的RVA入edi
……
003D04F9 03BD 99234000 ADD EDI,DWORD PTR SS:[EBP+402399] ; 轉換成VA(401000)
003D04FF 8BB5 9D234000 MOV ESI,DWORD PTR SS:[EBP+40239D] ; 這裡實際就是先申請一個空間把Text段解壓資料臨時到到申請空間裡,完畢後,寫回實際地址
003D0505 F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[>
003D0507 5E POP ESI
003D0508 8B85 9D234000 MOV EAX,DWORD PTR SS:[EBP+40239D]
003D050E 68 00800000 PUSH 8000
003D0513 6A 00 PUSH 0
003D0515 50 PUSH EAX
003D0516 FF95 15244000 CALL DWORD PTR SS:[EBP+402415] ; 還原出text段的資料後,釋放臨時空間(3F0000)
……
003D05C1 83C6 08 ADD ESI,8
003D05C4 833E 00 CMP DWORD PTR DS:[ESI],0
003D05C7 ^ 0F85 0AFDFFFF JNZ 003D02D7 ; 判斷有沒有解壓完全部段,沒有則回去繼續解壓
003D05CD E8 D00D0000 CALL 003D13A2 ; 這裡前面說是是清除斷點的,所以不用跟進去
003D05D2 6A 04 PUSH 4
003D05D4 68 00100000 PUSH 1000
003D05D9 8B85 91234000 MOV EAX,DWORD PTR SS:[EBP+402391] ; EAX=C5E
003D05DF 6BC0 02 IMUL EAX,EAX,2
003D0687 50 PUSH EAX ;push申請空間大小
003D0688 6A 00 PUSH 0
003D068A FF95 11244000 CALL DWORD PTR SS:[EBP+402411] ; VirtualAlloc
……
0012FF74 003D0690 /CALL to VirtualAlloc from 003D068A
0012FF78 00000000 |Address = NULL
0012FF7C 000018BC |Size = 18BC (6332.)
0012FF80 00001000 |AllocationType = MEM_COMMIT
……
003D0690 8985 AD234000 MOV DWORD PTR SS:[EBP+4023AD],EAX ; 申請的空間3F0000入[EBP+4023AD]處
003D0696 6A 04 PUSH 4
003D0698 68 00100000 PUSH 1000
003D069D 8B85 8D234000 MOV EAX,DWORD PTR SS:[EBP+40238D] ; EAX=830(申請空間大小)
……
003D0748 50 PUSH EAX
003D0749 6A 00 PUSH 0
003D074B FF95 11244000 CALL DWORD PTR SS:[EBP+402411] ; VirtualAlloc
……
0012FF74 003D0751 /CALL to VirtualAlloc from 003D074B
0012FF78 00000000 |Address = NULL
0012FF7C 00000830 |Size = 830 (2096.)
0012FF80 00001000 |AllocationType = MEM_COMMIT
……
003D0757 8D85 00104000 LEA EAX,DWORD PTR SS:[EBP+401000] ; EP入EAX
003D075D B9 85130000 MOV ECX,1385 ;要解壓的大小
003D0762 8D95 B41B4000 LEA EDX,DWORD PTR SS:[EBP+401BB4] ; 下一段要解壓的起始地址438bb4
003D0768 FFD2 CALL EDX ; 這個CALL就是計算CRC的值
……
003D080F 8DBD 31254000 LEA EDI,DWORD PTR SS:[EBP+402531] ; 這裡又開始解壓下一面的程式碼
003D0815 03BD B5234000 ADD EDI,DWORD PTR SS:[EBP+4023B5]
003D081B 33D2 XOR EDX,EDX
003D081D B9 00010000 MOV ECX,100
003D0822 F7F1 DIV ECX
003D0824 8BDA MOV EBX,EDX
003D0826 F7F1 DIV ECX
003D0828 03DA ADD EBX,EDX
003D082A F7F1 DIV ECX
003D082C 03DA ADD EBX,EDX
003D082E F7F1 DIV ECX
003D0830 03DA ADD EBX,EDX
003D0832 59 POP ECX
003D0833 8BC3 MOV EAX,EBX
003D0835 8B8D B9234000 MOV ECX,DWORD PTR SS:[EBP+4023B9]
003D083B 3007 XOR BYTE PTR DS:[EDI],AL ; 這次從4399e8處開始解碼
003D083D 47 INC EDI
003D083E 49 DEC ECX
003D083F ^ 75 FA JNZ SHORT 003D083B ; 沒解壓完跳回去繼續
……
003D08E6 E8 B70A0000 CALL 003D13A2 ; 又清除斷點
003D08EB 8B85 A9234000 MOV EAX,DWORD PTR SS:[EBP+4023A9] ; 把上面申請的地址空間920000入EAX
003D08F1 8BF0 MOV ESI,EAX
003D08F3 50 PUSH EAX
003D08F4 8D9D 31254000 LEA EBX,DWORD PTR SS:[EBP+402531]
003D08FA 039D B5234000 ADD EBX,DWORD PTR SS:[EBP+4023B5] ; 004399E8
……
003D09A5 53 PUSH EBX
003D09A6 8D95 08114000 LEA EDX,DWORD PTR SS:[EBP+401108]
003D09AC FFD2 CALL EDX ; ApLib解碼
003D09AE 83C4 08 ADD ESP,8
003D09B1 8BBD A9234000 MOV EDI,DWORD PTR SS:[EBP+4023A9] ; 申請的空間920000入EDI
003D09B7 803F C3 CMP BYTE PTR DS:[EDI],0C3 ; 判斷是否開始處理相關的DLL(也就是就是否第一次處理相應的DLL中的API)
003D09BA 0F85 CC000000 JNZ 003D0A8C ; 如果不是則跳
003D09C0 83C7 02 ADD EDI,2
003D09C3 57 PUSH EDI ; /Push "User32.dll"
003D09C4 FF95 C8244000 CALL DWORD PTR SS:[EBP+4024C8] ; \GetModuleHandleA判斷DLL有沒有載入
003D09CA 85C0 TEST EAX,EAX
003D09CC 0F85 AC000000 JNZ 003D0A7E ; 如果已經載入則跳
……
003D0A77 57 PUSH EDI ; 如果沒有載入則載入user32.dll
003D0A78 FF95 CC244000 CALL DWORD PTR SS:[EBP+4024CC] ; LoadLibraryA
003D0A7E 8985 7C244000 MOV DWORD PTR SS:[EBP+40247C],EAX ; hModule(77D1000.USER32.DLL)入[EBP+40247C]處
003D0A84 33DB XOR EBX,EBX
003D0A86 8A5F FF MOV BL,BYTE PTR DS:[EDI-1]
003D0A89 03FB ADD EDI,EBX
003D0A8B 47 INC EDI
003D0A8C 803F C4 CMP BYTE PTR DS:[EDI],0C4 ; 對輸入表的幾種不同情況進行處理??
003D0A8F 0F84 98010000 JE 003D0C2D ; 第一次這裡沒有跳,主程式沒有跳。
003D0A95 47 INC EDI
003D0A96 57 PUSH EDI ; /PUSH "TranslateMessage"
003D0A97 FFB5 7C244000 PUSH DWORD PTR SS:[EBP+40247C] ; |hModule = 77D10000 (USER32)
003D0A9D FF95 C4244000 CALL DWORD PTR SS:[EBP+4024C4] ; \GetProcAddress
……
003D0B4A 8A5F FF MOV BL,BYTE PTR DS:[EDI-1] ; 加地址
003D0B4D 03FB ADD EDI,EBX
003D0B4F 47 INC EDI
003D0B50 8A1F MOV BL,BYTE PTR DS:[EDI]
003D0B52 47 INC EDI
003D0B53 E9 B5000000 JMP 003D0C0D
……
003D0C0D 80FB 00 CMP BL,0 ; 如果BL大於0就跳
003D0C10 ^ 0F87 42FFFFFF JA 003D0B58
……
003D0B58 50 PUSH EAX ; PUSH API(77D18bce)
003D0B59 8B0F MOV ECX,DWORD PTR DS:[EDI] ; 把要寫入iat的地址入ECX
003D0B5B E8 62090000 CALL 003D14C2 ; 這看到這裡我就猜它裡面應該填充API,進去看看
003D14C2 60 PUSHAD ; 進入後到這裡
003D14C3 8BF0 MOV ESI,EAX ; API地址入esi
003D14C5 8B85 A5234000 MOV EAX,DWORD PTR SS:[EBP+4023A5] ; EAX=003E0000
……
003D1570 0385 B1234000 ADD EAX,DWORD PTR SS:[EBP+4023B1] ; [EBP+4023B1](4393b1)處儲存放後的值,比如第一沒寫就是0,第二的話就是4了
003D1576 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX ; 這裡的用意就是把API的部分放到申請的空間裡,真正的IAT呼叫申請的地址
003D157A E8 00000000 CALL 003D157F
003D157F 5B POP EBX
003D1580 81C3 61020000 ADD EBX,261 ; 3d157F+261=3D17E0 處臨時儲存API的地址
003D1586 8933 MOV DWORD PTR DS:[EBX],ESI ; API臨時儲存到3D17E0處
003D1588 8BF8 MOV EDI,EAX ; EDI=3E0000
……
003D162F 8BF3 MOV ESI,EBX ; 再把API存放的地址放到ESI中
003D1631 81EE 38000000 SUB ESI,38
003D1637 B9 4A000000 MOV ECX,4A
003D163C FC CLD
003D163D F3:A4 REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; 這裡把作者自己搞的花指令先填在我們去API的程式碼前
003D163F 8B85 A5234000 MOV EAX,DWORD PTR SS:[EBP+4023A5]
003D1645 0385 B1234000 ADD EAX,DWORD PTR SS:[EBP+4023B1] ; EAX=3E0000
……
003D16F0 8BD8 MOV EBX,EAX ; 再把003E0000的地址放到ebx上去
003D16F2 83C3 04 ADD EBX,4
003D179A 8918 MOV DWORD PTR DS:[EAX],EBX
003D179C 8185 B1234000 4A00>ADD DWORD PTR SS:[EBP+4023B1],4A ; 這也就是說程式碼指定大小為4A
003D17A6 61 POPAD
003D17A7 C3 RETN ;返回上去
……
003D0C05 8901 MOV DWORD PTR DS:[ECX],EAX ; 把加密後的地址放到IAT中,這個值是殼計算生成的.
003D0C07 83C7 04 ADD EDI,4 ; 繼續指向下一個要處理的API
003D0C0A FECB DEC BL
003D0C0C 58 POP EAX
003D0C0D 80FB 00 CMP BL,0 ; 如果BL大於0就跳
003D0C10 ^ 0F87 42FFFFFF JA 003D0B58
003D0C16 803F C3 CMP BYTE PTR DS:[EDI],0C3 ; 到這裡跟過就會發現殼是透過兩個C3來判斷有沒有處理完當前的DLL
003D0C19 ^ 0F84 A1FDFFFF JE 003D09C0 ; 判斷當前DLL是否已經處理完,處理則跳去下一個DLL的api處理
003D0C1F 833F 00 CMP DWORD PTR DS:[EDI],0
003D0C22 0F84 DE000000 JE 003D0D06 ; 判斷有沒有處理完全部的API,如果處理完就跳
003D0C28 ^ E9 8AFDFFFF JMP 003D09B7 ; 沒處理完則回去繼續
好了,處理完輸入表,到這裡:
003D0D06 E8 97060000 CALL 003D13A2 ; 處理完IAT就到這裡,清除斷點,不用跟進
003D0D0B 8D9D 31254000 LEA EBX,DWORD PTR SS:[EBP+402531] ; EBX=439531
……
003D0DB6 039D B5234000 ADD EBX,DWORD PTR SS:[EBP+4023B5]
003D0DBC 039D B9234000 ADD EBX,DWORD PTR SS:[EBP+4023B9] ; 00439C6D
……
003D0E67 8B8D 95234000 MOV ECX,DWORD PTR SS:[EBP+402395] ; ECX=A1E
……
003D0F12 8B85 AD234000 MOV EAX,DWORD PTR SS:[EBP+4023AD] ; EAX=3F0000
003D0F18 50 PUSH EAX
003D0F19 53 PUSH EBX ; 解開439c6d開始,大小為A1E的程式碼段
003D0F1A 8D95 08114000 LEA EDX,DWORD PTR SS:[EBP+401108]
003D0F20 FFD2 CALL EDX ; ApLib解壓
003D0F22 90 NOP
……
003D0FC7 83C4 08 ADD ESP,8
003D0FCA 8B85 AD234000 MOV EAX,DWORD PTR SS:[EBP+4023AD] ; EAX=3F0000
003D0FD0 8B9D 91234000 MOV EBX,DWORD PTR SS:[EBP+402391] ; EBX=C5E
……
003D107B 8BB5 85234000 MOV ESI,DWORD PTR SS:[EBP+402385] ; ESI=406B07(這個就是OEP後的第二條指令來的,第一行程式碼被殼抽掉了)
003D1081 03C3 ADD EAX,EBX ; EAX=eax+ebx=3F0000+C5E
003D1083 C600 E9 MOV BYTE PTR DS:[EAX],0E9 ; 003F0C5E處寫入E9遠端跳
003D1086 40 INC EAX
003D1087 8BCE MOV ECX,ESI ; alexprot.00406B07
……
003D112E 2BC8 SUB ECX,EAX ; 計算跳去OEP後第二條指令的程式碼的值
003D1130 83E9 04 SUB ECX,4
003D1133 8908 MOV DWORD PTR DS:[EAX],ECX ; 計算出來值當然要填到上面的地址了
……
003D11DA 8B85 AD234000 MOV EAX,DWORD PTR SS:[EBP+4023AD] ; 好了快到站了
003D11E0 894424 1C MOV DWORD PTR SS:[ESP+1C],EAX ; 這裡還要再玩一下,先跳去申請的3F0000的那裡再跳去OEP後的第二條指令
003D11E4 61 POPAD
003D11E5 - FFE0 JMP EAX ; 跳去殼裡,然後殼再跳去OEP後的第二條指令
進入殼抽程式碼處一下就可以找到第一行程式碼。好了,分析到此結束。
輸入表的處理:
我取的以下兩個地址
411000 開始寫入資料地址
410FD0 記錄地址
003D0A61 /EB 11 JMP SHORT 003D0A74
003D0A63 |90 NOP
003D0A64 |8305 D00F4100 04 ADD DWORD PTR DS:[410FD0],4 ; 當處理不同DLL時加8(第一次自己寫個地址)
003D0A6B |8985 7C244000 MOV DWORD PTR SS:[EBP+40247C],EAX ; 執行原殼的程式碼
003D0A71 |C3 RETN
003D0A72 |90 NOP
003D0A73 |90 NOP
003D0A74 \90 NOP
003D0A75 90 NOP
003D0A76 90 NOP ; ---------------------------
003D0A77 57 PUSH EDI ; 原殼程式碼
003D0A78 FF95 CC244000 CALL DWORD PTR SS:[EBP+4024CC] ; ---------------------------
003D0A7E E8 E1FFFFFF CALL 003D0A64 ; 這裡修改Call上面的程式碼
003D0A83 90 NOP
……
第二處就是寫入輸入表:
003D0BEC 58 POP EAX ; 出棧
003D0BED 53 PUSH EBX
003D0BEE 8B1D D00F4100 MOV EBX,DWORD PTR DS:[410FD0] ; 把要寫入IAT的地址放到EBX中
003D0BF4 8903 MOV DWORD PTR DS:[EBX],EAX ; API寫到IAT中
003D0BF6 8919 MOV DWORD PTR DS:[ECX],EBX ; IAT地址寫到程式呼叫中
003D0BF8 8305 D00F4100 04 ADD DWORD PTR DS:[410FD0],4 ; 呼叫完畢遞增
003D0BFF 5B POP EBX ; EBX出棧
003D0C00 90 NOP
003D0C01 90 NOP
003D0C02 90 NOP
003D0C03 90 NOP
003D0C04 90 NOP
003D0C05 90 NOP ; 去除原來的程式碼
003D0C06 90 NOP
003D0C07 83C7 04 ADD EDI,4
003D0C0A FECB DEC BL
003D0C0C 90 NOP ; 前面已經出棧了,所以不用再出棧
附兩個去花指令指令碼:
PatList_Alex=_alex_push01,_alex_call01
[CODE_alex_push01]
S =60EB03EB03??EBFBE801000000??83C4040F318BD8EB03EB03??EBFBE801000000??83C4048BCAEB03EB03??EBFBE801000000??83C4040F312BC3EB03EB03??EBFBE801000000??83C4041BD10F3103C3EB03EB03??EBFBE801000000??83C40413D10F312BC3EB03EB03??EBFBE801000000??83C404EB05??????????EB03EB03??EBFBE801000000??83C4041BD1EB03EB03??EBFBE801000000??83C40485D275D661
R =909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090
[CODE_alex_call01]
S =E824000000EB01E98B44240CEB03EB03C7EBFBE801000000A883C4048380B80000000233C0EB01E9C35883C404EB03EB03C7EBFBE801000000A883C4045064FF350000000064892500000000EB01??FFFF
R =909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090909090
全文完,跟完後才發現這個殼原來……:-)
聖誕節快到了,先祝大家聖誕節愉快!身體健康!
Greetz:
Fly.Jingulong,yock,tDasm.David.hexer,hmimys,ahao.UFO(brother).alan(sister).all of my friends and you!
By loveboom[DFCG][FCG][US]
Email:bmd2chen#tom.com
相關文章
- JDPack
Version 1.01 外殼完全分析筆記2004-05-15筆記
- [原創]帶殼分析共享軟體 (9千字)2015-11-15
- ASPACK外殼一點分析2004-08-12
- C32Asm外殼脫殼分析筆記2015-11-15ASM筆記
- PesPin
1.0外殼簡略分析2004-09-25
- PesPin 1.1外殼簡略分析2015-11-15
- 【原創】一個dex脫殼指令碼2017-01-03指令碼
- [原創]多層殼與Anti-ImportREC2004-11-15Import
- [原創]heXer老兄的telock0.98脫殼機原理2004-06-16
- 股市風暴4.0的外殼分析與脫殼方法(一) (7千字)2001-06-10
- 實施在系統外(原創)2007-07-28
- Linux 外殼程式2018-08-05Linux
- Fvwm新手入門不完全手冊(原創) (轉)2007-12-14
- 以殼解殼--SourceRescuer脫殼手記破解分析2004-11-16
- [原創] KCP 原始碼分析(上)2024-03-15原始碼
- 【原創】簡單嘗試脫“愛加密”官網加固的DEX殼2017-01-03加密
- [原創]破解-分析Crackme演算法2009-06-13演算法
- 【原創】需求分析之用例規模2010-01-13
- JVM原始碼分析之堆外記憶體完全解讀2020-12-08JVM原始碼記憶體
- 關於Windows外殼(Windows Shell)2024-11-11Windows
- 兩個火車頭原創外掛網站2020-10-15網站
- 魔術情書
6.55 破解過程+不脫殼打破解補丁【原創】2004-12-07
- 【原創】Oracle RAC故障分析與處理2013-07-18Oracle
- 標
題:avserve病毒初步分析!【原創】2004-05-02
- 利用DELPHI編寫WINDOWS外殼 (轉)2008-03-20Windows
- 完全解析QQ2004
sp1的本地加密策略!(原創)2004-12-04加密
- 某殼分析+修復(二)2018-05-14
- 先分析,再脫殼(一)2003-09-04
- [原創] Linux ptrace詳細分析系列(一)2021-02-02Linux
- 【原創】Linux PCI驅動框架分析(一)2020-12-20Linux框架
- 【原創】Linux PCI驅動框架分析(二)2020-12-29Linux框架
- 原創:oracle data block 內部結構分析2011-09-27OracleBloC
- 原創-XNview v1.65演算法分析2015-11-15View演算法
- Hollis原創|深入分析Java的編譯原理2019-05-14Java編譯原理
- 【原創】ORACLE 資料分析和動態取樣2014-08-12Oracle
- 【原創】Oracle execute plan 原理分析與例項分享2012-12-13Oracle
- [原創逆向]Telock98加密過程分析(上)2004-06-24加密
- 【原創】TextPad 4.7.3序列號演算法分析2015-11-15演算法