IDA简易教程
作者:www.datarescue.com
本文的主要内容就是讲如何用IDA来辅助识别各种类型的数据.
版权信息:所有版权归原文作者所有,如许转载清保持文章完整性。
索引
1 第一节:C语言的小程序
2 第二节:基本类型的识别
3 第三节:操作数格式
4 第四节:字符和字符串的操作
5 第五节:数组
6 第六节:枚举类型
7 第七节:Bit-fields(位域)
8 第八节:结构体
9 第九节:结构变量和结构数组
10 第十节:联合体和结构体中的结构体
11 第十一节:可变的结构体
12 第十二节:结构体偏移
13 第十三节:联合体偏移量
14 第十四节:地址偏移量
15 第十五节:最终逆向结果
附录
第一节:C语言的小程序
为了演示IDA的功能先写一段小程序。(代码在附录)程序在此 源代码
程序执行结果:
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
----------------------------------------------------------------------
第二节:基本类型的识别
用IDA分析我们前面的程序,我们会发现下图的类型
只要按"D"我们就可以任意转换这些不确定的类型.可以变成byte,word,dword(db,dw,dd)。
当然你也可以设置更多的数据转换类型:
选择“Options”菜单的“Setup data types”命令就可以设置了
值得注意的是:你在数据转换的时候,它是依据数据自身的结构来转换的。我们按“D”的时候,
如果下一个字节已经被你转换过,你的本次转换,IDA将会提示让你确认。
注:如果你想改变这种默认设置可以在“Options”菜单“Convert already defined bytes”命令里设置
撤销你的所有转换按“U”键。
TOP
-------------------------------------------------------------------------------------
第三节:操作数格式
数据类型自定义转换后,被操作过的数据(就是你按过“D”的)的进制IDA也是可以自定义转变的,
通过在“Operands”工具栏的“Number”命令我们可以随意转换数字的进制
最下面的“Toggle leading point”就是填补数据前的空位为0(就是说如果当前数据未占满数据格式的所有位高位用0来填补)
IDA还可以转换数据的标志位(就是正负)具体操作如下图:
最后呢~~如果这些转换你还不满意(够BT)当然你还可以自定义数据进制如图:
TOP
-----------------------------------------------------------------------------------------
第四节:字符和字符串的操作
作者又说话了:很多程序都是包含字符串的,一些被操作过的数据(就是你按过“D”的)可以转化为
字符,使用的命令就在“Operands”工具栏上
由于编程语言的不同造成字符串也有不同的格式,当然IDA就支持所有的格式了。
IDA在转化后会在地址添加一个名字。因为我们的程序是c的所以就找到c的字符串。具体操作如图:
如果不是C写的程序怎么办呢?我们可以在“Options”菜单“ASCII string style”命令中设置。
允许你修改其它类型为默认设置,使用默认设置的快捷键是“A”,或者自定义一种类型可以使用不常用的终止字符。
TOP
--------------------------------------------------------------------------
第五节:数组
在c中,ASCII字符串被认为是字符数组,IDA是如何处理数组的呢?
我们用最常用命令来定义数组中的第一个元素,设置第一个元素类型为byte,格式为char,然后点击“*”号键(或者“Edition ”工具栏的“Array”命令)来创建数组。这时弹出一个对话框,可以设置很多变量。
你可以定义数组一行的显示个数,还可以使用“Element width”来设置他们之间的宽度。
使用“Use dup construct ”选项可以合并连贯的相似字节,“ Display index ”选项可以像注释一样显示数组的下标。
例如我们设置一个有64个元素的数组,一行有8个元素,每个元素之间的宽度为4,不选取“dup constructs”,选取“Display index ”,我们就可以得到下面的数组。
当IDA遇到未被识别的字节他会用红色的高亮显示。
当然你也可以选择一个范围来创建数组,IDA会自适应的设定。
TOP
------------------------------------------------------------------------------------
第六节:枚举类型
还记得我们在C程序中定义的product_category_t 类型吗?
让我们用IDA的“Enumerations”来定义一下。
首先,我们打开“Enumerations”窗口来创建一个新的枚举类型
我们输入我们的枚举类型值
在check_product()函数,我们可以用枚举类型重新定义一些操作数。
右键点击在数值上,就会弹出一个菜单,选择“Symbolic constant”。
IDA就会自动列举枚举值,用以匹配当前的数值。
操作完成,我们就会得到下面的结果:
TOP
-----------------------------------------------------------------------------------------------------
第七节:Bit-fields(位域)
BTW:Bit-fields,我的理解就是在结构体中的位标志。太菜!希望高手指正!
现在,我们来定义一下在software_info_t 结构中的bitfields。
IDA的观点就是,bitefields是一种特殊的枚举类型。
我们可以选择在枚举类型创造窗口中的“Bitfield”选项。
还记得我们曾经在我们的程序中建立了两种不同类型的bitfields ,
plateform和os包含了一种隐藏的模式:用来包含组合模式(用逻辑或来操作) 。因为一种产品可以同时在几种plateforms和OS的组合。另一方面,category bitfield 中每一个数字表示一种类别:一种产品每次只能属于一种类别。
在IDA中一种指定的模式,bitfield只能包含一个值。所以在描述plateform 和category bitfields时为了显示组合模式,我们必须创建一个小的bitfields,每个值的一个bit.
现在我们开始创建category bitfield。mask值为0x3 (2 bits).我们指定一个名字、一个值、还有bitfield mask。我们还需要定义mask的名字:这个我们不用IDA自动生成的,IDA有一个内存助手可以帮助生成。
当所有的bitfields被输入,我们就会得到下面的结果:
用Operands 工具栏上的Enum member命令就可以定义我们程序中的Enum member数据
TOP
---------------------------------------------------------------------------------------------------------
第八节:结构体
我们的程序当中包含了很多结构体。现在让我们来在IDA中描述一下结构体,
看看是怎么提高汇编代码的可读性。
第一步,我们必须打开Structures 窗口,来创建一个新的结构体类型。
结构体的成员是一汇编的模式定义的。让我们来定义software_t 结构中的第一个成员。
一直按“D”知道它变成“dd”意思就是这个成员的值为 dword类型。
把它的格式定义为我们以前定义好的software_info_t 枚举类型,然后我们用Rename命令输入一个适当的名字:info
开始定义第二个成员,这次使用ASCII命令(按“A”),在这个环节
IDA会弹出一个专用对话框用来设定字符串的大小
我们还可以从已经分析好的数据中来建立结构体。
举个例子:假设我们选择了一块数据正好是和我们的customer_t结构体的数据格式一样,我们就可以用IDA的“Create struct from data ”命令来创建结构体
一旦使用了这个命令,IDA就会在Structures窗口创建一个相对应的结构体
我们使用“A”键来修改name成员的长度为32bytes(和我们源代码中定义的一样),然后再给结构体一个好听的名字。
我们拿这些结构体有什么用呢?IDA提供给我们两种方法:
·Apply structure types to initialized data in the program.
·Convert operands as offsets inside structures.
我们将在下面的教程当中来介绍这两种方法
TOP
---------------------------------------------------------------------------------------------------------------------
第九节:结构变量和结构数组
现在让我们用来customer_t结构体整理另外一个客户信息John。
把鼠标指针放在我们定义的结构体的第一个自己上面,然后使用Struct var命令。
这样我们就得到了一个新的结构体变量。IDA会自动在结构体成员的后面加上变量名的。
通过我们的源码,我们知道有一个包含个4元素的customers数组,我们先前把
Peter和John都定义为 customer_t 结构体了。现在取消对Join结构变量的定义,然后在Peter结构上按“*”键创建我们的customer数组,这样IDA就弹出一个数组设置框他会自动检测出来我们要创建的数组最大数是4。
下来我们就看到创建好的数组了,剩下的就是改一下数组的名字。
TOP
-------------------------------------------------------------------------------------------------------
第十节:联合体和结构体中的结构体
IDA中可以像定义标准结构体那样来定义联合体。
让我们来试着定义product_u 这个联合体吧。
book_t和software_t这两个结构体我们已经定义过了。
IDA认为联合体就是一种特别的结构体:因此我们打开Structures窗口,运行Add struct type命令,在对话框中我们选择创建Create union 选项。
我们可以使用IDA常用的命令来创建联合体成员,分别添加一个book_t 结构体类型的book和一个software_t 结构体的software联合体成员
当然结构体也可以嵌套一个结构体。事实上,我们刚才做的例子就实现了。
记住IDA认为联合体只不过是一种特殊的结构体
TOP
----------------------------------------------------------------------------------------------
第十一节:可变的结构体
我们还记得有一个softwares_t 结构体。结构体softs 的长度是不确定的。
在汇编中,我们必须创建一个大小可变的结构体~。这种结构体创建的时候和普通的一样,仅仅最后一个元素定义的数组元素个数为0。
既然IDA不能计算出这种结构体的大小,我们就必须通过选择结构体的区域,来定义大小。
我们可以看到所有的类型IDA用注释模式来显示成员名称
TOP
----------------------------------------------------------------------------------------------------
第十二节:结构体偏移
现在我们知道如何定义联合体和结构体了。现在我们来将一些操作数指向他们原本指向的结构体。
在print_customer() 函数中,我们知道他只有一个指向customer_t结构体的参数。EAX寄存器初始化这个指针的值,使他指向customer_t 结构体。因此我们推断所有的[EAX+....]都是指向customer_t结构体成员的偏移。
我们开始重新定义这些结构体变量的偏移,你右击在他们上面IDA会自动给你提供偏移的信息。
当我们把所有的偏移量都整理一下的话,汇编代码马上就变得清晰易懂了。
print_software()函数呢就是另外一个例子:EBX在初始化的时候指向了software_t 及构体。注意EBX寄存器在整个函数中都有应用(一个一个替换会累死的)。不要紧张,IDA会使用一次操作就能替换全部。
做法如下:
选择整个函数的代码,然后选在Operands工具栏上的Offset (struct) 命令。
弹出Structure offsets窗口。然我们在列表中选择EBX寄存器。
左边树形视图显示了在IDA中定义的所有结构。
右边就显示与EBX有关系的所有操作。如果我们选择了左边的一个结构,
IDA就会自动改变被选择代码中与结构体有关的偏移量。
树视图前面不同的符号表示经过计算后的状态。对号就表示完全匹配,相反就是不完全匹配。在我们的操作中正好完全匹配。
确定以后,我们就得到了下面的结果:
TOP
--------------------------------------------------------------------------------------------------------------
第十三节:联合体偏移量
依靠产品种类,我们可以调用适当的函数来打印产品信息。
但是这一次的结构体偏移量跟以前不一样了,它是product_u联合体中的一个成员,它是一个数,这时我们就选择Edit struct 菜单中Select union member命令来处理
结果就是这样:
Structure offset对话框显示如何表明一个联合体成员。在你选择的区域中打开了这个窗口,IDA就会用“?”来显示联合体类型。
如果展开树视图中适当的分支,我们可以选择被描述为联合体成员的偏移量。
一旦选中,IDA会用在一种绿色的符号来表示偏移量指向的记录中的联合体。
TOP
--------------------------------------------------------------------------------------------------------
第十四节:地址偏移量
IDA也可以重新定义操作数。在下面的例子中,桔黄色的部分显示一个可能存在的参考~
使用Operands 工具栏上的Offset 按钮就可以进行转换。
TOP
--------------------------------------------------------------------------------------------------------------------
第十五节:最终逆向结果
To end this tutorial, we propose you a visual comparison of the original C source code and our final interactively disassembled code.
来look look我们用IDA整理的结果把
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)¦
; +------------------------------------------------------------+
;
; 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
'aCrypt',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 structure
long
id;
char
name[32];
char
sex; // 'm'ale - '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 bitfields
unsigned
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 softwares
long
count;
software_t
softs[];
};
// generic products we're selling
enum
product_category_t { // an enumerated type
BOOK
,
SOFTWARE
,
HARDWARE
// we actually don't sell hardware
};
union
product_u { // an union to contain product information depending on its category
book_t
book;
software_t
software;
// struct hardware_t hardware; // we actually don't sell hardware
};
struct
product_t { // a structure containing another structure
long
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);
}