KENJI’S BLOG このページをアンテナに追加 RSSフィード

Freezed...

2008-10-24

MacOS Xのバイナリに興味あったから少しずつ調べてます

僕はMacOSに関しては初心者この上なく、最近やっとMacOS Xの使い方を覚えたくらいなので、そもそもバイナリだのなんだのと話せる感じではないのですが、とりあえずgdbあるので、ちょっと実行ファイルのバイナリを見てみようとか思いました。

それで、そもそもMacには、Cocoaという開発環境(というかAPI群?)があって、これはObject-Cという言語で記述しなければならず、しかも中間言語に変換されて実行されるという、要するにWindowsでいうところの.NET的な位置づけのものが主流となっているっぽいので、バイナリ見てもあんまり楽しくないかも、とか思ったのですが、Macには他にもOS X以前の環境のAPI群を引き継ぎつつ、それをOS X用に拡張したというCarbonというものがあって、これはC/C++で記述できるらしいので、これで作られたものは、思いっきりバイナリとか素直に出力してくれるのでは? と思い、とりあえず、Carbon使って簡単なアプリを作成し、gdbでバイナリ見てみました。

ちなみに、Carbonアプリはソースコード的には、かなりWindowsアプリと似てて、↓こんな感じです。

int main(int argc, char* argv[])
{
    OSStatus                    err;
    static const EventTypeSpec    kAppEvents[] =
    {
        { kEventClassCommand, kEventCommandProcess }
    };

    // Create a Nib reference, passing the name of the nib file (without the .nib extension).
    // CreateNibReference only searches into the application bundle.
    err = CreateNibReference( CFSTR("main"), &sNibRef );
    require_noerr( err, CantGetNibRef );
    
    // Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
    // object. This name is set in InterfaceBuilder when the nib is created.
    err = SetMenuBarFromNib( sNibRef, CFSTR("MenuBar") );
    require_noerr( err, CantSetMenuBar );
    
    // Install our handler for common commands on the application target
    InstallApplicationEventHandler( NewEventHandlerUPP( AppEventHandler ),
                                    GetEventTypeCount( kAppEvents ), kAppEvents,
                                    0, NULL );
    
    // Create a new window. A full-fledged application would do this from an AppleEvent handler
    // for kAEOpenApplication.
    HandleNew();
    
    // Run the event loop
    RunApplicationEventLoop();

CantSetMenuBar:
CantGetNibRef:
    return err;
}

イベントドリブン的な関数(WinProcみたいな関数)もあって、かなり同じ感じです。これは期待できそうです。

それで、さっそくgdbで見てみると、一応、バイナリにはなっているっぽいです。

(gdb) b main
Breakpoint 1 at 0x1ee3: file /Users/kenji/test/main.c, line 28.
(gdb) r
Starting program: /Users/kenji/test/build/Release/test.app/Contents/MacOS/test 
Reading symbols for shared libraries ++++... done
Reading symbols for shared libraries . done

Breakpoint 1, main (argc=1, argv=0xbffff94c) at /Users/kenji/test/main.c:28
28	    err = CreateNibReference( CFSTR("main"), &sNibRef );
(gdb) disassemble $eip
Dump of assembler code for function main:
0x00001edc <main+0>:	push   %ebp
0x00001edd <main+1>:	mov    %esp,%ebp
0x00001edf <main+3>:	push   %ebx
0x00001ee0 <main+4>:	sub    $0x24,%esp
0x00001ee3 <main+7>:	movl   $0x2064,0x4(%esp)
0x00001eeb <main+15>:	movl   $0x2040,(%esp)
0x00001ef2 <main+22>:	call   0x3000 <dyld_stub_CreateNibReference>
0x00001ef7 <main+27>:	test   %eax,%eax
0x00001ef9 <main+29>:	mov    %eax,%ebx
0x00001efb <main+31>:	jne    0x1f57 <main+123>
0x00001efd <main+33>:	mov    0x2064,%eax
0x00001f02 <main+38>:	movl   $0x2050,0x4(%esp)
0x00001f0a <main+46>:	mov    %eax,(%esp)
0x00001f0d <main+49>:	call   0x3032 <dyld_stub_SetMenuBarFromNib>
0x00001f12 <main+54>:	test   %eax,%eax
0x00001f14 <main+56>:	mov    %eax,%ebx
0x00001f16 <main+58>:	jne    0x1f57 <main+123>
0x00001f18 <main+60>:	call   0x300a <dyld_stub_GetApplicationEventTarget>
0x00001f1d <main+65>:	movl   $0x0,0x14(%esp)

なんか関数も普通に呼ばれているので、いい感じです。あとアドレスが00000000から始まっていますね。なんかWinとかLinuxとかのバイナリばかり読んでいると、こういう些細なことに「おおー」とかなってしまいますが。あと、引数の受け渡しにpush命令を使ってないのは何故なんでしょう? movでesp指しているところに直接値を格納してますけど、これは何か意図があるのか。あとは別段変わったところはないっぽいですね。

とりあえず、Carbonアプリは普通に解析できることが分かりました。

あと、OS Xは開発環境とか関係なく、gccとかも普通に使えるので(terminalあるし、ベースはFreeBSDらしいし)、↓こんな感じでも使えます。

$ cat >test2.c
#include<stdio.h>
int main(void)
{
    printf("Hello World!\n");
    return 0;
}
^C
$ gcc test2.c -o test2
$ ./test2
Hello World!
$ 

それで、これも当然バイナリを見れます。

(gdb) b main
Breakpoint 1 at 0x1fce
(gdb) r
Starting program: /Users/kenji/test/build/Release/test.app/Contents/MacOS/test2 
Reading symbols for shared libraries ++. done

Breakpoint 1, 0x00001fce in main ()
(gdb) disassemble $eip
Dump of assembler code for function main:
0x00001fca <main+0>:	push   %ebp
0x00001fcb <main+1>:	mov    %esp,%ebp
0x00001fcd <main+3>:	push   %ebx
0x00001fce <main+4>:	sub    $0x14,%esp
0x00001fd1 <main+7>:	call   0x1fd6 <main+12>
0x00001fd6 <main+12>:	pop    %ebx
0x00001fd7 <main+13>:	lea    0x1a(%ebx),%eax
0x00001fdd <main+19>:	mov    %eax,(%esp)
0x00001fe0 <main+22>:	call   0x3005 <dyld_stub_puts>
0x00001fe5 <main+27>:	mov    $0x0,%eax
0x00001fea <main+32>:	add    $0x14,%esp
0x00001fed <main+35>:	pop    %ebx
0x00001fee <main+36>:	leave  
0x00001fef <main+37>:	ret    
End of assembler dump.

printfが華麗にputsに変換されてるところはナイスという感じですが、main+7のよくわからんcall命令は何だろう? 次の命令へジャンプしているだけだし、eipが取りたいのかな? とも思いましたが、popしたebxをいっさい使っていない感じ。これは理由が分からない。前にFFRの金居さんにMacのバイナリは最初に変なcallが入るんですよ的なことを教わった気がするけど、おそらくこれのことだろう。うーん、Macのバイナリ、なかなか興味深い。

ちなみに、Cocoaで作成したアプリをgdbに渡してみたところ以下のバイナリが見えた。

(gdb) disassemble $eip
Dump of assembler code for function main:
0x00001ff6 <main+0>:	push   %ebp
0x00001ff7 <main+1>:	mov    %esp,%ebp
0x00001ff9 <main+3>:	leave  
0x00001ffa <main+4>:	jmp    0x4000 <dyld_stub_NSApplicationMain>
End of assembler dump.
(gdb) disassemble 0x4000
Dump of assembler code for function dyld_stub_NSApplicationMain:
0x00004000 <dyld_stub_NSApplicationMain+0>:	call   0x8fe18b20 <__dyld_fast_stub_binding_helper_interface>
End of assembler dump.
(gdb) disassemble 0x8fe18b20 0x8fe18b50
Dump of assembler code from 0x8fe18b20 to 0x8fe18b50:
0x8fe18b20 <__dyld_fast_stub_binding_helper_interface+0>:	push   $0x0
0x8fe18b22 <__dyld_stub_binding_helper_interface+0>:	sub    $0x64,%esp
0x8fe18b25 <__dyld_stub_binding_helper_interface+3>:	mov    %eax,0x54(%esp)
0x8fe18b29 <__dyld_stub_binding_helper_interface+7>:	mov    0x68(%esp),%eax
0x8fe18b2d <__dyld_stub_binding_helper_interface+11>:	mov    %eax,0x60(%esp)
0x8fe18b31 <__dyld_stub_binding_helper_interface+15>:	mov    %ebp,0x68(%esp)
0x8fe18b35 <__dyld_stub_binding_helper_interface+19>:	mov    %esp,%ebp
0x8fe18b37 <__dyld_stub_binding_helper_interface+21>:	add    $0x68,%ebp
0x8fe18b3a <__dyld_stub_binding_helper_interface+24>:	mov    %ecx,0x58(%esp)
0x8fe18b3e <__dyld_stub_binding_helper_interface+28>:	mov    %edx,0x5c(%esp)

中間言語が入っているっぽい? ああー、でもNSApplicationMainは見えるので、一応Cocoaもバイナリ解析で追えるのかなぁ。Winにおける.NETとはまた少し違うかもしれない。

2008-10-16

近況

ブログが更新されないときは(特に技術ネタが無いときは)大体仕事が忙しいときでつ…すみません。そろそろひと段落なので来週くらいからまた技術ネタ更新始めます。

たぶん健康です

約1年半くらい前に肺の手術をしたのですが、それまでにも結構いろいろと身体を壊していて、実は結構健康じゃないですw。それで、最近も、ちょっと下腹部辺りが1ヶ月ほどずっと痛くて、うーん病院行こうかなぁ、どうしようかなぁという感じだったのですが、今日病院行ってきました。とりあえず精密検査したいから3日後にまた来て、と言われましたが、たぶん大丈夫でしょう、と付け加えられました。たぶんって何だよたぶんってw。

ハッカージャパン10周年記念

今月号のハッカージャパンは、10周年記念ということで、紙のページとは別に、これまで発売されたハッカージャパンの中から厳選された記事600ページ分が、付録DVD-ROMに収録されているようです(参照)。以前(確か)Cマガジンなどで、5年分の記事が入ったDVDが数万円で売られたりしてましたが(僕はそのDVDを買ってましたが…(笑))、ハッカージャパンは、それらが完全に付録状態で、しかも書籍自体の値段もいつもと同じというありえないものになっているため、普段買わない方も、今月号くらいは買っても損しないと思いまつ。

BHJ2008復習

BHJ2008のプレゼン資料が配布されていますが、長谷川氏の趣味と実益の文字コード攻撃と、石山氏の”FFR EXCALOC”コンパイラのセキュリティ機能に基づいたExploitabilityの数値化がリンク切れ(URL間違い)なため、この文章で本当のリンクを指しておきます。ちなみに今日両方を読み終えました。"FFR EXCALOC"は、ソフトウェアのバイナリを静的解析して、そのソフトウェアにどの程度のセキュリティ強度があるかを数値化するという話です。例えば、オーバーフローなんかの脆弱性対策にカナリア(Canary)などが使われますが、そのカナリアを使用した場合、バイナリに特徴的な(スタックにカナリア値が挟まる)コードが入るため、そういうのを検出して、このソフトウェアはこれくらいセキュアです、といったようなことを数値化するという話です。セキュリティ強度を数値化するという発想が面白く、個人的にツボな内容でもあって、正直もっとも興味深いプレゼンのひとつでした。というか、セッションを受けたかったw。文字コード攻撃の方は、はっきり言ってまったくの専門外で、プレゼン資料読んだだけではまったく意味が分からなかったw。なので、会社で専門の人に頼んで、1ページずつ説明してもらいました。とりあえず、utf-7って非サポートにできないのかな、とか、さすがに文字コード系は英語圏の人じゃ調べられないだろうなぁ、とか、JavaScriptがここ数年進化しまくってて、いつの間にか僕の知らないものになってました(JSON?何それ?おいしいの?)、とか、そんな感じでしたが、説明を受けてとりあえず書かれてあることが理解できるくらいにはなった。

2008-10-14

「Black Hat Japan 2008」お疲れ様でした

http://www.blackhat.com/

本当に嵐のような1週間でしたが、無事終了しました。関係者、参加者、スピーカーの皆様、本当にお疲れ様でした。正直、本当に疲れました(^^;。BHJの全スピーカーのプレゼン資料はBHJのサイトからダウンロードできるようです。実は僕自身、8日〜9日にかけてプレゼン資料作り、9日〜10日にかけてデモのプログラム作りで、実質10日の午後からのセッションしか参加できませんでした。ちなみに参加したのは村上氏のハイパーバイザーIPSとKarsten Nohl氏のHardwareに隠されたアルゴリズムの公開でした。どちらもツボなネタだったので、普通に楽しめましたが、できれば全部見たかったので、プレゼン資料見て勉強中でつ。

本当にものすごい1週間でしたが、振り返ってみると、引き受けてよかったなぁと感じます(スピーカーの経験なんてそうそうできるものではないですし)。反省点としては、セッション開始直後、緊張しすぎて何言っているか分からなかったこと、pptに研究的な内容を入れられなかったこと、でしょうか。本当はsysenterフックとか、ntdll.dllの書き換え(置換)とか、OSブート時にバイナリを書き換えると、最初っからいろんなことが可能だぜ! というようなことも書きたかったのですが、今回は時間制限がシビアだったので、実践用のデモのみしか用意できませんでした。でも、最善は尽くしたので、まぁ結果がどうあれ満足しています。本当にお疲れ様でした。

「AV Tokyo 2008」お疲れ様でした

http://www.avtokyo.org/

勉強会という形式では、今回初となるAVTokyo2008ですが、参加してみると本当に楽しかったです。AVTokyoは参加費が安い(1000円とか3000円とか)ので、誰でも気軽に参加できますし、BHJと同じくCFPが通れば無料で参加できます。なので、来年以降のお勧めの作戦は、まずBHJのCFPに応募して、受かれば無料でBHJに参加できるぜーやっほーい、落ちたらAVTokyoのCFPに応募して無料で参加できるぜやっほーい、というダブル応募作戦でつ(なんだそれw)。

ただ、実際、今回の参加者の方ともいろいろと話をしましたが、皆さん本当にちゃんとした技術力を持っており、普通にプレゼンの場で話を聞きたいなと思いました。コンピュータセキュリティはUSAが本場だけど、日本人も結構すごいんじゃないのか? とか普通に思いました。実際、BHJの僕以外の4名の方のセッションも研究的でとても楽しそうだったし、AVTokyoで行われたショートトークも難読化、FlashのXSS、HTMLとELFとplで動くバイナリ、とか、個人的にはかなり興味を引かれるものでした。特に難読化はリバースエンジニアリングが主な仕事な僕としては、知っておきたい内容でした。竹迫氏のHTMLバイナリの話は意味不明すぎてすごいことしか分からなかった(笑。FlashのXSSは対象がFlashであるため、バイナリをダウンロードしデコンパイルすればソースコードが見えることになり、そうなるとサーバに何度もコネクションする必要なく脆弱性を調べることができ、完全に調べた後に一撃必殺でアタックができるという、個人的には少し新鮮な内容でした。

というわけで、個人的には、十分にイベントとして成功ではないかと思います(僕は運営ではないので詳しくは分からないですが)。ただ、運営の方に聞いたところ、来年もまったく同じ形でやる(やれる)かどうかは未定とのことだったので、やはりイベントを開催、運営するのも、結構いろいろと大変なのかなぁと思ったり。

まぁでも、来年あるかどうかは別としても、とりあえず今回は一参加者として十分に楽しめたので、満足しています。本当にお疲れ様でした。

2008-10-08

「Black Hat Japan 2008」でスピーカーとして発表します

ものすごい展開になりました(↓)。

http://www.blackhat.com/html/bh-japan-08/brief-bh-jp-08-speakers.html#Aiko

http://www.blackhat.com/html/bh-japan-08/brief-bh-jp-08-index.html#brisch01

とにかく頑張ります。全力を尽くします。


とりあえず徹夜は決定っぽい…。

2008-09-17

MacBook買っちゃいました

2ヶ月くらい迷ってたけど、ついにMacBook買いました。15万円でした。デフォルトでgccが入ってなくて、どうやってgcc入れるんだーと迷ってたらインストールCDについてました。Mac自体使った経験がほぼゼロで、使い方からしてまったく分からないので、とりあえずOSの使い方から勉強してまつ。

このMacの上でVMでWindowsとか動かしたいなーとか思ったけど、Mac版のVMWareがフリーでなかった…orz。と思ってたら、以前紹介してもらった「VirtualBox」というのが、なんかMacOSXで行けそう。キタコレww。というわけで、今お試し中…。


追記:

窓「同意するならF8を押してください」

俺「F8押しても何もおこらない」

fn + F8を押す必要あり

MacOSX上で動作するVirtualBoxにWindowsXPをインストール中

窓「日本語キーボードなら「全角/半角キー」を押してください」

俺「ちょw、ねーよw」

とりあえず「その他のキーボード」から日本語キーボード(106)を選べばおk


追記2:

MacBookのマウス→ボタン1個

Windowsのマウス→ボタン2個

Mac上で動くWindowsを操作したいんだが、ボタン1個でどうしろと?

というか、Mac用の2ボタンマウスってあったような…。


追記3:

MacBookの場合「環境設定」の「キーボードとマウス」からマウスの設定を変更でき、「2タッチ(2本指で同時にスクラッチを触りながら)クリック」で右クリックの機能っぽい(参考

2008-09-07

「Black Hat Japan 2008」スピーカー決定!

「Black Hat Japan 2008」のスピーカーが決定した模様です。

http://www.blackhat.com/html/bh-japan-08/brief-bh-jp-08-speakers.html

ちょw日本人4人もいるwwキタコレwww

と盛り上がりつつも、自分は普通に落ちてました…orz。

まぁ…、仕方ないです…、機会があれば来年また頑張ります…。


というわけで、これから気になるセッションをチェックしてきまつヽ(`Д')ノワーン

2008-09-04

よく使うASM命令ベスト100位に説明つけてみた(6/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

ベスト71〜80に説明つけてみた(間違いあるかも…)

  22341 ds	セグメントオーバーライドプリフィックス(データセグメント)
  21736 jp	PF=1 PFが1ならジャンプ(JPEとも書く)
  21175 fnstsw	FSTフラグをオペランドへ転送(FSTSWとも書く)
  20458 not	1の補数、要するにビット反転命令
  19998 cs	セグメントオーバーライドプリフィックス(コードセグメント)
  19554 fild	符号付き整数を浮動小数点数に変換しst0へ格納
  18972 lock	割り込み禁止に設定
  18866 sete	ZFフラグの値をオペランドへ格納
  18297 setne	ZFフラグと逆の値をオペランドへ格納
  18055 lods	メモリの内容をEAXに読み込みESIをその分加算or減算する

いろいろとマニアックな命令が出てきましたが、50位以降は、浮動小数点演算で使う命令が目立ちます。ここではfnstswとかfild辺りですね。あと、コメントで教えてもらったセグメントオーバーライドプリフィックスというものは、「セグメントをまたぐコール命令やジャンプ命令の前に置かれる命令」らしいです。

セグメントとは、えっと…、説明するのが難しいです(ぉぃ)。

例えば、すべてのメモリが地球だとすると、セグメントは大陸です。確か世界に大陸は6つありますよね。それらをそれぞれ、CS、SS、DS、ES、FS、GS、とかいう名前にします。それぞれの大陸は海で区切られているため、行き来できません。それで、例えばCSには命令コード人が住んでるとか、DSにはデータ人が住んでるとか、SSにはスタック人が住んでるとかします。要するにそれぞれのセグメントをだいたいの用途に分けるんです。それらは、すでにだいたいの用途に分けられているから、あんまり大陸間で行き来する必要ないんだけど、でもたまに行き来したい時があったりするんだ。そんなときに、ただ、call命令やjmp命令を呼んでも、海は渡れないから、自分のセグメント内にしか移動できない。それで、しかたなく船を作ろうか、みたいな。要するにそういう話です(えっどういう話?)。要するに海を渡りたい時はセグメントオーバーライドプリフィックスを呼べよ、ということですね。うん。そういうこと。うんうん、そういうことだね。うん…、えっと、ここに「google」置いときますね。

2008-09-02

よく使うASM命令ベスト100位に説明つけてみた(5/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

ベスト61〜70に説明つけてみた(間違いあるかも…)

  37928 repz	repと同じだが、次の命令が転送命令ならrepを比較命令ならrepzを使うのが一般的らしい
  36217 out	外部デバイスの入出力ポートへデータを送る(outsのパワーダウン版?)
  34432 cdq	EAXレジスタを符号付き整数としてEDX:EAXに型変換する
  33914 movsx	基本的に16ビット版mov(メモリ上の16ビット以下のデータを転送する)
  30026 pusha	全レジスタの値をスタックへ格納する
  28262 fadd	浮動小数点演算での足し算(st0と渡されたオペランドが足される)
  27495 rol	左方向へのローテート(CFは含まれない)
  24020 aas	アンパックBCDの減算結果ALを補正(繰り下がりが発生するとah--)
  23651 jno	OF=0 オーバーフローでないならジャンプ
  23371 ror	右方向へのローテート(CFは含まれない)

ついに出てきたローテート(rol、ror)。といっても、このランキング位置。ローテートってあまり使わないんだなぁとつくづく感じた。僕も何かの暗号アルゴリズムで見ただけで、他ではお目にかからなかったような…。シフトと違ってC言語命令もないし…。ローテートって何? という方はこちらを。

あと、aaaとaasは、一応、以下のコードを見れば、動作原理はだいたい分かるかと。

004011DB     33C0           XOR EAX,EAX
004011DD     B0 08          MOV AL,8(AH=00, AL=08)
004011DF     04 04          ADD AL,4(AH=00, AL=0C)
004011E1     37             AAA     (AH=01, AL=02)
004011E2     2C 04          SUB AL,4(AH=01, AL=FE)
004011E4     3F             AAS     (AH=00, AL=08)

アンパックBCDというのは、簡単に言えば、10進数の数値の1桁ずつを8ビットで表す方法。例えば、1024という10進数の数値は、0x01000204という4バイトの値になる。256なら、0x020506という感じ。つまり、8なら、0x0008なわけです。そこで0x0008に4を加算すると、当然0x000Cになるわけですが、でも10進数だと12なので、0x0102とかになったらいいなぁと思ったらAAAを実行せよと。するとAAAが勝手に0x0102に補正してくれます。逆に、0x0102の0x02(=AL)から4を減算すると、当然0xFEなわけですが、でも10進数だと8なので、0x0008とかに戻ったらいいなぁと思ったらAASを実行せよと。

かなり適当な説明ですが、aaaとaasはこんな感じの理解で大丈夫だと思います。というか、解析作業時、こんな命令ほとんど見たことないんですが…orz。

それにしても検索時間が長くなってきたw。71位〜80位は明後日(4日)くらいにて。

2008-09-01

よく使うASM命令ベスト100位に説明つけてみた(4/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

ベスト51〜60に説明つけてみた(間違いあるかも…)

  62273 stos	EAXの値をES:EDIの指すメモリへ格納する(REPと組み合わせることで初期化処理になる)
  60421 jns	SF=0 マイナスじゃないならジャンプ
  58573 movq	MMXレジスタで使われるmovで64ビット転送に使用する(最適化とかそういう話)
  58422 fmul	浮動小数点演算での掛け算(st0と渡されたオペランドが掛けられる)
  53800 jg	ZF=0 && SF=OF 符号ありで、大きいならジャンプ
  50155 movaps	XMMレジスタで使われるmovで128ビット転送に使用する(これも最適化とかそういう話)
  45608 sar	符号ありで右シフト(シフト系は符号のありなしで少し複雑)
  45156 bound	int3と似たようなものだが、こちらは境界チェックの例外
  38960 data16	?
  38840 in	外部デバイスの入出力ポートからデータを受け取る(insのパワーダウン版?)

stosは初期化関連で良く使われてそうだけど、実際は51位ということで、それほど頻出しているわけではない。あとmovqやmovapsは最適化処理関連で良く見かける命令ですが、僕自身それほど知らないです。とりあえず「MMX命令」「SIMD命令」辺りを見ておけばOKかと。

↓こういう感じで一気に128ビットのデータの計算(掛け算)ができます。

movaps      xmm0, [edi];
mulps       xmm0, [esi];
movaps      [edi], xmm0;

あとは、シフト系の命令で、符号ありと符号なしでの、右左シフトそれぞれの場合の命令とかが、結構覚えにくいので、余裕があるなら覚えておいてもよいかも(シフト命令)。個人的には、bound命令が最後まで分からなかった。意味としては理解しているけど、実際に使い方を知らないw。


うーん、しかし、この辺りから本当に「調べないと分からない」命令ばかりになってきた。そろそろ年貢の納め時、というわけで勉強しながら更新していくことにします。

61位〜70位は明日(2日)にて。

2008-08-30

よく使うASM命令ベスト100位に説明つけてみた(3/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

ベスト41〜50に説明つけてみた(間違いあるかも…)

 113117 jo	OF=1 オーバーフローしたらジャンプ
 111416 jle	ZF=1 or SF!=OF (符号あり)以下ならジャンプ
 111125 shl	左方向にシフト(C言語でいう << ←これ)
 104434 fstp	st0レジスタからデータを取得(浮動小数点系の演算でよく使われる)
 103882 rep	ECXが0になるまで次の命令を繰り返す(比較命令時はZFフラグも見る)
  91023 xchg	2つのオペランドを交換する(xchg eax, ebxでeaxとebxの値が交換される)
  74925 addr16	?
  72425 fs	?
  71879 neg	2の補数値にする(符号ありの値に対して、符号を反転させる)
  63106 js	SF=1 マイナスならジャンプ

改めて思いましたが、ベスト50位まで覚えておけば、アセンブルコード読むだけならまったく問題ない。というか、50位以内でもいらない命令結構あるです。

逆に、必須なのは、やはりジャンプ系かなと思います。cmp命令に代表されるように、アセンブラ命令はフラグを変更することで条件を変えます。その変えられた条件によってジャンプするかどうか? という二択がよく出てくるので、それは抑えておくべきかなと思います。

fldやfstpについては、浮動小数点演算によって使用される命令で、例えばfloat型とかdouble型とかで加減乗除すると、このような命令が出現します。詳しい内容を知りたければ「MASMインラインアセンブラ」が参考になるかと。

51位〜60位は、明後日(1日)にて。

2008-08-29

よく使うASM命令ベスト100位に説明つけてみた(2/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

ベスト21〜40に説明つけてみた(間違いあるかも…)

 416677 outs	外部デバイスの入出力ポートへデータを送る(repと組み合わせて使おう)
 393871 jb	CF=1 符号なしで、小さいならジャンプ
 362616 (bad)	解析できなかった命令?
 311007 imul	符号ありの乗算(掛け算)EAXと渡された値を掛けてEDX:EAXへ入れる
 295376 ins	外部デバイスの入出力ポートからデータを受け取る(repと組み合わせて使おう)
 290626 jl	SF!=OF 符号あり(マイナスの数値あり)で、小さいならジャンプ
 249056 jae	CF=0 符号なし(0が最小値)で、以上ならジャンプ
 220561 leave	retの前に置かれるもの("mov esp, ebp"+"pop ebp"と同じ)
 205579 popa	全レジスタ分のデータをスタックから取り出し
 201044 gs	
 181922 movzx	渡したレジスタ値やメモリ値のサイズが異っても転送可能なmov
 172773 sbb	基本的にsubと同じ(異なるのはCF=1の場合にさらに1を減算する点)
 168170 adc	基本的にaddと同じ(異なるのはCF=1の場合にさらに1を加算する点)
 158961 jbe	CF=1 && ZF=1 符号なしで、以下ならジャンプ
 149619 movs	repと組み合わせることで大量のデータを一気に転送できる(EDIやESIと連動)
 143792 jge	SF=OF 符号ありで、以上ならジャンプ
 138609 arpl	特権レベルを調整する(1行では説明不能、解析屋には必要ない?)
 131230 shr	右方向にシフト(C言語の >> ←これ)
 125488 fld	st0レジスタにデータを格納(浮動小数点系の演算でよく使われる)
 122132 ja	CF=0 && ZF=0 符号なしで、大きいならジャンプ

gsは分からなかった。一度も見たことない?

arplは知ってるけれど解析作業にはあまり使わないかな?

sbbやadcは使い方を知らないと、なぜこんな命令が存在するか理解できないかもしれない。

一応、↓こんな感じで使われまつ

// レジスタのサイズより大きいデータの加算をやりたい時
mov eax, 0FFFFFFFFh
mov edx, 5h
mov esi, 0FFFFFFFFh
mov edi, 2h
// 05FFFFFFFFh(edx:eax) + 02FFFFFFFFh(edi:esi) という計算結果を(edx:eax)へ入れたい
add eax, esi
adc edx, edi
// 最初のaddで繰り上がりが起こるためCF=1となる。
// 次のadcでedxにCF=1となった値(1)も加算されるため、結果的に(edx:eax)へ加算結果が入る
// 結果、edx=8h、eax=FFFFFFFEhとなり、無事08FFFFFFFEh(edx:eax)となる。

間違い指摘はウェルカム(;^o^b

41位〜50位は明日(30日)にて

2008-08-28

よく使うASM命令ベスト100位に説明つけてみた(1/10)

http://d.hatena.ne.jp/rootkit/20080818/1219042285

とりあえずベスト20に説明つけてみた

11378610 mov	レジスタ値やメモリの値を転送
9156176 push	スタックへ値を格納
3825704 add	値を加算(足し算)
3638244 call	スタックに次の実行命令のアドレスを入れてジャンプ
2329166 int3	デバッグ用割り込み
2271495 pop	スタックから値を取り出す
2105874 cmp	値を評価してフラグに反映
2000442 je	ZF=1 同じならジャンプ
1920361 lea	説明しにくい。まぁ[]の中の計算結果がレジスタへ入ると覚えておけばおk
1673045 nop	何もしない
1495072 test	フラグだけ変化するAND命令(真 or 偽 だけを判断する時によく使う)
1426586 jmp	指定アドレスへジャンプ
1217054 jne	ZF=0 違うならジャンプ
1031610 xor	ただのxor(C言語の ^ ←これ)
 971938 inc	インクリメント 値に1加算
 914353 ret	スタックのトップにある値を取り出してそこへジャンプ
 843280 and	ただのand(C言語の & ←これ)
 601980 dec	デクリメント 値から1減算
 561539 sub	値を減算(引き算)
 437624 or	ただのor(C言語の | ←これ)

解析屋としてはこの辺までは即答できないとダメかも…

21位〜40位は明日(29日)にて

2008-08-26

明日の夜にCFP提出予定っす

「Black Hat Japan 2008 Briefings」発表資料(CFP)の募集↓(締切:9月1日)

http://www.blackhat.com/html/bh-japan-08/bh-jp-08-cfp-terms.html


今日は徹夜で最後のまとめ。

結局、英訳だけで丸々1週間かかった罠(泣


よく考えたら小さい頃から英語苦手で

中学時代には英語の定期テスト、20点(50点満点)とかとってました。

高校時代には30点くらいはとってましたが、100点満点でした。


…どう見ても才能ありません。本当にありがとうございましたw

追記(28日)

出しますた。もう後には戻れない…

2008-08-18

マイクロコード変換ツールってあるのかな?

http://www.hex-rays.com/idapro/ppt/decompilers_and_beyond_white_paper.pdf

↑このホワイトペーパーの「Microcode generation」で、マイクロコードなるものを出力しているのですが、これってどうやって生成しているんだろう…。逆アセンブルコードに対応したマイクロコードって出力可能なのかな? そういうツールがあるのかな?

実はこれ、Black Hat USA 2008でもっとも興味深かったプレゼンのひとつです。アセンブルコードだけでなく、マイクロコードも利用することでデコンパイルの精度を高めるという内容。まぁあくまで実験段階らしく、実用化にはまだかなり難問があるっぽかったですが、研究内容としてすばらしく面白かったです。興味があれば読んでみてください。

CFP英訳できたら「Black Hat Japan 2008」スピーカー応募します

「Black Hat Japan 2008 Briefings」発表資料(CFP)の募集↓(締切:9月1日)

http://www.blackhat.com/html/bh-japan-08/bh-jp-08-cfp-terms.html

とりあえず、日本語版CFPは出来ました。

今から英訳して、ネイティブの方に見てもらって、ダメだしを受けて、「ヽ(*`Д')ノワーン」ってなりながら、なんとか英訳できたら(あと間に合ったら)「Black Hat Japan 2008」スピーカー応募します。

前回(USAに応募したもの)は新しいネットワークの提案でしたが、話によるとそういう系は受かりにくいということらしかったので、今回はリバースエンジニアリングで行きまつ(大丈夫か?)。

まぁとりあえずtryだ! ダメだったら引きこもればいいさ…(ぉぃ。

2008-08-17

ntdll.dllの書き換えとCRCチェックの回避

ntdll.dllはシステムディレクトリに格納されており、WFP(Windows File Protection)で守られているわけですが、これを、sfc_os.dllがエクスポートしている、エクスポート序数が「5」の関数とか、sfc.dllのエクスポート序数「2」の関数を使うことで、WFPを無効にして、ntdll.dllを書き換えられます。

しかし、ntdll.dllはWindowsシステム上例外的に重要なDLLで、ntdll.dllを強引に書き換えてWindowsを再起動すると、ブルースクリーンにエラーが表示され、2度とWindowsが起動しなくなります。

STOP: c0000221 Unknown Hard Error
 \SystemRoot\System32\ntdll.dll

ntdll.dllを好きなように書き換えただけなのに、二度とWindowsが起動できなくなるなんてヒドイ(セーフモードでもダメ)。

それで、おそらくはWindows起動時に、ntdll.dllの改変チェック(CRC)をして、もし変更が加えられていたらWindows自体を起動しないという処理が行われていると推測できます。なので、エラー時の処理を追いました。するとnt!RtlpBreakWithStatusInstructionで処理が停止。

nt!RtlpBreakWithStatusInstruction:
804e5b25 cc              int     3
804e5b26 c20400          ret     4

上の関数に戻ると↓このような感じ。

nt!KiBugCheckDebugBreak:
805348ce 6a24            push    24h
805348d0 6878495380      push    offset nt!RamdiskBootDiskGuid+0xcc (80534978)
805348d5 e8b801fbff      call    nt!_SEH_prolog (804e4a92)
805348da 33db            xor     ebx,ebx
805348dc 895dfc          mov     dword ptr [ebp-4],ebx
805348df ff7508          push    dword ptr [ebp+8]
805348e2 e83a12fbff      call    nt!DbgBreakPointWithStatus (804e5b21)
805348e7 eb63            jmp     nt!KiBugCheckDebugBreak+0x74 (8053494c)

さらにコールスタックを戻っていくとそれっぽい部分を発見。

806a170f e8639f0000      call    nt!IopInitializeBootDrivers (806ab677)
806a1714 84c0            test    al,al
806a1716 0f8413970100    je      nt!IoInitSystem+0x716 (806bae2f)
806a171c 381da0a35580    cmp     byte ptr [nt!IoRemoteBootClient (8055a3a0)],bl
806a1722 891de4ec6880    mov     dword ptr [nt!IopLoaderBlock (8068ece4)],ebx
806a1728 0f8518970100    jne     nt!IoInitSystem+0x73b (806bae46)
806a172e e8b7210100      call    nt!PpLastGoodDoBootProcessing (806b38ea)
806a1733 8b0d6c9e5580    mov     ecx,dword ptr [nt!NtGlobalFlag (80559e6c)]
806a1739 b800000400      mov     eax,40000h
806a173e 85c8            test    eax,ecx
806a1740 898dc0feffff    mov     dword ptr [ebp-140h],ecx
806a1746 7508            jne     nt!IoInitSystem+0x776 (806a1750)
806a1748 0bc8            or      ecx,eax
806a174a 890d6c9e5580    mov     dword ptr [nt!NtGlobalFlag (80559e6c)],ecx
806a1750 53              push    ebx
806a1751 e82b270100      call    nt!PsLocateSystemDll (806b3e81) ←それっぽい部分
806a1756 85c0            test    eax,eax

どうやら、nt!PsLocateSystemDllでntdll.dllがシステムにロードされているようなので、この中を解析してみる。

806b3e83 55              push    ebp
806b3e84 8bec            mov     ebp,esp
806b3e86 83ec30          sub     esp,30h
806b3e89 6a06            push    6
806b3e8b e87ee5e5ff      call    nt!ExVerifySuite (8051240e)
806b3e90 84c0            test    al,al
806b3e92 0f85d7feffff    jne     nt!PsLocateSystemDll+0x13 (806b3d6f)
806b3e98 53              push    ebx
806b3e99 33db            xor     ebx,ebx
806b3e9b 385d08          cmp     byte ptr [ebp+8],bl
806b3e9e 7506            jne     nt!PsLocateSystemDll+0x31 (806b3ea6)
806b3ea0 891d58ef6880    mov     dword ptr [nt!PspSystemDll+0xc (8068ef58)],ebx
806b3ea6 56              push    esi
806b3ea7 57              push    edi
806b3ea8 53              push    ebx
806b3ea9 33ff            xor     edi,edi
806b3eab 47              inc     edi
806b3eac 57              push    edi
806b3ead 8d45e8          lea     eax,[ebp-18h]
806b3eb0 50              push    eax
806b3eb1 8d45d0          lea     eax,[ebp-30h]
806b3eb4 50              push    eax
806b3eb5 6820001000      push    100020h
806b3eba 8d45fc          lea     eax,[ebp-4]
806b3ebd be407e5d80      mov     esi,offset nt!PsNtDllPathName (805d7e40)
806b3ec2 50              push    eax
806b3ec3 c745d018000000  mov     dword ptr [ebp-30h],18h
806b3eca 895dd4          mov     dword ptr [ebp-2Ch],ebx
806b3ecd c745dc40000000  mov     dword ptr [ebp-24h],40h
806b3ed4 8975d8          mov     dword ptr [ebp-28h],esi
806b3ed7 895de0          mov     dword ptr [ebp-20h],ebx
806b3eda 895de4          mov     dword ptr [ebp-1Ch],ebx
806b3edd e8bbb7e2ff      call    nt!ZwOpenFile (804df69d)
806b3ee2 3bc3            cmp     eax,ebx
806b3ee4 0f8c99feffff    jl      nt!PsLocateSystemDll+0x71 (806b3d83)
806b3eea 57              push    edi
806b3eeb ff75fc          push    dword ptr [ebp-4]
806b3eee e8a154efff      call    nt!MmCheckSystemImage (805a9394)
806b3ef3 3d210200c0      cmp     eax,0C0000221h
806b3ef8 8945f4          mov     dword ptr [ebp-0Ch],eax
806b3efb 0f845bffffff    je      nt!PsLocateSystemDll+0x1ef (806b3e5c)
806b3f01 3d300100c0      cmp     eax,0C0000130h
806b3f06 0f8450ffffff    je      nt!PsLocateSystemDll+0x1ef (806b3e5c)

nt!PsNtDllPathName、nt!ZwOpenFile、nt!MmCheckSystemImageのコンボ辺りから、おそらくここでntdll.dllを読み出して、CRCを計算しているんだろうなと推測。nt!MmCheckSystemImageは、おもいっきりそれっぽい関数名をしているため、多分のここの戻り値を修正すれば通りそう。「cmp eax,0C0000221h」の定数「0C0000221h」は、エラーメッセージの番号と一致しているし。というわけで、デバッガからこのcmp命令でブレイクポイント仕掛けて処理を止め、戻り値(eax)を0に変更して、動かしたら、無事稼動完了! というわけで、nt!MmCheckSystemImageが元凶。

ただ、ntdll.dll変更して起動する際、毎回デバッガでアタッチするわけにもいかないため、CRCチェックの計算方法を解析してみる。 nt!MmCheckSystemImageの中を潜ってみる。

805a9427 e8a565f3ff      call    nt!ZwQueryInformationFile (804df9d1)
805a942c 8945e4          mov     dword ptr [ebp-1Ch],eax
805a942f 3bc6            cmp     eax,esi
805a9431 7c4a            jl      nt!MmCheckSystemImage+0x115 (805a947d)
805a9433 8975fc          mov     dword ptr [ebp-4],esi
805a9436 ff7584          push    dword ptr [ebp-7Ch]
805a9439 ff75e0          push    dword ptr [ebp-20h]
805a943c e8eafeffff      call    nt!LdrVerifyMappedImageMatchesChecksum (805a932b)
805a9441 84c0            test    al,al
805a9443 0f84535e0200    je      nt!MmCheckSystemImage+0xc5 (805cf29c)
805a9449 ff75e0          push    dword ptr [ebp-20h]
805a944c e88435f5ff      call    nt!RtlImageNtHeader (804fc9d5)
805a9451 8945d0          mov     dword ptr [ebp-30h],eax
805a9454 3bc6            cmp     eax,esi
805a9456 0f84405e0200    je      nt!MmCheckSystemImage+0xc5 (805cf29c)
805a945c 8d4804          lea     ecx,[eax+4]
805a945f 894dcc          mov     dword ptr [ebp-34h],ecx
805a9462 6681394c01      cmp     word ptr [ecx],14Ch
805a9467 0f853b5e0200    jne     nt!MmCheckSystemImage+0xf8 (805cf2a8)
805a946d 668178180b01    cmp     word ptr [eax+18h],10Bh
805a9473 0f852f5e0200    jne     nt!MmCheckSystemImage+0xf8 (805cf2a8)
805a9479 834dfcff        or      dword ptr [ebp-4],0FFFFFFFFh
805a947d ff75e0          push    dword ptr [ebp-20h]
805a9480 6aff            push    0FFFFFFFFh
805a9482 e8596ff3ff      call    nt!ZwUnmapViewOfSection (804e03e0)

完全にそれっぽい処理をしている部分が見つかる。nt!LdrVerifyMappedImageMatchesChecksumとかが多分CRCチェックルーチンだと推測。この中に潜る。

805a932b 8bff            mov     edi,edi
805a932d 55              push    ebp
805a932e 8bec            mov     ebp,esp
805a9330 56              push    esi
805a9331 57              push    edi
805a9332 8b7d0c          mov     edi,dword ptr [ebp+0Ch]
805a9335 8d4701          lea     eax,[edi+1]
805a9338 d1e8            shr     eax,1
805a933a 50              push    eax
805a933b ff7508          push    dword ptr [ebp+8]
805a933e 6a00            push    0
805a9340 e8a4ffffff      call    nt!ChkSum (805a92e9)
805a9345 ff7508          push    dword ptr [ebp+8]
805a9348 8bf0            mov     esi,eax
805a934a e88636f5ff      call    nt!RtlImageNtHeader (804fc9d5)
805a934f 85c0            test    eax,eax
805a9351 7436            je      nt!LdrVerifyMappedImageMatchesChecksum+0x4e (805a9389)

さらにnt!ChkSumというチェックルーチンがあった。多分これがアルゴリズム部分かな。

nt!ChkSum:
805a92e9 8bff            mov     edi,edi
805a92eb 55              push    ebp
805a92ec 8bec            mov     ebp,esp
805a92ee 8b4d10          mov     ecx,dword ptr [ebp+10h]
805a92f1 85c9            test    ecx,ecx
805a92f3 7424            je      nt!ChkSum+0x30 (805a9319)
805a92f5 8b450c          mov     eax,dword ptr [ebp+0Ch]
805a92f8 56              push    esi
805a92f9 0fb710          movzx   edx,word ptr [eax]
805a92fc 015508          add     dword ptr [ebp+8],edx
805a92ff 8b5508          mov     edx,dword ptr [ebp+8]
805a9302 8b7508          mov     esi,dword ptr [ebp+8]
805a9305 40              inc     eax
805a9306 c1ea10          shr     edx,10h
805a9309 81e6ffff0000    and     esi,0FFFFh
805a930f 03d6            add     edx,esi
805a9311 40              inc     eax
805a9312 49              dec     ecx
805a9313 895508          mov     dword ptr [ebp+8],edx
805a9316 75e1            jne     nt!ChkSum+0x10 (805a92f9)
805a9318 5e              pop     esi
805a9319 8b4508          mov     eax,dword ptr [ebp+8]
805a931c c1e810          shr     eax,10h
805a931f 034508          add     eax,dword ptr [ebp+8]
805a9322 5d              pop     ebp
805a9323 c20c00          ret     0Ch

なんだこのシンプルさは…、すばらしす。処理の内容的には、2バイトずつの単位で加算していき、桁あふれが起こったら+1という具合。

計算方法は分かったので、今度は比較対象となるCRC値が格納されている部分を探したい。多分nt!RtlImageNtHeader辺りで取ってきているだろうから、ntdll.dllのヘッダにあるのかな…。

(後編に続く…、かも…)

2008-08-13

夢のような日々が過ぎていって…(「Black Hat USA 2008」レポ)

一週間ほどラスベガスに行っていましたが、日本時間2008年/08月/12日の18時ちょうどに、無事家に帰り着きました。初めてのUSA、初めてのラスベガス、初めてのBlack Hat USAでしたが、本当に夢のような日々でした。もしかしたら、これまでの僕の人生でもっとも楽しかった時間だったかもしれません。

僕は日本で開催されたBlack Hat Japanにも参加した経験があるのですが、Black Hat USAはその10倍以上の規模があり、プレゼンの内容も多岐に渡ります。やはり、本場のUSAだけあって、セキュリティに関心のある人が多いのかもしれません。さらに特徴的なのが、USAではバイナリ解析やリバースエンジニアリング、カーネル Hackingなどがメジャーで、Webアプリ系の脆弱性解析が日本ほど主流ではありません。僕はバイナリ系の人間なので最高に楽しい日々でしたが、日本のWeb系のエンジニアの方は「今回はハズレが多いですよー」とプレゼンの内容にガッカリしていました。

また、今回、FFR(株式会社フォティーンフォティ技術研究所)の村上氏が「A Hypervisor IPS based on Hardware Assisted Virtualization Technology」という内容でプレゼンを行いました。プレゼンを行う以上、技術力(コンピュータスキル)だけでなく、英語力や文化の違いによるプレゼンの進め方(どう見せれば向こうの人に面白く感じてもらえるか)など、多くのことが必要になります。新たにもうひとつ言葉を学ぶということ、世界で戦うということが、日本人にとっていかに難しく、困難なことであるかを思い知らされますが、同時に、この部分こそが、世界で戦えるセキュリティエンジニアか否かの違いかもしれません。そして、村上氏の英語は決して完璧なものではありませんでしたが、大多数のリスナー(お客さん)が最後まで席に座り、耳を傾けていたことを考えると、彼の研究内容の質の高さは、十分に認められたのではないかと思います。少なくとも、僕か感じた限りでは、村上氏の研究内容は、今回のBlack Hat USA 2008の中でも、ベスト5に入るほど優秀でハイレベルな技術力を要するものでした(本人は否定するかもしれませんが…^^;)。

USAだからといって、神の如し技術力を持ったエンジニアばかりでは決してありません。だからといって、日本と比べてどうなのか? と聞かれれば、そりゃやはり断然USAが高いわけですが、英語さえ習得すれば戦えないわけではないと僕は思いました(その英語がもっとも大きな壁だったりするわけですが…)。

ちなみに、あるアメリカ人ハッカーに「あなたはWeb系のセキュリティはしないのか?」と聞いたところ、「Webは簡単で退屈だから興味が湧かない」とかいいやがりましたw。一理あるけど、僕の知り合いのWeb系エンジニアはみんなWeb系全般をリスニングして「今回はハズレが多いねー」とか言ってたぞ。はるばる日本から来てありきたりの内容ばかり説明される日本人の気持ちも考えてくれよww。逆に僕はリバースエンジニアリングrootkitを中心に受けたので、かなりハッピーでした。米国ぐっじょぶ!


それで、帰ってきて早々ですが、やはり日本に帰ってくると現実に引き戻されて、やるべきことが多数溜まっていることに気づかされるわけです(汗)。とりあえず、メール確認ができなかったので、4日以降のメールの返信から始めたいと思いまつ。

2008-08-03

パスポート取れたので「Black Hat USA 2008」行きます

とりあえず、クレジットカードを2日前にゲット!(登録後2週間以上かかった(汗))。パスポートを5日前にゲット! 飛行機とホテルもそうとう高かったけど一応ゲット! というわけで、明日USAに発ちます。

飛行機は往復で15万から20万くらいかかりました(高いw)。ホテルは10万くらい(これも高いw)。4日の夜に出ても、時差の関係で4日の昼に到着っぽいので、結構時間あるので、観光でもしよかなと思ってまつ。

あと、一人だし、USA初めてだし、ぶっちゃけ空港からホテルまで行けるのか? って感じですが、きっと何とかなるだろ、って感じで楽観してます。自分の英語力がどれくらい通用するか知りたいってのもあるし。ただ、USAは銃社会なので、万が一、新聞に「プログラマの邦人男性(24)、ラスベガスで銃殺される」とかニュースになったら、俺かもですw(本当に治安だけが心配ですよ)。

持っていくものは、海外で使えるケイタイ(SoftBank)、ノートPC、変圧器、着替え、くらいです。何もって行けばいいのか分からないし、そもそも僕は必要最低限のものしか持って行かない人なので、こんな感じです。変圧器はUSAと日本では電源自体が違うので、日本の電化製品を持っていく場合は、必ず必要らしいです。

お金は一応500ドルだけ用意しました。チップとかで現金が必要になるっぽいので。普通の買い物はカードで大丈夫と聞いたので、それでOKかと。

あとは言葉さえ通じればなんとかなるはずということで、自分の修行の成果に期待w。

2008-07-30

とりあえずSYSENTER呼んでる関数をCALLしている関数を集めてみた2

http://kenjinet.s26.xrea.com/syssys.txt

↑NTDLL.DLLを抜けるまで呼び出し履歴を追ってみたもの。基本的にKERNEL32.DLLとかADVAPI32.DLLとかまで追うけど、関数呼び出しを再帰させてたりすると、最後まで追いきれないので、NTDLL.DLLでストップさせる場合アリ。

これでSYSENTERフックしたときに、どのAPIが呼び出されてSYSENTERまで来たのかが、なんとなくわかるw。でもあくまでなんとなくなので…、というか、予想以上に多種多様なAPI関数から呼ばれてて笑ってしまった。

とりあえず「実践投入できるかどうか?」が自分的に結構ポイントなのですが、これだと微妙だw。というわけで、さらなるアイディアを考え中。

2008-07-29

少しずつ趣味の時間が取れてきました

仕事のプログラミングで徹夜 → きつい…、だるい…、俺はいったい何をやっているんだろう…

趣味のプログラミングで徹夜 → ちょw、もう朝かよww、おまっww、うわっまぶしいwww

2008-07-28

とりあえずSYSENTER呼んでる関数をCALLしている関数を集めてみた

http://kenjinet.s26.xrea.com/call_sysenter.txt

昨日のコメント欄で教えてもらったサイトより、とりあえずSYSENTER呼んでる関数をCALLしている関数を集めてみたが…、どこからも呼ばれていない関数(システムコール)があるのは何故なんだぜ!

というか、NtDeleteFileがどこからも呼ばれてないとか有り得ないだろ…(汗)。となると、kernel32.dllのDeleteFile関数辺りは、動的に関数アドレスを取ってきてNtDeleteFileを呼んでいるのか…? ちょと調べる必要がありそう…?

2008-07-27

どのシステムコールがどの関数から呼ばれているの?

http://d.hatena.ne.jp/kenjiaiko/20080724の続きっす

SYSENTER呼んでる関数は分かっても、そこからなるべく上位の関数に絞れないと実用性に欠けるのでなるべく絞れる感じにしたい。とりあえず、ntdll.dllがエクスポートしている関数を取ってきて、それらひとつひとつからCALL命令を取り出して、SYSENTER呼んでる関数をCALLしてたらログ↓にすることにした。

http://kenjinet.s26.xrea.com/call_systemcall.txt

収集方法はかなり適当で、関数内の処理から0xE8(CALL)を探して、それ以降の値からジャンプ先を特定。ジャンプ先がSYSENTER呼んでる関数のいずれかと一致したらログに保存。ただ、動的に関数アドレス取られてたりすると0xE8にならないのでアウト。また関数内のCALLを完全に追っているわけではないのでアドレス的に上下にある関数と間違ったりするかも。

個人的に、kernel32.dllのそれぞれの関数がntdll.dllの何の関数を呼んでいて、そのntdll.dllのそれぞれの関数がどのシステムコール呼んでるか? みたいな関数間の関係みたいなのを作成するライブラリが欲しい。それがあるとSYSENTERフックから上位のAPIが分かって結構使えるのかなと思う。

2008-07-24

SYSENTER実行時の識別コード表

カーネルに処理が飛ぶ場合にSYSENTERが呼ばれます。

7C94EB8B >/$ 8BD4           MOV EDX,ESP
7C94EB8D  |. 0F34           SYSENTER

このときeaxに識別コード(システムコールテーブルの関数呼び出し番号?)が入っています。

これは、SYSENTER呼び出し前にセットされます。

7C94E01B >/$ B8 9A000000    MOV EAX,9A        ←eaxに識別子セット
7C94E020  |. BA 0003FE7F    MOV EDX,7FFE0300
7C94E025  |. FF12           CALL DWORD PTR DS:[EDX] ←7C94EB8Bへジャンプ
7C94E027  \. C2 1400        RETN 14

というわけで、ntdll.dllがエクスポートしている関数で、

直接SYSENTERを呼んでいる関数を調べて、

その関数が使っている識別子(eaxの値)を調べました。

方法↓

ntdll.dllがエクスポートしている関数を調べて、その関数の先頭が

MOV EAX,xx
MOV EDX,7FFE0300
CALL DWORD PTR DS:[EDX]

となっていたら、関数名とxxの部分を取得するプログラム↓を作成。


#include <windows.h>
#include <stdio.h>

#include <imagehlp.h>
#pragma comment(lib, "imagehlp.lib")

#pragma pack(push, 1)
typedef struct _mov_code
{
    UCHAR code;
    DWORD sysenter_num;
    UCHAR ident[8];

} MOV_CODE, *PMOVE_CODE;
#pragma pack(pop)

int JudgeIdent(UCHAR *a, UCHAR *b)
{
    for(int i=0; i < 8; i++)
        if(a[i] != b[i])
            return 1;
    return 0;
}

int WriteData(void)
{
    UCHAR szIdent[8] = {
        0xBA, 0x00, 0x03, 0xFE, 0x7F, 
        0xFF, 0x12, 0xC2
    };

    DWORD dwBase = (DWORD)GetModuleHandle("ntdll.dll");
    if(dwBase == 0)
        return -1;

    DWORD dwSize;
    PIMAGE_EXPORT_DIRECTORY pExportDirectory = 
        (PIMAGE_EXPORT_DIRECTORY)
        ImageDirectoryEntryToData((LPVOID)dwBase, TRUE, 
        IMAGE_DIRECTORY_ENTRY_EXPORT, &dwSize);

    DWORD *pExportAddressTable = (DWORD *)
        (dwBase + pExportDirectory->AddressOfFunctions);
    WORD *pExportOrdinalTable = (WORD *)
        (dwBase + pExportDirectory->AddressOfNameOrdinals);
    DWORD *pExportNamePointerTable = (DWORD *)
        (dwBase + pExportDirectory->AddressOfNames);

    for(DWORD i=0; i < pExportDirectory->NumberOfFunctions; i++){
        PMOVE_CODE pmc = (PMOVE_CODE)(dwBase + pExportAddressTable[i]);
        if( pmc->code == 0xB8 && 
            JudgeIdent(pmc->ident, szIdent) == 0)
        {
            for(DWORD j=0; j < pExportDirectory->NumberOfNames; j++){
                if(pExportOrdinalTable[j] == i){
                    printf("%08X - %08X (%s)\n", 
                        pmc->sysenter_num, 
                        dwBase + pExportAddressTable[i], 
                        dwBase + pExportNamePointerTable[j]);
                }
            }
        }
    }

    return 0;
}

int main(int argc,char *argv[])
{
    if(WriteData() == -1)
        fprintf(stderr, "Error: WriteData\n");
    return 0;
}

実行して出来たもの↓

http://kenjinet.s26.xrea.com/sysenter_ident.txt

左から「eaxの値」「関数アドレス」「関数名」です。

とりあえずSYSENTERフックしたらこれだけの関数の呼び出し履歴は分かるわけですが、

低レイヤーになりすぎてるので、APIフックより断然分かりにくいです。

解析屋としては、使いどころを見極める必要がありそう…。

追記:Windowsバージョン別コード表rootkitさん thanx!)

2008-07-18

パスポート取れそうなので「Black Hat USA 2008」行きます

今日パスポートの手続きしてきました。

パスポート作成に必要なもの↓

  • 戸籍謄本
  • 身分を証明するもの(免許証とか)
  • パスポート用写真(写真屋でパスポート用写真お願いしますという)
  • ハガキ(その辺りのコンビニに売ってある)
  • 期限切れパスポート(もしあるなら)
  • 住民票(なくても良いけどあった方が若干スムーズ)

これらを自分が住んでいる(住民登録してある)県の「旅券事務所」とか「県民センター」とかに持っていった上で、パスポート作成の書類(一般旅券発給申請書)を書いて提出すればOK。早くて20分くらい、遅くても1時間以内には、登録完了。あと、パスポートを受け取るには、1万〜2万円くらい必要。出来上がるには1〜2週間くらいかかるから、受け取りのために再度行く必要アリ。


飛行機やホテルに関しては、旅行会社に電話すればOK。僕はFLEX Internationalという旅行会社に電話して、「8月4日くらいにラスベガスに行きたいんですが、どうすればいいでしょうか?」とか言えば、なんとかしてくれた。飛行機代は往復で15万〜20万くらいらしい。あと、飛行機を手配してもらったついでに「ホテルとかも実はまだとってないんですが、どうしたらいいでしょうか?」とか言えば、ホテルについてもいろいろとアドバイスしてくれる。相手は海外旅行のプロです。なんでも答えてくれます。モウマンタイです。


あとクレジットカードは必要だけど、現金も若干必要らしい(タクシーとかチップとか)。日本円で5万円くらい持っていけば問題ないようです。

2008-07-16

パスポート取れたら「Black Hat USA 2008」行きます

いや実際まったく行く予定じゃなかったのですが、

上司からの命令により行くことになりました(しかも一人で行って来いって…)。

ちなみに現状↓

  • パスポート取得してない
  • クレジットカード(VISAカード)ない
  • 飛行機まだ取ってない
  • ホテルまだ予約してない
  • とりあえず戸籍謄本は今日実家から送ってもらった

さらに、海外旅行は実質初めて*1なので、何すればいいのかまったく分からんです。

とりあえずホテルと飛行機予約しつつ、パスポートとVISAカードの申請すればOK?

無事行くことができたら、ここにいろいろとレポ書こうと思いまつ。


ちなみになんでVISAカードがいるんだろう? と思って海外旅行経験者に聞いてみたら

USAはカードが主流。いまどき現金なんて誰もつかってない。とか言われました。

*1:高校の修学旅行で行ったけど、学生なので手続きはほとんど全部学校側がやってくれるため、自分でやることはほぼ皆無でした

2008-07-13

ソフトウェア解析で一番大事なものは?

  1. アセンブルコードを読む技術
  2. 問題箇所を即座に特定できる鋭い嗅覚
  3. 折れない心

「3」と言わずにはいられない…orz

2008-07-10

国際ハッキングコンテスト DEFCON CTF 2007 の問題1

↓の画像が示している街の名前は何?

http://security2600.sakura.ne.jp/up/img/812.jpg

↓考え方

画像をバイナリエディタで開くと「Exif」という文字が出るので、ググる。すると、画像に関する付加情報みたいなものだと分かるので、Exif情報が確認できる画像編集ツールをゲット!(例:IrfanView)。Exif情報を見ていくと「GPS Information」なるものがある。位置情報っぽいものもそこに書かれてある(42 40 16.21 N 72 33 1.55 W)ので、それをGoogleMapsで検索。街の名前が出る(Bernardston)。問題としては、プログラミング系ではなく、画像フォーマット系の話。画像からどれだけの情報が得られるかという問題?

2008-07-09

世界的なセキュリティカンファレンス「Black Hat Japan 2008」のスピーカー受付が開始されました

「Black Hat Japan 2008 Briefings」発表資料(CFP)の募集↓(締切:9月1日)

http://www.blackhat.com/html/bh-japan-08/bh-jp-08-cfp-terms.html

2007年は、金床さんという日本人の方がスピーカーとして発表されました。彼はその日のNHKニュースでも取り上げられ、「今そこにある現実的な脅威」が大きくクローズアップされました。

2007年の日本人スピーカーは彼だけでしたが、日本人で優秀なセキュリティエンジニアはまだまだたくさんいると思うので、もし何かネタを持っていれば、どんどん応募した方がよいと思います。それにスピーカーとして参加すれば、参加費も無料ですし、世界各地の優秀なセキュリティエンジニアと情報をやり取りすることもでき、まさに一石二鳥です(さらに東京に住んでいなくとも、スピーカーならばホテルとか用意してくれるため、その辺りも心配ありません)。「お金は無いけどスキルは伸ばしたい」というそんなあなたにうってつけです。


…なんか、宣伝みたいになってしまいましたけど(汗)、ただ、せっかく日本でやるので、日本人のスピーカーがもっといてもいいんじゃないかなと思って(^^;。ちなみに僕自身は、「Black Hat USA 2008」のCFPに応募して落選した傷あとがまだ残っているので、ちょと考え中です。 …打たれ弱い? よく言われまつ…orz。

2008-07-07

今日ハマったこと

00001100 dword DCD 0x67452301
00001104 dword DCD 0xEFCDAB89
00001108 dword DCD 0x98BADCFE
0000110C dword DCD 0x10325476

ああー、MD5か〜、と思ってたら、

00001110 dword DCD 0xC3D2E1F0

SHA-1ですた…。1日無駄にした…orz。

プログラミングと解析の違い

プログラミングは、一本ずつ「木」を植えていって「森」を作る感じ。

解析は、一本ずつ「木」を切り倒しながら「森」から脱出する感じ。

2008-07-04

国際ハッキングコンテスト DEFCON CTF 2008 の問題1

↓これは何のライブラリ(libc)関数?

00000000     89C7           MOV EDI,EAX
00000002     89DE           MOV ESI,EBX
00000004     89CA           MOV EDX,ECX
00000006     C1E9 02        SHR ECX,2
00000009     F3:A5          REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
0000000B     89D1           MOV ECX,EDX
0000000D     81E1 04000000  AND ECX,4
00000013     F3:A4          REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
00000015     C3             RETN

↓考え方

使う値は3つ(EDI, ESI, ECX)で「SHR ECX,2」は、ECXの値を4で割ることと等価。EDIとESIはアドレスが入ることが「REP MOVS DWORD」命令から分かるので、とりあえず4バイトずつデータをコピーしている。またコピーされるデータは4の倍数バイトではない場合もあるので、4で割った余りのデータを、今度は「REP MOVS BYTE」でコピーして、RETNで終了。ただ『4で割った余りは「AND ECX,4」ではなく「AND ECX,3」なのでは?』と思ったけど、まぁだいたいの流れで問題の答えは分かるので気にしないこと(^^;。というわけで、答えは「memcpy」ですね。

国際ハッキングコンテスト DEFCON CTF 2008 の問題2

↓この状態で、EAXとEDXの両方を0にする、1バイトアセンブリ命令は何?

EAX = 0. EDX is undefined.

↓考え方

普通1バイトアセンブリ命令なんてpushとpopとretくらいしか覚えてないので、とにかくググる! もしくはx86命令セットリファレンスを熟読。検索能力を存分に発揮する。答えは「CDQ」。list of instructions参考

2008-07-03

再開します

すみません。忙しさのあまり、長らく更新してませんでした。

今日からまた頑張ります。とりあえず毎日更新が目標です。

CPUが違っても結構何とかなる罠

↓何をしているコードでしょう?

02000C14 E3A05000      MOV      R5, 0x0
02000C18 E3A04001      MOV      R4, 0x1
02000C1C EAFFFFFF      B        0x02000C20
02000C20 EA000001      B        0x02000C2C
02000C24 E0855004      ADD      R5, R5, R4
02000C28 E2844001      ADD      R4, R4, 0x1
02000C2C E3540064      CMP      R4, 0x64
02000C30 DAFFFFFB      BLE      0x02000C24

↓答え

00401153 33D2          XOR      EDX, EDX
00401155 B8 01000000   MOV      EAX, 0x1
0040115A 03D0          ADD      EDX, EAX
0040115C 40            INC      EAX
0040115D 83F8 64       CMP      EAX, 0x64
00401160 7E F8         JLE      0x0040115A

CPUが異なるといっても、結構何とかなるものです。きっと。

ただ、長くなるとやっぱりキツイですが…。

Connection: close