はじめに
この記事は、SECCON 2015 Online CTFの問題集が公開されているので
、後追いで、勉強がてら調べながらやってみた記録になります。
SECCONという楽しそうなものがあるらしいというのを丁度2015年の年末に知った、ただの謎解き好きの挑戦記録のため、超初心者目線です。
近い将来リアルタイムで参加できるようになるために、環境を整えたりわからない事を調べたりまとめたりしながら進めております。
- ネタバレなので閲覧の際はご注意ください。
- 問題集(解答付き)はこちら
- タイトルに■がついているものは、後追いでは出来ない問題です。
- □になっているものは、気合いと根性の別解で何とか解けた/解けそう
- タイトルに▲がついているものは、コンテスト当日の環境が閉じられているものの、
build
という環境再現用のソースがセットで公開されている問題です- △になっているものは、
build
の中身から環境構築成功、解けた/解けそう - 環境構築のためにソースを読んでると、うっかりフラグが見えてしまうので注意
- △になっているものは、
- やりながら、便利ツール・解読ツールを作ったら下記にupしていきます。
- 他にも実際にリアルタイムで参加された方のwrite-upや、後追いでやってみた本格的な記事もあるので探してみてください。
SECCON online CTF とは
- SecCon CTF 日本公式ページ
- Security Contest Capture the flagの略
- 問題が出されて、その中からflagを探す競技だそうです
- ちなみに2015年からリンクがないですが、下記の要領で増えていくようです
- 2014年: http://2014.seccon.jp/
- 2015年: http://2015.seccon.jp/
- SECCONとは
「SECCON(SECurity CONtest)」とは、情報セキュリティをテーマに多様な競技を開催する情報セキュリティコンテストイベントです。実践的情報セキュリティ人材の発掘・ 育成、技術の実践の場の提供を目的として設立されました。「SECCON」 の競技には、攻撃・防御両者の視点を含むセキュリティの総合力を試すハッキングコンテスト「CTF (Capture the Flag)」や、あるテーマにあわせてプログラムを作成して披露するプログラミングコンテスト「ハッカソン」などがあります。
基本装備(環境,初期装備)
- ほぼ未チューニングのMacBookAir(OS X 10.9くらい) 2011モデル
- ruby 2.0.0
- ちょっと古い。。。途中から2.3.0に上げました
- python 2.7.5
- GIMP 2.8.10
Excercise
- はじめに、とおわりに
50_Start SECCON CTF
まずは順当にこれからやってみる
question.txt
ex1 Cipher:PXFR}QIVTMSZCNDKUWAGJB{LHYEO Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ{} ex2 Cipher:EV}ZZD{DWZRA}FFDNFGQO Plain: {HELLOWORLDSECCONCTF} quiz Cipher:A}FFDNEVPFSGV}KZPN}GO Plain: ?????????????????????
ヒント
- 一文字ずつ特定の文字に一意に変換される換字式暗号(Substitution cipher)になっています
- ex1とex2で導いた変換式をそのままquizに適用すればOK
プログラム例
- まず上記を探り当てるのがめんどくさいですよね。なので、換字式暗号か判定して解読までするコードを書きました。
- Githubリポジトリの
substitution-cipher.rb
- リンクは階層替えの可能性があるので、ファイル名検索して探してください
50_Last Challenge (Thank you for playing)
最後らしいけどいけそうなので、すぐやってみる
question.txt
ex1 Cipher:PXFR}QIVTMSZCNDKUWAGJB{LHYEO Plain: ABCDEFGHIJKLMNOPQRSTUVWXYZ{} ex2 Cipher:EV}ZZD{DWZRA}FFDNFGQO Plain: {HELLOWORLDSECCONCTF} quiz Cipher:A}FFDNEA}}HDJN}LGH}PWO Plain: ??????????????????????
ヒント・解法
- みたまんま、
50_Start SECCON CTF
と同じ 50_Start SECCON CTF
で作成したツールで解読可能
Crypto
暗号関連。そういわれると心躍る。
100_Unzip the file
unzipするだけならいけるかも、割と早めに手を付けてみる
結局途中で攻撃手法を検索し、ハッキングツールに助けてもらう
一応これも立派な解法?
question.txt
Unzip the file unzip
これと、いかにもなunzip
という拡張子無しの22kbのファイルが置いてある
初心者の野生の勘による足跡
- まずは素直に
$ unzip unzip Archive: unzip [unzip] backnumber08.txt password:
passwordが必要らしい!中身にbacknumber08.txt
がいるらしい
backnumber...?
- 素直に
unzip
と入れてみる => やっぱだめでした - 間違えると、中に何のファイルが入っているか教えてくれる(こんな感じ)
skipping: backnumber08.txt incorrect password skipping: backnumber09.txt incorrect password skipping: flag incorrect password
ほほーん。上の二つをヒントにflagを解読するパターンかしら。と推測してみる。
unzip -v unzip
でより詳細な内容を表示Archive: unzip Length Method Size Ratio Date Time CRC-32 Name
14182 Defl:N 5288 63% 11-30-15 16:23 30b7a083 backnumber08.txt 12064 Defl:N 4839 60% 11-30-15 16:22 b93d9a46 backnumber09.txt 22560 Defl:N 11021 51% 12-01-15 15:21 fcd63eb6 flag
48806 21148 57% 3 files
上記二つのファイルの平文がないかということで探してみる。後追いでてやっているので、2015年のwrite-upが沢山引っかかりそうな予感。なるべく今年の記事は避けながら検索。(案の定2015年のwrite-upが沢山ひっかかる)
seccon online backnumber
で検索の結果、下記が引っかかる- SECCON メールマガジン
- 2014年から始まったらしい
- backunmberのVol.08とVol.09のリンクをたどると、
backnumberxx.txt
形式の静的ファイルなので当たりっぽい!DLしてzipしてみる。
$ zip backnumber08.zip backnumber08.txt $ unzip -v backunmber08.zip
Length Method Size Ratio Date Time CRC-32 Name
-------- ------ ------- ----- ---- ---- ------ ----
14182 Defl:N 5288 63% 12-31-15 18:35 30b7a083 backnumber08.txt
-------- ------- --- -------
14182 5288 63% 1 file
- ぴたりと一致。よしよし。
backnumber09.txt
も同じようにzipして確認。一致。
で?ということで自力はここまで。
ヒント
検索した結果、このパターンは既知平文攻撃というらしい。
既知平文攻撃でよく使われるのはPkCrackというツールらしい。
pkcrackのsrcを上記サイトからDLし、make。pkcrack
でコマンド実行できる状態にし、気を取り直して続き。macの人はmakeが一筋縄でいかないらしいので、検索してそのとおりにやるのを推奨。
ちなみに、pkcrackの使い方
-C [暗号化されたzipファイル] -c [暗号化されたzipファイルの中で平文がわかるファイル] -P [平文のファイルが入っている暗号化されていないzip] -p [平文のファイル] -d [出力先(復号したzipファイルの名前)]
解法・解答
$ pkcrack -C unzip -c backnumber08.txt -c backnumber09.txt -P backnumber08.zip -P backnumber09.zip -p backnumber08.txt -p backnumber09.txt -d unzip_output
- unzip_outputになんか出た。
unzip unzip_putput
するとめでたくbacknumber08.txt
,backnumber09.txt
,flag
救出。 - flagをエディタで開くと、テキスト形式じゃないっぽい
- ※ここから力技
$ less flag
- 無理矢理呼んでみると、
word/***
とword
配下のなにかを参照しにいっている箇所が散見。doc
形式と推測してwordで開いてみる。(300_Decrypt itで知ったfileコマンドを使えば、一発で形式がわかったっぽい) - あれ、真っ白。。。と思ったら白文字で書いてあった。ちゃんちゃん。
- ちなみにこれ、解答が間違っていて、正しくは
SECCON{1s_th1s_passw0rd_ weak?}
△ 200_Find the prime numbers
素数を見つけろ!
question.txt
$ cp pq.cgi /var/www/pq.cgi.txt http://pailler.quals.seccon.jp/pq.cgi.txt http://pailler.quals.seccon.jp/cgi-bin/pq.cgi
あと、build
フォルダ
$ ls -l build/ total 32 -rw-r--r-- 1 Kusuwada staff 104 12 30 12:59 access.json -rw-r--r-- 1 Kusuwada staff 84 12 30 12:59 data.json -rw-r--r-- 1 Kusuwada staff 960 12 30 12:59 log.txt -rwxr-xr-x 1 Kusuwada staff 1821 12 30 12:59 p.cgi
足跡
- とりあえずquestionにあったリンクに飛んでみるが、アクセスできません。quiestionの1行目のコマンドも、もともと
pq.cgi
なんてものはないし、p.cgi
の書き間違いかな? prime number
って素数の事らしい。お恥ずかしながら今知りました。- urlにある、
pailler
ってなんか意味あるのかと思って調べてみた。- Paillier暗号:Wikipedia
Paillier暗号とはPascal Paillierが1999年に提案した公開鍵暗号方式で、m_1の暗号文とm_2の暗号文からm_1+m_2の暗号文を計算出来る(加法準同型性)という性質を満たす
- 暗号の名前らしい!数式がずらーーーーっと並んでおる
- Paillier暗号:Wikipedia
- 大会当時の気持ちになってみる。question.txtの2行目のリンクにアクセスすると、
pq.cgi.txt
がゲットできたのではなかろうか
build
の環境を構築してみる
- といっても、cgiを実行するだけ
pq.cgi
を実行してみる
$ python pq.cgi
あら、エラー。どうやら環境変数にREMOTE_ADDR
というのがご所望らしい
これはサーバ側がアクセスしてきた人を判別するのに使っていたようだ
$ export REMOTE_ADDR=localhost $ python pq.cgi <html> <body> <pre> 6083209677006732801 + 1852956351578481830 = 1928955616563352856 </pre> </body> </html>
お、っぽいのが返ってきた。
解いてみよう
pq.cgi
を読んでみる- 明らかにflagを出力してそうなあたり
z = "QUERY_STRING" if z in os.environ and os.environ[z] != "": if w[e]["time"] < t and os.environ[z] == v["num"]: print "SECCON{" + v["flag"] + "}" w[e]["time"] = t + 60 w[e]["outp"] = q else: w[e]["time"] = t + 3 w[e]["outp"] = q
- 環境変数の
QUERY_STRING
がv["num"]
と合っていれば、フラグを出力してくれるらしい w
はaccess.json
で、ここにアクセス元別の情報time
,outp
が記録される- どうやら不正解だった場合は3秒後、正解だった場合は60秒後じゃないと答えを出してくれないらしい
- サーバが立っているときは、リクエストのクエリにキーを詰めて投げると推測
- サーバがリクエストを受け取ってどう捌いていたかは与えられた情報から読み取れなかったので、今回はキーが求まったら環境変数
QUERY_STRING
に直接入れる事にする - という事で、求めるべきは
v["num"]
のようだ。実行時に必ず返ってくる%019d + %019d = %019d
の生成に使用されている
下記の箇所のpq.cgi
コード(コメント入り)と出力結果から、v["num"]
を求める
a = int(v["p"]) # a = 定数 b = int(v["q"]) # b = 定数 n = (a * b) # n = 定数 (a * b) l = (a - 1) * (b - 1) # l = 定数 ((a - 1) * (b - 1)) r = l # r = ((a - 1) * (b - 1)) : 初期値 d = 1 # d = 1 : 初期値 while 1: d = ((n // r + 1) * d) % n # d = ((n // r + 1) * d) % n r = (d * l) % n # r = (d * l) % n if r == 1: break while 1: x = pow(random.randint(1000000000, 9999999999), n, (n * n)) # x = ((10桁のランダム整数)のn乗) % (n * n) o = (pow(n + 1, 1, n * n) * x) % (n * n) # o = ((n + 1) % (n * n) * x) % (n * n) y = (((pow(o, l, n * n) - 1) // n) * d) % n # y = (((oのl乗) % (n * n) - 1) // n) * d) % n if y == 1: break c = (pow(n + 1, int(v["num"]), n * n) * x) % (n * n) h = (c * o) % (n * n) q = "%019d + %019d = %019d" % (c, o, h) print q
まず
h = (c * o) % (n * n)
から、
(c * o) / (n * n) = k...h
(c * o) - h = (n * n) * k
n
は固定なので、いくつかpq.cgi
の結果を見ていれば出てきそう- こちらのサイト:ぴよぴよ.pyから素因数分解のpythonコードを拝借
- 3回程度、
$ python pq.cgi
の出力結果を元に(c * o) - h
を素因数分解してみる - 素因数分解結果
1.[3, 11, 11, 42727, 42727, 58757, 58757, 103093, 6682443329L] 2.[2, 2, 5, 13, 17, 41, 61, 42727, 42727, 58757, 58757, 7413421597L] 3.[137, 1657, 42727, 42727, 58757, 58757, 12434869587941L]
n = 42727 * 58757
が求まった!- 幸い、素数同士の掛け合わせだったので、a,bは{4227, 58757}の組み合わせである事も判明
行き詰まり、そしてPaillierについて学ぶ
- ここまではすんなり来たのだが、ここからが難航。
- 先に紹介したPaillier暗号:Wikipediaの記事を読み込むと、今回の問題と同じ暗号方式であったので、ここの復号の数式をプログラムに落としてみることにした。
とは言っても、皆さんの力を借りた寄せ集めな感じではある。
# 最小公倍数を求める def gcd(a, b): while b: a, b = b, a % b return a def lcm(a, b): return a * b // gcd (a, b) # 合同式の逆元を求める def egcd(a, b): (x, lastx) = (0, 1) (y, lasty) = (1, 0) while b != 0: q = a // b (a, b) = (b, a % b) (x, lastx) = (lastx - q * x, x) (y, lasty) = (lasty - q * y, y) return (lastx, lasty, a) def modinv(a, m): (inv, q, gcd_val) = egcd(a, m) return inv % m # 復号用 def L(u, n): return (u - 1) / n # main処理 c = 548241137083630932 # pq.cgiの出力例 a = 42727 b = 58757 n = 42727 * 58757 lbd = lcm(a - 1, b - 1) g = n + 1 x = L(pow(g, lbd, n * n), n) mi = int(modinv(x, n)) m = L(pow(c, lbd, n * n), n) * pow(mi, 1, n) v = m % n print v
出力されたv
を環境変数に入れてpq.cgi
実行
$ export QUERY_STRING={v} $ python pq.cgi
無事判定を通り抜けてフラグが出力されました。長かった。。。
参考サイト
- https://en.wikipedia.org/wiki/Paillier_cryptosystem:Wikipedia(english)
- コードに落とす際はこっちのほうがわかりやすかった
- ぴよぴよ.py
- taichino.com
- 今回初めて知った「合同式の逆元」のコードを拝借
300_Decrypt it
なんてシンプルなタイトル。
question.txt
$ ./cryptooo SECCON{*************************} Encrypted(44): waUqjjDGnYxVyvUOLN8HquEO0J5Dqkh/zr/3KXJCEnw= what's the key? cryptooo.zip
と、cryptooo.zip
というzipっぽいファイル。
初心者の野生の勘による足跡
- まずは素直に解凍してみる
$ unzip cryptooo.zip Archive: cryptooo.zip creating: cryptooo/ inflating: cryptooo/cryptooo inflating: cryptooo/readme.txt
cryptooo
という怪しげなexecファイルと、下記内容のreadme.txtが出てきた。
$ ./cryptooo SECCON{ } Encrypted(44): waUqjjDGnYxVyvUOLN8HquEO0J5Dqkh/zr/3KXJCEnw= what's the key?
- とりあえずreadmeの通りにやってみる
$ ./cryptooo SECCON{ } -bash: ./cryptooo: cannot execute binary file
- あれ、なんかこの環境で実行出来ないみたい。ググる。
file
コマンドなるものを知る。【 file 】 ファイル・タイプを判定する fileは,実行可能ファイルかテキストかその他データかなどの,ファイルのタイプを判定して表示する。
これ、今後もすごくお世話になりそう。 * ということで、ファイルタイプを判別してもらう。
$ file cryptooo cryptooo: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for_GNU/Linux 2.6.24, stripped
GNU/Linuxということなので、MacOSでは実行できない形式のようだ。またググる。 まさにこれだった。MAC OS X & UNIX
Mac OS X は、Mach-O (Mach Object) というバイナリーフォーマットを採用している。ELF ではなく、ELF とも互換はありません。
その後しばらく調べるも、MacOS上でELF形式のバイナリを開発する方法はいくつか見つかったが、実行する方は見つからず。ということで、ここからMacOSのVMで動かしているUbuntu14.04上でお送りします。
ヒント・解法
- readmeの通りにやってみる
$ ./cryptooo SECCON{************************} Encrypted(44): waUqjjDGneViOT9RNQCQaOU6J+PVuI7FYsBFmBL/URg=
お、既に出だしが問題文の文言と似ているぞ。どうやらEncryptするツールらしい。
$ ./cryptooo SECCON{ Encrypted(12): waUqjjDGnQ==
ふむふむ。なんか流れが読めてきたぞ。このコメコメの部分に入れるの(の一部)が、問題文のwhat's the key?のkey
で、出力が問題文のwaUqjjDGnYxVyvUOLN8HquEO0J5Dqkh/zr/3KXJCEnw=
と一致すれば良いのだな。
$ ./cryptooo SECCON{ Encrypted(12): waUqjjDGnQ== # waUqjjDGnまで確定 $ ./cryptooo SECCON{a Encrypted(12): waUqjjDGna4= # waUqjjDGnaまで確定 $ ./cryptooo SECCON{aa Encrypted(12): waUqjjDGna79 # waUqjjDGna79まで確定, (12)の終わりなので2つ確定か $ ./cryptooo SECCON{aaa Encrypted(16): waUqjjDGna79ug== # waUqjjDGna79uまで確定 $ ./cryptooo SECCON{aaaa Encrypted(16): waUqjjDGna79ukM= # waUqjjDGna79ukまで確定
- 最初の試行で桁数が揃っていそうなので{}の中は25文字かな。
- key全体のうち、わかっている`SECCON{'の部分までの出力は一致しているので、前から暗号化してるっぽい。25文字程度なら、総当たりで前から攻めていってよさそう。
- 出力の
(**)
部分が3つおきに変わり、4の倍数。
出力の雰囲気からbase64でエンコードされているような気配がしたが、そのままデコードできなかったのでまぁいいや。 - 上記を考慮して下記のようなスクリプトを作成。
candidates
にkeyの候補文字を入れているが、記号はカバーしきれているか若干不安。
# coding: utf-8 candidate = (0..9).to_a + ('a'..'z').to_a + ('A'..'Z').to_a candidate += ['!','#','%','-','_','=','+','*',':','{','}'] answer = 'waUqjjDGnYxVyvUOLN8HquEO0J5Dqkh/zr/3KXJCEnw=' key = 'SECCON{' can_indexes = [] find = false num = 0 index = 0 while num < 25 do mod = (key.length + 1).modulo(3) div = (key.length + 1).div(3) len = (div) * 4 + mod len = (div + 1) * 4 if num == 24 find = false index.upto(candidate.length - 1) do |i| c = candidate[i] key_can = "#{key}#{c}" encrypted = `./cryptooo #{key_can}` if encrypted.split(':')[1][1,len] == answer[0,len] key = key + c.to_s puts "match!! key =#{key}" can_indexes.push(i) num += 1 index = 0 find = true break end end if find == false index = can_indexes.pop + 1 key = key[0..-2] num -= 1 end end puts "key = #{key}"
特化したスクリプトなので、とくに整形してないです。。
答えにたどり着けたようなので結果オーライ。
△ 400_Please give me MD5 collision files
MD5関連らしい
question.txt
http://md5.quals.seccon.jp/MD5_treivvwcxTx2/
build
の中
$ ls -l build/ total 216 -rwxr-xr-x 1 Kusuwada staff 6589 12 30 12:59 cg.cgi drwxr-xr-x 3 Kusuwada staff 102 12 30 12:59 db -rw-r--r-- 1 Kusuwada staff 6384 12 30 12:59 index.html -rw-r--r-- 1 Kusuwada staff 84320 12 30 12:59 jquery-2.1.3.min.js -rw-r--r-- 1 Kusuwada staff 4309 12 30 12:59 pysqldb.py drwxr-xr-x 3 Kusuwada staff 102 12 30 12:59 uploadfiles
足跡
- タイトルから、MD5で衝突が起こるfileをquestionのサイトにアップロードするようだ。
- やっぱりquestionのリンクは応答無しだったので、とりあえずbuildの中にある
index.html
を開いてみる - サイト内のhelpにこんな説明が
- Your team can upload different 2 files of same MD5.
- After your team uploads your files, you will not be allowed to upload again for 1 hour.
- All files will be ranked by its code size.
- The Team which 1st files uploads, gain 500 points, when the CTF finished.
- どうやら、md5で衝突が起こるファイルセットを作成し、アップロード。制限時間内に一番サイズの大きいファイルを上げたチームに500point入る仕組みらしい。flag集めじゃなくてこんな問題もあるのね。
解法(md5で衝突の起きるファイルの作成方法)
- 先人の知恵を借りる
- MD5 Collision Demo
- ここのevilize-0.2をDLし、手順通りに実行してみる。手順が明記されていてすばらしい。
- 数時間かかるそうだが、何かが生まれるらしい
- 大会中の答え合わせ環境に上げないと、一番大きいファイルかは分からないが、衝突ファイルを作るだけなら後追いで問題無し。ちなみに競技時間内で、という場合は、このツールを試す前に過去の事例を(同ページに記載あり)試しに上げてみると思う。
Stegano
あこがれのステガノグラフィ。名前だけはよく聞くものの、実物を見る(解く)のは始めて。
100_SECCON WARS 2015
あーもーあれでしょ。はやりの。宇宙的なやつ。
question.txt
https://youtu.be/8SFsln4VyEk
こんだけ。他に情報無し。
初心者の野生の勘による足跡
- とりあえずquestionのリンクへ飛んでみる
- スター○ォーズのオープニングチックな、SECCONの説明らしきもの(日本語)が流れてきた
- 一生懸命読んでいると、時々字がちらちらする。
ヒント・解法
- 特定の部分だけ、電光掲示板の電球が切れた所みたいに字が欠けて表示されている。どうやら映像にQRコードが隠されていそうだ。
- 動画中のスナップショットをとりまくって(10枚くらい)gimpで静止画を重ね合わせ
Colors > color to alphaで黒を指定すると、文字(黄色)の部分だけ合成できるので便利
携帯のQRコード読み取りアプリが認識するようになるまで重ね合わせていって、読み取ったらそこにフラグがいらっしゃいました。
100_Steganography 1
1から順にやっていくことに。
question.txt
Find image files in the file MrFusion.gpjb Please input flag like this format-->SECCON{*** ** **** ****}
と、MrFusion.gpjb
というよくわからん形式のファイル。
初心者の野生の勘による足跡
- 今回覚えた
file
コマンドで、MrFusion.gpjbが何者か調べてみる
$ file MrFusion.gpjb MrFusion.gpjb: GIF image data, version 89a, 1280 x 720
おう!GIFなのか。
- gif形式にして開いてみる
SECCON{
という文字が書いてある。意味深。でもそんだけ。続きがうっすら書いてあるんじゃないかなー?とおもって画像の明度や色のカーブを変えたりしてみたけど、それはなさそう。 - んー、8.4Mって超重くない?そういえば、問題文にfind image filesって書いてあるくない?
- ということで、複数imageが連結されているのではと予想してみる。
- ファイル分析して分割してくれるようなツールないかなーということでググる。
- foremostというのがお手軽そう。macでも使えそう。
- latestをDLして解凍、makeしてみる。
bash $ sudo make mac $ sudo make macinstall
- READMEに
man foremost
でmanualが出ると書いてあるが、出ず。仕方ないので見つかったLinux用manualを見ながらやってみることに。
- latestをDLして解凍、makeしてみる。
ヒント・解法
- MrFusion.gpjbを分解してもらう
$ foremost -i MrFusion.gpjb
- outputフォルダに、gif, jpg, pngが出てきた。わーい!
- 出てきた画像ファイルたちを組み合わせると、それっぽいのが出来たのだが、
SECCON{*** ** **** ****}
のフォーマットにするにはまだ文字が足りない。。。foremostの力だけでは取り出せなかったimageがあるようです。 - 先ほどの出力のoutputにaudit.txtというログ的なものが出力されていて、どのoffsetにどのサイズのファイルを発見したか確認できます。それを元に、先頭から出てきていないファイルを捜索してみる。
- 見た感じ、余白なく詰まっているようなので、最初に間が空いている箇所のoffsetを指定してbinaryを分割してみます。
$ split -b 26632 MrFusion.gpjb split_
二つに分かれるかと思いきや、指定したバイトずつに分割されるんでした。だーっとsplit_**ファイルが生成されたので、先頭のだけ名前を変えて後半を統合、ファイルタイプ確認
$ mv split_aa split1 $ cat split_* > split2 $ file split2 split2: PC bitmap, Windows 3.x format, 1280 x 720 x 24
おお、ビンゴ!この調子でいけそうだ。とりあえずbmpの取り出しに成功、同じようにして他の画像データも取り出し。bmpはサイズがわからないので、その直後のファイルはforemostで拾えた体で進める。 * 結果、bmpが2つと、最初のforemost取り出し時は半分で切れていて数字が読めなかったgifを救出。無事flagが手に入りました。
100_Steganography 2
なぜsteganographyだけタイトルが雑なのか。
question.txt
Find the flag in this file. sunrise.zip ファイルからflagをさがせ. sunrise.zip
と、sunrise.zip
。question.txtが日本語訳ついているのは何か深い理由があるのか?
足跡
unzip sunrise.zip
で、sunrize.png
が出てきた。絵を見てみると、確かにsunrize。飛行機の上からの写真みたい。- なんだか先ほどと同じくファイルサイズ大きめ。11.2MB。
- 特におかしな所も見当たらないので、exiftoolでメタ情報を見てみたりしてみる。flagにつながりそうな情報無し。
less
してみる。なんか最後の方が愉快なパターンになっている気がする。確か圧縮形式の画像で自然画像ならば、あんなパターンは現れないはずだ。- ついにバイナリを見る時が来たか!ということで0xEDをinstallしてみる。
- バイナリを眺めてみる。PNGのファイルフォーマットと照らし合わせたりしつつ、おかしなとこがないかじっくり観察。
...ぜんぜんわからん。
解法
- ということで、この問題は完全にギブアップ。他の方のwrite-upを横目で見つつ、どうすれば良かったのかをなぞってみる。
- やっぱり最後の方の並びがおかしいのは注目すべき点だったらしい。あそこの部分に何か隠されているとして
- メタとして抜き出し可能(pngフォーマット内のタグは一通り確認したが、なかった)
- 画像ファイルに続きがある(領域外に書いてある。これは盲点だった!)
- pngフォーマットの幅・高さは上記のリンクから
IHDR
チャンクの先頭から[4byte, 4byte]らしいので、高さの方をいじってみる
49 48 44 52 | 00 00 0B D0 | 00 00 0F C0 ( IHDR )| 3024 | 4032
↓
49 48 44 52 | 00 00 0B D0 | 00 00 10 C0 ( IHDR )| 3024 | 4288
無事データの範囲内に入っていたようで、png形式でgimpで開けました。flag発見。
今回何気なく、縦の長さを変えてみたけども、領域外に何かが隠されているパターンについて後から考えてみた。 横方向の領域外に何かが隠れているとしたら、見るためには横の長さを返ることになる訳で、フォーマット的に横の長さを変えてしまうと、絵がダーーーーっとラインでずれていってしまう。それで何かが現れるようなステガノコンテンツを作れなくはないのだろうけど、少なくとも最初に見える絵はがびがびになっているに違いない。こんなに普通な絵で領域外に何か隠されているとしたら、縦方向にのばすのが筋なのだろう。
100_Steganography 3
これでステガノはラスト。
question.txt
We can get desktop capture! Read the secret message. desktop_capture.png デスクトップのキャプチャに成功した! 秘密のメッセージを読み取ってほしい desktop_capture.png
と、desktop_capture.png
。png率高し。
初心者の野生の勘による足跡
- まずは素直に
desktop_capture.png
を開いて眺める。確かにデスクトップ画像だ。 - 何やら作業中らしい。BZというバイナリエディタで
flag
というファイルが開かれているのと、そのエディタをキャプチャしてペイントで開いている。更に、バックにあるWebBrowserにメッセージらしきものが出ている。This problem can be solved by pre-school children... Who knows the answer? i can't figure it out!!?
This problem can be solved by pre-school children in 5-10 minutes, by programer - in 1 hour, by people with higher education... well, check it yourself. - 何やらやたらと挑発的である。
- 上記の挑発的な文言を信じるならば、幼稚園児の方が簡単に解いちゃうぜ!ということになるが、信じていいのか?これはヒントなのか、それともひっかけか・・・?
- まず気になるのは、開いているバイナリエディタ。頭が
ELF
で始まっているので、ELF形式の実行ファイルっぽい。832bytesらしい。ファイル名がflagであるからして、これからバイナリをデータ起こして、実行したらフラグになるのだろうか?でも、この画像から文字を読み取ってテキストに起こすのは、まさに1時間以上かかりそうだ。これは引っかけに違いない。 - 眺めてても埒が明かないので、とりあえず絵のとおりお絵描きツール(ペイントじゃなくてgimp)で開いてみる。
- 再度、ペイントで開いているウィンドウのあたりの絵を良く眺めてみると、塗りつぶしツール、黒が選択されている。
神のお告げ、きたる。(ヒント・解法)
いつもテレビを見ながらゆる〜くやっているのだが、なぜかちょうど「立体視」について取り上げ始めた。
航空写真を二枚左右に並べて、右の目で右の絵を、左の目で左の絵を見ると、3Dに見えるというあれだ。
小学校の教科書に載っていたが、私だけ全く出来なかったのでよく覚えている。
ぼーっとそれを見ていると、本当に偶然だが「あ、この問題ももしかして、画像からバイナリを起こすんじゃなく、このまま画像として俯瞰して見るんじゃね?」というお告げが舞い降りた。
- この仮説だと、上の挑発的な文言にも当てはまらなくはない
- そういえば他のパズル問題で、数字の○の部分を黒く塗りつぶした所をつなげてみると、でっかい文字が洗われる、的なのをやったことがある。
- あ、さっき塗りつぶしツールになってたし、これ塗りつぶしたら○が白く残って何か出てくるんじゃね?
- やってみる。ビンゴ!!ちょっと読みにくいけどflagが現れた!これは気持ちよかった!
Unknown
その他ってことかしら。
ただの謎解き好きとしては、この後に控える専門外の知識が必要そうな問題より取っ付きやすいかも。
一方、他のはタイトルで解法の一部を示してくれていた分、今回は解き方の方向性もヒント無し。
100_4042
4042って言うタイトルの問題らしい。
question.txt
Unknown document is found in ancient ruins, in 2005. Could you figure out what is written in the document? no-network.txt 謎の文章が2005年に古代遺跡から発見された。 これは何を意味している? no-network.txt
こ、古代遺跡!昂るーー!!
と、3kbのno-network.txt
。数字の羅列である。
初心者の野生の勘による足跡
- no-network.txtを眺めてみる
- 0~7の数字で構成されているようだ。8,9は出てこない
- 「8個」の何かあったかしら?曜日は7こだし。8進数とか?
- 割と数字が続いている箇所が多い気がする
- 81字×38行 + 15字。正方形ではない。
- 「2005」っちゅうのは意味深。何かありそうー!問題出したのから10年前、という見方も出来る。
- no-network.txtの2,0,5を■で置換してみる。ステガノの後だから、ビジュアルに頼ろうとしてしまったようだ。特に何も見えない。
- no-networkが8進数で表現されているとして、これを16進⇒ASCIIに変換してみる。文字列にならず。
- そういえば、4042ってなんだろう?ググる。
- 東ソー株式会社の株式ナンバーらしい。多分無関係。
- 他、どっかの商品の製品番号が沢山引っかかる。多分無関係。
- RFCの4042も引っかかった。ほう。ちょっと読んでみる。お、2005年発行らしいぞ。ビンゴか?
- UTF-9 and UTF-18...?そんなのあったっけ?あれ、そういえば発行日4/1...怪しくない?
- RFCってだいたい日本語サイトあるし、日本語サイト調べてみよう。
RFC4042
でググる。 - ジョークRFCというサイトが引っかかる。えっ!?
- RFCは、毎年伝統的に4/1にジョークRFCというのを発行しているらしい。知らなかった!4042もそのうちの一つ。上記リンクは途中で更新が切れていますが、Wikipediaにも載ってるほど。
- 無事、丁寧な日本語訳サイト発見。ありがたや。文字符号化形式UTF-8の拡張?版みたいな感じらしい。
解法
- 上記仕様書とutfの仕様書をにらめっこしつつ、utf9->utf8変換スクリプトを作成
- 問題文は上記の観察の結果8進数で書かれているっぽいので、これを3文字ずつ取得してbit列に変換するとnonet(9bitのブロック)に
- このbit列の先頭bitが、1文字を表現する際に次のbit-groupを使うかどうかのフラグになっている、との説明だったので、先頭bitが1なら次のnonetを同じ文字の続きとして処理、0ならそこで文字終わり、というように処理していく。
- 残った8bitをUTF-8のbitになるらしいので、上記処理でUTF-8にして読んでみる。
- 結果、下記のような出力になった。実は表示できていない文字がフラグの中に2カ所。一つは想像で補えたが、もう一つは無理かも。この問題は自力で解けるかも!と息巻いていたのだが、下記の出力を見てやり方が間違っている部分があったかもと思い他の方のwrite-upを見てしまった。
- 残念ながら、不明な2文字はなぜ解答のように見えるかは不明なまま。
- 古代遺跡云々は関係なかったらしい。。。
参考にさせていただいたリンク
- 文字コード(UTF-8,Shift_JIS,EUC-JP,ISO-2022-JP)についての俺的まとめ
- 文字コードの仕組みを全く知らなかったので。図解されていてわかりやすかったです。
- Unicode Character Search
- 自分の環境で読めない文字を絵で表示してくれる
■ 100_Command-Line Quiz
question.txtしかないけど大丈夫かしら・・・?
question.txt
telnet caitsith.pwn.seccon.jp User:root Password:seccon The goal is to find the flag word by "somehow" reading all *.txt files. telnet caitsith.pwn.seccon.jp User:root Password:seccon すべての *.txt ファイルを読め
ただの足跡
- 競技中の期間限定環境っぽいから、もう閉じられてるかなーと思ってtelnet接続を試みた。
$ telnet caitsith.pwn.seccon.jp Trying 153.120.171.19... telnet: connect to address 153.120.171.19: Operation timed out telnet: Unable to connect to remote host
やっぱだめだった。 これは後追いでは無理っぽい。あとで他の人のwrite-upをみてフムフムしよう。
200_QR puzzle (Windows)
Windowsじゃない(しOSライセンスも持っていない)けど大丈夫かしら?
question.txt
Please solve a puzzle 300 times QRpuzzle.zip
と、QRpuzzle.zip
初心者の野生の勘による足跡
- QRpuzzle.zipの中には、下記のものが。
$ unzip QRpuzzle.zip Archive: QRpuzzle.zip inflating: QRpuzzle.exe inflating: DotNetBarcode.txt inflating: DotNetBarcode.dll
- DotNetBarcode.txtを読んでみる。。。長い。とにかく、デンソー製の「VB2005,C#2005で使える高機能QRCode対応完全無料バーコードライブラリ(サンプルソース付)」らしい。
- こんなこともあろうかと、macにexeファイル実行環境だけそろえておいた(Wine+WineBottler)ので、QRpuzzle.exeをとにかく実行してみる。こんなのが出現!
- どうやらパネルを並び替えてQRコードを完成させるようだ。選択したパネル同士を置換できるので、そんな感じで一度遊んでみる。
- 完成したのに何も起きない。よく見ると、下の方に
Answer
という何か欲しそうなフォームがいる。QRコードを解釈して出てくるメッセージ的なものをここに入れるのか、と思いやってみる。 - 今回のパターンだと
sound
でした。入力すると次のが出てきた。ふむふむ、これを300回解けってことね。上の方にバーがあって、一回解くと少し進んだ気がする。 - アプローチとしてはこれくらいのパターンがありそう。
- 300回ぽちぽち解く。。。気合いだ!!でも300回ならやれそうな気もする。。。
- 300回解くプログラムを組む
- 実行ファイルをいじって数回でflagが出てくるようにする
- 実行ファイルを解析してflagを見つける
- 1.の解法が実は一番早いかもしれない、と思わせる繰り返し回数(300回)
- 競技中だとすると、残り時間と自分の担当問題数(複数人でやってればですが)とを考慮して、最速で解けそうなものを選択するんでしょうが(私の場合アセンブラ的知識0なので多分1.)、今回は2.を作ってみたくなったので2でやってみる事にしました。
- ruby暦浅いので、画像処理をどれだけrubyでお手軽にできるか試してみたかったのと、QRコード+rubyの相性を知っておきたかったという意図もあり。
解法
- まずは環境を整える。画像処理環境もなにもない状態。
- macにimagemagickを入れる
- rubyで画像解析するためにRMagickを使う
- imagemagickをrubyで使えるようgem化したライブラリ
上記の環境を整えて、いざパズル自動で解く君を作成。
流れ的にはこんな感じでしょうか。
- capture window.
- make qr code.
- read qr code.
fill answer form.
1,2は好きな分野だったのでさくさくっと。rmagick便利。
- rubyでQRコードの読み取りはちょっとはまったのでメモを残した
- 4.が超苦労した。wineで実行している事もあってか、出来そうで出来ない事多し。
- 開いているウィンドウの中から、ターゲットウィンドウを指定してテキストを送る、というのがなかなか。
- Application名はwine?でもwineは沢山開いているので指定が難しそう。Window名を指定してみたり。。。という試行錯誤を下記に残しました。
- rubyからmac上で実行中のアプリケーションを操作
- 何とかあきらめずに全自動になった。よかった。
- コード完成!!ぱんぱかぱーん!!実行!!!
- ドキドキしながら実行
- なんとか動いてくれるが、文字の入力時にいっぺんに送ると何文字か飛ばして入力しちゃう。かわいらしい。実際に競技中だったら憎たらしいに違いない。1文字ずつdelayしながら入力させる事に。
- Answer入力後の画面切り替えに結構時間がかかる事が判明。5秒delayを入れても時々間に合っていない。
- 色々delayやヒストグラム値の調整をして、いざ走らせる。
- よちよち実行している感じ(遅い)でかわいらしい。が、遅いよ遅い。。。コーディング時間と実行時間足したら、全部手動で実行した方が俄然早かったと思われる。
- 300問達成!すると、Answer部分にFlagが現れた!感動!記念にスクリーンショット。結局delayが効いて、300問に40分近くかかったんではなかろうか。
- この問題に超特化してますが、折角作ったかわいい子なのでコードをアップしてみました。
- このスクリプトの大きな問題点は、実行している間他の作業が同じマシンでし辛い(というかほぼ出来ない)こと。見守るだけ。折角自動化したのに・・・笑
■ 300_QR puzzle (Nonogram)
Nonogramって初めて聞いたのでググってみる。
Wikipedia - Nonogram
ん!?
Wikipedia - ノノグラム
わーお!お絵描きロジックの事!?
何を隠そう、私は小学生時代、お絵描きロジック部だったのだ!
これは、、、解ける!解いてみせる!!
question.txt
Solve a puzzle 30 times http://qrlogic.pwn.seccon.jp:10080/game/
あわわ、こ、これはもしや。。。期間限定環境?もう残っていないデスヨネー。。。
ということで、question.txtのurlにアクセスしてみるも、やはりもう閉じられている様子。くぅ。。。
▲ 400_QR puzzle (Web)
ここまで来てようやく、最初の数字が管理番号ではなく得点だと言う事に気づく。
Webってことは、こちらももう環境が閉じちゃっているかしら?
question.txt
Solve the slide puzzle and decode the QR code. http://puzzle.quals.seccon.jp:42213/slidepuzzle
と、build
フォルダ。
buildフォルダがあるやつは、Web環境を再現できるのかな。
build
の環境をたててみる
- buildの中を見てみる
make_image.py
とweb/の中
$ ls imgsvr.py qrpuzzle.py qrpuzzle.sh
- どうやら順序としては、
make_image.py
を実行しつつqrpuzzle.sh
を実行するらしい - 一通り全部のファイルを見てみて、インストールすべきものを確認。。。ついでにフラグも発見。が、ここは見てみぬふり。
- 必要なpythonライブラリをinstallするのに
apt-get
が使いやすいそうなので、linux(VM)で実行
$ sudo apt-get install python-imaging $ sudo apt-get install python-qrcode $ sudo apt-get install python-qrtools
$ sudo pip install bottle $ sudo pip install paste $ sudo pip install wsgi-request-logger
$ python make_image.py
お、エラー。。。55行目の最後に)
が余計。削除。再実行で動いたっぽい。
build
直下にcatalog.txt
と、webの下にimg
ディレクトリ、その中に大量のpngが生成されているようだ。カウントが100ずつ出力されるが、かなり待って400で終了。
ちなみに、pngはすべてQRコードの一部のようだ。全部入っているのもあれば、タグ部分のみのものもある。
$ cd web $ ./qrpuzzle.sh vagrant@vagrant-VirtualBox:~/workspace/build/web$ nohup: 出力を `nohup.out' に追記します'
そうか。nohup.out
を見てみるけども、特に何も出ていない。エラーにはなってなさそう。
* http://localhost:42213/slidepuzzle
にアクセスしてみる
* うーん、画像が出てこない。ブラウザのNetwork通信を見てみると、http://puzzle.quals.seccon.jp
に画像を探しにいっている
* qrpuzzle.py
の196行目を変更
imagehtml += "<img src='http://puzzle.quals.seccon.jp:100%d%d/img/%s.png>' name='%d%d' onclick=clicked(this)>" % (y, x, imagepath, y, x)
↓
imagehtml += "<img src='http://localhost:100%d%d/img/%s.png>' name='%d%d' onclick=clicked(this)>" % (y, x, imagepath, y, x)
- 再度
http://localhost:42213/slidepuzzle
にアクセス、今度は画像取得時に500(internal server error)が返ってきている模様 - 500エラーの原因は不明。渡しているpath(上記
%s
)の値が期待と違う気がするのだが、どうすれば良いかわからず。後少しな気がするんだけどな〜。
□ 400_Reverse-Engineering Android APK 2
Android apkですか。reverse engineeringですか。
両方ほぼ無縁ですし、点数高いってことは難しいのかしら。
question.txt
The key is stored in the application, but you will need to hack the server. ( *Do not use your real mail address.) app-release-apk.pwn.seccon.jp-v1.3.apk キーはアプリケーションの中にある。しかしサーバをHackしなければ手に入らないだろう。 (登録情報に他人に知られたくないメールアドレスは使用しないでください) app-release-apk.pwn.seccon.jp-v1.3.apk
と、app-release-apk.pwn.seccon.jp-v1.3.apk
サーバをHackしなければ〜という事は、これも特定のサーバと通信するんかいな?
しかもそのサーバはもう閉じられとる気がするなぁ・・・
そして何なんだ、この長い名前のapkは。怪しすぎる。
とにかく触ってみる
- まずは自分のAndroid端末に入れて試してみる
- Application名がyekehtmai...I am the keyの逆ですね。意味深。
- Applicationを立ち上げてみる。EmailとPasswordを入力するようになっていて、適当に入れてSign inしてみる。
- Logging inダイアログがくるくるした後、何か言いたげなポップアップ(中身は空)が小さく表示されて元の画面に戻る。
- question.txtを信じるなら、やはりどこかに通信に行っているはずで、しかもその環境がもうなくてエラーメッセージすら出ない状況、と推測。
とにかく解析してみる
- 難しそうだったので、先にBinaryカテゴリの100_Reverse-Engineering Android APK 1(以降パート1)を先にやる。この続き物っぽいし。
- パート1と同じ手順を試してみる
- 今回はソースが巨大。そして何より難読化されているっぽく、ファイル名も変数もaとかbとか意味のない文字ばかり。
- まずはこのApplicationのEntryPointを探るべく、
AndroidManifest.xml
を開いてみる kr.repo.h2spice.yekehtmai.AppControlleractivity&kr.repo.h2spice.yekehtmai.MainActivity
おお、さっきみてたみてた。- ざーっと再度見てみる。画面構成要素が作られていく感じの関数がずらり。特に気になる点無し。しかし関数名とかって大事ですね。aとかbとか、もう何のための何がしたい関数(or変数)なのかさっぱりわからん!
- 問題文を思い出してみる。
しかしサーバをHackしなければ手に入らないだろう
- どこかでこのアプリのAPIサーバに接続に行っているに違いない。そこをまずは見つけてみよう。(そしてまだ生きているか確かめよう)
$ grep http * a.java: public static String a = "http://apk.pwn.seccon.jp/login.php"; a.java: public static String b = "http://apk.pwn.seccon.jp/register.php";
おったおった。phpですって。アクセスしてみる。応答無し。終了。。。
- 悔しいので、ちょっと続けてみる。次に怪しそうなのは、
WelcomeActivity.java
=中略= bundle = (String)((HashMap) (obj)).get("name"); String s = (String)((HashMap) (obj)).get("email"); obj = ((String)((HashMap) (obj)).get("uid")).substring(i, k); try { f = kr.repo.h2spice.yekehtmai.c.b("fuO/gyps1L1JZwet4jYaU0hNvIxa/ncffqy+3fEHIn4=", ((String) (obj))); }
最初に出てきた画面の入力部分ですかね。注目すべきはtryの中身。その後、bundle
とf
を表示しているようです。
- とりあえず
f
生成に使用しているobj
の出自を確認。grepで"uid"を突っ込んでいる箇所を探す。
$ grep uid * WelcomeActivity.java: obj = ((String)((HashMap) (obj)).get("uid")).substring(i, k); d.java: hashmap.put("uid", cursor.getString(3)); d.java: contentvalues.put("uid", s2); d.java: sqlitedatabase.execSQL("CREATE TABLE user(id INTEGER PRIMARY KEY,name TEXT,email TEXT UNIQUE,uid TEXT,created_at TEXT)"); g.java: s = ((JSONObject) (obj)).getString("uid"); m.java: s = ((JSONObject) (obj)).getString("uid");
どうやらd.java
が怪しそうだ。見てみると、Class dはSQLiteOpenHelper
を継承しているようだ。サーバーとの通信部かしら。
uidが普通のuidだとすると、フォーマット決まっているのでサーバーとつながらなくても総当たりで行けるかしら。
f
生成部kr.repo.h2spice.yekehtmai.c.b
を確認
=中略= public static String b(String s, String s1) { Object obj = null; try { s1 = new SecretKeySpec(s1.getBytes(), "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(2, s1); s = cipher.doFinal(kr.repo.h2spice.yekehtmai.b.a(s)); } // Misplaced declaration of an exception variable catch(String s) { System.out.println(s.toString()); s = obj; } return new String(s); }
おお、なんかフラグに近づいた気がする!
SecretKeySpec
はjava1.4以降に入っているjavax.crypto.spec
の機能らしい。バイト配列から SecretKey を構築
- らしいので、
s1
は生成したSecretKeyで置き換えられるようだ - 更にその
s1
をcipherの初期化に利用して、s
を生成するらしい。このs
がフラグっぽい - ここでこの関数内の
s
,s1
は何だったかというとs
:"fuO/gyps1L1JZwet4jYaU0hNvIxa/ncffqy+3fEHIn4="
s1
:((String)((HashMap) (obj)).get("uid")).substring(i, k)
最後のcipherでAES暗号化するバイナリ生成部のコード(kr.repo.h2spice.yekehtmai.b.a(s)
,s
はString)を追ってみる
=中略= public static final byte[] a(String s) { if(s == null) return null; else return a(s.getBytes()); } public static final byte[] a(byte abyte0[]) { =中略=(長い) }
色々処理をしているようです。
整理すると
1. ログインフォームの部分で"uid"にあたる文字列を取得
2. そのuidを元にSecretKeySpecを生成,cipherのinitializeに使う
3. "fuO/gyps1L1JZwet4jYaU0hNvIxa/ncffqy+3fEHIn4="をごにょごにょして、2.で初期化したcipherで復号
解法
- 残念ながら、サーバーからデータを取ってくる方向の解法は使えないので、総当たり!ブルートフォースってやつですね!
uidが普通のuidだとすると、フォーマット決まっているのでサーバーとつながらなくても総当たりで行けるかしら。
- sqlのuidは数値、これをstringにしているので、候補文字列は
0~f
。カットされた後の長さは、AESに食わせるためには16
なはず。 - ということで、総当たりプログラム作成
- デコンパイルして出てきたソース達から、フラグっぽいと睨んだ部分を導き出すために必要な部分を切り貼り。入力値のuidを総当たりでぶん回し、出てきた答えがフラグっぽかったら停止させるという感じ。
- 書きながら気づいてしまった事。上記、uidフォーマット前提を間違えると、時間がかかるのに答えにたどり着けないという最悪の結果に!
- 本番コンテスト中は、そもそも総当たってる時間はない(マシンパワー次第ではあるが、最初の方に手を付けてプログラムを走らせとかないと厳しそう)し、上記のリスクもあるため、後追いならではの方法かもしれない。
まわしてみた。
- 最初、えらい計算量が多い・かつ桁溢れを起こすプログラムでまわしていたので、途中から高速化を図ったのだけど、それでも答えまでたどり着くには数日かかりそうだった。
- ので最後までまわしてません><!うちのPC子ちゃんもそんなに暇じゃないので!
- 10桁くらいがあきらめずに回せる限界かな。。。
感想
- 300_Decrypt it でも総当たりに近い事をやったけど(前から確定していけるので計算量は格段に少なくてすんだ)、解法が合っているか自信のないまま総当たりプログラムを走らせるのは辛い。しかも桁数が多い場合は。きっとパスワードクラッカーも同じ気持ちだろうと推測する。
- なので、よく言われる下記のパスワードポリシーは、攻撃者にとっては嫌な事が実感できた。攻撃に必要な時間が桁違いに変わってくる。
- 桁を長く
- 数字だけ、アルファベットだけ、は避け、できるだけ大文字小文字・記号も織り交ぜる
銀行の暗証番号とか4桁の数字だから、総当たりで一瞬。。。
Web経由だと暗証番号だけで操作できる事はまずないけど。
Exploit
Exploitってあれでしょ、「取り除く」とか言う意味じゃなかったっけ?
という初心者丸出しの状態で、しかも英語に自身がなかったのでググってみる。
コンピュータ関連のソフトウェアやハードウェアの脆弱性を利用した悪意ある行為のために書かれた、スクリプトまたはプログラムを指す言葉である。<中略>あるいは全く逆のセキュリティ確認目的での、脆弱性検証するための実証コード(Proof of concept:PoC)を指すこともある。また、前記のようなスクリプトやプログラムを用いて脆弱性を攻撃するという意味合いでも用いられる。
出典:wikipedia
おう!セキュリティ用語でしたか!脆弱性に関する知識はあまりないので、苦戦する予感。
△ 200_FSB/ TreeWalker
何でも調べてみる。TreeWalkerとは、DOMのインタフェースのようだ。
文書のサブツリーのノード及びその位置を表します
また、FSBとは。ググると、ロシア連邦保安庁 だとか フロントサイドパス(データ伝送路の一種) だとか 金融安定理事会 がヒットするが、どれもピンと来ない。
だから略語は嫌いなんだよーとか言いつつ続けて調べていると
Format String Bug というのが引っかかった。これっぽい。
書式文字列攻撃(しょしきもじれつこうげき、英: Format string attack)は、1999年ごろ発見された(それまでは無害と考えられていた)セキュリティホールを利用した攻撃のクラスである。書式文字列攻撃は、プログラムをクラッシュさせたり、不正なコードを実行させたりできる。
question.txt
treewalker.pwn.seccon.jp 20000 treewalker
あとは、treewalker
という正体不明ファイルと、build
フォルダ。ここいらまで来ると何となく察しがついてくるのは、buildファイルがあるものはリアルタイムで解いたときは存在していた環境を再現するためのソースなのかしら。ということ。きっとbuildの中には、開いたらflagが埋まっている。。。
初心者の野生の勘による足跡
- もはや、まずはとりあえず生!くらいの勢いになってきた
file
コマンド。
$ file treewalker treewalker: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for_GNU/Linux 2.6.32, not stripped
ubuntu上で実行してみる。
$ ./treewalker vulnserver.c(46): No flag.txt
ん。なんかはずれですよ〜って感じ? * 問題としては、urlとこのファイルだけ渡された状態のはずなので、もう少しこのファイルをいじってみる
$ objdump -d treewalker > dump.txt
dump.txtを見てみるとread_flag
なる関数が存在するようだ
build
の環境を立ち上げてみる
$ ls
development-files production-files src
dist-files scripts
全部ディレクトリ * docker使っているようなので、インストール
$ sudo apt-get install docker.io
※docker
もあるが、docker.io
のほうらしい
$ cd scripts
$ sudo ./create-production-image.sh
$ sudo ./run-production.sh
localhost:20000/
にアクセスしてみるvulnserver.c(46): No flag.txt
- あれ、さっきと同じ文言が表示されるだけ・・・?
- でも環境としては動作しており、立ち上がったっぽい
わかったこと
- ここでギブアップして他の人のwrite-upを読んでみる
- どうやら
treewalker
バイナリの逆アセンブル結果をちゃんと解析して、FSBを発見し、そこを攻撃するようなプログラムを書いてサーバに投げつけるようだ - ちなみに他の人のwrite-upは、数がそんなにない上に、上記アセンブラの知識無し、FSBとか初めて聞いたわ!という状態だと、宇宙語にしか思えない。。。
□ 300_Micro computer exploit code challenge
※この記事は解まで到達しておりません
micro computer...って何だっけ?
ググってみると、意味はいくつかありそうだ。
ちょっと問題を眺めた後、一番適切そうな解説
question.txt
micro.pwn.seccon.jp 10000 * A program is running at port 10000 on this server. * Flag word "SECCON{...}" is located at address 0x1800 in machine code area. * The program is running on GDB simurator. (gdb-7.10 + special patch for read service) avr-elf.x micro.pwn.seccon.jp 10000 * プログラムはサーバの10000番ポートで稼働中 * フラッグ "SECCON{...}" はマシンコードの 0x1800 にある * プログラムはGDBシミュレータの上で動いている (gdb-7.10 + special patch for read service) avr-elf.x
と、avr-elf.x
という謎ファイル。
初心者の野生の勘による足跡
$ file avr-elf.x avr-elf.x: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
Atmel AVR 8-bit
だなんて怪しそうな事かいてある。
SECCONでは、今後も色んなコンピュータアーキテクチャの実行ファイルがぽいっと渡されることあるかも?と思い、クロスコンパイル環境を整える事に。
クロスコンパイル環境を整えて実行してみる
- クロスコンパイル環境を立ち上げ
kusuwada.hatenablog.com
- ↑環境立ち上げ時のメモ
- この環境は今後も何度か使うので、【熱血クロスコンパイル環境】と命名してみます
- VirtualBoxで立ち上げてみる
usr/local/cross-gcc4/bin
に、各種実行バイナリが取り揃えてあります。
$ cd /user/local/cross-gcc4/bin $ ./avr-elf-run ~/tmp/micro/avf-elf.x This is avr-elf server. OK. Input name:
おお、なんか出た!
Input name
と言われたので、kusuwada
と、とりあえず入れてみる。- しーーーん。次の入力が出来るようなので色々入れてみたが、特に何も起きず。
- タイトルを思い出してみよう。Micro computer exploit code challenge だ。脆弱性を見つけて攻撃する感じな気がする。
avr-elf.xを解析してみる
- 下記サイトでavrの基礎知識を得る ※超斜め読み。。。
- Atmel AVRとは (Wikipedia)
- すっげ〜AVRマイコン
- すごく古い記事ですが、初心者向け
- AVR-GCC 導入編
- どうやらアセンブリらしいので、逆アセンブルしてみる。
- 幸い、【熱血クロスコンパイル環境】に
/usr/local/cross-gcc4/bin
にavr-elf-objdump
がいらっしゃる。このVMイメージすごい!
$ pwd /usr/local/cross-gcc4/bin $ ./avr-elf-objdump -d ~/tmp/micro/avf-elf.x > ~/tmp/micro/avr-obj.dump
avr-obj.dump、一部抜粋
/home/user/tmp/micro/avr-elf.x: file format elf32-avr Disassembly of section .text: 00001000 <_start>: 1000: c0 e5 ldi r28, 0x50 ; 80 1002: dc e1 ldi r29, 0x1C ; 28 1004: cd bf out 0x3d, r28 ; 61 1006: de bf out 0x3e, r29 ; 62 1008: 11 24 eor r1, r1 100a: b6 d0 rcall .+364 ; 0x1178 <main> 0000100c <__exit>: 100c: 8f bd out 0x2f, r24 ; 47 100e: 08 95 ret 00001010 <__read1>: 1010: e6 2f mov r30, r22 1012: f7 2f mov r31, r23 1014: 81 b7 in r24, 0x31 ; 49 1016: 80 83 st Z, r24 1018: 08 95 ret 0000101a <__write1>: 101a: e6 2f mov r30, r22 101c: f7 2f mov r31, r23 101e: 80 81 ld r24, Z 1020: 82 bf out 0x32, r24 ; 50 1022: 08 95 ret 00001024 <lpm>: 1024: e8 2f mov r30, r24 1026: f9 2f mov r31, r25 1028: 85 91 lpm r24, Z+ 102a: 90 e0 ldi r25, 0x00 ; 0 102c: 08 95 ret 0000102e <exit>: 102e: 0e 94 06 08 call 0x100c ; 0x100c <__exit> 00001032 <read1>: 1032: cf 93 push r28 1034: df 93 push r29 1036: cd b7 in r28, 0x3d ; 61 1038: de b7 in r29, 0x3e ; 62 103a: 21 97 sbiw r28, 0x01 ; 1 103c: 0f b6 in r0, 0x3f ; 63 103e: f8 94 cli 1040: de bf out 0x3e, r29 ; 62 1042: 0f be out 0x3f, r0 ; 63 1044: cd bf out 0x3d, r28 ; 61 1046: 2f ef ldi r18, 0xFF ; 255 1048: 29 83 std Y+1, r18 ; 0x01 104a: be 01 movw r22, r28 104c: 6f 5f subi r22, 0xFF ; 255 104e: 7f 4f sbci r23, 0xFF ; 255 1050: 0e 94 08 08 call 0x1010 ; 0x1010 <__read1> 1054: 89 81 ldd r24, Y+1 ; 0x01 1056: 99 27 eor r25, r25 1058: 21 96 adiw r28, 0x01 ; 1 105a: 0f b6 in r0, 0x3f ; 63 105c: f8 94 cli 105e: de bf out 0x3e, r29 ; 62 1060: 0f be out 0x3f, r0 ; 63 1062: cd bf out 0x3d, r28 ; 61 1064: df 91 pop r29 1066: cf 91 pop r28 1068: 08 95 ret 0000106a <write1>: 106a: cf 93 push r28 106c: df 93 push r29 106e: cd b7 in r28, 0x3d ; 61 1070: de b7 in r29, 0x3e ; 62 1072: 21 97 sbiw r28, 0x01 ; 1 1074: 0f b6 in r0, 0x3f ; 63 1076: f8 94 cli 1078: de bf out 0x3e, r29 ; 62 107a: 0f be out 0x3f, r0 ; 63 107c: cd bf out 0x3d, r28 ; 61 107e: 69 83 std Y+1, r22 ; 0x01 1080: be 01 movw r22, r28 1082: 6f 5f subi r22, 0xFF ; 255 1084: 7f 4f sbci r23, 0xFF ; 255 1086: 0e 94 0d 08 call 0x101a ; 0x101a <__write1> 108a: 21 96 adiw r28, 0x01 ; 1 108c: 0f b6 in r0, 0x3f ; 63 108e: f8 94 cli 1090: de bf out 0x3e, r29 ; 62 1092: 0f be out 0x3f, r0 ; 63 1094: cd bf out 0x3d, r28 ; 61 1096: df 91 pop r29 1098: cf 91 pop r28 109a: 08 95 ret 0000109c <getchar>: ~~略~~ 000010a8 <putchar>: ~~略~~ 000010c0 <gets>: ~~略~~ 000010e0 <puts>: ~~略~~ 00001108 <check_ok>: 1108: 84 e0 ldi r24, 0x04 ; 4 110a: 98 e1 ldi r25, 0x18 ; 24 110c: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1110: 8c e1 ldi r24, 0x1C ; 28 1112: 98 e1 ldi r25, 0x18 ; 24 1114: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1118: 8e e1 ldi r24, 0x1E ; 30 111a: 98 e1 ldi r25, 0x18 ; 24 111c: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1120: 80 e0 ldi r24, 0x00 ; 0 1122: 90 e0 ldi r25, 0x00 ; 0 1124: 08 95 ret 00001126 <proc>: 1126: cf 93 push r28 1128: df 93 push r29 112a: cd b7 in r28, 0x3d ; 61 112c: de b7 in r29, 0x3e ; 62 112e: 60 97 sbiw r28, 0x10 ; 16 1130: 0f b6 in r0, 0x3f ; 63 1132: f8 94 cli 1134: de bf out 0x3e, r29 ; 62 1136: 0f be out 0x3f, r0 ; 63 1138: cd bf out 0x3d, r28 ; 61 113a: 83 e2 ldi r24, 0x23 ; 35 113c: 98 e1 ldi r25, 0x18 ; 24 113e: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1142: ce 01 movw r24, r28 1144: 01 96 adiw r24, 0x01 ; 1 1146: 0e 94 60 08 call 0x10c0 ; 0x10c0 <gets> 114a: 80 e3 ldi r24, 0x30 ; 48 114c: 98 e1 ldi r25, 0x18 ; 24 114e: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1152: ce 01 movw r24, r28 1154: 01 96 adiw r24, 0x01 ; 1 1156: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 115a: 8c e1 ldi r24, 0x1C ; 28 115c: 98 e1 ldi r25, 0x18 ; 24 115e: 0e 94 70 08 call 0x10e0 ; 0x10e0 <puts> 1162: 80 e0 ldi r24, 0x00 ; 0 1164: 90 e0 ldi r25, 0x00 ; 0 1166: 60 96 adiw r28, 0x10 ; 16 1168: 0f b6 in r0, 0x3f ; 63 116a: f8 94 cli 116c: de bf out 0x3e, r29 ; 62 116e: 0f be out 0x3f, r0 ; 63 1170: cd bf out 0x3d, r28 ; 61 1172: df 91 pop r29 1174: cf 91 pop r28 1176: 08 95 ret 00001178 <main>: 1178: c0 e5 ldi r28, 0x50 ; 80 117a: db e1 ldi r29, 0x1B ; 27 117c: de bf out 0x3e, r29 ; 62 117e: cd bf out 0x3d, r28 ; 61 1180: 64 e0 ldi r22, 0x04 ; 4 1182: 70 e0 ldi r23, 0x00 ; 0 1184: ce 01 movw r24, r28 1186: 01 96 adiw r24, 0x01 ; 1 1188: 0e 94 84 08 call 0x1108 ; 0x1108 <check_ok> 118c: 0e 94 93 08 call 0x1126 ; 0x1126 <proc> 1190: 80 e0 ldi r24, 0x00 ; 0 1192: 90 e0 ldi r25, 0x00 ; 0 1194: 0e 94 17 08 call 0x102e ; 0x102e <exit> 1198: 80 e0 ldi r24, 0x00 ; 0 119a: 90 e0 ldi r25, 0x00 ; 0 119c: 0c 94 17 08 jmp 0x102e ; 0x102e <exit>
- んー!未知の世界(正確には未知ではないはずだけど、10年前に数時間講義を受けた程度)の言語としては、結構大物!
- Atmel AVR 8ビット 命令一式を眺めながら読み解いてみる
あーーーー!無理ーーーーー!
根気のない私にはこれは無理だ。うん。そもそもこの分野が学びたかった訳ではない!事にして、この問題はギブアップ。
他の方のwrite-upを参考にしようとしたが、さすがこの問題を解けたチームが少ないだけあって、皆さんデキル方の用で。初心者向けのwrite-upはあまりなかった感じ。
アセンブリにまた興味が出てきたらまたやるかも。
(そもそもmicro.pwn.seccon.jp 10000
は2016/2/7現在、もはや稼働しておらず、フラグは稼働中のサーバに埋まっている訳で、avr-elf.x
だけを解析しても攻撃手法が分かるまで。実際のフラグは手に入らない。。。)
▲ 500_SYSCALL/ Impossible
500点問題・・・。ごくり。しかもImpossible・・・。
question.txt
pinhole.pwn.seccon.jp 10000 Pinhole.cpp vulnserver Read "flag.txt" and then write the content to stdout, such as the following pseudo code. == fd=open("flag.txt", 0); len=read(fd, buf, 4096); write(1, buf, len); == Notice that the vulnserver executable is protected by an Intel Pin tool, the source code of which is "Pinhole.cpp". pinhole.pwn.seccon.jp 10000 Pinhole.cpp vulnserver 以下のような擬似コードを使用して"flag.txt"を読み出し標準出力に書き出してください。 == fd=open("flag.txt", 0); len=read(fd, buf, 4096); write(1, buf, len); == 実行可能なvulnserverはIntel Pin(pintool)によって保護されている、そのソースコードは "Pinhole.cpp"です。
と、Pinhole.cpp
、vulnserver
、build
フォルダ。
build
フォルダはREADME付きで親切な感じ。。。
だが、「どうせvulnserver
の逆アセンブルとか出てくるんでしょ」という気持ちになっており。
このジャンルほんと厳しーわー、、、と思っている所への500点問題ということで、パスッ!
Web_Network
Network系。配点が低めのものが多い。
▲ 100_Connect the server
サーバにつなげるだけ?
question.txt
login.pwn.seccon.jp:10000
一行!
と、build
フォルダ。その中にMakefile
とmylogin.c
build
の環境を構築
- 両ファイルとも特に説明はなし
$ cd build $ make
mylogin
の実行ファイルが出来た。
$ ./mylogin CONNECT 300 Welcome to SECCON server. The server is connected via slow dial-up connection. Please be patient, and do not brute-force. login:
なんか一文字ずつかたかた表示されて可愛い。 放置してたらタイムアウトした
Login timer timed out. Thank you for your cooperation. HINT: It is already in your hands. Good bye.
お、なんかヒントくれた。既にフラグが手に入っているらしい。
ってかこのbuild
、環境をたてる訳じゃなくて直でスクリプト実行なんだね。。。
- そうは言っても、何かもらったような気はしていない。
- コードを読んでみる。なるほど。。。いきなり一番上に答えが
const char *the_flag = "ふらぐふらぐ"; const char *p; for (p = the_flag; *p; p++) { fputc(*p, fpw); fputc('\b', fpw); fputc(' ', fpw); fputc('\b', fpw); }
出して消して出して消してする制御文字を書き出しているのね
- できそうなこと
- ターミナル上のすべての出力を記録する
- macのterminalではぱっとそういう設定に出来なかった。。
- 実際サーバを立ち上げて、
mylogin
君を稼働状態にする。で、リモートアクセス
- ターミナル上のすべての出力を記録する
けつろん
- サーバ上で稼働している場合は、Wireshark使ったり、teratermでlogging設定したりと、通信を全部Catchするようにしていれば、解けると思われる
- 深追いするのもなんなのでこの辺にしておく
■ 100_Entry form
どこかに登録したら何か情報が出てくるのかしら。
question.txt
http://entryform.pwn.seccon.jp/register.cgi ( Do not use your real mail address.) (登録情報に他人に知られたくないメールアドレスは使用しないでください)
question.txtのみ。urlアクセス系なので、後追いは不可。残念。
200_Bonsai XSS Revolutions
ぼんさい・・・?
question.txt
What is your browser(User-Agent)? hakoniwaWebMail_20151124.zip Requirement:.NET Framework 4.5 ブラウザの名称(User-Agent)を答えよ。 hakoniwaWebMail_20151124.zip 必要環境.NET Framework 4.5
と、hakoniwaWebMail_20151124.zip
ただの足跡
hakoniwaWebMail_20151124.zip
を解答するとexeファイルが出現- 実行してみる。SECCONはexeファイル実行環境は必須のようだ
- 青い画面のアプリが現れた!windowsのdektopのように見えなくもない
- ゴミ箱がある、が触れない。インタラクティブではないようだ。あとはStartボタンとIEのように見えるボタン。
- 地味にApplicationアイコンが盆栽の絵になってる。。。かわいい。
- まずはIEっぽいボタンを押してみる。⇒なんかフリーズした!立ち上げ直し
- Startボタンを押してみる。⇒やっぱりフリーズ!まぁ必要環境.NETって書いてあるしね。。。
ということで、自力で解くのはあきらめて他の方のwrite-upを見る事に。
ほうほう、とってもわかりやすく解説されている!
XSS攻撃してみるだなんて、まさに今回やりたかった事!かつこういう機会でもないとやらないに違いない。
う〜ん、やってみたい!!!苦行と言っている人もいるけど、幸い後追いな私には時間がある!
windows(家族マシン)を借りてやってみる事に
- 武器はコマンドプロンプトとteratermのみ
- むしろ何故teratermが入っているのか。。。
- このままでは辛そうなので、人気そうなGowとclinkをinstallして、コマンドプロンプトでLinuxコマンド&bashっぽいシェル環境が使えるようにしておく
- 参考記事
- ※ただし今回使わなかった。。。
===仕切り直し===
- 再度
hakoniwaWebMail.exe
を実行! - 同じ画面が出た後、なんとWebっぽいアプリケーション(っぽい)ものが立ち上がる
- そしてID,Passwordを入力画面になり、勝手になんか入れられた後Webメール画面が表示される
- 画面をつんつんしてみると、
You can NOT operate anything.
ですって - アドレスバーらしきものに
https://tsuribori.test/webMail
と出ていたのでアクセスしてみる。・・・つながらず。 - 先に解き方をちら見してしまっているので、そこで得た下記の情報をもとにやる。
- とにかくつないでみようということで、teratermで下記に接続を試みる
- おお、つながった。こんなんでた。
220 tsuribori.test Tsuribori-SMTPserver by KeigoYAMAZAKI, 2014.12.09- ESMTP
- そういえば、さっきのログイン画面、こんなユーザ名だったような気がする
- 適当な文字列を入力してみる
502 unimplemented
が返ってくる。何かしら動いているようだ。
- この箱庭メールサーバーにメールを送ってみる。bonsaiアプリケーション画面からは、
keigo.yamazki@tsuribori.test
さんに送ると、中身が見れる気配がする - メールのプロトコルとか何度かちら見した程度なので、後述の参考サイトをふむふむしながら下記コマンドをうってみる
HELO kusuwadan.com MAIL FROM: kusuwadan@hoge.com RCPT TO: keigo.yamazaki@tsuribori.test DATA hello, keigo! .
- 最初、何を送っても
502 unimplemented
しか返ってこない!と思ったら、teraterm側の設定で送信側の改行コードがCRに設定されていた。SMTPプロトコルは改行はCRLFなので、設定を変更して再チャレンジ。うまくいった! - 上記はプロトコルしか送っていないので、何の情報もない、まさに空メールが送られました。ちゃんとbonsaiアプリケーション画面上に新着のからメールが表示されてます!!
- 今度はもう少し情報を詰めて。
HELO kusuwadan.com MAIL FROM: kusuwadan@hoge.com RCPT TO: keigo.yamazaki@tsuribori.test DATA From: kusuwadummy@hoge.com To: keigo.yamazaki.dummy@tsuribori.test Date: 2016/1/21 Subject: hello, keigo! hello, hello! .
- これでWebメールチックに表示されている項目が一通り埋まりました。
- このどこかの項目に、XSSの穴がある!というのを、お題や経験から推測するらしいです。
- 穴が開いている項目を探すのに、下記のようなコマンドにして投げてみます
HELO kusuwadan.com MAIL FROM: <s>kusuwadan@hoge.com RCPT TO: keigo.yamazaki@tsuribori.test DATA From: <s>kusuwadummy@hoge.com To: <s>keigo.yamazaki.dummy@tsuribori.test Date: <s>2016/1/21 Subject: <s>hello, keigo! <s>hello, hello! .
- おお!Dateの項目が
<タグ>
内容を実行してしまってます!(打消し線が引かれちゃっている)エスケープとかいらないタイプの、割と大きめの穴だったようです。 - 喜んでばかりもいられません。ここからが本番。そう、目的はFlagをとること。
- 問題文にブラウザの名称(User-Agent)を答えよ。とあった。UserAgentがフラグになっているに違いない。
HELO kusuwadan.com MAIL FROM: kusuwadan@hoge.com RCPT TO: keigo.yamazaki@tsuribori.test DATA From: kusuwadummy@hoge.com To: keigo.yamazaki.dummy@tsuribori.test Date: <script>document.write( "UserAgent:", navigator.userAgent)</script> Subject: hello, keigo! Clear! .
Hey!Hey!来ましたよ!Google先生にUserAgent 取得
と聞いて最初に来たページを参考に書いたコードで行けるとは!
ということで、無事FlagGet!!
個人的にこの問題は、環境を整えてちゃんと問題のアプリケーションを動作させるまでが一番困ったけど、たぶんそのあと他の人のwrite-upを見てなかったらport25で何かがうごめいていることもわからなかったと思う。
SMTPプロトコルもXSSも書物で得たおぼろげな知識しかなかったので、実際に使ってみることができて大満足です。いい問題だった!
MacやLinux環境の人はどうやってこの問題に立ち向かったのか知りたい。
⇒と思ったら、去年.NETがオープンソース化してMacやLinuxディストリビューションがリリースされたっぽい。今度使ってみよう。
参考サイト(SMTP)
200_Fragment2
断片。名前からは何なのかさっぱり。
question.txt
Decode me fragment2.pcap
と、fragment2.pcap
という謎ファイル
初心者の野生の勘による足跡
- pcapというファイルは何なのか。packet captureの略かしら。
- 今回覚えたfileコマンド実行
$ file fragment2.pcap fragment2.pcap: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 262144)
- ほうほう、tcpdump capture fileってやつなのね。
- ちなみに、ググった感じ、packet解析は
wireshark
というのが一般的。私でも名前聞いた事あるくらい有名な感じ。 - それ以外の手段については、このスライドが面白かった
- ちなみに、ググった感じ、packet解析は
- なんかpcap形式とかよくわからんから、とりあえずお得意のlessしてみる
$ less fragment2.pcap
- 最後尾に
flag is in header
という文字列発見。何かのヘッダにFlagがあるようだ。 - ググった結果、
tcpdump
ファイルはtcpdump -r {file}
で読み込めるらしい - tcpdumpは基本headerを表示するので、
-X
オプションでbodyを表示、-v
オプションで詳細表示
$ tcpdump -r fragment2.pcap -Xv reading from file fragment2.pcap, link-type EN10MB (Ethernet) 17:36:42.312294 IP (tos 0x0, ttl 64, id 16901, offset 0, flags [DF], proto TCP (6), length 139) 10.128.0.10.http > 10.128.0.9.55956: Flags [P.], cksum 0x58bd (correct), seq 3101509738:3101509825, ack 1446096855, win 235, options [nop,nop,TS val 132536 ecr 132650], length 87 0x0000: 4500 008b 4205 4000 4006 e355 0a80 000a E...B.@.@..U.... 0x0010: 0a80 0009 0050 da94 b8dd 486a 5631 afd7 .....P....HjV1.. 0x0020: 8018 00eb 58bd 0000 0101 080a 0002 05b8 ....X........... 0x0030: 0002 062a 0000 3401 0400 0000 0288 c3c2 ...*..4......... 0x0040: 4085 f2b4 b40e 6f94 dd82 f5ed 5a7f ff63 @.....o.....Z..c 0x0050: ff7f eeb1 19b4 6a20 0fff 3ffd 0f0d 0231 ......j...?....1 0x0060: 37c1 c0bf 4089 f2b4 e94d 625a bb51 3f01 7...@....MbZ.Q?. 0x0070: 3100 0011 0001 0000 0002 666c 6167 2069 1.........flag.i 0x0080: 7320 696e 2068 6561 6465 72 s.in.header
- tcpdumpの出力の詳しい読み方を書いてくれているサイトがあったので、読みながらフムフムする。
- srcのportはhttp(80),dst側は55956らしい。プロトコルはTCP。
- この問題のタイトルに思いを馳せてみる。
fragment2
。2ですよ、2。 - ちなみに、上記サイトに気になる説明が。
[DF] means don’t fragment, so the packet is entire and not fragmented [F]
だそうです。このパケットはフラグメントではないそうですよ。ってかそもそもフラグメントって何?
ってな感じで、ネットワーク系の知識のなさが露呈しました。
ここから、他の方のwrite-upを見つつ、何言ってんのかさっぱりわからん!な部分を勉強した足跡をば。
お勉強
- まず、
http2
というのがキーワードのようです。私はものすごく物忘れが良いので、去年あたりに概要を聞きかじった気がするのですが、完全に内容を忘れていました。 - 上述の
flag is in header
という情報から、tcpdumpファイルをもう一度良く見てみる。が、httpってヘッダはtcpdumpしたときに、asciiで中身が全部見えるはずらしい。- 試しに
http://www.google.com
に接続したときのdumpをとってみた13:38:00.677878 IP (tos 0x0, ttl 52, id 8799, offset 0, flags [none], proto TCP (6), length 552) nrt04s06-in-f15.1e100.net.http > kusuwadaip.59215: Flags [P.], cksum 0x7d9f (correct), seq 1:501, ack 1162, win 388, options [nop,nop,TS val 64418957 ecr 163861156], length 500 0x0000: b88d 1218 a37a 0024 a5b9 c593 0800 4500 .....z.$......E. 0x0010: 0228 225f 0000 3406 6a53 adc2 7eaf c0a8 .("_..4.jS..~... 0x0020: 0b04 0050 e74f d9d2 b392 1846 5248 8018 ...P.O.....FRH.. 0x0030: 0184 7d9f 0000 0101 080a 03d6 f48d 09c4 ..}............. 0x0040: 52a4 4854 5450 2f31 2e31 2033 3032 2046 R.HTTP/1.1.302.F 0x0050: 6f75 6e64 0d0a 4c6f 6361 7469 6f6e 3a20 ound..Location:. 0x0060: 6874 7470 733a 2f2f 7777 772e 676f 6f67 https://www.goog 0x0070: 6c65 2e63 6f2e 6a70 2f3f 6777 735f 7264 le.co.jp/?gws_rd 0x0080: 3d73 736c 0d0a 4361 6368 652d 436f 6e74 =ssl..Cache-Cont 0x0090: 726f 6c3a 2070 7269 7661 7465 0d0a 436f rol:.private..Co 0x00a0: 6e74 656e 742d 5479 7065 3a20 7465 7874 ntent-Type:.text 0x00b0: 2f68 746d 6c3b 2063 6861 7273 6574 3d55 /html;.charset=U 0x00c0: 5446 2d38 0d0a 4461 7465 3a20 5375 6e2c TF-8..Date:.Sun, 0x00d0: 2032 3420 4a61 6e20 3230 3136 2030 343a .24.Jan.2016.04: 0x00e0: 3338 3a30 3020 474d 540d 0a53 6572 7665 38:00.GMT..Serve 0x00f0: 723a 2067 7773 0d0a 436f 6e74 656e 742d r:.gws..Content- 0x0100: 4c65 6e67 7468 3a20 3233 330d 0a58 2d58 Length:.233..X-X 0x0110: 5353 2d50 726f 7465 6374 696f 6e3a 2031 SS-Protection:.1 0x0120: 3b20 6d6f 6465 3d62 6c6f 636b 0d0a 582d ;.mode=block..X- 0x0130: 4672 616d 652d 4f70 7469 6f6e 733a 2053 Frame-Options:.S 0x0140: 414d 454f 5249 4749 4e0d 0a0d 0a3c 4854 AMEORIGIN....<HT 0x0150: 4d4c 3e3c 4845 4144 3e3c 6d65 7461 2068 ML><HEAD><meta.h 0x0160: 7474 702d 6571 7569 763d 2263 6f6e 7465 ttp-equiv="conte 0x0170: 6e74 2d74 7970 6522 2063 6f6e 7465 6e74 nt-type".content 0x0180: 3d22 7465 7874 2f68 746d 6c3b 6368 6172 ="text/html;char 0x0190: 7365 743d 7574 662d 3822 3e0a 3c54 4954 set=utf-8">.<TIT 0x01a0: 4c45 3e33 3032 204d 6f76 6564 3c2f 5449 LE>302.Moved</TI 0x01b0: 544c 453e 3c2f 4845 4144 3e3c 424f 4459 TLE></HEAD><BODY 0x01c0: 3e0a 3c48 313e 3330 3220 4d6f 7665 643c >.<H1>302.Moved< 0x01d0: 2f48 313e 0a54 6865 2064 6f63 756d 656e /H1>.The.documen 0x01e0: 7420 6861 7320 6d6f 7665 640a 3c41 2048 t.has.moved.<A.H 0x01f0: 5245 463d 2268 7474 7073 3a2f 2f77 7777 REF="https://www 0x0200: 2e67 6f6f 676c 652e 636f 2e6a 702f 3f67 .google.co.jp/?g 0x0210: 7773 5f72 643d 7373 6c22 3e68 6572 653c ws_rd=ssl">here< 0x0220: 2f41 3e2e 0d0a 3c2f 424f 4459 3e3c 2f48 /A>...</BODY></H 0x0230: 544d 4c3e 0d0a TML>..
まぁリダイレクトされてますが、こんな感じで見えるはず、と。https(port443)の場合はもちろんそのままでは見えません。
- 試しに
- で、これってhttp1.1までの話だそうで。http2.0からはひと味違う!っちゅーのが今回の問題の作者も伝えたかった事のようです。
- ということで、HTTP2をお勉強しました。HTTP/2 入門(http2の基礎がわかりやすく書かれています)
- 今回必須だった知識としては、headerに関する変更点
- http2ではheaderを圧縮して通信していること
- その圧縮形式は
HPACK
というヘッダー圧縮形式であること
これくらいがわかった所で、解法
- 世の中のネットワークエンジニア的には常識らしいので、
wireshark
をインストール - Wiresharkを立ち上げて、問題のファイル(fragment2.pcap)を開く。
- 分析 ⇒ ...としてデコード ⇒ 現在のプロトコルをHTTP2に変更
- すると、詳細表示の最下部に、HTTP2用の記述が増える。
- 残念ながらHeaderの中はこんな感じに出ており、Statusしかわからない。
- ここで選択されている
Header Block Fragment
がHPACKで圧縮されているそうなので、これをhpack decodeする - ちらっと探した感じ、pythonとgoで出ているhpack decoderが割と使われていそう
- とはいえ、ここまでrubyで通してきたので、他の言語への浮気はなんだか癪。ということで、ruby gem hpackを使ってみる。version 0.0.1 & commiterが1人 & totak commit 9回!と、そこはかとないβ感が気になりつつ、下記のように使ってみました。
require 'hpack' def input_fixture data io = StringIO.new io.write [data.gsub(/\s/, "")].pack "H*" io.rewind io end io_stream = input_fixture "88 c3c2 4085 f2b4 b40e 6f94 dd82 f5ed 5a7f ff63 ff7f eeb1 19b4 6a20 0fff 3ffd 0f0d 0231 37c1 c0bf 4089 f2b4 e94d 625a bb51 3f01 31" decoder = Hpack::Decoder.new decoder.decode io_stream do |header, value, metadata| puts "#{header}: #{value}" end
io_stream
はベタに、先ほどwireshark様がHeader Block Fragment
に対応するとおっしゃっていた箇所の16進表示をコピペ。
- すんなり動いてくれれば良かったのですが、
IndexOutOfBounds
とか踏んじゃってちょっとずつしかdecodeしてくれないので、入力streamを前から少しずつへつりながら解読しました。gemのバグなのか、まだ私の知らない情報が上記のデータ列に入っているのか。。。全部問題といたら戻ってきたいくらいのもやもや感を残しつつ、一応flagはget。 - 一応取り出せたheaderの中身はこんな感じ
:status: 200 x-flag: SECCON{H++p2i5sOc0o|} content-length: 17 refresh: refresh: 17???@???MbZ?Q?1??j ???
フラグのメッセージ:Http2 is so cool
Binary
バイナリ関連。Reverse-Engineeringとかした事ない。
100_Reverse-Engineering Android APK 1
まずは100点問題から
question.txt
Please win 1000 times in rock-paper-scissors rps.apk じゃんけんに1000回連続で勝ち続けよ rps.apk
と、rps.apk
○回解けのパターン来ましたよ!しかも勝ち続けないといけないようです。
初心者の野生の勘・・・は効かなさそうなので、まずは対象を観察
- Android端末に入れて遊んでみる
- 何の映像も説明もないが、
R
(グー),P
(パー),S
(チョキ)のボタンの中から一つを選ぶとCPUも手を出してきて、勝ち負け判定と連勝カウントが表示される。ちなみに、引き分けでも連勝カウントはリセットされないようだ。 - CPU後出しなので、上記のQRコードパズルのように遊び自体を自動化して勝ち続けるのは無理っぽい。
- 何の映像も説明もないが、
- fileコマンド
$ file rps.apk rps.apk: Zip archive data, at least v2.0 to extract
- ふむふむ、apkってzipだったかいね?と思いつつ、解凍してみる(apkはzipとして解凍も出来るらしい)
- 構成的には、普通のAndroidApplicationのように見える。動いたしそりゃそうか。
- 普段はAndroidAppは人が作っているのを端から見る程度ですが、なんと
AndroidManifest.xml
とかがバイナリ化されているらしく、全然読めない。わーお。
勉強しながらの解法
- Android apkをdecompileしてみるのが定石らしい
- ということで、上記の手順で
rock_paper_scissors
というsrcディレクトリ配下にいたclassファイルがjavaに変身を遂げました。やったー!Reverse-Engineeringっぽい!
$ grep 1000 ./*.java
で、このjavaソース内から1000回判定を探してみる。./MainActivity.java: if(1000 == cnt)
が引っかかりました!ここだ!
$ less MainActivity.java /1000 # でソース内の場所を特定
if(1000 == cnt) textview.setText((new StringBuilder()).append("SECCON{").append(String.valueOf((cnt + calc()) * 107)).append("}").toString()); flag = 0; }
フラグのにおい!String.valueOf((cnt + calc()) * 107)
=(1000 + calc() * 107)
がフラグの中身ですね!
calc()
を捜索。MainActivity.java内ではSystem.loadLibrary("calc")
らしいので、native libraryの中にあるようだ。- 上記apkを解凍したときに出てきた
lib
ディレクトリに、libcalc.so
君がいる。きっとこれだ。 - しかしここでまた問題が。
.so
ファイルもバイナリじゃん。Toolは沢山ありそうだけど。 - どうやらsoファイルは
objdump
というので逆アセンブルするのが一般的らしい - macにbrewでobjdump入れてみた
$ gobjdump -d libcalc.so > dump.txt
dump.txt
を開いてみると、アセンブルっぽいのがずらーっと。長い。こんなに読めん。- セクションがいくつかある
セクション .plt の逆アセンブル
: .pltはProcedure Linkage Table が置かれる場所らしい。今回はひとまず無視してよさそうセクション .text の逆アセンブル
: .textはプログラム本体らしい。今回はここだけ見る。
- .textのなかにも、二つブロックが。
Java_com_example_seccon2015_rock_1paper_1scissors_MainActivity_calc-0xc0
Java_com_example_seccon2015_rock_1paper_1scissors_MainActivity_calc
- 他の方のwrite-upを見ると、下の方だけ見れば良いらしい。この辺の読み方はまだまだわかっていないので、今度自分で組んだプログラムを逆アセンブルしながら見ておきたい。
00000400 <Java_com_example_seccon2015_rock_1paper_1scissors_MainActivity_calc>: 400: b8 07 00 00 00 mov $0x7,%eax 405: c3 ret
mov src,dest
はsrcオペランドをdestオペランドにコピー(GAS文法)
らしいので、7を汎用レジスタeax
に代入してreturn
ということで、このcalc関数はただ7が返るらしい。
(cnt + calc()) * 107 = 1007 * 107 = 107749
Flagの内容と合致。
200_GDB Remote Debugging
※この記事は解まで到達しておりません
- GDB? グレート デンジャラス バイナリ?
- Remoteってところがちょっと不安。
question.txt
Decode the key putskey log.txt
シンプル。これと、putskey
, log.txt
初心者の野生の勘による足跡
- ここまで来ると、問題のタイトルが重要な意味を持っている事は察しがつく。
- まずはどこかで聞いた事ある気がする
GDB
をググってみる。Wikipedia先生GNUデバッガ(単にGDBとも)は、GNUソフトウェア・システムで動く標準のデバッガである。 これは、多くのUnix系システムで動作可能な移植性の高いデバッガであり、Ada、C言語、C++、FORTRAN、FreeBASICといったプログラミング言語に対応している。
- ふむ、なるほど。もちろん使った事はない。今回はこれを使うのかしら。
- 与えられたものを確認
$ file putskey putskey: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.18, from 'p) 4@%edi 4@$0', not stripped
- 【熱血クロスコンパイル環境】で実行してみる
$ chmod 755 putskey $ ./putskey
- なんか入力待ちっぽかったので、
a\n
,b\n
を入力してみる。何も起きずにプログラム終了 - どうやら2度入力を受け付けて終了するようだ
- よっしゃ!逆アセンブルじゃ!
$ objdump -d putskey
止まる事のないdump...こんな量読めるかい!!!
log.txtを読んでみる
- そういえばもう一つファイルが渡されていたのであった。
log.txt
を開いてみるSending packet: $m80483e0,1#66...Packet received: 55
的なのが並んでおる。通信ログっぽい。- タイトルがGDB Remote Debuggingという事なので、GDBのリモートデバッグログなのでしょう、という事でググってみる。
- 私的 GNU マニュアル翻訳プロジェクト
- GDB 5.0 > デバッグ・ターゲットの指定 > リモート・デバッギング >
通信プロトコル
こちらを参考に読み解けそうである。
読み解けそうでは、ある。
- GDB 5.0 > デバッグ・ターゲットの指定 > リモート・デバッギング >
通信プロトコル
こちらを参考に読み解けそうである。
......
だいぶ読み進めては見たものの、「ほーん」という感じ。この分野はまだまだ修行が足りないようだ。
ちなみに、他の方のwrite-upも拝見してみたが、エスパーとしか思えない。
どうやってputskey
の中身を読んだのか、あまりにも当然の事のように書いてあったり。
もしかして、上記でやったdumpファイルを読み解くの?他に便利ツール・コマンドがあるの?
という事で、binaryに強くなりたくなった時が来たら続きをやってみる。。。かも。
200_Individual Elebin
えれびん。
question.txt
Execute all ELF files Individual_Elebin.zip すべてのELFファイルを実行せよ Individual_Elebin.zip
と、Individual_Elebin.zip
初心者の野生の勘による足跡
Individual_Elebin.zip
を解凍してみると、1~11のバイナリファイルが現れた。- よし、とりあえず全部の種類を見てみよう
$ file 1.bin 1.bin: ELF 32-bit LSB executable, Intel 80386, version 1 (FreeBSD), statically linked, stripped $ file 2.bin 2.bin: ELF 32-bit MSB executable, version 1 (SYSV), statically linked, stripped $ file 3.bin 3.bin: ELF 32-bit LSB executable, NEC v850, version 1 (SYSV), statically linked, stripped $ file 4.bin 4.bin: ELF 32-bit MSB executable, Renesas M32R, version 1 (SYSV), statically linked, stripped $ file 5.bin 5.bin: ELF 64-bit MSB executable, Renesas SH, version 1 (SYSV), statically linked, stripped $ file 6.bin 6.bin: ELF 32-bit MSB executable, SPARC, version 1 (SYSV), statically linked, stripped $ file 7.bin 7.bin: ELF 32-bit LSB executable, Motorola RCE, version 1 (SYSV), statically linked, stripped $ file 8.bin 8.bin: ELF 32-bit LSB executable, Axis cris, version 1 MathCoPro/FPU/MAU Required (SYSV), statically linked, stripped $ file 9.bin 9.bin: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, stripped $ file 10.bin 10.bin: ELF 32-bit LSB executable, ARM, version 1, statically linked, stripped $ file 11.bin 11.bin: ELF 32-bit MSB executable, MIPS, MIPS-I version 1 (SYSV), statically linked, stripped
見事に全部違う!
クロスコンパイル環境で実施!解法
- もう私には【熱血クロスコンパイル環境】がある!
Micro computer exploit code challenge
で整えたVM環境を使って片っ端から実行してみる- 上の
file
コマンド結果より、それぞれ実行してみる。どのバイナリが何用かは、調べつつ試しつつ。
$ pwd /usr/local/cross-gcc4/bin $ ./tmp/elebin/1.bin SECCON{AaA $ ./850-elf-run ~/tmp/elebin/3.bin i $ ./m32r-elf-run ~/tmp/elebin/4.bin N $ ./sh64-elf-run ~/tmp/elebin/5.bin 12345678 $ ./sparc-elf-run ~/tmp/elebin/6.bin 90abcdef $ ./cris-elf-run ~/tmp/elebin/8.bin AW $ ./avr-elf-run ~/tmp/elebin/9.bin 3a5d37a3 $ ./arm-elf-run ~/tmp/elebin/10.bin 8a0d28f $ ./mips16-elf-run ~/tmp/elebin/11.bin aAq}
- とりあえずこんだけとれた。
}
で終わっているので、順番につなげるようだ。 file
の結果から推測できる実行ファイル名に、大体なっていて感動。- 2.binと7.binがどれも合わなかったので、上述のwrite-upサイトに従って
FreeBSD
インストールイメージを同サイトからDL。 - VirtualBoxで立ち上げてみて、同様に実行してみる
% pwd /usr/local/cross/bin % ./m6811-elf-run ~/tmp/elebin/2.bin B % ./mcore-elf-run ~/tmp/elebin/7.bin BDFHJLNP
よしよし、すごい。全部出てきた。 * 1から順につなげてみる。あってるかな?
`SECCON{AaABiN1234567890abcdefBDFHJLNPAW3a5d37a38a0d28faAq}``
あってた!最長flagかも
300_Exec dmesg
いきなりググりました。
【 dmesg 】カーネルのリングバッファの内容を出力するlinux command.
question.txt
Please find secret message from the iso linux image. image.zip 秘密のメッセージをLinuxのisoイメージの中から見つけてください。 image.zip
と、image.zip
初心者の野生の勘による解法
- image.zipを解凍すると、
core-current.iso
が現れた。
$ file core-current.iso core-current.iso: ISO 9660 CD-ROM filesystem data 'TC-Core ' (bootable)
- isoイメージという事でlinux iso tc-coreというキーワードでググってみると、Tiny Core LinuxというLinuxディストリビューションの1つらしい
- VirtualBoxで立ち上げてみる。こんなん出た
- CUIらしいのでこのまま使ってみる。とりあえず近辺の階層をうろうろして、何か落ちていないか探していく
- 割と何もないので、rootに行ってみると、超怪しいもの発見
- しかし、lessして検索してみてもgrepしてみても、このファイル内にはフラグ文字は見つからず。
- ええい!と、下記を実行してみる
$ sudo grep -rs SECCON / /home/tc/.ash_history:sudo grep -rs SECCON / /proc/kmsg:<7>SECCON{elf32-i386}
※-s
オプションをつけないと、エラーメッセージが大量に出てきて埋もれてしまった。。
* まさかの出てきてしまった。。あれ、dmesg
は?
納得いかなかったので、タイトルを意識した解法
$ dmesg dmesg: applet not found
あーはん。このイメージでは、dmesgが有効になっていないみたい。
前述の通り、【dmesg】
はカーネルのリングバッファの内容を出力するコマンドらしいので、この内容が他のどこかに書かれていれば問題ない。
* またググってみる
* > システムログはコンソールデバイスに表示されますが、dmesgコマンドおよびcat /proc/kmsgで仮想端末に表示することも可能です
* なるほどー!じゃあ得意のやつで
$ sudo less /proc/kmsg : /SECCON
でたよー!前の解法よりはスッキリ!!!
400_Reverse-Engineering Hardware 1
※この記事は解まで到達しておりません
ハードは全く専門外なのだけど、どうなる事やら
question.txt
We've found some pictures of a decoder board and a program to produce a nice text. Please help us to get the text. gpio.py ChristmasIllumiations.zip 私たちはデコーダーボードの写真と、すてきなテキストを生成するプログラムを入手した。 解読のお手伝いをしてくれない? gpio.py ChristmasIllumiations.zip
と、gpio.py
,ChristmasIllumiations.zip
。やけにフレンドリーな問題文。
初心者の野生の勘による足跡
ChristmasIllumiations.zip
を解凍してみる。jpegとm4vファイルが大量に出てきた- 静止画はすべて、ブレッドボードの上に導線とLEDが刺してある。すごい色んな角度から撮られているので、きっと配線とか分析するんだろう。
- 動画を見てみる。LEDがちかちかしとる。規則正しいような、そうでもないような。
- 写真を見ながら、配線の確認+回路図の作成をしていくものらしい
pythonコード
- gpio.pyを分析してみる。
- 最終行に
print "The flag is SECCON{"+flag+"}"
とある!flag
変数に何が入るか分かれば良いのね - コードの中で、ハードと関係ありそうな
RPi.GPIO
が何者かググってみる
どうやらRaspberry Piの汎用入出力コネクタGPIO
をPythonで操作するためのライブラリらしい - GPIOの使い方はここを参考にした
GPIO.setmode(GPIO.BCM)を選んだ場合、ピン番号ではなく役割に記載されたGPIOの数字で指定することになります。
- とのことなので、番号は全部GPIO番号。
- inputが
X1~X6
, outputがCLR,CLK,DA,DB
- encode関数は、ばらすと
32X1 + 16X2 + 8X3 + 4X4 + 2X5 + X6
になる - ロジックはそのままで、GPIOで入出力している箇所を置き換えたら答えが出てきそう
RaspberryPiのピン配置対応表作成
- 写真を目を皿にして眺める。密集していてよくわからん。目に悪い問題だ。
- いい感じに写真がぼけてくれているおかげで、ぼけの度合いから配線がたどりやすかった。
- ピン配置を確認しようと思ってRaspberryPi公式ページを見てみたのだけど、ピン番号しか載ってなかったのでこちらのサイトを参考にさせていただきました
ブレッドボード分析
- LEDは、RaspberryPi側(手前)に7個、奥に4個
- 7個の方は、それぞれ3つの抵抗と黒い謎の物体が刺さっている。
- 4個の方は、抵抗が1個ずつ
- なんかチップっぽいのが刺さってる。読み取れたのは
JAPAN 23H
,74HC74AP
CMOS Digital Integrated Circuit Silicon Monolithic Dual D-Type Flip Flop Preset and Clearらしい。フリップフロップ。 - もう、、むり、、めんどくさい。。。そういえば、大学のときも電子回路嫌いだったなぁ。。。
ということで、この問題はギブアップ!後追いで更に他のwrite-upを見ながらでもOK!という状況にも関わらず。
面倒なのは嫌いなんです。もし万が一気が向いたら、続きをやってみようかな。
500_Reverse-Engineering Hardware 2
※この記事は解まで到達しておりません
もう、ギブアップしたHardware 1より配点高いし、やめとこうかな。。。
という考えが頭をよぎったが、戦わずして負けるのは悔しい!という事で見るだけ見てみる事に。
question.txt
We've found an encoder board using double 74HC161s along with a binary file. Please help us to decode it. gpio2.py encripted counterhardware.zip 我々は2つの74HC161を使ったエンコーダーボードによるバイナリを入手した。 復元を手伝ってほしい。 gpio2.py encripted
と、gpio2.py
、encripted
、counterhardware.zip
Hardware1とほぼ同じ予感
初心者の野生の勘による足跡
- きっと配線の写真だろうと思いつつ、
counterhardware.zip
を展開 - やっぱり配線の写真がいっぱいと、動画が一個。さっきよりブレッドボードのフィールドは小さそうだ
- 謎のファイル、
encripted
を調べてみる
$ file encripted encripted: data
すごいあっさり!バイナリデータだったけど、サイズはかなり小さめ。
- pythonコードを確認
- このコードの引数は
rfd
(read file),wfd
(write file),len:繰り返し実行回数
のようだ a2v
関数は、先ほどのencode
関数と同じ感じ。rfd.read(1)
という事で、rfdファイルから1バイトずつ読み込み- 与えられた内容から、rfdとして食わせるファイルは
encrypted
と推測
- 与えられた内容から、rfdとして食わせるファイルは
d += struct.pack('B', ord(v) ^ value)
wfd.write(d)
で、上記のdをファイルに書き出すらしいsetValue(value)
で、reset -> value回pulseを送るらしい
- このコードの引数は
さて、なんとか回路を見ずに解く方法はないものか。
指定した出力ファイルにフラグが現れるとするならば、
wfd.write(d)
の出力はSECCON{
で始まるはず。- という事で、
SECCON{
から始まるテキストが出力される事を前提として、value
に何が入るのか見るプログラムを組んでみた
import sys import struct rfd = open(sys.argv[1], 'rb') seccon = "SECCON{" # main for i in range(len(seccon)): v = rfd.read(1) number = struct.unpack('B', seccon[i])[0] # ord(v) ^ value value = ord(v) ^ number print format(value,'08b')
実行結果
$ python test.py encripted 01001100 01001111 00001001 11101001 10000001 01110010 11010110
う、うむ。そうか。特にこれというパターン見つからず。ギブアップ。
その後、他の方のwrite-upを見てみると、どうやら出力はテキストファイルじゃなかったらしい。 こういう事もあるよね。うん。
おわりに
- セキュリティの〜とかハッキングの〜とかすごい難しそう!無理無理!と思っていたけど、意外と親しめた(write-upをかいてくださっている皆様のお力による所が大きいです)。
- 新しく出会った用語やツール・OSコマンドも多く、とても為になる楽しいお遊びでした。
- 自分が得意(少なくとも問題の意図が分かるくらいに)な分野・全くわからない分野を知る事が出来たので、後追いでやっても大変意義があったように思う。また、わからない分野も、目的を持って調べたり学んだりできるので、私のような勉強嫌いには知識と経験をつける良い機会でした。
- 一部の問題が後追いだと出来ないのが残念。期間限定公開の環境を使うやつ。まぁでもgithubに全問上がってるだけでも感謝。