2017-04-26 21 views
2

私はC++で非常に単純なデバッガを作ったが、dwMillisecondsの値を持つWaitForDebugEventを呼び出した場合を除いて問題なく動作するようだ。デバッガが例外時にdebugeeを停止しないC++

私はifステートメントを持っています。これは、例外アドレスがブレークポイントIのアドレスと一致するかどうかを確認します。if(ExceptionDebugInfo.ExceptionRecord.ExceptionAddress == lpBreakpoint)です。

デクリメントeipwow64cntxt.Eip --;)は、Wow64SetThreadContext(、元の命令(WriteProcessMemory)とブレークポイント(int3)バイトを置き換え、命令キャッシュ(FlushInstructionCache)をフラッシュし、その後、私は元の命令に置き換えブレークポイントを指すようにeipを設定し、 )。

その後、メインのデバッグループ(break)に戻り、デバッグを続けます(ContinueDebugEvent)。

case EXCEPTION_BREAKPOINT: 
{ 
    WOW64_CONTEXT wow64cntxt = {0}; 

    wow64cntxt.ContextFlags = WOW64_CONTEXT_ALL; 

    if(!Wow64GetThreadContext(hThread, &wow64cntxt)) 
    { 
     printf("Error getting thread context: %lu\n", GetLastError()); 
    } 

    //lpFunction is the address of a mov instruction I set a breakpoint on 
    if(excDbgInfo.ExceptionRecord.ExceptionAddress == lpBreakpoint) 
    { 
     printf("EIP-Before: 0x%X\n", wow64cntxt.Eip); 

     //Decrement eip value to point back to the opcode I wrote over with int3 
     wow64cntxt.Eip --; 

     printf("EIP-After: 0x%X\n", wow64cntxt.Eip); 

     //original opcode I replaced with int3(0xCC) 
     instr = 0x89; 

     //replace the breakpoint with the original instruction 
     if(!WriteProcessMemory(hProcess, lpBreakpoint, &instr, sizeof(CHAR), NULL)) 
     { 
      printf("Error reversing breakpoint: %lu\n", GetLastError()); 
     } 

     //Flush the instruction cache 
     FlushInstructionCache(hProcess, lpBreakpoint, 1); 

     //Set eip to previous instruction 
     if(!Wow64SetThreadContext(hThread, &wow64cntxt)) 
     { 
      printf("Error setting thread context: %lu\n", GetLastError()); 
     } 

    } 
    system("pause"); 
    //Return to main debug loop, ContinueDebugEvent... 
    break; 
} 

私が設定されたブレークポイントの後にいくつかの時間を実行したアドレスに設定されているINFINITEその後eipWaitForDebugEventと以外のものを使用している場合。

INFINITEWaitForDebugEventを使用しないと、デバッガが例外をキャッチしたときにすでにeipがブレークポイントを過ぎてしまっているという問題があります。 WaitForDebugEventが0ミリ秒間待っていてもすぐに復帰しても、デバッグ担当者はまだブレークポイントを過ぎて実行されます。

この結果、アクセス違反が発生します。ブレークポイントで置き換えられた命令の残りの半分が、それが許可されていないメモリを変更する新しいオペコードになるためです。

while(1) 
{ 
    WaitForDebugEvent(&dbgEvent, INFINITE); 

    ProcessDebugEvent(&dbgEvent); 

    ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE); 
} 

どれ情報、洞察、ヒント、説明などをいただければ幸いです。

はここに私のメインのデバッグループです。ありがとう。

+0

あなたのコードで何がうまくいかないのですが、ブレークポイント例外がwow64コードデバッガビューの 'STATUS_WX86_BREAKPOINT'(0x4000001F)では' STATUS_BREAKPOINT'(0x80000003)ではなく 'normal 'コンテキストを使用できますGet [Set] ThreadContextしかし、wow64コード – RbMm

+0

でも(STATUS_WX86_BREAKPOINTまたはSTATUS_BREAKPOINTがあなたのデバッガ64ビットまたは32ビットに依存しています) – RbMm

+0

ところで、私はインデント編集を行ったときこれをアップしました。その理由は、これが簡単で面白い質問でも、あなたはそれをよく尋ねて、誰かがそれに答えるために必要なすべての情報を提示したからです。それをやってくれてありがとう、私たちの助けを読んでくれてありがとスタックオーバーフローへようこそ!あなたがこのような質問をし続ければ、ここではすばらしい時間を過ごすでしょう。 –

答えて

2

dwMillisecondsパラメータは、デバッグイベントが到着するのを待つためにどのくらいWaitForDebugEvent()を伝えます:ミリ秒数は、デバッグイベントを待つ

dwMilliseconds
[中]。このパラメーターがゼロの場合、関数はデバッグ・イベントをテストし、すぐに戻ります。

を:パラメータがINFINITEの場合、デバッグイベントはあなたが実際に処理を必要とする本当のデバッグイベントがあることを確認するために WaitForDebugEvent()の戻り値をチェックする必要があり

を発生するまで、関数は戻りません。

関数が成功すると、戻り値はゼロ以外です。

この関数が失敗すると、戻り値はゼロになります。拡張エラー情報を取得するには、GetLastErrorに電話してください。例えば

while (1) 
{ 
    if (WaitForDebugEvent(&dbgEvent, AnyValueHere)) // <-- 
    { 
     ProcessDebugEvent(&dbgEvent); 
     ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_CONTINUE); 
    } 
    ... 
} 

言われているので、dwMillisecondsパラメータは、ブレークポイントがヒットされたときにデバッグが待機する時間に影響を及ぼしません。ブレークポイントに達すると、デバッグがすぐに停止し、デバッガに通知されます。これは明確に文書に記載されている:

システムがデバッグイベントのデバッガを通知

Debugging Events

が、それはまた、影響を受けるプロセスですべてのスレッドを中断します。 ContinueDebugEventを使用してデバッガがデバッグイベントを続行するまで、スレッドは実行を再開しません。

だからチャンスがProcessDebugEvent()は単純に正しくブレークポイントを処理していない、とあなたが行って処理した後ContinueDebugEvent()を呼び出した場合にのみ、その後デバッグ対象がウェイクアップされ、あります。

+0

非常に高く評価されています。 WaitForDebugEventの戻り値をチェックしておかなければなりません。 ** Facepalm **。今はうまくいっています、どうもありがとうございます。 :) – EggHead

関連する問題