编程语言
1、机器语言,电脑CPU可直接解读,与运行平台密切相关,通用性很差,早期计算机利用卡带记录01便是如此;
2、汇编语言,是一种用于可编程器件的低级语言。在不同的设备中,汇编语言对应着不同的机器语言指令集, 运行时按照设备对应的机器码指令进行转换,所以可移植性也较差;
3、高级语言。
编译、链接和PE文件
编译是指编译器将源代码进行词法和语法的分析,将高级语言指令转换为汇编代码。
1、预处理。正式编译前,根据已放置在文件中的预处理指令来修改源文件的内容,包含宏定义指令,条件编译指令,头文件包含指令,特殊符号替换等。
2、编译、优化。编译程序通过词法分析和语法分析,将其翻译成等价的中间代码表示或汇编代码。
3、目标代码生成。将上面生成的汇编代码译成目标机器指令的过程。目标文件中所存放着与源程序等效的目标的机器语言代码。
链接是指将有关的目标文件彼此相连接生成可加载、可执行的目标文件,其核心工作是符号表解析和重定位。链接按照工作模式分静态和动态链接两类。
静态链接:链接器将函数的代码从其所在地(目标文件或静态链接库中)拷贝到最终的可执行程序中,整个过程在程序生成时完成。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码,静态链接则是把相关代码拷贝到源码相关位置处参与程序的生成。
动态链接:动态链接库在编译链接时只提供符号表和其他少量信息用于保证所有符号引用都有定义,保证编译顺利通过。程序执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间,根据可执行程序中记录的信息找到相应的函数地址并调用执行
经过编译链接后,程序生成,windows程序以PE文件形式存储。
PE文件全称Portable Executable,意为可移植可执行文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件。 PE文件以段的形式存储代码和相关资源数据,其中数据段和代码段是必不可少的两个段。
在应用程序中最常出现的段有以下6种:
1、执行代码段,.text命名;
2、数据段,.data、.rdata 命名;
3、资源段,.rsrc命名;
4、导出表,.edata命名;
5、导入表,.idata命名;
6、调试信息段,.debug命名。
系统并非在硬盘上直接运行程序,而是将其装载进内存里,包括其中的代码段、数据段等。
程序运行时,由“装载器”将硬盘上的数据复制到内存,装载器根据程序的PE头中的各种信息,进行堆栈的申请和代码数据的映射装载,在完成所有的初始化工作后,程序从入口点地址进入,开始执行代码段的第一条指令。
逆向原理
“逆向”,顾名思义,将编译链接好的程序反过来恢复成“代码级别”。
C\C++程序在经过编译链接后,程序为机器码,直接可供CPU使用,对于这类程序我们使用IDA、OD等逆向程序,只能将其恢复成汇编代码状态,然后通过读汇编代码来解读程序的运行过程机制,当然,一些逆向工具提供的插件可以将一些函数恢复成伪代码级别。
至此,我们把程序恢复成了可读代码,依靠阅读这些代码来梳理程序运行过程,这叫做“静态调试”。
与此对应的“动态调试”则是让程序运行起来,更加直观的观察程序的运行过程。在动态调试中,断点起着很大的作用,使程序能够暂停下来以观察各寄存器状态。
常用工具
静态分析工具
(1)IDA Pro(Interactive Disassembler Professional )
IDA Pro是总部位于比利时列日市(Liège)的Hex-Rayd公司的一款产品。IDA 的主要目标之一,在于呈现尽可能接近源代码的代码,而且通过派生的变量和函数名称来尽其所能地注释生成的反汇编代码,适用于三大主流操作 系统:Microsoft Windows.Mac OS X 和 Linux。IDA Pro提供了许多强大功能,例如函数的交叉引用查看、函数执行流程图及伪代码等,并且也有一定的动态调试功能。同时,IDA pro可以在windows、linux、ios下进行二进制程序的动态调试和动态附加,支持查看程序运行内存空间,设置内存断点和硬件断点。
(2)c32asm
c32asm 是款非常好用的反汇编程序,具有反汇编模式和十六进制编辑模式,能跟踪exe文件的断点,也可直接修改软件内部代码 ,提供输入表、输出表、参考字符、跳转、调用、PE文件分析结果等显示 ,提供汇编语句逐字节分析功能,有助于分析花指令等干扰代码。
(3)Win32Dasm
Win32dasm可以将应用程序静态反编译为WIN 32汇编代码,利用Win32dasm我们可以对程序进行静态分析,帮助快速找到程序的破解突破口。笔者下载的 Win32Dasm还可以附加到正在运行的进程,对进程进行动态调试,但如果原程序经过了加密变换处理或着是被EXE压缩工具压缩过,那么用Win32dasm对程序进行反汇编就没有任何意义了。
(4)VB Decompiler pro
VB Decompiler pro是一个用来反编译VB编写的程序的工具。VB Decompiler反编译成功后,能够修改VB窗体的属性,查看函数过程等 ,VB Decompiler Pro 能反编译Visual Basic 5.0/6.0的p-code形式的EXE, DLL 或 OCX文件。对native code形式的EXE, DLL或OCX文件,VB Decompiler Pro 也能给出反编译线索。
动态分析工具
(1)Ollydbg
Ollydbg运行在windows平台上,是 Ring 3级调试器,可以对程序进行动态调试和附加调试,支持对线程的调试同时还支持插件扩展功能, 它会分析函数过程、循环语句、选择语句、表[tables]、常量、代码中的字符串、欺骗性指令、API调用、函数中参数的数目,import表等等 ;支持调试标准动态链接库(Dlls),目前已知 OllyDbg 可以识别 2300 多个 C 和 Windows API 中的常用函数及其使用的参数,是 Ring3级功能最强大的一款动态调试工具。
(2)Windbg
Windbg是Microsoft公司免费调试器调试集合中的GUI的调试器,支持Source和Assembly两种模式的调试。Windbg不仅可以调试应用程序,还可以 对内核进行调试。结合Microsoft的Symbol Server,可以获取系统符号文件,便于应用程序和内核的调试。Windbg支持的平台包括X86、IA64、AMD64。Windbg 安装空间小,具有图形操作界面,但其最强大的地方是有丰富的调试指令。
辅助工具
系统监视工具:
Wireshark (免费软件,网络监视和包分析类软件)
Outpost Firewall (共享软件,使用hook技术的Windows防火墙)
ProcExp (免费软件,强大的进程分析软件)
FileMon (免费软件,强大的文件读写监视软件)
RegMon (免费软件,强大的注册表读写监视软件)
反保护工具:
LordPE (Win32 PE文件修改,转存工具)
ImportREC (Win32 PE文件结构修复软件)
AIl versions ASPack unpacker (免费软件,ASPack压缩壳脱壳工具)
UnPECompact(免费软件,PECompact压缩壳脱壳工具)
UPX(自由软件,UPX压缩壳加壳和脱壳工具)
其它:
Hedit (共享软件,16进制编辑器)
PEiD (免费较件,软件信息和编写语言分析工具)
crackme
crackme(通常简称CM)是用来测试程序设计人员的逆向工程技能的小程序。
KeygenMe、ReverseMe、UnpackMe,KeygenMe是要求别人做出程序对应的 keygen (序号产生器)。
ReverseMe 要求别人把它的算法做出逆向分析。
UnpackMe 是则是要求别人把它成功脱壳 。
一些汇编知识
CPU大体上可以分为3个部分:
1.算术逻辑部件ALU(arithmetic logic unit)用来进行算术和逻辑运算。这部分与我们的关系不太大,我们没必要管它。
2.控制逻辑。同样与我们的关系不大。
3.工作寄存器,它在计算机中起着重要的作用,每一个寄存器相当于运算器中的一个存储单元,但它的存取速度远远快于存储器。它用来存放计算过程中所需要的或所得到的各种信息,包括操作数地址、操作数及运算的中间结果等。
我们常说的32位,就是说寄存器是32位的。
通用寄存器一共八个,分别是EAX、EBX、ECX、EDX、ESP、EBP、EDI、ESI。
其中,EAX—EDX这四个寄存器又可称为数据寄存器,除了直接访问外,还可分别对其高十六位和低十六位进行访问。它们的低十六位就是把它们前边儿的E去掉,即EAX的低十六位就是AX。而且它们的低十六位又可以分别进行八位访问,也就是说,AX还可以再进行分解,即AX还可分为AH(高八位)AL(低八位)。
这四个寄存器,主要就是用来暂时存放计算过程中所用的操作数、结果或其它信息。
而ESP、EBP、EDI、ESI这四个寄存器的主要用途就是在存储器寻址时,提供偏移地址,可以称为指针或变址寄存器。
1. 通用寄存器:
AX (单字=16位) = AH + AL -> 其中’+’号并不代表把它们代数相加。AH和AL寄存器是相互独立的,只不过都是AX寄存器的一部分,所以你改变AH或AL (或者都改变) ,AX寄存器也会被改变。
-> 'accumulator'(累加器): 用于进行数学运算
BX -> 'base'(基址寄存器): 用来连接栈(之后会说明)
CX -> 'counter'(计数器):
DX -> 'data'(数据寄存器): 大多数情况下用来存放数据
DI -> 'destination index'(目的变址寄存器): 例. 将一个字符串拷贝到DI
SI -> 'source index'(源变址寄存器): 例. 将一个字符串从SI拷贝
o2. 索引寄存器(指针寄存器):
BP -> 'base pointer'(基址指针寄存器): 表示栈区域的基地址
SP -> 'stack pointer'(栈指针寄存器): 表示栈区域的栈顶地址
o3. 段寄存器:
CS -> 'code segment'(代码段寄存器): 用于存放应用程序代码所在段的段基址
DS -> 'data segment'(数据段寄存器): 用于存放数据段的段基址
ES -> 'extra segment'(附加段寄存器): 用于存放程序使用的附加数据段的基地址
SS -> 'stack segment'(栈段寄存器): 用于存放栈段的段基址
o4. 指令指针寄存器:
IP -> 'instruction pointer'(指令指针寄存器): 指向下一个指令
API所用的数据,均是靠堆栈来传送的,即先将要传送的数据压入堆栈,然后CALL至API函数,API函数会在函数体内用出栈指令将相应的数据出栈。然后进行操作。