软件安全逆向——汇编语言
汇编语言
可理解
堆结构
堆块
堆块是堆的基本组织单位,包括块首和块身;一般位于整个堆区的开始位置,用于索引堆区中所有堆块的重要信息;堆块共分为占有态(系统管理)和空闲态(程序员管理),对于空闲态堆块而言,块首会额外存储两个4字节指针:Flink(前向)指针和Blink(后向)指针。
当我们使用函数申请的地址指针/句柄,会指向堆块块身的首地址(直接越过8字节的块首);堆块的大小包括块首,当申请16字节时,实际会分配24字节(自动加首部);堆块的单位是8字节,因此不足会按8字节进行分配。
堆表
在windouws系统中占有态的堆块被使用程序索引,空闲态的对快被堆表索引;其中最重要的堆表有:空闲双向链表(空表,freelist)和快速单向链表(快表,lookaside,加速堆块分配);空表包含空表索引(也叫空表表头,大小为128的数组(free[]),数组的每一项包含两个指针用于标识一条空表)和空闲链块两部分。
空表索引的free[1]用于白哦是堆中所有大小为8字节的空闲堆块,之后每个索引项指引的空闲堆块递增8字节。free[0]用于存放≥1024B而小于512KB的堆块并升序排列;因此在分配时会先从free[0]中反向查找,满足时再正向搜索最小能满足要求的空闲堆块。
堆块的释放和分配操作可能引发堆块合并,即当堆管理系统发现两个空闲堆块相临时会进行堆块合并操作。
寄存器
中央处理器CPU的组成部分,因CPU的运算速度远远高于内存的读写速度,为避免被拖慢,CPU会自带一级缓存和二级缓存;对于读写频繁的数据都会存档在寄存器中,CPU优先读取寄存器,再由寄存器跟内存交换数据。32位CPU指的就是寄存器的大小。
变址寄存器(通用寄存器ESI【源地址指针】,EDI【目的地址指针】 指针寄存器EBP,ESP)用于栈操作中存放操作数和计算操作数的有效地址,不可分割为8位寄存器。
[!CAUTION]
CPU使用寄存器读数据比从一/二级缓存里更快
需掌握
内存区域
- 代码区:存储被装入执行的二进制机器代码,可执行文件包含的二进制机器代码将被加载到内存的代码区,由处理器依次取出送去ALU执行;
- 静态数据区:存放程序运行的全局变量、静态变量等;
- 堆区:用于动态分配进程内存;需要使用专有函数进行申请,其大小受限于计算机的虚拟内存;
1 | /*C使用malloc/calloc作为堆分配关键字,int**意为强制类型转换*/ |
栈区:动态存储函数之间的调用关系;向低地址扩展的数据结构,采取FILO的访存方式,主要存储函数运行时的局部变量、数组等。
[!TIP]
在栈区中,变量a先入栈,变量b后入栈,则变量a所在内存地址比变量b高
对代码块
int *p1 = new int[200];char *p2 = new char[30];我们可以分析得到,其所申请的内存将分配到堆区,而p1和p2的值的大小无法确定(堆分配不是栈那样的顺序地址)
堆区和栈区的区别(4个区别)
在申请方式上,栈由程序自动分配,而堆需要程序员自己申请(如C语言的malloc函数);
在申请效率上,栈由于自动分配,速率较快,不产生内存碎片,而堆因手动分配速度较慢,可能产生内存碎皮;
在释放方式上,栈在作用域结束后自动释放而堆需要作用域结束前手动释放,否则会造成内存泄露;
在使用场合上,若需要的内存很少且运行前可知需多少内存时,使用栈,否则使用堆。
1 | /*区分*/ |
数据寄存器
32位CPU有4个32位通用寄存器EAX、EBX、ECX和EDX。对其低16位的存取不会影响到高16位的数据。这些低16位寄存器分别命名为AX、BX、CX和DX与先前CPU中的寄存器相一致;
4个16位寄存器又可分割为8个独立的八位寄存器,每个寄存器有自己的名称,可独立存取
AX:AH-AL BX:BH-BL CX:CH-CL DX:DH-DL
EAX(累加器):使用频率高,用于算术运算和输入/输出操作,还常用于存储函数返回值;
EBX(基地址寄存器):作为内存指针使用,用于访存;
ECX(计数寄存器):用于控制循环次数和;在移位操作时,用CL来指明移位的位数;
EDX(数据寄存器):进行乘除运算时作为默认数参与运算,也用于存放I/O设备端口。
函数栈帧(!important)
ESP和EBP之间的内存空间为当前栈帧,EBP标识了当前栈帧的底部,ESP标识当前栈帧的顶部;对于当前正在运行的函数栈帧总是在栈顶
指令指针寄存器
IP,永远指向当前等待执行的指令;EIP用于存储下次将要执行的指令在代码段的偏移量。
标志寄存器(EFlags)
在32位操作系统中大小为32位,可存32个标志。
- ZF(零标志):运算结果为0,置1;
- OF(溢出):按照无符号数计算加减法再转为有符号数,若超出有符号数表示范围(-128
127,即1000000001111111)或运算结果错误,置1; - CF(进位):运算结果最高位产生进位/借位,置1;
- SF(符号标志):运算结果最高位为1,置1。
| EXAMPLE(8bit) | |
|---|---|
| 01111111+00000001=10000000(运算结果错误,本该为128,但是现在显示的-128) | ZF=0 OF=1 CF=0 SF=1 |
| 00000000-10000000=10000000 (0-(-128)=128,超出范围) | ZF=0 OF=1 CF=1 SF=1 |
| 10000000-01111111=00000001 | ZF=0 OF=1 CF=0 SF=0 |
| 11111111+00000001=00000000 | ZF=1 OF=0 CF=1 SF=0 |
x64架构CPU寄存器
寄存器均扩展至64位,名称的第一个字母E改为R,增加了8个64位通用寄存器R8-R15,也可使用其低位寄存器R8D(32位),R8W(16位),R8B(8位)。
第二章 结
