IDA簡(jiǎn)易教程
作者:www.datarescue.com
mailto:winroot@126.com
2004-11-20 初步翻譯完成,希望大家指正錯(cuò)誤,謝謝!
我的鳥語(yǔ)太差大概翻譯了一下,大家湊合著能看懂就行了:-)有些地方用自己理解的意思改寫了一下!
本文的主要內(nèi)容就是講如何用IDA來(lái)輔助識(shí)別各種類型的數(shù)據(jù).
版權(quán)信息:所有版權(quán)歸原文作者所有,如許轉(zhuǎn)載清保持文章完整性。
索引
1 第一節(jié):C語(yǔ)言的小程序
2 第二節(jié):基本類型的識(shí)別
3 第三節(jié):操作數(shù)格式
4 第四節(jié):字符和字符串的操作
5 第五節(jié):數(shù)組
6 第六節(jié):枚舉類型
7 第七節(jié):Bit-fields(位域)
8 第八節(jié):結(jié)構(gòu)體
9 第九節(jié):結(jié)構(gòu)變量和結(jié)構(gòu)數(shù)組
10 第十節(jié):聯(lián)合體和結(jié)構(gòu)體中的結(jié)構(gòu)體
11 第十一節(jié):可變的結(jié)構(gòu)體
12 第十二節(jié):結(jié)構(gòu)體偏移
13 第十三節(jié):聯(lián)合體偏移量
14 第十四節(jié):地址偏移量
15 第十五節(jié):最終逆向結(jié)果
附錄
第一節(jié):C語(yǔ)言的小程序
為了演示IDA的功能先寫一段小程序。(代碼在附錄)程序在此 源代碼
程序執(zhí)行結(jié)果:
CUSTOMERS:
CUSTOMER 0001: Peter (m)
CUSTOMER 0002: John (m)
CUSTOMER 0003: Mary (f)
PRODUCTS:
PRODUCT 0001: BOOK: IDA QuickStart Guide
PRODUCT 0002: SOFTWARE: IDA Pro: PC; WINDOWS DOS; DISASSEMBLY
PRODUCT 0003: SOFTWARE: PhotoRescue: PC MAC; WINDOWS OS-X; RECOVERY
PRODUCT 0004: SOFTWARE: aCrypt: PC; WINDOWS; CRYPTOGRAPHY
TOP
----------------------------------------------------------------------
第二節(jié):基本類型的識(shí)別
用IDA分析我們前面的程序,我們會(huì)發(fā)現(xiàn)下圖的類型
只要按"D"我們就可以任意轉(zhuǎn)換這些不確定的類型.可以變成byte,word,dword(db,dw,dd)。
當(dāng)然你也可以設(shè)置更多的數(shù)據(jù)轉(zhuǎn)換類型:
選擇“Options”菜單的“Setup data types”命令就可以設(shè)置了
值得注意的是:你在數(shù)據(jù)轉(zhuǎn)換的時(shí)候,它是依據(jù)數(shù)據(jù)自身的結(jié)構(gòu)來(lái)轉(zhuǎn)換的。我們按“D”的時(shí)候,
如果下一個(gè)字節(jié)已經(jīng)被你轉(zhuǎn)換過(guò),你的本次轉(zhuǎn)換,IDA將會(huì)提示讓你確認(rèn)。
注:如果你想改變這種默認(rèn)設(shè)置可以在“Options”菜單“Convert already defined bytes”命令里設(shè)置
撤銷你的所有轉(zhuǎn)換按“U”鍵。
TOP
-------------------------------------------------------------------------------------
第三節(jié):操作數(shù)格式
數(shù)據(jù)類型自定義轉(zhuǎn)換后,被操作過(guò)的數(shù)據(jù)(就是你按過(guò)“D”的)的進(jìn)制IDA也是可以自定義轉(zhuǎn)變的,
通過(guò)在“Operands”工具欄的“Number”命令我們可以隨意轉(zhuǎn)換數(shù)字的進(jìn)制
最下面的“Toggle leading point”就是填補(bǔ)數(shù)據(jù)前的空位為0(就是說(shuō)如果當(dāng)前數(shù)據(jù)未占滿數(shù)據(jù)格式的所有位高位用0來(lái)填補(bǔ))
IDA還可以轉(zhuǎn)換數(shù)據(jù)的標(biāo)志位(就是正負(fù))具體操作如下圖:
最后呢~~如果這些轉(zhuǎn)換你還不滿意(夠BT)當(dāng)然你還可以自定義數(shù)據(jù)進(jìn)制如圖:
TOP
-----------------------------------------------------------------------------------------
第四節(jié):字符和字符串的操作
作者又說(shuō)話了:很多程序都是包含字符串的,一些被操作過(guò)的數(shù)據(jù)(就是你按過(guò)“D”的)可以轉(zhuǎn)化為
字符,使用的命令就在“Operands”工具欄上
由于編程語(yǔ)言的不同造成字符串也有不同的格式,當(dāng)然IDA就支持所有的格式了。
IDA在轉(zhuǎn)化后會(huì)在地址添加一個(gè)名字。因?yàn)槲覀兊某绦蚴莄的所以就找到c的字符串。具體操作如圖:
如果不是C寫的程序怎么辦呢?我們可以在“Options”菜單“ASCII string style”命令中設(shè)置。
允許你修改其它類型為默認(rèn)設(shè)置,使用默認(rèn)設(shè)置的快捷鍵是“A”,或者自定義一種類型可以使用不常用的終止字符。
TOP
--------------------------------------------------------------------------
第五節(jié):數(shù)組
在c中,ASCII字符串被認(rèn)為是字符數(shù)組,IDA是如何處理數(shù)組的呢?
我們用最常用命令來(lái)定義數(shù)組中的第一個(gè)元素,設(shè)置第一個(gè)元素類型為byte,格式為char,然后點(diǎn)擊“*”號(hào)鍵(或者“Edition ”工具欄的“Array”命令)來(lái)創(chuàng)建數(shù)組。這時(shí)彈出一個(gè)對(duì)話框,可以設(shè)置很多變量。
你可以定義數(shù)組一行的顯示個(gè)數(shù),還可以使用“Element width”來(lái)設(shè)置他們之間的寬度。
使用“Use dup construct ”選項(xiàng)可以合并連貫的相似字節(jié),“ Display index ”選項(xiàng)可以像注釋一樣顯示數(shù)組的下標(biāo)。
例如我們?cè)O(shè)置一個(gè)有64個(gè)元素的數(shù)組,一行有8個(gè)元素,每個(gè)元素之間的寬度為4,不選取“dup constructs”,選取“Display index ”,我們就可以得到下面的數(shù)組。
當(dāng)IDA遇到未被識(shí)別的字節(jié)他會(huì)用紅色的高亮顯示。
當(dāng)然你也可以選擇一個(gè)范圍來(lái)創(chuàng)建數(shù)組,IDA會(huì)自適應(yīng)的設(shè)定。
TOP
------------------------------------------------------------------------------------
第六節(jié):枚舉類型
還記得我們?cè)贑程序中定義的product_category_t 類型嗎?
讓我們用IDA的“Enumerations”來(lái)定義一下。
首先,我們打開“Enumerations”窗口來(lái)創(chuàng)建一個(gè)新的枚舉類型
我們輸入我們的枚舉類型值
在check_product()函數(shù),我們可以用枚舉類型重新定義一些操作數(shù)。
右鍵點(diǎn)擊在數(shù)值上,就會(huì)彈出一個(gè)菜單,選擇“Symbolic constant”。
IDA就會(huì)自動(dòng)列舉枚舉值,用以匹配當(dāng)前的數(shù)值。
操作完成,我們就會(huì)得到下面的結(jié)果:
TOP
-----------------------------------------------------------------------------------------------------
第七節(jié):Bit-fields(位域)
BTW:Bit-fields,我的理解就是在結(jié)構(gòu)體中的位標(biāo)志。太菜!希望高手指正!
現(xiàn)在,我們來(lái)定義一下在software_info_t 結(jié)構(gòu)中的bitfields。
IDA的觀點(diǎn)就是,bitefields是一種特殊的枚舉類型。
我們可以選擇在枚舉類型創(chuàng)造窗口中的“Bitfield”選項(xiàng)。
還記得我們?cè)?jīng)在我們的程序中建立了兩種不同類型的bitfields ,
plateform和os包含了一種隱藏的模式:用來(lái)包含組合模式(用邏輯或來(lái)操作) 。因?yàn)橐环N產(chǎn)品可以同時(shí)在幾種plateforms和OS的組合。另一方面,category bitfield 中每一個(gè)數(shù)字表示一種類別:一種產(chǎn)品每次只能屬于一種類別。
在IDA中一種指定的模式,bitfield只能包含一個(gè)值。所以在描述plateform 和category bitfields時(shí)為了顯示組合模式,我們必須創(chuàng)建一個(gè)小的bitfields,每個(gè)值的一個(gè)bit.
現(xiàn)在我們開始創(chuàng)建category bitfield。mask值為0x3 (2 bits).我們指定一個(gè)名字、一個(gè)值、還有bitfield mask。我們還需要定義mask的名字:這個(gè)我們不用IDA自動(dòng)生成的,IDA有一個(gè)內(nèi)存助手可以幫助生成。
當(dāng)所有的bitfields被輸入,我們就會(huì)得到下面的結(jié)果:
用Operands 工具欄上的Enum member命令就可以定義我們程序中的Enum member數(shù)據(jù)
TOP
---------------------------------------------------------------------------------------------------------
第八節(jié):結(jié)構(gòu)體
我們的程序當(dāng)中包含了很多結(jié)構(gòu)體?,F(xiàn)在讓我們來(lái)在IDA中描述一下結(jié)構(gòu)體,
看看是怎么提高匯編代碼的可讀性。
第一步,我們必須打開Structures 窗口,來(lái)創(chuàng)建一個(gè)新的結(jié)構(gòu)體類型。
結(jié)構(gòu)體的成員是一匯編的模式定義的。讓我們來(lái)定義software_t 結(jié)構(gòu)中的第一個(gè)成員。
一直按“D”知道它變成“dd”意思就是這個(gè)成員的值為 dword類型。
把它的格式定義為我們以前定義好的software_info_t 枚舉類型,然后我們用Rename命令輸入一個(gè)適當(dāng)?shù)拿郑篿nfo
開始定義第二個(gè)成員,這次使用ASCII命令(按“A”),在這個(gè)環(huán)節(jié)
IDA會(huì)彈出一個(gè)專用對(duì)話框用來(lái)設(shè)定字符串的大小
我們還可以從已經(jīng)分析好的數(shù)據(jù)中來(lái)建立結(jié)構(gòu)體。
舉個(gè)例子:假設(shè)我們選擇了一塊數(shù)據(jù)正好是和我們的customer_t結(jié)構(gòu)體的數(shù)據(jù)格式一樣,我們就可以用IDA的“Create struct from data ”命令來(lái)創(chuàng)建結(jié)構(gòu)體
一旦使用了這個(gè)命令,IDA就會(huì)在Structures窗口創(chuàng)建一個(gè)相對(duì)應(yīng)的結(jié)構(gòu)體
我們使用“A”鍵來(lái)修改name成員的長(zhǎng)度為32bytes(和我們?cè)创a中定義的一樣),然后再給結(jié)構(gòu)體一個(gè)好聽的名字。
我們拿這些結(jié)構(gòu)體有什么用呢?IDA提供給我們兩種方法:
·Apply structure types to initialized data in the program.
·Convert operands as offsets inside structures.
我們將在下面的教程當(dāng)中來(lái)介紹這兩種方法
TOP
---------------------------------------------------------------------------------------------------------------------
第九節(jié):結(jié)構(gòu)變量和結(jié)構(gòu)數(shù)組
現(xiàn)在讓我們用來(lái)customer_t結(jié)構(gòu)體整理另外一個(gè)客戶信息John。
把鼠標(biāo)指針放在我們定義的結(jié)構(gòu)體的第一個(gè)自己上面,然后使用Struct var命令。
這樣我們就得到了一個(gè)新的結(jié)構(gòu)體變量。IDA會(huì)自動(dòng)在結(jié)構(gòu)體成員的后面加上變量名的。
通過(guò)我們的源碼,我們知道有一個(gè)包含個(gè)4元素的customers數(shù)組,我們先前把
Peter和John都定義為 customer_t 結(jié)構(gòu)體了?,F(xiàn)在取消對(duì)Join結(jié)構(gòu)變量的定義,然后在Peter結(jié)構(gòu)上按“*”鍵創(chuàng)建我們的customer數(shù)組,這樣IDA就彈出一個(gè)數(shù)組設(shè)置框他會(huì)自動(dòng)檢測(cè)出來(lái)我們要?jiǎng)?chuàng)建的數(shù)組最大數(shù)是4。
下來(lái)我們就看到創(chuàng)建好的數(shù)組了,剩下的就是改一下數(shù)組的名字。
TOP
-------------------------------------------------------------------------------------------------------
第十節(jié):聯(lián)合體和結(jié)構(gòu)體中的結(jié)構(gòu)體
IDA中可以像定義標(biāo)準(zhǔn)結(jié)構(gòu)體那樣來(lái)定義聯(lián)合體。
讓我們來(lái)試著定義product_u 這個(gè)聯(lián)合體吧。
book_t和software_t這兩個(gè)結(jié)構(gòu)體我們已經(jīng)定義過(guò)了。
IDA認(rèn)為聯(lián)合體就是一種特別的結(jié)構(gòu)體:因此我們打開Structures窗口,運(yùn)行Add struct type命令,在對(duì)話框中我們選擇創(chuàng)建Create union 選項(xiàng)。
我們可以使用IDA常用的命令來(lái)創(chuàng)建聯(lián)合體成員,分別添加一個(gè)book_t 結(jié)構(gòu)體類型的book和一個(gè)software_t 結(jié)構(gòu)體的software聯(lián)合體成員
當(dāng)然結(jié)構(gòu)體也可以嵌套一個(gè)結(jié)構(gòu)體。事實(shí)上,我們剛才做的例子就實(shí)現(xiàn)了。
記住IDA認(rèn)為聯(lián)合體只不過(guò)是一種特殊的結(jié)構(gòu)體
TOP
----------------------------------------------------------------------------------------------
第十一節(jié):可變的結(jié)構(gòu)體
我們還記得有一個(gè)softwares_t 結(jié)構(gòu)體。結(jié)構(gòu)體softs 的長(zhǎng)度是不確定的。
在匯編中,我們必須創(chuàng)建一個(gè)大小可變的結(jié)構(gòu)體~。這種結(jié)構(gòu)體創(chuàng)建的時(shí)候和普通的一樣,僅僅最后一個(gè)元素定義的數(shù)組元素個(gè)數(shù)為0。
既然IDA不能計(jì)算出這種結(jié)構(gòu)體的大小,我們就必須通過(guò)選擇結(jié)構(gòu)體的區(qū)域,來(lái)定義大小。
我們可以看到所有的類型IDA用注釋模式來(lái)顯示成員名稱
TOP
----------------------------------------------------------------------------------------------------
第十二節(jié):結(jié)構(gòu)體偏移
現(xiàn)在我們知道如何定義聯(lián)合體和結(jié)構(gòu)體了?,F(xiàn)在我們來(lái)將一些操作數(shù)指向他們?cè)局赶虻慕Y(jié)構(gòu)體。
在print_customer() 函數(shù)中,我們知道他只有一個(gè)指向customer_t結(jié)構(gòu)體的參數(shù)。EAX寄存器初始化這個(gè)指針的值,使他指向customer_t 結(jié)構(gòu)體。因此我們推斷所有的[EAX+....]都是指向customer_t結(jié)構(gòu)體成員的偏移。
我們開始重新定義這些結(jié)構(gòu)體變量的偏移,你右擊在他們上面IDA會(huì)自動(dòng)給你提供偏移的信息。
當(dāng)我們把所有的偏移量都整理一下的話,匯編代碼馬上就變得清晰易懂了。
print_software()函數(shù)呢就是另外一個(gè)例子:EBX在初始化的時(shí)候指向了software_t 及構(gòu)體。注意EBX寄存器在整個(gè)函數(shù)中都有應(yīng)用(一個(gè)一個(gè)替換會(huì)累死的)。不要緊張,IDA會(huì)使用一次操作就能替換全部。
做法如下:
選擇整個(gè)函數(shù)的代碼,然后選在Operands工具欄上的Offset (struct) 命令。
彈出Structure offsets窗口。然我們?cè)诹斜碇羞x擇EBX寄存器。
左邊樹形視圖顯示了在IDA中定義的所有結(jié)構(gòu)。
右邊就顯示與EBX有關(guān)系的所有操作。如果我們選擇了左邊的一個(gè)結(jié)構(gòu),
IDA就會(huì)自動(dòng)改變被選擇代碼中與結(jié)構(gòu)體有關(guān)的偏移量。
樹視圖前面不同的符號(hào)表示經(jīng)過(guò)計(jì)算后的狀態(tài)。對(duì)號(hào)就表示完全匹配,相反就是不完全匹配。在我們的操作中正好完全匹配。
確定以后,我們就得到了下面的結(jié)果:
TOP
--------------------------------------------------------------------------------------------------------------
第十三節(jié):聯(lián)合體偏移量
依靠產(chǎn)品種類,我們可以調(diào)用適當(dāng)?shù)暮瘮?shù)來(lái)打印產(chǎn)品信息。
但是這一次的結(jié)構(gòu)體偏移量跟以前不一樣了,它是product_u聯(lián)合體中的一個(gè)成員,它是一個(gè)數(shù),這時(shí)我們就選擇Edit struct 菜單中Select union member命令來(lái)處理
結(jié)果就是這樣:
Structure offset對(duì)話框顯示如何表明一個(gè)聯(lián)合體成員。在你選擇的區(qū)域中打開了這個(gè)窗口,IDA就會(huì)用“?”來(lái)顯示聯(lián)合體類型。
如果展開樹視圖中適當(dāng)?shù)姆种?,我們可以選擇被描述為聯(lián)合體成員的偏移量。
一旦選中,IDA會(huì)用在一種綠色的符號(hào)來(lái)表示偏移量指向的記錄中的聯(lián)合體。
TOP
--------------------------------------------------------------------------------------------------------
第十四節(jié):地址偏移量
IDA也可以重新定義操作數(shù)。在下面的例子中,桔黃色的部分顯示一個(gè)可能存在的參考~
使用Operands 工具欄上的Offset 按鈕就可以進(jìn)行轉(zhuǎn)換。
TOP
--------------------------------------------------------------------------------------------------------------------
第十五節(jié):最終逆向結(jié)果
To end this tutorial, we propose you a visual comparison of the original C source code and our final interactively disassembled code. 來(lái)look look我們用IDA整理的結(jié)果把
struct customer_t { long id; char name[32]; char sex; }
| ; ------------------------------------------------------------- customer_t struc ; (sizeof=0x28) id dd ? name db 32 dup(?) ; string(C) sex dd ? ; char customer_t ends | struct softwares_t { long count; software_t softs[]; };
| ; ------------------------------------------------------------- softwares_t struc ; (sizeof=0x4, variable size) count dd ? softs software_t 0 dup(?) softwares_t ends | struct book_t { char title[128]; };
| ; ------------------------------------------------------------- book_t struc ; (sizeof=0x80) title db 128 dup(?) ; string(C) book_t ends | struct software_t { software_info_t info; char name[32]; };
| ; ------------------------------------------------------------- software_t struc ; (sizeof=0x24) info dd ? ; enum software_info_t name db 32 dup(?) ; string(C) software_t ends |
union product_u { book_t book; software_t software; };
| ; ------------------------------------------------------------- product_u union ; (sizeof=0x80) book book_t ? software software_t ? product_u ends | struct product_t { long id; product_category_t category; product_u p; };
| ; ------------------------------------------------------------- product_t struc ; (sizeof=0x88) id dd ? category dd ? ; enum product_category_t p product_u ? product_t ends | enum product_category_t { BOOK, SOFTWARE, HARDWARE };
| ; ------------------------------------------------------------- ; enum product_category_t BOOK = 0 SOFTWARE = 1 HARDWARE = 2 | struct software_info_t { unsigned int plateform : 2; #define PC 0x1 // 0x01 #define MAC 0x2 // 0x02 unsigned int os : 3; #define WINDOWS 0x1 // 0x04 #define DOS 0x2 // 0x08 #define OS_X 0x4 // 0x10 unsigned int category : 2; #define DISASSEMBLY 0x1 // 0x20 #define RECOVERY 0x2 // 0x40 #define CRYPTOGRAPHY 0x3 // 0x60 };
| ; ------------------------------------------------------------- ; enum software_info_t (bitfield) PC = 1 MAC = 2 WINDOWS = 4 DOS = 8 OS_X = 10h category = 60h DISASSEMBLY = 20h RECOVERY = 40h CRYPTOGRAPHY = 60h |
| ; +------------------------------------------------------------+ ; ¦This file is generated by The Interactive Disassembler (IDA)¦ ; ¦Copyright (c) 2003 by DataRescue sa/nv, <ida@datarescue.com>¦ ; ¦ Licensed to: Eric <eric@datarescue.be>¦ ; +------------------------------------------------------------+ ; ; File Name : C:\IDA\Presentations\Data\data.exe ; Format : Portable executable for IBM PC (PE) ; Section 1. (virtual address 00001000) ; Virtual size : 00009000 ( 36864.) ; Section size in file : 00008E00 ( 36352.) ; Offset to raw data for section: 00000600 ; Flags 60000020: Text Executable Readable ; Alignment : 16 bytes ? unicode macro page,string,zero irpc c,<string> db ‘&c‘, page endm ifnb <zero> dw zero endif endm model flat ; -------------------------------------------------------------- ; Segment type: Pure code ; Segment permissions: Read/Execute _text segment para public ‘CODE‘ use32 assume cs:_text ;org 401000h ; [COLLAPSED AREA .text1. PRESS KEYPAD "+" TO EXPAND] | int check_software(software_info_t software_info) { bool valid = true;
if (software_info.plateform & PC) {
if (! (software_info.plateform & MAC)
&& (software_info.os & OS_X))
valid = false; }
else if (software_info.plateform & MAC) {
if (! (software_info.plateform & PC)
&& ((software_info.os & WINDOWS)
|| (software_info.os & DOS)))
valid = false; }
else valid = false;
return valid; }
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; int __cdecl check_software(software_info_t software_info) check_software proc near ; CODE XREF: main+108p software_info= byte ptr 8 push ebp mov ebp, esp mov al, 1 mov dl, [ebp+software_info] and edx, PC or MAC test dl, PC jz short not_PC mov cl, [ebp+software_info] and ecx, PC or MAC test cl, MAC jnz short end mov dl, [ebp+software_info] shr edx, 2 and edx, (WINDOWS or DOS or OS_X) >> 2 test dl, OS_X >> 2 jz short end xor eax, eax jmp short end ; -------------------------------------------------------------- not_PC: ; CODE XREF: check_software+Ej mov cl, [ebp+software_info] and ecx, PC or MAC test cl, MAC jz short not_MAC mov dl, [ebp+software_info] and edx, PC or MAC test dl, PC jnz short end mov cl, [ebp+software_info] shr ecx, 2 and ecx, (WINDOWS or DOS or OS_X) >> 2 test cl, WINDOWS >> 2 jnz short not_windows mov dl, [ebp+software_info] shr edx, 2 and edx, (WINDOWS or DOS or OS_X) >> 2 test dl, DOS >> 2 jz short end not_windows: ; CODE XREF: check_software+4Fj xor eax, eax jmp short end ; -------------------------------------------------------------- not_MAC: ; CODE XREF: check_software+36j xor eax, eax end: ; CODE XREF: check_software+19j ... xor edx, edx mov dl, al mov eax, edx pop ebp retn check_software endp ; -------------------------------------------------------------- align 4 | int check_product(product_category_t product_category) {
bool valid = true; if (product_category == HARDWARE) { valid = false; printf("We don‘t sell hardware for the moment...\n"); }
return valid; }
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; int __cdecl check_product(product_category_t product_category) check_product proc near ; CODE XREF: print_product+Ap main+D8p product_category= dword ptr 8 push ebp mov ebp, esp push ebx mov bl, 1 cmp [ebp+product_category], HARDWARE jnz short not_hardware xor ebx, ebx push offset aWeDonTSellHardwareForThe ; format call _printf pop ecx not_hardware: ; CODE XREF: check_product+Aj xor eax, eax mov al, bl pop ebx pop ebp retn check_product endp | void print_customer(customer_t *customer) {
printf("CUSTOMER %04X: %s (%c)\n", customer->id, customer->name, customer->sex);
}
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; void __cdecl print_customer(customer_t *customer) print_customer proc near ; CODE XREF: main+19p customer= dword ptr 8 push ebp mov ebp, esp mov eax, [ebp+customer] movsx edx, byte ptr [eax+customer_t.sex] push edx lea ecx, [eax+customer_t.name] push ecx push [eax+customer_t.id] push offset aCustomer04xSC ; format call _printf add esp, 10h pop ebp retn print_customer endp | void print_book(book_t *book) {
printf("BOOK: %s\n", book->title);
}
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; void __cdecl print_book(book_t *book) print_book proc near ; CODE XREF: print_product+38p book= dword ptr 8 push ebp mov ebp, esp push [ebp+book] push offset aBookS ; format call _printf add esp, 8 pop ebp retn print_book endp ; ------------------------------------------------------------- align 4 | void print_software(software_t *software) {
printf("SOFTWARE: %s:", software->name);
if (software->info.plateform & PC)
printf(" PC");
if (software->info.plateform & MAC)
printf(" MAC");
printf(";");
if (software->info.os & WINDOWS)
printf(" WINDOWS");
if (software->info.os & DOS)
printf(" DOS");
if (software->info.os & OS_X)
printf(" OS-X");
printf(";");
switch(software->info.category) {
case DISASSEMBLY:
printf(" DISASSEMBLY");
break;
case RECOVERY:
printf(" RECOVERY");
break;
case CRYPTOGRAPHY:
printf(" CRYPTOGRAPHY"); break;
}
printf("\n");
}
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; void __cdecl print_software(software_t *software) print_software proc near ; CODE XREF: print_product+44p software= dword ptr 8 push ebp mov ebp, esp push ebx push esi mov ebx, [ebp+software] mov esi, offset aWeDonTSellHardwareForThe lea eax, [ebx+software_t.name] push eax lea edx, (aSoftwareS - aWeDonTSellHardwareForThe)[esi] push edx ; format call _printf add esp, 8 mov cl, byte ptr [ebx+software_t.info] and ecx, PC or MAC test cl, PC jz short not_pc lea eax, (aPc - aWeDonTSellHardwareForThe)[esi] push eax ; format call _printf pop ecx not_pc: mov dl, byte ptr [ebx+software_t.info] and edx, PC or MAC test dl, MAC jz short not_mac lea ecx, (aMac - aWeDonTSellHardwareForThe)[esi] push ecx ; format call _printf pop ecx not_mac: lea eax, (asc_40A31B - aWeDonTSellHardwareForThe)[esi] push eax ; format call _printf pop ecx mov dl, byte ptr [ebx+software_t.info] shr edx, 2 and edx, (WINDOWS or DOS or OS_X) >> 2 test dl, WINDOWS >> 2 jz short not_windows lea ecx, (aWindows - aWeDonTSellHardwareForThe)[esi] push ecx ; format call _printf pop ecx not_windows: mov al, byte ptr [ebx+software_t.info] shr eax, 2 and eax, (WINDOWS or DOS or OS_X) >> 2 test al, DOS >> 2 jz short not_dos lea edx, (aDos - aWeDonTSellHardwareForThe)[esi] push edx ; format call _printf pop ecx not_dos: mov cl, byte ptr [ebx+software_t.info] shr ecx, 2 and ecx, (WINDOWS or DOS or OS_X) >> 2 test cl, OS_X >> 2 jz short not_os_x lea eax, (aOsX - aWeDonTSellHardwareForThe)[esi] push eax ; format call _printf pop ecx not_os_x: lea edx, (asc_40A331 - aWeDonTSellHardwareForThe)[esi] push edx ; format call _printf pop ecx mov cl, byte ptr [ebx+software_t.info] shr ecx, 5 and ecx, category >> 5 dec ecx jz short DISASSEMBLY dec ecx jz short RECOVERY dec ecx jz short CRYPTOGRAPHY jmp short end ; ------------------------------------------------------------ DISASSEMBLY: lea eax, (aDisassembly - aWeDonTSellHardwareForThe)[esi] push eax ; format call _printf pop ecx jmp short end ; ------------------------------------------------------------ RECOVERY: lea edx, (aRecovery - aWeDonTSellHardwareForThe)[esi] push edx ; format call _printf pop ecx jmp short end ; ------------------------------------------------------------ CRYPTOGRAPHY: lea ecx, (aCryptography - aWeDonTSellHardwareForThe)[esi] push ecx ; format call _printf pop ecx end: lea eax, (asc_40A358 - aWeDonTSellHardwareForThe)[esi] push eax ; format call _printf pop ecx pop esi pop ebx pop ebp retn print_software endp ; ------------------------------------------------------------ align 4 |
bool print_product(product_t *product) {
if (! check_product( product->category))
return false;
printf("PRODUCT %04X: ", product->id);
switch(product->category) {
case BOOK:
print_book(&product->p.book);
break;
case SOFTWARE:
print_software( &product->p.software); break;
}
return true; }
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; int __cdecl print_product(product_t *product) print_product proc near ; CODE XREF: main+128p product= dword ptr 8 push ebp mov ebp, esp push ebx mov ebx, [ebp+product] push [ebx+product_t.category] ; product_category call check_product pop ecx test eax, eax jnz short check_product_ok xor eax, eax pop ebx pop ebp retn ; ------------------------------------------------------------ check_product_ok: ; CODE XREF: print_product+12j push [ebx+product_t.id] push offset aProduct04x ; format call _printf add esp, 8 mov edx, [ebx+product_t.category] sub edx, 1 jb short case_book jz short case_software jmp short default ; ------------------------------------------------------------ case_book: ; CODE XREF: print_product+2Ej add ebx, product_t.p.book.title push ebx ; book call print_book pop ecx jmp short default ; ------------------------------------------------------------ case_software: ; CODE XREF: print_product+30j add ebx, product_t.p.software.info push ebx ; software call print_software pop ecx default: ; CODE XREF: print_product+32j ... mov al, 1 pop ebx pop ebp retn print_product endp ; ------------------------------------------------------------ align 4 | void main() {
printf("CUSTOMERS:\n");
customer_t *customer = customers;
while (customer->id != 0) { print_customer(customer);
customer++;
} product_t *products = (product_t*) malloc(PRODUCTS_COUNT * sizeof(product_t));
products[0].id = 1; products[0].category = BOOK; products[0].p.book = ida_book;
products[1].id = 2; products[1].category = SOFTWARE; products[1].p.software = softwares.softs[0];
products[2].id = 3; products[2].category = SOFTWARE; products[2].p.software = softwares.softs[1];
products[3].id = 4; products[3].category = SOFTWARE; products[3].p.software = softwares.softs[2];
printf("\nPRODUCTS:\n");
for (int i = 0; i < PRODUCTS_COUNT; i++) {
if (! check_product( products[i].category)) {
printf("Invalid product !!!\n");
break; }
if (products[i].category == SOFTWARE) {
if (! check_software( products[i].p.software.info)) {
printf("Invalid software !!!\n");
break; } }
print_product(&products[i]);
}
free(products);
}
| ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ ; Attributes: bp-based frame ; void __cdecl main() main proc near ; DATA XREF: .data:0040A0D0o push ebp mov ebp, esp push ebx push esi push edi push offset aCustomers ; format call _printf pop ecx mov ebx, offset customers jmp short loc_401376 ; ------------------------------------------------------------ loop_print_customer: ; CODE XREF: main+25j push ebx ; customer call print_customer pop ecx add ebx, 40 loc_401376: ; CODE XREF: main+16j cmp [ebx+customer_t.id], 0 jnz short loop_print_customer push 544 ; size call _malloc pop ecx mov ebx, eax mov [ebx+product_t.id], 1 xor eax, eax ; BOOK mov [ebx+product_t.category], eax mov esi, offset aIdaQuickstartG ; "IDA QuickStart Guide" lea edi, [ebx+product_t.p.book.title] mov ecx, 32 rep movsd mov dword ptr [ebx+product_t[1].id], 2 mov dword ptr [ebx+product_t[1].category], SOFTWARE mov esi, offset softwares.softs lea edi, [ebx+product_t[1].p.software] mov ecx, 9 rep movsd mov dword ptr [ebx+product_t[2].id], 3 mov dword ptr [ebx+product_t[2].category], SOFTWARE mov esi, (offset softwares.softs.info+24h) lea edi, [ebx+product_t[2].p.software] mov ecx, 9 rep movsd mov dword ptr [ebx+product_t[3].id], 4 mov dword ptr [ebx+product_t[3].category], SOFTWARE mov esi, (offset softwares.softs.info+48h) lea edi, [ebx+product_t[3].p.software] mov ecx, 9 rep movsd push offset aProducts ; format call _printf pop ecx xor esi, esi loop_verify_print_product: ; CODE XREF: main+132j mov eax, esi shl eax, 4 add eax, esi push [ebx+eax*8+product_t.category] ; product_category call check_product pop ecx test eax, eax jnz short product_is_valid push offset aInvalidProduct ; format call _printf pop ecx jmp short exit ; ------------------------------------------------------------ product_is_valid: ; CODE XREF: main+E0j mov edx, esi shl edx, 4 add edx, esi cmp [ebx+edx*8+product_t.category], SOFTWARE jnz short print_product mov ecx, esi shl ecx, 4 add ecx, esi push [ebx+ecx*8+product_t.p.software.info] ; software_info call check_software pop ecx test eax, eax jnz short print_product push offset aInvalidSoftwar ; format call _printf pop ecx jmp short exit ; ----------------------------------------------------------- print_product: ; CODE XREF: main+FBj main+110j imul eax, esi, 88h add eax, ebx push eax ; product call print_product pop ecx inc esi cmp esi, 4 jl short loop_verify_print_product exit: ; CODE XREF: main+EDj main+11Dj push ebx ; block call _free pop ecx pop edi pop esi pop ebx pop ebp retn main endp |
| ; [COLLAPSED AREA .text2. PRESS KEYPAD "+" TO EXPAND] ; [COLLAPSED AREA .text2. PRESS KEYPAD "+" TO EXPAND] ; Section 2. (virtual address 0000A000) ; Virtual size : 00003000 ( 12288.) ; Section size in file : 00002800 ( 10240.) ; Offset to raw data for section: 00009400 ; Flags C0000040: Data Readable Writable ; Alignment : 16 bytes ? ; ------------------------------------------------------------ ; Segment type: Pure data ; Segment permissions: Read/Write _data segment para public ‘DATA‘ use32 assume cs:_data ;org 40A000h ; [COLLAPSED AREA .data1. PRESS KEYPAD "+" TO EXPAND] | customer_t customers[] = { { 1, "Peter", ‘m‘ }, { 2, "John", ‘m‘ }, { 3, "Mary", ‘f‘ }, { 0 } };
| customers dd 1 ; id ; DATA XREF: main+11o db ‘Peter‘,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ... ; name dd ‘m‘ ; sex dd 2 ; id db ‘John‘,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,... ; name dd ‘m‘ ; sex dd 3 ; id db ‘Mary‘,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,... ; name dd ‘f‘ ; sex dd 0 ; id db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, ... ; name db 0 ; name dd 0 ; sex | book_t ida_book = { "IDA QuickStart Guide" };
| aIdaQuickstartG db ‘IDA QuickStart Guide‘,0 ; DATA XREF: ... db 6Bh dup(0) | softwares_t softwares = { 3, { { { PC, WINDOWS|DOS, DISASSEMBLY }, "IDA Pro" }, { { PC|MAC, WINDOWS|OS_X, RECOVERY }, "PhotoRescue" }, { { PC, WINDOWS, CRYPTOGRAPHY }, "aCrypt" } } };
| softwares dd 3 ; count ; DATA XREF: main+62o dd PC or WINDOWS or DOS or DISASSEMBLY; softs.info db ‘IDA Pro‘,0,0,0,0,0,0,0,0,0,0,0,0,0, ...; softs.name dd PC or MAC or WINDOWS or OS_X or RECOVERY; softs.info db ‘PhotoRescue‘,0,0,0,0,0,0,0,0,0,0,0, ...; softs.name dd PC or WINDOWS or CRYPTOGRAPHY; softs.info db ‘a(chǎn)Crypt‘,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...; softs.name |
| aWeDonTSellHardwareForThe db ‘We don‘,27h,‘t sell hardware ... ; DATA XREF: check_product+Eo ... aCustomer04xSC db ‘CUSTOMER %04X: %s (%c)‘,0Ah,0 ; ... aBookS db ‘BOOK: %s‘,0Ah,0 ; DATA XREF: print_book+6o aSoftwareS db ‘SOFTWARE: %s:‘,0 ; DATA XREF: ... aPc db ‘ PC‘,0 ; DATA XREF: print_software+27r aMac db ‘ MAC‘,0 ; DATA XREF: print_software+3Br asc_40A31B db ‘;‘,0 ; DATA XREF: print_software+45r aWindows db ‘ WINDOWS‘,0 ; DATA XREF: ... aDos db ‘ DOS‘,0 ; DATA XREF: print_software+72r aOsX db ‘ OS-X‘,0 ; DATA XREF: print_software+89r asc_40A331 db ‘;‘,0 ; DATA XREF: print_software+93r aDisassembly db ‘ DISASSEMBLY‘,0 ; DATA XREF: ... aRecovery db ‘ RECOVERY‘,0 ; DATA XREF: ... aCryptography db ‘ CRYPTOGRAPHY‘,0 ; DATA XREF: ... asc_40A358 db 0Ah,0 ; DATA XREF: print_software+D8r aProduct04x db ‘PRODUCT %04X: ‘,0 ; DATA XREF: ... aCustomers db ‘CUSTOMERS:‘,0Ah,0 ; DATA XREF: ... aProducts db 0Ah ; DATA XREF: main+C0o db ‘PRODUCTS:‘,0Ah,0 aInvalidProduct db ‘Invalid product !!!‘,0Ah,0 ; ... aInvalidSoftwar db ‘Invalid software !!!‘,0Ah,0 ; ... | |
TOP
附錄
#include
<stdio.h>
// our structures
// ==============
// information about our customers
struct
customer_t { // a typical structurelong id;
char name[32];
char sex; // ‘m‘a(chǎn)le - ‘f‘emale
};
// we sell books
struct
book_t {char title[128]; // an ASCII string
};
// and we sell computer softwares
struct
software_info_t { // a structure containing various bitfieldsunsigned int plateform : 2; // 2 bits reserved for the plateform - plateforms can be combined (0x03)#define
PC 0x1 // 0x01#define
MAC 0x2 // 0x02
unsigned int os : 3; // 3 bits reserved for the OS - OS can be combined (0x1C)#define
WINDOWS 0x1 // 0x04#define
DOS 0x2 // 0x08#define
OS_X 0x4 // 0x10
unsigned int category : 2; // 2 bits reserved for the category - categories can‘t be combined (0x60)#define
DISASSEMBLY 0x1 // 0x20#define
RECOVERY 0x2 // 0x40#define
CRYPTOGRAPHY 0x3 // 0x60
};
struct
software_t {software_info_t info;
char name[32];
};
struct
softwares_t { // a variable length structure to memorize our softwareslong count;
software_t softs[];
};
// generic products we‘re selling
enum
product_category_t { // an enumerated typeBOOK,
SOFTWARE,
HARDWARE // we actually don‘t sell hardware
};
union
product_u { // an union to contain product information depending on its categorybook_t book;
software_t software;
// struct hardware_t hardware; // we actually don‘t sell hardware
};
struct
product_t { // a structure containing another structurelong id;
product_category_t category;
product_u p;
};
// our data
// ========
// our customers
customer_t
customers[] = { // an initialized array to memorize our customers{ 1, "Peter", ‘m‘ },
{ 2, "John", ‘m‘ },
{ 3, "Mary", ‘f‘ },
{ 0 }
};
// our products
book_t
ida_book = { "IDA QuickStart Guide" };softwares_t
softwares = // an initialized variable length structure{
3,
{
{ { PC, WINDOWS|DOS, DISASSEMBLY }, "IDA Pro" },
{ { PC|MAC, WINDOWS|OS_X, RECOVERY }, "PhotoRescue" },
{ { PC, WINDOWS, CRYPTOGRAPHY }, "aCrypt" }
}
};
#define
PRODUCTS_COUNT 4
// our functions
// =============
// check software information
int
check_software(software_info_t software_info){
bool valid = true;
if (software_info.plateform & PC)
{
if (! (software_info.plateform & MAC) && (software_info.os & OS_X))
valid = false; // OS-X isn‘t yet available on PC ;)
}
else if (software_info.plateform & MAC)
{
if (! (software_info.plateform & PC) && ((software_info.os & WINDOWS) || (software_info.os & DOS)))
valid = false; // Windows & DOS aren‘t available on Mac...
}
else
valid = false;
return valid;
}
// check product category
int
check_product(product_category_t product_category){
bool valid = true;
if (product_category == HARDWARE)
{
valid = false;
printf("We don‘t sell hardware for the moment...\n");
}
return valid;
}
// print customer information
void
print_customer(customer_t *customer){
printf("CUSTOMER %04X: %s (%c)\n", customer->id, customer->name, customer->sex);
}
// print book information
void
print_book(book_t *book){
printf("BOOK: %s\n", book->title);
}
// print software information
void
print_software(software_t *software){
printf("SOFTWARE: %s:", software->name);
// plateform
// we use ‘if‘, as plateforms can be combined
if (software->info.plateform & PC)
printf(" PC");
if (software->info.plateform & MAC)
printf(" MAC");
printf(";");
// OS
// we use ‘if‘, as os can be combined
if (software->info.os & WINDOWS)
printf(" WINDOWS");
if (software->info.os & DOS)
printf(" DOS");
if (software->info.os & OS_X)
printf(" OS-X");
printf(";");
// category
// we use ‘switch‘, as categories can‘t be combined
switch(software->info.category)
{
case DISASSEMBLY:
printf(" DISASSEMBLY");
break;
case RECOVERY:
printf(" RECOVERY");
break;
case CRYPTOGRAPHY:
printf(" CRYPTOGRAPHY");
break;
}
printf("\n");
}
// print product information
bool
print_product(product_t *product){
if (! check_product(product->category))
return false;
printf("PRODUCT %04X: ", product->id);
switch(product->category) {
case BOOK:
print_book(&product->p.book);
break;
case SOFTWARE:
print_software(&product->p.software);
break;
}
return true;
}
// our main program
// ================
void
main() {// print customers listing
printf("CUSTOMERS:\n");
customer_t *customer = customers;
while (customer->id != 0)
{
print_customer(customer);
customer++;
}
// allocate a small array to store our products in memory
product_t *products = (product_t*) malloc(PRODUCTS_COUNT * sizeof(product_t));
// insert our products
products[0].id = 1;
products[0].category = BOOK;
products[0].p.book = ida_book;
products[1].id = 2;
products[1].category = SOFTWARE;
products[1].p.software = softwares.softs[0]; // we insert softwares from our variable length structure
products[2].id = 3;
products[2].category = SOFTWARE;
products[2].p.software = softwares.softs[1];
products[3].id = 4;
products[3].category = SOFTWARE;
products[3].p.software = softwares.softs[2];
// verify and print each product
printf("\nPRODUCTS:\n");
for (int i = 0; i < PRODUCTS_COUNT; i++)
{
// check validity of the product category
if (! check_product(products[i].category))
{
printf("Invalid product !!!\n");
break;
}
// check validity of softwares
if (products[i].category == SOFTWARE)
{
if (! check_software(products[i].p.software.info))
{
printf("Invalid software !!!\n");
break;
}
}
// and print the product
print_product(&products[i]);
}
free(products);
}