DbgEng In Windows Debugging tools
dbgeng.dllExport 2 functions.
DebugCreate
DebugConnect
This is note about DebugCreate
I use 2 general interface: IDebugClient(5 version) and IDebugControl(4 version).
IDebugClient work with Process, remote machines, servers and dump. Also, IDebugClient provide get\set callbacks, output and some masks.
IDebugControl managment debug engine: Debug statuts, assembler\disassembler, options, execute debug commands , logs and etc.
Creating dbgeng objects:
IDebugClient5 * g_lpDebugClient = NULL;
IDebugControl4 * g_lpDebugControl = NULL;
Creating dbgeng objects:
HRESULT hr;
hr = DebugCreate(
__uuidof(IDebugClient5),
(LPVOID*)&g_lpDebugClient
);
if (FAILED(hr))
{
printf("Failed DebugCreate hr = 0x%08X\n", hr);
return FALSE;
}
hr = g_lpDebugClient->QueryInterface(
__uuidof(IDebugControl4),
(LPVOID*)&g_lpDebugControl
);
if (FAILED(hr))
{
printf("Failed DebugControl::QueryInterface(__uuidof(IDebugControl4)) 0x%08X\n", hr);
DestroyDbgEng();
return FALSE;
}
Set output calbacks(Debug outputs)
class StdioOutputCallbacks : public IDebugOutputCallbacks
{
public:
// IUnknown.
STDMETHOD(QueryInterface)(
THIS_
IN REFIID InterfaceId,
OUT PVOID* Interface
);
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
STDMETHOD(Output)(
THIS_
IN ULONG Mask,
IN PCSTR Text
);
};
STDMETHODIMP_(ULONG)
StdioOutputCallbacks::AddRef(
THIS
)
{ return 1; }
STDMETHODIMP_(ULONG)
StdioOutputCallbacks::Release(
THIS
)
{ return 0; }
STDMETHODIMP
StdioOutputCallbacks::Output(
THIS_
IN ULONG Mask,
IN PCSTR Text
)
{ printf("%s", Text); return S_OK; }
//Set
hr = g_lpDebugClient->SetOutputCallbacks(&g_OutputCallback);
if (FAILED(hr))
{
printf("Failed DebugControl->SetOutputCallbacks 0x%08X\n", hr);
return FALSE;
}
//Set
hr = g_lpDebugClient->SetOutputCallbacks(&g_OutputCallback);
if (FAILED(hr))
{
printf("Failed DebugControl->SetOutputCallbacks 0x%08X\n", hr);
return FALSE;
}
Set Event Callbacks (Debug Events)
class EventCallbacks : public DebugBaseEventCallbacks
{
public:
STDMETHOD_(ULONG, AddRef)(
THIS
);
STDMETHOD_(ULONG, Release)(
THIS
);
STDMETHOD(GetInterestMask)(
THIS_
OUT PULONG Mask
);
STDMETHOD(CreateProcess)(
THIS_
IN ULONG64 ImageFileHandle,
IN ULONG64 Handle,
IN ULONG64 BaseOffset,
IN ULONG ModuleSize,
IN PCSTR ModuleName,
IN PCSTR ImageName,
IN ULONG CheckSum,
IN ULONG TimeDateStamp,
IN ULONG64 InitialThreadHandle,
IN ULONG64 ThreadDataOffset,
IN ULONG64 StartOffset
);
STDMETHOD(LoadModule)(
THIS_
IN ULONG64 ImageFileHandle,
IN ULONG64 BaseOffset,
IN ULONG ModuleSize,
IN PCSTR ModuleName,
IN PCSTR ImageName,
IN ULONG CheckSum,
IN ULONG TimeDateStamp
);
};
STDMETHODIMP_(ULONG)
EventCallbacks::AddRef(
THIS
)
{ return 1; }
STDMETHODIMP_(ULONG)
EventCallbacks::Release(
THIS
)
{ return 0; }
STDMETHODIMP
EventCallbacks::GetInterestMask(
THIS_
OUT PULONG Mask
)
{
*Mask = (DEBUG_EVENT_CREATE_PROCESS|DEBUG_EVENT_LOAD_MODULE);
return S_OK;
}
STDMETHODIMP
EventCallbacks::CreateProcess(
THIS_
IN ULONG64 ImageFileHandle,
IN ULONG64 Handle,
IN ULONG64 BaseOffset,
IN ULONG ModuleSize,
IN PCSTR ModuleName,
IN PCSTR ImageName,
IN ULONG CheckSum,
IN ULONG TimeDateStamp,
IN ULONG64 InitialThreadHandle,
IN ULONG64 ThreadDataOffset,
IN ULONG64 StartOffset
)
{
printf("Create new process!(%s)\n", ModuleName);
return DEBUG_STATUS_GO;
}
STDMETHODIMP
EventCallbacks::LoadModule(
THIS_
IN ULONG64 ImageFileHandle,
IN ULONG64 BaseOffset,
IN ULONG ModuleSize,
IN PCSTR ModuleName,
IN PCSTR ImageName,
IN ULONG CheckSum,
IN ULONG TimeDateStamp
)
{
printf("LoadModule!(%s)\n", ModuleName);
return DEBUG_STATUS_GO;
}
Debugger loop
void DbgEventLoop(void)
{
HRESULT hr;
ULONG ExecStatus;
while ( true )
{
//Wait event
hr = g_lpDebugControl->WaitForEvent(
DEBUG_WAIT_DEFAULT,
INFINITE
);
if ( hr != S_OK )
{
if (g_lpDebugControl->GetExecutionStatus(
&ExecStatus
) == S_OK
&& ExecStatus == DEBUG_STATUS_NO_DEBUGGEE
) {
break;
}
printf("WaitForEvent failed, 0x%X\n", hr);
}
//Check debug status
if (g_lpDebugControl->GetExecutionStatus(
&ExecStatus
) == S_OK )
{
printf("Exec status = %X\n", ExecStatus);
}
g_lpDebugControl->Execute(
DEBUG_OUTCTL_ALL_CLIENTS, "kb",
DEBUG_EXECUTE_DEFAULT);
g_lpDebugControl->Execute(
DEBUG_OUTCTL_ALL_CLIENTS, "g",
DEBUG_EXECUTE_DEFAULT);
//Check debug status, after exec 'g' debug go!
if (g_lpDebugControl->GetExecutionStatus(
&ExecStatus
) == S_OK )
{
printf("Exec status = %X\n", ExecStatus);
}
}
}
Destroy dbgeng Objects
BOOL DestroyDbgEng()
{
if ( g_lpDebugControl ) {
g_lpDebugControl->Release();
g_lpDebugControl = NULL;
}
if ( g_lpDebugClient )
{
g_lpDebugClient->EndSession(DEBUG_END_PASSIVE);
g_lpDebugClient->Release();
g_lpDebugClient = NULL;
}
return TRUE;
}
Test create process
hr = g_lpDebugClient->CreateProcess(
NULL,
"C:\\Windows\\system32\\notepad.exe",
DEBUG_ONLY_THIS_PROCESS
);
if (FAILED(hr))
{
printf("Failed create debug process(0x%08X)\n", hr);
DestroyDbgEng();
return 2;
}