Lock98主程式脫殼筆記 (1千字)

看雪資料發表於2015-11-15

Lock98是國內第一套基於Windows 32位作業系統的軟體加密工具,
自稱可以:
        可對抗任何靜態分析
        可對抗一切複製機
        對抗所有的脫殼工具及複製工具

太吹牛了吧,不太相信,就拿它開刀。
--------------------------------------------------------------
說得這麼好,也想來一份試一試。於是從他的主頁上下載了一份。接下來就開始安裝,在安裝過程中,任意
輸入了一些資訊,程式開始複製檔案。但很快提示“磁碟金鑰資訊校驗失敗”。
來到安裝資料夾中,只有幾個檔案:
DEFAULT  CFG
HDINST32 EXE
LOCK98  INI
LOCK98  HLP
沒有主程式檔案。

第一步,想辦法得到主程式檔案。
程式在安裝中會提示“磁碟金鑰資訊校驗失敗”,很有可能是在校驗失敗後將主程式檔案刪除了,
再來一次,啟動TRW2000,當安裝程式複製檔案完成,還沒有提示出錯時,按 CTRL+N 斷下,按幾次
F12回到程式領空,下命令 SUSPEND 讓程式掛起。

回到安裝資料夾中,果然看見了主程式lock98.exe ,馬上把它複製一份。再按CTRL+N ,讓安裝程式繼續,等
安裝程式完成,lock98.exe 果然被刪除了,不過我要的已經有了。執行 lock98.exe ,發現它也是用磁碟加
密的,沒有加密盤,程式沒法執行。

第二步,處理 lock98.exe 脫去它的磁碟加密的殼

執行lock98.exe後,提示 "加密盤錯誤",程式無法執行.
用peditor開啟lock98.exe,它的 sections 如下:
CODE
DATA
BSS
.idata
.tls
.rdata
.reloc
.rsrc
_LOCK98_ <---看樣子這就是透過LOCK98.EXE加密後增加的節,

檢視它的引入表,各種引入的DLL及引入API都在,初步判斷程式在加密過程中沒有對引入表做手腳.

使用TRW2000進行跟蹤,在加殼程式中,果然有很多的花指令,動態分析比較麻煩.
為了驗證一下它有沒有對程式碼段(即CODE段)進行加密,我找到程式碼段的一個地址,
對其下斷點 BMP .....
執行後程式被斷在_LOCK98_中的某處,它在一個迴圈中不斷的對程式碼段的資料進行還原.可見,程式對原始碼段進行的處理,程式碼段還原後,執行一段時間後開始讀加密盤.因為沒有加密盤,很快就提示出錯.

於時,我就大膽猜想,即然程式沒有對引入表做手腳,在讀加密盤之前又對程式碼進行了還原.那麼只要在提示出錯時,將程式DUMP下來,找到原程式的入口就可以了.
所以馬上用 peditor 將程式DUMP下來,儲存在磁碟中,接下來就開始想辦法找程式入口點.

在DUMP下來的程式中,使用peditor檢視其引入表,發現其引入表已經在載入過程中已經被破壞(因為這是一個Borland Delphi 3.0 編譯的程式。TLINK32 所產生的 PE 對引入表中的Characteristics [也就是 hint-name array ]總是 0 ,而使 FirstThunk 指向引入函式的名稱,而其它編譯器會使它指向引入函式的名稱。FirstThunk 在程式載入時,會被函式的實際地址填充而造成引入表被破壞),所以接下來就想辦法修正引入表。

在原程式中,引入表的DLL和API都很完整,所以首先想到用原程式中的引入表,把它提取出來,放到DUMP下來的程式中。經查在原程式中,引表入在檔案中的偏移在5E000處。

          Characteristics                    指向DLL名,在檔案中實際為5E728
          __________                          __________
          |        |                          |        |
0005E000  00 00 00 00 00 00 00 00  00 00 00 00 28 C7 06 00  ............(?.
         
  FirstThunk 指向引入函式名的指標陣列,在檔案中實際指向5e140
          __________
          |        |
0005E010  40 C1 06 00 00 00 00 00  00 00 00 00 00 00 00 00  @?.............
0005E020  80 C9 06 00 D0 C1 06 00  00 00 00 00 00 00 00 00  ?.辛..........
0005E030  00 00 00 00 BA C9 06 00  E0 C1 06 00 00 00 00 00  ....荷..嗔......
0005E040  00 00 00 00 00 00 00 00  FA C9 06 00 F0 C1 06 00  ..........鵒..
...............

          指向引入函式名
          __________
          |        |
0005E140  36 C7 06 00 4E C7 06 00  66 C7 06 00 7E C7 06 00  6?.N?.f?.~?.
0005E150  9A C7 06 00 A8 C7 06 00  B8 C7 06 00 C4 C7 06 00  ..ㄇ..蓋..那..
0005E160  D2 C7 06 00 E2 C7 06 00  F8 C7 06 00 0E C8 06 00  儀..餷.....?.


而在DUMP下來的程式中,引入表在檔案中的偏移為6C000處,其它的資訊都很完整,但其FirstThunk在載入時被破壞(都是Borland的小錯誤造成的,讓我多花了很多時間):


0006C000  00 00 00 00 21 AF 32 37  00 00 F7 BF 28 C7 06 00  ....!?7..骺(?.
0006C010  40 C1 06 00 00 00 00 00  72 DA 38 37 00 00 F5 BF  @?.....r?7..蹩
0006C020  80 C9 06 00 D0 C1 06 00  00 00 00 00 72 DA 38 37  ?.辛......r?7
0006C030  00 00 E8 BF BA C9 06 00  E0 C1 06 00 00 00 00 00  ..榪荷..嗔......
0006C040  76 26 48 39 00 00 E8 7F  FA C9 06 00 F0 C1 06 00  v&H9..?..鵒..
0006C050  00 00 00 00 21 AF 32 37  00 00 F7 BF 8A CA 06 00  ....!?7..骺..
0006C060  10 C2 06 00 00 00 00 00  72 DA 38 37 00 00 E8 BF  .?.....r?7..榪
0006C070  EC CA 06 00 28 C2 06 00  00 00 00 00 21 AF 32 37  焓..(?.....!?7
0006C080  00 00 F7 BF 5C CB 06 00  44 C2 06 00 00 00 00 00  ..骺\?.D?.....
0006C090  72 DA 38 37 00 00 E7 BF  78 CF 06 00 34 C3 06 00  r?7..緲x?.4?.
0006C0A0  00 00 00 00 38 74 5A 35  00 00 F2 BF C6 CF 06 00  ....8tZ5..蚩葡..
0006C0B0  44 C3 06 00 00 00 00 00  72 DA 38 37 00 00 F5 BF  D?.....r?7..蹩
0006C0C0  C0 D4 06 00 6C C4 06 00  00 00 00 00 CF 40 A0 3B  澇..l?.....@?
0006C0D0  00 00 B7 BF 9E DD 06 00  A0 C6 06 00 00 00 00 00  ..房........
0006C0E0  75 DA 38 37 00 00 E1 7F  C8 DF 06 00 04 C7 06 00  u?7..?冗...?.
0006C0F0  00 00 00 00 75 DA 38 37  00 00 CB 7F FE DF 06 00  ....u?7..?..
0006C100  10 C7 06 00 00 00 00 00  21 AF 32 37 00 00 F7 BF  .?.....!?7..骺
0006C110  1A E0 06 00 18 C7 06 00  00 00 00 00 73 DA 38 37  .?..?.....s?7
0006C120  00 00 DE BF 34 E0 06 00  20 C7 06 00 00 00 00 00  ..蘅4?. ?.....
0006C130  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................

  本來就是指向引入函式名的,現在已經變為實際地址。 
            _________
            |      |
0006C140  06 AF F8 BF 82 BA F7 BF  5D BA F7 BF 8F 45 F8 BF  .瑚]瑚E
0006C150  B6 44 F8 BF 5C 02 F8 BF  50 4A F7 BF 34 49 F7 BF  D\.PJ骺4I骺
0006C160  C6 0E FA BF 1F 7E F7 BF  01 7E F7 BF 29 74 F7 BF  ?.~骺.~骺)t骺
0006C170  78 73 F7 BF 54 DA 08 C0  15 F3 F9 BF 2D 78 F7 BF  xs骺T??簌?x骺


我就將原程式中的引入表從 5E000 大小為 204E 的引入表,覆蓋到DUMP下來的程式的6C000處,再使用peditor檢視時,引入表已經顯示正常。

找入口點前,先把DUMP下來的程式處理一下,使用 peditor 開啟程式,檢視程式的sections,看到 _LOCK98_ 這一個節在檔案中的偏移在C7000開始,於是,先將節的總數由9改為8,用WINHEX開啟,將C7000處開始的無用的資料刪除。
找入口點真是件麻煩的事,沒有加密盤,要分析它的的執行過程找入口點比較煩,於是就想到了另一種方法。
在很多的程式中,程式的開始處的程式碼都非常類似:如VC++編譯的程式,
第一條語句一般是
PUSH EBP
很快就是一個KERNEL32的函式的呼叫
GetVersion
這是一個用 Borland Delphi 編譯的程式,它也一定有類似的程式碼。於是找了一個其它的 Delphi 編譯的程式,發現它的碼代呼叫的特點是:
第一句 PUSH EBP
而且入口點基本是在程式碼段的結束的地方。
於是我先將 DUMP下來的程式用peditor 改入口點為 1000 ,再用 w32dasm 反編譯,在結束處有以下程式碼:


:0045DB04 98384500                DWORD 00453898
:0045DB08 98564500                DWORD 00455698
:0045DB0C 60564500                DWORD 00455660
:0045DB10 306C4500                DWORD 00456C30
:0045DB14 006C4500                DWORD 00456C00
:0045DB18 B46F4500                DWORD 00456FB4
:0045DB1C 846F4500                DWORD 00456F84
:0045DB20 5C854500                DWORD 0045855C
:0045DB24 2C854500                DWORD 0045852C


:0045DB28 00000000                BYTE  4 DUP(0)


:0045DB2C 30D9                    xor cl, bl
:0045DB2E 45                      inc ebp
:0045DB2F 00                      BYTE 0


:0045DB30 55                      push ebp 〈---------找到一個 push ebp 的程式碼
:0045DB31 8BEC                    mov ebp, esp
:0045DB33 83C4F4                  add esp, FFFFFFF4
:0045DB36 B858D94500              mov eax, 0045D958
:0045DB3B E8A87BFAFF              call 004056E8
:0045DB40 A1A4ED4500              mov eax, dword ptr [0045EDA4]
:0045DB45 8B00                    mov eax, dword ptr [eax]
:0045DB47 E8DC0FFDFF              call 0042EB28
:0045DB4C A1A4ED4500              mov eax, dword ptr [0045EDA4]
:0045DB51 8B00                    mov eax, dword ptr [eax]
:0045DB53 83C034                  add eax, 00000034

* Possible StringData Ref from Code Obj ->"Lock98.hlp"
                                  |
:0045DB56 BAB8DB4500              mov edx, 0045DBB8
:0045DB5B E8185EFAFF              call 00403978
:0045DB60 8B0D30ED4500            mov ecx, dword ptr [0045ED30]
:0045DB66 A1A4ED4500              mov eax, dword ptr [0045EDA4]
:0045DB6B 8B00                    mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"@"
                                  |
:0045DB6D 8B15BC6F4500            mov edx, dword ptr [00456FBC]
:0045DB73 E8C80FFDFF              call 0042EB40
:0045DB78 8B0D5CEE4500            mov ecx, dword ptr [0045EE5C]
:0045DB7E A1A4ED4500              mov eax, dword ptr [0045EDA4]
:0045DB83 8B00                    mov eax, dword ptr [eax]

* Possible StringData Ref from Code Obj ->"@"
                                  |
:0045DB85 8B1508364500            mov edx, dword ptr [00453608]
:0045DB8B E8B00FFDFF              call 0042EB40
:0045DB90 A15CEE4500              mov eax, dword ptr [0045EE5C]
:0045DB95 8B00                    mov eax, dword ptr [eax]
:0045DB97 E880ECFCFF              call 0042C81C
:0045DB9C A1A4ED4500              mov eax, dword ptr [0045EDA4]
:0045DBA1 8B00                    mov eax, dword ptr [eax]
:0045DBA3 E82410FDFF              call 0042EBCC
:0045DBA8 E8475CFAFF              call 004037F4
:0045DBAD 000000                  BYTE  3 DUP(0)


:0045DBB0 FFFFFFFF                BYTE  4 DUP(0ffh)


:0045DBB4 0A00                    or al, byte ptr [eax]
:0045DBB6 0000                    add byte ptr [eax], al
:0045DBB8 4C                      dec esp
:0045DBB9 6F                      outsd
:0045DBBA 636B39                  arpl dword ptr [ebx+39], ebp
:0045DBBD 382E                    cmp byte ptr [esi], ch
:0045DBBF 686C700000              push 0000706C  〈--------程式碼結束處


從程式碼結束處往上找,很快就找到一個 push ebp的指令,指令的地址是:0045DB30
去除基址是:5db30 就先試試它吧。用 peditor 再次開啟 DUMP 下來的程式,填寫入口點為 5db30
試執行,竟然一次執行成功,哈哈,程式就這樣被脫殼了,運氣不錯。
一個吹大牛的東東就這樣搞定了。
-------------------------------------------------------------
從這一次脫殼過程中,我的體會是:
lock98 的加密有很多地方做得不好,
1.在讀加密盤以前就將所有的程式碼段進行的還原。
2.沒有對原程式的引入表進行加密
3.沒有對記憶體DUMP進行防範。
還有,找入口點還可以從某種編譯程式的特點入手,從它的入口程式碼的特點去多次嘗試,可能會有很大的收穫。

相關文章