對Crunch v1.1主程式檔案的脫殼方法 ---ljtt

看雪資料發表於2000-11-30

對Crunch v1.1主程式檔案的脫殼方法

【宣告】
我寫文章以交流為主,希望大家在轉載時能保持文章的完整性。

【前言】
Crunch v1.1的主程式檔案的註冊方法採用了和Armadilo的方法類似,由於其自身有多處反跟蹤的程式碼,所以如果不處理。。。。。

樣例檔案:    Crunch.EXE    (Crunch v1.1的主程式檔案)
加殼方式:    Crunch v1.1
目標:        手動脫殼
作者:        ljttt
寫作日期:    2001-xx-xx (有感於某製假企業)

1、啟動ICEDUMP,並啟動ProcDump 1.6.2,選擇Option/Rebuild new import table,單擊Bhrama Server。這樣我們將來手動脫殼時可以藉助ProcDump的自動脫殼功能。這樣很方便、快潔。

2、Ctrl-D進入SoftICE,設斷點
bpint 3

3、用PEditor 1.5開啟Crunch.EXE,單擊break'n'enter。這時將在第一條指令處中斷進入SoftICE。可以看到如下提示:
015F:0066C000  CC                  INT      3
015F:0066C001  E800000000          CALL      0066C006
015F:0066C006  5D                  POP      EBP
在命令視窗提示如下:
You have to enter "eb eip 55" before you continue !

現在我按照提示輸入
eb eip 55
這樣修改了入口處的 CC (int 3)。現在顯示如下,可以繼續跟蹤了。
015F:0066C000  55                  PUSH      EBP
015F:0066C001  E800000000          CALL      0066C006
015F:0066C006  5D                  POP      EBP

4、繼續到如下程式碼處:(特徵是第一個 REPZ MOVSB 指令)
015F:0066C0D9  BFE4000000          MOV      EDI,000000E4
015F:0066C0DE  03FD                ADD      EDI,EBP
015F:0066C0E0  8BC8                MOV      ECX,EAX
015F:0066C0E2  F3A4                REPZ MOVSB                <--在該指令執行完後,以下將得到SMC方法還原後的正確程式碼
015F:0066C0E4  8B07                MOV      EAX,[EDI]        <--現在還是加密的程式碼
015F:0066C0E6  D581                AAD
015F:0066C0E8  C2A614              RET      14A6

5、在 REPZ MOVSB 執行後,我們可以看到如下的程式碼:
015F:0066C0D9  BFE4000000          MOV      EDI,000000E4
015F:0066C0DE  03FD                ADD      EDI,EBP
015F:0066C0E0  8BC8                MOV      ECX,EAX
015F:0066C0E2  F3A4                REPZ MOVSB
015F:0066C0E4  8BD5                MOV      EDX,EBP        <--這是還原後的正確程式碼了,可以繼續跟蹤了
015F:0066C0E6  81C2A6140000        ADD      EDX,000014A6
015F:0066C0EC  52                  PUSH      EDX

6、繼續跟蹤到如下程式碼處:(特徵是 CALL EDX 後緊跟著兩個 INT 3 指令)
015F:0066C11C  5A                  POP      EDX
015F:0066C11D  90                  NOP
015F:0066C11E  FFD2                CALL      EDX            <--在此處我們要停下,其中有反跟蹤的程式碼,我們要跳過這段程式碼
015F:0066C120  CC                  INT      3
015F:0066C121  CC                  INT      3
015F:0066C122  E85E140000          CALL      0066D585

7、在 CALL EDX 處我們要停下,下指令跳過反跟蹤程式碼(關於這段反跟蹤程式碼的分析我已在《對Crunch v1.1加殼程式的手動脫殼的一點分析》一文中說明)
r eip eip+E
r esi 10

8、好了,現在我們又可以繼續跟蹤了,到如下程式碼處:(特徵是 JG 0066C19F 指令)
015F:0066C1A6  83C701              ADD      EDI,01
015F:0066C1A9  4B                  DEC      EBX
015F:0066C1AA  83FB00              CMP      EBX,00
015F:0066C1AD  7FF0                JG        0066C19F        <--現在程式又要用到SMC的方法來還原始碼了。
015F:0066C1AF  90                  NOP                        <--現在這裡還是加密的程式碼
015F:0066C1B0  EBCD                JMP      0066C17F
015F:0066C1B2  90                  NOP

9、我們來看看SMC方法還原的正確程式碼:
015F:0066C1A6  83C701              ADD      EDI,01
015F:0066C1A9  4B                  DEC      EBX
015F:0066C1AA  83FB00              CMP      EBX,00
015F:0066C1AD  7FF0                JG        0066C19F        <--該指令後的程式碼現在是還原後的正確程式碼了,可以比較以上的程式碼看看
015F:0066C1AF  B942000000          MOV      ECX,00000042
015F:0066C1B4  59                  POP      ECX

10、繼續跟蹤到如下程式碼處:(特徵是 SUB ECX,00000042 指令)
015F:0066C216  83F900              CMP      ECX,00
015F:0066C219  75EB                JNZ      0066C206
015F:0066C21B  59                  POP      ECX
015F:0066C21C  81E942000000        SUB      ECX,00000042
015F:0066C222  51                  PUSH      ECX
015F:0066C223  E8C3110000          CALL      0066D3EB        <--內有反跟蹤的程式碼,所以在此處我們要按F8鍵進入
015F:0066C228  33C0                XOR      EAX,EAX

11、在 CALL 0066D3EB 處我們按進入,可以看到如下程式碼:(這裡的反跟蹤程式碼說明見我寫的《對Crunch v1.1加殼程式的手動脫殼的一點分析》一文)
015F:0066D3EB  8BDD                MOV      EBX,EBP
015F:0066D3ED  8B85483C0000        MOV      EAX,[EBP+00003C48]
015F:0066D3F3  8B8D86330000        MOV      ECX,[EBP+00003386]
015F:0066D3F9  C1E908              SHR      ECX,08
015F:0066D3FC  33D2                XOR      EDX,EDX
015F:0066D3FE  B902000000          MOV      ECX,00000002
015F:0066D403  F7F1                DIV      ECX
015F:0066D405  0BD2                OR        EDX,EDX
015F:0066D407  7502                JNZ      0066D40B        <--在此處我們要停下!
015F:0066D409  EB72                JMP      0066D47D
015F:0066D40B  8BDD                MOV      EBX,EBP

12、在 JNZ 006D40B 處停下,我們不能讓其跳轉,所以我們可下指令
方法一:修改跳轉方向
r fl z
方法二:NOP掉跳轉指令
eb eip 90
eb eip+1 90

13、按F12返回到主程式程式碼段中,繼續跟蹤如下程式碼處:(特徵是 CALL EBX 後緊跟一條 NOP 指令)
015F:0066C273  BB76060000          MOV      EBX,00000676
015F:0066C278  03DD                ADD      EBX,EBP
015F:0066C27A  899D643C0000        MOV      [EBP+00003C64],EBX
015F:0066C280  BB050A0000          MOV      EBX,00000A05
015F:0066C285  03DD                ADD      EBX,EBP
015F:0066C287  FFD3                CALL      EBX            <--內有反跟蹤程式碼,在此處我們要停下,想辦法跳過它
015F:0066C289  90                  NOP
015F:0066C28A  60                  PUSHAD
015F:0066C28B  BB85230000          MOV      EBX,00002385

14、在 CALL EBX 處停下,下指令跳過反跟蹤(其中的反跟蹤程式碼說明見我寫的《Crunch v1.1中的一段有趣的檢測跟蹤程式碼》一文)
r eip eip+2

15、好了,到此主程式中的反跟蹤程式碼大部分被我們跳過了,有沒有一種登山的感覺,但是現在還只是過了一小段路程,我們繼續!

如果你有過對Crunch加殼的程式的脫殼經驗,一定會發現大部分類似,現在我們來看看Crunch.EXE主程式和他們的不同。這也是我們以下要進行的步驟的一個原理說明吧:
首先,Crunch.EXE自身用Crunch v1.1的方法加了殼,(其中我們在跟蹤時已經知道了有大量的反跟蹤程式碼,如果不小心掉了進去,呵呵!接受一次被超度的感覺吧!)。
然後,Crunch.EXE建立一個臨時檔案,其中的程式碼是由主程式在記憶體中還原得到的(此檔案也用Crunch v1.1加了殼)。然後透過此檔案建立一個子程式。進行註冊分析。
此時,主程式Crunch.EXE進入一個的迴圈中,等待子程式(臨時檔案建立)的註冊過程結束,當子程式退出後,主程式Crunch.EXE退出迴圈。並刪除此臨時檔案。最後,主程式進入主介面。
因此,我們要在主程式進入主介面之前,DUMP得到我們想要的脫殼檔案。由於子程式中也有反跟蹤程式碼,所以我們必須也要跳過其中的反跟蹤程式碼,否則前功盡棄。開始我想過很多辦法,比如在臨時檔案剛剛儲存還未建立程式的時候得到完整的加殼檔案來進行單獨的脫殼,然後在下次跟蹤時用我脫殼後沒有反跟蹤程式碼的檔案替換掉臨時檔案,但是發現單獨執行臨時檔案竟然無法工作,(看來作者早有防範)可見主程式Crunch.EXE需要和子程式有資訊通訊,必須要同時工作,我們也只有在主程式中執行的情況下對子程式進行分析跳過其中的反跟蹤程式碼。不過這把我一下難住了。由於WINDOWS的多工特點,我們無法在單步跟蹤時知道何時子程式開始執行第一條指令。我跟蹤的情況並非在CreatProcess函式執行後,也不在ResumeThread函式執行後。不過還是讓我想出了辦法。Yeah!

16、繼續跟蹤來到如下程式碼處:
015F:0066C473  50                  PUSH      EAX
015F:0066C474  FFB50D240000        PUSH      DWORD PTR [EBP+0000240D]    <--資料緩衝區地址,我跟蹤時為 920000
015F:0066C47A  FFB505240000        PUSH      DWORD PTR [EBP+00002405]
015F:0066C480  FF951E210000        CALL      [EBP+0000211E]                <--即 CALL WriteFile
015F:0066C486  FFB505240000        PUSH      DWORD PTR [EBP+00002405]
015F:0066C48C  FF9522210000        CALL      [EBP+00002122]
015F:0066C492  6800800000          PUSH      00008000
015F:0066C497  6A00                PUSH      00
015F:0066C499  FFB50D240000        PUSH      DWORD PTR [EBP+0000240D]
015F:0066C49F  FF9512210000        CALL      [EBP+00002112]

17、在 CALL [EBP+0000211E] 處停下,我們要做些準備工作。我跟蹤時 [EBP+0000240D] = 920000 ,這就是即將被儲存到臨時檔案中的資料。
我們要修改其中第一條指令為 CC 。臨時檔案的 Entry Point = 31C00,(這個值可以透過顯示 920000 的內容,分析 PE 結構知道,也可以在無除錯環境下用ProcDump來DUMP出臨時檔案得到。方法很多,可以自己去分析。)所以第一條指令位於 920000+31C00 處。
下指令
eb 920000+31C00 CC

18、下指令
I3HERE ON

19、繼續跟蹤到如下程式碼處:(特徵是 JMP EBX 後緊跟一條指令 MOV EAX,[EBP+00003536])
015F:0066C52D  83C304              ADD      EBX,04
015F:0066C530  FF33                PUSH      DWORD PTR [EBX]
015F:0066C532  FFD0                CALL      EAX
015F:0066C534  BBCC0C0000          MOV      EBX,00000CCC
015F:0066C539  03DD                ADD      EBX,EBP
015F:0066C53B  FFE3                JMP      EBX                <--在此處停下
015F:0066C53D  8B8536350000        MOV      EAX,[EBP+00003536]    <--在此處設下斷點
015F:0066C543  83C014              ADD      EAX,14
015F:0066C546  B914000000          MOV      ECX,00000014
015F:0066C54B  33D2                XOR      EDX,EDX
015F:0066C54D  8034101A            XOR      BYTE PTR [EDX+EAX],1A
015F:0066C551  42                  INC      EDX
015F:0066C552  49                  DEC      ECX
015F:0066C553  83F900              CMP      ECX,00

20、在 JMP EBX 處時我們暫時停下,在 MOV EAX,[EBP+00003536] 處設下斷點
bpx 0066C53D
此處斷點將在子程式結束後中斷。現在子程式還並未真正執行。在 JMP EBX 後將進入了一個迴圈。我們不需要浪費時間,按F5鍵繼續。

21、程式將中斷在子程式第一條指令處:
015F:0047FFFF  FFCC                DEC      ESP
015F:00480001  E800000000          CALL      00480006
015F:00480006  5D                  POP      EBP
015F:00480007  83ED06              SUB      EBP,06
015F:0048000A  8BC5                MOV      EAX,EBP

22、還原原來的程式碼,下指令
r eip eip-1
e eip 55        <--由於原來的第一條指令程式碼為 55

23、現在我們的跟蹤步驟和前面對主程式Crunch.EXE類似了。重複第 4 - 14 步中的方法來反跟蹤。這裡就不多說了,只是把一些特徵程式碼列出。方法比較。
㈠請對比步驟4:
特徵一: REPZ MOVSB
015F:004800E2  F3A4                REPZ MOVSB            <--特徵
015F:004800E4  8B07                MOV      EAX,[EDI]    <--未還原前的加密程式碼
015F:004800E6  D581                AAD
015F:004800E8  C29D14              RET      149D
015F:004800EB  0E                  PUSH      CS
以下是還原後的程式碼
015F:004800E2  F3A4                REPZ MOVSB            <--特徵
015F:004800E4  8BD5                MOV      EDX,EBP    <--還原後的正確程式碼
015F:004800E6  81C29D140000        ADD      EDX,0000149D
015F:004800EC  52                  PUSH      EDX
015F:004800ED  33C0                XOR      EAX,EAX

㈡請對比步驟6:
特徵二: CALL EDX 後緊跟 INT 3
015F:0048011D  90                  NOP
015F:0048011E  FFD2                CALL      EDX        <--特徵,要跳過這裡的反跟蹤
015F:00480120  CC                  INT      3
015F:00480121  CC                  INT      3
015F:00480122  E855140000          CALL      0048157C

㈢請對比步驟8:
特徵三: JG 0048019F
015F:004801AA  83FB00              CMP      EBX,00
015F:004801AD  7FF0                JG        0048019F    <--特徵
015F:004801AF  90                  NOP                    <--未還原前的加密程式碼
015F:004801B0  EBCD                JMP      0048017F
015F:004801B2  90                  NOP
以下是還原後的程式碼
015F:004801AA  83FB00              CMP      EBX,00
015F:004801AD  7FF0                JG        0048019F    <--特徵
015F:004801AF  B942000000          MOV      ECX,00000042    <--還原後的正確程式碼
015F:004801B4  59                  POP      ECX
015F:004801B5  57                  PUSH      EDI

㈣請對比步驟10:
特徵四: SUB ECX,00000042
015F:0048021B  59                  POP      ECX
015F:0048021C  81E942000000        SUB      ECX,00000042
015F:00480222  51                  PUSH      ECX
015F:00480223  E8BA110000          CALL      004813E2    <--要跳過這裡的反跟蹤
要跳過的地方
015F:004813FA  F7F1                DIV      ECX
015F:004813FC  0BD2                OR        EDX,EDX
015F:004813FE  7502                JNZ      00481402    <--NOP
015F:00481400  EB72                JMP      00481474

㈤請對比步驟13:
特徵五: CALL EBX 後緊跟 NOP
015F:00480285  03DD                ADD      EBX,EBP
015F:00480287  FFD3                CALL      EBX        <--要跳過此處的反跟蹤
015F:00480289  90                  NOP
015F:0048028A  60                  PUSHAD

24、跳過了以上這些反跟蹤的部分後,按F5鍵讓子程式進行註冊分析。這時將回到WINDOWS中,單擊 CONTINUE 鍵將進入程式主介面。(如果你想分析註冊碼,可以試試了)這時將中斷在我們在主程式中留下的一個斷點 CALL 0066C53D。顯示如下:
015F:0066C534  BBCC0C0000          MOV      EBX,00000CCC
015F:0066C539  03DD                ADD      EBX,EBP
015F:0066C53B  FFE3                JMP      EBX                
015F:0066C53D  8B8536350000        MOV      EAX,[EBP+00003536]    <--在此處中斷
015F:0066C543  83C014              ADD      EAX,14
015F:0066C546  B914000000          MOV      ECX,00000014
015F:0066C54B  33D2                XOR      EDX,EDX
015F:0066C54D  8034101A            XOR      BYTE PTR [EDX+EAX],1A

25、我們繼續跟蹤到如下程式碼處:(特徵是  JMP EAX 後緊跟 JMP [EBP+00003C6C])
015F:0066C9DB  83850124000014      ADD      DWORD PTR [EBP+00002401],14
015F:0066C9E2  FF8D55330000        DEC      DWORD PTR [EBP+00003355]
015F:0066C9E8  6683BD5533000000    CMP      WORD PTR [EBP+00003355],00
015F:0066C9F0  0F85FAFDFFFF        JNZ      0066C7F0
015F:0066C9F6  B83C160000          MOV      EAX,0000163C
015F:0066C9FB  03C5                ADD      EAX,EBP
015F:0066C9FD  FFE0                JMP      EAX                <--此處有大量的程式碼
015F:0066C9FF  FFA56C3C0000        JMP      [EBP+00003C6C]        <--這裡是關鍵!
015F:0066CA05  8CD8                MOV      AX,DS
015F:0066CA07  A804                TEST      AL,04

26、我們可以在 JMP EAX 處停下,直接在 JMP [EBP+00003C6C] 處設下斷點,或者把游標移動到此處按F7鍵,快速到此。(如果你想了解各個細節可以繼續慢慢跟蹤。)然後繼續跟蹤到如下程式碼處:
特徵是 MOV EAX,[EBP+00002415] 加 ADD [EBP+00003382],EAX 後跟一條 JMP [EBP+00003C5C] 指令
015F:00670094  BB810A0000          MOV      EBX,00000A81
015F:00670099  03DD                ADD      EBX,EBP
015F:0067009B  FFD3                CALL      EBX
015F:0067009D  64678F060000        POP      DWORD PTR FS:[0000]
015F:006700A3  83C408              ADD      ESP,08
015F:006700A6  8B8515240000        MOV      EAX,[EBP+00002415]
015F:006700AC  018582330000        ADD      [EBP+00003382],EAX
015F:006700B2  FFA55C3C0000        JMP      [EBP+00003C5C]        <--在這裡將跳轉到最後一段程式碼處
015F:006700B8  C3                  RET                     

27、在 JMP [EBP+00003C5C] 處按F10鍵將來到如下程式碼處:
015F:0066C0E4  61                  POPAD
015F:0066C0E5  5D                  POP      EBP
015F:0066C0E6  8B8582330000        MOV      EAX,[EBP+00003382]
015F:0066C0EC  5D                  POP      EBP
015F:0066C0ED  FFE0                JMP      EAX                <--EAX=OEP,這裡將跳轉到程式真正的入口處了!

28、在 JMP EAX 處我們要停下來,這裡將到了我們來DUMP檔案的時候到了。(這裡我使用的是ICEDUMP 6.0168的命令使用方法)
/bhrama ProcDump32 - Dumper Server
這時程式將回到WINDOWS,過一段時間,如果成功,將出現檔案儲存對話方塊讓你選擇想儲存的檔名。存完將回到SoftICE,好!我們按F5結束工作。

【後記】
用這種方法脫殼很累,寫這篇文章也很累。不過再累也得把方法留下來,讓自己以後能夠對該程式的加殼方法溫故知新。
Crunch.EXE v1.1
在脫殼後,還需要修改一處程式碼使之成為註冊版。
004043C8: 8D45EC                    lea eax,dword ptr [ebp-14]
004043CB: BA02000000                mov edx,00000002
004043D0: E81BA40D00                call 004DE7F0
004043D5: 59                        pop ecx
004043D6: 84C9                      test cl,cl
004043D8: 7409                      jz 004043E3                    <--修改此處的程式碼為NOP,即 7409=9090
004043DA: C605F4054E0001            mov byte ptr [004E05F4],01
004043E1: EB07                      jmp 004043EA
004043E3: C605F4054E0000            mov byte ptr [004E05F4],00
004043EA: FF4E1C                    dec dword ptr [esi+1C]
004043ED: 8D45FC                    lea eax,dword ptr [ebp-04]
004043F0: BA02000000                mov edx,00000002
004043F5: E8F6A30D00                call 004DE7F0

【補充】
最新下載了Crunch v1.2 。發現脫殼方法與上類似,就不寫了。
不過注意在跟蹤

相關文章