Exploiting a Windows 10 PagedPool off-by-one overflow (WCTF 2018)

During the weekend of 6-8th of July, our CTF team – Dragon Sector – played in an invite-only competition called WCTF, held in Beijing. The other participants were top-tier groups from around the world (e.g. Shellphish, ESPR, LC↯BC or Tokyo Westerns), and the prize pool of the contest was a stunning $100,000 USD. One particularly unique rule of the CTF was that the challenges were prepared by the teams themselves and not the organizers. Each of the 10 teams was obligated to provide two tasks, at least one of which had to run on Windows. This meant that each team could capture a maximum of 18 flags set up by the other teams in the room. In practice, the structure of the contest incentivized submitting extremely difficult and complex challenges. Remote help was allowed, and the scoring system offered first blood bonus points for being the first, second and third team to solve a task. The hacking part of the event was followed by a soft part, where additional points were granted by a jury and the participants for presenting one’s own tasks on stage.

After two days of though competition, we came out as the runner up of the CTF with 6/18 tasks solved, behind the winner – Tokyo Westerns (7/18 tasks):

Read more

Wrapping up the kernel infoleak research with a whitepaper

Following the previous post in June last year, I continued to actively work on Bochspwn Reloaded, a Bochs-based tool designed to detect leaks of uninitialized memory from kernels to the user address space. In addition to my talk at REcon Montreal 2017 (slides, video), I also gave similar presentations at Black Hat USA 2017 (slides, video) and a Polish event called Security PWNing Conference held in Warsaw (slides in Polish).

Since then, I improved and polished various parts of the instrumentation and testing environment, which led to new waves of Windows bugs being reported to Microsoft in several iterations throughout the year. The most significant advancements I made during this time are as follows:

  • Implemented support for x64 guest systems and used it to identify 17 new Windows bugs specific to the 64-bit platform.
  • Developed and evaluated a taint-less method of detecting leaks to mass storage devices, which helped find a number of bugs in the Windows NTFS.sys file system driver.
  • Implemented a test suite of programs to automatically test the NtQuery system call family on Windows, which uncovered new issues in a total of 14 syscalls across 23 different information classes.
  • Tested other types of instrumentation aimed to detect problems related to user↔kernel communication, such as kernel address disclosures through double-writes.

Read more

Announcing Bochspwn Reloaded and my REcon Montreal 2017 slides

A few days ago at the REcon conference in Montreal, I gave a talk titled Bochspwn Reloaded: Detecting Kernel Memory Disclosure with x86 Emulation and Taint Tracking. During the presentation, I introduced and thoroughly explained the core concept, inner workings and results of my latest research project: a custom full-system instrumentation based on the Bochs x86 emulator, designed to detect instances of uninitialized kernel memory disclosure to user-mode applications. This work was largely based on the original Bochspwn research, conducted by Gynvael and me in 2013, whose goal was to identify so-called double fetch conditions in the kernels of various popular operating systems (see SyScan slides and whitepaper, Black Hat slides and source code on GitHub). Bochspwn Reloaded repeated the success of its predecessor, so far having found nearly 30 infoleak vulnerabilities in Windows, and more than a dozen lesser issues in Linux.

The most relevant part of the abstract is as follows:

This presentation will introduce another subtle class of kernel vulnerabilities – disclosure of uninitialized stack and heap memory to user-mode applications. Since information leaks of this kind leave hardly any footprint, they are rarely noticed and reported to system vendors. However, we have found that it is still a prevalent problem in current kernels (especially Windows), and can be abused to defeat certain exploit mitigations or steal sensitive data residing in ring-0. In order to address this matter, we have developed a new Bochspwn-style instrumentation based on rudimentary kernel memory taint tracking, which we then used to discover 30 memory disclosure issues in Windows alone. In this talk, we will discuss the kernel design problems behind the bugs, the design of our tool, and the exploitation process of some of the most interesting findings.

Without further ado, the full slide deck presented at REcon can be downloaded below:

Read more

Windows Kernel Local Denial-of-Service #5: win32k!NtGdiGetDIBitsInternal (Windows 7-10)

Today I’ll discuss yet another way to bring the Windows operating system down from the context of an unprivileged user, in a 5th and final post in the series. It hardly means that this is the last way to crash the kernel or even the last way that I’m aware of, but covering these bugs indefinitely could soon become boring and quite repetitive, so I’ll stop here and return with other interesting material in the near future. Links to the previous posts about Windows DoS issues are listed below:

The bug explained today can be found in the win32k!NtGdiGetDIBitsInternal system call, which has been around since the very early days of Windows existence (at least Windows NT). The syscall is used by the GetDIBits, BitBlt and StretchBlt documented API functions, and has been recently subject to patching in Microsoft’s April Patch Tuesday, in order to fix an unrelated double-fetch vulnerability reported by Project Zero (CVE-2017-0058, issue #1078 in the tracker). The DoS problem was also reported to the vendor at that time, but due to its low severity, it didn’t meet the bar for a security bulletin.

Read more

Windows Kernel Local Denial-of-Service #4: nt!NtAccessCheck and family (Windows 8-10)

After a short break, we’re back with another local Windows kernel DoS. As a quick reminder, this is the fourth post in the series, and links to the previous ones can be found below:

The bug we’re discussing today resides in an internal nt!SeAccessCheckByType function, reachable via three system calls: NtAccessCheck, NtAccessCheckByType and NtAccessCheckByTypeResultList. All Windows versions starting with Windows 8 are affected, which is caused by the fact that the relevant code area is specific to so-called lowbox tokens (used by AppContainers), a mechanism that was only introduced in Windows 8. Similarly to the past issues, this one was also discovered by a Bochspwn-like instrumentation, and is caused by an unsafe access to user-mode memory (not guarded by adequate exception handling).

Read more

Windows Kernel Local Denial-of-Service #3: nt!NtDuplicateToken (Windows 7-8)

This is the third post in a series about unpatched local Windows Kernel Denial-of-Service bugs. The list of previous posts published so far is as follows:

As opposed to the two issues discussed before, today’s bug is not in the graphical subsystem (win32k.sys), but in the core kernel module: ntoskrnl.exe, and more specifically in the handler of the nt!NtDuplicateToken system call (under the same name). An equivalent bug can also be found in the nt!NtCreateToken system call, but since it requires the SeCreateTokenPrivilege privilege, it cannot be triggered by a regular user, and hence is not of much interest to us.

According to MSDN, the definition of the syscall is as follows:

Read more

Windows Kernel Local Denial-of-Service #2: win32k!NtDCompositionBeginFrame (Windows 8-10)

Another week, another way to locally crash the Windows kernel with an unhandled exception in ring-0 code (if you haven’t yet, see last week’s DoS in win32k!NtUserThunkedMenuItemInfo). Today, the bug is in the win32k!NtDCompositionBeginFrame system call handler, whose beginning can be translated into the following C-like pseudo-code:

NTSTATUS STDCALL NtDCompositionBeginFrame(HANDLE hDirComp, PINPUT_STRUCTURE lpInput, POUTPUT_STRUCTURE lpOutput) {
  NTSTATUS st;
  INPUT_STRUCTURE Input;
  DirectComposition::CConnection *Connection;

  if (lpInput != NULL) {
    try {
      ProbeForRead(lpInput, sizeof(INPUT_STRUCTURE), 1);
      RtlCopyMemory(&Input, lpInput, sizeof(INPUT_STRUCTURE));
      st = STATUS_SUCCCESS;
    } __except(EXCEPTION_EXECUTE_HANDLER) {
      st = GetExceptionCode();
    }
  } else {
    st = STATUS_INVALID_PARAMETER;
  }

  KeEnterCriticalRegion();
  if (NT_SUCCESS(st)) {
    st = DirectComposition::CConnection::ReferenceHandle(hDirComp, &Connection);
    if (NT_SUCCESS(st)) {
      if (Microsoft_Windows_Win32kEnableBits & 1) {
        Template_xq(&DCompBeginFrameEvent, hDirComp, lpInput->SomeField);
      }
      [...]
    }
  }

  [...]
}

Since the i/o structure names and definitions are not known to me, I just generically called them INPUT_STRUCTURE and OUTPUT_STRUCTURE; their details are non-essential to understand the bug. Here, we can see that the 2nd argument (lpInput) is accessed twice: once in line 9, with a proper sanitization with an inlined ProbeForRead call and a try/except block, but then also in line 23, where a field at offset 0x10 (SomeField in the above listing) is read from the user pointer while exception handling is disabled. The Template_xq function is just a thin wrapper around EtwWrite, which is used for logging kernel-mode events. This is the bug we want to exploit.

Read more

Windows Kernel Local Denial-of-Service #1: win32k!NtUserThunkedMenuItemInfo (Windows 7-10)

Back in 2013, Gynvael and I published the results of our research into discovering so-called double fetch vulnerabilities in operating system kernels, by running them in full software emulation mode inside of an IA-32 emulator called Bochs. The purpose of the emulation (and our custom embedded instrumentation) was to capture detailed information about accesses to user-mode memory originating from the kernel, so that we could later run analysis tools to discover multiple references to single memory addresses within the scope of one system call, and produce meaningful reports. The project was called Bochspwn [1][2][3] (or kfetch-toolkit on Github) and was largely successful, leading to the discovery of several dozen serious vulnerabilities in the Windows kernel. We believe it also played a significant role in popularizing the double-fetch vulnerability class and the concept of using system-wide instrumentation for security, as several other fruitful projects ensued as a result, probably most notable of which is Xenpwn.

After all this time, I decided to get back on the subject of full system instrumentation and analyzing various execution traces in search of indicators of potential vulnerabilities. Specifically, one of my goals was to develop more patterns (based on memory accesses or other events) which could signal problems in kernel-mode code other than just double fetches. One intuitive example of such pattern is the lack of exception handling being set up at the time of accessing ring-3 memory area. As the documentation of the Windows ProbeForRead function states:

Drivers must call ProbeForRead inside a try/except block. If the routine raises an exception, the driver should complete the IRP with the appropriate error. Note that subsequent accesses by the driver to the user-mode buffer must also be encapsulated within a try/except block: a malicious application could have another thread deleting, substituting, or changing the protection of user address ranges at any time (even after or during a call to ProbeForRead or ProbeForWrite).

Read more

Slides about my Windows Metafile research and fuzzing now public

During the past few weeks, I travelled around the world to give talks at several great security conferences, such as Ruxcon (Melbourne, Australia), PacSec (Tokyo, Japan), Black Hat Europe (London, UK) and finally Security PWNing Conference (Warsaw, Poland). At a majority of the events, I presented the results of my Windows Metafile security research, which took place earlier this year and yielded vulnerabilities in GDI (exploitable e.g. in Internet Explorer), GDI+ (e.g. Microsoft Office), ATMFD.DLL (Windows local privilege escalation) and the Virtual Printers mechanism in VMware Workstation. As part of the talks, I explained what GDI and metafiles really are, the process I followed while hunting for and identifying the vulnerabilities, and the exploitation paths for some of them. Finally, I discussed my approach to fuzzing a user-mode Windows DLL module on Linux machines (cross-platform), on the example of a 3rd party JPEG2000 decoder used in VMware products. Since my allocated time slots at both Ruxcon and PacSec were too short to cover the entirety of the material, I talked about the ATMFD.DLL vulnerabilities exclusively at Ruxcon, and about GDI+ only at PacSec. A complete list of the EMF bugs that were mentioned in the presentations can be found in the Google Project Zero tracker.

The second talk (presented at BH) focused purely on fuzzing and the various thoughts, techniques and results I arrived at after actively using this approach to uncover software security flaws for more than 5 years, both as part of and outside of work. The topics included gathering initial corpora of input files, extracting code coverage information from running programs, using this information to “distill” and manage live corpora (using a parallelized algorithm), interacting with our target application on various levels, and effectively mutating the input data to accomplish the best results. The presentation was then concluded with a brief analysis of my recent Windows kernel font fuzzing initiative, which has resulted in the discovery of 18 issues so far.

Read more

Windows system call tables updated, refreshed and reworked

Those of you interested in the Windows kernel-mode internals are probably familiar with the syscall tables I maintain on my blog: the 32-bit and 64-bit listings of Windows system calls with their respective IDs in all major versions of the OS, available here (and are also linked to in the menu):

After a few years of inactivity in this area, I’ve found some time to update and thoroughly refresh the tables. The changelog is as follows:

  1. Added information from Windows Server 2003 (R2, R2 SP2), Windows Server 2008 (R2, R2 SP1), Windows Server 2012 (R2) and Windows 10 (1507, 1511, 1607).
  2. Clarified some versions of Windows, resulting in removing non-existent Windows Server 2008 SP1 (32-bit), Windows XP SP0 (64-bit), Windows Server 2003 SP1 (64-bit), Windows Server 2008 SP1 (64-bit).
  3. Removed empty columns with missing information from the win32k 32-bit table.
  4. Performed a major clean up of the lists, resolving all syscall handler collisions and renaming invalid symbols (e.g. “FsRtlSyncVolumes”) stemming from compiler optimizations to their correct form. From now on, all system calls are represented by their real names starting with “Nt”.
  5. Unified the layout of NT and win32k tables.
  6. Added more granular information to the win32k 64-bit table (accounting for all service packs and major releases).
  7. Fixed HTML syntax errors and improved JavaScript code formatting.

I hope the tables keep proving useful for Windows researchers interested in those interfaces. :-) And of course, all comments, suggestions and bug reports are highly appreciated!