SlideShare ist ein Scribd-Unternehmen logo
1 von 84
Downloaden Sie, um offline zu lesen
リバースエンジニアリングのための新しいトレース手法
Niizh (Section 1b) : 背景と実装 (途中経過)
大居 司 (@a4lg)
このセッションでは:
• リバースエンジニアリングを効率的にする
―― かもしれない手法を紹介します。
• かもしれない ?
– (2010年11月時点で) VM 上で汎用 OS が動作しない。
• ライブデモができず申し訳ない!
– これにより、ある程度の推測なども含まれるため。
関連分野
• リバースエンジニアリング
– 特に動的解析、デバッガ、トレーサ
• Intel x86 (32-bit) アーキテクチャ
• 仮想化 / 仮想マシンモニタ (VMM)
– Record and Replay
• 異常検出と解析 (ハニーポットなど)
• バグ検出 (ファジングなど)
アジェンダ
• 多くの トレーサ が抱える問題
• Record and Replay を改良した提案手法
• x64 上における VMM の実装
• 部分的な検証
• 応用 (の可能性)
• トレース VM の課題
対象プラットフォーム
• Intel x86 (16/32-bit) アーキテクチャ
• PC/AT
• 汎用 OS (Windows, Linux etc...)
背景
Background
動的解析
• 動作しているプログラムに介入するなどして、
その挙動、内部構造などを解析する。
• 使用するツールは一般に多岐にわたる。(代表例)
– デバッガ
• OllyDbg, Windbg, IDA Pro...
– モニター
• Process Monitor, Wireshark...
– トレーサ
• API Monitor, OllyDbg, Process Stalker...
• 今回は トレーサのようなもの に関わる話題です。
トレーサ (1)
• コンピュータ内で発生した特定の
イベントをキャプチャ、保存する。
– 命令単位
– 基本ブロック / 関数単位
– API / システムコール / 入出力単位など
• 命令単位のトレース
– 自動解析の対象にすることが容易
(自動 unpacking などが代表的)
– コンピュータの内部状態を記録することができれば、
事実上コンピュータのすべてがトレースできる。
トレーサ (2)
• しかし、私が調査した命令トレーサには
共通する欠点があった。
– 遅い
• 1 命令単位でフックとトレースを行うため、
トレースに実時間の数十倍かかることも珍しくない。
– データ量が大きい
• 実時間換算 (仮にトレースが元のプログラムと同等の
速度で動作した場合) で数 GB/s のオーダー。
• トレースの書き込み処理そのものが
ボトルネックになってしまう。
トレーサ (3)
• この点を改善したトレーサを作成できないか?
• 主要な要件:
– トレースにかかる時間は、エミュレーションしない
環境と比較して 2 倍以内であること。
– トレースのサイズは、ネットワーク送信できる
ように 5MB/s 以下であること。
• このような要件を満たすトレーサをどのように
実装 (する¦した) かが今回のテーマです。
理論 ‒ Record and Replay
Theory ― Record and Replay
Record and Replay (0)
• 実のところ独自に発見したつもりだった。
– 文献を十分に調査していなかった。
• ReVirt : Enabling Intrusion Analysis through Virtual-
Machine Logging and Replay
– 既存の論文に当てはめれば、提案手法は
Record and Replay の変種に当たる。
– 両者は強く関連していて、分離が難しい。
• そのため、提案手法と Record and Replay を
まとめて解説する。
Record and Replay (1)
• 文献によって呼び方が異なる場合がある。
– Logging and Replay Lockstep など。
• 2 パス (Record + Replay) によって、トレースと、
そこからの情報の復元を行う。
• 一般的なアーキテクチャに共通する特長を
利用し、データ量を極めて小さく抑えている。
– 通常、ハードウェアなどからの入力は
その他の命令による操作よりはるかに少ない。
• 多くのアーキテクチャ (ここでは 1 CPU とする) は
次のようにモデル化することができる。
– 入力 (空の場合もある)
– 計算 / 処理 (+内部状態)
– 出力 (空の場合もある)
• ここで、出力は内部状態から一意に
与えられるものとする。(下式の関数 g)
• zn+1 = f(zn, in)
on+1 = g(zn+1)
Record and Replay (2)
入力
出力
計算/処理
+内部状態
• CPU の全状態を保存することは、ここでは
内部状態 (zn) をすべて保存することに相当する。
– 前述の定義により、出力は内部状態から
一意に決定できるため、出力はモデルから便宜上
省くことができる。
• 内部状態の初期値である z0 は別途与える。
• 計算/処理に相当する関数 f は、いわゆる
数学的な「函数」であること。
– 一定の入力で一定の出力を
行い、そこに曖昧さは無い。
Record and Replay (3)
入力
出力
計算/処理
+内部状態
• さらに依存関係を考える。
– 入力 : 他のいずれにも依存しない独立した値
– 計算 / 処理 (+内部状態) : 入力に依存
• この関係から…
– このモデルにおける内部状態は初期状態と
入力にのみ依存する。これだけをトレースすれば、
事実上コンピュータのすべてをトレースしたことに
なるのだ。
Record and Replay (4)
入力
計算/処理
+内部状態
• Pass 1 : Record
– 初期状態をキャプチャし、トレースに保存。
– すべての入力をキャプチャし、トレースに保存。
• ここでは、実際のハードウェアからの
入力を受け入れる。
• これにより、Replay パスで復元可能な
トレースを生成できた。
Record and Replay (5)
入力
トレース
計算/処理
+内部状態
初期状態
• Pass 2 : Replay
– 初期状態をトレースから復元。
– 仮想マシンを動作させる。ただし、すべての
入力はトレースから読み取る。
• つまり、新たなハードウェア入力は
受け付けない。
– 内部状態を読み取る。
• Record パスと非常に類似している。
Record and Replay (6)
入力
トレース
計算/処理
+内部状態
初期状態
利点 (1)
• これまでの説明なら単に 2 回実行するだけの
ようにも見えるが…
– トレースを用いて、いつでも、あるいは
何回でも Replay パスを実行できる。
• 解析結果が不十分ならば、別の解析手法を
適用することができる。
– 必要ならば Replay を並列に実行することもできる。
• 自動解析の時間を短縮できる可能性がある。
(実際には解析の依存関係の問題がある。)
利点 (2)
• (続き)
– Replay パスの実行は Record パスに何の影響も
与えない。これらはまったく独立している。
• どのような解析をしても Record パスは遅くならない。
• Replay パスにおいて詳細な、これまで使用
が難しかった解析手法が適用できる可能性もある。
(ポインタの追跡や依存性解析など。)
• これらのことから、この手法は
リバースエンジニアリングとの親和性が高い。
実例 (1)
• VMware Workstation (6 以降)
– 記録と再生 機能がこれに該当する。
• 実行を記録してビデオと同様に再生したり、
あるいはデバッグのために使用できる。
– プロプライエタリであり、また堅牢性が高いとも
言えないが、確かにこの理論を実用化した例である。
– トレース出力は一般に 1∼10MB/s
実例 (2)
• VMware Workstation (6 以降)
– ただし…
• VMware である (バックドアなどがよく知られている)
• デバッグインタフェースが十分ではない。
– デバッグ機能さえ充実していれば
リバースエンジニアリングに使えたかも…。
• その他の例
– ReplayDIRECTOR (Java デバッグツール)
– Jockey (Linux 用記録 / デバッグ補助ツール)
• http://home.gna.org/jockey/
• すべての決定論的でない要因を 入力 として
扱うのは単純だが、VMM の実装には不向き。
– データ入力のタイミングなどを考えれば、
不効率極まりない格納方法になる。
• そこで、この 入力 をさらに細分する。
– 決定論的でない入力
– 割り込み
• ただし、名称と内容は
必ずしも一致しない。
x86 への適用 (1)
入力
トレース
計算/処理
+内部状態
初期状態
• 決定論的でない入力
– x86 の in 命令のように、内部状態が不確定になる
タイミングは一意に決定できる。
– ただし、その具体的な内容までは決定できない。
– この場合、具体的な値や内容を保存する。ただし、
そのタイミング情報は保存しない。
• 先行する入力や割り込みでタイミングを
確定できるため、タイミング情報は余分である。
x86 への適用 (2.1)
• 割り込み
– x86 のハードウェア割り込みに代表されるように、
そのタイミングが不定 (一意に決定できない。)
– また、その具体的内容も決定論的でない場合がある。
– この場合、タイミング情報を保存する。また、
割り込みの具体的内容が決定論的でない場合、
その内容も保存する。
• ハードウェア割り込みでは、その割り込み
ベクトル番号などがそれに該当する。
• これらの分類をベースに、VM 内部すべての要素を
適切にモデル化することが最も重要である。
x86 への適用 (2.2)
• モデル化 ― VM の内部ディスク
– VMM の内部ディスクは信頼できると仮定し、
開始時の初期状態を記録する。
– ほとんどを決定論的とみなし、トレースを原則として
行わない。ただし、ディスクが発生させる割り込みは
割り込み として記録する。
• 読み取られたディスク内容は、以前に書き込んだ
ディスクの内容と同一であることが保証されるため。
• ただし、ATA 割り込みなどのタイミングは
一定とならないため、 割り込み とみなせる。
x86 への適用 (3.1)
• モデル化 ― マウス、キーボード、ネットワーク
– これらは外部からの予測できない入力である。
– デバイスからの入力は、割り込みと入力の両者を
使用するため、 割り込み と 決定論的でない入力
の複合的要素として扱う。
– ネットワーク出力は内部状態から決定できるため、
トレースを行わない。
x86 への適用 (3.2)
• モデル化 ― CPU のタイムスタンプカウンタ
– RDTSC などで読み取ることの可能な、
リセット時からカウントされるクロック数。
– 決定論的でない入力 とみなす。
– 物理的な位置が CPU 内部だったとしても、決定論的な
モデル化が不可能である場合には外部入力と同様に
扱うべきである!
• もしモデル化が可能であったとしても
ほとんどの場合効率が下がってしまうため、
敢えて決定論的でないとみなすことが効率の
向上につながる。
x86 への適用 (3.3)
• モデル化 ― CPU の例外
– 例外はほとんどの場合発生するタイミングが
決定論的である。またほとんどの場合、
例外処理の内容も決定論的に行われる。
– そのため、前述のどちらとしても扱わない。
• モデル化 ― CPU の不定値
– 具体例は多数あるが、特定の操作を行った後、
CPU の内部状態の一部が不定となることがある。
この場合、タイミングは特定できるものとする。
– 決定論的でない入力 とみなす。
x86 への適用 (3.4)
• モデル化 ― 厳密値のない算術命令
– FSINCOS, FATAN などの超越関数命令は IEEE 754 の
規定に従った丸めを行うことが不可能であるため、
満たすべき精度のみが定義されている。
– 具体的な値を特定できる最低限の情報を
決定論的でない入力 とみなす。
• などの様に、CPU 内外のあらゆる要素を
モデル化する必要がある。
– 本理論に基づく VMM を作成する最大の障害。
x86 への適用 (3.5)
x86 への適用 (4)
• あるものを 決定論的でない要因 として
扱うとはどのようなことか?
– フックとトレース回数を増やすこと。
– つまり、トレースは大きく、速度は遅くなる。
– このような状況は可能な限り減らしたほうが良い。
• 設計当初、このような要因の発生する回数は
一般命令数の多さに比べれば極めて小さく、
それほど問題とならないと考えていた。
– しかし、それは間違っていた。
例えば次の例:
• 次の命令は決定論的か否か
XOR edx, edx
– x86 のアセンブリを読んでいれば
ご存知のように、edx を 0 にする命令だ。
– しかし、前述の答えは No だ。
• 実際にはこのような命令を含めて、極めて多数の
命令が内部状態の一部を不定にしてしまう。
– EFLAGS だ。
EFLAGS の呪い? (1)
• それでは内部状態を詳しく見てみよう。
– edx は 0 になっているが、
同時に EFLAGS.AF が ? になっている。
– このとき、AF の値はマニュアルによって
未定義 (undefined) とされている。
xxx......xxx
000......000
x x x x x x
0 0 1 ? 1 0
XOR edx, edx
(next instruction)
OFedx SF ZF AF PF CF
EFLAGS
EFLAGS の呪い? (2)
• もちろんこれだけではない!
– 頻繁に使用される下記命令も同様!
– 下記のものを含め、x86 の全実行命令のうち
10∼15% がフラグの一部を不定にする。
0 M M ? M 0 AND, OR, XOR, TEST (論理演算)
OF SF ZF PF CFAF
M ? ? ? ? M MUL, IMUL (乗算)
? ? ? ? ? ? DIV, IDIV (除算)
? M M ? M ? SHL, SHR, SAL, SAR count (シフト)
EFLAGS の呪い? (3)
• 全く 小さく などないではないか!
– 10% 程の命令であったとしても、フックにどれだけ
時間を要するかを考えれば全く無視できない。
– これらの不定値を トレース するのでなく、
決定論的な値に置き換えることも考えられるが…
フラグを置換するのに必要な POPF 命令は
極めて時間がかかる (割り込みにも劣らない)。
• Intel Nehalem MA で 24-25 clocks
– 現実的な速度でトレースするには、
これらのトレースを何とか回避する必要がある。
実装に内在する問題
• 公開されている既存実装はこれらの不定要素に
対して最低限の対処しかしていない。
– 同一の CPU ファミリで両者を動かす場合に限定。
– 一般にアプリケーションは不定値に依存しないが、
1-bit の不定値であってもカオスを引き起こしうる。
• 堅牢性がない。
– トレースを複数の手段で復元した場合、
そのうちのどれが正しいかを特定できない。
• 情報の集積に支障を来しうる。
• 移植性に乏しい。
EFLAGS の遅延評価 (1)
• しかし、EFLAGS には次の特性もある。
– 更新されたフラグが使用されるとは限らない。
(現に、80%以上のフラグは単に破棄される。)
– フラグの更新と参照は大抵セットになっている。
• 比較命令 + 条件分岐命令のように。
• Intel は Macro-Fusion でそのような最適化を行う。
– では不定値はそれが使用されるまで許容し、
それ以外の内部状態に影響を与える場合に
トレースするのはどうか?
• 実験では極めて効果的であった。
EFLAGS の遅延評価 (2)
• 現時点での遅延評価実装:
– これは、JIT コンパイル時に行う。
(実行時評価の排除。高速化に寄与。)
– 実行に寄与するブロック毎に評価する。
• 分岐などで到達した地点から次の無条件分岐
(例外などを含む) までの命令列を指す。
• このブロックについて順方向に命令をスキャンする。
– 仮想的なフラグ (6-要素) の伝播を計算する。
• 決定論的/不定の二値 (ブロック開始時 : 不定)
• 最後にフラグの値を更新した命令。
• 一定条件下でヒューリスティクスも使用可能。
EFLAGS の遅延評価 (3)
• (実装続き)
– ブロック内の命令がフラグに依存し、対応する
仮想フラグが次の条件を満たす場合、
暫定的な不定値としてトレースする。
• 仮想フラグが不定である。
• 仮想フラグは決定論的だが、更新した命令が
32-bytes or 8-instructions 以上前である。
(上記打ち切りはパラメータで設定する。)
• 現段階では極めて効果的である。
– 実験段階では、トレースしたフラグのほぼ全てが
割り込み / コンテキストスイッチに絞り込まれた。
Record and Replay : まとめ
• Record and Replay を使用することにより、
トレースのオーバーヘッドとデータ量をともに
削減することができる。
• 改善された手法により、
x86 において堅牢的なトレースを取得できる。
実装
Implementation
実装
• VMM ベースのトレーサを実装する。
– 汎用 OS を動作させるため。
• しかし良い選択ではなかったようだ。
その複雑さのため、現時点 (2010/11) では
VM 上で OS を動作できるほど完成しなかった。
– バイナリ変換ベースの VM
– x86 を対象 (ゲスト) とし、x64 をホストとする。
• 様々な観点から、x86 のバイナリ変換には
x64 が優れている。
x86 on x64 (1)
• x64 は x86 の 64-bit 拡張
– 命令フォーマットも x86 (32-bit) のものと類似。
– ただし、幾つかの拡張が施された。
• 汎用レジスタと XMM レジスタの倍増 (8→16)
• 新しいアドレッシングモード
(64-bit、RIP [program counter] 相対)
• x86 のバイナリ変換を容易にする要素が
多数存在する!
x86 on x64 (2.1)
• Benefit : 32-bit レジスタの clamp
– x64 のレジスタは x86 のものを拡張したものである。
• 例 : ax (16-bit), eax (32-bit), rax (64-bit)
– ここで、32-bit レジスタを格納先とする
演算を行うと、対応する 64-bit レジスタの上位
32-bit がクリアされる。(これはロングモード固有)
0123
0123
4567
1234
MOV eax, 0x01234567
MOV ax, 0x1234
eax
ax
x86 on x64 (2.1)
• Benefit : 32-bit レジスタの clamp
– x64 のレジスタは x86 のものを拡張したものである。
• 例 : ax (16-bit), eax (32-bit), rax (64-bit)
– ここで、32-bit レジスタを格納先とする
演算を行うと、対応する 64-bit レジスタの上位
32-bit がクリアされる。(これはロングモード固有)
01234567
00000000
89abcdef
12345678
MOV rax, 0x0123456789abcdef
MOV eax, 0x12345678
rax
eax
x86 on x64 (2.2)
• Benefit : レジスタの増加 (汎用/XMM)
– 8→16 個に増加。(XMM 含めた増加分は 16 個)
– エミュレータやトレーサの状態を、
既存のレジスタを破壊することなく格納可能。
rax r8
rcx r9
rdx r10
rbx r11
rsp r12
rbp r13
rsi r14
rdi r15
xmm0 xmm8
xmm1 xmm9
xmm2 xmm10
xmm3 xmm11
xmm4 xmm12
xmm5 xmm13
xmm6 xmm14
xmm7 xmm15
x86 on x64 (2.2)
• Benefit : レジスタの増加 (汎用/XMM)
– 8→16 個に増加。(XMM 含めた増加分は 16 個)
– エミュレータやトレーサの状態を、
既存のレジスタを破壊することなく格納可能。
eax cs.base
ecx es.base
edx emuinfo
ds.base ebx
stack esp
ebp tmp2
esi ss.base
tmp1 edi
xmm0 fs.base
xmm1 gs.base
xmm2 tmp3
xmm3 tmp4
xmm4 notused
xmm5 notused
xmm6 notused
xmm7 notused
実際のレジスタ再配置マップ。
このマップに従い命令を変換す
る。
レジスタ使用を効率化するため、
一部の x86 レジスタは再配置
されている。
x86 on x64 (2.2)
• Benefit : レジスタの増加 (汎用/XMM)
– 8→16 個に増加。(XMM 含めた増加分は 16 個)
– エミュレータやトレーサの状態を、
既存のレジスタを破壊することなく格納可能。
– xmm レジスタはそのままでは使用が難しいが、
movq 命令を使用して汎用レジスタに転送する。
x86 on x64 (2.3.1)
• Benefit : アドレッシングの 非 変化
– アドレッシングモードは追加されたものもあるが、
基本は x86 のものをそのまま 64-bit 拡張しただけ。
– x86 は元々複雑なアドレッシングモードを持つ。
• [esi+edx*4+123] のような複合演算も可能。
• これを利用して、メモリ領域の隔離を行う。
– アドレス : [segbase+offset]
• すべてのメモリアクセスは、セグメントベース
(64-bit アドレス) との相対オフセットでアクセスする。
– メモリ領域さえ確保しておけば、その外に
アクセスが漏れることがない。
x86 on x64 (2.3.2)
• Benefit : アドレッシングの 非 変化
– 例 (1) : inc [ds:ecx] → inc [rbx+rcx]
• rbx : DS セグメントのベースアドレス
• rcx : ゲストの ecx レジスタ
– 32-bit レジスタの値を 64-bit として
読み取っている! (そんなやり方で大丈夫か?)
• 問題ない。前述したように 32-bit 演算の結果は
32-bit 範囲にしかならないため、アクセスされる領域を
完全にコントロールすることができる。
x86 on x64 (2.3.3)
• Benefit : アドレッシングの 非 変化
– 間違った例 (2) : inc [ds:ecx+edx] → inc [rbx+rcx+rdx]
• 一時レジスタに中間結果を格納する。
– 正しい例 (2) : inc [ds:ecx+edx] →
lea edi, [rcx+rdx] ; inc [rbx+rdi]
• edi/rdi : 一時レジスタ
• これ以外はほとんど変わらない。
– 一番良いエンコーディングを頼む。
• 64-bit のアドレス計算結果を 32-bit レジスタに格納。
• これも正当なエンコーディングで、結果が 32-bit に
切り詰められ、さらに命令が短くなる。
x86 on x64 (2.4.1)
• Benefit : 広大なメモリ領域
– アドレス幅は 64-bit
• 有効な論理アドレスは 48-bit (符号拡張される。)
• 例 : 0x0000_1234_5678 → 0x0000_0000_1234_5678
• 例 : 0x8000_1234_5678 → 0xffff_8000_1234_5678
– ゲストがアクセス可能な場所の外に
VMM だけが使用するデータやコードを配置できる。
• x86 on x86 ではアドレス空間が双方とも 4GB であり、
双方のアドレスを圧縮しなければ配置できない。
• VMM の性能が向上する。
x86 on x64 (2.4.2)
• Benefit : 広大なメモリ領域
– ただし問題がある。64-bit でアドレス計算を行った
結果は 32-bit の範囲を超えることがある。
– x86 (32-bit) は、32-bit におけるアドレス計算の
オーバーフロー、アンダーフローを無視する。
つまり、64-bit でアドレス計算を行った場合、
下位 32-bit がアクセスされるアドレスである。
– ここで下位 32-bit が等価 == アドレスが等価という
状態を作り出す。メモリに見かけ上のループを
作り出すのだ。
x86 on x64 (2.4.3)
• Benefit : 広大なメモリ領域
– 仮想メモリ空間を確保する。
– アドレスのオーバーフローなどを考慮し、
下に示す最大 44.5GB の連続領域を確保する。
• 赤と青の領域 (4GB) は同じ 物理的領域を指す。
• これはページテーブルを使用することで達成可能。
44.5GB
42.25GB
2.25GB
x86 on x64 (2.4.4)
• Benefit : 広大なメモリ領域
– セグメントやアクセス制御毎に定義する。
• ページテーブル置換を省略できる。
cs.base
ds.base
es.base
ss.base
data3
code0
data3
code3
x86 on x64 (2.4.4)
• Benefit : 広大なメモリ領域
– セグメントやアクセス制御毎に定義する。
• ページテーブル置換を省略できる。
cs.base
ds.base
es.base
ss.base
data3
code0
data3
code3
x86 on x64 (2.5.1)
• Benefit : シンプルになったアーキテクチャ
– x64 のアーキテクチャは比較的単純化され、
OS 上に Type-2 VMM を構築することが容易。
• 割り込みハンドラの種類の減少
– 割り込みゲートとトラップゲートの二種類のみ。
• セグメント機構の事実上の形骸化
– CS, DS, ES, SS セグメントについて
フラットメモリモデルを採用。
– IDT (割り込みベクトル) を置き換えることで、
VM 専用のコンテキストを確保する。
• PatchGuard の有効な Windows でも安全に動作する。
x86 on x64 (2.5.2)
• Benefit : シンプルになったアーキテクチャ
– 割り込みをパススルーする。
• IDT の切り替えによって安全に行える。
• 若干オーバーヘッドがある。
VM OS
実際にはもう少し複雑だ
が、
ここでは概略のみ示す。
IDT switch
IDT switch
OS Kernel
VM Trampoline
OS IntHandler
VM Entry
VM IntHandler
VM Kernel
x86 on x64 (3)
• 以上の機構を用いて VMM を実装する
– …のだが、現時点での完成度は低い。
• タイミングをトレースするには、
次の情報があればよい。
– 分岐カウンタの値 (ソフトウェア実装も可能)
– 現在のプログラムカウンタ (IP, EIP)
– 繰り返しカウント (CX, ECX)
• rep 命令が実行中だった場合のみ。
– いくつかこれについては例外があるのだが、
今回の範囲を著しく逸脱するため省略。
Everything into the Ring-0
• 権限の隔離は必要?
– JIT コンパイルされたコードは適切に隔離され、
管理された領域以外にはアクセスできないため、
すべてのコードを Ring-0 で実行可能。
• セキュリティチェックの一部を省略するなど、
フックや VMM のオーバーヘッドを
大きく減らすことができる。
• 現在の実装は Ring-0 上にすべてを構築している。
– セキュリティ上この動作が危険であれば、
Ring-3 で動作させることも理論上可能。
検証
Tests
トレースサイズの検証 (1.1)
• トレースに必要なデータ量
– Bochs (2.45) 付属の DLX Linux 起動シーケンス
• リセットからログイン画面の表示まで
• 52,217,403 instructions (実時間換算 : 約 53 秒)
– 各種スペック
• 1 MIPS (1,000,000 instructions/sec)
• 32MB MEM, 10MB HDD
– Bochs のトレース機能で出力したテキスト形式の
トレースを、提案手法と幾つかの対照手法の
理論に従って変形する。
トレースサイズの検証 (1.2)
• トレースに必要なデータ量
– 初期状態のサイズは含まない。
– Bochs 組み込みデバイスについて、
そのモデル化を行い、対応するトレースサイズの
導出も行った。
– ただしモデル化は簡易的なものであるため、
サイズは近似となる。
トレースサイズの検証 (1.3)
• 手法 (比較対象含む)
– Raw
Bochs が出力する命令/メモリトレース (テキスト)
– Verbose
一般的なトレーサが出力するトレース量の目安
– Dumb
読み取ったメモリを記録する、マルチコアに適した
Record and Replay 類似の方式
– RnR (1)
Record and Replay (EFLAGS をトレースする)
– 提案手法
改良された Record and Replay アルゴリズム
– RnR (2)
Record and Replay (EFLAGS の不定値を無視する)
トレースサイズの検証 (2.1)
手法 サイズ (bytes)
Raw 7,178,948,236 6.68GB
Verbose X > 419,430,400 400MB
Dumb 60,713,538 57.90MB
RnR (1) 6,932,542 6.61MB
提案手法 389,013 380KB
RnR (2) 31,788 31KB
ここに示すように、提案手法を含む Record and Replay 法は
極めて小さなトレースで同様のデータを表現できる。
一般的なトレーサの目安に相当する Verbose の数値に比べて
1/1,000 というサイズを達成している。
トレースサイズの検証 (2.2)
10,000
100,000
1,000,000
10,000,000
100,000,000
1,000,000,000
10,000,000,000
サイズ (bytes)
トレースサイズの検証 (2.3)
• まとめ
– この結果は実際の VMM から取得したものではない
ため、実装が要件を満たすかという点については
若干の疑いもある。
– しかしながら、他のトレース手法よりはるかに
小さいトレースを生成することだけはほぼ
確実といえる。
オーバーヘッド
0
10
20
30
40
min max
without Tracer
with Tracer
応用
Application
応用の可能性 (1)
• リバースエンジニアリング (一般)
– 動いた ものはすべて 明らか になっている。
• すべてのプログラムの動作はトレース中に
保存されているため、必要な情報はいつでも
ここから抽出できる。
• アンチデバッギングや VM 検出さえ回避すれば、
プログラムの正常な動作を完全に記録できる。
– unpack されたプログラムコードももちろん含まれる。
• 複数種類の解析を統合することができる。
応用の可能性 (2)
• アンチデバッギングの回避
– よく知られたバックドアは存在しないため、
既存手法での VM 検出は困難である。
– しかし、バイナリ変換ベースの VMM は
パフォーマンスに特有の癖が出てしまう。
• 自己書き換えによって極端に遅くなる、など。
– もちろんどのように VM 検出が行われたかという
部分は解析が可能であるため、最悪でも
次の解析を容易にするための情報は収集できる。
• 一般的なプログラムがもつプロテクトであれば、
二度目の実行により高い確率で回避できるだろう。
応用の可能性 (3)
• リバースエンジニアリング (マルウェア)
– 今のところ、ソフトウェアを「そのまま」動作させる
ことのみ想定しているため、マルウェアを VM 上で
動作させることは危険である。
• マルウェアの解析に関して言えば、従来の
エミュレータ使用のアプローチの方が安全かも。
– ただし、その点に適切な対処ができる場合、
マルウェアの動作を確実に分析できるだろう。
– ハニーポットへの適用もあり得る
応用の可能性 (4)
• ファジング / 脆弱性分析 / バグ解析
– OS 全体に Valgrind を適用したような、
高い精度、粒度の解析が可能である。
– 非リアルタイム解析により、メモリ破壊の位置や
その影響などを追跡できる。
– 再現性の低い脆弱性であっても、一度動作すれば
その実行パスを詳細に分析できる。
– ただし、ファジングを効率的に実行できるかは
実際の VMM 実装に強く依存する。
応用の可能性 (5)
• 解析の補助
– 特定ツールのためのデータを出力する。
• Wireshark のパケットダンプなど
– このとき、プログラムの動作を考慮に入れて
メタデータや追加処理を付加できるだろう。
• 例えば SSL/TLS の自動復号など。
盗聴や外部からのモニタリングによる復号は不可能
だが、VMM 上で動作させた場合には共通鍵を持つ
端点をモニタできる。
応用の可能性 (6)
• <<Place Entry Here>>
– VMM 上で起こるほぼ全てを保存できると
いうことは、他の応用も色々あるかも…。
– (マルウェア解析などの) 現場に携わったことのない
私よりも真価を発見できる方は多いかと。
課題・まとめ
Future Challenges / Conclusion
課題 : マルチコア (1)
• Record and Replay はそのままでは
マルチコアに応用できない。
– 複数の CPU が密に連携を取ることを想定していない。
– 先行例である VMware Workstation も私の実装も、
1 CPU/thread の実行にのみ対応する。
• ただし、全く不可能というわけでもない。
(一長一短はあるのだが。)
– タイムスライスによる時分割
– MESI プロトコルのソフトウェア実装
– メモリ内容をトレースする
課題 : マルチコア (2)
• タイムスライスによる時分割
– 同時に実行する仮想 CPU は 1 個のみ。
– ただし複数の仮想 CPU を切り替えながら実行する
ことで、複数の CPU が動作しているように
見せかける。
• Pros.
– 同期処理の必要性がほとんどないこと。
• Cons.
– 仮想 CPU の数に比例して性能が悪くなる。
– マルチスレッド特有の問題の再現が困難になる。
課題 : マルチコア (3)
• MESI プロトコルのソフトウェア実装
– メモリ一貫性アルゴリズムの一種
– マルチコアなどの環境においては、CPU 内部の
ハードウェアはこれらのプロトコルを用いて
メモリの状態を適切に管理する。
– これをソフトウェア (ページ単位) で実装する
• Pros.
– 共有メモリが少ない場合、性能が向上し易い。
• Cons.
– ソフトウェア実装は極めて遅い。
課題 : マルチコア (4)
• メモリ内容をトレースする
– 複数 CPU で共有されるメモリ領域について、
そこからの読み取り結果をトレースする。
• Pros.
– 一般に性能が向上し易い。
• Cons.
– 厳密には完全情報ではなくなる。
(どの CPU が書き換えた情報かの追跡が困難。)
– メモリトレースは遅い。
課題 : 64-bit / その他
• x64 on x64 の VMM 実装は極めて困難。
– 方法が無いわけではないが、実装コストと
オーバーヘッドがかかる。
• SSE2 の逆数 / 逆数平方根命令
– 精度が保証されないためかなり高速な命令であり、
不定値としてのトレースが難しい。
• 結局ハイパーバイザベース?
– 移植性を確保するには、生成したトレースに対して
別パス、同 CPU モデルで不定値を付加する。
– これは完璧ではないが、あり得る選択肢である。
注意 : 特許
• 構成技術の一部は特許化されている!
– Record and Replay の基礎部分
– バイナリ変換 VMM の高速化に関するアルゴリズム
– これらの回避は極めて難しい / 不可能である
• 確認した限りでは PCT 出願のない米国特許であり、
米国外で使用する分には特に問題無いと考えられ
る。
– が、利用には気をつける必要があるかも知れない。
まとめ
• ここでは、x64 上に x86 仮想マシンを構築し、
トレースする手法について解説した。
• 提案手法を用いれば、トレースが小さくなり、
さらにオーバーヘッドも小さくなる。
– ただし、リバースエンジニアリングに十分
使用できるか否かについては十分な検証が待たれる。
• トレースは様々な応用が可能である。
– 紹介した以外にもあるかもしれない。
contact me at : li at livegrid dot org
Open Source Project : Niizh
will be available at http://niizh.org/
Thank you!
Any questions?

Weitere ähnliche Inhalte

Was ist angesagt?

いいかげんな人のためのTransactional Memory Primer
いいかげんな人のためのTransactional Memory Primerいいかげんな人のためのTransactional Memory Primer
いいかげんな人のためのTransactional Memory Primer
Yuto Hayamizu
 

Was ist angesagt? (20)

2章 Linuxカーネル - メモリ管理1
2章 Linuxカーネル - メモリ管理12章 Linuxカーネル - メモリ管理1
2章 Linuxカーネル - メモリ管理1
 
【学習メモ#6th】12ステップで作る組込みOS自作入門
【学習メモ#6th】12ステップで作る組込みOS自作入門 【学習メモ#6th】12ステップで作る組込みOS自作入門
【学習メモ#6th】12ステップで作る組込みOS自作入門
 
【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門 【学習メモ#7th】12ステップで作る組込みOS自作入門
【学習メモ#7th】12ステップで作る組込みOS自作入門
 
いいかげんな人のためのTransactional Memory Primer
いいかげんな人のためのTransactional Memory Primerいいかげんな人のためのTransactional Memory Primer
いいかげんな人のためのTransactional Memory Primer
 
4章 Linuxカーネル - 割り込み・例外 5
4章 Linuxカーネル - 割り込み・例外 54章 Linuxカーネル - 割り込み・例外 5
4章 Linuxカーネル - 割り込み・例外 5
 
【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門【学習メモ#1st】12ステップで作る組込みOS自作入門
【学習メモ#1st】12ステップで作る組込みOS自作入門
 
【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門【学習メモ#5th】12ステップで作る組込みOS自作入門
【学習メモ#5th】12ステップで作る組込みOS自作入門
 
4章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 34章 Linuxカーネル - 割り込み・例外 3
4章 Linuxカーネル - 割り込み・例外 3
 
【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門【学習メモ#3rd】12ステップで作る組込みOS自作入門
【学習メモ#3rd】12ステップで作る組込みOS自作入門
 
StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件StackExchangeで見たシステムプログラミング案件
StackExchangeで見たシステムプログラミング案件
 
システムコール
システムコールシステムコール
システムコール
 
あるコンテキストスイッチの話
あるコンテキストスイッチの話あるコンテキストスイッチの話
あるコンテキストスイッチの話
 
d-kami x86-1
d-kami x86-1d-kami x86-1
d-kami x86-1
 
0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと0章 Linuxカーネルを読む前に最低限知っておくべきこと
0章 Linuxカーネルを読む前に最低限知っておくべきこと
 
signal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何かsignal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何か
 
【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門 【学習メモ#9th】12ステップで作る組込みOS自作入門
【学習メモ#9th】12ステップで作る組込みOS自作入門
 
【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門 【学習メモ#8th】12ステップで作る組込みOS自作入門
【学習メモ#8th】12ステップで作る組込みOS自作入門
 
Cpu pipeline basics
Cpu pipeline basicsCpu pipeline basics
Cpu pipeline basics
 
Linux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutesLinux Performance Analysis in 15 minutes
Linux Performance Analysis in 15 minutes
 
【学習メモ#11th】12ステップで作る組込みOS自作入門
【学習メモ#11th】12ステップで作る組込みOS自作入門 【学習メモ#11th】12ステップで作る組込みOS自作入門
【学習メモ#11th】12ステップで作る組込みOS自作入門
 

Andere mochten auch

ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
Tsukasa Oi
 
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
Tsukasa Oi
 

Andere mochten auch (7)

フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料フリーソフトではじめるChIP-seq解析_第40回勉強会資料
フリーソフトではじめるChIP-seq解析_第40回勉強会資料
 
Linuxセキュリティ強化エッセンシャル
Linuxセキュリティ強化エッセンシャルLinuxセキュリティ強化エッセンシャル
Linuxセキュリティ強化エッセンシャル
 
optimal Ate pairing
optimal Ate pairingoptimal Ate pairing
optimal Ate pairing
 
さらば、Stagefright 脆弱性
さらば、Stagefright 脆弱性さらば、Stagefright 脆弱性
さらば、Stagefright 脆弱性
 
ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
ステルスルートキット : 悪いヤツはどうライブメモリフォレンジックをすり抜ける? - PacSec 2009
 
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
セキュアVMの構築 (IntelとAMDの比較、あともうひとつ...) - AVTokyo 2009
 
Linux Profiling at Netflix
Linux Profiling at NetflixLinux Profiling at Netflix
Linux Profiling at Netflix
 

Ähnlich wie リバースエンジニアリングのための新しいトレース手法 - PacSec 2010

Linux/DB Tuning (DevSumi2010, Japanese)
Linux/DB Tuning (DevSumi2010, Japanese)Linux/DB Tuning (DevSumi2010, Japanese)
Linux/DB Tuning (DevSumi2010, Japanese)
Yoshinori Matsunobu
 
Hyper vを理解する
Hyper vを理解するHyper vを理解する
Hyper vを理解する
Naoki Abe
 
Inkernel disasm-from-intelsdm-kernelvm
Inkernel disasm-from-intelsdm-kernelvmInkernel disasm-from-intelsdm-kernelvm
Inkernel disasm-from-intelsdm-kernelvm
Masami Hiramatsu
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
Takeshi Yamamuro
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQL
akirahiguchi
 
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
Insight Technology, Inc.
 

Ähnlich wie リバースエンジニアリングのための新しいトレース手法 - PacSec 2010 (20)

C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1C# 7.2 with .NET Core 2.1
C# 7.2 with .NET Core 2.1
 
Code jp2015 cpuの話
Code jp2015 cpuの話Code jp2015 cpuの話
Code jp2015 cpuの話
 
201711 vxrailチャンピオンクラブ_ワークショップ~入門編~テキスト
201711 vxrailチャンピオンクラブ_ワークショップ~入門編~テキスト201711 vxrailチャンピオンクラブ_ワークショップ~入門編~テキスト
201711 vxrailチャンピオンクラブ_ワークショップ~入門編~テキスト
 
良いコードとは
良いコードとは良いコードとは
良いコードとは
 
CPUの同時実行機能
CPUの同時実行機能CPUの同時実行機能
CPUの同時実行機能
 
Linux/DB Tuning (DevSumi2010, Japanese)
Linux/DB Tuning (DevSumi2010, Japanese)Linux/DB Tuning (DevSumi2010, Japanese)
Linux/DB Tuning (DevSumi2010, Japanese)
 
Hyper vを理解する
Hyper vを理解するHyper vを理解する
Hyper vを理解する
 
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
CLUB DB2 第137回:基礎から再入門!DB2モニタリング入門
 
Cpu cache arch
Cpu cache archCpu cache arch
Cpu cache arch
 
本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown本当にわかる Spectre と Meltdown
本当にわかる Spectre と Meltdown
 
Inkernel disasm-from-intelsdm-kernelvm
Inkernel disasm-from-intelsdm-kernelvmInkernel disasm-from-intelsdm-kernelvm
Inkernel disasm-from-intelsdm-kernelvm
 
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
LLVMで遊ぶ(整数圧縮とか、x86向けの自動ベクトル化とか)
 
Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?Craft CMSに最適なサーバはどんな環境?
Craft CMSに最適なサーバはどんな環境?
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQL
 
Meltdown を正しく理解する
Meltdown を正しく理解するMeltdown を正しく理解する
Meltdown を正しく理解する
 
さわってみようTOPPERS/SSP
さわってみようTOPPERS/SSPさわってみようTOPPERS/SSP
さわってみようTOPPERS/SSP
 
20200709 fjt7tdmi-blog-appendix
20200709 fjt7tdmi-blog-appendix20200709 fjt7tdmi-blog-appendix
20200709 fjt7tdmi-blog-appendix
 
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
[C31]世界最速カラムナーDBは本物だ! by Daisuke Hirama
 
PostgreSQL運用管理入門
PostgreSQL運用管理入門PostgreSQL運用管理入門
PostgreSQL運用管理入門
 
ASPLOS2017: Building Durable Transactions with Decoupling for Persistent Memory
ASPLOS2017: Building Durable Transactions with Decoupling for Persistent MemoryASPLOS2017: Building Durable Transactions with Decoupling for Persistent Memory
ASPLOS2017: Building Durable Transactions with Decoupling for Persistent Memory
 

Mehr von Tsukasa Oi

Mehr von Tsukasa Oi (6)

Farewell, Stagefright bugs!
Farewell, Stagefright bugs!Farewell, Stagefright bugs!
Farewell, Stagefright bugs!
 
A New Tracer for Reverse Engineering - PacSec 2010
A New Tracer for Reverse Engineering - PacSec 2010A New Tracer for Reverse Engineering - PacSec 2010
A New Tracer for Reverse Engineering - PacSec 2010
 
Stealthy Rootkit : How bad guy fools live memory forensics? - PacSec 2009
Stealthy Rootkit : How bad guy fools live memory forensics? - PacSec 2009Stealthy Rootkit : How bad guy fools live memory forensics? - PacSec 2009
Stealthy Rootkit : How bad guy fools live memory forensics? - PacSec 2009
 
Creating Secure VM (Comarison between Intel and AMD, and one more thing...) -...
Creating Secure VM (Comarison between Intel and AMD, and one more thing...) -...Creating Secure VM (Comarison between Intel and AMD, and one more thing...) -...
Creating Secure VM (Comarison between Intel and AMD, and one more thing...) -...
 
Lack of System Registers and two simple anti-forensic attacks - AVTokyo 2009
Lack of System Registers and two simple anti-forensic attacks - AVTokyo 2009Lack of System Registers and two simple anti-forensic attacks - AVTokyo 2009
Lack of System Registers and two simple anti-forensic attacks - AVTokyo 2009
 
システムレジスタの不足と2つのシンプルなアンチフォレンジック攻撃 - AVTokyo 2009
システムレジスタの不足と2つのシンプルなアンチフォレンジック攻撃 - AVTokyo 2009システムレジスタの不足と2つのシンプルなアンチフォレンジック攻撃 - AVTokyo 2009
システムレジスタの不足と2つのシンプルなアンチフォレンジック攻撃 - AVTokyo 2009
 

Kürzlich hochgeladen

Kürzlich hochgeladen (11)

論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
Observabilityは従来型の監視と何が違うのか(キンドリルジャパン社内勉強会:2022年10月27日発表)
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 

リバースエンジニアリングのための新しいトレース手法 - PacSec 2010

  • 2. このセッションでは: • リバースエンジニアリングを効率的にする ―― かもしれない手法を紹介します。 • かもしれない ? – (2010年11月時点で) VM 上で汎用 OS が動作しない。 • ライブデモができず申し訳ない! – これにより、ある程度の推測なども含まれるため。
  • 3. 関連分野 • リバースエンジニアリング – 特に動的解析、デバッガ、トレーサ • Intel x86 (32-bit) アーキテクチャ • 仮想化 / 仮想マシンモニタ (VMM) – Record and Replay • 異常検出と解析 (ハニーポットなど) • バグ検出 (ファジングなど)
  • 4. アジェンダ • 多くの トレーサ が抱える問題 • Record and Replay を改良した提案手法 • x64 上における VMM の実装 • 部分的な検証 • 応用 (の可能性) • トレース VM の課題
  • 5. 対象プラットフォーム • Intel x86 (16/32-bit) アーキテクチャ • PC/AT • 汎用 OS (Windows, Linux etc...)
  • 7. 動的解析 • 動作しているプログラムに介入するなどして、 その挙動、内部構造などを解析する。 • 使用するツールは一般に多岐にわたる。(代表例) – デバッガ • OllyDbg, Windbg, IDA Pro... – モニター • Process Monitor, Wireshark... – トレーサ • API Monitor, OllyDbg, Process Stalker... • 今回は トレーサのようなもの に関わる話題です。
  • 8. トレーサ (1) • コンピュータ内で発生した特定の イベントをキャプチャ、保存する。 – 命令単位 – 基本ブロック / 関数単位 – API / システムコール / 入出力単位など • 命令単位のトレース – 自動解析の対象にすることが容易 (自動 unpacking などが代表的) – コンピュータの内部状態を記録することができれば、 事実上コンピュータのすべてがトレースできる。
  • 9. トレーサ (2) • しかし、私が調査した命令トレーサには 共通する欠点があった。 – 遅い • 1 命令単位でフックとトレースを行うため、 トレースに実時間の数十倍かかることも珍しくない。 – データ量が大きい • 実時間換算 (仮にトレースが元のプログラムと同等の 速度で動作した場合) で数 GB/s のオーダー。 • トレースの書き込み処理そのものが ボトルネックになってしまう。
  • 10. トレーサ (3) • この点を改善したトレーサを作成できないか? • 主要な要件: – トレースにかかる時間は、エミュレーションしない 環境と比較して 2 倍以内であること。 – トレースのサイズは、ネットワーク送信できる ように 5MB/s 以下であること。 • このような要件を満たすトレーサをどのように 実装 (する¦した) かが今回のテーマです。
  • 11. 理論 ‒ Record and Replay Theory ― Record and Replay
  • 12. Record and Replay (0) • 実のところ独自に発見したつもりだった。 – 文献を十分に調査していなかった。 • ReVirt : Enabling Intrusion Analysis through Virtual- Machine Logging and Replay – 既存の論文に当てはめれば、提案手法は Record and Replay の変種に当たる。 – 両者は強く関連していて、分離が難しい。 • そのため、提案手法と Record and Replay を まとめて解説する。
  • 13. Record and Replay (1) • 文献によって呼び方が異なる場合がある。 – Logging and Replay Lockstep など。 • 2 パス (Record + Replay) によって、トレースと、 そこからの情報の復元を行う。 • 一般的なアーキテクチャに共通する特長を 利用し、データ量を極めて小さく抑えている。 – 通常、ハードウェアなどからの入力は その他の命令による操作よりはるかに少ない。
  • 14. • 多くのアーキテクチャ (ここでは 1 CPU とする) は 次のようにモデル化することができる。 – 入力 (空の場合もある) – 計算 / 処理 (+内部状態) – 出力 (空の場合もある) • ここで、出力は内部状態から一意に 与えられるものとする。(下式の関数 g) • zn+1 = f(zn, in) on+1 = g(zn+1) Record and Replay (2) 入力 出力 計算/処理 +内部状態
  • 15. • CPU の全状態を保存することは、ここでは 内部状態 (zn) をすべて保存することに相当する。 – 前述の定義により、出力は内部状態から 一意に決定できるため、出力はモデルから便宜上 省くことができる。 • 内部状態の初期値である z0 は別途与える。 • 計算/処理に相当する関数 f は、いわゆる 数学的な「函数」であること。 – 一定の入力で一定の出力を 行い、そこに曖昧さは無い。 Record and Replay (3) 入力 出力 計算/処理 +内部状態
  • 16. • さらに依存関係を考える。 – 入力 : 他のいずれにも依存しない独立した値 – 計算 / 処理 (+内部状態) : 入力に依存 • この関係から… – このモデルにおける内部状態は初期状態と 入力にのみ依存する。これだけをトレースすれば、 事実上コンピュータのすべてをトレースしたことに なるのだ。 Record and Replay (4) 入力 計算/処理 +内部状態
  • 17. • Pass 1 : Record – 初期状態をキャプチャし、トレースに保存。 – すべての入力をキャプチャし、トレースに保存。 • ここでは、実際のハードウェアからの 入力を受け入れる。 • これにより、Replay パスで復元可能な トレースを生成できた。 Record and Replay (5) 入力 トレース 計算/処理 +内部状態 初期状態
  • 18. • Pass 2 : Replay – 初期状態をトレースから復元。 – 仮想マシンを動作させる。ただし、すべての 入力はトレースから読み取る。 • つまり、新たなハードウェア入力は 受け付けない。 – 内部状態を読み取る。 • Record パスと非常に類似している。 Record and Replay (6) 入力 トレース 計算/処理 +内部状態 初期状態
  • 19. 利点 (1) • これまでの説明なら単に 2 回実行するだけの ようにも見えるが… – トレースを用いて、いつでも、あるいは 何回でも Replay パスを実行できる。 • 解析結果が不十分ならば、別の解析手法を 適用することができる。 – 必要ならば Replay を並列に実行することもできる。 • 自動解析の時間を短縮できる可能性がある。 (実際には解析の依存関係の問題がある。)
  • 20. 利点 (2) • (続き) – Replay パスの実行は Record パスに何の影響も 与えない。これらはまったく独立している。 • どのような解析をしても Record パスは遅くならない。 • Replay パスにおいて詳細な、これまで使用 が難しかった解析手法が適用できる可能性もある。 (ポインタの追跡や依存性解析など。) • これらのことから、この手法は リバースエンジニアリングとの親和性が高い。
  • 21. 実例 (1) • VMware Workstation (6 以降) – 記録と再生 機能がこれに該当する。 • 実行を記録してビデオと同様に再生したり、 あるいはデバッグのために使用できる。 – プロプライエタリであり、また堅牢性が高いとも 言えないが、確かにこの理論を実用化した例である。 – トレース出力は一般に 1∼10MB/s
  • 22. 実例 (2) • VMware Workstation (6 以降) – ただし… • VMware である (バックドアなどがよく知られている) • デバッグインタフェースが十分ではない。 – デバッグ機能さえ充実していれば リバースエンジニアリングに使えたかも…。 • その他の例 – ReplayDIRECTOR (Java デバッグツール) – Jockey (Linux 用記録 / デバッグ補助ツール) • http://home.gna.org/jockey/
  • 23. • すべての決定論的でない要因を 入力 として 扱うのは単純だが、VMM の実装には不向き。 – データ入力のタイミングなどを考えれば、 不効率極まりない格納方法になる。 • そこで、この 入力 をさらに細分する。 – 決定論的でない入力 – 割り込み • ただし、名称と内容は 必ずしも一致しない。 x86 への適用 (1) 入力 トレース 計算/処理 +内部状態 初期状態
  • 24. • 決定論的でない入力 – x86 の in 命令のように、内部状態が不確定になる タイミングは一意に決定できる。 – ただし、その具体的な内容までは決定できない。 – この場合、具体的な値や内容を保存する。ただし、 そのタイミング情報は保存しない。 • 先行する入力や割り込みでタイミングを 確定できるため、タイミング情報は余分である。 x86 への適用 (2.1)
  • 25. • 割り込み – x86 のハードウェア割り込みに代表されるように、 そのタイミングが不定 (一意に決定できない。) – また、その具体的内容も決定論的でない場合がある。 – この場合、タイミング情報を保存する。また、 割り込みの具体的内容が決定論的でない場合、 その内容も保存する。 • ハードウェア割り込みでは、その割り込み ベクトル番号などがそれに該当する。 • これらの分類をベースに、VM 内部すべての要素を 適切にモデル化することが最も重要である。 x86 への適用 (2.2)
  • 26. • モデル化 ― VM の内部ディスク – VMM の内部ディスクは信頼できると仮定し、 開始時の初期状態を記録する。 – ほとんどを決定論的とみなし、トレースを原則として 行わない。ただし、ディスクが発生させる割り込みは 割り込み として記録する。 • 読み取られたディスク内容は、以前に書き込んだ ディスクの内容と同一であることが保証されるため。 • ただし、ATA 割り込みなどのタイミングは 一定とならないため、 割り込み とみなせる。 x86 への適用 (3.1)
  • 27. • モデル化 ― マウス、キーボード、ネットワーク – これらは外部からの予測できない入力である。 – デバイスからの入力は、割り込みと入力の両者を 使用するため、 割り込み と 決定論的でない入力 の複合的要素として扱う。 – ネットワーク出力は内部状態から決定できるため、 トレースを行わない。 x86 への適用 (3.2)
  • 28. • モデル化 ― CPU のタイムスタンプカウンタ – RDTSC などで読み取ることの可能な、 リセット時からカウントされるクロック数。 – 決定論的でない入力 とみなす。 – 物理的な位置が CPU 内部だったとしても、決定論的な モデル化が不可能である場合には外部入力と同様に 扱うべきである! • もしモデル化が可能であったとしても ほとんどの場合効率が下がってしまうため、 敢えて決定論的でないとみなすことが効率の 向上につながる。 x86 への適用 (3.3)
  • 29. • モデル化 ― CPU の例外 – 例外はほとんどの場合発生するタイミングが 決定論的である。またほとんどの場合、 例外処理の内容も決定論的に行われる。 – そのため、前述のどちらとしても扱わない。 • モデル化 ― CPU の不定値 – 具体例は多数あるが、特定の操作を行った後、 CPU の内部状態の一部が不定となることがある。 この場合、タイミングは特定できるものとする。 – 決定論的でない入力 とみなす。 x86 への適用 (3.4)
  • 30. • モデル化 ― 厳密値のない算術命令 – FSINCOS, FATAN などの超越関数命令は IEEE 754 の 規定に従った丸めを行うことが不可能であるため、 満たすべき精度のみが定義されている。 – 具体的な値を特定できる最低限の情報を 決定論的でない入力 とみなす。 • などの様に、CPU 内外のあらゆる要素を モデル化する必要がある。 – 本理論に基づく VMM を作成する最大の障害。 x86 への適用 (3.5)
  • 31. x86 への適用 (4) • あるものを 決定論的でない要因 として 扱うとはどのようなことか? – フックとトレース回数を増やすこと。 – つまり、トレースは大きく、速度は遅くなる。 – このような状況は可能な限り減らしたほうが良い。 • 設計当初、このような要因の発生する回数は 一般命令数の多さに比べれば極めて小さく、 それほど問題とならないと考えていた。 – しかし、それは間違っていた。
  • 32. 例えば次の例: • 次の命令は決定論的か否か XOR edx, edx – x86 のアセンブリを読んでいれば ご存知のように、edx を 0 にする命令だ。 – しかし、前述の答えは No だ。 • 実際にはこのような命令を含めて、極めて多数の 命令が内部状態の一部を不定にしてしまう。 – EFLAGS だ。
  • 33. EFLAGS の呪い? (1) • それでは内部状態を詳しく見てみよう。 – edx は 0 になっているが、 同時に EFLAGS.AF が ? になっている。 – このとき、AF の値はマニュアルによって 未定義 (undefined) とされている。 xxx......xxx 000......000 x x x x x x 0 0 1 ? 1 0 XOR edx, edx (next instruction) OFedx SF ZF AF PF CF EFLAGS
  • 34. EFLAGS の呪い? (2) • もちろんこれだけではない! – 頻繁に使用される下記命令も同様! – 下記のものを含め、x86 の全実行命令のうち 10∼15% がフラグの一部を不定にする。 0 M M ? M 0 AND, OR, XOR, TEST (論理演算) OF SF ZF PF CFAF M ? ? ? ? M MUL, IMUL (乗算) ? ? ? ? ? ? DIV, IDIV (除算) ? M M ? M ? SHL, SHR, SAL, SAR count (シフト)
  • 35. EFLAGS の呪い? (3) • 全く 小さく などないではないか! – 10% 程の命令であったとしても、フックにどれだけ 時間を要するかを考えれば全く無視できない。 – これらの不定値を トレース するのでなく、 決定論的な値に置き換えることも考えられるが… フラグを置換するのに必要な POPF 命令は 極めて時間がかかる (割り込みにも劣らない)。 • Intel Nehalem MA で 24-25 clocks – 現実的な速度でトレースするには、 これらのトレースを何とか回避する必要がある。
  • 36. 実装に内在する問題 • 公開されている既存実装はこれらの不定要素に 対して最低限の対処しかしていない。 – 同一の CPU ファミリで両者を動かす場合に限定。 – 一般にアプリケーションは不定値に依存しないが、 1-bit の不定値であってもカオスを引き起こしうる。 • 堅牢性がない。 – トレースを複数の手段で復元した場合、 そのうちのどれが正しいかを特定できない。 • 情報の集積に支障を来しうる。 • 移植性に乏しい。
  • 37. EFLAGS の遅延評価 (1) • しかし、EFLAGS には次の特性もある。 – 更新されたフラグが使用されるとは限らない。 (現に、80%以上のフラグは単に破棄される。) – フラグの更新と参照は大抵セットになっている。 • 比較命令 + 条件分岐命令のように。 • Intel は Macro-Fusion でそのような最適化を行う。 – では不定値はそれが使用されるまで許容し、 それ以外の内部状態に影響を与える場合に トレースするのはどうか? • 実験では極めて効果的であった。
  • 38. EFLAGS の遅延評価 (2) • 現時点での遅延評価実装: – これは、JIT コンパイル時に行う。 (実行時評価の排除。高速化に寄与。) – 実行に寄与するブロック毎に評価する。 • 分岐などで到達した地点から次の無条件分岐 (例外などを含む) までの命令列を指す。 • このブロックについて順方向に命令をスキャンする。 – 仮想的なフラグ (6-要素) の伝播を計算する。 • 決定論的/不定の二値 (ブロック開始時 : 不定) • 最後にフラグの値を更新した命令。 • 一定条件下でヒューリスティクスも使用可能。
  • 39. EFLAGS の遅延評価 (3) • (実装続き) – ブロック内の命令がフラグに依存し、対応する 仮想フラグが次の条件を満たす場合、 暫定的な不定値としてトレースする。 • 仮想フラグが不定である。 • 仮想フラグは決定論的だが、更新した命令が 32-bytes or 8-instructions 以上前である。 (上記打ち切りはパラメータで設定する。) • 現段階では極めて効果的である。 – 実験段階では、トレースしたフラグのほぼ全てが 割り込み / コンテキストスイッチに絞り込まれた。
  • 40. Record and Replay : まとめ • Record and Replay を使用することにより、 トレースのオーバーヘッドとデータ量をともに 削減することができる。 • 改善された手法により、 x86 において堅牢的なトレースを取得できる。
  • 42. 実装 • VMM ベースのトレーサを実装する。 – 汎用 OS を動作させるため。 • しかし良い選択ではなかったようだ。 その複雑さのため、現時点 (2010/11) では VM 上で OS を動作できるほど完成しなかった。 – バイナリ変換ベースの VM – x86 を対象 (ゲスト) とし、x64 をホストとする。 • 様々な観点から、x86 のバイナリ変換には x64 が優れている。
  • 43. x86 on x64 (1) • x64 は x86 の 64-bit 拡張 – 命令フォーマットも x86 (32-bit) のものと類似。 – ただし、幾つかの拡張が施された。 • 汎用レジスタと XMM レジスタの倍増 (8→16) • 新しいアドレッシングモード (64-bit、RIP [program counter] 相対) • x86 のバイナリ変換を容易にする要素が 多数存在する!
  • 44. x86 on x64 (2.1) • Benefit : 32-bit レジスタの clamp – x64 のレジスタは x86 のものを拡張したものである。 • 例 : ax (16-bit), eax (32-bit), rax (64-bit) – ここで、32-bit レジスタを格納先とする 演算を行うと、対応する 64-bit レジスタの上位 32-bit がクリアされる。(これはロングモード固有) 0123 0123 4567 1234 MOV eax, 0x01234567 MOV ax, 0x1234 eax ax
  • 45. x86 on x64 (2.1) • Benefit : 32-bit レジスタの clamp – x64 のレジスタは x86 のものを拡張したものである。 • 例 : ax (16-bit), eax (32-bit), rax (64-bit) – ここで、32-bit レジスタを格納先とする 演算を行うと、対応する 64-bit レジスタの上位 32-bit がクリアされる。(これはロングモード固有) 01234567 00000000 89abcdef 12345678 MOV rax, 0x0123456789abcdef MOV eax, 0x12345678 rax eax
  • 46. x86 on x64 (2.2) • Benefit : レジスタの増加 (汎用/XMM) – 8→16 個に増加。(XMM 含めた増加分は 16 個) – エミュレータやトレーサの状態を、 既存のレジスタを破壊することなく格納可能。 rax r8 rcx r9 rdx r10 rbx r11 rsp r12 rbp r13 rsi r14 rdi r15 xmm0 xmm8 xmm1 xmm9 xmm2 xmm10 xmm3 xmm11 xmm4 xmm12 xmm5 xmm13 xmm6 xmm14 xmm7 xmm15
  • 47. x86 on x64 (2.2) • Benefit : レジスタの増加 (汎用/XMM) – 8→16 個に増加。(XMM 含めた増加分は 16 個) – エミュレータやトレーサの状態を、 既存のレジスタを破壊することなく格納可能。 eax cs.base ecx es.base edx emuinfo ds.base ebx stack esp ebp tmp2 esi ss.base tmp1 edi xmm0 fs.base xmm1 gs.base xmm2 tmp3 xmm3 tmp4 xmm4 notused xmm5 notused xmm6 notused xmm7 notused 実際のレジスタ再配置マップ。 このマップに従い命令を変換す る。 レジスタ使用を効率化するため、 一部の x86 レジスタは再配置 されている。
  • 48. x86 on x64 (2.2) • Benefit : レジスタの増加 (汎用/XMM) – 8→16 個に増加。(XMM 含めた増加分は 16 個) – エミュレータやトレーサの状態を、 既存のレジスタを破壊することなく格納可能。 – xmm レジスタはそのままでは使用が難しいが、 movq 命令を使用して汎用レジスタに転送する。
  • 49. x86 on x64 (2.3.1) • Benefit : アドレッシングの 非 変化 – アドレッシングモードは追加されたものもあるが、 基本は x86 のものをそのまま 64-bit 拡張しただけ。 – x86 は元々複雑なアドレッシングモードを持つ。 • [esi+edx*4+123] のような複合演算も可能。 • これを利用して、メモリ領域の隔離を行う。 – アドレス : [segbase+offset] • すべてのメモリアクセスは、セグメントベース (64-bit アドレス) との相対オフセットでアクセスする。 – メモリ領域さえ確保しておけば、その外に アクセスが漏れることがない。
  • 50. x86 on x64 (2.3.2) • Benefit : アドレッシングの 非 変化 – 例 (1) : inc [ds:ecx] → inc [rbx+rcx] • rbx : DS セグメントのベースアドレス • rcx : ゲストの ecx レジスタ – 32-bit レジスタの値を 64-bit として 読み取っている! (そんなやり方で大丈夫か?) • 問題ない。前述したように 32-bit 演算の結果は 32-bit 範囲にしかならないため、アクセスされる領域を 完全にコントロールすることができる。
  • 51. x86 on x64 (2.3.3) • Benefit : アドレッシングの 非 変化 – 間違った例 (2) : inc [ds:ecx+edx] → inc [rbx+rcx+rdx] • 一時レジスタに中間結果を格納する。 – 正しい例 (2) : inc [ds:ecx+edx] → lea edi, [rcx+rdx] ; inc [rbx+rdi] • edi/rdi : 一時レジスタ • これ以外はほとんど変わらない。 – 一番良いエンコーディングを頼む。 • 64-bit のアドレス計算結果を 32-bit レジスタに格納。 • これも正当なエンコーディングで、結果が 32-bit に 切り詰められ、さらに命令が短くなる。
  • 52. x86 on x64 (2.4.1) • Benefit : 広大なメモリ領域 – アドレス幅は 64-bit • 有効な論理アドレスは 48-bit (符号拡張される。) • 例 : 0x0000_1234_5678 → 0x0000_0000_1234_5678 • 例 : 0x8000_1234_5678 → 0xffff_8000_1234_5678 – ゲストがアクセス可能な場所の外に VMM だけが使用するデータやコードを配置できる。 • x86 on x86 ではアドレス空間が双方とも 4GB であり、 双方のアドレスを圧縮しなければ配置できない。 • VMM の性能が向上する。
  • 53. x86 on x64 (2.4.2) • Benefit : 広大なメモリ領域 – ただし問題がある。64-bit でアドレス計算を行った 結果は 32-bit の範囲を超えることがある。 – x86 (32-bit) は、32-bit におけるアドレス計算の オーバーフロー、アンダーフローを無視する。 つまり、64-bit でアドレス計算を行った場合、 下位 32-bit がアクセスされるアドレスである。 – ここで下位 32-bit が等価 == アドレスが等価という 状態を作り出す。メモリに見かけ上のループを 作り出すのだ。
  • 54. x86 on x64 (2.4.3) • Benefit : 広大なメモリ領域 – 仮想メモリ空間を確保する。 – アドレスのオーバーフローなどを考慮し、 下に示す最大 44.5GB の連続領域を確保する。 • 赤と青の領域 (4GB) は同じ 物理的領域を指す。 • これはページテーブルを使用することで達成可能。 44.5GB 42.25GB 2.25GB
  • 55. x86 on x64 (2.4.4) • Benefit : 広大なメモリ領域 – セグメントやアクセス制御毎に定義する。 • ページテーブル置換を省略できる。 cs.base ds.base es.base ss.base data3 code0 data3 code3
  • 56. x86 on x64 (2.4.4) • Benefit : 広大なメモリ領域 – セグメントやアクセス制御毎に定義する。 • ページテーブル置換を省略できる。 cs.base ds.base es.base ss.base data3 code0 data3 code3
  • 57. x86 on x64 (2.5.1) • Benefit : シンプルになったアーキテクチャ – x64 のアーキテクチャは比較的単純化され、 OS 上に Type-2 VMM を構築することが容易。 • 割り込みハンドラの種類の減少 – 割り込みゲートとトラップゲートの二種類のみ。 • セグメント機構の事実上の形骸化 – CS, DS, ES, SS セグメントについて フラットメモリモデルを採用。 – IDT (割り込みベクトル) を置き換えることで、 VM 専用のコンテキストを確保する。 • PatchGuard の有効な Windows でも安全に動作する。
  • 58. x86 on x64 (2.5.2) • Benefit : シンプルになったアーキテクチャ – 割り込みをパススルーする。 • IDT の切り替えによって安全に行える。 • 若干オーバーヘッドがある。 VM OS 実際にはもう少し複雑だ が、 ここでは概略のみ示す。 IDT switch IDT switch OS Kernel VM Trampoline OS IntHandler VM Entry VM IntHandler VM Kernel
  • 59. x86 on x64 (3) • 以上の機構を用いて VMM を実装する – …のだが、現時点での完成度は低い。 • タイミングをトレースするには、 次の情報があればよい。 – 分岐カウンタの値 (ソフトウェア実装も可能) – 現在のプログラムカウンタ (IP, EIP) – 繰り返しカウント (CX, ECX) • rep 命令が実行中だった場合のみ。 – いくつかこれについては例外があるのだが、 今回の範囲を著しく逸脱するため省略。
  • 60. Everything into the Ring-0 • 権限の隔離は必要? – JIT コンパイルされたコードは適切に隔離され、 管理された領域以外にはアクセスできないため、 すべてのコードを Ring-0 で実行可能。 • セキュリティチェックの一部を省略するなど、 フックや VMM のオーバーヘッドを 大きく減らすことができる。 • 現在の実装は Ring-0 上にすべてを構築している。 – セキュリティ上この動作が危険であれば、 Ring-3 で動作させることも理論上可能。
  • 62. トレースサイズの検証 (1.1) • トレースに必要なデータ量 – Bochs (2.45) 付属の DLX Linux 起動シーケンス • リセットからログイン画面の表示まで • 52,217,403 instructions (実時間換算 : 約 53 秒) – 各種スペック • 1 MIPS (1,000,000 instructions/sec) • 32MB MEM, 10MB HDD – Bochs のトレース機能で出力したテキスト形式の トレースを、提案手法と幾つかの対照手法の 理論に従って変形する。
  • 63. トレースサイズの検証 (1.2) • トレースに必要なデータ量 – 初期状態のサイズは含まない。 – Bochs 組み込みデバイスについて、 そのモデル化を行い、対応するトレースサイズの 導出も行った。 – ただしモデル化は簡易的なものであるため、 サイズは近似となる。
  • 64. トレースサイズの検証 (1.3) • 手法 (比較対象含む) – Raw Bochs が出力する命令/メモリトレース (テキスト) – Verbose 一般的なトレーサが出力するトレース量の目安 – Dumb 読み取ったメモリを記録する、マルチコアに適した Record and Replay 類似の方式 – RnR (1) Record and Replay (EFLAGS をトレースする) – 提案手法 改良された Record and Replay アルゴリズム – RnR (2) Record and Replay (EFLAGS の不定値を無視する)
  • 65. トレースサイズの検証 (2.1) 手法 サイズ (bytes) Raw 7,178,948,236 6.68GB Verbose X > 419,430,400 400MB Dumb 60,713,538 57.90MB RnR (1) 6,932,542 6.61MB 提案手法 389,013 380KB RnR (2) 31,788 31KB ここに示すように、提案手法を含む Record and Replay 法は 極めて小さなトレースで同様のデータを表現できる。 一般的なトレーサの目安に相当する Verbose の数値に比べて 1/1,000 というサイズを達成している。
  • 67. トレースサイズの検証 (2.3) • まとめ – この結果は実際の VMM から取得したものではない ため、実装が要件を満たすかという点については 若干の疑いもある。 – しかしながら、他のトレース手法よりはるかに 小さいトレースを生成することだけはほぼ 確実といえる。
  • 70. 応用の可能性 (1) • リバースエンジニアリング (一般) – 動いた ものはすべて 明らか になっている。 • すべてのプログラムの動作はトレース中に 保存されているため、必要な情報はいつでも ここから抽出できる。 • アンチデバッギングや VM 検出さえ回避すれば、 プログラムの正常な動作を完全に記録できる。 – unpack されたプログラムコードももちろん含まれる。 • 複数種類の解析を統合することができる。
  • 71. 応用の可能性 (2) • アンチデバッギングの回避 – よく知られたバックドアは存在しないため、 既存手法での VM 検出は困難である。 – しかし、バイナリ変換ベースの VMM は パフォーマンスに特有の癖が出てしまう。 • 自己書き換えによって極端に遅くなる、など。 – もちろんどのように VM 検出が行われたかという 部分は解析が可能であるため、最悪でも 次の解析を容易にするための情報は収集できる。 • 一般的なプログラムがもつプロテクトであれば、 二度目の実行により高い確率で回避できるだろう。
  • 72. 応用の可能性 (3) • リバースエンジニアリング (マルウェア) – 今のところ、ソフトウェアを「そのまま」動作させる ことのみ想定しているため、マルウェアを VM 上で 動作させることは危険である。 • マルウェアの解析に関して言えば、従来の エミュレータ使用のアプローチの方が安全かも。 – ただし、その点に適切な対処ができる場合、 マルウェアの動作を確実に分析できるだろう。 – ハニーポットへの適用もあり得る
  • 73. 応用の可能性 (4) • ファジング / 脆弱性分析 / バグ解析 – OS 全体に Valgrind を適用したような、 高い精度、粒度の解析が可能である。 – 非リアルタイム解析により、メモリ破壊の位置や その影響などを追跡できる。 – 再現性の低い脆弱性であっても、一度動作すれば その実行パスを詳細に分析できる。 – ただし、ファジングを効率的に実行できるかは 実際の VMM 実装に強く依存する。
  • 74. 応用の可能性 (5) • 解析の補助 – 特定ツールのためのデータを出力する。 • Wireshark のパケットダンプなど – このとき、プログラムの動作を考慮に入れて メタデータや追加処理を付加できるだろう。 • 例えば SSL/TLS の自動復号など。 盗聴や外部からのモニタリングによる復号は不可能 だが、VMM 上で動作させた場合には共通鍵を持つ 端点をモニタできる。
  • 75. 応用の可能性 (6) • <<Place Entry Here>> – VMM 上で起こるほぼ全てを保存できると いうことは、他の応用も色々あるかも…。 – (マルウェア解析などの) 現場に携わったことのない 私よりも真価を発見できる方は多いかと。
  • 77. 課題 : マルチコア (1) • Record and Replay はそのままでは マルチコアに応用できない。 – 複数の CPU が密に連携を取ることを想定していない。 – 先行例である VMware Workstation も私の実装も、 1 CPU/thread の実行にのみ対応する。 • ただし、全く不可能というわけでもない。 (一長一短はあるのだが。) – タイムスライスによる時分割 – MESI プロトコルのソフトウェア実装 – メモリ内容をトレースする
  • 78. 課題 : マルチコア (2) • タイムスライスによる時分割 – 同時に実行する仮想 CPU は 1 個のみ。 – ただし複数の仮想 CPU を切り替えながら実行する ことで、複数の CPU が動作しているように 見せかける。 • Pros. – 同期処理の必要性がほとんどないこと。 • Cons. – 仮想 CPU の数に比例して性能が悪くなる。 – マルチスレッド特有の問題の再現が困難になる。
  • 79. 課題 : マルチコア (3) • MESI プロトコルのソフトウェア実装 – メモリ一貫性アルゴリズムの一種 – マルチコアなどの環境においては、CPU 内部の ハードウェアはこれらのプロトコルを用いて メモリの状態を適切に管理する。 – これをソフトウェア (ページ単位) で実装する • Pros. – 共有メモリが少ない場合、性能が向上し易い。 • Cons. – ソフトウェア実装は極めて遅い。
  • 80. 課題 : マルチコア (4) • メモリ内容をトレースする – 複数 CPU で共有されるメモリ領域について、 そこからの読み取り結果をトレースする。 • Pros. – 一般に性能が向上し易い。 • Cons. – 厳密には完全情報ではなくなる。 (どの CPU が書き換えた情報かの追跡が困難。) – メモリトレースは遅い。
  • 81. 課題 : 64-bit / その他 • x64 on x64 の VMM 実装は極めて困難。 – 方法が無いわけではないが、実装コストと オーバーヘッドがかかる。 • SSE2 の逆数 / 逆数平方根命令 – 精度が保証されないためかなり高速な命令であり、 不定値としてのトレースが難しい。 • 結局ハイパーバイザベース? – 移植性を確保するには、生成したトレースに対して 別パス、同 CPU モデルで不定値を付加する。 – これは完璧ではないが、あり得る選択肢である。
  • 82. 注意 : 特許 • 構成技術の一部は特許化されている! – Record and Replay の基礎部分 – バイナリ変換 VMM の高速化に関するアルゴリズム – これらの回避は極めて難しい / 不可能である • 確認した限りでは PCT 出願のない米国特許であり、 米国外で使用する分には特に問題無いと考えられ る。 – が、利用には気をつける必要があるかも知れない。
  • 83. まとめ • ここでは、x64 上に x86 仮想マシンを構築し、 トレースする手法について解説した。 • 提案手法を用いれば、トレースが小さくなり、 さらにオーバーヘッドも小さくなる。 – ただし、リバースエンジニアリングに十分 使用できるか否かについては十分な検証が待たれる。 • トレースは様々な応用が可能である。 – 紹介した以外にもあるかもしれない。
  • 84. contact me at : li at livegrid dot org Open Source Project : Niizh will be available at http://niizh.org/ Thank you! Any questions?