質問:
ハードウェアブレークポイントの検出
Trey
2017-10-14 07:31:55 UTC
view on stackexchange narkive permalink

ソフトウェアブレークポイントは、ハードウェアブレークポイントとは異なり、コードを変更するため、アンチデバッガー手法としてそれ自体でチェックサムを実行するプログラムを作成するのは比較的簡単です。ハードウェアブレークポイントで同様のことを行うことは可能ですか?

はい、コンテキストを取得して、デバッグレジスタdr7dr6などを/ modify / nullifyすることができます。
1 回答:
Megabeets
2017-10-14 23:42:16 UTC
view on stackexchange narkive permalink

このトピックは、ソフトウェアのブレークポイントを検出するためのデバッグ防止手法ほど一般的ではないため、これは非常に良い質問です。アーキテクチャについて言及しなかったため、ハードウェアブレークポイントは、その名前が示すように、実行しているハードウェアに依存するため、このようなブレークポイントの実装はアーキテクチャごとに異なることに注意する必要があります。この回答ではすべてのアーキテクチャを網羅することはできないため、ここでは、Windows上の Intelのx86アーキテクチャについて話していることを前提に説明します。

要するに、答えははいです。ハードウェアブレークポイントを検出するには、基本的に2つの一般的な方法があります。

  1. スレッドのコンテキストを使用してデバッグレジスタにアクセスする
  2. SEHを作成する(構造化例外処理) 、次に例外を発生させてデバッグレジスタにアクセスします。
  3. ol>

    各メソッドを理解するには、最初にハードウェアブレークポイントとは何か、(つまり)どのように機能するかを理解する必要があります。

    ハードウェアブレークポイント

    x86 アーキテクチャでは、デバッガはハードウェアブレークポイントを適用するために一連のデバッグレジスタを使用します。 DR0 から DR7 の範囲で、デバッグ手順を制御するための8つのデバッグレジスタが存在します。これらのレジスタには、 ring3 特権からはアクセスできませんが、CPL0(現在の特権レベル、ring0)からのみアクセスできます。したがって、他の特権レベルで実行しているときにデバッグレジスタを読み書きしようとすると、一般保護違反が発生します。デバッグレジスタを使用すると、デバッガはメモリにアクセスして読み取りまたは書き込みを行うときに、プログラムの実行を中断し、制御を渡すことができます。

    x86デバッグレジスタ

  • DR0-線形ブレークポイントアドレス0
  • DR1-線形ブレークポイントアドレス1
  • DR2-線形ブレークポイントアドレス2
  • DR3-線形ブレークポイントアドレス3

  • DR4-予約済み。 Intelによって定義されていません

  • DR5-予約済み。 Intelによって定義されていません

  • DR6-ブレークポイントステータス

  • DR7-ブレークポイント制御

DR0-DR3は、ブレークポイントの線形アドレスを格納します。保存されるアドレスは、物理アドレスと同じにすることも、物理アドレスに変換する必要があります。 DR6 は、アクティブ化されているブレークポイントを示します。 DR7 は、アクセスモード(読み取り書き込み、または実行)によってブレークポイントアクティブ化モードを定義します。

ハードウェアブレークポイントの検出

方法1-ThreadContextWin API

次の例は、 thisの例に基づいています。 CodeProjectからの記事。この例は、コードの各部分を説明するためにコメント化されています。

  bool IsHWBreakpointExists(){//この構造は関数のキーであり、CONTEXTctxです。 ZeroMemory(&ctx、sizeof(CONTEXT)); // CONTEXT構造体は入力/出力パラメータであるため、//フラグを設定して、Get / SetThreadContextが何を設定または取得するかを認識できるようにする必要があります。 ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; //スレッドへのハンドルを取得しますHANDLEhThread = GetCurrentThread(); //レジスタを取得しますif(GetThreadContext(hThread、&ctx)== 0)return false; if((ctx.Dr0)||(ctx.Dr1)||(ctx.Dr2)||(ctx.Dr3)){trueを返す; } else {falseを返す; }}  

方法2-SEH
デバッグレジスタを操作するSEH方法は、はるかに一般的であり、図に示すように、アセンブリで実装する方が簡単です。次の例でも、CodeProjectから:

  ClrHwBpHandler proto .safeseh ClrHwBpHandlerClearHardwareBreakpoints procはfs:nothing push offset ClrHwBpHandler push fs:[0] mov dword ptr fs:[0]、esp; SEH xor eax、eax diveaxを設定します;例外を発生させますpopdword ptr fs:[0];実行はここで続行されますaddesp、4 retClearHardwareBreakpoints endpClrHwBpHandler proc xor eax、eax
mov ecx、[esp + 0ch];これは、スタックmov dword ptr [ecx + 04h]、eaxのCONTEXT構造体です。 Dr0 mov dword ptr [ecx + 08h]、eax; Dr1 mov dword ptr [ecx + 0ch]、eax; Dr2 mov dword ptr [ecx + 10h]、eax; Dr3 mov dword ptr [ecx + 14h]、eax; Dr6 mov dword ptr [ecx + 18h]、eax; Dr7 add dword ptr [ecx + 0b8h]、2; div eax retClrHwBpHandler endpをスキップするためにEIPに2を追加します 

参照:



このQ&Aは英語から自動的に翻訳されました。オリジナルのコンテンツはstackexchangeで入手できます。これは、配布されているcc by-sa 3.0ライセンスに感謝します。
Loading...