我在写一个跟踪其他程序执行的程序。我正在使用动态指令工具来跟踪x86的CMP指令的行为。逃跑陷阱/单步
我使用Windows调试API来控制调试程序的行为。我使用“只调试此进程”标志启动程序,然后在主线程上设置陷阱标志。
然后我进入主调试循环:
bool cDebugger::ProcessNextDebugEvent(bool Verbose)
{
bool Result = true;
DEBUG_EVENT Event = { 0 };
DWORD Status = DBG_CONTINUE;
if (!WaitForDebugEvent(&Event, INFINITE))
{
_Reporter("Error: WaitForDebugEvent: " + to_string(GetLastError()));
return Result;
}
else
{
if (Event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Created process: " + GetFilenameFromHandle(Event.u.CreateProcessInfo.hFile));
}
else if (Event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Dll: " + GetFilenameFromHandle(Event.u.LoadDll.hFile) + " loaded at: " + to_string((unsigned int)Event.u.LoadDll.lpBaseOfDll));
_Dlls.insert(make_pair((unsigned int)Event.u.LoadDll.lpBaseOfDll, GetFilenameFromHandle(Event.u.LoadDll.hFile)));
}
else if (Event.dwDebugEventCode == CREATE_THREAD_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Thread[" + to_string(Event.dwThreadId) + "] created at: " + to_string((unsigned int)Event.u.CreateThread.lpStartAddress));
_Threads.push_back(Event.dwThreadId);
}
else if (Event.dwDebugEventCode == EXIT_THREAD_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Thread[" + to_string(Event.dwThreadId) + "] exited with: " + to_string(Event.u.ExitThread.dwExitCode));
auto It = std::find(_Threads.begin(), _Threads.end(), Event.dwThreadId);
if (It != _Threads.end())
_Threads.erase(It);
}
else if (Event.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Dll " + _Dlls[(unsigned int)Event.u.UnloadDll.lpBaseOfDll] + " unloaded at : " + to_string((unsigned int)Event.u.UnloadDll.lpBaseOfDll));
}
else if (Event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
{
if (Verbose)
_Reporter("Process exited with: " + to_string(Event.u.ExitProcess.dwExitCode));
Result = false;
_Threads.clear();
}
else if (Event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
{
if (Event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP)
{
Status = DBG_EXCEPTION_HANDLED;
}
else
{
Status = DBG_EXCEPTION_NOT_HANDLED;
}
}
for (size_t i = 0; i < _Threads.size(); i++)
{
HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, _Threads[i]);
if (hThread == NULL)
{
_Reporter("Error: Failed to open thread: " + to_string(GetLastError()));
}
else
{
CONTEXT ThreadContext = GetThreadContext(hThread);
ProcessStep(ThreadContext, hThread);
ThreadContext.EFlags |= 0x100; // Set trap flag.
SetThreadContext(hThread, ThreadContext);
CloseHandle(hThread);
}
}
if (!ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, Status))
{
_Reporter("Error: ContinueDebugEvent: " + to_string(GetLastError()));
}
}
return Result;
}
正如你可以看到我遍历在函数结束时,所有的线程,以确保单步异常将触发每一个指令的每一个线程。但是有时执行似乎会“逃避”这个陷阱,通常会在下一次调试事件再次捕获之前执行数百万条指令。
我写了另一个小应用程序来测试我的程序的行为:
int main(int argc, char* argv[])
{
//__asm int 3h
if (argc == 41234123)
{
printf("Got one\n");
}
return 0;
}
示踪剂的预期输出应该是:
0xDEADBEEF CMP 1 41234123
然而不知何故示踪剂不记录该指令(表明没有调试事件发生,并且没有设置陷阱标志)。
任何人都可以看到,如果我在我的调试循环中做错了什么?或者测试程序的哪种行为(加载dll)可能会对此负责?
您确定编译器生成了一个'CMP'指令,并且使用了您期望的指令的编码?你在哪里编码打印你期望的输出? – 2014-09-06 04:27:37
是的,我仔细检查了一个反汇编器,以确保实际上有一个CMP指令,而不是测试或其他东西。它在那里,只有我的追踪者没有看到它。 – user513647 2014-09-06 11:17:47