2012年5月13日日曜日

SECCON CTF 2012/2/18-19 Binary 300 Devide Section

問題:「キーを見つけろ」
まず最初に、説明が長い割に適当なので根気強く見てください(笑)。

問題のzipファイルをダウンロードし、中身を開くと
5つのバイナリファイルが入ってる。
#ファイル名は何を意味するんだろうか。謎だ。
これをバイナリエディタで見ると以下のようになる。
図1

左の2つのファイル(MILEENA.binとPITS.bin)の先頭を見るとMZとPEのマジックがあるので、明らかに Windows PE(Protable Executable)、つまり実行ファイルに関係することがわかる。また右下のREPTILE.binにはKERNEL32.dllの文字列が現れているのでインポートするWindows APIを表していることが伺える。
ここで、問題の名前、Divide Sectionから予想するにPEファイルがSectionごとに分割されていて、おそらくそれを結合すればキーが得られるという仕組みだと疑う。
またPEは
  • MZヘッダ
  • PEヘッダ
  • セクションテーブル
  • セクション1
  • セクション2
  • ...
のフォーマットとなっていることからもこのSecitonを意味している可能性が高い。
早速、この順番に結合してみたが(やはり)実行はできない。
#ここからバイナリエディタとの格闘が始まるのであった。

この分割されたデータを復元するにはSectionのデータをファイル内の正しいアドレスに書き込む必要がある。PEファイルを実行するときはそういったアドレスを参照しながら自分の中にどういうデータがあり、どこに格納されているかを知るのである。
#ちなみにぼくはアナライジング・マルウェアという本を参考にしました。著者の方々、ありがとうございます。

上の図はPEヘッダ(PITS.bin)で実行のヒントとなる部分をマークしたものである。
???の部分はおそらくIAT(Import Address Table)だと思われるが、確信がない。
こう見てみると、大事なところがDE AD BE EFでかき消されていることがわかる。

まず、PEヘッダ内のSection情報をもとに各セクションを復元する。
図中に示されていないNumberOfSectionという場所が0x03であることから残りの3つのファイルがそれに当たると察し、さらに残りのファイルのバイナリから予想して、それらは text(コード領域)、rdata(インポートする関数を並べる領域?)、data(データ領域)だとする。
ここでSection name領域の後のメモリにロードされたときのサイズとアドレス(緑線)と、ディスク上でのサイズとアドレス(青線)が大事となる。
例えば、先頭のtextセクション(file offset: 0xF8)の
  • VirtualAddress : 0x1000, VirtualSize : 0x93A
  • PointerToRawData : 0x400, SizeOfRawData : 0xA00
となります。
※Intelマシンはリトルエンディアンであることに注意してくださいね。
※(00 04 00 00 -> 0x400)

つまり、textセクションとなるデータ(図1の右真ん中TOASTY!.bin)はファイルオフセットが0x400となる場所に来ます。なので0x00でパッディングしなければなりません。
例えばMZヘッダとPEヘッダの間はGapが存在するため0x00を16個パッディングします。
同じようにパッディングを全セクションにすることで最終的には、
PEファイル =
                   MZヘッダ + (0x00 * 16) +
                   PEヘッダ + 0x00 * (16 * 26 + 18) +
                   text + 0x00 * (16 * 12 + 6) +
                   rdata + 0x00 * (16 * 6) +
                   data
となります。
これでヘッダとセクションは正しく配置されました。
 次にImportのアドレスを直します。
Importのアドレスはrdataの間から考えると図1の右下REPTILE.binから指し示す場所を見つけなければなりません。
本当はきちんとrdataのオフセットの差(VirtualAddress - PointerToRawData = 0x1200)を利用しDLLの出現位置から逆算してアドレスを決めるところですが、他の問題(Binary 100、200)のPEファイルから似たパターンを見つけることでimportアドレスを発見しました。
図の2番目のマーカがそのアドレスを示しています。
0x22B4(1番目のマーカ) - 0x1200(オフセット差) = 0x10B4(2番目のマーカ)になりますし、合ってる気がします。
とimportアドレスも分かったのであとはEntryPointです。
これも面倒くさかったのでBinary 100, 200のプログラムからEntryPointのパターン(C6 75 08 33)を探してVirtualAddressに変換して埋めました。

#プログラムが違っても、最初の初期化のルーチンは一緒なんだろうと思います。
つまりオフセット0x5DD + 0x1200 = 0x13DDがEntryPointのはずです。
こうして変換していくと、PEヘッダが下図の左から右に変わります。

試しに、修正したファイルを実行してみるとエラーなく実行できる。
#もうここまでで十分なのだが、問題はまだ続く。
Password:
と聞かれてしまったからである。つなり正しいパスワードが求めていたキーである。
となればデバッガの出番。
#DLLを調べたときにisDebuggerPresentの文字列が出て、まさかアンチデバッガじゃないだろうなと萎えてたけど、そうじゃないみたいで良かった。

逆アセンブルすると、test eax, eaxの結果でCorrectかTry again.に分岐するのでその前の
call loc_401090が怪しいとにらみ、break-pointを埋め込む。
loc_401090でも謎の処理があり、loop loc_4010B9を抜けると怪しいcmp命令がずらずら並ぶ。またesiをベースとしたアドレスが0x4増加するため、文字列を4Byteずつで比較しているのがわかる。それぞれのcmp命令の2番目のオペランドを結合すると答えの文字列が表れる。
以上です。
説明も長く、かけた時間も長く、回答の文字列も長かった。

2012年5月8日火曜日

SECCON CTF 2012/2/18-19 Forensic 300?

問題:「キーを見つけろ」

そして最初に渡されるファイルの先頭はこんな感じです。
しかし、こんなフォーマットのファイルは見たことがありません。普通、ファイルの先頭のヘッダを見てればなんとなく特徴を掴めるのですが、これははっきり言って謎でした。
そのためGoogle先生に頼るしかありませんでした。
そこで、繰り返し出現する「BUDlH0P6b」という文字列を検索すると、わずかなヒットともに、ishフォーマットの可能性を発見しました。
Wikipediaによるとishは1986年9月に発表されたバイナリとテキストを相互変換するための形式で、開発者の石塚さんから命名されたらしい(ishizuka)
#そんな古いフォーマット知らんわ笑
なので、ishフォーマットを展開できるExplzhを用いて展開しました。
するとテキストデータに変換されたのですが、まだ謎です。
 また未知のフォーマットかー。でも先頭がSで固定長のところを見ると何かの命令列のように思えなくもありません。そうしてGoogle先生に聞いてみるとMotorola S-record(SREC, S19)フォーマットにたどり着きました。
このフォーマットはどうやら携帯のメモリに書き込むための命令列のフォーマットのようで、例えば図の一行目の場合、
  • Start code : S
  • Record byte : 1
  • Byte count : 23
  • Address : 0x00
  • Data : 0x44...
  • Checksum : 0xDB
となっています。つまり0x00番地に0x44...を書き込めです。
これは指定したメモリ番地にデータを書き込む命令ということを考えると、当然メモりに何が書き込まれたかを知りたくなります。
つまりData部のみを抽出する必要があり、すると以下のようになります。
 先頭のDOCシグネチャ、V6、jxw.jexからこれは一太郎 Version 6の文書であることがわかります。もう解けたと思った瞬間。

まさかのパスワード付きですね。調べてみると今ではもうVersion 22になってセキュリティは万全ですが、Vserion 6のパスワード保護には脆弱性があるようで、それを解くアルゴリズムもあるみたいです。(ヒント:ビットシフト)
それを用いて解いてあげると、瞬く間にパスワードが得られます。
#速くてちょっとびっくりですね
それを入力してあげると、なんとCTFの歴史について語っている文書が手に入ります。
図には載せていないですが、そんな趣がある文書を経て、実は文書の内容と全く関係なく、キーワードが最後にぽつんと載っていることがこの問題の面白い点と言えますね。


2012年5月7日月曜日

SECCON CTF 2012/2/18-19 Network 200?

問題:「彼の本名を答えよ」

問題とともにpcapファイルが渡されました。
192.168.1.4から192.168.1.12へ一方的に通信が行なわれてますが、ポート、Seqから考えるとこれは通常ではあり得ないTCP通信であることがわかります。
 パケットの長さも(Len)86から124と大差ありません。

次にパケットの内容を見てみます
 すると、データ部が規則的であることがわかります。
 a1e1が非常に多くてa1fcとa2a3がちらほら見えます。
ここで、これはEUCの文字コードだと閃けば、あとは簡単です。
 EUCの文字列コード表をみると
a1e1 : "="
a1fc : "●"
a2a3 : "■"
であることがわかるが、意味ある文字列ではないのでこれで何かの図形をあらわしているに違いないと疑います。
ぼくは、ScapyというPythonのpcapファイルを扱うためのライブラリ(ユーティリティ)を使ってデータ部のみ切り出して、パケット毎に改行を差し込みました。
以下はそのPythonプログラムです

from scapy.all import *
pcap = rdpcap("network200.pcap")
data = "¥n".join(map(lambda x: str(x.payload.payload.payload), pcap))
open("network200.txt", "w").write(data)

そしてこのnetwork200.txtをテキストエディタで開くとなんと!
 「赤い彗星」という文字が見えてくるので、これで確実に正解がわかった気がします。