Я нахожусь в процессе эксперимента по созданию собственного отладчика на C ++ в Visual Studio 2017. Тестирование нескольких консольных приложений - это нормально. Однако, когда я запускаю блокнот с ним, все в порядке, пока я не нажму File -> Open, и он не перейдет в постоянный цикл с выводом этих двух кодов исключений, и диалоговое окно open не открывается:
Exception: 3221356611
Exception: 998
Когда тот же процесс был запущен под WinDbg, эти исключения не возникали.
Код скомпилирован как x86 и запускает 32-битный процесс в Windows 10 1803 build 17134.523 x64.
Любые предложения о том, что может вызвать это?
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <iostream>
#include <map>
std::map < LPVOID, std::wstring > DllNameMap;
int main()
{
std::wstring filename(L"c:\\windows\\syswow64\\notepad.exe");
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
DEBUG_EVENT debugEvent;
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
(LPWSTR)filename.c_str(), // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_SUSPENDED, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return -1;
}
if (DebugActiveProcess(pi.dwProcessId))
{
ResumeThread(pi.hThread);
std::cout << "Debugger attached!" << std::endl;
EnterDebugLoop(&debugEvent,pi.hProcess);
}
return 0;
}
void EnterDebugLoop(const LPDEBUG_EVENT DebugEv,HANDLE hProcess)
{
DWORD dwContinueStatus = DBG_CONTINUE; // exception continuation
for (;;)
{
// Wait for a debugging event to occur. The second parameter indicates
// that the function does not return until a debugging event occurs.
WaitForDebugEvent(DebugEv, INFINITE);
// Process the debugging event code.
switch (DebugEv->dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
// Process the exception code. When handling
// exceptions, remember to set the continuation
// status parameter (dwContinueStatus). This value
// is used by the ContinueDebugEvent function.
std::cout << "Exception: " << DebugEv->u.Exception.ExceptionRecord.ExceptionCode << std::endl;
switch (DebugEv->u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
std::cout << "ACCESS VIOLATION" << std::endl;
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_BREAKPOINT:
std::cout << "BREAKPOINT" << std::endl;
// First chance: Display the current
// instruction and register values.
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
std::cout << "DATATYPE MISALIGNMENT" << std::endl;
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
case EXCEPTION_SINGLE_STEP:
std::cout << "SINGLE STEP" << std::endl;
// First chance: Update the display of the
// current instruction and register values.
break;
case DBG_CONTROL_C:
std::cout << "CTRL+C" << std::endl;
// First chance: Pass this on to the system.
// Last chance: Display an appropriate error.
break;
default:
// Handle other exceptions.
break;
}
break;
case CREATE_THREAD_DEBUG_EVENT:
std::cout << "Create Thread" << std::endl;
// As needed, examine or change the thread's registers
// with the GetThreadContext and SetThreadContext functions;
// and suspend and resume thread execution with the
// SuspendThread and ResumeThread functions.
break;
case CREATE_PROCESS_DEBUG_EVENT:
std::cout << "Create Process" << std::endl;
// As needed, examine or change the registers of the
// process's initial thread with the GetThreadContext and
// SetThreadContext functions; read from and write to the
// process's virtual memory with the ReadProcessMemory and
// WriteProcessMemory functions; and suspend and resume
// thread execution with the SuspendThread and ResumeThread
// functions. Be sure to close the handle to the process image
// file with CloseHandle.
//dwContinueStatus = OnCreateProcessDebugEvent(DebugEv);
break;
case EXIT_THREAD_DEBUG_EVENT:
// Display the thread's exit code.
std::cout << "Exit Thread Exit Code " << DebugEv->u.ExitThread.dwExitCode << std::endl;
//dwContinueStatus = OnExitThreadDebugEvent(DebugEv);
break;
case EXIT_PROCESS_DEBUG_EVENT:
// Display the process's exit code.
std::cout << "Exit process Exit Code " << DebugEv->u.ExitProcess.dwExitCode << std::endl;
///dwContinueStatus = OnExitProcessDebugEvent(DebugEv);
break;
case LOAD_DLL_DEBUG_EVENT:
{
PVOID pDllPath = NULL;
PUCHAR DllPath[(MAX_PATH + 1) * sizeof(WCHAR)];
DWORD dwLen = 0;
ZeroMemory(DllPath, sizeof(DllPath));
if (DebugEv->u.LoadDll.lpImageName == NULL)
{
break;
}
// read DLL name pointer value
if (ReadProcessMemory(
hProcess,
DebugEv->u.LoadDll.lpImageName,
&pDllPath, sizeof(PVOID),
&dwLen) && pDllPath)
{
dwLen = (DebugEv->u.LoadDll.fUnicode ? MAX_PATH * sizeof(WCHAR) : MAX_PATH);
// read DLL name
if (ReadProcessMemory(
hProcess,
pDllPath,
DllPath, dwLen,
&dwLen))
{
char szDllPath[MAX_PATH], *lpszDllName = NULL;
if (DebugEv->u.LoadDll.fUnicode)
{
std::wstring path((wchar_t*)DllPath);
DllNameMap.insert(std::make_pair(DebugEv->u.LoadDll.lpBaseOfDll, path));
std::wcout << "Image loaded (Unicode): " << path.c_str() << std::endl;
}
else
{
// todo: Add to DllNameMAp
std::wcout << "Image loaded: " << DllPath << std::endl;
}
}
else
{
std::cout << "Error processing memory : " << GetLastError() << std::endl;
}
}
else
{
std::wcout << "ERROR reading process memory : " << GetLastError() << std::endl;
}
}
// Read the debugging information included in the newly
// loaded DLL. Be sure to close the handle to the loaded DLL
// with CloseHandle.
///dwContinueStatus = OnLoadDllDebugEvent(DebugEv);
break;
case UNLOAD_DLL_DEBUG_EVENT:
std::wcout << "Unload DLL: " << DllNameMap[DebugEv->u.UnloadDll.lpBaseOfDll] << std::endl;
break;
case OUTPUT_DEBUG_STRING_EVENT:
// Display the output debugging string.
std::wcout << "Debug Event" << std::endl;
if (DebugEv->u.DebugString.fUnicode)
{
std::wcout << (wchar_t)DebugEv->u.DebugString.lpDebugStringData << std::endl;
}
//dwContinueStatus = OnOutputDebugStringEvent(DebugEv);
break;
case RIP_EVENT:
//dwContinueStatus = OnRipEvent(DebugEv);
break;
}
// Resume executing the thread that reported the debugging event.
ContinueDebugEvent(DebugEv->dwProcessId,
DebugEv->dwThreadId,
dwContinueStatus);
}
}