使用IDA 分析高级数据结构

使用 IDA 反汇编时,一些数据和操作数的处理方式可能并不准确。IDA 允许我们手动去修
改这些数据的类型和定义,我们甚至可以使用类似高级语言的数据结构。

一个C 语言程序

为了介绍IDA 的数据分析处理功能,我们先看一个C 语言编写的使用特殊数据类型和结构
的小程序:

#include <stdio.h> 
#include <alloc.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]; 
}; 
// 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); 
} 

运行这个可执行程序可得到如下结果:
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
下面让我们打开IDA 装载这个程序来分析它。

基础类型
我们可以很容易的将数据和一些数据基础类型联系起来,我们可以简单的使用快捷键“D”
在字节db、字dw、双字dd 间进行循环切换。

你可以定义循环切换包含的数据类型。我们试着在这个循环切换队列种加入浮点数 float:
使用“D”可以将一个双字类型dd 的数据转换为浮点数float。使用options 菜单中Setup data
types 命令即可打开下面的窗口。

注意,数据类型改变时,相应数据的大小也随之变化。如下图,当我们在一个定义过的字节
db 上按“D”时,它将转换为一个字dw,但是由于下一个字已经定义,因此IDA 给出一个
提示以让我们确认。

这是数据类型切换时的默认操作,该操作可以通过修改options对话框种的Convert already
defined bytes来修改这个设置。

你也可以使用快捷键U 来取消对数据的定义。

操作数格式

一旦数据类型被确定,我们就希望能用特定的格式来显示他们。IDA提供了很多不同命令来
支持格式转换。我们来看一些有趣的。请注意所有这些命令也可以用在指令的操作数上。通
过在Operands工具条上的Number命令,我们可以随意切换数据格式。

我们可以在数字数据的前面补零显示。如下图:

也可以改变操作数的符号,或对操作数进行逐位取反。

最后,如果你需要的格式不在其中,你可以自己手动定义。

字符和字串
很多程序包含字符串。如果需要将定义的数据显示为字符,我们需要使用操作数工具条上的
字串命令。

当然,有很多不同的字符串类型。IDA 通过Strings 命令,支持多种字串类型。一旦你创建
一个字串,IDA 自动给出一个字串名字。下面我们用这种方法来处理我们C 程序中的一些字
串。

如果我们不是处理一个C 程序该如何做呢?在Options 菜单中提供了一些ASCII 字串风格条
目选项,允许我们来改变默认的字串类型。也可以手动定义一些带有不常用的结束字符的特
殊的字串。

数组
在C 中,ASCII 字串通常使用一个字符数组来表示。IDA 是如何处理数组的呢?
首先,我们要从定义数组的第一个元素来开始。在本例中,我们设定第一元素类型为字节并
设定它的格式为字符,接着我们按”*”键或使用Edition 工具条的数组命令来产生实际的
数组,这时,出现一个对话框,通过它我们可以生成不同的数组设定。

IDA 给出了建议的数组大小,它是根据在没有取消已有数据定义的前提下,可以使用的最大
的范围来给出的。你可以指定在一行中显示的元素的数目,元素的宽度。DUP 结构选项允许
你将相同的连续字节组合起来,Display Index 选项用于显示数组的索引。

例如,如果我们创建一个64 个元素的数组,每行有8 个元素,每个元素宽度为 4,不需要
使用dup 结构,带有索引注释,我们将得到下面这个数组形式

当IDA 无法根据选择的类型(本例中是字符类型)来显示时,它会使用红色来高亮这些字节。
也可以通过选择一个范围的方式,来生成一个合适大小的数组。

枚举类型
还记得在前面的C程序里定义的product_category_t类型码?我们可以在IDA中使用
Enumerations来定义它。首先,我们打开Enumerations窗口,创建一个枚举类型。

在这个枚举类型中,我们添加枚举数据。

 

在check_product()函数中,我们可以使用枚举类型来替换其中的部分操作数。在数值上使
用鼠标右键菜单,选择Symbolic constant:IDA 会列出与当前数值匹配的所有的枚举数值。

应用后,我们获得以下结果。

 

位域类型
现在我们来尝试定义一些在software_info_t 结构中定义的位域。从IDA 的角度,位域只是
一种特殊的枚举类型。我们在枚举类型创建对话框中选择位域的选项。

 

注意,在我们的C 程序中,有两种不同的位域类型。Platform 和os 位域包含在一个合并数
值的掩码中(通过使用或逻辑运算符号):一个产品能够应用在几个平台或操作系统中。另
一方面,category 位域包含一个代表一个类别的数字:同时,一个产品只能属于一个类别!
对 IDA,一个位域可以在一个特定的掩码中只包含一个数值。因此,为了表示 platform 和
category 位域,我们不得不为每个数值的每一位创建小位域,以允许他们组合。

现在,我们可以创建类别位域,使用掩码数值 0x3(2bits)。我们指定一个成员名字,一个
成员数值和一个位域掩码。我们也可以指定一个掩码名字:它不会被IDA 使用,只是一个帮
助记忆的注释。

当所有的位域都定义好后,我们可以获得如下定义

在operands 工具条中使用枚举成员命令,来应用这些位域定义到我们的软件数据中。

结构类型
我们的程序中包含许多结构。我们可以在IDA中应用结构定义,看看它是如何提高反汇编结
果的可读性。首先,我们打开结构窗口并创建一个新的结构类型。

 

我们定义结构成员与在反汇编的视图窗口中定义数据的方法是类似的。首先我们定义
software_t 结构体的第一个成员。按“D”直到我们获得一个 dd 类型,它表示该成员的数
值保存在一个双字里。我们指定它的格式为我们之前定义的software_info_t 枚举结构,并
通过Rename 命令。给它一个合适的名字,Info。

接着,我们使用ASCII 命令定义该结构体的第二个成员。在本例中,IDA 打开了一个对话框
询问我们字串的大小。

我们也可以从已经定义的数据中创建一个结构类型。例如,假设我们已经在一个代表
customer_t的结构的范围的数据做好了定义。我们可以使用IDA,通过选择合适的范围,并
使用“Create struct from data”命令来创建一个结构,。

一旦我们运行这个命令,IDA 创建了一个相应的结构,并打开结构窗口。为获得一个完美的
结构类型,我们按”A”键来修正name 成员的长度为32 字节(正如我们源码中定义的),同
时给这个结构一个更准确的名字。
对这些结构类型,我们该如何使用呢?IDA提供给我们两种方式:
u 应用结构类型来初始化数据
u 转换操作数为结构中的偏移量
我们将会在本教程的后面演示这两种方式

结构变量和结构数组
现在让我们定义一个包含John的客户信息的数据为一个customer_t结构。我们将鼠标指针放
在该数据结构体的第一个字节上,然后使用Struct var命令

这样我们得到了一个新的结构体变量。注意IDA 是如何使用注释显示结构体成员的名字的。

通过查看我们的源码,我们知道customers是一个包含四个成员的数组。我们前面已定义
Peter和John为 customer_t 结构体。现在取消对John结构的定义,然后在Peter结构上按
“*”键创建我们的customer数组,IDA会弹出一个数组设置对话框,它会自动检测出我们能
创建的最大的数组。

我们创建完这个数组,并给它一个合适的名字。

联合类型和结构中的结构
IDA 中定义联合体可以象定义标准结构体那样容易。
让我们来试着定义product_u  这个联合体吧。我们假定book_t 和software_t 这两个结构体已
经定义完成。对IDA 来说,联合体相当于是一种特殊的结构体。我们打开Structures 窗口,
运行Add struct type 命令,在对话框中我们选择创建Create union  选项。

我们可以使用IDA所有常规数据定义命令来创建联合体成员,我们定义一个book_t类型
的book成员,和一个software_t类型的software成员。

结构体中也也可以放置另一个结构体。事实上,我们在之前的创建联合体成员例子中就是这
样做的。记住:IDA 认为联合体只是一种特殊的结构体。
将你的鼠标放在一个成员的结构名字上,可以看到它相关的结构类型的定义。

 

可变大小的结构体类型
现在我们看一下softwares_t 这个结构体,结构体中softs 域长度没有被指定。为了在反
汇编中创建这样的结构,我们必须创建一种特殊类型的结构,我们称其为可变大小的结构。
这种结构的创建域普通结构基本一样:唯一的不同是结构体的最后一个成员应被定义为一个
有0 个元素的数组。

由于 IDA 无法计算出这种结构体的大小,我们需要通过选择一个区域,来指定我们期望的
结构体大小。

注意,IDA 是如何应用这些类型信息和如何以注释的方式来添加成员名称。

结构体偏移
现在我们已经知道如何定义我们需要的结构体和联合体。下面我们来看一下如何转换数据操
作数为结构体的偏移。
在print_customer()函数中,我们知道唯一的参数是一个指向cuttomer_t 的指针。EAX 寄
存器被初始化为这个指针:它指向一个customer_t 的结构。因此,我们推断出所有形式为
[EAX+…]的操作数实际均是在cutstomer_t 结构中的偏移。

为了定义每个操作数为一个结构体的偏移,我们使用鼠标右击这个操作数:IDA 会列出所有
可能的结构体偏移。

当我们把所有的数字偏移替换为我们结构体偏移后,汇编代码变得清晰多了。

另外一个例子是print_software()函数:EBX 寄存器被初始化为一个指向software_t 结构
体的指针。注意在整个函数中,EBX 寄存器都代表这个结构体。不用担心,IDA 可以使用一
个简单操作就能替换所有偏移:点击Operands 工具跳上的Offset (struct) 命令。

此时Structure offsets 窗口打开。我们在所有可能的寄存器列表中选择EBX 寄存器。对话
框左边树形视图显示了已在IDA 中定义的所有结构。右边的列表显示了EBX 相关的所有操作
数。如果我们在左边树形视图中选择了一个结构,IDA 将会格式化选择的操作数为结构中的
偏移量。名称前面的符号帮助我们确定是否所有的选择的操作数与选择的结构中的偏移匹
配。在本例中,software_t 结构似乎与所有的操作数匹配。

应用完成后,我们得到下面的结果:

联合体偏移
在Print_func()中使用EBX 寄存器指向了一个product_u 的联合体。在这个函数的结尾,
根据产品的种类,我们调用相应的函数来打印产品信息。
但此时结构偏移将会有一个不同的表示方法,如果它代表了Product_u 联合体中第一个成员
的偏移,或是这个联合体中的第二个成员的偏移。为了选择合适的成员,从Edit struct
菜单中使用select union member 命令。在这个对话框中,我们可以选择期望的联合体成
员。

结果如下:

结构体偏移对话框显示了如何选择一个联合体成员影响了偏移的表示方法。如果我们选择一
个区域并打开这个对话框,我们注意到结构体类型前面有个?号标记。

如果我们展开合适的树形分支,我们能够选择代表操作数偏移的联合体成员。一旦一个联合
体成员被中(本例中是software),IDA 使用一个绿色符号表示偏移与一个联合体成员记录匹
配。

最后,如上图所示,你可以使用在树形视图中的提示信息来查看结构类型的声明,。

 

地址偏移
IDA 可以在反汇编程序中将操作数定义为偏移。在下面的例子中,橘黄色表示存在一个可能
的有效参考。

使用Operands 工具栏上的Offset 按钮可以将这个操作数转换为一个偏移地址。

最终的反汇编结果
下面我们给出最终的完整反汇编结果,来结束这个教程:

; ------------------------------------------------------------- 
customer_t struc ; (sizeof=0x28) 
id dd ? 
name db 32 dup(?) ; string(C) 
sex dd ? ; char 
customer_t ends 
; ------------------------------------------------------------- 
softwares_t struc ; (sizeof=0x4, variable size) 
count dd ? 
softs software_t 0 dup(?) 
softwares_t ends 
; ------------------------------------------------------------- 
book_t struc ; (sizeof=0x80) 
title db 128 dup(?) ; string(C) 
book_t ends 
; ------------------------------------------------------------- 
software_t struc ; (sizeof=0x24) 
info dd ? ; enum software_info_t 
name db 32 dup(?) ; string(C) 
software_t ends 
; ------------------------------------------------------------- 
product_u union ; (sizeof=0x80) 
book book_t ? 
software software_t ? 
product_u ends 
; ------------------------------------------------------------- 
product_t struc ; (sizeof=0x88) 
id dd ? 
category dd ? ; enum product_category_t 
p product_u ? 
product_t ends 
; ------------------------------------------------------------- 
; enum product_category_t 
BOOK = 0 
SOFTWARE = 1 
HARDWARE = 2 
; ------------------------------------------------------------- 
; 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) 2005 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 
.686p 
.mmx 
.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] 
; ||||||||||||||| 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 
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 check_software+27j ... 
xor edx, edx 
mov dl, al 
mov eax, edx 
pop ebp 
retn 
check_software endp 
; --------------------------------------------------------------------------- 
align 4 
; ||||||||||||||| 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 
; ||||||||||||||| 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 
; ||||||||||||||| 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 
; ||||||||||||||| 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 ; "We don't sell hardware for the 
moment.."... 
lea eax, [ebx+software_t.name] 
push eax 
lea edx, (aSoftwareS - aWeDonTSellHardwareForThe)[esi] ; "We don't sell 
hardware for the moment.."... 
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] ; "We don't sell hardware 
for the moment.."... 
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] ; "We don't sell hardware 
for the moment.."... 
push ecx ; format 
call _printf 
pop ecx 
not_mac: ; "We don't sell hardware for the moment.."... 
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] ; "We don't sell 
hardware for the moment.."... 
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] ; "We don't sell hardware 
for the moment.."... 
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] ; "We don't sell hardware 
for the moment.."... 
push eax ; format 
call _printf 
pop ecx 
not_os_x: ; "We don't sell hardware for the moment.."... 
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: ; "We don't sell hardware for the moment.."... 
lea eax, (aDisassembly - aWeDonTSellHardwareForThe)[esi] 
push eax ; format 
call _printf 
pop ecx 
jmp short end 
; --------------------------------------------------------------------------- 
RECOVERY: ; "We don't sell hardware for the moment.."... 
lea edx, (aRecovery - aWeDonTSellHardwareForThe)[esi] 
push edx ; format 
call _printf 
pop ecx 
jmp short end 
; --------------------------------------------------------------------------- 
CRYPTOGRAPHY: ; "We don't sell hardware for the moment.."... 
lea ecx, (aCryptography - aWeDonTSellHardwareForThe)[esi] 
push ecx ; format 
call _printf 
pop ecx 
end: ; "We don't sell hardware for the moment.."... 
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 
; ||||||||||||||| 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 print_product+3Ej 
mov al, 1 
pop ebx 
pop ebp 
retn 
print_product endp 
; --------------------------------------------------------------------------- 
align 4 
; ||||||||||||||| 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] 
; 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] 
customers customer_t <1, 'Peter', 'm'> ; DATA XREF: main+11o 
customer_t <2, 'John', 'm'> 
customer_t <3, 'Mary', 'f'> 
customer_t <0> 
aIdaQuickstartG db 'IDA QuickStart Guide',0 ; DATA XREF: main+3Fo 
db 6Bh dup(0) 
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,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,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,0,0,0,0,0,0,0,0,0,0,0,0; softs.name 
aWeDonTSellHardwareForThe db 'We don',27h,'t sell hardware for the 
moment...',0Ah,0     ; DATA XREF: check_product+Eo print_software+8o ... 
aCustomer04xSC db 'CUSTOMER %04X: %s (%c)',0Ah,0 ; DATA XREF: print_customer+11o 
aBookS db 'BOOK: %s',0Ah,0 ; DATA XREF: print_book+6o 
aSoftwareS db 'SOFTWARE: %s:',0 ; DATA XREF: print_software+11r 
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:not_macr 
aWindows db ' WINDOWS',0   ; DATA XREF: print_software+5Cr 
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:not_os_xr 
aDisassembly db ' DISASSEMBLY',0 ; DATA XREF: print_software:DISASSEMBLYr 
aRecovery db ' RECOVERY',0 ; DATA XREF: print_software:RECOVERYr 
aCryptography db ' CRYPTOGRAPHY',0 ; DATA XREF: print_software:CRYPTOGRAPHYr 
asc_40A358 db 0Ah,0    ; DATA XREF: print_software:endr 
aProduct04x db 'PRODUCT %04X: ',0 ; DATA XREF: print_product+1Bo 
aCustomers db 'CUSTOMERS:',0Ah,0 ; DATA XREF: main+6o 
aProducts db 0Ah      ; DATA XREF: main+C0o 
db 'PRODUCTS:',0Ah,0 
aInvalidProduct db 'Invalid product !!!',0Ah,0 ; DATA XREF: main+E2o 
aInvalidSoftwar db 'Invalid software !!!',0Ah,0 ; DATA XREF: main+112o 
; [COLLAPSED AREA .data2. PRESS KEYPAD "+" TO EXPAND] 
; --------------------------------------------------------------------------- 
; [00001000 BYTES: COLLAPSED SEGMENT _tls. PRESS KEYPAD "+" TO EXPAND] 
; --------------------------------------------------------------------------- 
; [00001000 BYTES: COLLAPSED SEGMENT _rdata. PRESS KEYPAD "+" TO EXPAND] 
; --------------------------------------------------------------------------- 
; [000000C4 BYTES: COLLAPSED SEGMENT _idata. PRESS KEYPAD "+" TO EXPAND]


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值