{"id":337,"date":"2026-03-14T06:33:11","date_gmt":"2026-03-14T06:33:11","guid":{"rendered":"https:\/\/haco.club\/?p=337"},"modified":"2026-03-14T06:33:11","modified_gmt":"2026-03-14T06:33:11","slug":"black-hat-usa-2025-breaking-control-flow-integrity-by-abusing-modern-c","status":"publish","type":"post","link":"https:\/\/haco.club\/?p=337","title":{"rendered":"Black Hat USA 2025 | Breaking Control Flow Integrity by Abusing Modern C++"},"content":{"rendered":"\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Black Hat USA 2025 | Breaking Control Flow Integrity by Abusing Modern C++\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/hxIPoi4ONNA?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><strong>&#8220;Coroutine Frame-Oriented Programming: Breaking Control Flow Integrity by Abusing Modern C++&#8221;<\/strong>&nbsp;by Marcos Bajo:<\/p>\n\n\n\n<p><strong>Overview<\/strong><br>The presentation introduces a novel exploitation technique called&nbsp;<strong>Coroutine Frame-Oriented Programming (CFOP)<\/strong>. It demonstrates how attackers can leverage C++20 coroutines to completely bypass modern Control Flow Integrity (CFI) defenses (such as Intel CET and Microsoft CFG) that are designed to prevent code-reuse attacks like ROP (Return-Oriented Programming).<\/p>\n\n\n\n<p><strong>Key Concepts &amp; Background<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Control Flow Integrity (CFI):<\/strong>\u00a0A defense mechanism that prevents attackers from redirecting a program&#8217;s execution flow by enforcing valid transition paths for indirect jumps and calls.<\/li>\n\n\n\n<li><strong>C++20 Coroutines:<\/strong>\u00a0Coroutines are functions that can pause (suspend) and resume execution (using keywords like\u00a0co_await,\u00a0co_yield, and\u00a0co_return). Because they must remember their state between suspensions, C++ compilers implement them as\u00a0<strong>stackless coroutines<\/strong>, storing all local variables, parameters, and special control pointers (the\u00a0resume\u00a0and\u00a0destroy\u00a0pointers) in a\u00a0<strong>heap-allocated Coroutine Frame<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p><strong>The Vulnerability<\/strong><br>The core weakness lies in how compilers currently generate code for coroutines:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Writable Metadata:<\/strong>\u00a0The Coroutine Frame is allocated on the heap, meaning all of its vital data\u2014including function pointers and local variables\u2014resides in writable memory.<\/li>\n\n\n\n<li><strong>Lack of CFI Instrumentation:<\/strong>\u00a0Modern CFI schemes often fail to instrument the\u00a0resume\u00a0and\u00a0destroy\u00a0pointers generated by the compiler inside the coroutine frame. As a result, indirect jumps using these pointers are completely unchecked by defenses like Intel CET or CFG.<\/li>\n<\/ol>\n\n\n\n<p><strong>Attack Techniques (CFOP)<\/strong><br>Assuming an attacker has bypassed ASLR and has a memory corruption vulnerability (like an arbitrary memory write or a heap-based overflow), they can launch two main types of attacks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Data-Only Attacks (DOAs):<\/strong>\u00a0Because coroutine local variables are moved from the stack to the heap-allocated frame, they are stripped of typical stack protections (like stack canaries). An attacker can overwrite local variables, parameters, or internal state indices to manipulate program logic or achieve arbitrary memory frees\/reads without ever hijacking the control flow.<\/li>\n\n\n\n<li><strong>Control Flow Hijacking (Infinite Coroutine Chaining &#8211; ICC):<\/strong>\u00a0By injecting fake coroutine frames into memory or overwriting existing ones, an attacker can hijack the uninstrumented\u00a0resume\u00a0or\u00a0destroy\u00a0pointers.\n<ul class=\"wp-block-list\">\n<li><em>Chaining:<\/em>\u00a0Attackers can abuse &#8220;continuation points&#8221; (how one coroutine knows to resume another after an\u00a0await\u00a0finishes) to chain an infinite sequence of arbitrary function calls.<\/li>\n\n\n\n<li><em>Argument Passing:<\/em>\u00a0Because the Coroutine Frame pointer is naturally passed via the\u00a0rdi\u00a0register (which is also used as the\u00a0this\u00a0pointer in C++ class methods), attackers can easily pass arbitrary arguments to their hijacked functions by creating memory &#8220;collisions&#8221; with fake objects.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>Demonstration &amp; Defenses<\/strong><br>The speaker successfully demonstrated the CFOP attack against the SerenityOS browser, chaining uninstrumented coroutine calls to gain remote code execution despite CFI protections being active.<\/p>\n\n\n\n<p><strong>Proposed Mitigations:<\/strong><br>To fix this architectural flaw, compilers must be updated. The presenter suggests:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Moving\u00a0resume\u00a0and\u00a0destroy\u00a0function pointers into read-only memory and accessing them via a read-only jump table using a coroutine identifier.<\/li>\n\n\n\n<li>Relying on\u00a0<strong>HALO (Heap Allocation Elision Optimization)<\/strong>, an existing but highly fragile compiler optimization that moves coroutine frames from the heap back to the stack. While HALO inadvertently breaks this attack, it currently requires strict conditions (like LTO enabled) to trigger and is poorly supported across major compilers (GCC, Clang, MSVC).<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Coroutine Frame-Oriented Programming: Breaking Control Flow Integrity by Abusing Modern [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[30,5],"class_list":["post-337","post","type-post","status-publish","format-standard","hentry","category-black-hat","tag-binary","tag-security"],"_links":{"self":[{"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/posts\/337","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/haco.club\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=337"}],"version-history":[{"count":1,"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/posts\/337\/revisions"}],"predecessor-version":[{"id":338,"href":"https:\/\/haco.club\/index.php?rest_route=\/wp\/v2\/posts\/337\/revisions\/338"}],"wp:attachment":[{"href":"https:\/\/haco.club\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/haco.club\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/haco.club\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}