While looking at a recent exploit for VLC on Windows, I noticed some unexpected behaviors. In this blog post, I will describe how my journey led me to the discovery of several flaws that put users of many applications at unnecessary risk. VLC isn't the only victim here.

As a vulnerability analyst at the CERT Coordination Center, I am interested not only in software vulnerabilities themselves, but also exploits and exploit mitigations. Working in this field, it doesn't take too long to realize that there will never be an end to software vulnerabilities. That is to say, software defects are not going away. For this reason, software exploit mitigations are usually much more valuable than individual software fixes. Being able to mitigate entire classes of software vulnerabilities is a powerful capability. One of the reasons why we strongly promote mitigation tools like EMET or Windows Defender Exploit Guard , which is the replacement for EMET on the Windows 10 platform, is because exploit mitigation protections are not limited to the specific vulnerability du jour.

Memory Corruption Exploit Mitigations

When discussing memory corruption exploit mitigations, two rudimentary building blocks are Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR). Both techniques must be used together for the basis of an effective exploit mitigation strategy.

DEP

DEP, also referred to as NX or W^X on other platforms, ensures that a CPU executes only instructions that have been explicitly marked as executable. In other words, a system should only execute code. The system should refuse to execute bytes that are provided in the content of a document, for example.

ASLR

ASLR ensures memory locations associated with a process are not predictable. This capability is important to help prevent the use of Return Oriented Programming (ROP) by an attacker.

Confirming the Presence of DEP and ASLR

In the past I used CERT BFF to find some exploitable crashes in the Oracle Outside In library. I investigated several applications that use Outside In to demonstrate proof-of-concept (PoC) exploits for the vulnerabilities I discovered. I settled on two forensics investigation applications: Guidance EnCase and AccessData FTK. Why did I choose these applications? On one hand, the concept of exploiting vulnerabilities in forensics software seemed interesting to me, but more importantly it was because both applications failed their due diligence with respect to exploit mitigations.

The simplest way to check for the presence of DEP and ASLR is by using Microsoft Sysinternals Process Explorer. You can configure Process Explorer to display columns for DEP and ASLR. When a process is running, you can check these columns for the status of DEP and ASLR for the process. First let's check EnCase running on Windows XP. This was 2013, so Windows XP was still supported and prevalent.

EnCase didn't even enable DEP on Windows XP. You couldn't ask for an easier target to exploit!

On Windows 7, the situation is a little bit better, as DEP is enabled. However, Process Explorer reports that ASLR is not enabled for the EnCase.exe process, as shown in this figure:

Creating a PoC for Windows 7 required a little more work than the PoC for Windows XP, but it was still possible to achieve. As noted by Microsoft, DEP by itself or ASLR by itself do not provide viable protections against exploitation. Both must be present together to provide any meaningful protection against the exploitation of memory corruption vulnerabilities.

The VLC Exploit

Earlier this month, a PoC exploit for VLC 2.2.8 was posted to Exploit Database. This exploit was tagged as "E-DB Verified," which indicates that the exploit was confirmed to be functional. I tested out the exploit in a fully-patched 64-bit Windows 10 virtual machine that was connected to a CERT Tapioca Wildcard VM for network connectivity (since I don't fully trust what the exploit claims to do). Sure enough, opening the MKV file resulted in calc.exe popping, as shown in this figure:

Let's take a look to see if VideoLAN was negligent in opting in to exploit mitigations:

Something is quite strange here. The binary vlc.exe opts in to both DEP and ASLR, and all of its dependencies are ASLR-enabled as well. This means that there should be no predictable code locations for an attacker to leverage in a ROP exploit. But notice that the base address for vlc.exe is 0x00400000 , which is a special address in the world of Microsoft Windows. This address is an indicator that a process has not been loaded at an address that has been randomized by ASLR. Why is Process Explorer reporting that VLC is using ASLR, but it is also loading at a non-randomized address?

Looking at the exploit for VLC 2.2.8, we can see that it uses a ROP chain with fixed offsets that would live within the space of a process loaded at 0x00400000 :

rop_gadgets = { '64': { '2.2.8': [ 0x004037ac, # XCHG EAX,ESP # ROL BL,90H # CMP WORD PTR [RCX],5A4DH # JE VLC+0X37C0 # XOR EAX,EAX # RET 0x00403b60, # POP RCX # RET target_address, # lpAddress 0x004011c2, # POP RDX # RET 0x00001000, # dwSize 0x0040ab70, # JMP VirtualProtect target_address + 0x500, # Shellcode ], },



PE File Header Investigation

Using Process Explorer to check an EXE for ASLR compatibility is a convenient shortcut. But clearly something is wrong in the case of VLC. By using the Microsoft Visual Studio tool dumpbin, we can check the PE headers of the vlc.exe binary. This is where it gets interesting, as shown in this figure:

Here we have an executable file that has two contradicting properties:

Dynamic base - This property indicates that the binary was linked with the /DYNAMICBASE flag, which opts the binary in to ASLR randomization by the OS.

Relocations stripped - This property indicates that the binary has had its relocation table removed. A traditional Windows executable with no relocation table cannot be randomized by Windows ASLR. Even if "mandatory ASLR" is enforced via EMET or Windows Defender Exploit Guard, these executables cannot be randomized by Windows.

(Note: The exceptions to this rule are .NET executables. If executed on a Windows 8 or newer platform, a .NET executable with a stripped relocation table will still be relocated. On the Windows 7 platform, these .NET executables do not receive any benefit from ASLR.)

These two attributes of an executable file on Windows are at odds with each other. If a tool is simply looking for the presence of "Dynamic base" to determine whether an executable is using ASLR, this check alone is not sufficient. Microsoft Sysinternals Process Explorer versions 16.12 and earlier make this mistake. The impact of this flaw is that an analyst may be given a false sense of security about the exploit mitigations present in a product.

mingw-w64 and its Bad Defaults

How did we end up with a VLC executable that contains two different properties that contradict each other? To find the answer, look at the build chain that was used to compile the code: mingw-w64.

The build chain mingw-w64 allows the GCC compiler and its related tools to create executable code that functions on Microsoft Windows. Because GCC runs on multiple platforms, this means that I can use mingw-w64 on a Linux platform to create a Windows EXE file, for example.

The problem is that mingw-w64 doesn't produce a relocation table when linking executables with the "Dynamic base" option.

This limitation has been publicly known since 2013. This conversation thread ended in June 2013 with the comment: "Just a gentle reminder - any chance someone has been able to look at this?"

In 2014, a developer with the Tor Project suggested adding an optional flag to generate the relocation section required for proper ASLR functionality. The last activity on this ticket was from September 17, 2014, where the binutils developer requested some additional modifications to be made before the changes would be accepted.

In 2015, a ticket was filed for binutils that outlines several bad default settings for mingw-w64. One of the suggestions in this ticket is, "Never strip the reloc section."

A Workaround to Get Proper ASLR Compatibility with mingw-w64

Until binutils is updated to fix the generation of Windows code with mingw-w64, developers must take specific actions to produce executable files that are compatible with ASLR. While testing a simple "Hello world" application produced with mingw-w64, the addition of the following line before the main function resulted in an executable file that retained its relocation table:

__declspec(dllexport)

Apparently exporting a function in an executable file causes mingw-w64 to link the executable in a way that does not strip the relocation table. With the relocation table present, Windows can properly randomize the load address of executable using ASLR.

Conclusion and Recommendations

VideoLAN was a victim of using a toolchain (mingw-w64) that has insecure defaults. Because the VLC executable wasn't able to be randomized with ASLR, this allowed a fully functional and reliable exploit to be written for one of its vulnerabilities. Had mingw-w64 used secure default settings, which in this case means not stripping the relocation table of an executable that claims to be ASLR compatible, the public exploit that uses fixed ROP offsets would not be viable.

This situation is made worse by the fact that several tools that check for ASLR compatibility assume that the presence of the "Dynamic base" PE header is sufficient for ASLR compatibility. Because Process Explorer does not check that a relocation table is present, its indication of "ASLR" for a running process may be incorrect, and it may provide a false sense of security.

Note that a missing relocations table is not the only way that executable code may not be compatible with ASLR, despite the output files providing the "Dynamic base" PE header. Some executable content protected by WIBU-Systems tools appear to be ASLR compatible, both by the presence of the "Dynamic base" header, as well as the relocations table. However, such code may not be compatible with ASLR in practice. For example, WIBU IxProtector encrypts functions, and as a result the code produced may not be properly formed as far as Windows is concerned. Windows software defenses may not behave as designed in cases like this.

Recommendation for Security Researchers:

Unless you are certain that your security tool is checking for the presence of both the "Dynamic base" PE header and the presence of a relocation table, do not rely on that tool's indication of whether an executable is using ASLR or not. The PE headers, which are viewable via dumpbin and other tools, are the definitive source of this information.



the "Dynamic base" PE header and the presence of a relocation table, do not rely on that tool's indication of whether an executable is using ASLR or not. The PE headers, which are viewable via dumpbin and other tools, are the definitive source of this information. Some malformed executable code may appear to be ASLR compatible at a glance, but in practice is not compatible with ASLR. For this reason, it is important to verify the addresses that executable code (both executable and DLL) get loaded. With properly functioning ASLR, code will get loaded at an address other than what is statically specified as the "image base" in the PE header.

Recommendation for Developers:

Ensure that your executables contain both the "Dynamic base" PE header, and also contain a relocation table. Without a relocation table, vulnerabilities in any executable that you produce will be easier to exploit due to ASLR incompatibility. If you are using the mingw-w64 toolchain, the __declspec(dllexport) workaround outlined above appears to produce ASLR-compatible executables.

workaround outlined above appears to produce ASLR-compatible executables. If you are using software obfuscation tools, such as WIBU IxProtector, be sure to verify that the code being produced is compatible with Windows ASLR. This can be verified by confirming that the executable code is loaded at an address other than the image base that is specified within the binary itself. Code without ASLR protection is code more vulnerable to exploitation by attackers.

Whether you are a security researcher, a developer, or anybody else interested in the security of executables on your system, you can check for PE files that contain the problematic combination of "Dynamic base" and have a stripped relocation table using the following python script that I have created: (checkaslr.py):

This tool lists problematic code files, along with the image base that is specified in each file.

Additional information about the mingw-w64 issue is available in vulnerability note VU#307144.