我在寫一個跟蹤其他程序執行的程序。我正在使用動態指令工具來跟蹤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