Connect and corrupt:
C++ coroutines prone to code-reuse attack despite CFI
Devising a novel code-reuse attack, the CISPA-researchers Marcos Sanchez Bajo and Professor Dr. Christian Rossow have demonstrated that all existing implementations of C++ coroutines can be exploited to bypass state-of-the-art CFI protections in both Linux and Windows. Called Coroutine Frame-Oriented Programming (CFOP), the attack results in a corruption of heap memory, allowing attackers to manipulate data and assume complete control over applications. A relatively recent addition to C++, coroutines are already present in more than 130 unique popular GitHub repositories. “They’re being used to pause and resume functions”, Bajo explains, “which is very useful for asynchronous programming, for example in servers, databases and web browsers.”
Connecting C++ coroutine functions to corrupt heap memory
In more concrete terms, coroutines can, for instance, be used to create generators that produce a sequence of elements. Imagine a Fibonacci series, where each new number in the series is the sum of the two numbers that have gone before. After each new number in the series, the coroutine is paused until it is called to generate the next one. In CFOP, entire C++ coroutines and other existing functions are used to create a code-reuse attack, as Bajo explains: “With code-reuse attacks in general, attackers take snippets of code that belong to the application anyway, so no new code is injected. They then form chains of these code snippets to manipulate the program’s execution flow. But bypassing CFI protections is a little more difficult. Instead of just taking snippets of code and creating chains, you have to take full coroutine functions and connect them in smart ways.” Once the CFI protections are circumvented by hijacking a coroutine function in this manner, any other existing function can be submitted to a code-reuse attack.
CFI schemes fail to protect C++ coroutines
Introduced to protect against code-reuse attacks, CFI schemes ensure that the correct program execution flow is observed. Programming languages, however, evolve dynamically, while CFI schemes only protect the programming paradigms that were present at the time of their creation, as Bajo points out: “The main problem with CFI is that this defense is static in time, meaning that it only covers the possibilities of a programming language as is. If new features are introduced to the programming language later on, CFI does not recognize them and cannot deal with them because it was created based on an older version of the programming language.” In their study, Bajo and Rossow found that only 7 out of the 15 CFI schemes they considered initially were compatible with coroutines. Of these 7, only 2 (IBT and Control Flow Guard) provided partial protection against the exploitation of coroutines, while the remaining 5 provided none. “In the end”, Bajo summarizes, “we were able to bypass all of them. With CFOP, you can still do all the things that were possible previous to CFI.”
Patching CFOP is a structural issue
The fact that C++ coroutines are enjoying increasing popularity exacerbates the potential reach of CFOP. Bajo says: “Coroutines were introduced to C++ in 2020 and, since then, developers have been using them more and more. Unfortunately, we found that coroutines have certain structures in memory that can be targeted by attackers. To the best of our knowledge, this has not yet been exploited in real life.” Essentially, CFOP is possible because the three major compilers implement C++ coroutines in a way that renders them structurally vulnerable. Bajo says: “Mitigating this exploitation technique is not as easy as patching the code – this is a structural issue and you need to rethink how the application works internally.” Bajo and Rossow have developed successful implementation alternatives for C++ coroutines and reported these mitigations to Clang/LLVM, GCC and MVSC in November 2024. The CISPA research on CFOP will be presented at the Black Hat USA in Las Vegas on August 7, 2025.
Further information:
Further information on Coroutine Frame-Oriented Programming (CFOP) is available at https://syssec.cispa.io/coroutine-cfop/
Scientific contact:
Marcos Sanchez Bajo and Prof. Dr. Christian Rossow
CISPA Helmholtz Center for Information Security
Stuhlsatzenhaus 5
66123 Saarbrücken, Germany
marcos.sanchez-bajo@cispa.de / rossow@cispa.de
Academic publication:
Sanchez Bajo, Marcos; Rossow, Christian (2025) “Await() a Second: Evading Control Flow Integrity by Hijacking C++ Coroutines” In: 34th Usenix Security Symposium (USENIX-Security), 13-15 Aug 2025, Seattle, WA, USA. https://doi.org/10.60882/cispa.28718642.v1