void CMainDlg::UpdateProcessInfo() { DateTime now = DateTime::Now(); int idx = m_ListView.GetSelectedIndex(); for (unsigned i = 0; i < (unsigned)m_Processes.size(); i++) { PatchedProcess &proc = m_Processes[i]; if (proc.StillRunning) UpdateProcessStats(proc, proc.PID, m_ProcessorCount); if (!proc.StillRunning) proc.State = PatchProcessTerminated; TimeSpan runTime = now - proc.StartTime; if (!proc.StillRunning) runTime = proc.StopTime - proc.StartTime; m_ListView.AddItem(i, 2, runTime.ToString().c_str()); TCHAR tsz[128]; _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d%%"), proc.CpuUsage / 10); m_ListView.AddItem(i, 3, tsz); bool patchStarted = false; PerformProcessActions(proc, runTime, &patchStarted); if (patchStarted) m_ListView.SelectItem(i), idx = i; if (idx == i) { if (proc.LogChanged) { SetDlgItemText(IDC_EDIT1, proc.Log.c_str()); SendDlgItemMessage(IDC_EDIT1, WM_VSCROLL, SB_BOTTOM, 0); proc.LogChanged = false; } if (proc.State == PatchSuccessful) { m_StatsView.EnableWindow(TRUE); DisplayStats(proc); } else m_StatsView.EnableWindow(FALSE); } switch (proc.State) { case PatchInProgress: case PatchInProgress2: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0); m_ListView.AddItem(i, 4, _T("loading...")); break; case UnpatchInProgress: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0); m_ListView.AddItem(i, 4, _T("unloading...")); break; case PatchPending: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPending, 0, 0, 0); m_ListView.AddItem(i, 4, _T("")); break; case PatchSuccessful: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessPatched, 0, 0, 0); if (proc.pStatus) { const KdClientStatus &status = *proc.pStatus; m_ListView.AddItem(i, 4, status.PipeName + 9); proc.PipeName = status.PipeName; #ifdef _DEBUG { wchar_t wszT[MAX_PATH] = {0,}; GetVMPipeNameW(proc.PID, wszT, __countof(wszT), true); ASSERT(!wcscmp(wszT, status.PipeName)); } #endif _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d/%d"), status.PacketsSent, status.PacketsReceived); m_ListView.AddItem(i, 5, tsz); _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), status.ResyncCount); m_ListView.AddItem(i, 6, tsz); m_ListView.AddItem(i, 7, status.OSDetected ? _T("yes") : _T("")); m_ListView.AddItem(i, 8, status.DebuggerConnected ? _T("yes") : _T("")); _sntprintf_s(tsz, __countof(tsz), _TRUNCATE, _T("%d"), proc.PollRate); m_ListView.AddItem(i, 9, tsz); if (!proc.idDebuggerProcess) { if ((m_Params.AutoInvokeDebugger && status.PipeName[0]) && (!m_Params.WaitForOS || status.OSDetected)) { RunDebugger(i); } } } else { m_ListView.AddItem(i, 4, _T("loading...")); m_ListView.AddItem(i, 7, _T("")); m_ListView.AddItem(i, 8, _T("")); } break; case PatchFailed: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessFailed, 0, 0, 0); m_ListView.AddItem(i, 4, _T("")); break; case ProtocolMismatch: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessFailed, 0, 0, 0); m_ListView.AddItem(i, 4, _T("Old KDBAZIS.DLL/KDVM.DLL loaded in guest")); break; case PatchProcessTerminated: case Unpatched: m_ListView.SetItem(i, 0, LVIF_IMAGE, NULL, ProcessInactive, 0, 0, 0); m_ListView.AddItem(i, 4, (proc.State == Unpatched) ? _T("(KDCLIENT.DLL unloaded)") : _T("(terminated)")); if (proc.idDebuggerProcess) { if (m_Params.AutoCloseDebugger) { if (CloseDebugger(proc.idDebuggerProcess)) proc.idDebuggerProcess = 0; } } break; } if (proc.State != proc.PreviousState) { if (idx == i) UpdateUnpatchButton(i); proc.PreviousState = proc.State; } if ((proc.State != PatchProcessTerminated) && !proc.SessionNameRetreived) { wchar_t szName[MAX_PATH] = {0,}; GetVMSessionNameW(proc.PID, szName, _countof(szName)); // m_ListView.SetItem((UINT)i, 1, LVIF_TEXT, szName, 0, 0, 0, 0); if (szName[0]) proc.SessionNameRetreived = true; } } }
void CMainDlg::PerformProcessActions(PatchedProcess &proc, TimeSpan &runTime, bool *pPatchingStarted) { if ((proc.State == PatchProcessTerminated) || (proc.State == Unpatched)) CleanupProcessEntry(proc); else { if (proc.hLogPipe == INVALID_HANDLE_VALUE) proc.hLogPipe = CreateLogPipe(proc.PID); } if (proc.State == PatchPending) { if (runTime.GetTotalSeconds() > m_Params.PatchDelay) { bool started = InitiatePatching(proc); if (pPatchingStarted) *pPatchingStarted = started; } } if (proc.State == PatchInProgress) { if (WaitForSingleObject(proc.hRemoteThread, 0) == WAIT_OBJECT_0) { DWORD dwCode = 0; GetExitCodeThread(proc.hRemoteThread, &dwCode); if (dwCode) proc.State = PatchInProgress2; else proc.State = PatchFailed; CloseHandle(proc.hRemoteThread); proc.hRemoteThread = INVALID_HANDLE_VALUE; } } if ((proc.State == PatchInProgress2) || (proc.State == PatchSuccessful)) { if (proc.pStatus) { switch (proc.pStatus->PatchErrorPlus1 - 1) { case ERROR_SUCCESS: proc.State = PatchSuccessful; break; case -1: proc.State = PatchInProgress2; break; default: proc.State = PatchFailed; } } if (proc.pStatus->ProtocolMismatchStatus) { proc.State = ProtocolMismatch; WORD expected = HIWORD(proc.pStatus->ProtocolMismatchStatus), found = LOWORD(proc.pStatus->ProtocolMismatchStatus); proc.pStatus->ProtocolMismatchStatus = 0; TCHAR tsz[256]; _sntprintf(tsz, __countof(tsz), _T("Warning! KDBAZIS.DLL version %x.%02x was loaded by virtual machine, while version %x.%02x was expected. Debugging functions disabled!"), HIBYTE(found), LOBYTE(found), HIBYTE(expected), LOBYTE(expected)); MessageBox(tsz, _T("Invalid KDBAZIS.DLL version"), MB_ICONWARNING); } } if (proc.State == UnpatchInProgress) { if (WaitForSingleObject(proc.hRemoteThread, 0) == WAIT_OBJECT_0) { CloseHandle(proc.hRemoteThread); proc.hRemoteThread = INVALID_HANDLE_VALUE; proc.State = Unpatched; UpdateLog(proc); CleanupProcessEntry(proc); } } UpdateLog(proc); }
/** * Signals the current thread to stop processing for the specified time span. * * @param timeSpan The amount of time to stop processing. */ static void Sleep(const TimeSpan& timeSpan) { StackTrace trace(__METHOD__, __FILE__, __LINE__); if (timeSpan > TimeSpan::Zero()) { msleep((uint32_t) timeSpan.TotalMilliseconds()); Idle += timeSpan; } }
DateTime DateTime::operator-(const TimeSpan& span) { return DateTime(unixtime()-span.totalseconds()); }
/** * Returns the thread utilization. * * @return A value in between zero and one, where zero means the thread was completely idle, and one means the thread was completely busy. */ static double Utilization() { StackTrace trace(__METHOD__, __FILE__, __LINE__); double duration = (DateTime::Utc() - Started).TotalMilliseconds(); return (duration - Idle.TotalMilliseconds()) / duration; }