反汇编教程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

◆高级语言特性的识别
§ 浮点处理
浮点数的处理与整数不一样,它是由
FPU完成的。float用4个字节表示,double 则用8个。常用的浮点指令:
fld 压栈
fst弹栈
fcom 比较
fadd 加法
fdiv除法
fmul 乘法
fsub 减法
◆高级语言特性的识别
§ 浮点处理
浮点处理时,先把操作数压到浮点堆栈中,比 如:
◆高级语言特性的识别
§ 参数的传递规范
2、Pascal规范 函数参数由左往右压入堆栈,由被调用的函数负责清
栈。如: int __pascal swap(int a, int b); push a push b call swap
在swap内部: 由 retn 8 来清理堆栈。
注:在VC++中已不再支持,用相似的WINAPI来代替,也就 是说普通代码是不能编出Pascal调用类型。
var_4 = dword ptr -4
在用的时候:
mov [esp + var_4], 5555
5555
生长方向
-8 -4 0 4 8 c
◆高级语言特性的识别
§ 结构体
如果定义一个局部变量的结构体实例:
struct person{ int a;
Var_8
int b; };
Var_4
Void test(void){
retn 4 可以轻松的看出ecx 是一个结构体(或类)的指针,并
访问了它的偏移为0、4的两个成员。 看一个例子: struct.idb
◆高级语言特性的识别
§ 类 (this指针)
类的成员变量和结构类似,但是它在调 用成员函数的时候会准备this指针的传递。
在VC++、Intel C++和一些我们还不知道 的编译器中,this指针是通过寄存器ecx传 递的。而在gcc中,是通过堆栈传递的,最后 一个被压入堆栈的,在函数内部会表现为 arg_0。
关于这部分请参见: \\bzli\study\软件保护中的反向工程-地位分析与制度比较.pdf
◆反汇编简介
§ 说说软件破解
反汇编与软件破解的联系非常紧密。软 件破解离不开反汇编,但是还包括其它相 关技术:脱壳、解密技术等,所以反汇编 只是这些技术的一个必要的基础。
◆反汇编工具
§ 静态反汇编工具
对程序进行静态分析,把机器码转换成汇编的 工具,常见有:C32ASM、W32Dasm、IDA pro 等;
静态பைடு நூலகம்接:crt0.c 动态链接:crtexe.c 控制台 : wincmdln.c
◆高级语言特性的识别
§ 启动函数
一般WinMain的最后一个入栈的参数是 HINSTANCE hInstance,而这个实例句柄是由
GetModuleHandle取得的,所以,一般在 call edi ; GetModuleHandleA之后调用的就是
反汇编技术
软件四部 Kenny.zhang 2006-09-25
内容提要
§ 反汇编简介 § 反汇编工具—IDA pro的简单使用 § 高级语言(C++)特性的识别 § 编译器优化
◆反汇编简介
§ 反向工程
反向工程就是把软件的机器代码退回到源代码;
§ 反向编译
反编译包括了反汇编过程,并将得到的汇编代码进 行分析、进而反向编译成源代码;
§ 反汇编
反汇编其实就是利用程序的机器代码与反汇编器 反向解释出代码。
◆反汇编简介
§ 反汇编的用处:
1、更深层了解编译器特性,写出性能更高的程 序;
2、可以找到程序局部性能瓶颈; 3、当调试程度时出现用户断点,可以帮助你查 找bug; 4、不用说了吧……. 注:在很多软件的许可协议中可以看到这一条: “您不得对本“软件产品”进行反向工程(reverse engineer)、反向编译(decompile)或反汇编 (disassemble)……”
◆高级语言特性的识别
§ 结构体
当函数参数是结构体指针的时候:
int testp(struct person *per){
return per->a + per->b; }
对它的成员的访问是:基地址+偏移的方式,
mov ecx, [esp + arg_0]
mov eax, [ecx] add eax, [ecx + 4]
◆高级语言特性的识别
§ 类 (虚函数)
class parent { public:
int a;
virtual void demo(void); ……..
};
指向demo
vtal
vtal
a
demo
◆高级语言特性的识别
§ 类 (虚函数)
在构造函数里面,会将虚函数表的地址 移入到对象实例的开头部分。
mov dword ptr [eax], offset off_40810C 调用:
float a = 5.89 + 8.90; 在汇编中:
call dword ptr [eax]
例子:virtual.idb
◆高级语言特性的识别
§ 类 (纯虚函数)
抽象类是不允许创建对象的,那它是怎 么禁止的呢?
如果用抽象类实例化一个对象,那么这 个对象的虚函数表将是一个指向__purecall 的指针,在程序执行时调用到它的话,由 它给用户警告。
例:purecall.idb
WinMain。 类似,控制台程序的main函数则是在
call ds: GetCommandLineA 后面不远处。
◆高级语言特性的识别
§ 局部变量
局部变量一般是放在堆栈中 的。例如:
int swap(int a, int b){
int temp; ……….
Var_4
} 它当中的temp在编译后是在函数的开头:
◆高级语言特性的识别
§ 参数的传递规范
3、标准规范(__stdcall) 是__cdecl与__pascal的混和物。函数
参数由右往左压入堆栈,而由被调函数负 责清栈。它在函数名前加“_”,以及加一个 后缀“@”,后面紧跟参数的字节数目。
◆高级语言特性的识别
§ 参数的传递规范
如: int __pascal swap(int a, int b);
§ 类 (成员函数)
调用成员函数之前都会先准备this指针, 一般可以通过这个识别出是否是一个类的 成员函数:
lea ecx, [ebp+var_14] call sub_4010B0 可以得出var_14是一个类对象,sub_4010B0是 它的一个成员函数。
◆高级语言特性的识别
§ 类 (成员函数)
§ 调试工具
对可执行文件进行动态跟踪、调试,常见的 有:SoftICE、IDA pro等;
§ 十六进制编辑工具
对二进制可执行文件进行修改操作,常见的有 WinHex、HIEW等。
◆反汇编工具
§ IDA pro的特点
1、反汇编、调试; 2、支持众多处理器的文件格式(近百种); 3、智能识别库函数和局部变量; 4、智能分析函数调用关系; 5、程序浏览智能感知; ……… 装上它吧…..
§ 堆栈
堆栈是一段数据结
构,提供先进后出的
访问方式。主要用来
52
传递函数参数、保存
现场和保存局部变量
等。
例:
mov eax, [esp – 4]
eax的内容就是52
生长方向
-8 -4 0 4 8 c
◆高级语言特性的识别
§ 函数参数的传递
函数的参数传递有堆栈方式、寄存器方 式和同时利用堆栈和寄存器。
◆高级语言特性的识别
§ 类 (delete操作符)
delete与大多函数差不多,所以识别要困 难一点。但是它有一个显著特性:
它最终会调用到XXXFree一类的函数;
例:class2.idb
◆高级语言特性的识别
§ 类 (构造函数)
构造函数总是分配内存成功的情况下才会被调 用,一般紧跟在调用构造函数后是分配失败的跳转 代码,将this指针复0。 cmp [ebp+var_1C], 0 jz short loc_401042 mov ecx, [ebp+var_1C] call sub_4010A0 ; 构造函数 mov [ebp+var_28], eax
§ 参数的传递规范
1、__cdecl规范 按照参数的声明顺序从右往左向堆栈
中压入堆栈。但清栈是由调用函数来完成 的。编译器会函数名称前加一个“_”。
◆高级语言特性的识别
§ 参数的传递规范
如: int __cdecl swap(int a, int b) 那么它是类似这样传递的: push b push a call _swap add esp, 8 ;清栈
◆高级语言特性的识别
§ 类 (this指针)
1、VC++、Intel C++ lea ecx, [ebp+var_14] call sub_4010B0
2、GNU cc push dword ptr [esi+0BF4h] call Mark__17ScriptObjectTable
◆高级语言特性的识别
众所周知,在成员函数内部访问成员变 量,那在成员函数怎么访问的呢?当然是 通过this指针,传递this指针的作用当然不 是为了访问成员函数,除了虚函数,所有 的成员函数被编译之后都是全局函数。所 以传递this指针的作用就是为了访问成员变 量。
◆高级语言特性的识别
§ 类 (成员函数)
在成员函数内部:
mov eax, [ecx]
;将第一个成员赋给eax
add eax, [ecx+4]
;再用第一个成员的值加上
;可能是第二个成员的值
看一个例子:class.idb
◆高级语言特性的识别
§ 类 (new操作符)
编译器将new与delete转换成普通函 数。new有以下特点:
1、只有一个参数(要分配的字节数); 2、返回值会赋给this指针; 3、会判断返回值是否为空;
struct person r; ……..
}
在汇编中的函数开头:
var_8 = dword ptr -8
var_4 = dword ptr -4
生长方向
-8 -4 0 4 8 c
◆高级语言特性的识别
§ 结构体
当在函数参数传入的是一个结构体的自动变量 时,会把它的每一个成员单独传递: struct person r; test(r); 会用类似如下语句传递: push r.a push r.b call _test …… 所以在确定函数参数个数的时候,不能仅凭push 的个数来确定,还要结合上下文。
jmp short loc_401049 loc_401042: mov [ebp+var_28], 0
◆高级语言特性的识别
§ 类 (析构函数)
析构函数也总是在在内存分配成功的情 况下才会被调用,而且析构函数与delete操 作都被封装在一个“外壳”中.
看一个例子class2.idb
◆高级语言特性的识别
◆高级语言特性的识别
§ 返回值
对Intel C++ 、Visual C++、GCC而言: 1、如果是地址或整数就放在eax中; 2、如果字节类型就放在al中; 3、如果是浮点类型,放在浮点堆栈的
栈顶; …….
一个简单的例子 function.idb
◆高级语言特性的识别
§ 启动函数
在链接的时候,由你选择的应用程序类 型与CRT\SRC\crt***.c文件进行链接,由它 当中的代码来调用main 或者WinMain函 数。
push b push a call _swap@8 在swap内部: 由 retn 8 来清理堆栈。
◆高级语言特性的识别
§ 参数的传递规范
还有其它的一些规范:__fastcall、 __thiscall等。刚才所说的函数命只存在在 OBJ(.o)、LIB(.a)和DLL(.so)中,在最终可 执行文件中是不存在的 (在gcc中可以通过 编译选项在最终二进制文件中保留符号)。 而且这个名字和编译器密切相关。
§ 类 (构造函数与析构函数)
如果是处在堆栈中的自动变量的构造函 数,那么就只能猜了~~~
◆高级语言特性的识别
§ 类 (虚函数)
虚函数是C++的重要特性。它根据你的 具体对象的类型而去调用相应的函数。也 就是说这个函数必须和对象紧紧联系在一 起。在编译器上是用虚函数表来实现的。
虚函数表是象一个数组一样,将每个虚 函数的地址放在表中,而这个虚函数表的 地址又被放置在对象的偏移为0的地方(只针 对VC++、Inter C++; Gcc放置的位置不 定。)
Windows版
◆反汇编工具
Linux版
◆反汇编工具
◆高级语言特性的识别
§ 主流C++编译器
Intel C++ 、 Visual C++ 、GNU CC/++、 Borland C++……
§ C++各种特性
结构体、虚函数、继承关系、成员函数、this 指针、共用体(联合)….
◆高级语言特性的识别
相关文档
最新文档