About Me •Nafiez (@zeifan) • HITB CTF Core Crew (3rd Generation, after Spoonfork & RuFI0) • Passionate in Memory Corruption • Windows Internal Fan • As long as not related to Web Hacking ☺ (allergic!)
Source: http://i-web.i.u-tokyo.ac.jp/edu/training/ss/lecture/new-documents/Lectures/17-Win32K/Win32K.pdf 1. Windows Sub-system 2. GUI infra (architecture) of the OS 3. Core Kernel a) > 950 syscalls (up to Windows 10) 4. Complex System ☺ a) Callback in Kernel Mode b) Font Parsing 5. Including: a) Windows Manager (USER) b) Graphics Device Interface (GDI) c) DirectX
Reverse Engineering •Fresh installed of Windows • Windows XP, Windows 7, Windows 8, 8.1, Windows 10 (started early this year only!) •Reversing core kernel win32k.sys • BinDiffing + IDA Pro, a little help from WinDBG (symbols FTW!) • 2 – 3 months • Manual finding > 20+ bugs (5 vulnerabilities, 2 still unfix bug, rest are DoS / non-security related) • Patch Tuesday •Move to Fuzzing
Dumb Fuzzing • Required small amount of work to produce (Lazy Way) • Complexity of the module • Unknown functions, symbols, etc. • Things are getting harder and harder (Patch Tuesday) • Gambling with kernel • Call from User-mode to Kernel-Mode (e.g.: notepad.exe) • Single system calls • e.g.: NtUserGetDCEx • How-to-FAQ: • Menu structures • Callback • Handle • Etc.
Cont. •Callback functions •Scenario: 1) Creating kernel window 2) Get any pointer to the kernel window object 3) Overwrite WndProc pointer 4) Send message to window to trigger crash on WndProc (based on overwrite pointer)
Case Study 1: Kernel Integer Overflow •Target module: Coordinate Spaces & Transformations • Scale, Rotate, Translate, Graphics Output •Two different SysCalls shared the same vulnerability • ScaleViewportExtEx() • ScaleWindowExtEx() •Both function modifies the window for a device context using the ratios formed by the specified multiplicands and divisors. •Reported in 2013, someone found it few months before and reported. Lost track of the KB ☺
Cont. •There is no checking after dividing the value • It does not recognize the pattern of “Positive” or “Negative” numbers (Intel Manual explained in details) •Signed divide EDX:EAX by [ebp+Xdenom], with result stored as: • EAX = High-Level Address, EDX = Overflow. •Trivia • Sign of the remainder is always the same as the sign of the dividend. • The absolute value of the remainder is always less than the absolute value of the divisor. • Overflow is indicated with the #DE (divide error) exception rather than with the OF (overflow) flag.
Proof-of-Concept •The Maths • Putting all possible numbers • 0xFFFFFFFF, 0x80000000, etc. • Negative and Positive numbers • In Math, calculating “X” and “Y” axis should return any result, even remainder. • Regardless of negative or positive numbers • e.g.: 100, -1, 212, -12, 12.1 • Example equation: a = a / b * a % b •3 lines of C should be more than enough ☺
•1. Set SYSTIMER to 0x118 (WinSpy should be able to help) •2. Create new shape and assign ownership to specified window using CreateCaret() •3. Verify check by adding FlashWindow() function •4. The math: rand() % 0xFFFF
Cont. •Passed string and compare it • String passed when accessing pWnd->ppropList •Crash will trigger on GetProp() • The main idea is to passed string that will trigger memory corruption on function itself. •Lesson learned: • Remote Code execution != Local EOP • GetProp() does not handle any socket
•Relying on crash dumps •Re-code from Fuzzer •We need ACCESS_VIOLATION •Many exploitation tricks available • Writing exploit cost more time ☺ • I won’t explain any of it here • Token stealing, w-w-w, etc.
Flow of Exploitation •Some exploitation scenario: 1. Find the address of RegisterClassExWOWW 2. RegisterClassExWOWW() passing the FNID for a Menu and a WNDCLASSEX structure with a negative number for the extra bytes 3. CreateWindow() 4. SetWindowLongPtr() with a non-NULL array 5. DestroyWindow() 6. Find offset 7. Repeat steps 3-5, this time passing the actual address to overwrite minus the offset 8. Get the overwritten pointer to be called
Kernel Instrumentation •j00ru from Google Project Zero released instrumentation tool • Kfetch-Toolkit •Designed to perform advanced logging of memory references in Kernel level • Relying on Bochs IA-32 Emulator •Hard to setup • It took me one month to finish the project • Modifying few modules that do not work on the latest build of requirement tools.
Cont. •Capability • Monitor and logging performed by kernel-mode components • Post processing • Filtering • Separation •Upon installation, the BOCHS will boot up in between 10 – 12 hours. •Combining smart fuzzer with kfetch-toolkit • Target in Kernel Level: Anti-Virus, DirectX, Audio, Video, AFD.sys, etc. •Things are getting harder, time to move to smart way ☺
Guide to Smart Fuzzing 1. Constant base identifier for syscall 2. Specify maximum number of parameters target syscall can take 3. Number of syscalls on each supported platform 4. Reduce / Exclude service ID from fuzzing / being trigger 5. Fuzzing iteration used to detect hang threads 6. Algorithm to generate (RDTSC FTW) 7. Invoke each and every single syscall from win32k.sys
The Ideas •Deployed proper Kernel Fuzzer • Targeting specific driver such as win32k.sys •Run the Fuzzer in the BOCHS machine (Windows 7, etc.) • Let the instrumentation toolkit figure it out • More crash dump will be produced ☺ • Time consuming when move the mouse or even typing keyboard •You can always run public fuzzer • e.g.: Peach Fuzzer, IOCTLbf, etc.
BOCHS Emulator Windows 7 (BOCHS) Fuzzer win32k.sys Kernel-Mode Fuzzer Log ☺ Hardware Specs: • Core 2 Duo • 4GB RAM • 500GB HDD • Windows 7 Instrumentation Tool User-Mode Fuzzer Fuzzer executed Sending instruction executed after fuzzed Fuzzer deployed Emulator Installed on Windows 7 or 8 Windows 7 (Physical) Windows 7 used as target OS Log will be in Physical machine Sending crash log (crash dump) Logged every single instruction executed e.g.: callback, etc.