| 6 | } |
| 7 | |
| 8 | std::jthread Watchdog::ObserveProcess(int pid) { |
| 9 | if (m_observingProc) { |
| 10 | spdlog::error("Failed to observer process {} another process is already being observed", pid); |
| 11 | return std::jthread(); |
| 12 | } |
| 13 | m_observingProc = true; |
| 14 | std::jthread thread([this, pid](std::stop_token stop) { |
| 15 | bool d_proc = DebugActiveProcess(pid); |
| 16 | |
| 17 | DebugSetProcessKillOnExit(FALSE); |
| 18 | |
| 19 | DEBUG_EVENT event{}; |
| 20 | HANDLE proc = nullptr; |
| 21 | |
| 22 | while (!stop.stop_requested()) { |
| 23 | if (!WaitForDebugEvent(&event, INFINITE)) { |
| 24 | break; |
| 25 | } |
| 26 | |
| 27 | if (event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT) { |
| 28 | spdlog::info("{}", event.u.DebugString.nDebugStringLength); |
| 29 | } else if (event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { |
| 30 | EXCEPTION_RECORD e_info = event.u.Exception.ExceptionRecord; |
| 31 | std::string e_type = GetExceptionType(e_info.ExceptionCode); |
| 32 | std::string dllName = GetDllPath((uint64_t)e_info.ExceptionAddress); |
| 33 | |
| 34 | spdlog::warn("{}: {} - 0x{}", e_type, dllName, e_info.ExceptionAddress); |
| 35 | |
| 36 | ShowCallstack(proc, m_loadedThreads[(uint64_t)event.dwThreadId]); |
| 37 | } else if (event.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) { |
| 38 | LOAD_DLL_DEBUG_INFO e_info = event.u.LoadDll; |
| 39 | HANDLE dllName = e_info.hFile; |
| 40 | uint64_t dllAddr = (uint64_t)e_info.lpBaseOfDll; |
| 41 | |
| 42 | char m_path[MAX_PATH] = ""; |
| 43 | if (dllName) { |
| 44 | GetFinalPathNameByHandleA(dllName, m_path, MAX_PATH, 0); |
| 45 | CloseHandle(dllName); |
| 46 | } |
| 47 | |
| 48 | m_loadedDLLs[dllAddr] = m_path; |
| 49 | spdlog::info("Loaded: {} - 0x{}", std::filesystem::path(m_path).filename().string(), dllAddr); |
| 50 | } else if (event.dwDebugEventCode == UNLOAD_DLL_DEBUG_EVENT) { |
| 51 | UNLOAD_DLL_DEBUG_INFO e_info = event.u.UnloadDll; |
| 52 | |
| 53 | uint64_t dllAddr = (uint64_t)e_info.lpBaseOfDll; |
| 54 | std::string dllName = GetDllPath(dllAddr); |
| 55 | m_loadedDLLs.erase(dllAddr); |
| 56 | |
| 57 | spdlog::info("Loaded: {} - 0x{}", dllName, dllAddr); |
| 58 | } else if (event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { |
| 59 | CREATE_PROCESS_DEBUG_INFO e_info = event.u.CreateProcessInfo; |
| 60 | |
| 61 | uint64_t p_threadid = (uint64_t)event.dwThreadId; |
| 62 | |
| 63 | proc = e_info.hProcess; |
| 64 | m_loadedThreads[p_threadid] = e_info.hThread; |
| 65 | |