この大会は2016/9/24 16:00(JST)~2016/9/25 16:00(JST)に開催されました。
今回もチームで参戦。結果は600点で536チーム中44位でした。
惜しくも自分が得点した問題は1問も無し。本当に悔しい!
CSAW CTF Qualification Round 2016 Writeup
この大会は2016/9/17 7:00(JST)~2016/9/19 7:00(JST)に開催されました。
今回もチームで参戦。結果は1301点で1274チーム中118位でした。
自分で解けた問題をWriteupとして書いておきます。
Coinslot (Misc 25)
提示された金額をできるだけ大きいコインで支払っていくようにする。
#!/usr/bin/env python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('misc.chal.csaw.io', 8000)) for i in range(10000): data = s.recv(256) print data if i == 0: sum = float(data.split('\n')[0][1:]) * 100 else: sum = float(data.split('\n')[1][1:]) * 100 sum = int(str(sum).split('.')[0]) b10000 = int(sum / 1000000) sum = sum % 1000000 ans = str(b10000) print ans s.sendall(ans + '\n') data = s.recv(256) print data b5000 = int(sum / 500000) sum = sum % 500000 ans = str(b5000) print ans s.sendall(ans + '\n') data = s.recv(256) print data b1000 = int(sum / 100000) sum = sum % 100000 ans = str(b1000) print ans s.sendall(ans + '\n') data = s.recv(256) print data b500 = int(sum / 50000) sum = sum % 50000 ans = str(b500) print ans s.sendall(ans + '\n') data = s.recv(256) print data b100 = int(sum / 10000) sum = sum % 10000 ans = str(b100) print ans s.sendall(ans + '\n') data = s.recv(256) print data b50 = int(sum / 5000) sum = sum % 5000 ans = str(b50) print ans s.sendall(ans + '\n') data = s.recv(256) print data b20 = int(sum / 2000) sum = sum % 2000 ans = str(b20) print ans s.sendall(ans + '\n') data = s.recv(256) print data b10 = int(sum / 1000) sum = sum % 1000 ans = str(b10) print ans s.sendall(ans + '\n') data = s.recv(256) print data b5 = int(sum / 500) sum = sum % 500 ans = str(b5) print ans s.sendall(ans + '\n') data = s.recv(256) print data b1 = int(sum / 100) sum = sum % 100 ans = str(b1) print ans s.sendall(ans + '\n') data = s.recv(256) print data c50 = int(sum / 50) sum = sum % 50 ans = str(c50) print ans s.sendall(ans + '\n') data = s.recv(256) print data c25 = int(sum / 25) sum = sum % 25 ans = str(c25) print ans s.sendall(ans + '\n') data = s.recv(256) print data c10 = int(sum / 10) sum = sum % 10 ans = str(c10) print ans s.sendall(ans + '\n') data = s.recv(256) print data c5 = int(sum / 5) sum = sum % 5 ans = str(c5) print ans s.sendall(ans + '\n') data = s.recv(256) print data c1 = int(sum / 1) sum = sum % 1 ans = str(c1) print ans s.sendall(ans + '\n') print 'Round %d' % (i + 1)
400ラウンドしたら、フラグが表示された。
flag{started-from-the-bottom-now-my-whole-team-fucking-here}
Notesy 2.0 (Crypto 1)
問題にフラグが書いてあった。
abcdefghijklmnopqrstuvwxyz
Sleeping Guard (Crypto 50)
ncで接続すると、Base64データらしき長いデータが返ってくる。このデータをdataファイルに保存する。
与えられたコードはKEYについてどんな処理をしているか書かれていないが、PNGファイルの先頭12バイトは決まっていることとKEYとXORをしているのではないかと予想してコードを書いてみる。
import base64 png_head = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d] with open('data', 'rb') as f: data = f.read() data = base64.b64decode(data) key = [] for i in range(12): key.append(png_head[i] ^ ord(data[i:i+1])) flag = '' for i in range(len(data)): code = ord(data[i:i+1]) ^ key[i % 12] flag += chr(code) with open('flag.png', 'wb') as f: f.write(flag)
実行すると、画像にフラグが書かれている。
flag{l4zy_H4CK3rs_d0nt_g3T_MAg1C_FlaG5}
Watchword (Forensics 250)
添付されていたmp4ファイルに対してforemostを使う。
$ foremost powpow.mp4 Processing: powpow.mp4 |*|
するとpngファイルが抽出できた。抽出したファイル名をoreo.pngに変える。
stepicのURLがヒントに出ていたので、stepicを使って画像を抽出する。
$ stepic -d -i oreo.png -o out.png
抽出したファイルはjpg形式のため、out.pngからout.jpgに変更する。
powpow.mp4のプロパティのタイトルにこう書いてある。
aHR0cDovL3N0ZWdoaWRlLnNvdXJjZWZvcmdlLm5ldC8=
Base64デコードすると、以下のURLになる。
http://steghide.sourceforge.net/
今度はsteghideを使う。パスフレーズはpassword。
$ steghide info out.jpg "out.jpg": format: jpeg capacity: 1.7 KB Try to get information about embedded data ? (y/n) y Enter passphrase: embedded file "base64.txt": size: 83.0 Byte encrypted: rijndael-128, cbc compressed: yes $ steghide extract -sf out.jpg
すると、base64.txtが抽出できた。
ここで第2のヒント「Python3のbase64モジュールを使う」という情報から、Base85で復号する。
>c:\python35\python Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:01:18) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import base64 >>> e = 'W^7?+dsk&3VRB_4W^-?2X=QYIEFgDfAYpQ4AZBT9VQg%9AZBu9Wh@|fWgua4Wgup0ZeeU}c_3kTVQXa}eE' >>> d = base64.b85decode(e) >>> d b'flag{We are fsociety, we are finally free, we are finally awake!}' >>>
flag{We are fsociety, we are finally free, we are finally awake!}
WhiteHat Contest 12 Writeup
この大会は2016/9/10 11:00(JST)~2016/9/11 11:00(JST)に開催されました。
今回もチームで参戦ですが、結果は100点で81チーム中62位でした。
自分で解けた問題1問だけ正解という結果でしたが、その1問をWriteupとして書いておきます。
Crypto002 (Cryptography 100)
8進数が並んでいるように見えるので、それをASCIIコードとして読み込む。
with open('cipher.txt', 'r') as f: codes = f.read() codes = codes.split(' ') data = '' for code in codes: data += chr(int(code, 8)) print data
その結果以下のようになった。Brainfuck言語かな...。
+++++ +++[- >++++ ++++< ]>+++ +++++ +++.+ ++.<+ ++[-> +++<] >+.<+ +++[- >---- <]>-- .++++ +++.. +++++ +.<++ +++[- >---- -<]>- ----- --.<+ +++[- >++++ <]>++ +++.+ +++++ +.--- ----- ..+++ ++++. <+++[ ->+++ <]>++ +.--- --.-- ----. -.+++ +.<++ +++[- >---- -<]>- ----. <++++ ++[-> +++++ +<]>. <++++ [->-- --<]> .<+++ [->++ +<]>+ +.<++ +[->- --<]> ----- ..<++ +[->+ ++<]> ++.<+ ++++[ ->--- --<]> -.<++ ++[-> ++++< ]>+++ .-.<+ +++[- >---- <]>-- -.<++ +++[- >++++ +<]>+ +++.- ----- -.<++ +[->+ ++<]> +++.< +++[- >---< ]>--- .<+++ +[->+ +++<] >.<++ ++++[ ->--- ---<] >-.<+ +++[- >++++ <]>.< +++[- >+++< ]>+++ ++.<+ ++++[ ->--- --<]> ----. <++++ [->++ ++<]> +++++ .+++. ----- .<+++ +[->- ---<] >---- -.--. <++++ ++[-> +++++ +<]>+ +.--- --.+. <++++ +[->- ----< ]>--- ----- -.<++ ++[-> ++++< ]>+++ ++++. .<+++ [->++ +<]>+ +++.< +++++ [->-- ---<] >---- ----- -.<++ ++++[ ->+++ +++<] >.<++ ++[-> ----< ]>.<+ ++[-> +++<] >+++. <++++ [->-- --<]> .-.++ +++.- ----. <++++ [->++ ++<]> .++++ .<+++ [->-- -<]>- ---.+ +++++ ++.-- ----- .<+++ [->++ +<]>+ ++.-- ----- --.-- -.<++ +[->+ ++<]> +++++ .<+++ +[->- ---<] >---. <++++ [->-- --<]> ---.< +++++ [->++ +++<] >++.< +++++ [->-- ---<] >--.< +++++ [->++ +++<] >+++. ++.-- ----. ++.-- --.++ +++++ ++.++ +++++ +.<++ ++++[ ->--- ---<] >---. <++++ +[->+ ++++< ]>+++ +++++ ++.-- ----- .++++ .<+++ ++[-> ----- <]>-- ----. <++++ [->++ ++<]> ++.<+ +++[- >---- <]>-- -.+.< ++++[ ->+++ +<]>+ +++++ +.<++ ++[-> ++++< ]>.<+ ++[-> ---<] >--.+ +++++ +.<++ +[->- --<]> ----- .-.<+ +++[- >---- <]>-- -.<++ +++[- >++++ +<]>+ +++++ .---- ---.< +++[- >+++< ]>+++ .<+++ [->-- -<]>- ----. <++++ [->-- --<]> ----- .<+++ +[->+ +++<] >++++ ++.-- ----. --.<+ ++[-> +++<] >++.< +++[- >---< ]>--. <+++[ ->+++ <]>++ .--.< +++[- >---< ]>--. <++++ [->++ ++<]> +++++ +++.< ++++[ ->--- -<]>- ----. <++++ [->-- --<]> --.<+ ++[-> +++<] >++.. .<
Brainfuckオンラインツール https://sange.fi/esoteric/brainfuck/impl/interp/i.htmlで実行してみると、次のテキストになる。
KNXFMMS2GNFFMYTNMQ3WGRDDO5HG4QJVJZ5ES6KNI42XST2IIV3WGSCBGBRVIQJVMJXE2M2NPJLHQY2UNR3E23JZOVHG4SLXJ5KECNCNLAYD2===
アルファベットが全部大文字なので、Base32かも...。
https://emn178.github.io/online-tools/base32_decode.htmlでBase32デコードすると、以下のようになった。
SnV2Z3JVbmd7cDcwNnA5NzIyMG5yOHEwcHA0cTA5bnM3MzVxcTlvMm9uNnIwOTA4MX0=
今度はBase64デコードする。
$ echo 'SnV2Z3JVbmd7cDcwNnA5NzIyMG5yOHEwcHA0cTA5bnM3MzVxcTlvMm9uNnIwOTA4MX0=' | base64 -d JuvgrUng{p706p97220nr8q0pp4q09ns735qq9o2on6r09081}
http://www.geocachingtoolbox.com/index.php?lang=en&page=caesarCipherでROT13の復号をするとフラグになった。
WhiteHat{c706c97220ae8d0cc4d09af735dd9b2ba6e09081}
Tokyo Westerns/MMA CTF 2nd 2016 Writeup
この大会は2016/9/3 9:00(JST)~2016/9/5 9:00(JST)に開催されました。
今回もチームで参戦。結果は560点で835チーム中94位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome!! (Misc, Warmup 10)
問題文にフラグが書いてある。
TWCTF{Welcome_To_TW_MMACTF!!}
Twin Primes (Crypto, Warmup 50)
RSA暗号で復号するのに必要な情報はn=p*qの場合の(p-1)*(q-1)とe。
与えられている情報はn1(=p*q)とeのペアと、n2(=(p+2)*(q+2))とeのペア。
それぞれ簡単にオイラー関数の値を計算できるので、n2の方で復号した後にn1の方で復号する。
with open('encrypted', 'r') as f: c = int(f.read().strip()) with open('key1', 'r') as f: n1 = int(f.readline().strip()) e1 = int(f.readline().strip()) with open('key2', 'r') as f: n2 = int(f.readline().strip()) e2 = int(f.readline().strip()) sum = (n2 - n1 -4) / 2 phi1 = n1 - sum + 1 phi2 = n1 + sum + 1 x = 0 while True: if (phi2 * x + 1) % e2 == 0: d = (phi2 * x + 1) / e2 break x = x + 1 m1 = pow(c, d, n2) x = 0 while True: if (phi1 * x + 1) % e1 == 0: d = (phi1 * x + 1) / e1 break x = x + 1 m = pow(m1, d, n1) flag = ('%x' % m).decode('hex').split('\0')[0] print flag
TWCTF{3102628d7059fa267365f8c37a0e56cf7e0797ef}
Super Express (Crypto 100)
encryptedが60桁の16進数。文字ごとにASCIIコードが計算されて、暗号化される。
暗号データが「805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9」なので、フラグは30文字。
またフラグはTWCTF{で始まり、}で終わる。
コードから逆の処理をしたり、ブルートフォースをするのが難しいため、わかる範囲から特徴を探す。
それぞれ暗号化の結果は以下のようになっている。[]内はASCIIコード。
T:[84]→0x80(=128) W:[87]→0x5e(=94) C:[67]→0xed(=237) F:[70]→0xcb(=203) {:[123]→0xbc(=188) }:[125]→0xf9(=249)
ASCIIコード順で2つ置きに217プラスして251で割って暗号化していそう。
([暗号コード] * 214 + 51) % 251で復号できるようだ。
crypt = '805eed80cbbccb94c36413275780ec94a857dfec8da8ca94a8c313a8ccf9' flag = '' for i in range(0, len(crypt), 2): code = int(crypt[i:i+2], 16) code = (code * 214 + 51) % 251 flag += chr(code) print flag
TWCTF{Faster_Than_Shinkansen!}
Hackcon 2016 Writeup
この大会は2016/8/19 23:30(JST)~2016/8/21 3:30(JST)に開催されました。
今回もチームで参戦。結果は1051点で689チーム中40位でした。
自分で解けた問題をWriteupとして書いておきます。
Welcome to the game (1)
freenodeの##hackconに入る。
13:28 *topic : Hackcon 2016 - hackcon.in. First flag is HACKCON{GLHF}. Pwnie binary changed!
HACKCON{GLHF}
In Rainbows (150)
StegSolveでいろいろ見る。
少し色が違う部分を浮き上がらせる。
++++++++[>++++>++++++>++++++++>++++++++++>++++ ++++++++<<<<<-]> >>>>++++++++++++++++++++.--------------- .<++++++++.>+++++++++++++++.<+++++++.----------.<+++.- -.>-------.++++++.+++++++++++.>--.<<<+++.+.>>+++++.----- .>---------.++++++++++.<<<.>>.+++.>-.<-.++++++++.>----.<--- .<<<++++++++++..>>>>---. [>]<[[-]<]
Brainfuck言語のようだ。
https://sange.fi/esoteric/brainfuck/impl/interp/i.html で実行してみると、フラグが表示された。
teXt_UCANT_r34d_is4_brainf**k
You Can't See Me (150)
apkを解凍し、classes.dexをjarに変換する。
>d2j-dex2jar.bat classes.dex dex2jar classes.dex -> .\classes-dex2jar.jar
JD-GUIでclasses-dex2jar.jarを開いて、ソースコードを見てみる。
package com.mayank13059.theoracle; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.TextView; public class MainActivity extends AppCompatActivity { private String genLoginForm1() { Integer localInteger = Integer.valueOf(656); return Integer.valueOf(686964656).toString() + "c" + Integer.valueOf(696).toString() + "b" + Integer.valueOf(656163).toString() + Integer.valueOf(68616).toString() + "d" + localInteger.toString() + "c" + localInteger.toString() + "f6e"; } private String genLoginForm2() { Integer localInteger = Integer.valueOf(696); return Integer.valueOf(6265).toString() + Integer.valueOf(66696).toString() + Integer.valueOf(57263656).toString() + "c" + localInteger.toString() + "b" + Integer.valueOf(65616).toString() + "c" + localInteger.toString() + "f6e"; } protected void onCreate(Bundle paramBundle) { super.onCreate(paramBundle); setContentView(2130968601); paramBundle = (TextView)findViewById(2131492970); TextView localTextView = (TextView)findViewById(2131492971); paramBundle.setText(genLoginForm1()); localTextView.setText(genLoginForm2()); setSupportActionBar((Toolbar)findViewById(2131492969)); } public boolean onCreateOptionsMenu(Menu paramMenu) { getMenuInflater().inflate(2131558400, paramMenu); return true; } public boolean onOptionsItemSelected(MenuItem paramMenuItem) { if (paramMenuItem.getItemId() == 2131492994) return true; return super.onOptionsItemSelected(paramMenuItem); } }
genLoginForm1()とgenLoginForm2()に注目する。
genLoginForm1(): 686964656c696b65616368616d656c656f6eを返す。 genLoginForm2(): 62656669657263656c696b65616c696f6eを返す。
それぞれhexデコードする。
686964656c696b65616368616d656c656f6e → hidelikeachameleon 62656669657263656c696b65616c696f6e → befiercelikealion
結合した文字列がフラグだった。
hidelikeachameleonbefiercelikealion
LabyREnth 2016 Writeup
この大会は2016/7/16 9:00(JST)~2016/8/15 9:00(JST)に開催されました。
個人戦の大会ですが、順位とか点数とかがよくわからない大会でした。
解けた問題をWriteupとして書いておきます。
unix tier level 1
perlのスクリプトで、スクリプトコードやデータがBase64エンコードされている。それぞれデコードするスクリプトを作成する。
key_begin = '. MIME::Base64::decode' key_begin_e = 'eval MIME::Base64::decode' key_end = '")' def decode(a, data): index = 0 while True: i_begin = data.find(key_begin, index) if i_begin < 0: break i_end = data.find(key_end, i_begin) enc = data[i_begin + 24:i_end] a += enc.decode('base64') index = i_end i_begin = data.find(key_begin_e) if i_begin < 0: return a, "" i_end = data.find(key_end, i_begin) e_data = data[i_begin + 27:i_end].decode('base64') return a, e_data with open('bowie.pl', 'r') as f: data = f.read() a = '' while True: a, e_data = decode(a, data) if e_data == "": break data = e_data with open('flag.gif', 'wb') as f: f.write(a) print data
実行すると、gifファイルが生成され、フラグが埋め込まれている。
PAN{L3ts_533_h0W_U_deal_w_th1s_little_511CE}
threat tier level 1
GETのアクセス先URLの文字列がフラグに関係ありそう。Base64文字列になっているので、いろいろ試してみる。
/[A].php?[B]&L4bry1nth_(数字)?[C]-<***>の形式。
[A]をBASE64デコードすると2桁数値
[C]+[B]をBASE64デコードするとよくわからないデータ。
ASCIIアートの一部かもしれない。
[A]のデコードした数値の順に[C]+[B]のデコードしたものを並べるスクリプトを書く。
from scapy.all import * import base64 import re pattern = 'GET /(.{4})\.php\?(.+)&L4bry1nth_.+\?(.+)-.+' packets = rdpcap('dopefish_labyrinth.pcap') d = {} for p in packets: if p['TCP'].dport == 80: l = p['Raw'].load m = re.match(pattern, l) p1 = m.group(1) p2 = m.group(2)[::-1] p3 = m.group(3)[::-1] id = base64.b64decode(p1).replace('\n', '') data = base64.b64decode(p3 + p2).replace('\n', '') d[id] = data for key, val in sorted(d.items()): print val
これを実行すると、魚のようなASCIIアートが出来上がる。
317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317.;317;;317;;317.W317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317;;317;;317;;317;W317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317;;317;;317;;317;;317;W317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317.W317WW317WW317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317;;317;;317;;317;;317.W317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317..317;;317.W317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317..317;;317;.317..317..317..317;;317..317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317.;317;.317.W317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317..317.;317;;317;;317P;317;;317;;317;;317;;317;;317;;317;;317;.317.W317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317;;317;.317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317.;317;;317;;317;;317;;317;A317;;317;;317;;317;;317;;317;;317;;317;;317;;317..317WW317WW317WW317WW317WW317WW317WW317WW317W.317;;317;;317..317WW317WW317WW 317WW317WW317WW317WW317WW317W;317;;317;;317;;317;;317;;317;;317;;317N;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317.W317WW317WW317WW317WW317WW317WW317W.317;;317;;317;.317.W317WW317WW 317WW317WW317WW317WW317W.317;;317;;317;;317;;317;;317;;317;;317;;317;{317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317.W317WW317WW317WW317WW317WW317W.317;;317;;317;;317..317WW317WW 317WW317WW317WW317W.317..317.;317;;317;;317;;317;;317;;317;;317;;317;;317t;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317WW317WW317WW317WW317WW317.;317;;317;;317;;317;.317.W317WW 317WW317WW317W.317WW317W.317.W317WW317WV317..317;;317;;317;;317;;317;;317;h317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;+317..317WW317WW317WW317W.317;;317;;317;;317;;317;.317.W317WW 317WW317W.317WW317WW317WW317WW317WW317WW317WW317WW317;;317;;317;;317;;317;;3173;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317.W317WW317W.317;;317;;317;;317;;317;;317;.317.W317WW 317WW317.V317W.317..317..317.W317WW317WW317WW317WW317.;317;;317;;317;;317;;317;D317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317..317.;317;;317;;317;;317;;317;;317..317WW317WW 317WW317.W317W.317..317..317.W317WW317WW317WW317WW317W.317;;317;;317;;317;;317;;3170;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317.W317WW317WW 317WW317..317WW317W.317..317..317WW317WW317WW317WW317V.317;;317;;317;;317..317.;317;p317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317..317WW317WW317WW317WW 317WW317.;317.W317.W317WW317WW317WW317WW317WW317WW317.;317;;317;;317;;317;.317.;317;;3173;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317WW317WW317WW317WW 317WW317..317.;317.V317W.317.W317WW317WW317WW317W.317;.317.;317;;317;;317;.317.;317;;317;f317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317..317WW317WW317WW 317WW317W.317..317..317.;317;;317..317..317..317;;317;;317;;317..317;;317;.317.;317;;317;;317s;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317.W317WW317WW 317WW317W.317WW317.V317V.317..317..317..317..317..317..317..317;;317;;317;.317.;317;;317;;317;h317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317..317WW317WW 317WW317W.317WW317.W317WW317WV317.;317;;317;;317;.317;.317..317.;317;;317..317.;317;;317;;317;;317l;317;;317;;317;;317;;317;;317;;317;;317;.317..317.;317;;317;;317;;317;;317;;317..317WW317WW 317WW317W.317WW317.W317WW317WV317..317..317;;317;;317;;317;.317.;317;;317..317;;317;;317;;317;;317;1317;;317;;317;;317;;317;;317;;317;.317.W317WW317W.317.;317;;317;;317;;317;;317..317WW317WW 317WW317W.317WW317.W317WW317WV317.;317;;317;;317;.317;;317;;317.;317;;317;;317;;317;;317;;317;;317;;317v;317;;317;;317..317;;317..317..317WW317WW317WW317..317;;317;;317;;317;;317..317WW317WW 317WW317W.317WW317.W317WW317WV317..317..317.;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;3317.;317;;317;.317..317.W317WW317WW317WW317WW317WW317.;317;;317;;317;.317.W317WW317WW 317WW317W.317WW317.W317WW317WV317.;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317s;317;.317..317..317WW317WW317WW317WW317WW317WW317.;317;;317;;317;.317.W317WW317WW 317WW317W.317..317.W317WW317WV317..317;;317;;317;;317;.317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317.}317..317..317WW317WW317WW317WW317WW317WW317WW317.;317;;317;;317..317WW317WW317WW 317WW317WW317WW317W.317..317WV317.W317W.317..317..317.+317;;317;;317;;317;;317;;317;;317;;317;;317;;317;;317;.317..317WW317WW317WW317WW317WW317WW317WW317W.317;;317;;317;;317.W317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317W.317.;317;;317;;317;;317;;317;;317;;317;;317;;317..317.W317WW317WW317WW317WW317WW317WW317WW317WW317W.317;;317;.317.W317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317..317;;317;;317;;317;;317;.317..317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317.;317;.317WW317WW317WW317WW317WW317WW 317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW317WW
このアスキーアートの中に斜めにフラグが入っている。
PAN{th3D0p3fshl1v3s}
docs tier level 1
デバッグしながら実行すると、以下のURLにGETでアクセスしていることがわかる。
http://10.1.33.7/b64/x58/MDgxOTE2MjMwZTMxMDIzMTNhNjk2YjA3NjgzNjM0MjE2YTJjMzA2ODJiNmIwNzBmMzA2ODA3MTMz\nNjY4MmYwNzJmMzA2YjJhNmI2YTM0Njg2ODMzMjU=/evil.exe
でも実際にアクセスしても接続することはできない。URLのパスをヒントにして、まず以下の部分を "\n" は改行に変え、Base64デコードする。
MDgxOTE2MjMwZTMxMDIzMTNhNjk2YjA3NjgzNjM0MjE2YTJjMzA2ODJiNmIwNzBmMzA2ODA3MTMz\nNjY4MmYwNzJmMzA2YjJhNmI2YTM0Njg2ODMzMjU= →081916230e3102313a696b07683634216a2c30682b6b070f3068071336682f072f306b2a6b6a3468683325
さらに0x58とXORをとり、ASCIIコードとして文字に変換する。
enc = '081916230e3102313a696b07683634216a2c30682b6b070f3068071336682f072f306b2a6b6a3468683325' key = 0x58 dec = '' for i in range(0, len(enc), 2): code = int(enc[i:i+2], 16) dec += chr(code ^ key) print dec
PAN{ViZib13_0nly2th0s3_Wh0_Kn0w_wh3r32l00k}
docs tier level 2
マクロを参照しようとしたが、パスワードがかかっている。https://home.ayra.ch/unlock/でパスワードを解除した後、マクロのUserForm1のコードを見る。
Private Sub button_Click() x = suchcrypto(key.Text, "General Vidal") If x = "171,184,42,184,88,26,47,154,20,219,203,130,52,19,180,214,156,94,186,74,30,248,119,235,139,130,175,141,179,197,8,204,252," Then MsgBox "Wow. Good Job! Such crack." Else MsgBox "U can do. Try harder..." End If End Sub Function suchcrypto(sMessage, strKey) Dim kLen, x, y, i, j, temp Dim s(256), k(256) kLen = Len(strKey) For i = 0 To 255 s(i) = i k(i) = Asc(Mid(strKey, (i Mod kLen) + 1, 1)) Next j = 0 For i = 0 To 255 j = (j + k(i) + s(i)) Mod 256 temp = s(i) s(i) = s(j) s(j) = temp Next x = 0 y = 0 For i = 1 To 3072 x = (x + 1) Mod 256 y = (y + s(x)) Mod 256 temp = s(x) s(x) = s(y) s(y) = temp Next For i = 1 To Len(sMessage) x = (x + 1) Mod 256 y = (y + s(x)) Mod 256 temp = s(x) s(x) = s(y) s(y) = temp suchcrypto = suchcrypto & (s((s(x) + s(y)) Mod 256) Xor Asc(Mid(sMessage, i, 1))) & "," Next End Function Private Sub UserForm_Click() End Sub
途中までそのまま計算し、計算結果とIf文のチェックの内容とをXORで元に戻していく。
strKey = 'General Vidal' strCode = '171,184,42,184,88,26,47,154,20,219,203,130,52,19,180,214,156,94,186,74,30,248,119,235,139,130,175,141,179,197,8,204,252,' kLen = len(strKey) s = [] k = [] for i in range(256): s.append(i) pos = i % kLen k.append(ord(strKey[pos:pos+1])) j = 0 for i in range(256): j = (j + k[i] + s[i]) % 256 s[i], s[j] = s[j], s[i] x = 0 y = 0 for i in range(1, 3073): x = (x + 1) % 256 y = (y + s[x]) % 256 s[x], s[y] = s[y], s[x] codes = strCode[:-1].split(',') sMessage = '' for i in range(1, len(codes) + 1): x = (x + 1) % 256 y = (y + s[x]) % 256 s[x], s[y] = s[y], s[x] pos = (s[x] + s[y]) % 256 sMessage += chr(s[pos] ^ int(codes[i - 1])) print sMessage
PAN{L4$t_Night_@f@iry_Vizited_M3}
docs tier level 3
PDF Stream Dumperで見ようとしても見ることができない。どうやら壊れているようだ。https://www.pdf-online.com/osa/repair.aspx で修復し、修復したファイルをPDF Stream Dumperで見る。赤で表示されている「10 HLen: 0x189」のところを見ると、フラグが入っていた。
<< /JS ty.i.f.(.e.v.e.n.t...v.a.l.u.e.=.=.".P.A.N.{.g.0.o.b.y.g.o.0.b.y.d.0.0.w.h.3.r.3.r.u.?.}.".).{.a.p.p...a.l.e.r.t.(.".y.e.s.".).;.}.e.l.s.e.{.a.p.p...a.l.e.r.t.(.".n.o.".).;.}. /S /JavaScript /Type /Action >>
PAN{g0obygo0byd00wh3r3ru?}