mirror of
https://github.com/jthuraisamy/TelemetrySourcerer
synced 2026-06-08 15:11:15 +00:00
1773 lines
58 KiB
C++
1773 lines
58 KiB
C++
#include <Windows.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <tchar.h>
|
|
#include <commctrl.h>
|
|
#include <windowsx.h>
|
|
#include <strsafe.h>
|
|
#include <TlHelp32.h>
|
|
|
|
#include <string>
|
|
|
|
#include "TelemetrySourcerer.h"
|
|
#include "KmCallbacks.h"
|
|
#include "UmHooks.h"
|
|
#include "UmETW.h"
|
|
|
|
// ToDo: review visual styles before enabling.
|
|
//#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|
|
|
using namespace std;
|
|
|
|
// Global variables
|
|
HINSTANCE g_hInst;
|
|
|
|
struct WINDOW_HANDLES {
|
|
HWND Main;
|
|
HWND StatusBar;
|
|
HWND TabControl;
|
|
|
|
// Kernel-mode Callbacks
|
|
HWND KmcPage;
|
|
HWND KmcRefreshButton;
|
|
HWND KmcSuppressButton;
|
|
HWND KmcRevertButton;
|
|
HWND KmcCountLabel;
|
|
HWND KmcTipLabel;
|
|
HWND KmcListView;
|
|
|
|
// User-mode Hooks
|
|
HWND UmhPage;
|
|
HWND UmhRefreshButton;
|
|
HWND UmhRestoreButton;
|
|
HWND UmhLoadButton;
|
|
HWND UmhCountLabel;
|
|
HWND UmhTipLabel;
|
|
HWND UmhListView;
|
|
|
|
// User-mode ETW Traces
|
|
HWND UmePage;
|
|
HWND UmeRefreshButton;
|
|
HWND UmeDisableButton;
|
|
HWND UmeStopButton;
|
|
HWND UmeCountLabel;
|
|
HWND UmeTipLabel;
|
|
HWND UmeListView;
|
|
|
|
// About
|
|
HWND AbtPage;
|
|
HWND AbtLabel;
|
|
} wh;
|
|
|
|
struct WINDOW_DATA {
|
|
std::vector<PCALLBACK_ENTRY> KmcCallbacks;
|
|
std::vector<PLOADED_MODULE> UmhModules;
|
|
std::vector<PTRACING_SESSION> UmeSessions;
|
|
} wd;
|
|
|
|
// Function: WinMain
|
|
// Description: Entry point for the application.
|
|
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
|
|
{
|
|
// The main window class name.
|
|
static TCHAR szWindowClass[] = _T("DesktopApp");
|
|
|
|
// The string that appears in the application's title bar.
|
|
WCHAR szTitle[MAX_PATH] = { 0 };
|
|
StringCbPrintfW(szTitle, MAX_PATH, L"%s v%s by @Jackson_T (%s %s)", TOOL_NAME, VERSION, _T(__DATE__), _T(__TIME__));
|
|
|
|
WNDCLASSEX wcex;
|
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
|
wcex.lpfnWndProc = MainWndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = hInstance;
|
|
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
|
|
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wcex.lpszMenuName = NULL;
|
|
wcex.lpszClassName = szWindowClass;
|
|
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
|
|
RegisterClassEx(&wcex);
|
|
|
|
// Store instance handle in our global variable.
|
|
g_hInst = hInstance;
|
|
|
|
// Create the main window and show it.
|
|
wh.Main = CreateWindowEx(
|
|
NULL,
|
|
szWindowClass,
|
|
szTitle,
|
|
WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT, CW_USEDEFAULT,
|
|
900, 500,
|
|
NULL,
|
|
NULL,
|
|
hInstance,
|
|
NULL
|
|
);
|
|
ShowWindow(wh.Main, nCmdShow);
|
|
UpdateWindow(wh.Main);
|
|
|
|
// Main message loop:
|
|
MSG msg;
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
|
|
return (int)msg.wParam;
|
|
}
|
|
|
|
// Function: MainWndProc
|
|
// Description: Processes messages for the main window.
|
|
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
|
|
|
|
switch (message)
|
|
{
|
|
case WM_CREATE:
|
|
{
|
|
PaintWindow(hWnd);
|
|
|
|
KmcLoadResults();
|
|
UmhLoadResults();
|
|
UmeLoadResults();
|
|
|
|
ShowWindow(wh.KmcPage, SW_SHOW);
|
|
break;
|
|
}
|
|
case WM_DESTROY:
|
|
{
|
|
PostQuitMessage(0);
|
|
break;
|
|
}
|
|
case WM_GETMINMAXINFO:
|
|
{
|
|
lpMMI->ptMinTrackSize.x = 900; // Set minimum dimensions to 900x500.
|
|
lpMMI->ptMinTrackSize.y = 500;
|
|
lpMMI->ptMaxTrackSize.x = 900; // Set maximum dimensions to 900x500.
|
|
lpMMI->ptMaxTrackSize.y = 500;
|
|
break;
|
|
}
|
|
case WM_SIZE:
|
|
{
|
|
ResizeWindow(hWnd);
|
|
break;
|
|
}
|
|
case WM_NOTIFY:
|
|
{
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case TCN_SELCHANGE:
|
|
{
|
|
DWORD TabIndex = TabCtrl_GetCurSel(wh.TabControl);
|
|
ShowWindow(wh.KmcPage, (TabIndex == 0) ? SW_SHOW : SW_HIDE);
|
|
ShowWindow(wh.UmhPage, (TabIndex == 1) ? SW_SHOW : SW_HIDE);
|
|
ShowWindow(wh.UmePage, (TabIndex == 2) ? SW_SHOW : SW_HIDE);
|
|
ShowWindow(wh.AbtPage, (TabIndex == 3) ? SW_SHOW : SW_HIDE);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case WM_CLOSE:
|
|
UnloadDriver();
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Function: KmcWndProc
|
|
// Description: Processes messages for the kernel-mode callbacks tab.
|
|
LRESULT CALLBACK KmcWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_COMMAND:
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case BN_CLICKED:
|
|
{
|
|
if (wh.KmcRefreshButton == (HWND)lParam)
|
|
KmcLoadResults();
|
|
else if (wh.KmcSuppressButton == (HWND)lParam)
|
|
KmcSuppressCallback();
|
|
else if (wh.KmcRevertButton == (HWND)lParam)
|
|
KmcRevertCallback();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case WM_NOTIFY:
|
|
{
|
|
NMLVDISPINFO* plvdi;
|
|
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case LVN_GETDISPINFO:
|
|
{
|
|
plvdi = (NMLVDISPINFO*)lParam;
|
|
PCALLBACK_ENTRY Callback = wd.KmcCallbacks.at(plvdi->item.lParam);
|
|
LPWSTR Module = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(Module, MAX_PATH, L"%ls + 0x%x", Callback->ModuleName, Callback->ModuleOffset);
|
|
|
|
switch (plvdi->item.iSubItem)
|
|
{
|
|
case 0:
|
|
{
|
|
switch (Callback->Type)
|
|
{
|
|
case CALLBACK_TYPE::PsLoadImage:
|
|
plvdi->item.pszText = (LPWSTR)L"Image Load";
|
|
break;
|
|
case CALLBACK_TYPE::PsProcessCreation:
|
|
plvdi->item.pszText = (LPWSTR)L"Process Creation";
|
|
break;
|
|
case CALLBACK_TYPE::PsThreadCreation:
|
|
plvdi->item.pszText = (LPWSTR)L"Thread Creation";
|
|
break;
|
|
case CALLBACK_TYPE::CmRegistry:
|
|
plvdi->item.pszText = (LPWSTR)L"Registry";
|
|
break;
|
|
case CALLBACK_TYPE::ObProcessHandlePre:
|
|
case CALLBACK_TYPE::ObProcessHandlePost:
|
|
case CALLBACK_TYPE::ObThreadHandlePre:
|
|
case CALLBACK_TYPE::ObThreadHandlePost:
|
|
case CALLBACK_TYPE::ObDesktopHandlePre:
|
|
case CALLBACK_TYPE::ObDesktopHandlePost:
|
|
plvdi->item.pszText = (LPWSTR)L"Object Handle";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreatePre:
|
|
case CALLBACK_TYPE::MfCreatePost:
|
|
case CALLBACK_TYPE::MfCreateNamedPipePre:
|
|
case CALLBACK_TYPE::MfCreateNamedPipePost:
|
|
case CALLBACK_TYPE::MfClosePre:
|
|
case CALLBACK_TYPE::MfClosePost:
|
|
case CALLBACK_TYPE::MfReadPre:
|
|
case CALLBACK_TYPE::MfReadPost:
|
|
case CALLBACK_TYPE::MfWritePre:
|
|
case CALLBACK_TYPE::MfWritePost:
|
|
case CALLBACK_TYPE::MfQueryInformationPre:
|
|
case CALLBACK_TYPE::MfQueryInformationPost:
|
|
case CALLBACK_TYPE::MfSetInformationPre:
|
|
case CALLBACK_TYPE::MfSetInformationPost:
|
|
case CALLBACK_TYPE::MfQueryEaPre:
|
|
case CALLBACK_TYPE::MfQueryEaPost:
|
|
case CALLBACK_TYPE::MfSetEaPre:
|
|
case CALLBACK_TYPE::MfSetEaPost:
|
|
case CALLBACK_TYPE::MfFlushBuffersPre:
|
|
case CALLBACK_TYPE::MfFlushBuffersPost:
|
|
case CALLBACK_TYPE::MfQueryVolumeInformationPre:
|
|
case CALLBACK_TYPE::MfQueryVolumeInformationPost:
|
|
case CALLBACK_TYPE::MfSetVolumeInformationPre:
|
|
case CALLBACK_TYPE::MfSetVolumeInformationPost:
|
|
case CALLBACK_TYPE::MfDirectoryControlPre:
|
|
case CALLBACK_TYPE::MfDirectoryControlPost:
|
|
case CALLBACK_TYPE::MfFileSystemControlPre:
|
|
case CALLBACK_TYPE::MfFileSystemControlPost:
|
|
case CALLBACK_TYPE::MfDeviceControlPre:
|
|
case CALLBACK_TYPE::MfDeviceControlPost:
|
|
case CALLBACK_TYPE::MfInternalDeviceControlPre:
|
|
case CALLBACK_TYPE::MfInternalDeviceControlPost:
|
|
case CALLBACK_TYPE::MfShutdownPre:
|
|
case CALLBACK_TYPE::MfShutdownPost:
|
|
case CALLBACK_TYPE::MfLockControlPre:
|
|
case CALLBACK_TYPE::MfLockControlPost:
|
|
case CALLBACK_TYPE::MfCleanupPre:
|
|
case CALLBACK_TYPE::MfCleanupPost:
|
|
case CALLBACK_TYPE::MfCreateMailslotPre:
|
|
case CALLBACK_TYPE::MfCreateMailslotPost:
|
|
case CALLBACK_TYPE::MfQuerySecurityPre:
|
|
case CALLBACK_TYPE::MfQuerySecurityPost:
|
|
case CALLBACK_TYPE::MfSetSecurityPre:
|
|
case CALLBACK_TYPE::MfSetSecurityPost:
|
|
case CALLBACK_TYPE::MfPowerPre:
|
|
case CALLBACK_TYPE::MfPowerPost:
|
|
case CALLBACK_TYPE::MfSystemControlPre:
|
|
case CALLBACK_TYPE::MfSystemControlPost:
|
|
case CALLBACK_TYPE::MfDeviceChangePre:
|
|
case CALLBACK_TYPE::MfDeviceChangePost:
|
|
case CALLBACK_TYPE::MfQueryQuotaPre:
|
|
case CALLBACK_TYPE::MfQueryQuotaPost:
|
|
case CALLBACK_TYPE::MfSetQuotaPre:
|
|
case CALLBACK_TYPE::MfSetQuotaPost:
|
|
case CALLBACK_TYPE::MfPnpPre:
|
|
case CALLBACK_TYPE::MfPnpPost:
|
|
plvdi->item.pszText = (LPWSTR)L"File System";
|
|
break;
|
|
default:
|
|
plvdi->item.pszText = (LPWSTR)L"Unknown";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
switch (Callback->Type)
|
|
{
|
|
case CALLBACK_TYPE::PsLoadImage:
|
|
plvdi->item.pszText = (LPWSTR)L"PsSetLoadImageNotifyRoutine";
|
|
break;
|
|
case CALLBACK_TYPE::PsProcessCreation:
|
|
plvdi->item.pszText = (LPWSTR)L"PsSetCreateProcessNotifyRoutine";
|
|
break;
|
|
case CALLBACK_TYPE::PsThreadCreation:
|
|
plvdi->item.pszText = (LPWSTR)L"PsSetCreateThreadNotifyRoutine";
|
|
break;
|
|
case CALLBACK_TYPE::CmRegistry:
|
|
plvdi->item.pszText = (LPWSTR)L"CmRegisterCallbackEx";
|
|
break;
|
|
case CALLBACK_TYPE::ObProcessHandlePre:
|
|
plvdi->item.pszText = (LPWSTR)L"PsProcessType (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::ObProcessHandlePost:
|
|
plvdi->item.pszText = (LPWSTR)L"PsProcessType (post)";
|
|
break;
|
|
case CALLBACK_TYPE::ObThreadHandlePre:
|
|
plvdi->item.pszText = (LPWSTR)L"PsThreadType (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::ObThreadHandlePost:
|
|
plvdi->item.pszText = (LPWSTR)L"PsThreadType (post)";
|
|
break;
|
|
case CALLBACK_TYPE::ObDesktopHandlePre:
|
|
plvdi->item.pszText = (LPWSTR)L"ExDesktopObjectType (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::ObDesktopHandlePost:
|
|
plvdi->item.pszText = (LPWSTR)L"ExDesktopObjectType (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreatePre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreatePost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreateNamedPipePre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE_NAMED_PIPE (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreateNamedPipePost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE_NAMED_PIPE (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfClosePre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CLOSE (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfClosePost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CLOSE (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfReadPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_READ (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfReadPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_READ (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfWritePre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_WRITE (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfWritePost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_WRITE (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryInformationPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_INFORMATION (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryInformationPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_INFORMATION (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetInformationPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_INFORMATION (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetInformationPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_INFORMATION (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryEaPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_EA (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryEaPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_EA (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetEaPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_EA (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetEaPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_EA (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfFlushBuffersPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_FLUSH_BUFFERS (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfFlushBuffersPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_FLUSH_BUFFERS (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryVolumeInformationPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_VOLUME_INFORMATION (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryVolumeInformationPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_VOLUME_INFORMATION (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetVolumeInformationPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_VOLUME_INFORMATION (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetVolumeInformationPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_VOLUME_INFORMATION (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDirectoryControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DIRECTORY_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDirectoryControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DIRECTORY_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfFileSystemControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_FILE_SYSTEM_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfFileSystemControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_FILE_SYSTEM_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDeviceControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DEVICE_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDeviceControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DEVICE_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfInternalDeviceControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_INTERNAL_DEVICE_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfInternalDeviceControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_INTERNAL_DEVICE_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfShutdownPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SHUTDOWN (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfShutdownPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SHUTDOWN (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfLockControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_LOCK_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfLockControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_LOCK_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCleanupPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CLEANUP (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCleanupPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CLEANUP (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreateMailslotPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE_MAILSLOT (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfCreateMailslotPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_CREATE_MAILSLOT (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQuerySecurityPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_SECURITY (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQuerySecurityPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_SECURITY (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetSecurityPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_SECURITY (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetSecurityPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_SECURITY (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfPowerPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_POWER (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfPowerPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_POWER (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSystemControlPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SYSTEM_CONTROL (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSystemControlPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SYSTEM_CONTROL (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDeviceChangePre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DEVICE_CHANGE (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfDeviceChangePost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_DEVICE_CHANGE (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryQuotaPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_QUOTA (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfQueryQuotaPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_QUERY_QUOTA (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetQuotaPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_QUOTA (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfSetQuotaPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_SET_QUOTA (post)";
|
|
break;
|
|
case CALLBACK_TYPE::MfPnpPre:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_PNP (pre)";
|
|
break;
|
|
case CALLBACK_TYPE::MfPnpPost:
|
|
plvdi->item.pszText = (LPWSTR)L"IRP_MJ_PNP (post)";
|
|
break;
|
|
default:
|
|
plvdi->item.pszText = (LPWSTR)L"Unknown";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
plvdi->item.pszText = Module;
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
plvdi->item.pszText = (Callback->Suppressed) ? (LPWSTR)L"Yes" : (LPWSTR)L"No";
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
plvdi->item.pszText = (Callback->Notable) ? (LPWSTR)L"Yes" : (LPWSTR)L"No";
|
|
break;
|
|
}
|
|
default:
|
|
plvdi->item.pszText = (LPWSTR)L"N/A";
|
|
break;
|
|
}
|
|
}
|
|
case NM_CUSTOMDRAW:
|
|
{
|
|
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
|
|
|
|
BOOL IsNotable = FALSE;
|
|
BOOL IsSuppressed = FALSE;
|
|
ULONG CallbackIndex = lplvcd->nmcd.lItemlParam;
|
|
|
|
if (wd.KmcCallbacks.size())
|
|
{
|
|
PCALLBACK_ENTRY Callback = wd.KmcCallbacks.at(CallbackIndex);
|
|
|
|
if (Callback->Notable)
|
|
IsNotable = TRUE;
|
|
|
|
if (Callback->Suppressed)
|
|
IsSuppressed = TRUE;
|
|
}
|
|
|
|
switch (lplvcd->nmcd.dwDrawStage)
|
|
{
|
|
case CDDS_PREPAINT:
|
|
return CDRF_NOTIFYITEMDRAW;
|
|
case CDDS_ITEMPREPAINT:
|
|
{
|
|
if (IsSuppressed)
|
|
{
|
|
lplvcd->clrText = RGB(255, 255, 255);
|
|
lplvcd->clrTextBk = RGB(128, 128, 128);
|
|
}
|
|
else if (IsNotable)
|
|
{
|
|
lplvcd->clrText = RGB(0, 0, 0);
|
|
lplvcd->clrTextBk = RGB(255, 255, 200);
|
|
}
|
|
else
|
|
{
|
|
lplvcd->clrText = RGB(0, 0, 0);
|
|
lplvcd->clrTextBk = RGB(255, 255, 255);
|
|
}
|
|
return CDRF_NEWFONT;
|
|
}
|
|
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
|
|
return CDRF_NEWFONT;
|
|
}
|
|
break;
|
|
}
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
ListView_SortItems(wh.KmcListView, KmcCompareFunc, pnmv->iSubItem);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Function: UmhWndProc
|
|
// Description: Processes messages for the user-mode hooks tab.
|
|
LRESULT CALLBACK UmhWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_COMMAND:
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case BN_CLICKED:
|
|
{
|
|
if (wh.UmhRefreshButton == (HWND)lParam)
|
|
UmhLoadResults();
|
|
else if (wh.UmhRestoreButton == (HWND)lParam)
|
|
UmhRestoreFunction();
|
|
else if (wh.UmhLoadButton == (HWND)lParam)
|
|
UmhLoadDll();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case WM_NOTIFY:
|
|
{
|
|
NMLVDISPINFO* plvdi;
|
|
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case LVN_GETDISPINFO:
|
|
{
|
|
plvdi = (NMLVDISPINFO*)lParam;
|
|
|
|
int ModuleIndex = HIWORD(plvdi->item.lParam);
|
|
int FunctionIndex = LOWORD(plvdi->item.lParam);
|
|
PLOADED_MODULE lm = wd.UmhModules.at(ModuleIndex);
|
|
PHOOKED_FUNCTION hf = lm->HookedFunctions.at(FunctionIndex);
|
|
|
|
LPWSTR Ordinal = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(Ordinal, MAX_PATH, L"%d", hf->Ordinal);
|
|
LPWSTR Address = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(Address, MAX_PATH, L"0x%p", (ULONG64)hf->Address);
|
|
|
|
switch (plvdi->item.iSubItem)
|
|
{
|
|
case 0:
|
|
plvdi->item.pszText = (LPWSTR)lm->Path;
|
|
break;
|
|
case 1:
|
|
plvdi->item.pszText = (LPWSTR)hf->Name;
|
|
break;
|
|
case 2:
|
|
plvdi->item.pszText = Ordinal;
|
|
break;
|
|
case 3:
|
|
plvdi->item.pszText = Address;
|
|
break;
|
|
default:
|
|
plvdi->item.pszText = (LPWSTR)L"N/A";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
ListView_SortItems(wh.UmhListView, UmhCompareFunc, pnmv->iSubItem);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Function: UmeWndProc
|
|
// Description: Processes messages for the ETW sessions tab.
|
|
LRESULT CALLBACK UmeWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_COMMAND:
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case BN_CLICKED:
|
|
{
|
|
if (wh.UmeRefreshButton == (HWND)lParam)
|
|
UmeLoadResults();
|
|
else if (wh.UmeDisableButton == (HWND)lParam)
|
|
UmeDisableSelectedProvider();
|
|
else if (wh.UmeStopButton == (HWND)lParam)
|
|
UmeStopTracingSession();
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case WM_NOTIFY:
|
|
{
|
|
NMLVDISPINFO* plvdi;
|
|
|
|
switch (((LPNMHDR)lParam)->code)
|
|
{
|
|
case LVN_GETDISPINFO:
|
|
{
|
|
plvdi = (NMLVDISPINFO*)lParam;
|
|
|
|
int SessionIndex = HIWORD(plvdi->item.lParam);
|
|
int ProviderIndex = LOWORD(plvdi->item.lParam);
|
|
PTRACING_SESSION ts = wd.UmeSessions.at(SessionIndex);
|
|
PTRACE_PROVIDER tp = ts->EnabledProviders.at(ProviderIndex);
|
|
|
|
switch (plvdi->item.iSubItem)
|
|
{
|
|
case 0:
|
|
plvdi->item.pszText = (LPWSTR)ts->InstanceName;
|
|
break;
|
|
case 1:
|
|
plvdi->item.pszText = (LPWSTR)tp->ProviderName;
|
|
break;
|
|
case 2:
|
|
plvdi->item.pszText = (ts->Notable || tp->Notable) ? (LPWSTR)L"Yes" : (LPWSTR)L"No";
|
|
break;
|
|
default:
|
|
plvdi->item.pszText = (LPWSTR)L"N/A";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case NM_CUSTOMDRAW:
|
|
{
|
|
LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;
|
|
|
|
BOOL IsNotable = FALSE;
|
|
int SessionIndex = HIWORD(lplvcd->nmcd.lItemlParam);
|
|
int ProviderIndex = LOWORD(lplvcd->nmcd.lItemlParam);
|
|
|
|
if (wd.UmeSessions.size())
|
|
{
|
|
PTRACING_SESSION ts = wd.UmeSessions.at(SessionIndex);
|
|
|
|
if (ts->Notable)
|
|
IsNotable = TRUE;
|
|
else if (ts->EnabledProviders.size())
|
|
IsNotable = ts->EnabledProviders.at(ProviderIndex)->Notable;
|
|
}
|
|
|
|
switch (lplvcd->nmcd.dwDrawStage)
|
|
{
|
|
case CDDS_PREPAINT:
|
|
return CDRF_NOTIFYITEMDRAW;
|
|
case CDDS_ITEMPREPAINT:
|
|
{
|
|
if (IsNotable)
|
|
{
|
|
lplvcd->clrText = RGB(0, 0, 0);
|
|
lplvcd->clrTextBk = RGB(255, 255, 200);
|
|
}
|
|
else
|
|
{
|
|
lplvcd->clrText = RGB(0, 0, 0);
|
|
lplvcd->clrTextBk = RGB(255, 255, 255);
|
|
}
|
|
return CDRF_NEWFONT;
|
|
}
|
|
case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
|
|
return CDRF_NEWFONT;
|
|
}
|
|
break;
|
|
}
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
ListView_SortItems(wh.UmeListView, UmeCompareFunc, pnmv->iSubItem);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return DefWindowProc(hWnd, message, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// Function: PaintWindow
|
|
// Description: Paints the main window.
|
|
// Called from: MainWndProc
|
|
VOID PaintWindow(HWND hWnd)
|
|
{
|
|
// Get global instance.
|
|
g_hInst = (HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE);
|
|
|
|
// Get bounding box for window.
|
|
RECT rcMain;
|
|
GetClientRect(hWnd, &rcMain);
|
|
|
|
// Set font to default GUI font.
|
|
LOGFONT lf;
|
|
GetObject(GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf);
|
|
HFONT hFont = CreateFont(
|
|
lf.lfHeight, lf.lfWidth,
|
|
lf.lfEscapement, lf.lfOrientation, lf.lfWeight,
|
|
lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut,
|
|
lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
|
|
lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName);
|
|
SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
// Begin painting.
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hWnd, &ps);
|
|
|
|
// Status bar.
|
|
wh.StatusBar = CreateWindowEx(
|
|
NULL, // no extended styles
|
|
STATUSCLASSNAME, // name of status bar class
|
|
(PCTSTR)NULL, // no text when first created
|
|
WS_CHILD | WS_VISIBLE, // creates a visible child window
|
|
0, 0, 0, 0, // ignores size and position
|
|
hWnd, // handle to parent window
|
|
(HMENU)0, // child window identifier
|
|
g_hInst, // handle to application instance
|
|
NULL); // no window creation data
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Ready");
|
|
|
|
// Tab control.
|
|
wh.TabControl = CreateWindowEx(
|
|
NULL, // Extended styles
|
|
WC_TABCONTROL, // Predefined class; Unicode assumed
|
|
L"", // Control text
|
|
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE, // Styles
|
|
0, // X position
|
|
0, // Y position
|
|
rcMain.right, // Control width
|
|
rcMain.bottom - 22, // Control height
|
|
hWnd, // Parent window
|
|
NULL, // No menu.
|
|
g_hInst, // Global instance handle
|
|
NULL); // Pointer not needed
|
|
SendMessage(wh.TabControl, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
/**
|
|
* Kernel-mode Callbacks
|
|
*/
|
|
|
|
TCITEM tie;
|
|
tie.mask = TCIF_TEXT;
|
|
tie.pszText = (LPWSTR)L"Kernel-mode Callbacks";
|
|
TabCtrl_InsertItem(wh.TabControl, 0, &tie);
|
|
wh.KmcPage = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE,
|
|
0,
|
|
25,
|
|
rcMain.right - 5,
|
|
rcMain.bottom - 55,
|
|
wh.TabControl,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SetWindowLongPtr(wh.KmcPage, GWLP_WNDPROC, (LONG_PTR)KmcWndProc);
|
|
|
|
wh.KmcRefreshButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Refresh Results",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
5,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.KmcPage,
|
|
(HMENU)1,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.KmcRefreshButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.KmcSuppressButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Suppress Callback",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
110,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.KmcPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.KmcSuppressButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.KmcRevertButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Revert Callback",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
215,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.KmcPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.KmcRevertButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.KmcCountLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Count: 0 callbacks.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
5,
|
|
350,
|
|
15,
|
|
wh.KmcPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.KmcCountLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.KmcTipLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Tip: No results? Run elevated to load the driver.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
20,
|
|
250,
|
|
15,
|
|
wh.KmcPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.KmcTipLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.KmcListView = CreateWindowEx(
|
|
NULL,
|
|
WC_LISTVIEW,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_SINGLESEL,
|
|
5,
|
|
40,
|
|
rcMain.right - 15,
|
|
rcMain.bottom - 100,
|
|
wh.KmcPage,
|
|
(HMENU)0,
|
|
g_hInst,
|
|
NULL);
|
|
ListView_SetExtendedListViewStyle(wh.KmcListView, LVS_EX_FULLROWSELECT);
|
|
|
|
LVCOLUMN lvc = { 0 };
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
|
|
lvc.iSubItem = 0;
|
|
lvc.pszText = (LPWSTR)L"Collection Type";
|
|
lvc.cx = 150;
|
|
ListView_InsertColumn(wh.KmcListView, 0, &lvc);
|
|
|
|
lvc.iSubItem = 1;
|
|
lvc.pszText = (LPWSTR)L"Callback Type";
|
|
lvc.cx = 300;
|
|
ListView_InsertColumn(wh.KmcListView, 1, &lvc);
|
|
|
|
lvc.iSubItem = 2;
|
|
lvc.pszText = (LPWSTR)L"Module";
|
|
lvc.cx = 200;
|
|
ListView_InsertColumn(wh.KmcListView, 2, &lvc);
|
|
|
|
lvc.iSubItem = 3;
|
|
lvc.pszText = (LPWSTR)L"Is Suppressed?";
|
|
lvc.cx = 100;
|
|
ListView_InsertColumn(wh.KmcListView, 3, &lvc);
|
|
|
|
lvc.iSubItem = 4;
|
|
lvc.pszText = (LPWSTR)L"Is Notable?";
|
|
lvc.cx = 100;
|
|
ListView_InsertColumn(wh.KmcListView, 4, &lvc);
|
|
|
|
/**
|
|
* User-mode Hooks
|
|
*/
|
|
|
|
tie.pszText = (LPWSTR)L"User-mode Hooks";
|
|
TabCtrl_InsertItem(wh.TabControl, 1, &tie);
|
|
wh.UmhPage = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE,
|
|
0,
|
|
25,
|
|
rcMain.right - 5,
|
|
rcMain.bottom - 55,
|
|
wh.TabControl,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SetWindowLongPtr(wh.UmhPage, GWLP_WNDPROC, (LONG_PTR)UmhWndProc);
|
|
|
|
wh.UmhRefreshButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Refresh Results",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
5,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmhPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmhRefreshButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmhRestoreButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Restore Function",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
110,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmhPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmhRestoreButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmhLoadButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Load Testing DLL",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
215,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmhPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmhLoadButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmhCountLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Count: 0 hooked functions.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
5,
|
|
350,
|
|
15,
|
|
wh.UmhPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmhCountLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmhTipLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Tip: Validate unhooking by loading a test DLL.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
20,
|
|
250,
|
|
15,
|
|
wh.UmhPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmhTipLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmhListView = CreateWindowEx(
|
|
NULL,
|
|
WC_LISTVIEW,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_SINGLESEL,
|
|
5,
|
|
40,
|
|
rcMain.right - 15,
|
|
rcMain.bottom - 100,
|
|
wh.UmhPage,
|
|
(HMENU)0,
|
|
g_hInst,
|
|
NULL);
|
|
ListView_SetExtendedListViewStyle(wh.UmhListView, LVS_EX_FULLROWSELECT);
|
|
|
|
lvc.iSubItem = 0;
|
|
lvc.pszText = (LPWSTR)L"Module";
|
|
lvc.cx = 250;
|
|
ListView_InsertColumn(wh.UmhListView, 0, &lvc);
|
|
|
|
lvc.iSubItem = 1;
|
|
lvc.pszText = (LPWSTR)L"Function Name";
|
|
lvc.cx = 300;
|
|
ListView_InsertColumn(wh.UmhListView, 1, &lvc);
|
|
|
|
lvc.iSubItem = 2;
|
|
lvc.pszText = (LPWSTR)L"Ordinal";
|
|
lvc.cx = 100;
|
|
ListView_InsertColumn(wh.UmhListView, 2, &lvc);
|
|
|
|
lvc.iSubItem = 3;
|
|
lvc.pszText = (LPWSTR)L"Virtual Address";
|
|
lvc.cx = 200;
|
|
ListView_InsertColumn(wh.UmhListView, 3, &lvc);
|
|
|
|
/**
|
|
* ETW Trace Sessions
|
|
*/
|
|
|
|
tie.pszText = (LPWSTR)L"ETW Trace Sessions";
|
|
TabCtrl_InsertItem(wh.TabControl, 2, &tie);
|
|
wh.UmePage = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE,
|
|
0,
|
|
25,
|
|
rcMain.right - 5,
|
|
rcMain.bottom - 55,
|
|
wh.TabControl,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SetWindowLongPtr(wh.UmePage, GWLP_WNDPROC, (LONG_PTR)UmeWndProc);
|
|
|
|
wh.UmeRefreshButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Refresh Results",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
5,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmePage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmeRefreshButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmeDisableButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Disable Provider",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
110,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmePage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmeDisableButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmeStopButton = CreateWindowEx(
|
|
NULL,
|
|
L"BUTTON",
|
|
L"Stop Session",
|
|
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
|
|
215,
|
|
5,
|
|
100,
|
|
30,
|
|
wh.UmePage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmeStopButton, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmeCountLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Count: 0 sessions.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
5,
|
|
350,
|
|
15,
|
|
wh.UmePage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmeCountLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmeTipLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Tip: Missing results? Run as SYSTEM to view more sessions.",
|
|
WS_CHILD | WS_VISIBLE,
|
|
320,
|
|
20,
|
|
300,
|
|
15,
|
|
wh.UmePage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.UmeTipLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
wh.UmeListView = CreateWindowEx(
|
|
NULL,
|
|
WC_LISTVIEW,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_SINGLESEL,
|
|
5,
|
|
40,
|
|
rcMain.right - 15,
|
|
rcMain.bottom - 100,
|
|
wh.UmePage,
|
|
(HMENU)0,
|
|
g_hInst,
|
|
NULL);
|
|
ListView_SetExtendedListViewStyle(wh.UmeListView, LVS_EX_FULLROWSELECT);
|
|
|
|
lvc.iSubItem = 0;
|
|
lvc.pszText = (LPWSTR)L"Session";
|
|
lvc.cx = 300;
|
|
ListView_InsertColumn(wh.UmeListView, 0, &lvc);
|
|
|
|
lvc.iSubItem = 1;
|
|
lvc.pszText = (LPWSTR)L"Enabled Provider";
|
|
lvc.cx = 300;
|
|
ListView_InsertColumn(wh.UmeListView, 1, &lvc);
|
|
|
|
lvc.iSubItem = 2;
|
|
lvc.pszText = (LPWSTR)L"Is Notable?";
|
|
lvc.cx = 100;
|
|
ListView_InsertColumn(wh.UmeListView, 2, &lvc);
|
|
|
|
/**
|
|
* About Page
|
|
*/
|
|
|
|
tie.pszText = (LPWSTR)L"About";
|
|
TabCtrl_InsertItem(wh.TabControl, 3, &tie);
|
|
wh.AbtPage = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"",
|
|
WS_CHILD | WS_VISIBLE, // | WS_BORDER,
|
|
0,
|
|
25,
|
|
rcMain.right - 5,
|
|
rcMain.bottom - 55,
|
|
wh.TabControl,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
|
|
wh.AbtLabel = CreateWindowEx(
|
|
NULL,
|
|
WC_STATIC,
|
|
L"Telemetry Sourcerer is a utility that can be used to enumerate "
|
|
L"and disable common sources of events used by endpoint security "
|
|
L"products (AV/EDR).\n\n"
|
|
L"Developed by @Jackson_T (2020), leveraging code from @gentilkiwi, "
|
|
L"@fdiskyou, and @0x00dtm. Licenced under the Apache License v2.0.\n\n"
|
|
L"Use of this tool is intended for research purposes only and does "
|
|
L"not attempt to be OPSEC-safe.\n\n"
|
|
L"Code: github.com/jthuraisamy/TelemetrySourcerer\n"
|
|
L"Methodology: jackson-t.ca/edr-reversing-evading-01.html\n",
|
|
WS_CHILD | WS_VISIBLE | SS_CENTER,
|
|
5,
|
|
150,
|
|
rcMain.right - 10,
|
|
rcMain.bottom - 60,
|
|
wh.AbtPage,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
SendMessage(wh.AbtLabel, WM_SETFONT, (WPARAM)hFont, TRUE);
|
|
|
|
// END PAINTING
|
|
ShowWindow(wh.UmhPage, SW_HIDE);
|
|
ShowWindow(wh.UmePage, SW_HIDE);
|
|
ShowWindow(wh.AbtPage, SW_HIDE);
|
|
ShowWindow(wh.KmcPage, SW_HIDE);
|
|
EndPaint(hWnd, &ps);
|
|
}
|
|
|
|
// Function: ResizeWindow
|
|
// Description: Handles window resizes (currently not supported).
|
|
// Called from: MainWndProc
|
|
VOID ResizeWindow(HWND hWnd)
|
|
{
|
|
RECT rcClient;
|
|
GetClientRect(hWnd, &rcClient);
|
|
|
|
SetWindowPos(wh.TabControl, HWND_TOP, 0, 0, rcClient.right, rcClient.bottom - 22, SWP_SHOWWINDOW);
|
|
SetWindowPos(wh.KmcPage, HWND_TOP, 0, 25, rcClient.right - 5, rcClient.bottom - 40, SWP_SHOWWINDOW);
|
|
SetWindowPos(wh.StatusBar, NULL, 0, rcClient.bottom - 10, rcClient.right, 10, SWP_NOZORDER);
|
|
}
|
|
|
|
// Function: KmcLoadResults
|
|
// Description: Loads kernel-mode callback results.
|
|
// Called from: MainWndProc after painting, and KmcWndProc when clicking the refresh button.
|
|
VOID KmcLoadResults()
|
|
{
|
|
DWORD DriverStatus = LoadDriver();
|
|
switch (DriverStatus)
|
|
{
|
|
case ERROR_FILE_NOT_FOUND:
|
|
MessageBox(
|
|
NULL,
|
|
L"Could not find TelemetrySourcererDriver.sys.\n\n"
|
|
L"Please ensure it is in the same directory as the executable.",
|
|
TOOL_NAME,
|
|
MB_ICONERROR);
|
|
break;
|
|
case ERROR_INVALID_IMAGE_HASH:
|
|
MessageBox(
|
|
NULL,
|
|
L"The signature for the driver failed verification.\n\n"
|
|
L"To load kernel-mode callback results, either enable test signing, "
|
|
L"or sign this driver with a valid certificate.",
|
|
TOOL_NAME,
|
|
MB_ICONERROR);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Loading kernel-mode callbacks...");
|
|
|
|
// Delete rows and fetch latest results.
|
|
ListView_DeleteAllItems(wh.KmcListView);
|
|
wd.KmcCallbacks = GetCallbacks(wd.KmcCallbacks);
|
|
DWORD ListItemCount = 0;
|
|
|
|
for (int CallbackIndex = 0; CallbackIndex < wd.KmcCallbacks.size(); CallbackIndex++)
|
|
{
|
|
|
|
LVITEM lvi = { 0 };
|
|
lvi.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
|
|
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
|
|
lvi.stateMask = 0;
|
|
lvi.iSubItem = 0;
|
|
lvi.state = 0;
|
|
lvi.iItem = ListItemCount++;
|
|
lvi.lParam = CallbackIndex;
|
|
|
|
ListView_InsertItem(wh.KmcListView, &lvi);
|
|
}
|
|
|
|
LPWSTR CountText = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(CountText, MAX_PATH, L"Count: %d callbacks.", wd.KmcCallbacks.size());
|
|
Static_SetText(wh.KmcCountLabel, CountText);
|
|
|
|
// Default sort by notable items.
|
|
ListView_SortItems(wh.KmcListView, KmcCompareFunc, 4);
|
|
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Ready");
|
|
}
|
|
|
|
// Function: KmcCompareFunc
|
|
// Description: Sorts the kernel-mode callbacks list view depending on the column.
|
|
// Called from: KmcWndProc when clicking a column header of the callbacks list view.
|
|
int CALLBACK KmcCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int nRetVal = 0;
|
|
|
|
PCALLBACK_ENTRY Item1Callback = wd.KmcCallbacks.at(lParam1);
|
|
PCALLBACK_ENTRY Item2Callback = wd.KmcCallbacks.at(lParam2);
|
|
|
|
switch (lParamSort)
|
|
{
|
|
case 0: // Collection Type
|
|
case 1: // Callback Type
|
|
if (Item1Callback->Type > Item2Callback->Type)
|
|
nRetVal = 1;
|
|
else if (Item1Callback->Type < Item2Callback->Type)
|
|
nRetVal = -1;
|
|
else
|
|
nRetVal = 0;
|
|
break;
|
|
|
|
case 2: // Module
|
|
nRetVal = wcscmp(Item1Callback->ModuleName, Item2Callback->ModuleName);
|
|
break;
|
|
|
|
case 3: // Is Suppressed?
|
|
nRetVal = (Item1Callback->Suppressed == Item2Callback->Suppressed) ? 0 : (Item1Callback->Suppressed) ? -1 : (Item2Callback->Suppressed) ? 1 : 0;
|
|
break;
|
|
|
|
case 4: // Is Notable?
|
|
nRetVal = (Item1Callback->Notable == Item2Callback->Notable) ? 0 : (Item1Callback->Notable) ? -1 : (Item2Callback->Notable) ? 1 : 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return nRetVal;
|
|
}
|
|
|
|
// Function: KmcSuppressCallback
|
|
// Description: Suppresses the selected callback (if eligible).
|
|
// Called from: KmcWndProc when clicking the suppress button.
|
|
VOID KmcSuppressCallback()
|
|
{
|
|
int SelectedIndex = ListView_GetNextItem(wh.KmcListView, -1, LVNI_SELECTED);
|
|
|
|
if (SelectedIndex != -1)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = SelectedIndex;
|
|
lvi.iSubItem = 0;
|
|
ListView_GetItem(wh.KmcListView, &lvi);
|
|
|
|
PCALLBACK_ENTRY Callback = wd.KmcCallbacks.at(lvi.lParam);
|
|
WCHAR MessageTitle[MAX_PATH] = { 0 };
|
|
StringCbPrintfW(MessageTitle, MAX_PATH, L"%ls + 0x%x", Callback->ModuleName, Callback->ModuleOffset);
|
|
|
|
if (SuppressCallback(Callback))
|
|
{
|
|
Callback->Suppressed = TRUE;
|
|
MessageBox(NULL, L"Successfully suppressed callback!", MessageTitle, MB_OK | MB_ICONINFORMATION);
|
|
KmcLoadResults();
|
|
ListView_EnsureVisible(wh.KmcListView, SelectedIndex, FALSE);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(NULL, L"Callback could not be suppressed for unspecified reason.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function: KmcRevertCallback
|
|
// Description: Reverts the selected callback (if suppressed/eligible).
|
|
// Called from: KmcWndProc when clicking the revert button.
|
|
VOID KmcRevertCallback()
|
|
{
|
|
int SelectedIndex = ListView_GetNextItem(wh.KmcListView, -1, LVNI_SELECTED);
|
|
|
|
if (SelectedIndex != -1)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = SelectedIndex;
|
|
lvi.iSubItem = 0;
|
|
ListView_GetItem(wh.KmcListView, &lvi);
|
|
|
|
PCALLBACK_ENTRY Callback = wd.KmcCallbacks.at(lvi.lParam);
|
|
WCHAR MessageTitle[MAX_PATH] = { 0 };
|
|
StringCbPrintfW(MessageTitle, MAX_PATH, L"%ls + 0x%x", &Callback->ModuleName, Callback->ModuleOffset);
|
|
|
|
if (Callback->Suppressed)
|
|
{
|
|
if (Callback->OriginalQword == GetSuppressionValue(Callback->Type))
|
|
{
|
|
MessageBox(NULL, L"The callback could not be reverted because the function's original first bytes are unknown.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
else if (RevertCallback(Callback))
|
|
{
|
|
Callback->Suppressed = FALSE;
|
|
MessageBox(NULL, L"Successfully reverted callback!", MessageTitle, MB_OK | MB_ICONINFORMATION);
|
|
KmcLoadResults();
|
|
ListView_EnsureVisible(wh.KmcListView, SelectedIndex, FALSE);
|
|
}
|
|
else
|
|
{
|
|
MessageBox(NULL, L"Callback could not be reverted for unspecified reason.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox(NULL, L"The selected callback is currently not suppressed.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Function: UmhLoadResults
|
|
// Description: Loads user-mode inline hook results.
|
|
// Called from: MainWndProc after painting, and UmhWndProc when clicking the refresh button.
|
|
VOID UmhLoadResults()
|
|
{
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Loading user-mode hooks...");
|
|
|
|
// Delete rows and fetch latest results.
|
|
ListView_DeleteAllItems(wh.UmhListView);
|
|
wd.UmhModules = CheckAllModulesForHooks();
|
|
DWORD ListItemCount = 0;
|
|
|
|
for (int ModuleIndex = 0; ModuleIndex < wd.UmhModules.size(); ModuleIndex++)
|
|
{
|
|
PLOADED_MODULE lm = wd.UmhModules.at(ModuleIndex);
|
|
|
|
for (int FunctionIndex = 0; FunctionIndex < lm->HookedFunctions.size(); FunctionIndex++)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
|
|
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
|
|
lvi.stateMask = 0;
|
|
lvi.iSubItem = 0;
|
|
lvi.state = 0;
|
|
lvi.iItem = ListItemCount++;
|
|
lvi.lParam = (ModuleIndex << 16) | FunctionIndex;
|
|
|
|
ListView_InsertItem(wh.UmhListView, &lvi);
|
|
}
|
|
}
|
|
|
|
LPWSTR CountText = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(CountText, MAX_PATH, L"Count: %d hooked functions.", ListItemCount);
|
|
Static_SetText(wh.UmhCountLabel, CountText);
|
|
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Ready");
|
|
}
|
|
|
|
// Function: UmhCompareFunc
|
|
// Description: Sorts the hooked function list view depending on the column.
|
|
// Called from: UmhWndProc when clicking a column header of the hooked function list view.
|
|
int CALLBACK UmhCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int nRetVal = 0;
|
|
|
|
PLOADED_MODULE Item1Module = wd.UmhModules.at(HIWORD(lParam1));
|
|
PLOADED_MODULE Item2Module = wd.UmhModules.at(HIWORD(lParam2));
|
|
PHOOKED_FUNCTION Item1Function = Item1Module->HookedFunctions.at(LOWORD(lParam1));
|
|
PHOOKED_FUNCTION Item2Function = Item2Module->HookedFunctions.at(LOWORD(lParam2));
|
|
|
|
switch (lParamSort)
|
|
{
|
|
case 0: // Module
|
|
nRetVal = wcscmp(Item1Module->Path, Item2Module->Path);
|
|
break;
|
|
|
|
case 1: // Function Name
|
|
nRetVal = wcscmp(Item1Function->Name, Item2Function->Name);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return nRetVal;
|
|
}
|
|
|
|
// Function: UmhRestoreFunction
|
|
// Description: Unhooks the selected function.
|
|
// Called from: UmhWndProc when clicking the restore button.
|
|
VOID UmhRestoreFunction()
|
|
{
|
|
int SelectedIndex = ListView_GetNextItem(wh.UmhListView, -1, LVNI_SELECTED);
|
|
|
|
if (SelectedIndex != -1)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = SelectedIndex;
|
|
lvi.iSubItem = 0;
|
|
ListView_GetItem(wh.UmhListView, &lvi);
|
|
|
|
int ModuleIndex = HIWORD(lvi.lParam);
|
|
int FunctionIndex = LOWORD(lvi.lParam);
|
|
|
|
PLOADED_MODULE Module = wd.UmhModules.at(ModuleIndex);
|
|
PHOOKED_FUNCTION Function = Module->HookedFunctions.at(FunctionIndex);
|
|
|
|
WCHAR MessageTitle[MAX_PATH] = { 0 };
|
|
StringCbPrintfW(MessageTitle, MAX_PATH, L"%ls: %ls", Module->Path, Function->Name);
|
|
if (RestoreHookedFunction(Function))
|
|
MessageBox(NULL, L"Successfully unhooked function!", MessageTitle, MB_OK | MB_ICONINFORMATION);
|
|
else
|
|
MessageBox(NULL, L"Function could not be unhooked for unspecified reason.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
|
|
UmhLoadResults();
|
|
ListView_EnsureVisible(wh.UmhListView, SelectedIndex, FALSE);
|
|
}
|
|
}
|
|
|
|
// Function: UmhLoadDll
|
|
// Description: Loads a testing DLL to validate unhooking efficacy.
|
|
// Called from: UmhWndProc when clicking the load DLL button.
|
|
VOID UmhLoadDll()
|
|
{
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Loading test DLL...");
|
|
|
|
WCHAR DllPath[MAX_PATH] = { 0 };
|
|
OPENFILENAMEW OpenFileName = { 0 };
|
|
OpenFileName.lStructSize = sizeof(OpenFileName);
|
|
OpenFileName.hwndOwner = wh.Main;
|
|
OpenFileName.lpstrFilter = L"DLL Files (*.dll)\0*.DLL\0";
|
|
OpenFileName.lpstrFile = DllPath;
|
|
OpenFileName.nMaxFile = MAX_PATH;
|
|
|
|
GetOpenFileNameW(&OpenFileName);
|
|
LoadLibraryW(DllPath); // ToDo validation.
|
|
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Ready");
|
|
}
|
|
|
|
// Function: UmeLoadResults
|
|
// Description: Load ETW trace session results.
|
|
// Called from: MainWndProc after painting, and UmeWndProc when clicking the refresh button.
|
|
VOID UmeLoadResults()
|
|
{
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Loading ETW sessions...");
|
|
|
|
// Delete rows and fetch latest results.
|
|
ListView_DeleteAllItems(wh.UmeListView);
|
|
wd.UmeSessions = GetSessions();
|
|
DWORD ListItemCount = 0;
|
|
|
|
for (int SessionIndex = 0; SessionIndex < wd.UmeSessions.size(); SessionIndex++)
|
|
{
|
|
PTRACING_SESSION ts = wd.UmeSessions.at(SessionIndex);
|
|
|
|
for (int ProviderIndex = 0; ProviderIndex < ts->EnabledProviders.size(); ProviderIndex++)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.pszText = LPSTR_TEXTCALLBACK; // Sends an LVN_GETDISPINFO message.
|
|
lvi.mask = LVIF_TEXT | LVIF_STATE | LVIF_PARAM;
|
|
lvi.stateMask = 0;
|
|
lvi.iSubItem = 0;
|
|
lvi.state = 0;
|
|
lvi.iItem = ListItemCount++;
|
|
lvi.lParam = ((ULONG)SessionIndex << 16) | ProviderIndex;
|
|
|
|
ListView_InsertItem(wh.UmeListView, &lvi);
|
|
}
|
|
}
|
|
|
|
LPWSTR CountText = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_PATH);
|
|
StringCbPrintfW(CountText, MAX_PATH, L"Count: %d sessions.", wd.UmeSessions.size());
|
|
Static_SetText(wh.UmeCountLabel, CountText);
|
|
|
|
// Default sort by notable items.
|
|
ListView_SortItems(wh.UmeListView, UmeCompareFunc, 2);
|
|
|
|
SendMessage(wh.StatusBar, SB_SETTEXT, (WPARAM)0, (LPARAM)L"Ready");
|
|
}
|
|
|
|
// Function: UmeCompareFunc
|
|
// Description: Sorts the ETW list view depending on the column.
|
|
// Called from: UmeWndProc when clicking a column header of the ETW list view.
|
|
int CALLBACK UmeCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
int nRetVal = 0;
|
|
|
|
PTRACING_SESSION Item1Session = wd.UmeSessions.at(HIWORD(lParam1));
|
|
PTRACING_SESSION Item2Session = wd.UmeSessions.at(HIWORD(lParam2));
|
|
PTRACE_PROVIDER Item1Provider = Item1Session->EnabledProviders.at(LOWORD(lParam1));
|
|
PTRACE_PROVIDER Item2Provider = Item2Session->EnabledProviders.at(LOWORD(lParam2));
|
|
BOOL Item1Notable = FALSE;
|
|
BOOL Item2Notable = FALSE;
|
|
|
|
switch (lParamSort)
|
|
{
|
|
case 0: // Session
|
|
nRetVal = wcscmp(Item1Session->InstanceName, Item2Session->InstanceName);
|
|
break;
|
|
|
|
case 1: // Provider Name
|
|
nRetVal = wcscmp(Item1Provider->ProviderName, Item2Provider->ProviderName);
|
|
break;
|
|
|
|
case 2: // Is Notable?
|
|
Item1Notable = Item1Session->Notable || Item1Provider->Notable;
|
|
Item2Notable = Item2Session->Notable || Item2Provider->Notable;
|
|
nRetVal = (Item1Notable == Item2Notable) ? 0 : (Item1Notable) ? -1 : (Item2Notable) ? 1 : 0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return nRetVal;
|
|
}
|
|
|
|
// Function: UmeDisableSelectedProvider
|
|
// Description: Disables the selected provider for the session (if eligible).
|
|
// Called from: UmeWndProc when clicking the disable provider button.
|
|
VOID UmeDisableSelectedProvider()
|
|
{
|
|
int SelectedIndex = ListView_GetNextItem(wh.UmeListView, -1, LVNI_SELECTED);
|
|
|
|
if (SelectedIndex != -1)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = SelectedIndex;
|
|
lvi.iSubItem = 0;
|
|
ListView_GetItem(wh.UmeListView, &lvi);
|
|
|
|
int SessionIndex = HIWORD(lvi.lParam);
|
|
int ProviderIndex = LOWORD(lvi.lParam);
|
|
|
|
PTRACING_SESSION Session = wd.UmeSessions.at(SessionIndex);
|
|
PTRACE_PROVIDER Provider = Session->EnabledProviders.at(ProviderIndex);
|
|
|
|
WCHAR MessageTitle[MAX_PATH] = { 0 };
|
|
StringCbPrintfW(MessageTitle, MAX_PATH, L"%ls: %ls", Session->InstanceName, Provider->ProviderName);
|
|
DWORD Status = DisableProvider(Session->LoggerId, &Provider->ProviderId);
|
|
switch (Status)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
MessageBox(NULL, L"Successfully disabled provider!", MessageTitle, MB_OK | MB_ICONINFORMATION);
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
MessageBox(NULL, L"Denied. Administrative privileges required.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
break;
|
|
default:
|
|
MessageBox(NULL, L"Provider could not be disabled for unspecified reason.", MessageTitle, MB_OK | MB_ICONERROR);
|
|
break;
|
|
}
|
|
|
|
UmeLoadResults();
|
|
ListView_EnsureVisible(wh.UmeListView, SelectedIndex, FALSE);
|
|
}
|
|
}
|
|
|
|
// Function: UmeDisableSelectedProvider
|
|
// Description: Stops the selected session (if eligible).
|
|
// Called from: UmeWndProc when clicking the stop session button.
|
|
VOID UmeStopTracingSession()
|
|
{
|
|
int SelectedIndex = ListView_GetNextItem(wh.UmeListView, -1, LVNI_SELECTED);
|
|
|
|
if (SelectedIndex != -1)
|
|
{
|
|
LVITEM lvi = { 0 };
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = SelectedIndex;
|
|
lvi.iSubItem = 0;
|
|
ListView_GetItem(wh.UmeListView, &lvi);
|
|
|
|
int SessionIndex = HIWORD(lvi.lParam);
|
|
int ProviderIndex = LOWORD(lvi.lParam);
|
|
|
|
PTRACING_SESSION Session = wd.UmeSessions.at(SessionIndex);
|
|
PTRACE_PROVIDER Provider = Session->EnabledProviders.at(ProviderIndex);
|
|
|
|
DWORD Status = StopTracingSession(Session->LoggerId);
|
|
switch (Status)
|
|
{
|
|
case ERROR_SUCCESS:
|
|
MessageBox(NULL, L"Successfully stopped tracing session!", Session->InstanceName, MB_OK | MB_ICONINFORMATION);
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
MessageBox(NULL, L"Denied. Administrative privileges required.", Session->InstanceName, MB_OK | MB_ICONERROR);
|
|
break;
|
|
default:
|
|
MessageBox(NULL, L"Session could not be stopped for unspecified reason.", Session->InstanceName, MB_OK | MB_ICONERROR);
|
|
break;
|
|
}
|
|
|
|
UmeLoadResults();
|
|
ListView_EnsureVisible(wh.UmeListView, SelectedIndex, FALSE);
|
|
}
|
|
} |