史萊姆論壇

返回   史萊姆論壇 > 教學文件資料庫 > 資訊系統安全備援防護技術文件
忘記密碼?
論壇說明

歡迎您來到『史萊姆論壇』 ^___^

您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的!

請點擊這裡:『註冊成為我們的一份子!』

Google 提供的廣告


 
 
主題工具 顯示模式
舊 2003-12-12, 03:07 AM   #1
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設 **** 主程序脫殼筆記

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 ........G..鵒..
...............

指向引入函數名
__________
| |
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..?G..鵒..
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 禗幋.嵥J骺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檢視時,引入表已經顯示正常。

待續。。。。。(還有一個問題,就是OEP入口點問題)
找入口點前,先把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進行防範。
還有,找入口點還可以從某種編譯程序的特點入手,從它的入口程式碼的特點去多次嘗試,可能會有很大的收穫。
從上面的程序中,已經得到了脫殼後的文件,執行可以正常執行。但是檢視文件的大小,我發現DUMP下來的文件比原文件大了很多,不太滿意,再一次開始DIY。

原文件大小 758784 字元,其中加密殼所用的大小是16384(十六進位 4000)字元,這就是說,真正的原文件應該是742400 字元,這才是真正的程序大小。

而DUMP下來的文件大小處理完成時是 815104 字元,比原程序大了很多,造成這結果原因與32位程序的文件結構有關(有空會將此做詳細分析),得到這樣的脫殼文件當然不是最理想的,於是想把這一個文件再一次進行處理,將其真正做到與原程序一樣。

在這一次處理程序中,還是想到了另一個取巧的辦法,因為在原程序中,除了程式碼段被經過變換之外,其它的內容並沒有發生變化。於是就想到將DUMP下來的程序中的程式碼段複製到原程序中,再去除原程序中的加殼的程式碼。就可以得到一個理想的程序了。

用 peditor 開啟原程序,檢視它的 sections (節表):


Sention Virtual size Virtual Offset Raw Size Raw Offset Characteristics
CODE 005CBC4 0001000 0005CC00 00000400 E0000020
DATA ......
BSS ......
.isata
.tls
.rdata
.reloc
.rsrc

其中:CODE :是程式碼段
Virtual size :是文件被載入到記憶體中時的節的大小
Virtual Offset:是文件被載入到記憶體中時的節的偏移(加上基位址後就可以得到實際位址)
Raw Size :是該節在文件中的實際大小,在這個文件中,程式碼段的長度是5CC00.
Raw Offset :是該節在文件中的實際位置,在這個文件中,程式碼段位置從400(即1024)處開始

檢視 DUMP 下來的程序,它的 sections 如下:


Sention Virtual size Virtual Offset Raw Size Raw Offset Characteristics
CODE 005CBC4 0001000 0005CBC4 00001000 E0000020
DATA ......
BSS ......
.isata


在這個DUMP文件中,程式碼段的長度是5CBC4.
在這個DUMP文件中,程式碼段位置從1000(即4096)處開始.

分析到這裡,問題這十分明顯了,只要把 DUMP 下來的程序的 1000 開始的 5CBC4 字元的內容(十六進位),複製到原程序中的 400 開始的位置,覆蓋原程序的程式碼段,程序就可以被還原。

再將加殼的16384字元刪除,入口點修改一下等後期處理,終於得到一個理想的文件。

--------------------------------------------------------------------------------
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次
 



發表規則
不可以發文
不可以回覆主題
不可以上傳附加檔案
不可以編輯您的文章

論壇啟用 BB 語法
論壇啟用 表情符號
論壇啟用 [IMG] 語法
論壇禁用 HTML 語法
Trackbacks are 禁用
Pingbacks are 禁用
Refbacks are 禁用


所有時間均為台北時間。現在的時間是 04:51 PM


Powered by vBulletin® 版本 3.6.8
版權所有 ©2000 - 2024, Jelsoft Enterprises Ltd.


SEO by vBSEO 3.6.1