亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 邏輯算法 > 正文

第五節 脫殼高級篇

2019-09-10 09:02:25
字體:
來源:轉載
供稿:網友

 
1、認識Import表
著者: [yAtEs] [Jamesluton@hotmail.com]
譯者:hying[CCG]
標題:PE輸入表說明
例子:下載
有很多介紹PE文件的文章,但是我打算寫一篇關于輸入表的文章,因為它對于破解很有用。
我想解釋它的最好的方法是舉一個例子,你可以跟著我逐步深入,一步一步的思考,最后你將完全明白,我選擇了一個我剛下載下來的小程序,它是用TASM編譯的,有一個比較小的輸入表,所以我想它應該是個不錯的范例。
好了,讓我們開始吧。首先我們得找到輸入表,它的地址放在PE文件頭偏移80處,所以我們用16進制編輯器打開我們的EXE文件,我們先得找到PE文件頭的起始點,這很簡單,因為它總是以PE00開始,我們可以在偏移100處找到它。在一般的WIN32程序中文件頭偏移被放在文件0X3C處,在那我們通??煽吹?0 01 00 00,由于數據存儲時是低位在前,高位在后的,所以翻轉過來實際就是00000100,就象前面我們說的。接下來我們就可以在PE文件中找到我們的輸入表,100+80=180在偏移180處我們看到0030 0000,翻轉一下,它其實應該是00003000,這說明輸入表在內存3000處,我們必須把它轉換成文件偏移。
一般來說,輸入表總是在某個段的起始處,我們可以用PE編輯器來查看虛擬偏移,尋找3000并由此發現原始偏移。很簡單的。打開我們看到:
-CODE 00001000 00001000 00000200 00000600
-DATA 00001000 00002000 00000200 00000800
.idata 00001000 00003000 00000200 00000A00
.reloc 00001000 00004000 00000200 00000C00
找一下,我們就發現.idata段的虛擬偏移是3000,原始偏移是A00,3000-A00=2600,我們要記住2600,以便以后轉換其它的偏移。如果你沒找到輸入表的虛擬偏移,那么就找一下最接近的段。
來到偏移A00處,我們就看到被稱為IMAGE_IMPORT_DESCRIPTORs(IID)的東東,它用5個字段表示每一個被調用DLL的信息,最后以Null結束。
**************************************************************************
(IID) IMAGE_IMPORT_DESCRIPTOR的結構包含如下5個字段:
OriginalFirstThunk TimeDateStamp ForwarderChain Name FirstThunk


OriginalFirstThunk
該字段是指向一32位以00結束的RVA偏移地址串,此地址串中每個地址描述一個輸入函數,它在輸入表中的順序是不變的。

TimeDateStamp
一個32位的時間標志,有特殊的用處。

ForwarderChain
輸入函數列表的32位索引。

Name
DLL文件名(一個以00結束的ASCII字符串)的32位RVA地址。

FirstThunk
該字段是指向一32位以00結束的RVA偏移地址串,此地址串中每個地址描述一個輸入函數,它在輸入表中的順序是可變的。
**************************************************************************

好了,你有沒有理解?讓我們看看我們有多少IID,它們從偏移A00處開始
3C30 0000 / 0000 0000 / 0000 0000 / 8C30 0000 / 6430 0000
{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}
5C30 0000 / 0000 0000 / 0000 0000 / 9930 0000 / 8430 0000
{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}
0000 0000 / 0000 0000 / 0000 0000 / 0000 0000 / 0000 0000

每三分之一是個分界,我們知道每個IID包含了一個DLL的調用信息,現在我們有2個IID,所以我們估計這個程序調用了2個DLL。甚至我可以打賭,你能推測出我們將能找到什么。
每個IID的第四個字段表示的是名字,通過它我們可以知道被調用的函數名。第一個IID的名字字段是8C30 0000,翻轉過來也就是地址0000308C,將它減去2600可以得到原始偏移,308C-2600=A8C,來到文件偏移A8C處,我們看到了什么?啊哈!原來調用的是KERNEL32.dll。
好了,接下來我們就要去找出KERNEL32.dll中被調用的函數?;氐降谝粋€IID。
FirstThunk字段包含了被調用的函數名的標志,OriginalFirstThunk僅僅是FirstThunk的備份,甚至有的程序根本沒有,所以我們通??碏irstThunk,它在程序運行時被初始化。
KERNEL32.dll的FirstThunk字段值是6430 0000,翻轉過來也就是地址00003064,減去2600得A64,在偏移A64處就是我們的IMAGE_THUNK_DATA,它存儲的是一串地址,以一串00結束。如下:
A430 0000/B230 0000/C030 0000/CE30 0000/DE30 0000/EA30 0000/F630 0000/0000 0000
通常在一個完整的程序里都將有這些。我們現在有了7個函數調用,讓我們來看其中的兩個:
DE30 0000翻轉后是30DE,減去2600后等于ADE,看在偏移ADE處的字符串是ReadFile,
EA30 0000翻轉后是30EA,減去2600后等于AEA,看在偏移AEA處的字符串是WriteFile,
你可能注意到了,在函數名前還有2個這字節的00,它是被作為一個提示。
很簡單吧,你可以自己來試一下。回到A00,看第二個DLL的調用
5C30 0000 / 0000 0000 / 0000 0000 / 9930 0000 / 8430 0000
{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}
先找它的DLL文件名。9930翻轉為3099-2600 =A99,在偏移A99處找到USER32.dll。再看FirstThunk字段值:8430翻轉為3084-2600=A84,偏移A84處保存的地址為08310000,翻轉后3108-2600=B08,偏移B08處字符串為MessageBoxA。明白了吧,接下來你就可以把這些用在你自己的EXE文件上了。
摘要:
在PE文件頭+80偏移處存放著輸入表的地址,輸入表包含了DLL被調用的每個函數的函數名和FirstThunk,通常還有Forward Chain和TimeStamp。
當運行程序時系統調用GetProcAddress,將函數名作為參數,換取真正的函數入口地址,并在內存中寫入輸入表。當你對一個程序脫時你可能注意到你有了一個已經初始化的FirstThunk。例如,在我的WIN98上,函數GetProcAddress的入口地址是AE6DF7BF,在98上,所有的KERNEL32.dll函數調用地址看上去地址都象:xxxxF7BF,如果你在輸入表中看到這些,你可以利用orignal thunk重建它,或者重建這個PE程序。
好了,我已經告訴你它們是如何工作的,我不是專家,如果你發現什么錯誤,請告訴我。

2、Import表的重建

標題:重建 PE 文件的輸入表

原著:TiTi/BLiZZARD

翻譯:Sun Bird [CCG]

日期:2000年5月24日


1. 前言
=======

大家好 :) 我之所以寫這篇短文,是由于我在 Dump 時發現,很多加壓、加密軟件都使
得輸入表(Import Table)不可用,所以 Dump 出的可執行文件必須要重建輸入表。而在普
通的講授 Win32 匯編的站點上我沒有找到這樣的介紹,所以如果你對此感興趣,那么這篇
短文對你會有些幫助。

例如,為了讓從內存中 Dump 出的經 PETite v2.1 壓縮過的可執行文件正常運行,必
須重建輸入表。(對于 ASPack、PEPack、PESentry……也同樣)這就是所有 Dump 軟件
具備重建輸入表功能的原因(例如 G-RoM/UCF 制作的 Phoenix Engine(ProcDump 內含),
或者由 Virogen/PC 和我制作的 PE Rebuilder)。

鑒于這個問題十分特殊,而且比較復雜,所以我假定你已經了解了 PE 文件結構。(你
需要閱讀有關 PE 文件的文檔)

2. 預備知識
===========

首先是一些關于輸入表和 RVA/VA 的簡介。

輸入表的相對虛擬地址(RVA)儲存在 PE 文件頭部的相應目錄入口(它的偏移量為
[ PE 文件頭偏移量+80h ])。由于是虛擬偏移量,所以它和文件輸入表中的偏移量(VA)
是不匹配的(除非文件純粹是剛剛從內存中 Dump 出來的)。于是我們首先要做的事情是,
找到 PE 文件的輸入表,將 RVA 轉換為相應的 VA。為此,我們可以采用不同的辦法:你可
以自行編制軟件來分析塊(Sections)目錄并計算 VA,但最簡單的辦法是使用專門為此設
計的應用程序接口(API)。這個 API 包括在 IMAGEHLP.DLL(Win9X 和 NT 系統都使用的
一個庫)中,名為 ImageRvaToVa。下面是對它的描述(完整的內容詳見 MSDN 庫):

# LPVOID ImageRvaToVa(
# IN PIMAGE_NT_HEADERS NtHeaders
# IN LPVOID Base
# IN DWORD Rva
# IN OUT PIMAGE_SECTION_HEADER *LastRvaSection
#);
#
# 參數:
#
# NtHeaders
#
# 指示一個 IMAGE_NT_HEADERS 結構。通過調用 ImageNtHeader 函數可以獲得這個結構。
#
# Base
#
# 指定通過調用 MapViewOfFile 函數映射入內存的一個映象的基址(Base Address)。
#
# Rva
#
# 指定相對虛擬地址的位置。
#
# LastRvaSection
#
# 指向一個指定的最終 RVA 塊的 IMAGE_SECTION_HEADER 結構。這是一個可選參數。當被
#指定時,它指向一個變量,該變量包含指定映象的最后塊值,以便將 RVA 轉換為 VA。

就這么簡單。你只需要將 PE 文件映射入內存,然后調用這個函數就能夠得到輸入表的正
確 VA。

注意,下面我會忽略所有的 RVA/VA 注釋,但是,當你對重建的 PE 文件進行讀出或寫入
RVAs 操作時,不要忘記它們之間的轉換。

3. 完整說明
===========

這里是一個完整改變輸入表的例子(這個 PE 文件的輸入表已經被 PETite v2.1 壓縮過,
并且是直接從內存中 Dump 出來的):

我們用“`”表示 00,用“-”表示非字符串

0000C1E8h : 00 00 00 00 00 00 00 00 00 00 00 00 BA C2 00 00 ````````````----
0000C1F8h : 38 C2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ----````````````
0000C208h : C5 C2 00 00 44 C2 00 00 00 00 00 00 00 00 00 00 --------````````
0000C218h : 00 00 00 00 D2 C2 00 00 54 C2 00 00 00 00 00 00 ````--------````
0000C228h : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ````````````````
0000C238h : 7F 89 E7 77 4C BC E8 77 00 00 00 00 E6 9F F1 77 --------````----
0000C248h : 1A 38 F1 77 10 40 F1 77 00 00 00 00 4F 1E D8 77 --------````----
0000C258h : 00 00 00 00 00 00 4D 65 73 73 61 67 65 42 6F 78 ``````MessageBox
0000C268h : 41 00 00 00 77 73 70 72 69 6E 74 66 41 00 00 00 A```wsprintfA```
0000C278h : 45 78 69 74 50 72 6F 63 65 73 73 00 00 00 4C 6F ExitProcess```Lo
0000C288h : 61 64 4C 69 62 72 61 72 79 41 00 00 00 00 47 65 adLibraryA````Ge
0000C298h : 74 50 72 6F 63 41 64 64 72 65 73 73 00 00 00 00 tProcAddress````
0000C2A8h : 47 65 74 4F 70 65 6E 46 69 6C 65 4E 61 6D 65 41 GetOpenFileNameA
0000C2B8h : 00 00 55 53 45 52 33 32 2E 64 6C 6C 00 4B 45 52 ``USER32.dll`KER
0000C2C8h : 4E 45 4C 33 32 2E 64 6C 6C 00 63 6F 6D 64 6C 67 NEL32.dll`comdlg
0000C2D8h : 33 32 2E 64 6C 6C 00 00 00 00 00 00 00 00 00 00 32.dll``````````

正如你看到的,這個輸入表被分成三個主要部分:

- C1E8h - C237h:IMAGE_IMPORT_DESCRIPTOR 結構部分,對應著每一個需要輸入的動態
鏈接庫(DLL)。這部分以關鍵字 00 結束。

IMAGE_IMPORT_DESCRIPTOR struct
OriginalFirstThunk dd 0 ;原拆分 IAT 的 RVA
TimeDateStamp dd 0 ;沒有使用
ForwarderChain dd 0 ;沒有使用
Name dd 0 ;DLL 名字符串的 RVA
FirstThunk dd 0 ;IAT 部分的 RVA
IMAGE_IMPORT_DESCRIPTOR ends

- C238h - C25Bh:這部分雙字(DWord) 稱作“IAT”,由 IMAGE_IMPORT_DESCRIPTOR
結構中的 FirstThunk 部分指明。這部分每一個 DWord 對應一個輸入函數。

- C25Ch - C2DDh : 這里是輸入函數和 DLL 文件的名稱。問題是,這些是沒有規定順序
的:有時候 DLL 文件在函數前面,有時候正好相反,另外一些時候它們混在一起。

輸入表的簡介
------------

OriginalFirstThunk 是 IAT 的一部分,它是 PE 文件引導時首先要搜索的。如果存在,PE
文件的引導部分將使用它來糾正在 FirstThunk IAT 部分的問題。當調入內存后,FirstThunk
的每一個 Dword (包含有函數名字符串的 RVA),將被 RVA 替換為函數的真實地址(當調用這
些函數時,它們調入內存的位置將被執行)。所以,只要 OriginalFirstThunk 沒有被改變,基
本上這里不存在輸入表的問題。 下面來看我們的問題
------------------

好了,經過簡單描述后,下面來看我們的問題。如果你試圖運行包含上面顯示的輸入表的可
執行文件,它不會被調入,Windows 會顯示一個錯誤信息。為什么?很簡單,因為
OriginalFirstThunk 被刪除了。事實上,你應該注意到,在這個輸入表的每一個IMAGE_IMPORT_DESCRIPTOR 結構,OriginalFirstThunk 的內容都是 00000000h。嗯,所以我們
可以推測出,當我們運行這個可執行程序時,PE 文件的引導部分試圖從 FirstThunk 部分獲得
輸入函數的名字。但是,正象你注意到的,這部分根本沒有包含函數名字符串的 RVA,但是函數
地址的 RVA 在內存中。

我們需要怎么做
--------------

現在,為了讓這個可執行文件運行,我們需要重建 FirstThunk 部分的內容,讓它們指向我
們在輸入表第三部分看到的函數名字符串。這不是一項很困難的任務,但是,我們需要知道哪個
IAT 對應哪個函數,而函數字符串和 FirstThunk 內容并不采用同樣的存儲方法。所以,對于每
一個 IAT,我們需要驗證它對應的是哪個函數名(事實上,根據 IMAGE_IMPORT_
DESCRIPTOR.Name DWord 我們已經有了 DLL 名稱,這些并沒有被改變)。

如何驗證每一個函數
------------------

正向我們上面所見到的,在內存中,每一個被破壞的 IAT 都有一個函數地址的 RVA。這些
地址并沒有被破壞,所以,我們只要重新找回指向錯誤 IAT 的函數地址,把它們指向函數名字
符串。
為此,在 Kernel32.dll 中有一個非常有用的 API:GetProcAddress。它允許你得到給定函
數的地址。這里是它的描述:

GetProcAddress(

HMODULE hModule // DLL 模塊的句柄
LPCSTR lpProcName // 函數名
);

所以,對于每一個被破壞的 IAT,在 GetProcAddress 返回我們尋找的函數地址之前,只需
要分析包含在輸入表第三部分的所有函數名。

- hModule 參數是 DLL 模塊的句柄(也就是說,模塊映象在內存中的基址),我們可以通
過 GetModuleHandleA API 得到:

HMODULE GetModuleHandle(
LPCTSTR lpModuleName // 返回模塊名地址句柄
);

(lpModuleName 只需要指向我們從 IMAGE_IMPORT_DESCRIPTOR.Name 部分得到的 DLL 文件
名字符串)

- lpProcName 僅指向函數名字符串。

注意,有時候函數是按序號輸入的。這些序號是在每個 [ 函數名偏移量-2 ] 處的單字(WORDS)。
所以,你在分析程序時需要檢查函數是按名稱還是按序號輸入的。

使用上面輸入表的實例
--------------------

針對上面輸入表的例子,我將說明如何修復第一個輸入 DLL 的第一個輸入函數。

1. 我們來看第一個 IMAGE_IMPORT_DESCRIPTOR 結構部分(C1E8h),.Name 部分(C1E4h,指向
C1BAh)指出了 DLL 名。我們看到,那是 USER32.dll。

2. 我們來看 .FirstThunk 部分,它們指向 IAT 部分;每個對應一個這個 DLL(user32.dll)的
輸入函數。在這里是 C1F8h,指向 C238h。所以,在 C238h,我們可以修復被破壞的 IATs。(你
會注意到,這個 IAT 部分包含二個 DWords,所以,這個 DLL 有二個函數輸入)

3. 我們得到了第一個被破壞的 IAT。它的值是 77E7897Fh。這是函數在內存中的地址。

4. 對每一個輸入表第三部分中的函數,我們調用 GetProcAddress API。當該 API 返回 7E7897Fh
時就意味著,我們到達了正確的函數。所以我們讓被破壞的 IAT 指向正確函數名(在本例中為 'wsprintfA')。

5. 現在我們只需要將 IAT 指向:偏移量(函數名字符串)-2。為什么是 -2 ?因為有時候使用了
函數序列。
所以在本例中,我們改變地址 C238h,讓它指向 C26Ah(以代替 77E7897Fh)。

6. 就這樣,這個函數被修復了,下面你只需要對所有的 IATs 重復這個過程就可以了。

后記
----

我描述的是一般的操作過程。當然只有在 DLLs 被正常調入內存后才能夠這樣做。對于其他情
況,你需要將它們調入,或者你需要仔細研究它們的輸出表才能找到正確的函數地址。

3、IceDump和NticeDump使用

  IceDump和NticeDump是一款配合SoftICE擴展其內存操作的工具,IceDump支持Windows 9x、Windows Millennium系統,NticeDump支持Windows NT/2000。它們的出現,使SoftICE如虎添翼,TRW2000的許多特色功能在SoftICE里也可實現了。

1.Icedump操作簡介
  運行IceDump前,首先要確定SoftICE版本號,按Ctrl+D切換到SoftICE下命令:VER,查看版本號。然后在相應SoftICE版本號目錄下運行icedump.exe文件,它會調用自身的VXD文件,裝載成功出現圖7.16所示畫面。如果發現SoftICE沒運行或版本不符,就拒絕運行。 如果想從內存中卸載它,可以在DOS下鍵入"icedump u"。

1)/DUMP <起始地址> [<長度> <文件名>]
  抓取內存中的數據到文件里,類似TRW2000中的W命令。<文件名>參數可以指定盤符和路徑,當在Ring-0下還原時最好清除還原區域內的全部斷點,否則會給SoftICE帶來不必要麻煩。(這一點在所有的IceDump命令里都應該值得注意)
在Win32系統下讀者可能會想到用/BHRAMA或/PEDUMP從內存內中重建一個可用的PE鏡像。請看下面關于/OPTION命令的說明。

注意: IceDump 6.015以前類似的命令是PAGEIN D <address> [<length> <200456124836.htm>]

2)/LOAD <地址> <長度> <文件名>
  把<文件>指定長度的字節內容調入到內存中的<地址>處。與/DUMP的作用相反,同樣需要注意的是不要設置斷點。

3)/BHRAMA <Bhrama dumper server 窗口名>
  用Procdump的Bhrama(由G-Rom出品的著名脫工具)來初始化dumping。用戶必須提供窗口的名稱,可以從標題條找到它。為了使工作簡單化,可以在winice.dat里設置F3鍵:
F3="/BHRAMA ProcDump32 - Dumper Server;"

4) /TRACEX <low EIP> [<high EIP>]
  控制跟蹤器并退出SoftICE。注意該命令只能用于跟蹤當前線程,如果要跟蹤其它線程,請使用/TRACE命令。


  /TRACEX <low EIP>: 跟蹤當前線程。注意,如果跟蹤當前線程彈出SoftICE窗口后想繼續跟蹤,必須使用/TRACEX命令,否則跟蹤器會失去對當前線程的控制。
   當線程的EIP到達<low EIP>時,跟蹤停止并彈出SoftICE窗口。這也要求EIP真正可以到達,否則SoftICE不會彈出。


  /TRACEX <low EIP> <high EIP> 跟蹤當前線程,注意事項同上。
  當線程的EIP到達<low EIP>與<high EIP>之間的區域內時停止并彈出SoftICE窗口。注意這里沒有作<low EIP>和<high EIP>的邊界檢查,所以錯誤的參數地址會使SoftICE不能中斷。

5) /SCREENDUMP [<文件名>]
  把SoftICE屏幕內容保存到一個文件中。注意該功能只支持通用顯示驅動模式。這個命令的用法類似于/DUMP,如果沒有指定<文件名>,IceDump將在模式0、1、2、3和4中切換。
  模式1:默認模式,將以ASCII格式輸出。
  模式0:字節屬性也將被抓取。
  模式2:可以把屏幕內容保存成一個HTML文件。
  模式3:會把屏幕內容保存成LaTeX格式的文件。
  模式4 :把屏幕內容保存為EPS (encapsulated Postscript)格式。

2.NticeDump操作簡介
  Nticedump遠不如IceDump功能強大,并且Nticedump裝載方式不同于IceDump,它是通過給SoftICE打補丁來實現0特權級控制權的,這是因為在Windows 2000上,要切換到0特權級不象Windows9x那么容易了。
  要打補丁的文件是/WINNT/SYSTEM32/DRIVERS/Ntice.sys,在Nticedump目錄里有一補丁工具ntid.exe,把安裝目錄下相應SoftICE版本的Icedump文件與ntid.exe一同復制到/WINNT/SYSTEM32/DRIVERS/目錄下,然后運行ntid.exe程序就能正確補丁Ntice.sys。這樣Nticedump和SoftICE就完全結合了。

1) 抓取內存數據:PAGEIN D 基地址 長度 文件名
例: PAGEIN D 400000 512 /??/C:/memory.dmp


注意: 在NT輸入輸出管理系統中,象"C:/memory.dmp"不是合法路徑。"/??/C:/200456124836.htm.dmp"是在C盤根目錄下創建"200456124836.htm.dmp"文件。

2) 抓取進程: PAGEIN B <Bhrama窗口名>
例: PAGEIN B ProcDump32 - Dumper Server

3) 導入文件: PAGEIN L 基地址 長度 文件名
Example: PAGEIN L 400000 512 /??/C:/memory.dmp


4) 幫助: PAGEIN 例: PAGEIN

 4、Import REConstructor使用

   Import REConstructor可以從雜亂的IAT中重建一個新的Import表(例如加軟件等),它可以重建Import表的描述符、IAT和所有的ASCII函數名。用它配合手動脫,可以脫UPX、CDilla1、PECompact、PKLite32、Shrinker、ASPack ASProtect等。該工具位于:光盤/tools/PE tools/Rebuilders/Import REConstructor。
在運行Import REConstructor之前,必須滿足如下條件:
1) 目標文件己完全被Dump到另一文件;
2) 目標文件必須正在運行中;
3) 事先要找到真正的入口點(OEP);
4) 最好加載IceDump,這樣建立的輸入表較少存在跨平臺的問題。

步驟如下:

(1)找被脫的入口點(OEP);
(2)完全Dump目標文件;
(3)運行Import REConstructor和需要脫的應用程序;
(4)在Import REConstructor下拉列表框中選擇應用程序進程;
(5)在左下角填上應用程序的真正入口點偏移(OEP);
(6)按"IAT AutoSearch"按鈕,讓其自動檢測IAT位置, 出現"Found address which may be in the Original IAT.Try 'Get Import'"對話框,這表示輸入的OEP發揮作用了。
(7)按"Get Import"按鈕,讓其分析IAT結構得到基本信息;
(8)如發現某個DLL顯示"valid :NO" ,按"Show Invalids"按鈕將分析所有的無效信息,在Imported Function Found欄中點擊鼠標右鍵,選擇"Trace Level1 (Disasm)",再按"Show Invalids"按鈕。如果成功,可以看到所有的DLL都為"valid:YES"字樣;
(9)再次刷新"Show Invalids"按鈕查看結果,如仍有無效的地址,繼續手動用右鍵的Level 2或3修復;
(10)如還是出錯,可以利用"Invalidate function(s)"、"Delete thunk(s)"、編輯Import表(雙擊函數)等功能手動修復。
(11)開始修復已脫的程序。選擇Add new section (缺省是選上的) 來為Dump出來的文件加一個Section(雖然文件比較大,但避免了許多不必要的麻煩) 。
(12)按"Fix Dump"按鈕,并選擇剛在(2)步Dump出來的文件,在此不必要備份。如修復的文件名是"Dump.exe",它將創建一個"Dump_.exe",此外OEP也被修正。
(13)生成的文件可以跨平臺運行。

1、ASProtect v0.95保護

教程寫作: 看雪
技術指導:D.boy 和RuFeng
寫作日期:2000年5月30日
目標程序:ShowDep 4.0 beta 1
程序大?。篠howdep.exe 為177K
程序下載:ShowDep 4.0
使用工具:Softice 4.05; ProcDump 1.6.2 Final; FrogsICE v0.43;Icedump 6.016

  首先忠心感謝D.boy 和RuFeng的熱心幫助,是在他們的幫助下,我才對PE文件有一定程度的了解。我把從他們那里吸取的經驗總結了一篇文章,希望對大家有所幫助。為了使初學者能更好理解這文章,本人盡量寫的仔細點。


一、Import表的一些理論知識

在你看這篇文章之前你應對PE文件的結構有一定了解否則請先看看PE介紹.

1、現在不少軟件后Import表被損壞或地址發生改變,需要我們手動找到正確的Import表來替換被破壞的Import表,并修正Import表的地址,程序才能正確執行。

程序裝載時需要裝載很多函數和DLL文件這時程序需要判定目標函數的地址并將該函數插補到該執行文件的映像中,所需要的信息都是放在PE文件的Import表,PE文件中的每一個輸入函數都明確的列于該表中。 一般來說Import表是存放在程序的.idata塊,它一般包含其他外來DLL的函數及數據信息。但也有不少程序的Import表不存在idata塊中,給我們判斷Import表的地址造成困難,但不要著急,只要了解Import表的結構你就能迅速定位Import表的地址。

2、Import表以一個IMAGE_IMPORT_DESCRIPTOR數組開始。每一個被PE文件隱式連結進來的DLL都有一個IMAGE_IMPORT_DESCRIPTOR。在這個數組中,沒有字段指出該結構數組的項數,但它的最后一個單元是NULL,可以由此計數算出該數組的項數。IMAGE_IMPORT_DESCRIPTOR的格式如下:

image_import_descriptors結構:

IMAGE_IMPORT_DESCRIPTOR struct
 riginalFirstThunk dd 0 該字段是一個指針數組的RVA偏移。其中每一個指針都指向一IMAGE_IMPORT_BY_NAME結構
 TimeDateStamp dd 0 時間及日期標志,在這可以忽略
 ForwarderChain dd 0 正向鏈結索引,在這可以忽略
 Name dd 0 以NULL結尾的ASCII字符的RVA地址,該字符串包含輸入的DLL名,比如"Kernel32.dll" 或"USER32.DLL" (關鍵!,我們定位Import表的依據)
 FirstThunk dd 0 該字段是在Image_thunk_data聯合結構中的RVA偏移。大多數情況下,Image_thunk_data是指IMAGE_IMPORT_BY_NAME結構的指針。如果不是一個指針的話,那它就是該功能在DLL中的序號。
IMAGE_IMPORT_DESCRIPTOR ends

3、為了使大家更好理解,我們以ShowDep 4.0 beta的Import表為例,ShowDep 4.0用 ASProtect 加,用prodump 分析,發現沒有idata段。 脫大師D.boy很成功分析出該軟件的Import表:import rav 0042D104,size 00001470 ;Image Base(基址)=00400000。

軟件的Import表的image_import_descriptors結構如下:


-----SHOWDEP!.rdata+1104--------------------------dword-------------PROT---(0)--
0030:0042D104 ①0002D23C ②00000000 ③00000000 ④0002DA8A <............... ^
0030:0042D114 ⑤0002C070 ⑥0002D43C ⑦00000000 ⑦00000000 p...<........... v

(圖一)
為了解釋方便,我在每個數據前加了序號。上圖就是一個典型的Import表開始處的image_import_descriptors結構,Import表就是以這個數組開始的一段連續內存空間,在這里大小是1470的連續空間。各項數據含義如下:

IMAGE_IMPORT_DESCRIPTOR struct
 riginalFirstThunk dd 0 ①0002D23C
 TimeDateStamp dd 0 ②00000000
 ForwarderChain dd 0 ③00000000
 Name dd 0 ④0002DA8A(關鍵!,我們定位Import表的依據)
 FirstThunk dd 0 ⑤0002C070
IMAGE_IMPORT_DESCRIPTOR ends

現在我們將image_import_descriptors結構中每項的地址均顯示分析一下:


① Name選項(我們定位Import表地址就是以此為依據的)

在這例Name項值為:④0002DA8A

下命令DD 42DA8A (顯示內存地址42DA8A的數據,其中42DA8A=④0002DA8A+Image Base(基址))

-----SHOWDEP!.rdata+1A8A--------------------------dword-------------PROT---(0)--
0030:0042DA8A 4E52454B 32334C45 4C4C442E 019A0000 KERNEL32.DLL.... ^
0030:0042DA9A 64616F4C 73727543 0041726F 6F4C01AB LoadCursorA...Lo v

(圖二)
想必大家己睜大眼睛了,發現什么有價值的東西?對,就是KERNEL32.DLL!就是我們的突破口。

Import表裝載的基本原理是:根據Import表的指示找到外部模塊的文件名,再使用Win32 API函數GetModuleHandleA獲得該模塊在內存中的句柄。如果沒在內存中就使用LoadLibraryA API調用裝入該模塊。隨后使用獲得的模塊句柄調用Win32 API函數GetProcAddress 獲得該模塊中Import表指定功能的實際地址,加上裝入基址,并且填入Import表的FirstThunk所指的IMAGE_IMPORT_BY_NAME結構指針數組中,完成該模塊的一個功能的人工裝入填寫。循環調用函數GetProcAddress以獲得其他功能調用的地址,加上裝入基址,并填入之,以完成一個外部模塊的裝入。再循環上述過程對其他模塊進行裝入。

因此我們可以從函數LoadLibraryA入手,該函數會裝入外部模塊,我們視這函數的入口參數是否為KERNEL32.DLL,以此來確定Import表的狀況。即確定 image_import_descriptors結構中的name選項。

函數LoadLibrary:

HINSTANCE LoadLibrary(
 LPCTSTR lpLibFileName // 執行模塊的文件名和地址
);

只要函數LoadLibrary參數的模塊名為KERNEL32.DLL,就會出現圖二的情況,這時KERNEL32.DLL地址為0042DA8A。因此image_import_descriptors結構中name為0042DA8A―400000=2DA8A,這時利用S命令在內存中查找字條串002DA8A,就可確定import表的地址。


(到這里我們就能確定Import表的地址了,下面幾項可幫助我們大家更好理解Import表)

②riginalFirstThunk項

在這里riginalFirstThunk項值為:①0002D23C

下命令DD 42D23C (顯示內存地址42D23C的數據,其中42DA8A=①0002D23C+Image Base(基址))

-----SHOWDEP!.rdata+123C--------------------------dword-------------PROT---(0)--
0030:0042D23C 0002D798 0002D7A8 0002D7BE 0002D782 ................ ^
0030:0042D24C 0002D7CC 0002D7E0 0002D7F6 0002D80A ................ ^
0030:0042D25C 0002D81C 0002D830 0002D840 0002D854 ....0...@...T... v
0030:0042D26C 0002D868 0002D87C 0002D890 0002D8A0 h...|........... v

(圖三)
圖三是一個指針數組,其中每一個指針都指向一IMAGE_IMPORT_BY_NAME結構。

我們以第一個指針0002D798為例,顯示它所指的IMAGE_IMPORT_BY_NAME結構.
下命令:dd 42d798(注意:0002D798+Image Base(基址))

-----SHOWDEP!.rdata+1798--------------------------dword-------------PROT---(0)--
0030:0042D798 6547011B 636F4C74 69546C61 0000656D ..GetLocalTime.. ^
0030:0042D7A8 6F430025 6E69746E 65446575 45677562 %.ContinueDebugE ^
0030:0042D7B8 746E6576 022B0000 65736552 65764574 vent..+.ResetEve v
0030:0042D7C8 0000746E 615702CB 6F467469 62654472 nt....WaitForDeb v

(圖四)
③FirstThunk項

在這例,FirstThunk項的值為:⑤0002C070


下命令dd 42c070 (注意:0002c070+Image Base(基址)):

-----SHOWDEP!.rdata+0070--------------------------dword-------------PROT---(0)--
0030:0042C070 0002D798 0002D7A8 0002D7BE 0002D782 ................ ^
0030:0042C080 0002D7CC 0002D7E0 0002D7F6 0002D80A ................ ^
0030:0042C090 0002D81C 0002D830 0002D840 0002D854 ....0...@...T... v
0030:0042C0A0 0002D868 0002D87C 0002D890 0002D8A0 h...|........... v

(圖五)
圖五是一個指針數組(Image_thunk_data聯合結構),大多數情況下,Image_thunk_data是指IMAGE_IMPORT_BY_NAME結構的指針。如果不是一個指針的話,那它就是該功能在DLL中的序號。不知你發現沒有,圖五的數據和圖三完全相同,原因就是這個。

二、確定Import表的地址和大小并修正Import表

通過上面的講解,想必大家對Import表己比較熟悉了吧,現在以脫ShowDep 4.0 beta 1的為例,講解定位Import表的位置和大小的幾種方法。

方法一:通過idata來確定Import表的位置

大部分加程序的塊表中都有.idata這一項,.idata包含其他外來DLL的函數及數據信息,也就是說Import表的起始地址就是.idata的地址。如是這種情況,脫就簡單多了。

先dump取正確的Import表(假設取名為idata.bin),然后在解壓入口點full dump取整個程序(假設取名為dump.exe)用 Procdump打開dump.exe文件, 察看.idata Section. 記下Raw Size和 Raw Offset的值。用HexWorkshop打開dump.exe 將idata.bin拷貝/粘貼到 dump.exe(粘貼位置為Raw Offset 大小為Raw Size). 再修正Entry Point和Import表的地址(此值就是.idata的RVA)

具體操作參考后面幾節的脫教學實例。

方法二:沒.idata一項,利用bpx loadlibrarya來判斷Import表的位置

由于ShowDep 4.0 beta 1沒.idata一項,因此要確定Import表的位置和大小較困難,步驟如下:

①分析ShowDep 4.0 beta 1的文件PE頭

運行 Procdump,點擊pe-editor按鈕,選中ShowDep.exe文件:

Size of image : 000A0000 ; 這個PE文件執行時分配的內存空間。
Image Base : 00400000 ; 基址

②確定Import表的地址

a.先裝載Icedump
在這用Icedump 6.016版本,其命令操作形式完全和以前的版本不同。先在Icedump目錄里運行相應SOFTICE版本的icedump.exe(我用的SOFTICE是4.05版,因此在win9x/405目錄下運行icedump.exe),如Icedump裝載成功,Icedump會返回如下信息:

icedump v6.0.1.6 for winice v4.05 loader
icedump unloaded
icedump loaded ←出現這句話表示Icedump裝載成功

C:>

(圖六)
b.再裝載FrogsICE
由于ShowDep能檢測到SOFTICE的存在,因此裝載Frogsice就可躲過。在我機子里:FrogsICE 1.00 Final和Icedump不能很好兼容工作,因此我將FrogsICE換成版本v0.43,hehe..它們配合的很好。雙擊FPloader.exe文件即可裝載成功。
OK到此你的SOFTICE的功能己大大加強里。
這時試試運行ShowDep,這時屏幕將藍屏給你一菜單選項,告知ShowDep發現了SOFTICE,是否欺騙它,這時你按ESC按鈕,程序即可正常運行。(注:我的SOFTICE用icepath打過補丁)


c、攔截函數loadlibararya


下命令:bpx loadlibrarya do "dd esp->4"
(注:在TRW2000下實現同樣功能的命令是: bpx loadlibrarya do "dd *(esp+4)"

這個命令就是當攔截loadlibararya函數時,顯示其入口參數的在內存的值,如:

0137:00710242 PUSH EAX
0137:00710243 CALL [loadlibarary] ;當調用此函數將中斷,并顯示push參數的值,在這里即:d eax

ok斷點設置好后,運行ShowDep程序,將中斷,此時按F5一直到數據窗口顯示為:KERNEL32.DLL字符。在我win97系統下,只要按兩下F5即可看到如下情況:

-----SHOWDEP!.rdata+1A8A--------------------------dword-------------PROT---(0)--
0030:0042DA8A 4E52454B 32334C45 4C4C442E 019A0000 KERNEL32.DLL.... ^
0030:0042DA9A 64616F4C 73727543 0041726F 6F4C01AB LoadCursorA...Lo v

(圖六)
hehe...看看圖六和圖三是不是一樣??!其中前面的地址0042DA8A就是關鍵。
0042DA8A就是image_import_descriptors結構中的name項的值,因為該結構如下:

0030:0042D104 0002D23C 00000000 00000000 0002DA8A <............... ^
0030:0042D114 0002C070 0002D43C 00000000 00000000 p...<........... v

因此這時我要在數據窗口向前查找字符串0002DA8A(0002DA8A=0042DA8A-基址):

下命令:S DS:400000 L FFFFFFFF 8A DA 02 00
(注:在TRW2000下實現同樣功能的命令是: S 30:0 L FFFFFFFF 8A DA 02 00)(用上面的好象不行但愿新版能改進)
結果如下:

-----SHOWDEP!.rdata+1100--------------------------dword-------------PROT---(0)--
013F:0042D100 0042B385 0002D23C 00000000 00000000 ..B.<........... ^
013F:0042D110 0002DA8A 0002C070 0002D43C 00000000 ....p...<....... v

(圖七)
仔細比較圖七和圖一,發現這就是Import表的IMAGE_IMPORT_DESCRIPTOR數組。
如你看不習慣,可再下命令: D 42D110-C 這樣就可顯示和圖一一樣的畫面了。

這樣就可確定Import表的地址是2D104=0042D104―400000(基址)

③確定Import表的大小

現己將Import表的起始地址確定了:RVA=42D104。只要確定Import表的尾部就可計算出其大小,Import表在內存里是連續存放的一段數據,其一般結尾處一段內存空間都是0在此例,你開始先定位來到Import表的起始處,按ALT+↓向下翻頁(或ALT+PageDown),直到看到如下情況:

013F:0042E54A 65530262 766E4574 6E6F7269 746E656D b.SetEnvironment
013F:0042E55A 69726156 656C6261 011D0041 4C746547 VariableA...GetL
013F:0042E56A 6C61636F 666E4965 0000576F 00000000 ocaleInfoW......
013F:0042E57A 00000000 00000000 00000000 00000000 ................ v
013F:0042E58A 00000000 00000000 00000000 00000000 ................ v

(圖八)
字符串0000576F就是Import表的最后一項,其后面一位000000的地址為:42e574(其邊界就是上面紅色的W如你在SOFTICE不能確定可DUMP后在十六進制工具Hexworkshop很方便知邊界地址)

因此Import表的大?。?2E574-42D104=1470

④、找入口點

在SOFTICE你會來到如下:
0137:00710B35 MOV EDX[EAX] 
0137:00710B37 MOV EAX[EBP+08] 
0137:00710B3A ADD EDX[EAX+18]
0137:00710B3D MOV EAX[EBP+08]
0137:00710B40 MOV EAX[EAX+1C]
0137:00710B43 CALL 007104C8 ←按F8進去
0137:00710B48 POP EDI
0137:00710B49 POP ESI
0137:00710B4A POP EBX
0137:00710B4B POP ECX

按F8進去來到:

0137:007104C6 8BC0 MOV EAXEAX
0137:007104C8 89C4 MOV ESPEAX
0137:007104CA 89D0 MOV EAXEDX
0137:007104CC 8B1D34567100 MOV EBX[00715634]
137:007104D2 89041C MOV [EBX+ESP]EAX
0137:007104D5 61 POPAD
0137:007104D6 50 PUSH EAX ←此處EAX=422c3a即入口點的值
0137:007104D7 C3 RET ←返回到入口點

(圖九)
此時程序己完全解壓準備運行了。記下程序入口點:00422c3a 在dump前,清除所有的斷點:bc *. 因此你可在SOFTICE下用命令:

:/dump 400000 A0000 c:/temp/dump.exe
(如你是用Icedump 6.016以前版本用此命令:pagein d 400000 A0000 c:/temp/dump.exe)

⑤修正PE文件頭

用 Procdump打開剛建好的 dump.exe文件,點擊pe-editor按鈕,然后再點擊SECTIONS按鈕,在每個section點擊右鍵,選中Edit section,把所有的 section 的PSize == VSize offset == RVA (即讓物理地址和大小等于虛擬地址和大小)。如你是用Procdump脫的,可省去這一步。

在改完所有的sections后,按OK存盤后,你在資源管理器中刷新一下,就會發現dumped.exe的圖標回來了,但還不能運行,你還要修正入口點和import表。

將入口點(Entry Point)改為:00422c3a(記著:00422c3a-imagebase=22c3a)

再點擊Directory按鈕,將Import Table改為 RVA (2D104 );而其選項Size只要比0大就可;(這程序DUMP后improt并沒被破壞,只要把import rav/size 填上就OK了!) 在這例中,Import表的尺寸沒用上,但方法要掌握,如碰到Import表損壞的程序,就要替換Import表程了,這時需要Import表的大小了。

然后點擊OK退出Procdump,再運行 dumped.exe ,程序成功運行!


方法三:利用S命令查找字串KERNEL32.DLL來確定Import表的位置

如果軟件沒.idata項,用方法二bpx loadlibrarya do "dd esp->4"也不能看到KERNEL32.DLL,這種情況就要用S命令來協助了。

先bpx loadlibrarya do "dd esp->4"

中斷后,憑經驗來判斷Import表完全觸壓時機,一般中斷在第一次或第二次(某些情況要幾次)Import表就基本解壓結束了。這時下命令:S DS:400000 l FFFFFFFF 'KERNEL32.DLL'


會在數據區找到KERNEL32.DLL ,但這不一定是image_import_descriptors結構中對應的KERNEL32.DLL項,這要跟據具體情況來分析了,一般我們要找到的KERNEL32.DLL是在xxx:4xxxxxx的地址形式處。

如不能確定何處是關鍵的KERNEL32.DLL,只好dump后,用十六進制工具來分析了,這樣較直觀,打開后查找image_import_descriptors類似結構。

當然Import表確定方法多種,這里將本人常用的幾種方法列出供參考!也歡迎你將自己的經驗告訴大家,互相提高。

2、ASProtect v0.94b保護

英文原作:r!sc 《Almost Manual Unpacking (using Softice and Icedump)》
原作日期:6th febuary 2000
教程翻譯: 看雪
翻譯日期:2000年5月26日
聲 明: 本文以r!sc的教程為基礎,以自己的觀點補充調整。

目標程序:aspack.exe . 231424 . v 2.001
程序下載:AsPack
使用工具:Softice 4.05; ProcDump 1.6.2 Final; FrogsICE v0.43;Icedump 6.016


part1 . 理論知識

part2 . 分析原文件的PE頭

part3 . 抓取import table

part4 . Dump整個程序并修正文件頭


=part1===part1===part1===part1===part1===part1===part1===part1===part1===part1=
理論知識

這種被壓縮或加密的PE文件,執行時,在內存中將會完全解壓。其中import表在裝載中也會被完全解壓或解密(―攻擊點)。其中抓取import表就很關鍵了,其具體位置,可用 Procdump分析文件頭得到。然后,要跟蹤程序完全解壓后的跳到程序處的入口點,然后在內存里dump取程序的整個部分。將剛dump取的正確import表用十六進制工具粘貼到完全dump的程序,再 修正文件頭,這樣程序就可正常運行。


=part2===part2===part2===part2===part2===part2===part2===part2===part2===part2=
分析原文件的PE頭

運行 Procdump,點擊pe-editor按鈕,選中ASPack.exe文件,我們想要得到程序解壓后的尺寸,import表的地址和大小...幸運的是這個文件的每個塊(section )都存在。

Size of image : 00079000 ; 這個PE文件執行時分配的內存空間。
Image Base : 00400000 ; 基址

.idata ;.idata包含其他外來DLL的函數及數據信息
Virtual Size : 00002000 ; idata在內存的尺寸
Virtual Offset : 00046000 ; idata的地址(+imagebase == 00446000)

.rdata
Virtual Size : 00001000
Virtual Offset : 00049000

import表有可能在idata塊或rdata塊,到底在哪部分?看看它們的尺寸,我將馬壓在.idata ...


=part3===part3===part3===part3===part3===part3===part3===part3===part3===part3=
抓取import table

1、先裝載Icedump
在這用Icedump 6.016版本,其命令操作形式完全和以前的版本不同。先在Icedump目錄里運行相應SOFTICE版本的icedump.exe(我用的SOFTICE是4.05版,因此在win9x/405目錄下運行icedump.exe),如Icedump裝載成功,Icedump會返回如下信息:

icedump v6.0.1.6 for winice v4.05 loader
icedump unloaded
icedump loaded ←出現這句話表示Icedump裝載成功

C:>

2、再裝載FrogsICE
由于aspack能檢測到SOFTICE的存在,因此裝載Frogsice就可躲過。在我機子里:FrogsICE 1.00 Final和Icedump不能很好兼容工作,因此我將FrogsICE換成版本v0.43,hehe..它們配合的很好。雙擊FPloader.exe文件即可裝載成功。
OK到此你的SOFTICE的功能己大大加強里。
這時試試運行aspack,這時屏幕將藍屏給你一菜單選項,告知aspack發現了SOFTICE,是否欺騙它,這時你按ESC按鈕,程序即可正常運行。

3、 記住我們的第一步是抓取import table,它在內存的446000到449000處,因此程序運行時注意這段內存代碼的解壓情況。
由于SOFTICE不能LOAD aspack.exe我們用:bpx loadlibrarya命令來攔斷。

loadlibrarya命令解釋:如果import表沒在內存中就使用LoadLibraryA API調用裝入該模塊,因此我們可以攔截此函數來觀察import表。


:bpx loadlibrarya 然后運行aspack將中斷如下:
Break due to BPX KERNEL32!LoadLibraryA
:dd 446000 l 40 (下此命令觀察內存446000到449000處的數據)


.
-------SPACK!.idata--------------------dword----------ROT--?(0)--
0030:00446000 ???????? ???????? ???????? ???????? ................ 
0030:00446010 ???????? ???????? ???????? ???????? ................ 
0030:00446020 ???????? ???????? ???????? ???????? ................ 
0030:00446030 ???????? ???????? ???????? ???????? ................

上圖是SOFTICE的數據窗口,顯示 ??...說明import表在內存中沒解壓。
再按F5一下,程序將中斷如下:(記著:在這例中只能要按一下F5,否則將不能抓取正確的import表)

0030:00446000 00000000 00000000 00000000 0004669C .............f..
0030:00446010 0004612C 00000000 00000000 00000000 a..............
0030:00446020 000468B6 000461AC 00000000 00000000 .h...a..........
0030:00446030 00000000 000468D0 000461B4 00000000 .....h...a......

這時446000處不是?? ?? ?? ??,意味著import表己被解壓了。

.import表以一個IMAGE_IMPORT_DESCRIPTOR數組開始。 image_import_descriptors數據有5組dwords組成。

image_import_descriptors結構:
①dd offset original_first_thunk
②dd timedatestamp    時間及日期標志
③dd forwardchain    正向鏈結索引
④dd offset library name以NULL結尾的ASCII字符的RVA地址,該字符串包含輸入的DLL名,
            比如"Kernel32.dll"或"USER32.DLL"。
⑤dd offset first_thunk 該字段是在Image_thunk_data聯合結構中的RVA偏移

其中timedatestamp和forwardchain通常設置為00000000 original first thunk 選項不是必須的.

:dd 446000 l 40
0030:00446000 00000000 00000000 00000000 0004669C .............f..
0030:00446010 0004612C 00000000 00000000 00000000 a..............

地址4669c 指向 LibraryName (RVA 你需要加上基址imagebase+400000)

:db 44669c l 10
0030:0044669C 4B 45 52 4E 45 4C 33 32-2E 44 4C 4C 00 00 00 00 KERNEL32.DLL....

地址612c指向 first_thunk 庫。

:dd 44612c l 10
0030:0044612C 000466AA 000466C2 000466DA 000466F2 .f...f...f...f..

這些是以NULL結尾的ASCII字符的RVA地址, . . 466aa 是第一個API函數的地址,466c2是第二個API函數地址...它們以以NULL結尾。


:db 0004466aa l 20
0030:004466AA 00 00 44 65 6C 65 74 65-43 72 69 74 69 63 61 6C ..DeleteCritical
0030:004466BA 53 65 63 74 69 6F 6E 00-00 00 4C 65 61 76 65 43 Section...LeaveC

通過上面的分析可知這就是原始的.import表,快dump it!!(看看上文的image_import_descriptors地址)

:/dump 446000 2000 c:/aspack.idata.bin
(如你是用Icedump 6.016以前版本用此命令:pagein d 446000 2000 c:/aspack.idata.bin)


為了方便大家對比,特將dump正確的import表放在此下載。


=part4===part4===part4===part4===part4===part4===part4===part4===part4===part4=
Dump整個程序并修正文件頭

1、現在我們要找程序的入口點,下命令:bpx loadlibrarya ,然后按14下F5然后按F10一步一步跟蹤來到如下代碼

0137:00C1150E 8B4508 MOV EAX[EBP+08]
0137:00C11511 8B10 MOV EDX[EAX] DS:004664FC=00400000
0137:00C11513 8B4508 MOV EAX[EBP+08]
0137:00C11516 035018 ADD EDX[EAX+18]
0137:00C11519 8B4508 MOV EAX[EBP+08]
0137:00C1151C 8B401C MOV EAX[EAX+1C]
0137:00C1151F E874F9FFFF CALL 00C10E98 ←在此按F8進入
0137:00C11524 5F POP EDI
0137:00C11525 5E POP ESI
0137:00C11526 5B POP EBX
0137:00C11527 59 POP ECX
0137:00C11528 59 POP ECX
0137:00C11529 5D POP EBP
0137:00C1152A C20400 RET 0004


F8進入后來到如下:

0137:00C10E96 8BC0 MOV EAXEAX
0137:00C10E98 89C4 MOV ESPEAX
0137:00C10E9A 89D0 MOV EAXEDX
0137:00C10E9C 8B1D6C66C100 MOV EBX[00C1666C]
0137:00C10EA2 89041C MOV [EBX+ESP]EAX
0137:00C10EA5 61 POPAD
0137:00C10EA6 50 PUSH EAX ;push 442b98 即為入口點
0137:00C10EA7 C3 RET ;返回到己完全解壓的代碼處,即入口點處。
0137:00C10EA8 C3 RET

來到入口點:

0167:00442B98 55 PUSH EBP ←此處為入口點
0167:00442B99 8BEC MOV EBPESP
0167:00442B9B 83C4F4 ADD ESP-0C

在0167:00442B98 處就可dump整個內存數據了,此時程序己完全解壓準備運行了。記下程序入口點:00442B98
在dump前,清除所有的斷點:bc *.

./dump 400000 79000 c:/aspack.dumped.exe
(如你是用Icedump 6.016以前版本用此命令:pagein d 400000 79000 c:/aspack.dumped.exe)

2、替換正確的import表

用Hexworkshop打開aspack.dumped.exe和aspack.idata.bin. Goto到exe文件的46000偏移處Select Block大小為2000. 拷貝aspack.idata.bin文件的同樣大小(2000)的Block粘貼到exe文件中以替換掉不正確的.idata section然后存盤。(注意:以上所有數據都是十六進制)

3、修正PE文件頭

用 Procdump打開剛建好的 aspack.dumped.exe文件,點擊pe-editor按鈕,然后再點擊SECTIONS按鈕,在每個section點擊右鍵,選中Edit section,把所有的 section 的PSize = VSize offset = RVA 。

如:CODE 的PSize=0001E000; VSize=00042000;offset =00000400;RVA=00001000;
改成:PSize = VSize= 00042000;offset = RVA =00001000;

在改完所有的sections后,按OK存盤后,你在資源管理器中刷新一下,就會發現aspack.dumped.exe的圖標回來了,但還不能運行,你還要修正入口點和import表。

將入口點(Entry Point)改為:00042B98(記著:00442B98-imagebase=42B98)

再點擊Directory按鈕,將Import Table改為 RVA (46000 );而其選項Size只要比0大就可;

然后點擊OK退出Procdump,再運行 aspack.dumped.exe ,程序運行的很甜美!

這時你用W32DASM不能反匯編,你可用 Procdump編輯第一個section characteristics:

將其 c0000060 (data writable)改為: 60000040 (code executable)或 e0000060 (code data etc etc)

注:大家抓取屏幕可在Icedump 6.016中,用:/Screendump抓取。
不加參數命令:/Screendump 選取模式,重復執行,會在0、1、2、3、4五種模式下轉換。
模式1(默認)是以文本方式存盤,模式2是以HTML文件存盤。其它的請參考其readme.
模式選好后,就可用命令: /SCREENDUMP [路徑]文件名 抓取整個SOFTICE的屏幕。

3、ASProtect v0.9x保護


Advanced Zip Password Recovery 3.0的脫

教程寫作: ****
作者信箱: break_ice@hotmail.com
寫作日期: 2000年3月25日
版權聲明: 本文沒有版權允許任意轉貼和修改. 但如果只引用文中部分內容時請最好注明原文出處以表示對一位Cracker同行的勞動的尊重.

使用工具:
TRW2000 1.03
ProcDump 1.6.2
Hexworkshop 3.02

下載:Advanced Zip Password Recovery 3.0

比起其Beta版來AZPR 3.0正式版的保護更為加強. 1. 對Softice的多處Check用FrogsICE不能完全騙過; 2. CRC的校驗; 3. 動態地址(好象是這個名吧?); 4.對Loader的防范這回用Process Patch不行了.

用Softice跟蹤它會是一種痛苦 (當然完全可以用Softice只是你要了解程序的Anti-debugger技巧在關鍵的Check后改變跳轉方向). 這次祭出我們中國人的驕傲TRW2000來對付它.

先用Procdump的PE Editor查看一下程序的.idata section記下數值. Virtual size=2000 Virtual offset=21000. 另外記下程序的Image Base: 400000.

1. 運行TRW Load程序. 程序中斷在入口處. 但接下來無論是否BPX設斷只要G繼續運行程序便會出錯. 下Faults off G OK程序退出.
2. 試BPM 421000 (.idata的offset) 再Load程序. G 程序可以被正常中斷 COOL!
3. G當程序第三次(? 記不清了. 原則是d 421000顯示的data區見到XXXX0200 000000字樣)中斷時BD*F10直到下面的語句

*********************************
注意: 程序每次Load時Offset都不一樣你的機器中的XXXX:YYYYYYYY肯定和下面的不同. 下Code on指令這樣才好參照下面的代碼. 另外下面所摘的幾段代碼是引用高手tiamath的.因為我不清楚在TRW下如何dump屏幕 (誰能指教一下:);而用ICEDump的pagein n命令來Dump Softice的屏幕我的機器會死機. :(
*********************************

0167:004F34CD 50 PUSH EAX
0167:004F34CE B890274F00 MOV EAX004F2790
0167:004F34D3 50 PUSH EAX
0167:004F34D4 B8A4274F00 MOV EAX004F27A4
0167:004F34D9 50 PUSH EAX
0167:004F34DA B8A0284F00 MOV EAX004F28A0
0167:004F34DF 50 PUSH EAX
0167:004F34E0 B8AC274F00 MOV EAX004F27AC
0167:004F34E5 50 PUSH EAX
0167:004F34E6 B8646C4E00 MOV EAX004E6C64
0167:004F34EB 50 PUSH EAX
0167:004F34EC 8B4508 MOV EAX[EBP+08]
0167:004F34EF 8D4824 LEA ECX[EAX+24]
0167:004F34F2 8B4508 MOV EAX[EBP+08]
0167:004F34F5 8B500C MOV EDX[EAX+0C]
0167:004F34F8 8B4508 MOV EAX[EBP+08]
0167:004F34FB 8B4008 MOV EAX[EAX+08]
0167:004F34FE E899F4FFFF CALL 004F299C
0167:004F3503 33C0 XOR EAXEAX <--在這里Dump .idata

下指令 W 421000 L 2000 azprdata.bin

OK. 再往下直到

0167:004F3637 8D4818 LEA ECX[EAX+18]
0167:004F363A 8B4508 MOV EAX[EBP+08]
0167:004F363D 8B10 MOV EDX[EAX]
0167:004F363F 8B4508 MOV EAX[EBP+08]
0167:004F3642 8B401C MOV EAX[EAX+1C]
0167:004F3645 E8EAF6FFFF CALL 004F2D34 <--F8進入
0167:004F364A 5F POP EDI
0167:004F364B 5E POP ESI

到了

0167:004F2D72 E9148B1DA8 JMP A86CB88B
0167:004F2D77 8E4F00 MOV CS[EDI+00]
0167:004F2D7A EB01 JMP 004F2D7D
0167:004F2D7C EB89 JMP 004F2D07
0167:004F2D7E 041C ADD AL1C
0167:004F2D80 EB02 JMP 004F2D84
0167:004F2D82 EBE8 JMP 004F2D6C
0167:004F2D84 61 POPAD
0167:004F2D85 EB01 JMP 004F2D88
0167:004F2D87 E850EB02E9 CALL E95218DC
0167:004F2D8C 17 POP SS
0167:004F2D8D E802000000 CALL 004F2D94
0167:004F2D92 E91758C35E JMP 5F1285AE
0167:004F2D97 5B POP EBX
0167:004F2D98 59 POP ECX

此時小心地跟蹤碰到JMP時按F8而不要按F10

直到顯示變成

0167:004F2D72 E9148B1DA8 JMP A86CB88B
0167:004F2D77 8E4F00 MOV CS[EDI+00]
0167:004F2D7A EB01 JMP 004F2D7D
0167:004F2D7C EB89 JMP 004F2D07
0167:004F2D7E 041C ADD AL1C
0167:004F2D80 EB02 JMP 004F2D84
0167:004F2D82 EBE8 JMP 004F2D6C
0167:004F2D84 61 POPAD
0167:004F2D85 EB01 JMP 004F2D88
0167:004F2D87 E850EB02E9 CALL E95218DC
0167:004F2D8C 17 POP SS
0167:004F2D8D E802000000 CALL 004F2D94
0167:004F2D92 E91758C35E JMP 5F1285AE
0167:004F2D94 58 POP EAX <-- 光標位于此行時 EAX=401000
0167:004F2D95 C3 RET <--這里

下Suspend指令. 回到Windows. 用ProcDump來Dump(full)脫的程序得到azprdump.exe. 你也可以用TRW的PEDUMP命令來得到脫程序但我個人的經驗很容易死機所以我寧愿用ProcDump來做.

4. 用PE Editor修改程序的Entry Point為1000. 并查看脫后程序的.idata section. 此時Raw size=1670 Raw offset=1FC00. 修改Directory中Import Table的RVA=21000SIZE=1670.
5. 用Hexworkshop打開azprdump.exe和azprdata.bin. Goto到exe文件的1FC00偏移處Select Block大小為1670. 拷貝.bin文件的同樣大小(1670)的Block粘貼到exe文件中以替換掉不正確的.idata section.

現在再試著運行程序應該可以正常運行了. 如果程序出錯再做一件事: 把 .bss section的raw size值改為00000000 (高手tiamath的建議).

有了脫的程序大家應該會Patch它成為注冊版了吧. 只需改一個字節.

結語: 用本文所描述的方法可以對絕大多數Asprotect+Aspack保護的程序進行成功的脫. 大家讀完這篇教程不妨找幾個程序開刀. 比方說The Bat! 1.39現在不應該再難住大家了.

好了這次就到這兒了下回見.

致謝:

感謝SV Hobgoblin tiamath. 沒有他們的幫助我不可能做到這一步


(編輯:天命孤獨)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久影视三级福利片| 亚洲精品av在线播放| 国产噜噜噜噜久久久久久久久| 国产精品久久久久久av下载红粉| 国产精品尤物福利片在线观看| 热门国产精品亚洲第一区在线| 日韩精品中文字| 中文字幕少妇一区二区三区| 青青a在线精品免费观看| 欧美成aaa人片免费看| 成人在线免费观看视视频| 亚洲国产女人aaa毛片在线| 欧美综合在线第二页| 国产成人综合精品| 国产精品羞羞答答| 亚洲精品自在久久| 成人免费看黄网站| 国产日本欧美一区| 亚洲新中文字幕| 中文字幕国产精品久久| 欧美电影在线观看高清| 亚洲最大成人在线| 国产一区二区丝袜| 亚洲色图国产精品| 美日韩在线视频| 91精品国产自产在线| 国产欧美精品在线播放| 久久久久久亚洲精品中文字幕| 久久久久一本一区二区青青蜜月| 日韩欧中文字幕| 97在线看免费观看视频在线观看| 久久久女人电视剧免费播放下载| 日韩女优人人人人射在线视频| 久久久免费电影| 成人国产亚洲精品a区天堂华泰| 欧美日韩国产丝袜美女| 亚洲91精品在线观看| 精品国产一区二区三区久久狼黑人| 国产精品人成电影在线观看| 国外日韩电影在线观看| 亚洲理论电影网| 欧美第一黄色网| 26uuu国产精品视频| 国产一区二区三区中文| 久久久国产精彩视频美女艺术照福利| 成人免费激情视频| 亚洲女人天堂色在线7777| 丝袜美腿亚洲一区二区| 国产va免费精品高清在线| 日韩av网址在线| 亚洲在线视频观看| 亚洲视频一区二区三区| 国产日本欧美一区二区三区在线| 亚洲国产欧美在线成人app| 国产精品白丝jk喷水视频一区| 亚洲欧洲av一区二区| 日韩精品极品毛片系列视频| 日韩av观看网址| 97视频人免费观看| 欧美二区乱c黑人| 自拍偷拍亚洲在线| 中文字幕精品一区二区精品| 精品香蕉在线观看视频一| 国产高清在线不卡| 日韩在线免费观看视频| 亚洲免费av电影| 狠狠久久亚洲欧美专区| 欧美性猛交99久久久久99按摩| 亚洲аv电影天堂网| 成人激情视频在线播放| 国产精品狼人色视频一区| 亚洲激情在线观看视频免费| 欧美激情网友自拍| 成人在线免费观看视视频| 91精品国产色综合久久不卡98口| 国产午夜精品麻豆| 亚洲网站在线看| 国产精品亚洲аv天堂网| 日韩中文字幕第一页| 美女黄色丝袜一区| 欧美激情亚洲一区| 亚洲成人精品在线| 精品毛片三在线观看| 精品国偷自产在线视频| 日本成人精品在线| 中文字幕视频一区二区在线有码| 国产精品视频资源| 久久不射电影网| 性色av一区二区三区在线观看| 欧美成人午夜激情| 亚洲精品美女久久久久| 另类视频在线观看| 欧美精品www| 国产视频丨精品|在线观看| 亚洲国产成人精品久久| 欧美xxxx做受欧美| 日韩av网址在线观看| 欧美亚洲在线观看| 亚洲免费伊人电影在线观看av| 欧美日韩国产成人在线| 免费97视频在线精品国自产拍| 超碰97人人做人人爱少妇| 国产精品国产福利国产秒拍| 欧美性猛交xxxx富婆弯腰| 日韩激情第一页| 亚洲精品在线不卡| 777精品视频| 日韩精品免费一线在线观看| 在线播放日韩精品| 国产精品成人观看视频国产奇米| 亚洲综合大片69999| 亚洲国产成人精品女人久久久| 亚洲欧美日韩国产中文专区| 日韩视频免费大全中文字幕| www.欧美视频| 在线视频免费一区二区| 亚洲欧美国产va在线影院| 97超视频免费观看| 久久久久久久久久久人体| 欧美激情亚洲一区| 国产成人亚洲综合91| 欧美成人精品激情在线观看| 日韩亚洲欧美成人| 国产精品成人观看视频国产奇米| 久久久精品久久| 在线播放国产一区中文字幕剧情欧美| 激情亚洲一区二区三区四区| 精品一区二区三区四区在线| 视频直播国产精品| 欧美精品在线免费播放| 成人黄色免费看| 久久影院资源网| 26uuu久久噜噜噜噜| 亚洲精品美女在线观看播放| 久热精品视频在线| 国内精品中文字幕| 久久久伊人日本| 亚洲**2019国产| 日韩一级裸体免费视频| 最近2019好看的中文字幕免费| 日韩欧亚中文在线| 美女福利视频一区| 国产日韩精品在线| 精品久久久久久久中文字幕| 亚洲系列中文字幕| 国产香蕉精品视频一区二区三区| 久久久久久国产精品三级玉女聊斋| 成人a视频在线观看| 久久久久久久久久久免费| 久久久久久国产精品美女| 亚洲男人第一网站| 欧美成人午夜激情| 国产精品一区二区三区成人| 久久av在线看| xxxxx91麻豆| 亚洲欧美中文日韩在线v日本| 欧美色图在线视频| 欧美壮男野外gaytube| 日韩中文字幕国产精品| 国内精品免费午夜毛片| 日韩欧美a级成人黄色| 久精品免费视频| 久久99视频精品| 国产精品人成电影|