2016年8月29日月曜日

katagaitaiCTF#5 関西medに参加しました

本日(08月28日)に大阪で開催されたkatagaitai CTF勉強会(med)に参加してきました。

内容は午前はCryptography, 午後はPwnでした。Cryptographyはハッシュ関数に関する攻撃をやりました。問題はhack you 2014のhashmeと、ebCTF 2013のmd5collidingを中心に勉強しました。どうも講師の方がこのwriteupを読む可能性があるようなので、今回はしっかり書こうと思います。ちなみに一番前の中央に座っていました。[ ^o^]
katagaitaiCTFの5周年おめでとうございます。

午前 - Cryptography

Length extension attackやハッシュ衝突系の問題は昔勉強したことがあったので、今回のCryptographyはあまり資料を見なくても解けました。

hashme

ユーザー名を登録すると、「login=[username]&role=anonymous」で登録されます。ログインする際にroleにadministratorが入っていればフラグが表示されます。しかし、ログインするには登録時に生成される認証コードが必要です。認証コードは
s = "login=[username]&role=anonymous"
base64( xor( s + hashme(SALT + s), KEY ) )
で生成されます。
ただし、SALTとKEYはサーバー側にあり、不明です。(ローカルで実行する際はSALT="HOGE", KEY="\x01\x02\x03\x04"にしました)
ここでhashmeという独自実装のハッシュ関数がありますが、md5のように32バイトのhexdigestを出力するハッシュ関数で、ハッシュでごちゃごちゃにした各4バイトのA, B, C, DをB, A, D, Cの順にくっつけて出力しています。

(1)KEYを取得
とりあえずKEYは単純なxorで使われており、入出力はどちらも取得できるので、まずKEYを計算します。方法として、認証コード(cert)をbase64デコードし、それと"login=[username]&role=anonymous"をxorすれば、KEYの最初の方から復号化できます。さらに、[username]の長さを長くすると、それだけKEYを長く復号化できます。xorではKEYを繰り返してxorしているので、同じパターンの繰り返しが出た時点でそこまでが実際のKEY値です。

(2)length extension attackを実行
本日まではhashpumpしか使えなかったのですが、今回の講義を通して原理が分かったので実装することができました。ハッシュ関数は、ある時点で(A, B, C, D)が計算され、それをもとに次の(A, B, C, D)を計算する、という動作を繰り返しています。したがって、最終的に出力された(A, B, C, D)を使って、次の(A, B, C, D)を計算することで、hashme(A)の結果だけからhashme(A+B)が作れるということです。ただし、(A, B, C, D)の計算内には現在のバイトインデックスも含まれるので、Aの長さも必要です。今回の場合、 s = "login=[username]&role=anonymous"のときのhashme(SALT + s)が取得できるので、それをもとにhashme(SALT + s + "&role=administrator")を作ります。
しかし、SALTの長さは分からないので、ここは1から順番に仮定して、成功するまで繰り返します。

これらを実装したpython2のコードを載せます。ただし、pwntoolsというライブラリを使用しています。

今まで完全に闇の世界だったlength extension attackの原理が理解できたときは、かなり感動しました。

md5colliding

これ系も実は昔やったことがあり、そのときfastcollを使ったのも覚えていますが、2つまでしか同じハッシュを持つファイルが作れないなぁと思っていてそのままでした。今回の講義で少しステップアップした使い方ができるようになったかな。
さて、この問題は、指定された5つの文字列をそれぞれ出力するようなexeファイルを5つ作る、という問題です。ただし、5つのファイルは全てmd5が同じである必要があり、sha1が異なる必要があります。
fastcollというツールを使うと、
$ fastcoll A -o B C
でA+paddingという内容で、異なるpadding、同じmd5ハッシュ値を持つBとCが出力されます。ここから3つ以上同じハッシュを持つファイルの作り方が分からなかったのですが、
$ fastcoll B -o D E
としてCとD(もしくはE)との差分(追加分)をCに付けたせば良いようです。(なぜなら、hashmeで言ったように、サイズさえ一致すれば、それより前のバイナリは後のハッシュ値に影響しないからです。)
次にexeが異なる出力を持つ必要があるのですが、argv[0][0]などハッシュ値に影響しない部分を利用すれば良いようです。(もしファイル名が自動で割り当てられる場合はどんな方法がベストかな...?) とにかく今回はargv[0]で1から5までの出力を振り分けるのですが、Windows起動が面倒だったのでx86用のelfでやりました。
実行ファイル用のコードは次のようにしました。(linuxでは"./main"のように実行するのでargv[0][0]ではなくargv[0][2]を判定に使っています。) 実行ファイル用のCコードと、衝突生成用のpython2のコードを載せておきます。

同じmd5ハッシュ、異なるsha1ハッシュが出力され、出力内容も指定通りでした。コードは5個に限らず自由な個数だけ衝突ファイルを生成できるように工夫しています。

parlor

この問題はそもそも問題文を理解しておらず、時間内には解けませんでしたが、家でやったのでwriteupしておきます。
入力に対して条件を通過すれば賭け金だけ増え、失敗すれば賭け金が消えるゲームです。条件というのが
md5(hoge + input) % odds == 0
であることです。ちなみに問題文ではもうちょっと分りにくかったです。また、この「+」は文字列の結合で、hogeは16進数形式のダイジェストなのですが、バイナリとして結合されます。ここで数値加算してみたり文字列そのまま結合してみたりして時間取られました。さらに、inputには改行コードが最後に付いてくるっぽいのでそこにも注意。
この問題でユーザーが指定できるのはlog_2(odds)の整数とinputのバイナリです。hogeはランダムでサーバー側に保存されています。oddsの指数は100まで指定できるので、最大で2**100まで設定可能です。一回成功すればそれを繰り返せば良さそうなのですが、一度送ったinputは二度と送れません。

(1)md5(hoge + x)を知りたい
md5(hoge + x)が求まれば、md5(hoge + x + y)も求まります。しかし、md5(hoge + x)は最大でも下位100bitまでしか残りません。ということでbrute force attackで残りの28bitを探すことにしました。
...と書きながらコードを書いて実行したらあまりの重さにパソコンが止まったので今日はここまで。

午後 - Pwn

なんか凄いことやってるなぁって感じでした。
1つ1つのプロセスで何やってるのかは分かりましたし、資料にソースコードや構造体、サンドボックスの命令などが書かれていたので良かったものの、実際にソースコードも無い状態であれを解けと言われたら確実に捨てます。

tp

最後まで分からなかったこと(自分の書いた攻撃コードに関する疑問):
  • fastbinsに繋がったりbinsに繋がったり。その辺の設計もうろ覚えでした。 
  • 0x1337という数が分かりませんでした。idなら10とか20とかでもいいはず?
  • shellstormのshellcodeが動きませんでしたが、あれはseccompが原因だったのかな?
  • どうやってあんなに長いアセンブリを読む気になれるのか。

でも、やっぱりヒープ苦手だなと実感しました。もっと勉強してきます。

(2)習得したこと:
  • malloc, seccompなどの設計が少し分かりました。
  • main_arena以外にthread_arenaなるものがあるとは......
  • gdbでアタッチしたりダンプしたりするのが便利でした。
  • DynamicROP(?)の復習になりました。
最終的にflag1は取得できたので良かったですが、flag2については手も足も出ない状態です。特にヒープのところの動作がいまいち分かってないので解説みたいなのは書けませんが、書いた攻撃コードを載せておきます。(Ubuntuで書いたので日本語で書けませんでした。)

最初にひっかかったのはremote_readで、payloadを書き込んですぐにsendしなければならないのですが、remote_read内にrecvがあったので、次のステップに進めないままrecvで止まっていました。次にひっかかったのはpayloadのROP gadgetで、「pop esi; ret」を使ってるつもりが「pop esi; rep ...」みたいなのを使ってました。目grepが足りない。最後にひっかかったのがshellcodeで、shellstormからコピーしたものは動きませんでした。たぶんseccompのせいかな?
個人的にtpはflag1だけを集中的に説明しても良かったんじゃないかなとも思います。(そうするとプロが困るのかも。)

さいごに

今回はCryptography, Pwnいずれも前回のmedに比べるとかなり成長した状態で挑戦できたと思っています。(前のmedは1つも解けなかった。)
いつもkatagaitaiCTFではたくさんの知識を習得させてもらっています。講師のみなさん、NRIさんなど、運営してくださっている方々、本当にありがとうございます。
今後も参加したいと思っているので、よろしくお願いします!

2016年8月13日土曜日

katagaitaiCTF#6 関西easyに参加しました

本日(08月13日)に大阪で開催されたkatagaitai CTF勉強会(easy)に参加してきました。

内容は午前はWeb, 午後はReversingでした。WebはHack.lu CTF 2014のHotCows Datingという問題で、ReversingはCSAW CTF 2013のcrackmeという問題をそれぞれ解きました。正直Webの方はBurpの設定が上手くいかずにあまり付いていけませんでした。一応フラグは取得できたもののイマイチ「なんで?」というところが多いので、今回はcrackmeの方を中心にWriteUpを書こうと思います。

crackmeは32bitのLinux用バイナリで、とりあえずWindowsを起動してIDA Pro Freeで解析を開始しました。bindやaccpetなどから単体でサーバーとして動作するプログラムだと分かったので、とりあえずポート番号だけメモして動作しました。crackmeへ接続すると、パスフレーズを聞かれます。パスワードが合っていないと終了してしまいます。あまりIDAを使ったことの無い私は文字列検索で文字列を送信(表示)している部分を見つけ、その周辺から解析を始めました。その結果、明らかに分岐している部分があったので、その上の関数にverifyという名前を付けて関数を見ます。ちょっと前に変数名とコメントを付ける機能を知ってからはじゃんじゃん使ってるので解説が始まる前には解析が終わってたと思います。verify関数(仮)をC言語にすると次のようになりました。

int verify(char* input)
{
  char chr = input[0];
  int hash = 0x539;
  char *pass = input;
  int tmp;
 
  for(; *pass != 0; pass++) {
    tmp = chr + (hash << 5);
    chr = *(pass + 1);
    hash += tmp;
  }
 
  return hash;
}

あらためて見るといかにC言語が苦手かが分かります......
さて、とりあえず自分で解こうと思って6桁くらいまでのブルートフォースを書きましたが一向に終わらないので別の方針を立てることにしました。
そこで、入力を「A」「AA」「AAA」「AAAA」...のように試すと、徐々にハッシュ値が増加していることが分かりました。(4バイトを超えたらまた小さくなる感じでした。)
入力が長く、ASCII値が大きいほどハッシュ値も大きくなるので、二分探索(手動)で0xEF2E3558に徐々に近づけていきました。(でも5分程度で下2桁以外は揃いました。)
6桁でハッシュ値が答えに近づき、最後の方は揃わなそうだったので、最後の1文字だけブルートフォースアタックしました。その結果「aSA6>6」で通りそうだったので送ったらフラグが表示されました。

勉強会が終わった今では頭の悪い解き方です。はい。

ということで、勉強会ではkleeとz3pyを使う方法をやったので、その内勉強会中ずっとやってたz3による解法についてもWriteUpします。z3pyは条件式に当てはまるような入力を見つけてくれるモジュールです。文字列を探す方法は分からなかったのでIntVectorでやってましたが実行できず。スライドを読むとBitVecなら上手くいくそうなので時間がかかりましたが書いてみました。

実行すると入力条件に当てはまるような文字列を見つけて表示してくれます。講師の方の書かれたコードでは40秒程度かかりましたが、このコードでは1秒前後で実行できました。私は講師の方のコードをリストにして初期化に入力、hashともにBitVecを使っただけなのですが、なぜここまで違いが出たのかは全く分かりません......

easyとはいえ、今回の勉強会を通して知らなかったことをたくさん学ぶことができたので、大変有意義な1日でした。主催者やNRI Secureの皆様、ありがとうございます!次のmedも参加する予定なのでよろしくお願いします。

2016年7月17日日曜日

SECCON 2016 九州大会のWrite Upと感想

本日2016年07月17日(日)に、福岡県の博多にある富士通株式会社 九州支部で、IoT CTFが開催されました。このCTFは過去に参加してきたCTFと違い、電子回路やハードウェア関連の問題が出題されます。今回は部活のチーム4人で、チームinsecureとして参加しました。最終的なスコアテーブルの上位3位は以下の通りです。(他チームはぼかし処理済み)


ということで、何とか優勝してSECCON本戦出場権を獲得することができました。今回はチームでかなり協力し、労力を分散させて挑戦することができたのが良かったと思います。また、CTFとしては、過去にやったことの無いタイプでしたが、今までほとんど触れたことのない分野だけあって、非常に勉強になりました。

今回のCTFの概要

大会直前までどんな形式か全く分からず、「ブレッドボード回路が渡されるんじゃないか」とか「配線の写真からデコーダを書くんじゃないか」とか事前にいろいろ考えてきました。会場に入ると、各チームのテーブルにRaspberry Pi 2、ブレッドボード、配線、各種IC、テスタ、ニッパーなどが用意されていました。
問題は大問で4問、小問を含めて5問ありました。全て100[pt]です。insecureは3問(300[pt])を正解し、最初の1問がFirst Bloodだったので追加で10[pt]を獲得しました。今回は、どんな問題が出題されたのかと、解いた問題についてのWrite Upを書きます。



問題1

水道局員の人数が足りないから自動で制御しよう、という問題。用意された部品を使って、1秒毎にモータがON,OFFを繰り返す回路を作る。優しいことに、回路図が用意されていたので、回路の方はそのまま実装しました。なお、使用した機器は「Raspberry Pi 2」「モータ」「ダイオード」「抵抗」「MOSトランジスタ」です。
Raspberry Pi 2の3番ピンから1秒ごとに出力と入力を切り換えるようなコードを書いて実行します。正しく動作していることと、その入力をオシロスコープで示した上で、担当の方を呼んで動作確認してもらいます。実行結果が正しいと判断されたら、フラグが貰えました。
ここのオシロスコープの波形がかなりひどい状態でしたが、運営の方の優しさでフラグが貰えました。ありがとうございました。この問題がFirst Bloodでした。


問題2.a

スパイとして活動しているとき、任務内容を8PINのICで渡されるという問題です。8PINのICは24LC256で、これはEEPROMです。EEPROMについては調べてきて、Pickit2のも持って来たのですが、なぜかリードが正しくできずに挫折。その後、同じチームのtheoldmoon0602が、持って来たArduino互換機で挑戦し、見事データの抽出に成功。データのヘッダが1F 8Bで、一目見てtar.gzだと分かったので、解凍するとフラグのテキストが出てきました。


問題2.b

上と同じです。ここで、上の問題ではEEPROMの最初の方しか取り出しておらず、それに気付くのにかなり時間が取られました。結局最後までデータを取ると、回路図のjpgとRaspberry Pi用のコードがあり、回路図を構成してコードを実行するとフラグが取得できます。プログラムで回路をエミュレートしたものの、終了数分前だったのでダメでした。


問題3

1分ごとにエアコンのリモコンが使えなくなる原因を探ってほしい、という問題。会場の前後に回路が置いてあり、そこから赤外線が発生していました。(それはデバッグ用で、実際には運営に頼んで赤外線を定期的に発生させるボードを借りてくる。)この問題では、Raspberry Piのmode2コマンドを使って赤外線の波形データを取得しました。さらに、エアコンのリモコンの赤外線の仕様書を調べ、それに従って不要な部分をカットしました。しかし、このプロトコルは製造会社によって結構違い、どれを使えばいいか迷ってる間に時間切れでした。今思えば「SECCON{~~}」の「ECC」のところは取得できていたので、もう少し頑張れば解けたかもしれません。個人的には赤外線モジュールについて勉強できたので、非常に楽しい問題でした。


問題4

テロリストのUSB機器がどんな動作をするか確認する、という問題。この問題については私は全く触っておらず、チームメンバーが解いてくれたので詳細は知りません。チームメンバーの解き方としては、用意されたAVRマイコンに配布されたhexデータを書き込み、さらにUSBに変換する謎の機器とを接続し、それをパソコンに繋いだとのこと。すると、一定周期でキーボードが勝手に入力され、フラグが書かれたそうです。この問題は全チームが解いていました。すごい。
個人的に自分で作ってみたいので今後教えてもらおうかな。

感想

とにかく色んなことが勉強できて素晴らしかったです。企画してくださった運営の皆様、会場やパーツ等を提供してくださった協賛社の方々、本当にありがとうございます。それから今回出場されたチームの方々もお疲れ様でした。
細かい部品は持って帰っても構わないということで赤外線モジュールとEEPROM等をいただきました。家で勉強させていただきます。m(_ _)m
 





2016年6月27日月曜日

Practical Malware Analysis - kosen14s読書会

はじめに

この投稿は、kosen14s読書会用の記事です。

kosen14s読書会

kosen14s読書会では、何人かのメンバーが自由なジャンルの本を紹介します。私は他にブログらしきものを持っていないことと、ちょうど技術的な内容の本を紹介する予定だったので、ここに投稿しました。


Practical Malware Analysis


本記事で紹介するのは、Michael SikorskiさんとAndrew Honigさんの著書「Practical Malware Analysis: The Hands-On Guide to Dissecting Malicious Software」です。

Practical Malware Analysis

宇宙人が解剖されかけているという一見不思議な表紙ですが、これは「中身の分からないものを調査する」ということを暗示しているのだと思います。

さて、この本ではマルウェア(端的に言うとウイルス)を解析するために必要な知識を1から100まで記載した技術書で、内容がとにかく充実しています。私は自分の読みたいところだけを読む人なので、本当はこの本の内容を全て読んだ訳ではありません。しかし、さらっと読んだだけでも有用な情報が数多く書かれていたので、その中でも特に面白かったものについてのみここで取り上げようと思います。


この本との出会い

この本を初めて知ったのは高校1年生の冬、北海道で開かれたセキュリティミニキャンプという勉強会でした。その勉強会は私がコンピュータセキュリティを勉強するきっかけにもなったのですが、そのため当時は会場一の初心者でした。勉強会を通して活躍が見られた人にはこの本が貰えるとのことだったのですが、もちろん本はプロ達の手に渡っていきました。そこで、「プロが良本を手に入れるとよりプロになる」というプロサイクルを見出しました。これではいかんと思い、それから1年後にネット通販でこの本を買うことにしたのです。おしまい。


逆アセンブルとは

まず説明する前に、逆アセンブルということについて説明します。
逆アセンブルとは、実行ファイルなどの機械語を、アセンブリ言語という多少人間が読みやすい形式に変換する作業を指します。
機械語はintelやらARMやらといったプロセッサにより異なりますが、アセンブリ形式はどの種類でもある程度似ているので、普通の人がマルウェアを解析するとき、逆アセンブルされたものを読みます。この記事では、intel形式のアセンブリ言語(NASM)で書きたいと思います。

例えば

b8 77 00 00 00 50

という機械語列はさっぱり意味が分かりませんが、これを逆アセンブルして

mov eax, 0x77
push eax

にすると、あら不思議。分かりやすい。

さて、みなさんが普段使っているソフトウェアは、例えばWindowsならexeなどの実行ファイルになっていることが多いです。これが実行できるということは、このファイルの中に一連の動作を表す機械語が書かれています。マルウェアに限らず、実行ファイルを解析するときはこの機械語を逆アセンブルするのです。そして、逆アセンブルするためのツールはたくさん用意されています。個人的に代表的なのは次のツールです。

静的解析:IDA Pro, radare2
動的解析:OllyDbg, x64dbg

静的解析のツールは、先に説明したように、ただ機械語を逆アセンブルした結果を表示するツールです。ただ、こういったツールの良いところは、逆アセンブルした結果をフローチャートのようにするなど、できるだけ人間に分かりやすく整理して表示してくれるのです。動的解析のツールは、逆アセンブルをすると共に、そのプログラムを実行します。しかし、マルウェアは実行したら危ないので、今回はやりませんでした。


ANTI-DISASSEMBLY

解析を困難にする技術には大別して「ANTI-DISASSEMBLY」「ANTI-DEBUGGING」「ANTI-VIRTUAL MACHINE TECHNIQUES」「PACKERS」の4つがあります。特に3つ目の「ANTI-VIRTUAL MACHINE TECHNIQUES」 はマルウェア特有の技術ですし、「PACKERS」に関しては「ANTI-DISASSEMBLY」に含まれてもおかしくありません。ということで、個人 的には「ANTI-DISASSEMBLY」および「ANTI-DEBUGGING」に分かれるのですが、ANTI-DEBUGGINGの方は前から触ったことがあったので、そこまで驚きの技術ではありませんでした。
ということで、解析防止技術の中でも特に面白かったものが逆アセンブル自体を困難にする技術です。
そもそもなぜこんな面倒なことをするかと言うと、例えばC言語でゲームを作ったとしても、配布する時点では機械語の入った実行ファイルを公開します。そしてそれを逆アセンブルされると、理論的にはどんなプログラムでもソースコード(アセンブリ)が見られてしまいます。しかし、開発者としてはできればやめてほしいことも多いです。ゲームのストーリーからセーブデータの保存アルゴリズムまで見られてしまうのですから。ましてやパスワードやライセンスキーを要求するソフトウェアなどは解析されたらたまったものではありません。(実際に有名なソフトウェアでも解析されて構造がバレてしまうことが多々あります。)

そこで、頭の良い先人たちは、逆アセンブルを防ぐ技術(Anti-Disassembly)をいくつも考案してきました。とは言え、逆アセンブル自体は防げないので、逆アセンブルにより出力されたソースコード(アセンブリ)を、いかにツールに解析されにくく、そして人間にとって見にくくするかがポイントです。これを難読化といいます。


次のアセンブリを見てください。これは逆アセンブル結果ではなく、開発者が書くコードです。単純にSleep関数を実行するだけなのですが、これがバレたくない開発者は、コードに難読化を施します。

    jmp short obfuscation
    db 0xE8
obfuscation:
    push 0x2A
    call Sleep

このコードの説明は次のような感じです。

1行目:ラベル"obfuscation"にジャンプ(そこを実行)
2行目:機械語にしたときに、ちょうどここに0xE8という1バイトのデータを埋め込む
3行目:"obfuscation"というラベルを作る
4行目:メモリに0x2Aというデータを入れておく
5行目:Sleep関数を呼び出す。(引数は上の0x2Aとなる)

つまり実行すると、
「obfuscationにジャンプ」 -> 「Sleep(0x2A)を実行」
となるだけのコードです。

このコードを機械語にし、さらに逆アセンブルすると次のようになります。(あくまでも出力例)

    jmp short near ptr loc_2+1
loc_2:
    call near ptr 0x15ff2a71
    or [ecx], dl
    inc eax
    db 0


本来なら前に書いたコードがそのまま結果として出力されてほしいのですが、見たところ全く違うものが出てきました。もう一度オリジナルのコードを書きます。

    jmp short obfuscation
    db 0xE8
obfuscation:
    push 0x2A
    call Sleep

全然違いますね。ここで重要となるのは「db 0xE8」です。0xE8はintelのx86アーキテクチャの機械語において、call命令の最初のバイトです。したがって、逆アセンブルツール(逆アセンブラ)が機械語を解析する際、この0xE8をcall命令として読んでしまい、さらに次の機械語まで巻き込んでしまいます。

つまり本来なら次のように区切って解析してほしいのですが、

| 0xEB 0x01 (jmp) | 0xE8 (db) | 0x6A 0x2A (push) | 0xE8 ... (call) | ...

逐次的に解析するツールは次のように区切ってしまいます。

| 0xEB 0x01 (jmp) | 0xEB 0x6A 0x2A 0xE8 ... (call) | ... (or) | ... (inc) | ...

これだけの説明ではちょっと分かりにくいですが、このようにゴミデータを入れることによって、単純に上から解析するタイプのツールから、ある程度コードを守ることができます。(このように上から解析する逆アセンブリを"Linear Disassembly"と呼んでいます。)

今回紹介した本では、上述のような逆アセンブル防止技術だけでも、他にも様々な種類の技術が詳しく記載されています。


さいごに

この本の分かりやすいところは、たいてい実例を示して詳細に書かれていることです。
それでいて必要なポイントだけがまとめられているので、この本一冊からたくさんの情報を得ることができます。
それから、マルウェアについての解析を中心としているので、各種技術が身に付くとともに、マルウェアの仕組みについても分かります。

残念ならが、調べた限りでは日本語版はありませんが、マルウェア解析技術の本としては海外でも非常に評価の高い一冊です。さらに、kosen14s所属の古月くんもこの本の電子書籍版を持っており、いかにこの本が凄いかを証明しています。

表紙の上で解剖されんとする宇宙人を見た際には、是非一度手にとって読んでみてください。

2016年2月7日日曜日

katagaitai CTF 2016 関西 med に参加しました

2016年02月06日(土曜日)に大阪で開かれたkatagaitai CTFの中級者向け勉強会に参加しました。内容は暗号とエクスプロイトで、私は脱初心者を目指して参加しました。
暗号はCSAW CTF 2014 Crypto300のfeal.pyを、エクスプロイトはCodeGate 2015 Pwnable400のbeef_steakを中心にハンズオンで講義が行われました。
いずれも惜しくも時間内には解けませんでしたが、また時間に余裕がある時に解法コードを作って載せられたらと思います。(試験のすぐ前なので今は時間が無いです)

暗号 - feal.py

暗号問題は、サーバーで動作しているpythonコード(feal.py)が渡され、そこに接続します。
・第一段階
まず、指定された文字列(ランダムな16文字)から始まり、sha1の最終16ビットが全て1になるような文字列を送信しなくてはなりません。つまり、
h = sha1(str_rnd + something)
について、
h[:-1] == h[-2] == 0xFF
であれば通過できます。
これは単純にsomethingにブルートフォースしたら簡単に通りました。
ここまでは家で解いてきたのですが、その後はでっていう状態でした。

・第二段階
次に暗号化されたフラグが渡されます。これは保存しておきます。今回使用されている暗号は、タイトルの通りFEAL暗号ですが、よく見ると、

return ((x << 2) | (x >> 6)) & 0xff

であるはずのシフト関数が、

return ((x << 3) | (x >> 5)) & 0xff

になっていました。本来の仕様との違いはこれだけです。
今回使用する攻撃はDifferential Cryptanalysis(差分解読法)とかいう聞いたこともない方法で、要するに
「入力A, BについてFEAL(A), FEAL(B)が求まっていて、その出力差分FEAL(A) ^ FEAL(B)が一定ならX ^ Y == A ^ B(入力差分がA,Bと等しい)ような入力に対して、その出力の差分はFEAL(A) ^ FEAL(B)となる」
みたいな感じでした。(間違ってたらすいません)
なんとなーく分かったのですが、実際にコードを書くと何かしっくりこなかったです。それに、後から知ったのですが、pythonで書くと十数時間かかるようで、C言語で書く必要があったそうです。ずっとpythonで買いてパソコンのファンを鳴らしていました。

結局私のコードで答えは出ずに、解答だけ聞いて終了してしまいました。暇なときにコードを書きます。


エクスプロイト - beef_steak
エクスプロイトと聞いてうわぁって感じだったのですが、内容はとても面白かったです。とにかくスライドが詳しく書かれていました。(暗号のスライドも図が多くて分かりやすかったですが、こちらは300ページ程度ありました)
beef_steakでは、steakというLinux x86_64のバイナリが渡され、それを実行しているサーバーを攻略するという問題です。家で解析しておきましょうという指令が出ていたので、C言語のコードに直したのですが、その時はStack BOFがあるだけで、フラグが読めそうとは思いませんでした。というのも、Stack Canaryが付いており、オーバーフローしてもすぐに終了してしまうのです。

・第一段階
家で解析したときのCコードを以下に示します。

RC4で暗号化されたデータを復号化するのが目的です。オーバーフローというとret2libcやROPのイメージが強かったので、今回は全く分からない状態からスタートしました。
ここで新たに学んだのは、"argv[0] leak"という手法です。(正式名称でない?)これは、Stack CanaryのStack Smashingメッセージが表示されることを利用し、内部のデータを取得するという方法です。
具体的には、オーバーフローを起こした際の
*** stack smashing detected ***: ./steak terminated
というおなじみのメッセージの
./steak
を取得したい変数に変更します。そのためASLRが有効な場合は固定アドレスに存在するデータが取得する対象となります。今回のCコードを読めば分かるように、key、state、output等のデータはアドレスが固定されています。
どうやって"./steak"の部分を変えるかですが、__stack_chk_fail関数では、普通にargvの内容からargv[0]のファイル名を表示しているそうです。(詳しくはkatagaitai CTFの資料を参考に。)つまり、十分にオーバーフローできる場合、argv[0]のポインタがある部分を取得したいデータのアドレスに書き換えてやります。
これを聞いてさっそく
"\xe0\x20\x60\x00\x00\x00\x00\x00" * 40
みたいなデータ(keyのアドレスを繰り返し)を送ろうと考えたのですが、よく考えたらkeyは使用した直後にmemsetで0にクリアされています。ということでstateを取得したら見事取得できました。と思ったら256バイトあるはずのデータを途中までしか取れていません。これはstateの途中に0x00が存在するのが原因で、
 接続→stateを取得(lengthバイト)→切断→接続→state+lengthを取得(lengthバイト)...
みたいに何度か接続するようにして全てのデータを取得しました。

・第二段階
もともと"What's your favorite food?"という質問に対して答えが正しければ通ります。取得したstateを元に、バイナリから取得した暗号化済みデータを復号化し、それを送りました。ここで新たなバグを使用します。steakは入力の文字数をstrlenで取得し、その分暗号化しているのですが、入力の最初に0x00を持ってくることで、暗号化処理をスキップできます。そうしてチェックを通過すると、自由にメッセージを"./message"に書き込むことができるようになります。
ここで使用するのがShared Library Injectionという手法で、これはLD_PRELOADで自前のライブラリを使用することで攻撃できます。したがって、今回のように自由にファイルをアップロードできる状態か、sshのような形式でないと利用できません。今回は、systemをexecve("/bin/sh", 0, NULL);に変更するようなライブラリを作りました。(messageへの書き込みにsystem関数が呼び出される。)messageに保存できたら、これを利用したいのですが、ライブラリmessageを読み込ませる手段が必要です。

・第三段階
messageを読み込ませるには、環境変数LD_PRELOADを./messageにする必要があります。つまり、オーバーフローを使用してenvp[0]のアドレスを"LD_PRELOAD=./message"を指すアドレスにすればよいのです。こんなコードを作って実行したのですが、ローカルでは「ライブラリをロードできません」みたいなメッセージが出て、リモートではそもそも何も起こりませんでした。ちょっとよく分からないので暇な時にやります。

この他にも様々なexploit tipsを教えていただきました。

まとめ
katagaitai CTFの勉強会に参加させていただくのは今回が初めてでしたが、内容は難しかったものの、その技術は(なんとなく)分かったので、非常に有意義な勉強会だったと言えます。どちらも全く知らなかった攻撃揃いだったので、自分でコードを作りながらも新鮮な感じがしました。難しかったとはいえ、このくらいのレベルはやってて楽しいので、次回も同じレベルの勉強会があれば是非参加したいです。

2016年1月31日日曜日

SECCON 2015 Final Intercollegeに参加しました

2016年01月30日(土)に東京電機大学でSECCON 2015 Final Intercollegeが開催されました。1チーム4人までで、中学生から大学院生までで構成された18チームが参加しました。私のチームはinsecureで、
初めてA&Dに参加したので、何をすればいいかが分からず、かなり戸惑いましたが、その上での感想と軽いwrite upをしようと思います。

各チームに一台のサーバーが割り当てられ、チームメンバーはあらかじめ渡されたパスワードで管理者(root)としてsshでログインできます。開始からしばらくはIPもユーザーも分からなかったので、全員何もできない状態でしたが、しばらくして運営から説明がありました。
サーバーでは3つのサービスを稼働させることができ、私はvulnerable_blogとsbox2015を担当しました。vulnerable_blogはブログの記事を投稿できるサービスです。サイトを見ると、XSSとSQL Injectionの脆弱性がありました。また、SQL Injectionの際のエラーがそのまま出力されます。とりあえず自分のチームのSQLiの脆弱性を修正し、Webアプリの設定をdevelopmentからproductionに変更してエラー出力を無くしました。チームでやったDefenseらしい行動はこれだけで、この防御力が後に悪く影響しました。
ORDER BY等で調べた結果からUNION SELECTを使用しました。

hoge') UNION SELECT 0,0,load_file("/var/www/html/vulnerable_blog/keycode"),0,0#

これにより管理者のパスワードを取得できます。また、自チームのkeycodeが初期状態で"test"だったので、"abc123password"みたいなのに変更しました。これで管理者になり、記事のログの削除キーにボットが登録したフラグが見つけられました。この時点でSQLiを修正していたり、keycodeを変更していたり、何かしら修正していたチームは半分以上あったと思います。
次にsbox2015の脆弱性を探し始めます。sbox2015でruby, php, pythonのコードを投稿すると、ランダムな数字が返され、その数字を同じアプリに渡すとコードが実行できるようになる。とりあえすlsを実行して一覧を取得し、何か無いかを探しました。vulnerable_blogのSQLiが修正されたサーバーについては、sbox2015のコード実行でkeycodeを取得しました。一部のチームはコード実行をできなくしたり、管理者ページにアクセスできなくしたりしていました。
チームメンバーがsbox2015により攻撃された際のコードを保存しておいてくれたので、それと同じ方法で他のチームに攻撃を開始しました。攻撃はmysqlコマンドをrootで実行することにより、他の問題のデータベースの内容を取得しました。自チームではrootでの実行を禁止することで対策しました。(チームメンバーがやってくれました)

他の問題などで脆弱性を突かれて防御点が大きく原点されていたようで、8000点以上の攻撃点を得たものの防御点は-7000点以上になっており、結果は18チーム中の15位でした。

今回のA&Dで分かったことは以下のことです。
・防御専門のメンバーを作る
・フラグの取得は自動化する
・サービスを中途半端に止めるなら、ずっと稼働させておく方が良い
・相手の攻撃から攻撃手法を知ることもできる
・相手の攻撃よりも先に自分のサーバーの修正をする
・上位チームを狙った方が点数はかなり稼ぎやすい

・チームで全部の問題を同時に担当する。(1つでも放置しておくと、それを通して他の問題のフラグも取られる)

とにかく難しかったですが、新しいことばかりで面白かったです。それから可視化システムは相変わらず格好良かったです。参加者のみなさん、運営のみなさん、その他関連している方々、お疲れ様でした。(internationalの方もお疲れさまです。)

2015年11月9日月曜日

SECCON福島大会 サイバー甲子園に参加しました

2015年11月07日(土)に福島の会津で開催されたサイバー甲子園(SECCON予選)に出場しました。10チームが抽選で選ばれ、私(ptr-yudai)のチーム名はinsecureで、theoldmoon0602殿と一緒に参加しました。

結果は2位で決勝の出場権を貰いました。以下が上位3位までの最終スコアです。
 CTF事情を知っている方によると、どうやら1位の方はプロだそうです。
以下は得点の推移です。(上位3チームまでチーム名を残しています)

とりあえず、自分が解いた問題の中で、覚えているもののwriteupを書こうと思います。

binary100
Linuxの32bit実行ファイルが渡されたので、gdbで起動しました。スタックに1を入れて、直後にその値が2より大きいかを調べて分岐しています。setでEIPを変更して続行すると「SECCON{Can Uread me?」と表示されましたが、送信してもポイントゲットならず。色々試して、「SECCON{Can U read me?}」を送ったら正解でした。

binary200:
Linuxの32bit実行ファイルが渡されたので、gdbで起動しました。重要な部分をCっぽく直すと、

gets(s);
for(i=0; i<32; i++) {
  tmp = esp_2C + s[i];
  foo = 0xFF ^ (char)tmp;
  bar = cipher[i];
  if ( bar == foo ) // OK
}


つまり、入力から1文字ずつNOTをとり、それを予め用意されたデータ(cipher)と比較しています。cipherをメモリから出力し、pythonでNOTをとるとフラグになりました。「SECCON{XOR_encryption_message}

network100
パケットデータが渡されます。ファイル無いので覚えてないですが、認証みたいなのがあるので、見るとBase64文字列があります。デコードしたらフラグでした。(たぶん)

network100
パケットデータが渡されます。なんかエラーが連なっているところがあったので、そこらへんのIPの192.168.44.161でSYNフラグが立っている部分をwiresharkでフィルター(ip.src==192.168.44.161 && tcp.flags.syn==1)します。出て来たパケットを上から見ると、各パケットのオフセット0x12に連続してフラグが1バイトずつ書かれていました。「SECCON{Data_is_included_NOT_ONLY_in_payload_but_also_header_field.}

net300
パケットデータが渡されます。wiresharkで見るとメールのプロトコルが使われており、中にいくつか送信されたデータがありました。まず目に止まったのが、何行にもわたるbase64文字列です。メールの添付ファイルだなと思ってデコードすると、zipファイルが出てきます。解凍しようとするとパスワードが求められます。メールの送信データの中にパスワードっぽいフレーズがいくつかあったので、試すと開きました。中にあったファイルはComposite Document Fileというもので、theoldmoon0602殿の助言でLibreで開くと、またパスワードを求められます。これもメール内の別のフレーズで試すと開き、フラグが表示されました。「SECCON{Sending_File_Password_with_Followed_Mail_is_bogus.}


crypt100
「U0VDQ09Oe1VyOXdnbWZZWXh5N2VvOFFnTDJWfQ==」というbase64文字列が渡されるので、デコードすると「SECCON{Ur9wgmfYYxy7eo8QgL2V}」になります。


programming100
turtleとかいうライブラリを使用したpythonのコードが渡されます。windowsのpythonには標準で入っていたので、draw_flag関数を実行すると、亀が絵を書き始めます。ちょっと遅かったので早くし、最後に停止ルーチンを挟むと、国旗が表示されました。theoldmoon0602殿がすぐにミャンマーの国旗であると知らせてくれました。「SECCON{MYANMAR}


web100
アクセスすると同じページがロードされるので、wiresharkで見るとフラグが受信されていました。

web100
ログインページでしたが、何を入力してもサーバー側でエラーになります(出題ミス?)。Fiddlerで見ると、レスポンスの最後にgzipデータがあったので、抽出して展開するとフラグのページが現れました。

misc100
Excelデータの各セルの背景色が色分けされており、SECCONの「突破」マークがドット絵みたいになっていました。Libreで開くと中央らへんに左三角がたくさん並んでいました。調べた結果から、excelのリスト機能と思って調査しました。とりあえず重たいので背景色を全て削除し、リスト内に「#」が書いているところと書いていないところを区別しようと閉じて、再度開くとなぜか三角が減っており、それらがフラグをAAのように表示していました。「SECCON{NIRVANA_KA1}


misc100
「作者は誰か」という問題で、短いアルファベット羅列が渡される。ダブルクオーテーションで囲って調べると、たくさんのサイトがヒット。一番上のサイトを読むと、ベートーベンの楽曲のリズム(だったかな?)であることが判明。形式が指定されていなかったので、いろいろ入力しましたが、最終的にtheoldmoon0602殿が正しい形式で送ってくれました。


感想
CTF歴は1年ちょっとで、SECCON決勝を大きな目標として必死に勉強してきましたが、初の予選で決勝への出場権を貰えて嬉しいです。これからしばらくはAttack&Defenceの勉強をする予定です。
問題はちょうど良い難易度で、CTF4bでの講義が結構役に立ちました。
theoldmoon0602殿のプログラミング力は凄く、何やってるのか分かりませんでした。
まだまだ勉強しないと......