ほっしーの技術ネタ備忘録

技術ネタの備忘録です。基本的に私が忘れないためのものです。他の人の役にも立つといいなぁ。

デバッガの作り方

たまにはハックっぽいことをしたいなと思って。
簡単なデバッガ(のコアだけ)を作ってみた。


デバッガを作るために必要なものは2つ。

  1. アタッチする
  2. デバッグイベントを処理する

デバッガとしてアタッチする


まずデバッガからプログラムを起動する場合は

PROCESS_INFORMATION pcInfo;
STARTUPINFO supInfo = { sizeof(STARTUPINFO) };
BOOL bResult = CreateProcess( NULL, lpCmdLine, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS | CREATE_SUSPENDED | DEBUG_PROCESS, NULL, NULL, &supInfo, &pcInfo );
if( !bResult ) throw std::runtime_error( "CreateProcess" );

こんな感じで CreateProcess API を呼ぶときに DEBUG_PROCESS フラグを立てるだけ。
他はオプション。お好みで。


も1つ、既に動いてるプロセスにアタッチしたい場合。

DebugActiveProcess( hProcess );


簡単ですね。

デバッグイベントの処理


デバッガとしてアタッチしている状態で WaitForDebugEvent API を呼ぶと、
次のデバッグイベントが発生するまで待機します。


返されたイベントを処理後、ContinueDebugEvent で継続できます。

for(;;) {
	DEBUG_EVENT evDebug;
	WaitForDebugEvent( &evDebug, INFINITE );

	switch( evDebug.dwDebugEventCode ) {
	case CREATE_PROCESS_DEBUG_EVENT: printf("CREATE_PROCESS_DEBUG_EVENT\n"); break;
	case CREATE_THREAD_DEBUG_EVENT:  printf("CREATE_THREAD_DEBUG_EVENT\n"); break;
	case EXCEPTION_DEBUG_EVENT:      printf("EXCEPTION_DEBUG_EVENT\n"); break;
	case EXIT_PROCESS_DEBUG_EVENT:   printf("EXIT_PROCESS_DEBUG_EVENT\n"); return;
	case EXIT_THREAD_DEBUG_EVENT:    printf("EXIT_THREAD_DEBUG_EVENT\n"); break;
	case LOAD_DLL_DEBUG_EVENT:       printf("LOAD_DLL_DEBUG_EVENT\n"); break;
	case OUTPUT_DEBUG_STRING_EVENT:  printf("OUTPUT_DEBUG_STRING_EVENT\n"); break;
	case RIP_EVENT:                  printf("RIP_EVENT\n"); break;
	case UNLOAD_DLL_DEBUG_EVENT:     printf("UNLOAD_DLL_DEBUG_EVENT\n"); break;
	}

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

基本はこんな感じ。

簡単すぎてビックリですね。