好奇心の足跡

飽きっぽくすぐ他のことをしてしまうので、忘れないため・形にして頭に残すための備忘録。

SECCON 2015 Online CTF を、後追いでみっちりやってみよう!

はじめに

この記事は、SECCON 2015 Online CTFの問題集が公開されているので 、後追いで、勉強がてら調べながらやってみた記録になります。
SECCONという楽しそうなものがあるらしいというのを丁度2015年の年末に知った、ただの謎解き好きの挑戦記録のため、超初心者目線です。
近い将来リアルタイムで参加できるようになるために、環境を整えたりわからない事を調べたりまとめたりしながら進めております。

  • ネタバレなので閲覧の際はご注意ください。
  • 問題集(解答付き)はこちら
  • タイトルに■がついているものは、後追いでは出来ない問題です。
    • □になっているものは、気合いと根性の別解で何とか解けた/解けそう
  • タイトルに▲がついているものは、コンテスト当日の環境が閉じられているものの、buildという環境再現用のソースがセットで公開されている問題です
    • △になっているものは、buildの中身から環境構築成功、解けた/解けそう
    • 環境構築のためにソースを読んでると、うっかりフラグが見えてしまうので注意
  • やりながら、便利ツール・解読ツールを作ったら下記にupしていきます。
  • 他にも実際にリアルタイムで参加された方のwrite-upや、後追いでやってみた本格的な記事もあるので探してみてください。

SECCON online CTF とは

  • SecCon CTF 日本公式ページ
    • Security Contest Capture the flagの略
    • 問題が出されて、その中からflagを探す競技だそうです
    • ちなみに2015年からリンクがないですが、下記の要領で増えていくようです
  • 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 で検索の結果、下記が引っかかる
  • 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の暗号文を計算出来る(加法準同型性)という性質を満たす

    • 暗号の名前らしい!数式がずらーーーーっと並んでおる
  • 大会当時の気持ちになってみる。question.txtの2行目のリンクにアクセスすると、pq.cgi.txtがゲットできたのではなかろうか
    • questionのpq.cgiはq.cgiの間違いだった(もしくはq.cgiが本当はpq.cgiだった)事にして進めてみる
    • という事は、参加者はpq.cgiのコードは読める状態だったという事になる
    • 中で参照している、access.jsondata.jsonがないので、実行はできない
    • ちなみにコードを読むとすぐにdata.jsonにフラグがいるのが分かるのだが、見なかった事にする

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_STRINGv["num"]と合っていれば、フラグを出力してくれるらしい
  • waccess.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

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

無事判定を通り抜けてフラグが出力されました。長かった。。。

参考サイト

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形式のバイナリを開発する方法はいくつか見つかったが、実行する方は見つからず。ということで、ここからMacOSVMで動かしている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まで確定
  1. 最初の試行で桁数が揃っていそうなので{}の中は25文字かな。
  2. key全体のうち、わかっている`SECCON{'の部分までの出力は一致しているので、前から暗号化してるっぽい。25文字程度なら、総当たりで前から攻めていってよさそう。
  3. 出力の(**)部分が3つおきに変わり、4の倍数。
    出力の雰囲気からbase64エンコードされているような気配がしたが、そのままデコードできなかったのでまぁいいや。
  4. 上記を考慮して下記のようなスクリプトを作成。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にこんな説明が
    1. Your team can upload different 2 files of same MD5.
    2. After your team uploads your files, you will not be allowed to upload again for 1 hour.
    3. All files will be ranked by its code size.
    4. 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を見ながらやってみることに。

ヒント・解法

  • 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を横目で見つつ、どうすれば良かったのかをなぞってみる。
  • やっぱり最後の方の並びがおかしいのは注目すべき点だったらしい。あそこの部分に何か隠されているとして
    1. メタとして抜き出し可能(pngフォーマット内のタグは一通り確認したが、なかった)
    2. 画像ファイルに続きがある(領域外に書いてある。これは盲点だった!)
  • 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.pngpng率高し。

初心者の野生の勘による足跡

  • まずは素直に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変換スクリプトを作成
    • srcはこちら
    • 使用例はこちら
    • 実は4042.txtの中にUTF-9 文字列から UCS-4 値を返却する (C 版)という章があってコピペですんだっぽいのだけど、折角後追いで時間がある&UTF8の作り方もよくわかっていなかったので、rubyで作ってみました。
  • 問題文は上記の観察の結果8進数で書かれているっぽいので、これを3文字ずつ取得してbit列に変換するとnonet(9bitのブロック)に
  • このbit列の先頭bitが、1文字を表現する際に次のbit-groupを使うかどうかのフラグになっている、との説明だったので、先頭bitが1なら次のnonetを同じ文字の続きとして処理、0ならそこで文字終わり、というように処理していく。
  • 残った8bitをUTF-8のbitになるらしいので、上記処理でUTF-8にして読んでみる。
  • 結果、下記のような出力になった。実は表示できていない文字がフラグの中に2カ所。一つは想像で補えたが、もう一つは無理かも。この問題は自力で解けるかも!と息巻いていたのだが、下記の出力を見てやり方が間違っている部分があったかもと思い他の方のwrite-upを見てしまった。 unknown_4042_flag
  • 残念ながら、不明な2文字はなぜ解答のように見えるかは不明なまま。
  • 古代遺跡云々は関係なかったらしい。。。

参考にさせていただいたリンク

■ 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をとにかく実行してみる。こんなのが出現! qrpuzzle
  • どうやらパネルを並び替えてQRコードを完成させるようだ。選択したパネル同士を置換できるので、そんな感じで一度遊んでみる。
  • 完成したのに何も起きない。よく見ると、下の方にAnswerという何か欲しそうなフォームがいる。QRコードを解釈して出てくるメッセージ的なものをここに入れるのか、と思いやってみる。
  • 今回のパターンだとsoundでした。入力すると次のが出てきた。ふむふむ、これを300回解けってことね。上の方にバーがあって、一回解くと少し進んだ気がする。
  • アプローチとしてはこれくらいのパターンがありそう。
    1. 300回ぽちぽち解く。。。気合いだ!!でも300回ならやれそうな気もする。。。
    2. 300回解くプログラムを組む
    3. 実行ファイルをいじって数回でflagが出てくるようにする
    4. 実行ファイルを解析してflagを見つける
  • 1.の解法が実は一番早いかもしれない、と思わせる繰り返し回数(300回)
  • 競技中だとすると、残り時間と自分の担当問題数(複数人でやってればですが)とを考慮して、最速で解けそうなものを選択するんでしょうが(私の場合アセンブラ的知識0なので多分1.)、今回は2.を作ってみたくなったので2でやってみる事にしました。
  • ruby暦浅いので、画像処理をどれだけrubyでお手軽にできるか試してみたかったのと、QRコード+rubyの相性を知っておきたかったという意図もあり。

解法

上記の環境を整えて、いざパズル自動で解く君を作成。
流れ的にはこんな感じでしょうか。

  1. capture window.
  2. make qr code.
  3. read qr code.
  4. fill answer form.

  5. 1,2は好きな分野だったのでさくさくっと。rmagick便利。

  6. rubyでQRコードの読み取りはちょっとはまったのでメモを残した
  7. 4.が超苦労した。wineで実行している事もあってか、出来そうで出来ない事多し。
    • 開いているウィンドウの中から、ターゲットウィンドウを指定してテキストを送る、というのがなかなか。
    • Application名はwine?でもwineは沢山開いているので指定が難しそう。Window名を指定してみたり。。。という試行錯誤を下記に残しました。
    • rubyからmac上で実行中のアプリケーションを操作
    • 何とかあきらめずに全自動になった。よかった。
  8. コード完成!!ぱんぱかぱーん!!実行!!!
    • ドキドキしながら実行
    • なんとか動いてくれるが、文字の入力時にいっぺんに送ると何文字か飛ばして入力しちゃう。かわいらしい。実際に競技中だったら憎たらしいに違いない。1文字ずつdelayしながら入力させる事に。
    • Answer入力後の画面切り替えに結構時間がかかる事が判明。5秒delayを入れても時々間に合っていない。
    • 色々delayやヒストグラム値の調整をして、いざ走らせる。
    • よちよち実行している感じ(遅い)でかわいらしい。が、遅いよ遅い。。。コーディング時間と実行時間足したら、全部手動で実行した方が俄然早かったと思われる。
  9. 300問達成!すると、Answer部分にFlagが現れた!感動!記念にスクリーンショット。結局delayが効いて、300問に40分近くかかったんではなかろうか。 qrpuzzle_flag
  10. この問題に超特化してますが、折角作ったかわいい子なのでコードをアップしてみました。
  11. このスクリプトの大きな問題点は、実行している間他の作業が同じマシンでし辛い(というかほぼ出来ない)こと。見守るだけ。折角自動化したのに・・・笑

■ 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.pyweb/の中
$ 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の中身。その後、bundlefを表示しているようです。

  • とりあえず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...って何だっけ?
ググってみると、意味はいくつかありそうだ。
ちょっと問題を眺めた後、一番適切そうな解説

中央処理装置や記憶装置などを,一個から数個の LSI チップによって実現した,ごく小型のコンピューター。マイコン

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では、今後も色んなコンピュータアーキテクチャの実行ファイルがぽいっと渡されることあるかも?と思い、クロスコンパイル環境を整える事に。

ロスコンパイル環境を整えて実行してみる

$ 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を解析してみる

$ 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.cppvulnserverbuildフォルダ。

buildフォルダはREADME付きで親切な感じ。。。
だが、「どうせvulnserverの逆アセンブルとか出てくるんでしょ」という気持ちになっており。
このジャンルほんと厳しーわー、、、と思っている所への500点問題ということで、パスッ!

Web_Network

Network系。配点が低めのものが多い。

▲ 100_Connect the server

サーバにつなげるだけ?

question.txt

login.pwn.seccon.jp:10000

一行!
と、buildフォルダ。その中にMakefilemylogin.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(家族マシン)を借りてやってみる事に

===仕切り直し===

  • 再度hakoniwaWebMail.exeを実行!
  • 同じ画面が出た後、なんとWebっぽいアプリケーション(っぽい)ものが立ち上がる
  • そしてID,Passwordを入力画面になり、勝手になんか入れられた後Webメール画面が表示される bonsai_webmail
  • 画面をつんつんしてみると、You can NOT operate anything.ですって
  • アドレスバーらしきものにhttps://tsuribori.test/webMailと出ていたのでアクセスしてみる。・・・つながらず。
  • 先に解き方をちら見してしまっているので、そこで得た下記の情報をもとにやる。
    • アプリ内で25番ポートにメールサーバーっぽいのを立ちあげてるらしい
    • XSS攻撃をたくさんしてみる問題らしい
  • とにかくつないでみようということで、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!
.

bonsai_normal

  • これで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!
.

bonsai_find

  • おお!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も書物で得たおぼろげな知識しかなかったので、実際に使ってみることができて大満足です。いい問題だった!
MacLinux環境の人はどうやってこの問題に立ち向かったのか知りたい。
と思ったら、去年.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というのが一般的。私でも名前聞いた事あるくらい有名な感じ。
    • それ以外の手段については、このスライドが面白かった
  • なんか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しかわからない。 wireshark-http2-header
  • ここで選択されている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とかがバイナリ化されているらしく、全然読めない。わーお。

勉強しながらの解法

$ 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を読んでみる

......

だいぶ読み進めては見たものの、「ほーん」という感じ。この分野はまだまだ修行が足りないようだ。
ちなみに、他の方の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で立ち上げてみる。こんなん出た core-current
  • CUIらしいのでこのまま使ってみる。とりあえず近辺の階層をうろうろして、何か落ちていないか探していく
  • 割と何もないので、rootに行ってみると、超怪しいもの発見 find_SECCON
  • しかし、lessして検索してみてもgrepしてみても、このファイル内にはフラグ文字は見つからず。
  • ええい!と、下記を実行してみる
$ sudo grep -rs SECCON /
/home/tc/.ash_history:sudo grep -rs SECCON /
/proc/kmsg:<7>SECCON{elf32-i386}

-sオプションをつけないと、エラーメッセージが大量に出てきて埋もれてしまった。。 * まさかの出てきてしまった。。あれ、dmesgは?

納得いかなかったので、タイトルを意識した解法

  • vmでTiny_Core_Linuxを立ち上げたとこから再開
$ 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の汎用入出力コネクタGPIOPythonで操作するためのライブラリらしい
  • 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.pyencriptedcounterhardware.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と推測
    • d += struct.pack('B', ord(v) ^ value)
      • pack関数は、文字列や数値をバイナリに変換するらしい。
      • struct.pack(fmt, v1, v2, ...)で、フォーマットはB(unsigned char)
      • ord:長さ 1 の与えられた文字列に対し、その文字列が unicode オブジェクトならば Unicode コードポイントを表す整数を、 8 ビット文字列ならばそのバイトの値を返します。 だそうです。
      • ord(v) ^ value^はビットXOR演算子らしい
    • 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に全問上がってるだけでも感謝。

SECCON参加にあたって必要と感じたもの