scieee AI-readable full text Open interactive document viewer

InSpectre Gadget: Inspecting the residual attack surface of cross-privilege Spectre v2

Sander Wiebing; Alvise de Faveri Tron; Herbert Bos; Cristiano Giuffrida

Abstract

Spectre v2 is one of the most severe transient execution vulnerabilities, as it allows an unprivileged attacker to lure a privileged (e.g., kernel) victim into speculatively jumping to a chosen gadget, which then leaks data back to the attacker. Spectre v2 is hard to eradicate. Even on last-generation Intel CPUs, security hinges on the unavailability of exploitable gadgets. Nonetheless, with (i) deployed mitigations—eIBRS, no-eBPF, (Fine)IBT—all aimed at hindering many usable gadgets, (ii) existing exploits relying on now-privileged features (eBPF), and (iii) recent Linux kernel gadget analysis studies reporting no exploitable gadgets, the common belief is that there is no residual attack surface of practical concern. In this paper, we challenge this belief and uncover a significant residual attack surface for cross-privilege Spectre-v2 attacks. To this end, we present InSpectre Gadget, a new gadget analysis tool for in-depth inspection of Spectre gadgets. Unlike existing tools, ours performs generic constraint analysis and models knowledge of advanced exploitation techniques to accurately reason over gadget exploitability in an automated fashion. We show that our tool can not only uncover new (unconventionally) exploitable gadgets in the Linux kernel, but that those gadgets are sufficient to bypass all deployed Intel mitigations. As a demonstration, we present the first native Spectre-v2 exploit against the Linux kernel on last-generation Intel CPUs, based on the recent BHI variant and able to leak arbitrary kernel memory at 3.5 kB/sec. We also present a number of gadgets and exploitation techniques to bypass the recent FineIBT mitigation, along with a case study on a 13th Gen Intel CPU that can leak kernel memory at 18 bytes/sec.

Full text

This paper is included in the Proceedings of the 33rd USENIX Security Symposium. August 14–16, 2024 • Philadelphia, PA, USA 978-1-939133-44-1 Open access to the Proceedings of the 33rd USENIX Security Symposium is sponsored by USENIX. InSpectre Gadget: Inspecting the Residual Attack Surface of Cross-privilege Spectre v2 Sander Wiebing, Alvise de Faveri Tron, Herbert Bos, and Cristiano Giuffrida, Vrije Universiteit Amsterdam https://www.usenix.org/conference/usenixsecurity24/presentation/wiebing InSpectre Gadget: Inspecting the Residual Attack Surface of Cross-privilege Spectre v2 Sander Wiebing∗Alvise de Faveri Tron∗Herbert Bos Cristiano Giuffrida Vrije Universiteit Amsterdam ∗Equal contribution joint first authors Abstract Spectre v2 is one of the most severe transient execution vulnerabilities, as it allows an unprivileged attacker to lure a privileged (e.g., kernel) victim into speculatively jumping to a chosen gadget, which then leaks data back to the attacker. Spectre v2 is hard to eradicate. Even on last-generation Intel CPUs, security hinges on the unavailability of exploitable gadgets. Nonetheless, with (i) deployed mitigations—eIBRS, no-eBPF, (Fine)IBT—all aimed at hindering many usable gadgets, (ii) existing exploits relying on now-privileged features (eBPF), and (iii) recent Linux kernel gadget analysis studies reporting no exploitable gadgets, the common belief is that there is no residual attack surface of practical concern. In this paper, we challenge this belief and uncover a significant residual attack surface for cross-privilege Spectre-v2 attacks. To this end, we present InSpectre Gadget, a new gadget analysis tool for in-depth inspection of Spectre gadgets. Unlike existing tools, ours performs generic constraint analysis and models knowledge of advanced exploitation techniques to accurately reason over gadget exploitability in an automated fashion. We show that our tool can not only uncover new (unconventionally) exploitable gadgets in the Linux kernel, but that those gadgets are sufficient to bypass all deployed Intel mitigations. As a demonstration, we present the first native Spectre-v2 exploit against the Linux kernel on last-generation Intel CPUs, based on the recent BHI variant and able to leak arbitrary kernel memory at 3.5 kB/sec. We also present a number of gadgets and exploitation techniques to bypass the recent FineIBT mitigation, along with a case study on a 13th Gen Intel CPU that can leak kernel memory at 18 bytes/sec. 1 Introduction As the community slowly comes to grips with various forms of transient execution attacks [16,32,34,35,38,54], Spectre v2 or Branch Target Injection (BTI) [2] remains one of the most severe ones, able to transiently divert the control flow of a program. If attackers can find a snippet of code that encodes secret data into the microarchitectural state, i.e., a (disclosure) gadget, they can force a victim program, e.g., the kernel, to transiently jump to it. Even in the face of hardware mitigations such as eIBRS, researchers have shown that Spectre v2 can still leak secret data across privilege levels on Intel systems through what is known as Branch History Injection (BHI) [16]. However, neither academia [16] nor industry [8] ever found an exploitable “native” gadget and the only existing exploit relies on a gadget injected by the authors themselves using eBPF. Since then, new advanced mitigations such as Indirect Branch Tracking (IBT) and its recent fine-grained counterpart FineIBT, have reduced the set of usable gadgets even (much) further. As a result, it is a common belief that deployed mitigations such as eIBRS and privileged eBPF (now default in all popular Linux distributions) are sufficient to eliminate the cross-privilege Spectre-v2 attack surface—and even more so in combination with the opt-in (Fine)IBT mitigations. To challenge this belief, our key observation is that current techniques to identify such gadgets either overfit “standard” patterns—identifying only gadgets that look like a handful of known Spectre examples and ignoring less conventional patterns—or grossly overapproximate—identifying many potential gadgets of which exploitability is highly uncertain. Examples of the latter are approaches that identify gadgets based on their high-level data flow, leaving exploitability to manual analysis [16,24,31]. Examples of the former include all pattern-based gadget scanners [40,42,43], but also all simplifying and self-limiting gadget definitions [8]. Overly constraining the definition of a gadget is dangerous, because even snippets that do not meet all the preconditions of a standard gadget can still leak data with advanced exploitation techniques [24,31,54]—leaving a gap between what attackers need for exploitation and what vendors and developers consider for mitigation. In this paper, we present InSpectre Gadget, an in-depth Spectre gadget inspector that uses symbolic execution to accurately reason about exploitability of usable gadgets. To this end, our tool explicitly models data constraints and knowlUSENIX Association 33rd USENIX Security Symposium 577 edge of advanced exploitation techniques. This strategy relaxes the common preconditions of standard gadgets, while still avoiding the common overapproximations that would otherwise report many unexploitable gadgets. Moreover, it provides the analyst with insights into exploitability characteristics, such as the exploitation techniques required, the constraints to be met, the values that can be leaked, etc. Scanning the Linux Kernel, InSpectre Gadget finds 1,565 gadgets leading to secret transmission, a significant residual attack surface. Furthermore, it uncovers hundreds dispatch gadgets, i.e., gadgets containing an indirect branch to an attacker-controlled target and, as we will show, providing the attacker with a variety of interesting capabilities for exploitation in face of deployed mitigations. Examples include increasing control over registers, expanding the set of reachable gadgets, or crafting disclosure gadgets by chaining multiple loads. To demonstrate the practicality of our findings, we use the reported gadgets to implement the first native Spectre-v2 exploit against the Linux kernel on last-generation Intel CPUs. Our exploit is based on the BHI variant and is able to leak kernel memory at 3.5 kB/sec without eBPF. Furthermore, in contrast to previous findings, we show the recent (Fine)IBT mitigations still allow transient execution of between 4 and 6 (unchecked) dependent loads. To exploit the resulting attack surface, we showcase a number of gadgets and exploitation techniques, along with a case study on a 13th Gen Intel CPU, leaking kernel memory at 18 bytes/sec. Contributions. To summarize our contributions: 1. We build InSpectre Gadget, a gadget inspector that evaluates exploitability of potential gadgets, incorporating data constraints and knowledge of advanced exploitation techniques. InSpectre Gadget is available at https://github.com/vusec/inspectre-gadget, along with a database of gadgets found for Linux kernel v6.6-rc4. 2. We present the first native (no-eBPF) BHI exploit on the latest Linux kernel and last-generation Intel CPUs (CVE-2024-2201). 3. We analyze the effectiveness of both the IBT and FineIBT mitigations and demonstrate they are insufficient to hinder native BHI exploitation. 4. We uncover a large presence of dispatch gadgets in the kernel, showing how an attacker can abuse them to further the attack surface and bypass deployed mitigations. 2 Background 2.1 Transient Execution Attacks Modern CPUs rely on a multitude of speculation mechanisms to achieve better performance. For example, whenever a CPU encounters a control flow instruction like a conditional branch HA HV Speculate KernelUser 3 4 HA HV call [rax] BTB Collision legit target eBPF gadget 1 2 call [rax] CA CV TA TV eBPF victim Figure 1: The BHI attack. The attacker first triggers the branch CA with history HA1  , which inserts the target TA into the BTB 2  , then triggers the victim branch CV with history HV3  . The histories are crafted so that CA and CV share the same BTB entry, so from CVthe CPU speculates to TA4 . or an indirect branch, the correct target might not be known yet. To avoid stalling, the CPU uses a set of internal structures, called predictors, to determine the next instruction to fetch, and starts speculatively executing instructions. If the speculation is later revealed to be incorrect, the CPU will undo the effects of the transient execution and restart from the correct jump target. However, traces of the transient computation can still be observed in the shared microarchitectural state, e.g. in the cache. An attacker can then measure these traces with techniques such as FLUSH+RELOAD [55] and PRIME+PROBE [36] and recover the values of registers and memory used during the transient computation. 2.2 Spectre v2 In 2018, the disclosure of Spectre [32] famously demonstrated how speculation can be used to leak data across security domains. One variant presented in the paper, originally known as Spectre v2 or Branch Target Injection (BTI), shows how speculation of indirect branches can be used to transiently divert the control flow of a program and redirect it to an attackerchosen location. The attack works by poisoning one of the CPU predictors, the Branch Target Buffer (BTB), which is used to decide where to jump on indirect branch speculation. Initially, mitigations were proposed at the software level and, later, in-silicon mitigations such as Intel eIBRS [6] an ARM CSV2 [14] were added to newer generations of CPUs to isolate predictions across privilege levels. 2.3 Branch History Injection In 2022, Branch History Injection (BHI) [16] showed that, despite mitigations, cross-privilege Spectre v2 is still possible on latest Intel CPUs by poisoning the Branch History Buffer (BHB). Figure 1provides a high-level overview of the attack. 578 33rd USENIX Security Symposium USENIX Association In summary, by executing a sequence of conditional branches (HAand HV) right before performing a system call, an unprivileged attacker can cause the CPU to transiently jump to a chosen target ( TA ) when speculating over an indirect call in the kernel ( CV ). This happens because the CPU picks the speculative target for CV from a shared structure, the BTB, that is indexed using both the address of the instruction and the history of previous conditional branches, which is stored in the Branch History Buffer (BHB). Finding the right combination of histories that will result in a collision can be done with brute-forcing. To ensure the injected target, TA , contains a disclosure gadget, the original BHI attack relied on the presence of the extended Berkeley Packet Filter (eBPF), through which an unprivileged user can craft code that lives in the kernel. 2.4 Defenses As a recommended mitigation for BHI, Intel has advised to disable unprivileged eBPF, which is now disabled by default in the Linux kernel, and to mitigate potential disclosure gadgets by prepending a LFENCE instruction to them [1]. Attack Surface Analysis. The original BHI paper presented an initial estimate of the BHI attack surface beyond eBPF using simple data-flow analysis and a loose definition of disclosure gadget [16]. The analysis pinpointed 1,177 potential gadgets in the Linux kernel, but with no insights into their exploitability. Later, Intel researchers statically analyzed the Linux kernel [8], adopting a more refined data-flow-based approach and finding an order of magnitude more potential gadgets. Again, with the analysis unable to automatically reason over exploitability, Intel researchers resorted to manually assessing exploitability of the 8 simplest (linear) gadgets. No gadgets were deemed exploitable (6 due to reachability issues, 2 due to leakage constraints). Ultimately, with many potential gadgets uncovered by both scanners but no evidence of practical exploitability, no additional mitigations were deployed. Hardware mitigations. On the hardware front, Intel has proposed a hardware mitigation, the BHI_DIS_S indirect predictor control, which prevents the CPU from selecting BTB entries based on history coming from lower security domains. As the performance overhead is nontrivial, future CPUs might come with an optimized version, namely BHI_NO . At the time of writing, while Alder Lake and Raptor Lake Intel CPUs support BHI_DIS_S after applying a microcode update, the Linux Kernel does not have support to enable this feature. Advanced software mitigations. Additional software mitigations, like Retpoline [10] or a software BHB-clearing sequence [1], have been proposed as spot fixes. However, they come with a prohibitive performance cost, discouraging practical deployment. For Linux, in particular, the software BHBclearing sequence recommended by Intel has not been implemented at all, as developers rely on unprivileged eBPF being “the only known real-world BHB attack vector” [11]. IBT. Indirect Branch Tracking (IBT) [48] is a defense for code-reuse attacks, such as return-oriented programming [46] and jump-oriented programming [19], which ensures that indirect branches always jump to an intended target. Intel CPUs implement a coarse-grained version of IBT in hardware, which ensures that every indirect branch lands on a special instruction ( endbr32 or endbr64 ), which has to be inserted by the compiler. While IBT was originally designed to address architectural control-flow hijacking, it is also part of Intel’s mitigation guidance for BHI [1]. This is to provide defense-in-depth against speculative control-flow hijacking, limiting—somewhat similarly to the existing eIBRS—the possible Spectre-v2 disclosure gadget locations to the beginning of any indirect branch target in the kernel. Support for IBT was added to Intel processors with the Tiger Lake series [7] and is enabled by default from Linux kernel v6.2 [4]. FineIBT. Researchers have recently proposed a finergrained IBT variant in software, called FineIBT [23]. The idea is to instrument the caller of each IBT-guarded indirect call to load a unique value into a register as well as the callee to check said value. If the value is different from the expected one, the execution path is directed to an illegal instruction to abort execution. This further restricts indirect calls to (architecturally or speculatively) target only compliant callees. Support for FineIBT was recently introduced in Linux kernel v6.2 [5]. Since FineIBT relies on Clang-instrumented kernels [23], to our knowledge, it is not yet enabled by default in any Linux distribution (unlike its IBT building block). 3 Threat Model We consider a traditional cross-privilege Spectre-v2 threat model, with a local unprivileged attacker seeking to disclose information from a privileged victim, such as the operating system kernel or the hypervisor. We specifically focus on a victim Linux kernel, running with all default Spectre-v2 mitigations on last-generation Intel CPUs such as eIBRS [6] and privileged eBPF. Finally, we assume other classes of vulnerabilities (e.g., memory errors) are subject of orthogonal mitigations and not part of the attack surface under study. 4 Overview To perform a Spectre-v2 attack against the kernel on lastgeneration Intel systems, one must target an indirect branch in the kernel that jumps to a disclosure gadget. Using BHI, one can then speculatively hijack a victim branch to the chosen gadget. InSpectre Gadget aids the analyst in choosing a suitable gadget, following the workflow depicted in Figure 2. As shown in the figure, the analyst provides InSpectre Gadget with a kernel image and a list of candidate gadgets in input. Our tool inspects each candidate for a fixed number USENIX Association 33rd USENIX Security Symposium 579 Exploitable Gadgets Filtered Gadgets 1 2 3 Control Defenses  Craft Exploit call [rax] call [rax] InSpectre Gadget Chosen gadget + Kernel Targets Figure 2: InSpectre gadget workflow. The analyst provides a kernel image and a list of target addresses to InSpectre Gadget 1  , which performs in-depth inspection to find gadgets that can leak secrets and output their characteristics. The gadgets can be filtered 2  based on the available attackercontrolled registers and the mitigations enabled, and used to craft Spectre-v2 exploits against the kernel 3 . of basic blocks with symbolic execution and returns a list of gadgets that lead to the transmission of a secret. Along with the gadgets, our tool outputs a number of gadget characteristics: the advanced exploitation techniques required (if any), the constraints that have to be met, the registers that have to be controlled, and the values that can be leaked. Such characteristics are stored into a database, which the analyst can later filter according to what targets are reachable, what registers are controlled when the speculative hijack happens, and what mitigations are enabled for a given target. Additionally, an annotated assembly file is generated for each gadget to give the analyst a quick overview of the gadget, as shown in Appendix C. The resulting gadgets can then be exploited to mount end-to-end Spectre-v2 kernel attacks. In the next sections, we first elaborate on how InSpectre Gadget models gadgets (constraints, exploitability, etc.) and how it then performs exploitation-aware gadget inspection. Next, we demonstrate how an attacker can use its output to mount an end-to-end BHI attack against the Linux kernel. 5 InSpectre Gadget A recurring problem in transient execution attacks is evaluating if a given instruction sequence can leak a secret via a—typically cache [27,33,36,41,47,55]—covert channel. To leak a secret through the cache, an attacker needs to open a speculation window and accommodate a disclosure gadget. In this section, we explain that practical disclosure gadgets extend well beyond those that fit existing narrow definitions. Next,we show how InSpectre Gadget uses symbolic execution to analyze the candidate gadgets for Spectre-v2 exploitability. Listing 1: Standard Spectre disclosure gadget. 1// Load from attacker-controlled address 2uint64_t secret = *attacker; 3// Mask the loaded value 4uint8_t secretByte =(secret & 0xFF); 5// Shift the result 6uint32_t tsecret =secretByte << 9; 7// Use transmission secret as index. 8uint64_t transmission = *(tbase +tsecret); 5.1 Standard Gadgets Today’s tools typically concentrate on finding speculation windows and overapproximating exploitability—leaving the analysis of disclosure gadgets to the human analyst. Unfortunately, the complexity of such exploitability analysis is daunting and, unsurprisingly, analysts generally look for standard Spectre disclosure gadgets, such as the one in Listing 1. In a standard (or “perfect”) gadget, the CPU loads a secret from an attacker-controlled address. The loaded secret must be sufficiently small, either by nature, or as the result of a bitmask (Line 4), to serve as an index into a second buffer— ideally shared with the attacker. This second buffer is known as the reload buffer. Moreover, to ensure that each value of the secret corresponds to a different cache line, the gadget should shift the value left by some stride (Line 6). The result is known as the transmitted secret. As the gadget subsequently adds it to a second attacker-controlled value which we refer to as the transmission base and dereferences the resulting value, it inadvertently establishes a transmission through a cache covert channel. Specifically, by iterating over the reload buffer with the same stride while timing the accesses, attackers can infer that the secret value is the index of the buffer element for which the access is fast (because it is in the cache). 5.2 Exploitation-Aware Gadget Analysis Standard gadgets are the most intuitive to understand and the most straightforward to exploit, but they are by no means the only exploitable ones. While limiting the analysis to standard gadgets reduces the complexity, attackers are under no obligation to respect such restrictions. BLINDSIDE [24], KASPER [31], PACMAN [44], and RETBLEED [54], for example, all exploit gadgets that deviate from such narrow definitions. Moreover, besides leaking information through the cache, attackers may avail themselves of a myriad of other covert channels [18,22,25,45,52]. In this section, we relax the assumptions for standard gadgets, describe the additional challenge posed by each relaxation, and where appropriate, explain how we can meet the challenge and still leak secrets. C1. Base not controlled. To perform FLUSH+RELOAD an attacker needs to be in control not only of the secret address, but also of the transmission base, so that the transmission load falls inside of the reload buffer. However, if the base is not 580 33rd USENIX Security Symposium USENIX Association buff - 0xdeadbe00 + 0xdeadbeef Transmission Base Known Prefix 00 00 00 00 de ? 00 00 00 00 de ad be ? 00 00 00 00 ? 1 2 3 Secret Figure 3: Known-prefix technique. The attacker first points the secret address to some known data 1  . Then, by shifting the address 2  , small portions of the secret are revealed. With that, one can adjust the base of subsequent transmissions 3  . controlled, attackers can still perform PRIME+PROBE [36]. C2. Secret entropy too big. If the code does not mask the secret prior to its transmission, the entropy impedes its recovery by the attacker who would have to probe too many memory locations. However, if the attackers control the transmission base, they can still exploit such gadgets by repurposing a technique pioneered in earlier attacks [24,52,54], which we call the known-prefix technique. First, the attacker chooses a location in memory near the secret that contains a small known value, and uses that as the secret address. Then, by increasingly shifting the address, the attacker makes sure that only a few bytes of the secret are unknown at any given transmission, and adjusts the transmission base according to the bytes that are already known (see Figure 3). C3. Max secret too high. Another problem that may occur when leaking a large secret value is that the transmission address might end up outside the valid address space. However, if enough bits of the transmission base are under attacker control, one can adjust the base to overflow the secret value, ensuring that the transmission always occurs in the valid address space. We call this technique base adjusting and it is often used in conjunction with the known-prefix technique. C4. Secret too small. If the gadget does not shift the secret value prior to transmission, the lower bits cannot be recovered through cache covert channels, since nearby addresses belong to the same cache line. However, if at least one byte of the secret is above cache-line granularity, we can use the knownprefix technique to leak the uppermost byte in each iteration. Otherwise, an attacker may use the sliding technique of RETBLEED [54], which exploits the fact that prefetchers generally do not prefetch cache lines across pages [49]. An attacker may now adjust the base address to be near a page boundary, so that even a one-bit difference in the secret value will result in the transmission being observed on another memory page. Doing so eliminates any cache and prefetcher noise that would otherwise make two different values indistinguishable. C5. Base aliasing. In some cases, even if the transmission base is attacker-controlled, the base cannot be chosen without influencing the secret address—a phenomenon we refer to as aliasing. This may occur, for instance, if the base is computed from a value that is also used to compute the secret address. In this case, an attacker can still leak values using PRIME+PROBE. However, not all secret addresses may be targeted as the probe region must reside within mapped memory. Specifically, since the probe region typically follows the secret address, the final secret addresses result in a non-mapped probe region. Other, more complex dependencies between the base and the secret address out of scope. InSpectre Gadget marks these cases as not (easily) exploitable. C6. Non-linear gadgets. An implicit assumption of most static analysis techniques for gadget scanning is that all the instructions have to be in the same basic block. Since modern CPUs all support nested speculation, this is not a limitation in practice. The attacker can either train branches or simply use static prediction to ensure that the transmission gadget is reached during speculative execution. An attacker can also use SMT contention, as demonstrated by prior work [39], to delay branch resolution and create large speculation windows that can accommodate multiple basic blocks. C7. Other transmitters. Finally, a plethora of covert channels exist in modern CPUs outside of caches (e.g., the TLB [37]) and one should flexibly support different transmitters. For brevity, we focus our main analysis on classic secret-dependent data load/store transmitters and later show our tool can be easily extended to support other vectors such as the recent SLAM covert channel [29]. 5.3 Design While advanced exploitation techniques relax the assumptions for standard gadgets, each has its own requirements and constraints for applicability. To reason over the constraints and to assess if the code satisfies them, InSpectre Gadget employs symbolic execution—expressing variables as symbols, and exploring all the possible directions of a program’s control flow at the same time, while recording the corresponding symbolic constraints. To this end, we build our tool on top of ANGR [50], a symbolic execution engine widely used in the field of software security and reverse engineering. Although symbolic execution quickly leads to state explosion in the general case, InSpectre Gadget explores only a small fraction of the program’s control flow. In particular, since the number of instructions executed during a speculation window is limited, symbolic execution can easily explore multiple paths, while keeping the number of explored states small. All the steps described below are performed automatically by InSpectre Gadget. Tracking attacker control. We start our analysis by substituting all the values stored in registers and on the stack with USENIX Association 33rd USENIX Security Symposium 581 Transmission Base Secret Transmitted Secret LOAD[ LOAD[rax] + (( LOAD[rbx] & 0xff) * 8) ] Figure 4: Anatomy of a transmission. Once a potential transmission is identified through symbolic execution, InSpectre Gadget dissects its symbolic expression into components, which are then analyzed to reason about exploitability. symbolic variables, which for now we assume are attackercontrolled, and marked as such. Next, we symbolically execute code starting from a given location. On each load, we produce a new symbolic value with a label attached to it. If the load comes from an attacker-controlled symbol, it is marked as a potential secret. If the address comes from a potential secret, it is marked as a potential transmission. Note that potential secret implies attacker-controlled, since it is any value loaded from an attacker-chosen location. Similarly, potential transmission implies potential secret. This strategy allows us to track of attacker control through complex chains of loads. Store-to-Load Forwarding (STL). We model Store-ToLoad Forwarding by keeping a list of all the symbolic stores, and checking this list for each of the loads encountered by the symbolic execution engine. If the symbolic expression of the load address aliases with that of a previous store, we forward the stored value to the load. Store-to-Load forwarding can be enabled or disabled with a runtime flag. Potential transmissions. We let the symbolic execution engine run for a configurable number of basic blocks, recording all the constraints that might be added, for instance by cmove or branch instructions. We also record the symbolic expression of each load. Finally, after the scanning phase is finished, the scanner reports a list of potential transmissions, i.e., loads whose symbolic address has been marked as a potential secret. In a second phase, we inspect the AST of the symbolic expression of each potential transmission, identifying the transmission base, transmitted secret, and secret address. A highlevel example is shown in Figure 4. Finally, we check if the base depends on any value used to construct the secret address, perform a range analysis to infer the minimum, maximum and stride of all the transmission components, and perform an inferable-bits analysis to infer which bits of the secret end up in the transmission and at which position. This comprehensive analysis is crucial for accurate exploitability reasoning. For instance, data-flow information alone is insufficient to determine the controllability requirements to be met. Gadget reasoning. With this information, we can finally reason about each gadget. All the properties found during the analysis, along with a list of registers that the attacker needs to control for each gadget, are saved in a database. We now use a reasoner to model exploitation techniques with database queries. The reasoner inserts columns indicating which gadgets can leak a secret, and, if needed, which techniques are required. For instance, if a gadget has a high secret entropy (i.e., number of transmitted bits > 16), the reasoner checks if we can perform the known-prefix technique (i.e., secret address is attacker-controlled with granularity <= 16 bits). 5.4 Evaluation To evaluate the ability of InSpectre Gadget to uncover a new attack surface, we analyzed the Linux kernel version 6.6-rc4 (latest at time of writing) with the default configuration. By listing all the code locations that contain an endbr instruction and looking at the symbol table, we found a total of 35,212 indirect call targets (have a symbol), and 7,562 indirect jump targets (have no associated symbol). InSpectre Gadget took approximately 14 hours to analyze all indirect branch targets, running on the i9-13900K Intel CPU with 20 cores. We count each unique transmission address as a gadget, so multiple paths leading to the same transmission count as 1 gadget. Additionally, while InSpectre Gadget does not directly output information about reachable gadgets (i.e., those that can be user-triggered through a syscall), we estimate reachability for call targets by cross-referencing the labels with the coverage report generated by Syzkaller [13], a state-of-theart kernel fuzzer. We use the openly-available results from the Syzbot project [12], which runs Syzkaller for 24 hours, finding a total of 14,391 reachable targets. This approach underapproximates the number of reachable gadgets, as the completeness is subject to fuzzing coverage, but it is useful to provide an estimate. Table 1summarizes the gadgets we uncovered. We found a total of 955 and 610 gadgets in kernel indirect call and jump targets (respectively). We manually analyzed 40 randomly sampled gadgets from the list by manually inspecting the assembly code (in approximately 3 hours). After manual analysis, we considered 35 to be exploitable. This shows InSpectre Gadget provides good accuracy, with the few misses caused by imprecise controllability modeling of our current prototype (Section 5.5). Figure 5shows statistics that we can use to estimate the size of the required speculation window, e.g., the number of instructions and branches present in the gadget, or how many dependent loads have to fit in the window to leak a secret. Finally, Table 2presents the number of potential gadgets that were not deemed exploitable by our tool. Gadgets with an invalid base are gadgets where the attacker does not completely control the transmission base, and in particular, for some values of the secret, the transmission address would be invalid, without the attacker being able to compensate by adjusting the transmission base. Gadgets classified as having an invalid secret address do not allow the attacker to choose an arbitrary memory location to leak, and gadgets where no 582 33rd USENIX Security Symposium USENIX Association Table 1: The number of exploitable gadgets found by InSpectre Gadget in indirect call targets and indirect jump targets of the kernel, grouped by technique needed for exploitation. Technique Call Targets Reachable Jump Targets Load Store Load Store Load Store None 14 2 1 1 0 0 Prime+Probe 199 126 64 51 126 17 Sliding 69 30 34 7 208 50 Known Prefix 399 121 107 19 135 110 Base Adjust 7 1 4 1 0 0 (Base Adjust + Known Prefix) (79) (30) (28) (9) (88) (43) Train In-Place 467 210 174 68 153 52 Train OOP 53 10 25 2 130 77 Total 738 288 230 78 471 179 bits of the secret survive before being transmitted, e.g., if the secret is XOR-ed with itself, are classified as Not Inferable. Finally, the labels Secret Too Big,Secret Too Small and Base Alias refer to the problems mentioned in Section 5.2. As mentioned earlier, InSpectre Gadget can be easily extended to support new covert channels. As a demonstration, we added support for both the recent SLAM covert channel [29] and the code-load (i.e., secret-dependent function pointer dereference) covert channel [45]. With our tool, we found ~4x more exploitable gadgets than SLAM’s simple scanner, primarily due to our ability to reason about the exploitability of complex gadgets. The code-load covert channel further revealed over 2,000 SLAM gadgets, although no new traditional gadgets were found. For a more detailed analysis, we refer the reader to Appendix A. 5.5 Limitations As opposed to tools like KASPER [31], InSpectre Gadget is designed to analyze only the content of speculation windows (e.g., call and jump targets for Spectre-v2), whose entry points have to be provided by the analyst. Other aspects needed for end-to-end exploitation, such as the reachability of the target and the presence of a suitable victim branch, are not part of the tool’s output. Nonetheless, in Section 6.1, we show how to construct an end-to-end attack based on the results of our analysis. Moreover, InSpectre Gadget cannot completely prove the absence of gadgets in a given snippet of code. Regarding exploitability results, our current prototype has a number of limitations potentially impacting accuracy. First, our tool is based on ANGR and relies on both its disassembler (CAPSTONE) and constraint solver (Z3). Whenever an error occurs in one of these components, e.g., on unsupported instructions, we have to bail out from the analysis, leaving some symbolic states unexplored. Second, transmissions that conTable 2: The number of potential gadgets marked as “not exploitable” by InSpectre Gadget, broken down by the reason for which they were deemed unexploitable. Problem # of Gadgets # Reachable Load Store Load Store Base Alias 1322 730 502 151 Invalid Base 32651 5619 9270 1391 Invalid Secret Address 412 78 104 11 CMOVE Alias 773 171 246 50 Secret Not Inferable 114 5 59 1 Invalid Transmission 268 56 51 9 Secret Too Big 2045 439 282 159 Secret Too Small 561 67 198 28 Total 34825 6035 9609 1530 tain a complex symbolic expression, e.g., two independentlycontrolled loads used in a XOR operation, cannot be easily unpacked into a base and a transmitted secret, but might still leak a value. We mark these cases as complex and approximate their ranges by querying the SAT solver for the minimum and maximum values of the whole expression and of each sub-expression. We also use this approach when performing range analysis on expressions with complex (symbolic) constraints, whose values cannot be easily reduced to an interval or a small set. For these cases, besides reporting the minimum and the maximum values, we also check if certain bits are always 0 or 1 to approximate the stride. Finally, at the moment our tool models the attacker’s control over complex chains of loads as a binary condition (controlled or not controlled), as opposed to reporting the degree of control as done for transmission components. For complex aliasing cases, this can introduce imprecision (e.g., inaccurate classification of the required exploitation techniques). 6 Native BHI In the previous section, we saw that InSpectre Gadget was able to uncover in the Linux kernel many gadgets that can lead to the transmission of a secret. In this section, we demonstrate how an attacker can use such gadgets to mount an end-to-end Spectre-v2 exploit against the kernel, by presenting the first native BHI attack (without the need of unprivileged eBPF). 6.1 Preliminaries To perform native BHI, an attacker must first trigger the gadget via a syscall to insert its entry in the BTB. As discussed in Section 5.4, we use the reports from Syzkaller to determine which target can be triggered, and how. Note that, since we use valid indirect call targets, the attack is completely unaffected by the eIBRS and IBT mitigations. USENIX Association 33rd USENIX Security Symposium 583 0 20 40 60 Number of Instructions 0 200 400 600 800 Cumulative # of Gadgets Call Jump Reachable 0123456 Number of Branches 0 200 400 600 800 Cumulative # of Gagdets Call Jump Reachable 012345 Number of Loads 0 200 400 600 800 Cumulative # of Gadgets Call Jump Reachable Figure 5: Cumulative distributions of the number of instructions, branches and dependent loads found in disclosure gadgets. In addition, we must choose a victim indirect branch. Attackers need to ensure they control the registers and memory required by the gadget, when the victim call is triggered. To find potential victims, we use ANGR to search for indirect branches from the syscall entry point. Upon detecting an indirect branch, we perform range analysis on attacker-controlled registers. To find attacker-controlled values that require an extra dereference with a small offset, we first query the solver to determine if the expression stored in a register has a single solution. If so, we examine the memory at this address and the adjacent 256 bytes for attacker-controlled values and perform range analysis on them if found. We identified 21 indirect branches across 11 syscalls, each with at least one register under sufficient attacker control to pass a kernel pointer. 6.2 End-To-End Exploit In this section, we show how we craft an end-to-end exploit against the Linux kernel to leak the content of /etc/shadow on the latest Intel CPUs in under two minutes. Figure 6shows a general overview of the attack. Disclosure gadget and victim branch. As a first step, we search for a FLUSH+RELOAD gadget to provide an efficient covert channel, by filtering the database generated by InSpectre Gadget. In particular, we select cgroup_seqfile_show , shown in Listing 2, as our gadget. The corresponding annotated assembly file, generated by InSpectre Gadget, is included in Appendix C. As our victim branch, we choose the kernel syscall handler. When executing this branch, all of the (attacker-controlled) syscall arguments have already been pushed on the stack, while rdi points to the location of these arguments. Since cgroup_seqfile_show loads a value from rdi + 0x70 and uses it to compute all other values, attackers need to control just the first syscall argument when the misprediction occurs. Inserting the BTB entry. To ensure that the CPU mispredicts to our gadget, its address must be injected into the BTB before calling the victim. To this end, we trigger the gadget from userspace exactly once. Manual analysis shows that we call [rax] call [rax] Collision legit target Speculate Leak KernelUser 12 34 <cgroup_seqfile_show> rax = load[rdi+0x70] rax = load[rax]  transmit[rdi+rax*8] [rdi+0x70] controlled read file syscall Figure 6: Workflow for the native BHI exploit. The attacker first triggers an indirect call in kernel 1  , which jumps to cgroup_seqfile_show 2  . Then, a colliding history is executed, and the syscall dispatcher is invoked 3  , which expects the user-provided syscall argument at address rdi+0x70 . Before executing the intended target, the CPU transiently jumps to cgroup_seqfile_show 4  , which dereferences rdi+0x70 and uses its value to construct a transmission. can trigger cgroup_seqfile_show by reading a file in the cgroup directory (/sys/fs/cgroup) from userspace. Increasing the transient window size. The induced transient window must be sufficiently large to fit our transmission. There are various ways to achieve this. In our case, we opted for evicting from the cache the syscall table entry that contains the legitimate target of our victim, making the victim call slow. Our experiments show that evicting the entry from the L2 data cache provides a window that is large enough. Finding the reload buffer. To use FLUSH+RELOAD, there needs to be a shared buffer between the attacker and the victim. We can obtain such a reload buffer by allocating a user page and identifying its corresponding address in the kernel’s direct map of physical memory. However, the map address is not known in advance, and must be leaked. In principle, an attacker can brute-force this address by exploiting BHI to transiently jump to an attacker-controlled load, and check if the load brought the user page into the cache. However, two significant sources of entropy stand in 584 33rd USENIX Security Symposium USENIX Association References [1] BHI and intra-mode BTI. https://www.intel.com/ content/www/us/en/developer/articles/technical/ software-security-guidance/technical-documentation/ branch-history-injection.html. [2] Branch target injection. https://www.intel.com/content/ www/us/en/developer/articles/technical/softwaresecurity-guidance/advisory-guidance/branch-targetinjection.html. [3] Don’t force use of indirect calls for system calls. https://git.kernel.org/pub/scm/ linux/kernel/git/torvalds/linux.git/commit/?id= 1e3ad78334a69b36e107232e337f9d693dcc9df2. [4] Enable kernel IBT by default. https://lore.kernel.org/ lkml/166764458451.4906.10224019690835731804. tip-bot2@tip-bot2/T/. [5] Implement FineIBT. https://git.kernel.org/pub/ scm/linux/kernel/git/torvalds/linux.git/commit/?id= 931ab63664f0. [6] Indirect branch restricted speculation. https://www.intel. com/content/www/us/en/developer/articles/technical/ software-security-guidance/technical-documentation/ indirect-branch-restricted-speculation.html. [7] Indirect branch tracking for Intel CPUs. https://lwn.net/ Articles/889475. [8] Intel research on disclosure gadgets at indirect branch targets in the Linux kernel. https://www.intel.com/ content/www/us/en/developer/articles/news/update-toresearch-on-disclosure-gadgets-in-linux.html. [9] Merge tag ’nativebhi’. https://git.kernel.org/pub/ scm/linux/kernel/git/torvalds/linux.git/commit/?id= 2bb69f5fc72183e1c62547d900f560d0e9334925. [10] Retpoline: A branch target injection mitigation. https://www.intel.com/content/www/us/en/developer/ articles/technical/software-security-guidance/ technical-documentation/retpoline-branch-targetinjection-mitigation.html. [11] Spectre side channels. https://docs.kernel.org/adminguide/hw-vuln/spectre.html#spectre-variant-2-branchtarget-injection. [12] Syzbot. https://syzkaller.appspot.com/. [13] Syzkaller. https://github.com/google/syzkaller. [14] Vulnerability of speculative processors. https: //developer.arm.com/support/arm-security-updates/ speculative-processor-vulnerability. [15] Nadav Amit, Fred Jacobs, and Michael Wei. JumpSwitches: Restoring the performance of indirect branches in the era of Spectre. In USENIX ATC, 2019. [16] Enrico Barberis, Pietro Frigo, Marius Muench, Herbert Bos, and Cristiano Giuffrida. Branch history injection: On the effectiveness of hardware mitigations against Cross-Privilege Spectre-v2 attacks. In USENIX Security, 2022. [17] Atri Bhattacharyya, Andrés Sánchez, Esmaeil M Koruyeh, Nael Abu-Ghazaleh, Chengyu Song, and Mathias Payer. SpecROP: Speculative exploitation of ROP chains. In RAID, 2020. [18] Atri Bhattacharyya, Alexandra Sandulescu, Matthias Neugschwandtner, Alessandro Sorniotti, Babak Falsafi, Mathias Payer, and Anil Kurmus. SMoTherSpectre: Exploiting speculative execution through port contention. In CCS, 2019. [19] Tyler Bletsch, Xuxian Jiang, Vince W. Freeh, and Zhenkai Liang. Jump-oriented programming: A new class of code-reuse attack. In ASIACCS, 2011. [20] Sunjay Cauligi, Craig Disselkoen, Klaus v Gleissenthall, Dean Tullsen, Deian Stefan, Tamara Rezk, and Gilles Barthe. Constant-time foundations for the new Spectre era. In PLDI, 2020. [21] Lesly-Ann Daniel, Sébastien Bardin, and Tamara Rezk. Hunting the haunter-efficient relational symbolic execution for Spectre with haunted relse. In NDSS, 2021. [22] Dmitry Evtyushkin, Ryan Riley, Nael CSE AbuGhazaleh, ECE, and Dmitry Ponomarev. BranchScope: A new side-channel attack on directional branch predictor. In ASPLOS, 2018. [23] Alexander J Gaidis, Joao Moreira, Ke Sun, Alyssa Milburn, Vaggelis Atlidakis, and Vasileios P Kemerlis. FineIBT: Fine-grain control-flow enforcement with indirect branch tracking. ACM 2023, 2023. [24] Enes Göktas, Kaveh Razavi, Georgios Portokalidis, Herbert Bos, and Cristiano Giuffrida. Speculative probing: Hacking blind in the Spectre era. In CCS, 2020. [25] Ben Gras, Kaveh Razavi, Herbert Bos, Cristiano Giuffrida, et al. Translation leak-aside buffer: Defeating cache side-channel protections with TLB attacks. In USENIX Security, 2018. [26] Daniel Gruss, Clémentine Maurice, Anders Fogh, Moritz Lipp, and Stefan Mangard. Prefetch side-channel attacks: Bypassing SMAP and kernel ASLR. In CCS, 2016. USENIX Association 33rd USENIX Security Symposium 591 [27] Daniel Gruss, Clémentine Maurice, Klaus Wagner, and Stefan Mangard. Flush+Flush: A fast and stealthy cache attack, 2016. [28] Marco Guarnieri, Boris Köpf, José F Morales, Jan Reineke, and Andrés Sánchez. Spectector: Principled detection of speculative information flows. In IEEE S&P, 2020. [29] Mathé Hertogh, Sander Wiebing, and Cristiano Giuffrida. Leaky address masking: Exploiting unmasked Spectre gadgets with noncanonical address translation. In IEEE S&P, 2024. [30] Intel. Intel 64 and IA-32 architectures software developer’s manual combined volumes. 2019. [31] Brian Johannesmeyer, Jakob Koschel, Kaveh Razavi, Herbert Bos, and Cristiano Giuffrida. Kasper: scanning for generalized transient execution gadgets in the Linux kernel. In NDSS, 2022. [32] Paul Kocher, Jann Horn, Anders Fogh, Daniel Genkin, Daniel Gruss, Werner Haas, Mike Hamburg, Moritz Lipp, Stefan Mangard, Thomas Prescher, Michael Schwarz, and Yuval Yarom. Spectre attacks: Exploiting speculative execution. In IEEE S&P, 2019. [33] Paul C. Kocher. Timing attacks on implementations of Diffie-Hellman, RSA, DSS, and other systems. In CRYPTO, 1996. [34] Esmaeil Mohammadian Koruyeh, Khaled N. Khasawneh, Chengyu Song, and Nael Abu-Ghazaleh. Spectre returns! speculation attacks using the return stack buffer. In WOOT, 2018. [35] Moritz Lipp, Michael Schwarz, Daniel Gruss, Thomas Prescher, Werner Haas, Anders Fogh, Jann Horn, Stefan Mangard, Paul Kocher, Daniel Genkin, et al. Meltdown: reading kernel memory from user space. In USENIX Security, 2018. [36] Fangfei Liu, Yuval Yarom, Qian Ge, Gernot Heiser, and Ruby B. Lee. Last-level cache side-channel attacks are practical. In IEEE S&P, 2015. [37] Kevin Loughlin, Ian Neal, Jiacheng Ma, Elisa Tsai, Ofir Weisse, Satish Narayanasamy, and Baris Kasikci. DOLMA: Securing speculation with the principle of transient non-observability. In USENIX Security, 2021. [38] Giorgi Maisuradze and Christian Rossow. ret2spec: Speculative execution using return stack buffers. In CCS, 2018. [39] Alyssa Milburn, Ke Sun, and Henrique Kawakami. You cannot always win the race: Analyzing mitigations for branch target prediction attacks. In IEEE EuroS&P, 2023. [40] Oleksii Oleksenko, Bohdan Trach, Mark Silberstein, and Christof Fetzer. SpecFuzz: Bringing Spectre-type vulnerabilities to the surface. In USENIX Security, 2020. [41] Colin Percival. Cache missing for fun and profit. 2005. [42] Zhenxiao Qi, Qian Feng, Yueqiang Cheng, Mengjia Yan, Peng Li, Heng Yin, and Tao Wei. SpecTaint: Speculative taint analysis for discovering Spectre gadgets. In NDSS, 2021. [43] Hany Ragab, Andrea Mambretti, Anil Kurmus, and Cristiano Giuffrida. GhostRace: Exploiting and mitigating speculative race conditions. In USENIX Security, 2024. [44] Joseph Ravichandran, Weon Taek Na, Jay Lang, and Mengjia Yan. PACMAN: Attacking ARM pointer authentication with speculative execution. In ISCA, 2022. [45] Xida Ren, Logan Moody, Mohammadkazem Taram, Matthew Jordan, Dean M. Tullsen, and Ashish Venkat. I see dead µops: Leaking secrets via Intel/AMD micro-op caches. In ISCA, 2021. [46] Hovav Shacham. The geometry of innocent flesh on the bone: Return-into-libc without function calls (on the x86). In CCS, 2007. [47] Dag Arne Osvik Shamir, Adi and Eran Tromer. Cache attacks and countermeasures: the case of AES, 2005. [48] Vedvyas Shanbhogue, Deepak Gupta, and Ravi Sahita. Security analysis of processor instruction set architecture for enforcing control-flow integrity. In S&P, 2019. [49] Youngjoo Shin, Hyung Chan Kim, Dokeun Kwon, Ji Hoon Jeong, and Junbeom Hur. Unveiling hardwarebased data prefetcher, a hidden source of information leakage. In ACM CCS, 2018. [50] Yan Shoshitaishvili, Ruoyu Wang, Christopher Salls, Nick Stephens, Mario Polino, Andrew Dutcher, John Grosen, Siji Feng, Christophe Hauser, Christopher Kruegel, and Giovanni Vigna. (State of) the art of war: Offensive techniques in binary analysis. In IEEE S&P, 2016. [51] Daniël Trujillo, Johannes Wikner, and Kaveh Razavi. Inception: Exposing new attack surfaces with training in transient execution. In USENIX Security, 2023. [52] Stephan Van Schaik, Alyssa Milburn, Sebastian Österlund, Pietro Frigo, Giorgi Maisuradze, Kaveh Razavi, Herbert Bos, and Cristiano Giuffrida. RIDL: Rogue in-flight data load. In IEEE S&P, 2019. 592 33rd USENIX Security Symposium USENIX Association [53] Guanhua Wang, Sudipta Chattopadhyay, Arnab Kumar Biswas, Tulika Mitra, and Abhik Roychoudhury. KLEESPECTRE: Detecting information leakage through speculative cache attacks via symbolic execution. ACM TOSEM, 2020. [54] Johannes Wikner and Kaveh Razavi. RETBLEED: Arbitrary speculative code execution with return instructions. In USENIX Security, 2022. [55] Yuval Yarom and Katrina Falkner. FLUSH+RELOAD: A high resolution, low noise, L3 cache side-channel attack. In USENIX Security, 2014. [56] Hosein Yavarzadeh, Mohammadkazem Taram, Shravan Narayan, Deian Stefan, and Dean Tullsen. Half&Half: Demystifying Intel’s directional branch predictors for fast, secure partitioned execution. In IEEE S&P, 2023. A Extra Covert Channels To demonstrate the flexibility of InSpectre Gadget, we extended the tool to include two extra covert channels, namely the code-load covert channel [45], which requires a secretdependent function pointer, and the recent SLAM covert channel [29]. SLAM leverages Intel’s recently announced Linear Address Masking (LAM) feature, as well as microarchitectural race conditions present on some existing AMD CPUs. Via SLAM, an attacker can leak data via a straightforward dereference of a 64-bit secret, typically a noncanonical address, by transiently bypassing canonicality checks. Supporting SLAM required modifications only in the reasoner, with 83 line changes. The code-load covert channel required even fewer modifications, with only 7 line changes in the scanner. We ran the extended implementation of InSpectre Gadget with the same setup described in Section 5.4. Table 5 presents our results. We count each entry point as a single gadget, in line with SLAM’s definition. The SLAM paper reports a large potential attack surface when scanning the Linux kernel’s indirect call targets (16,046 potential gadgets), but practical exploitability is approximated by pattern-matching simple cases, resulting in 4,194 exploitable gadgets. In contrast, by reasoning on complex gadgets as well, InSpectre Gadget is able to uncover 13,648 SLAM gadgets that pass all exploitability tests in indirect call targets, and a total of 16,287 exploitable SLAM gadgets when considering also indirect jump targets and code-loads. While we did not uncover any new traditional gadgets via the code-load covert channel, we identified 2,856 SLAM gadgets that are exploitable via the code-load covert channel. B FineIBT Case Study Gadget Listing 6presents the assembly code of the unix_poll_gadget, the gadget used in the FineIBT bypass case study. The gadget Table 5: The number of exploitable SLAM gadgets found by InSpectre Gadget in indirect call targets and indirect jump targets of the kernel, grouped by technique needed for exploitation. Counted by the number of indirect entry points with at least one gadget. Technique Call Targets Jump Targets CodeCodeLoad Store load Load Store load Known Prefix 14,840 3,470 2,440 1,981 831 474 Train In-Place 5,285 1,796 1,230 531 308 49 Train OOP 363 174 75 1,132 430 424 Total 14,847 3,485 2,440 1,987 832 474 loads a secret from memory with attacker-controlled register rsi as address. Next, the gadget loads the call target from the attacker-controlled address in rdx and calls it subsequently. The secret is transmitted by the instruction at the call target, selected by the attacker, that performs a load with the secret as an argument and an attacker-controlled value as the base. We selected the instruction movzx ebx, BYTE PTR[r8+rbx] found in the uuid_string function. Listing 6: Assembly of the unix_poll gadget. Linux kernel 6.6-rc4, FineIBT enabled. 1__cfi_unix_poll: 2endbr64 3sub r10d,0x1eb58ddc 4je <unix_poll> 5ud2 6nop 7unix_poll: 8nop WORD PTR [rax] 9push rbp 10 push r14 11 push rbx 12 mov rbx,QWORD PTR [rsi+0x18]; load secret 13 test rdx,rdx 14 je <unix_poll+55> 15 mov r11,QWORD PTR [rdx]; load call target 16 test r11,r11 17 je <unix_poll+55> 18 add rsi,0x40 19 mov r10d,0xd0facb91 20 sub r11,0x10 21 nop DWORD PTR [rax+0x0] 22 call r11; call attacker chosen target C Annotated Assembly Output Figure 10 shows the annotated assembly output of the (cgroup_seqfile_show) gadget used in our exploit. USENIX Association 33rd USENIX Security Symposium 593 ----------------- TRANSMISSION ----------------- cgroup_seqfile_show: ffffffff8114ff30 endbr64 ffffffff8114ff34 push rbp ffffffff8114ff35 mov rax,qword ptr [rdi+0x70] ; {Attacker@rdi} -> {Attacker@0xffffffff8114ff35} ffffffff8114ff39 mov r8,rsi ffffffff8114ff3c mov rbp,rdi ffffffff8114ff3f mov rax,qword ptr [rax] ; {Attacker@0xffffffff8114ff35} -> {Attacker@0xffffffff8114ff3f} ffffffff8114ff42 mov rsi,qword ptr [rax+0x60] ; {Attacker@0xffffffff8114ff3f} -> {Attacker@0xffffffff8114ff42} ffffffff8114ff46 mov rdx,qword ptr [rax+0x8] ; {Attacker@0xffffffff8114ff3f} -> {Attacker@0xffffffff8114ff46} ffffffff8114ff4a mov rax,qword ptr [rsi+0x58] ; {Attacker@0xffffffff8114ff42} -> {Attacker@0xffffffff8114ff4a} ffffffff8114ff4e mov rdi,qword ptr [rdx+0x60] ; {Attacker@0xffffffff8114ff46} -> {Attacker@0xffffffff8114ff4e} ffffffff8114ff52 test rax,rax ffffffff8114ff55 je 0xffffffff8114ff67 ; Not Taken <Bool LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 rdi + 0x70>]_21>]_22 + 0x60>]_23 + 0x58>]_25 != 0x0> ffffffff8114ff57 movsxd rax,dword ptr [rax+0x9c] ; {Attacker@0xffffffff8114ff4a} -> {Secret@0xffffffff8114ff57} ffffffff8114ff62 mov rdi,qword ptr [rdi+rax*0x8+0x8] ; {Attacker@0xffffffff8114ff4e, Secret@0xffffffff8114ff57} -> TRANSMISSION ffffffff8114ff67 mov rax,qword ptr [rsi+0x98] ffffffff8114ff6e test rax,rax ffffffff8114ff71 je 0xffffffff8114ff7f  ------------------------------------------------ uuid: 5bb996d2-d414-4452-a858-c2d306eedb9a transmitter: TransmitterType.LOAD Secret Address: - Expr: LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x60]_23 + 0x58]_25 + 0x9c - Range: (0x0,0xffffffffffffffff,0x1) Exact: True Transmitted Secret: - Expr: (0#32 .. LOAD_32[ LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x60]_23 + 0x58]_25 + 0x9c]_27) << 0x3 - Range: (0x0,0x3fffffff8,0x8) Exact: True - Spread: 3 - 34 - Number of Bits Inferable: 32 Base: - Expr: LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x8]_24 + 0x60]_26 + 0x178 - Range: (0x0,0xffffffffffffffff,0x1) Exact: True - Independent Expr: LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x8]_24 + 0x60]_26 + 0x178 - Independent Range: (0x0,0xffffffffffffffff,0x1) Exact: True Transmission: - Expr: 0x8 + LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x8]_24 + 0x60]_26 + (0x170 + ((0#32 .. LOAD_32[ LOAD_64[ LOAD_64[ LOAD_64[ LOAD_64[ rdi + 0x70]_21]_22 + 0x60]_23 + 0x58]_25 + 0x9c]_27) << 0x3)) - Range: (0x0,0xffffffffffffffff,0x1) Exact: False Register Requirements: { rdi } Constraints: [('0xffffffff8114ff57', <Bool LOAD_32[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 rdi + 0x70]_21]_22 + 0x60]_23 + 0x58]_25 + 0x9c]_27[31:31] == 0, 'ConditionType.SIGN_EXT')] Branches: [('0xffffffff8114ff55', <Bool LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 LOAD_64[<BV64 rdi + 0x70]_21]_22 + 0x60]_23 + 0x58]_25 != 0x0 , 'Not Taken')] ------------------------------------------------ 1 2 3 4 5 6 6 7 6 8 6 9 Figure 10: Annotated assembly file generated by InSpectre Gadget. Right to the assembly instructions, we output the annotations attached to the source and destination operands (source → destination). The annotations include the origin of the value, which is either the instruction pointer of the source load or a register (e.g., @rdi ). As we generate for each detected gadget an annotated assembly file, we do not print annotations that are irrelevant to the gadget flow and we replace all secret annotations with an attacker annotation that are, for this specific gadget, not used as a secret but as an attacker-controlled value. In the case of a branch instruction, we show the branch condition to hold instead. As shown by the annotations, the attacker-controlled value rdi is used in the first load 1  , followed by a series of loads whose controllability is tracked 2  . The encountered branch condition is recorded 3  . Subsequently, the secret value is loaded from an attacker-controlled value 4  and transmitted using an attacker-controlled value as the base 5  . We output key details after the assembly code, including the symbolic expression and the range—i.e., (min, max, stride)—for each transmission component 6  , insights about the transmitted secret bits 7 , details about which registers an attacker should control to exploit the gadget 8 as well as the constraints and branches encountered 9 . 594 33rd USENIX Security Symposium USENIX Association