3/18/2009

Ildasm.exe 教學

文章&圖示請參照http://msdn.microsoft.com/zh-tw/library/aa309387(VS.71).aspx

這個教學課程提供了 .NET Framework SDK 中所附之 MSIL 反組譯工具 (Ildasm.exe) 的簡介。Ildasm.exe 工具可以剖析任何 .NET Framework .exe 或 .dll 組件 (Assembly),並且以人們可閱讀的 (Human-Readable) 格式顯示資訊。Ildasm.exe 不只會顯示 Microsoft Intermediate Language (MSIL) 程式碼,也會顯示包括介面在內的命名空間 (Namespace) 和型別。您可以使用 Ildasm.exe 來檢查 .NET Framework 的原生組件 (例如 Mscorlib.dll),以及其他人提供的或是您自行建立的 .NET Framework 組件。大部分 .NET Framework 開發人員都會認為 Ildasm.exe 是不可或缺的工具。

對於這個教學課程,請使用隨附在 SDK 中之 WordCount 範例的 Visual C# 版本。您也可以使用 Visual Basic 版本,但是這兩種語言所產生的 MSIL 將會不同,畫面影像也不盡相同。WordCount 位於 \Samples\Applications\WordCount\ 目錄中。若要建置 (Build) 和執行範例,請依照 Readme.htm 檔案中所列的指示進行。這個教學課程會使用 Ildasm.exe 來檢查 WordCount.exe 組件。

若要開始,請建置 WordCount 範例,並使用下列命令列將它載入 Ildasm.exe 中:

ildasm WordCount.exe

這樣便會使 Ildasm.exe 的視窗顯示出來,如下圖所示。



Ildasm.exe 視窗中的樹狀結構會顯示 WordCount.exe 內部包含的組件資訊清單資訊,以及四個全域類別型別:App、ArgParser、WordCountArgParser 和 WordCounter。

按兩下樹狀結構中的任何型別,即可看見型別的詳細資訊。在下圖中,已將 WordCounter 類別型別展開。



在上圖中,您可以看見所有的 WordCounter 成員。下列表格將說明每一個圖形符號所代表的意義。

符號 意義
詳細資訊
命名空間
類別
介面
數值類別
列舉型別
方法
靜態方法
欄位
靜態欄位
事件
屬性
資訊清單或類別資訊項目

按兩下 .class public auto ansi beforefieldinit 項目會顯示下列資訊:



在上圖中,您可以清楚地看出來,WordCounter 型別是從 System.Object 型別衍生而來。

WordCounter 型別還包含另外一個型別,名稱為 WordOccurrence。您可以將 WordOccurrence 型別展開,即可看見它的成員,如下圖所示。



從樹狀結構中可以看出來,WordOccurrence 實作了 System.IComparable 介面,更明確地講,就是 CompareTo 方法。不過,在後續的說明中,我們將略過 WordOccurrence 型別,而將焦點集中在 WordCounter 型別上。

您可以看到 WordCounter 型別含有五個 private 欄位:totalBytes、totalChars、totalLines、totalWords 和 wordCounter。前四個欄位是 int64 型別的執行個體 (Instance),而 wordCounter 欄位則是 System.Collections.SortedList 型別的參考。

在這些欄位之後,您可以看見方法。第一個方法 .ctor 是建構函式 (Constructor)。這個特殊的型別只有一個建構函式,但是其他型別則可以有多個建構函式,每一個的簽名碼 (Signature) 都不同。WordCounter 建構函式的傳回型別 (Return Type) 為 void (和所有建構函式一樣),而且不接受參數。如果按兩下建構函式方法,會出現新的視窗,它會顯示方法中所包含的 MSIL 程式碼,如下圖所示。



MSIL 程式碼實際上很容易閱讀和了解 (如需所有的詳細資訊,請參閱位於 \Tool Developers Guide\Docs 資料夾 Partition III CIL.doc 檔案中的 CIL Instruction Set Specification)。在最接近頂端的地方,您可以看見這個建構函式需要 50 個位元組的 MSIL 程式碼。從這個數字並不能判斷出 JIT 編譯器將會發出多少機器碼,因為它的大小是根據主機 CPU 和用來產生程式碼的編譯器而定。

Common Language Runtime 為堆疊架構。因此,若要執行任何作業,MSIL 程式碼會先將運算元推入虛擬堆疊中,然後執行運算子。運算子會將運算元從堆疊中抓取出來、執行所需的作業,然後將結果放回堆疊上。不論任何時候,這個方法推入虛擬堆疊上的運算元都不能超過八個。您只要查看出現在 MSIL 程式碼前面的 .maxstack 屬性,就可以辨識出這個數目。

現在,請檢查前面幾個 MSIL 指令,如下列四行:

IL_0000: ldarg.0 ; Load the object's 'this' pointer on the stack
IL_0001: ldc.i4.0 ; Load the constant 4-byte value of 0 on the stack
IL_0002: conv.i8 ; Convert the 4-byte 0 to an 8-byte 0
IL_0003: stfld int64 WordCounter::totalLines

位於 IL_0000 的指令會將傳遞至方法的第一個參數載入到虛擬堆疊上,而且一定會將物件記憶體的位址傳遞給每一個執行個體方法 (Instance Method)。這個引數稱為 Argument Zero,而且不會明確顯示在方法的簽名碼中。因此,即使 .ctor 方法看起來像是接收了零個引數,實際上是接收了一個引數。接著,位於 IL_0000 的指令會將這個物件的指標載入到虛擬堆疊上。

位於 IL_0001 的指令會將 4 位元組的零值常數載入到虛擬堆疊上。

位於 IL_0002 的指令會取得堆疊頂端的數值 (4 位元組的零),並將它轉換成 8 位元組的零,如此便會將 8 位元組的零放到堆疊的頂端。

這時,堆疊含有兩個運算元:8 位元組的零和指向這個物件的指標。位於 IL_0003 的指令會使用這兩個運算元,將堆疊頂端的數值 (8 位元組的零) 儲存到堆疊上所辨識物件的 totalLines 欄位中。

totalChars、totalBytes 和 totalWords 欄位會重複相同的 MSIL 指令序列 (Sequence)。

wordCounter 欄位的初始化是從位於 IL_0020 的指令開始,如以下所示:

IL_0020: ldarg.0
IL_0021: newobj instance void [mscorlib]System.Collections.SortedList::.ctor()
IL_0026: stfld class [mscorlib]System.Collections.SortedList WordCounter::wordCounter

位於 IL_0020 的指令會將 WordCounter 的 this 指標推入虛擬堆疊上。newobj 指令不會使用這個運算元,但是位於 IL_0026 的 stfld 指令將會使用。

位於 IL_0021 的指令會告知 Runtime 建立新的 System.Collections.SortedList 物件,並且不使用任何引數呼叫它的建構函式。當 newobj 傳回時,SortedList 物件的位址是在堆疊上。這時候,位於 IL_0026 的 stfld 指令會將 SortedList 物件的指標儲存到 WordCounter 物件的 wordCounter 欄位中。

在所有 WordCounter 物件的欄位都完成初始化之後,位於 IL_002b 的指令會將 this 指標推到虛擬堆疊上,然後 IL_002b 會呼叫基底型別 (Base Type) (System.Object) 中的建構函式。

當然,位於 IL_0031 的最後一個指令是傳回指令,會使 WordCounter 建構函式傳回到建立函式的程式碼中。建構函式必須傳回 void,在建構函式傳回之前才不會將任何物件放入堆疊上。

下面是另外一個範例。請按兩下 GetWordsByOccurranceEnumerator 方法,即可看見它的 MSIL 程式碼,如下圖所示。



您可以看見,這個方法的程式碼大小為 69 個位元組,而且這個方法在虛擬堆疊上需要有四個位置。此外,這個方法還有三個區域變數:一個為 System.Collection.SortedList 型別,另外兩個為 System.Collections.IDictionaryEnumerator 型別。請注意,除非組件與 /debug 選項相容,否則不會將原始程式碼中提到的變數名稱發出到 MSIL 程式碼中。如果沒有使用 /debug,會分別使用 V_0、V_1 和 V_2 等變數名稱來取代 sl、de 和 CS$00000003$00000000。

當這個方法開始執行時,第一件事就是執行 newobj 指令,這個指令會建立新的 System.Collections.SortedList 物件,並呼叫這個物件的預設建構函式。當 newobj 傳回時,所建立物件的位址是在虛擬堆疊上。stloc.0 指令 (位於 IL_0005) 會將這個值儲存在區域變數 0 或 sl (不含 /debug 的 V_0) (屬於 System.Collections.SortedList 型別) 中。

位於 IL_0006 和 IL_0007 的指令會將 WordCounter 物件的 this 指標 (在傳遞至方法的 Argument Zero 中) 載入到堆疊上,並呼叫 GetWordsAlphabeticallyEnumerator 方法。當 call 指令傳回時,列舉值的位址是在堆疊上。stloc.1 指令 (位於 IL_000c) 會將這個位址儲存在區域變數 1 或 de (不含 /debug 的 V_1),這個變數屬於 System.Collections.IDictionaryEnumerator 型別。

位於 IL_000d 的 br.s 指令會造成 while 陳述式的 IL 測試條件無條件分支。這個 IL 測試條件從位於 IL_0032 的指令開始。在 IL_0032 位址中,會將 de (或 V_1) (IDictionaryEnumerator) 的位址推到堆疊上,然後在 IL_0033 位址呼叫它的 MoveNext 方法。如果 MoveNext 傳回 True,表示有要列舉的項目,而且 brtrue.s 指令會跳到位於 IL_000f 的指令。

在位於 IL_000f 和 IL_0010 的指令中,會將 sl (或 V_0) 和 de (或 V_1) 中的物件位址推到堆疊上。然後,呼叫 IdictionaryEnumerator 物件的 get_Value 屬性方法,以取得目前項目的項目數目。這個數目是儲存在 System.Int32 中的 32 位元值。程式碼會將 Int32 物件轉換成 int 數值型別 (Value Type)。將參考型別 (Reference Type) 轉換成數值型別需要位於 IL_0016 的 unbox 指令。當 unbox 傳回時,Unboxed 數值的位址是在堆疊上。ldind.i4 指令 (位於 IL_001b) 會將 4 位元組的數值 (這個數值會指向目前在堆疊上的位址) 載入到堆疊上。換句話說,Unboxed 4 位元組整數是放在堆疊上。

在位於 IL_001c 的指令中,會將 sl (或 V_1) 的數值 (IDictionaryEnumerator 的位址) 推到堆疊上,並呼叫它的 get_Key 屬性方法。當 get_Key 傳回時,System.Object 的位址是在堆疊上。程式碼知道字典中包含字串,因此編譯器會使用位於 IL_0022 的 castclass 指令,將這個 Object 轉換成 String。

以下幾個新的指令 (從 IL_0027 到 IL_002d) 會建立新的 WordOccurrence 物件,然後將物件的位址傳遞至 SortedLists 物件的 Add 方法。

在位於 IL_0032 的指令中,會再評估一次 while 陳述式的測試條件。如果 MoveNext 傳回 True,迴圈 (Loop) 會執行另一個循環。但是,如果 MoveNext 傳回 False,迴圈會停止執行,並在位於 IL_003a 的指令結束。位於 IL_003a 到 IL_0040 的指令會呼叫 SortLists 物件的 GetEnumerator 方法。傳回的值為 System.Collections.IDictionaryEnumerator,它是被留在堆疊上而成為 GetWordsByOccurrenceEnumerator 傳回值。

MSIL 反組譯工具 (Ildasm.exe)

.NET Framework 工具
MSIL 反組譯工具 (Ildasm.exe)

MSIL 反組譯工具是 MSIL 組譯工具 (Ilasm.exe) 的附屬工具。Ildasm.exe 使用包含 Microsoft Intermediate Language (MSIL) 程式碼之可移植的執行檔 (PE),並建立可以做為 Ilasm.exe 之輸入檔的文字檔。


ildasm [options] [PEfilename] [options]
參數
下列選項可用於 .exe、.dll、.obj 和 .lib 檔。

選項 描述
/output= filename
建立具有指定 filename 的輸出檔,而非在圖形化使用者介面中顯示結果。

/rtf
以 Rich Text Format (.rtf 檔案) 產生輸出。使用 /text 選項時無效。

.NET Framework 2.0 版的新功能。

/text
顯示結果到主控台 (Console) 視窗,而非在圖形化使用者介面中顯示或做為輸出檔。

/html
以 HTML 格式產生輸出。僅使用 /output 選項時才有效。

.NET Framework 2.0 版的新功能。

/?
顯示工具的命令語法和選項。


下列額外的選項可用於 .exe 和 .dll 檔。

選項 描述
/bytes
以十六進位格式顯示實際位元組做為指令註解。

/caverbal
以動詞化格式產生自訂屬性 BLOB (二進位大型物件)。預設為二進位格式。

.NET Framework 2.0 版的新功能。

/linenum
包含原始程式行的參考。

/nobar
隱藏反組譯碼進度指示器快顯視窗 (Pop-Up Window)。

/noca
隱藏自訂屬性的輸出。

.NET Framework 2.0 版的新功能。

/pubonly
僅反組譯公用型別和成員。等同於 /visibility:PUB。

/quoteallnames
在單引號內包含所有的名稱。

/raweh
以未經處理格式顯示例外處理 (Exception Handling) 子句。

/source
顯示原始程式行做為註解。

/tokens
顯示類別和成員的中繼資料語彙基元 (Token)。

/visibility: vis [+vis ...]
以指定的可視性僅反組譯型別或成員。下列都是 vis 的有效值:

PUB — Public

PRI — Private

FAM — Family

ASM — Assembly

FAA — Family 和 Assembly

FOA — Family 或 Assembly

PSC — Private Scope

如需這些可視性修飾詞 (Modifier) 的定義,請參閱 MethodAttributes 和 TypeAttributes。


下列選項對 .exe 和 .dll 檔有效,僅適用於檔案或主控台輸出。

選項 描述
/all
指定 /header、/bytes、/stats、/classlist 和 /tokens 選項的組合。

注意事項
在 .NET Framework 1.0 和 1.1 版中,指定 /header、/bytes 和 /tokens 選項的組合。


/classlist
包括在模組中定義的類別清單。

.NET Framework 2.0 版的新功能。

/forward
使用 forward 類別宣告。

.NET Framework 2.0 版的新功能。

/header
在輸出中包含檔頭資訊。

/item: class[::method [(sig)]]
根據提供的引數反組譯下列項目:

反組譯指定的 class。

反組譯指定之 class 的 method。

以指定的簽名 sig 反組譯 class 的 method。以傳回型別 (Return Type) 以及所需的參數指定簽名。例如,returntype (param1, param2,..paramn)。

/noil
隱藏 MSIL 組譯碼輸出。

/stats
包括映像的統計資料。

.NET Framework 2.0 版的新功能。

/typelist
產生型別完整清單,以保留來回之間的型別順序。

.NET Framework 2.0 版的新功能。

/unicode
輸出使用 Unicode 編碼方式。

/utf8
輸出使用 UTF-8 編碼方式。ANSI 是預設值。


下列選項對 .exe、.dll、.obj 和 .lib 檔有效,僅適用於檔案或主控台輸出。

選項 描述
/metadata[=specifier]
顯示中繼資料 (Metadata),其中 specifier 是:

MDHEADER — 顯示中繼資料的標頭資訊和大小。

HEX — 使用十六進位和文字顯示資訊。

CSV — 顯示記錄計數和堆積大小。

UNREX — 顯示無法解析的外部符號。

SCHEMA — 顯示中繼資料的標頭和結構描述資訊。

RAW — 顯示原始中繼資料的表格。

HEAPS — 顯示原始的堆積。

VALIDATE — 驗證中繼資料的一致性。

您可以多次指定 /metadata,每次使用不同的 specifier 值。

.NET Framework 2.0 版的新功能。


下列選項只對適用於檔案或主控台輸出的 .lib 檔有效。

選項 描述
/objectfile=filename
在指定的程式庫中顯示單一物件檔案的中繼資料。

.NET Framework 2.0 版的新功能。


注意事項
所有 Ildasm.exe 的選項都不區分大小寫,並且是以前三個字母識別。例如,/quo 就相當於 /quoteallnames。指定引數的選項可以接受冒號 (:) 或等號 (=) 做為選項與引數之間的分隔符號。例如,/output:filename 等同於 /output=filename。


備註
Ildasm.exe 只在磁碟上的 PE 檔上作業。它無法在安裝於全域組件快取中的檔案上作業。

Ildasm.exe 所產生的文字檔可以被用來做為 MSIL 組譯工具 (Ilasm.exe) 的輸入。這非常有用,例如在不支援所有執行階段中繼資料屬性的程式語言中編譯程式碼時。在編譯程式碼並透過 Ildasm.exe 執行其輸出之後,可以手動編輯產生的 MSIL 文字檔來加入遺漏的屬性。然後可以透過 MSIL 組譯工具執行這個文字檔來產生最後的可執行檔。

注意事項
目前您無法將這項技術用於包含內嵌機器碼的 PE 檔 (例如,由 Visual C++ 所產生的 PE 檔)。


您可以使用 MSIL 反組譯工具中的預設 GUI,來檢視在階層式樹狀檢視中任何現有 PE 檔的中繼資料和反組譯碼。若要使用 GUI,請在命令列輸入 ildasm,但不提供 PEfilename 引數或任何選項。您可以從 [檔案] 功能表,巡覽至要載入到 Ildasm.exe 的 PE 檔。若要儲存為所選的 PE 所顯示的中繼資料和反組譯程式碼,請從 [檔案] 功能表中選取 [傾印] 命令。若只要儲存階層式樹狀檢視,請從 [檔案] 功能表中選取 [傾印樹狀檢視] 命令。如需載入檔案到 Ildasm.exe 和解譯輸出的詳細指引,請參閱<Ildasm.exe 教學課程>,位於與 .NET Framework SDK 一起推出的 Samples 資料夾中。

如果您提供 Ildasm.exe 和包含內嵌資源的 PEfilename 引數,這個工具就會產生多個輸出檔案:包含 MSIL 程式碼的文字檔,以及對每個內嵌的 Managed 資源,使用來自中繼資料 (Metadata) 的資源名稱所產生的 .resources 檔。如果 Unmanaged 資源是內嵌於 PEfilename,.res 檔是使用由 /output 選項輸出的 MSIL 的指定檔名所產生。

注意事項
Ildasm.exe 僅會顯示 .obj 和 .lib 輸入檔的中繼資料描述。這些檔案類型的 MSIL 程式碼是不被反組譯的。


您可以在 .exe 或 .dll 檔上執行 Ildasm.exe 來判斷這個檔案是否為 Managed。如果這個檔案不是 Managed,工具便會顯示訊息,說明這個檔案沒有有效的 Common Language Runtime 標頭而且無法反組譯。如果這個檔案是 Managed,工具就會順利執行。

範例
下列命令會使得 PE 檔 MyHello.exe 的中繼資料和反組譯的程式碼顯示在 Ildasm.exe 的預設 GUI 中。

複製程式碼
ildasm myHello.exe下列命令會反組譯 MyFile.exe 檔案,並將產生的 MSIL 組譯工具文字儲存到 MyFile.il 檔案。

複製程式碼
ildasm MyFile.exe /output:MyFile.il下列命令會反組譯 MyFile.exe 檔案,並將產生的 MSIL 組譯工具文字顯示到主控台視窗。

複製程式碼
ildasm MyFile.exe /text如果檔案 MyApp.exe 含有內嵌 Managed 和 Unmanaged 資源,則下列命令會產生四個檔案:MyApp.il、MyApp.res、Icons.resources, 和 Message.resources:

複製程式碼
ildasm MyApp.exe /output:MyApp.il下列命令會反組譯 MyFile.exe 中類別 MyClass 內的方法 MyMethod,並且將輸出顯示到主控台視窗。

複製程式碼
ildasm /item:MyClass::MyMethod MyFile.exe /text在上述範例中,可能有好幾個具有不同簽名碼的 MyMethod 方法。下列命令會以 void 和參數 int32 和 System.String 的傳回型別反組譯 MyMethod 方法。

複製程式碼
ildasm /item:"MyClass::MyMethod(void(int32,class System.String))" MyFile.exe /text 請參閱
參考
.NET Framework 工具
MSIL 組譯工具 (Ilasm.exe)
SDK 命令提示字元

概念
編譯為 MSIL

什麼是反組譯

程式有分高低階
低階有機器語言(0 與 1 的組合), 組合語言(以簡易的名稱/指令來代表 0/1 的組合).
組合語言是唯一與機器語言產生一對一的關係.

當原始碼寫好,要將他轉成機碼時, 在低階(ASM)叫做組譯, 如果是高階(C, BASIC)叫做編譯/直譯...

相對的, 把 ASM 翻成機碼叫組譯, 那把組譯翻成 ASM 叫反組譯

要看你電腦的平台是什麼,理論上是可以,實際上就要看有沒現成的工具給你用,不然只好自己寫,不過有時高階寫出來的一行等於低階的好幾 xxx 行,此時你在閱讀程式碼時就造成了困擾了


假設一段C程式碼如下:
a=b+c;
d=e-f;
經過c語言編譯器轉譯為組合語,再由組譯器轉為機器語言。有些編譯器直接就轉譯為機器語言,這要看編譯器如何設計。
(為了方便解釋,用a,b,c,d,e,f來代暫存器,實際上的寫法並不是如此)
add—起動加法電路
sub-起動減法電路(實際上還是用加法器來做減法)
add a, b,c (將暫存器b,c的值相加放回暫存器a)
sub d,e ,f(將暫存器e,f的值相減放回暫存器d)
cpu計算完後,把結果值放回記憶體。
經過組譯器轉譯後的機器碼為:
以下為假設性的排列:(實際上還是要看cpu的指令集的對應關係,及如何設計)
我用4個位元來表示;
0001 0010 0011
0100 0101 0110
反組譯的意思,就是相辦法把機器語言,用反向操作的方式還原。
必須要相當了解各種平台CPU的指令集機構,及指令集對照表來設計反組譯程式。難度很高,因為各種語的語法都不相同,資料結構也不同。
還有另一位一種方法是透過中介語言來逹成。

範例:
c原始碼:
#include
main()
{
printf("Hello World\n");
}
[root@localhost test]# ls
hello.c
[root@localhost test]# gcc hello.c
[root@localhost test]# ls
a.out hello.c
[root@localhost test]# ./a.out
Hello Wolrd
[root@localhost test]# objdump -d a.out > hello.asm #反組譯
[root@localhost test]# ls
a.out hello.asm hello.c
[root@localhost test]# vi hello.asm #反組譯結果
8048337: 68 38 95 04 08 push $0x8049538
804833c: e8 bf 7c fb f7 call 0 <_init-0x8048250>
8048341: 83 c4 10 add $0x10,%esp
8048344: c9 leave
8048345: c3 ret
8048346: 90 nop
8048347: 90 nop

08048348
:
8048348: 55 push %ebp
8048349: 89 e5 mov %esp,%ebp
804834b: 83 ec 08 sub $0x8,%esp
804834e: 83 e4 f0 and $0xfffffff0,%esp
8048351: b8 00 00 00 00 mov $0x0,%eax
8048356: 29 c4 sub %eax,%esp
8048358: 83 ec 0c sub $0xc,%esp
804835b: 68 40 84 04 08 push $0x8048440
8048360: e8 23 ff ff ff call 8048288 <_init+0x38>
8048365: 83 c4 10 add $0x10,%esp
8048368: c9 leave
8048369: c3 ret
804836a: 90 nop
804836b: 90 nop

0804836c <__libc_csu_init>:
804836c: 55 push %ebp
804836d: 89 e5 mov %esp,%ebp
804836f: 57 push %edi
8048370: 56 push %esi
8048371: 53 push %ebx
8048372: 83 ec 0c sub $0xc,%esp
8048375: e8 00 00 00 00 call 804837a <__libc_csu_init+0xe>
804837a: 5b pop %ebx
804837b: 81 c3 c2 11 00 00 add $0x11c2,%ebx
8048381: e8 ca fe ff ff call 8048250 <_init>
8048386: 8d 93 18 ff ff ff lea 0xffffff18(%ebx),%edx
804838c: 8d 8b 18 ff ff ff lea 0xffffff18(%ebx),%ecx
8048392: 29 ca sub %ecx,%edx
8048394: c1 fa 02 sar $0x2,%edx

a.out: file format elf32-i386

Disassembly of section .init:

08048250 <_init>:
8048250: 55 push %ebp
8048251: 89 e5 mov %esp,%ebp
8048253: 83 ec 08 sub $0x8,%esp
8048256: e8 61 00 00 00 call 80482bc
804825b: e8 bc 00 00 00 call 804831c
8048260: e8 93 01 00 00 call 80483f8 <__do_global_ctors_aux>
8048265: c9 leave
8048266: c3 ret
Disassembly of section .plt:

08048268 <.plt>:
8048268: ff 35 40 95 04 08 pushl 0x8049540
804826e: ff 25 44 95 04 08 jmp *0x8049544
8048274: 00 00 add %al,(%eax)
8048276: 00 00 add %al,(%eax)
8048278: ff 25 48 95 04 08 jmp *0x8049548
804827e: 68 00 00 00 00 push $0x0
8048283: e9 e0 ff ff ff jmp 8048268 <_init+0x18>
8048288: ff 25 4c 95 04 08 jmp *0x804954c
804828e: 68 08 00 00 00 push $0x8
8048293: e9 d0 ff ff ff jmp 8048268 <_init+0x18>
Disassembly of section .text:

08048298 <_start>:
8048298: 31 ed xor %ebp,%ebp
804829a: 5e pop %esi
804829b: 89 e1 mov %esp,%ecx
804829d: 83 e4 f0 and $0xfffffff0,%esp
"hello.asm" 214L, 9749C



先從 compiler 說起, 假設一個程式很簡單就是

int main()
{
printf('hello, world');
}

只是很簡單的一行程式, 在螢幕上 show "hello, world", 在 compile 成執行檔就是一大堆 binary code, 當你用反組譯程式解回來時,當然不會是你上面看到的樣子,實際上類似這樣:

520:0100 0100 ADD [BX+SI],AX
520:0102 CD21 INT 21
520:0104 7217 JB 011D
520:0106 40 INC AX
520:0107 A3A800 MOV [00A8],AX
520:010A 48 DEC AX
520:010B 8EC0 MOV ES,AX
520:010D B449 MOV AH,49
520:010F CD21 INT 21
520:0111 720A JB 011D
520:0113 B80158 MOV AX,5801
520:0116 BB0000 MOV BX,0000
520:0119 CD21 INT 21
520:011B 7303 JNB 0120
520:011D E98901 JMP 02A9
.......

你唯一會看到的是一大堆 assembly code, 道理很簡單, 雖然只是一行程式, 但實際上有很多 I/O & Function Call 在運作, 上面是C程式,算是中階語言,如果換做是其他更高階的電腦語言,如 BASIC -> C -> ASM 中間經過多少道 "轉換" 程序. 這也就是我所謂即使解出來意義也不大了.

12/13/2008

[技巧]分享備份MSN 8.1版表情符號備份

輸入以下路徑:

『C:\Documents and Settings\使用者帳號\Local Settings\Application Data\Microsoft\MSN Messenger\MSN帳號\ObjectStore』(MSN 8.1版路徑與網路上別的版本的不一樣。

  裡面有幾個目錄,網路上找到的資料如下:
  Backgrounds => 是存放使用者的背景
  CustomEmoticons => 是存放使用者的表情符號
  DynamicBackgrounds => 是存放使用者的動態背景
  UserTile => 是存放使用者的顯示圖片
  Winks3 => 是存放動畫快遞

  不過現在只對『CustomEmoticons => 是存放使用者的表情符號』這個目錄的東西有興趣,就找它下手吧!不過進去後是一種看不懂的檔案格式,所以再次放棄單檔的備份,只好把『CustomEmoticons』這個目錄整個COPY一份到隨身碟上,再帶回家再放到上面講到的目錄位置,就可以享受成就感囉!^^

  在來,就是找找看有沒有辦法把備份出來的那些亂碼檔名的東西,轉成一般容易閱讀的圖檔工具囉!

PS:
1.若是MSN重度使用者,且MSN是8.1版的,可能要從『ObjectStore』這個目錄將下面的五個子目錄的東西一起備份,這樣才可以把自己個人化的背景、表情符號、使用者的圖像、動畫快遞...等等的東西一次備齊。

2.上面文章中有講到的路徑中有關『使用者帳號』的部份,就是指你登入Windows時所打入的帳號密碼中的『帳號』,會顯示在『C:\Documents and Settings\』這個路徑底下。若是電腦只有一個使用者時比較好找到路徑,不是Administrator就是安裝時所打的第一個帳號,但若是還搞不清楚該從那一個帳號下手,那就一個個的點一定會點到上面說的路徑。若是多使用者且用不同帳號登入系統的話,就不應該不知道自己要從那一個目錄去下手。

3.上面文章中有講到的路徑中有關『MSN帳號』的部份,就是指你登入MSN所打的『帳號』,會在『C:\Documents and Settings\使用者帳號\Local Settings\Application Data\Microsoft\MSN Messenger\』這個目錄下會出現,所以應該不難找到。

參考看看!!

12/01/2008

防毒軟體卡巴斯基vs.antiVirus

最近從卡巴斯基6.0用到最新版8.0/9.0 只有一個感想 就是怎麼愈來愈難用?

卡巴斯基不是說很強嗎? 9.0用了之後感覺不好就換成KIS8.0版

卻不斷跑出錯誤回報 安裝或解安裝的過程也有時候會卡住 我總共安裝/解安裝3-4次吧~

連安裝KAV版都用的不是很順

於是問問同事看他們用什麼防毒

有人說卡巴斯基愈來愈遜了 有些明明有毒的地方卻掃不到?!

於是我決定捨棄對卡巴斯基的堅持 換成antiVirus試試好了 至少antiVirus是free的!!

搜尋了一下網頁 發現有幾篇關於anti-virus的文章寫的還不錯
可以供剛使用antiVirus的新手參考,裡面有些小技巧與秘訣還不錯喔!!

推薦A : 重灌狂人
一、安裝AntiVir防毒軟體
二、更新病毒碼、幫電腦掃描病毒
三、讓AntiVir自動每天新兩次
四、讓AntiVir掃到病毒時,自動解毒或刪除中毒檔案
五、啟動「啟發式掃描」,自動防禦未知病毒
六、如何禁止AntiVir出現廣告視窗?

推薦B : 高登工作室
來自德國免費防毒軟體 - 小紅傘AntiVir Personal Free
小紅傘AntiVir使用篇 Part I
kavo,taso,jvvo,kxvo病毒一次解決
防毒教室

建議至官網上安裝最新版的antiVirus比較保險!!