読者です 読者をやめる 読者になる 読者になる

Log.i53

Themidaのアンパックを目指すブログ改め使い物になるえんじにゃを目指すブログ

デバッガ検出技術:Timing Checks

Unpack Anti-Debug

 プロセスがデバッグされている間にデバッグイベントを処理するコードや、分析者が命令をステップ実行することなどによっていくらかのCPUサイクルが費やされます。パッカーは、いくつかの命令の間に費やされた時間を確認することで、通常に比べて費やされた時間が長い場合には、プロセスがデバッガ上で実行されていると判断することができます。

 以下に、タイミングチェックの簡単な例を示します。これは、いくつかの命令の前後にRDTSC(Read Time-Stamp Counter)命令を使用して、実行後に経過時間デルタを計算します。このデルタ値は2つのRDTSC命令の間で実行されるコードの量に依存します。この例ではデルタ値が0x200より大きい場合にデバッガ上で実行されていると判定します:
f:id:i53:20150609035704p:plain

 タイミングチェックのバリエーションには、RDTSC命令の他にkernel32!GetTickCountの呼び出しや、SharedUserData構造体のオフセット0xCに常に配置されているTickCountLowやTickCountMultiplierフィールドの値をマニュアルで確認する方法があります。

 これらのタイミング技術は、特にRDTSCコードが使用されている場合に、ジャンクコードやその他の難読化技術によってこれを隠ぺいされると識別することが難しくなります。

解決策

 タイミングチェックのコードの場所を特定して、これらのタイミングチェック間のコードのステップ実行を回避する方法があります。分析者は、デルタ値の比較命令の直前にブレークポイントをセットして、その後でブレークポイントにヒットするまでステップ実行の代わりに通常の実行を行います。また、GetTickCountに対してもブレークポイントを設定し、それが呼び出されている場所を特定するか、またはその戻り値を改変することができます。

 OllyAdvancedプラグインはその他の解決策を備えています。それは、以下の処理を行うカーネルモードドライバをインストールするものです:

  1. 制御レジスタCR4のTime Stamp Disable Bit(TSD)を設定します。このビットが設定された場合、RDTSC命令がRing 0以外の特権レベルで実行されたときにGeneral Protection(GP)例外がトリガされます。
  2. Interrupt Descriptor Table(IDT)が、GP例外のフックとRDTSC命令の実行がフィルターされるように設定されます。RDTSC命令によってGP例外が発生した場合、前の呼び出しから返されたタイムスタンプの値をインクリメントして返します。

 上記のカーネルドライバがシステムに不安定性を引き起こしえることに留意すべきです。したがって、この機能を使って実験を行う際には、常に実験用マシンまたは仮想マシン上で実行すべきです。