目录
一、汇编数据存储宽度
1. 常见的数据存储宽度
2. 数据存储宽度在汇编中的应用
3. 数据存储宽度的意义
二、汇编中的内存地址与边界对齐
1. 内存地址
示例:
2. 数据对齐
3. 数据对齐在汇编中的体现
正确对齐
错误对齐
汇编代码示例
三、汇编中的数据宽度截断
1. 数据截断的影响
示例:
2. 数据宽度截断在赋值和运算中的体现
汇编代码:
数据截断溢出示例:
四、技术扩展
1. 结构体内存对齐
示例:
2. 溢出和截断攻击
示例:
3. 操作系统中的对齐机制
在逆向工程和汇编语言中,对内存地址、数据存储宽度及边界对齐的理解是分析程序行为、修复漏洞和优化代码的基础。
数据存储宽度是指在内存中存储数据时占用的字节范围。不同的存储宽度适合存放不同的数据类型。
在 x86/x64 汇编中,存储宽度通常可以是以下几种:
数据类型 | 宽度(字节) | 宽度(位) | 数据范围 | 汇编定义 |
---|---|---|---|---|
字节(Byte) | 1 | 8 | 0 ~ 255 或 -128 ~ 127 | BYTE |
字(Word) | 2 | 16 | 0 ~ 65535 或 -32768 ~ 32767 | WORD |
双字(DWord) | 4 | 32 | 0 ~ 2³²-1 或 -2³¹ ~ 2³¹-1 | DWORD |
四字(QWord) | 8 | 64 | 0 ~ 2⁶⁴-1 或 -2⁶³ ~ 2⁶³-1 | QWORD |
1 字节 (1 byte) = 8 位 (8 bit),存储宽度直接决定了计算机能够处理的数据大小和精度。
存储宽度在汇编中通常决定了寄存器、指令和数据类型的选择:
寄存器与数据存储宽度的关系:
AL/AH
(8 位),AX
(16 位),EAX
(32 位),RAX
(64 位)。数据指令的宽度:
不同的指令操作不同的数据宽度:
mov al, 0xFF ; 1 字节数据 (8-bit)
mov ax, 0xFFFF ; 2 字节数据 (16-bit)
mov eax, 0xFFFFFFFF; 4 字节数据 (32-bit)
mov rax, 0xFFFFFFFFFFFFFFFF; 8 字节数据 (64-bit)
计算机内存储存数据时,会将数据映射到地址空间的特定位置,而程序的性能与数据的存储方式密切相关。
每个内存地址对应 1 字节
的存储单元。数据的存储位置由其起始地址决定,而数据的存储宽度影响其占据的字节范围。
若数据 WORD
(2字节)存储在地址 0x1000
,其实际范围为 0x1000
~ 0x1001
。
1 字节对齐
:无需对齐。2 字节对齐
:地址可被 2 整除。4 字节对齐
:地址可被 4 整除。8 字节对齐
:地址可被 8 整除。若一个 DWORD
(4字节)从对齐地址开始存储,如 0x1000
:
地址 0x1000 | 0x1001 | 0x1002 | 0x1003
数据 XXXX
若 DWORD
从非对齐地址 0x1001
开始存储:
地址 0x1000 | 0x1001 | 0x1002 | 0x1003 | 0x1004
数据 XXXX
正确对齐方式:
section .data
align 4 ; 强制 4字节对齐
mydata dd 0x12345678
数据截断(Truncation)是指将宽度较大的数据缩小为占用更少的存储空间。
DWORD
转换为 WORD
或 BYTE
。mov eax, 0x12345678 ; 将 0x12345678 装载到 eax 中 (32位寄存器)
mov ax, eax ; 仅保留低 16 位 0x5678,截断高位
截断结果为仅保留 0x5678
,高位 0x1234
被丢弃。
mov rax, 0xFFFFFFFF12345678 ; 64位寄存器
mov eax, rax ; 截断为低 32 位,结果为 0x12345678
mov al, rax ; 截断为低 8 位,结果为 0x78
mov ah, 0xFF ; AH = 高8位,值为 255 (0xFF)
add al, 2 ; AL = 低8位,加上2溢出
; AL 的结果可能导致不可预料的错误
C/C++ 中常见问题,影响结构体大小与性能。
struct Example {
char a; // 1 字节
int b; // 4 字节
};
a
后填充3字节)。应用:优化对齐,提高内存访问效率。
在逆向工程中的常见场景。攻击者通过数据截断/溢出导致程序行为异常。
int value = 0x100; // 256
char buffer[8];
snprintf(buffer, value, "Test Overflow");
// 多余的字节可能覆盖函数返回地址
应用:
// Windows内存分配对齐
void* pAligned = _aligned_malloc(16, 8); // 16 字节分配,8 字节对齐
_aligned_free(pAligned);