<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="https://blog.bl4nk.kr/feed_style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <tabi:metadata xmlns:tabi="https://github.com/welpo/tabi">
        <tabi:base_url>https://blog.bl4nk.kr</tabi:base_url>
        <tabi:separator>
            •
        </tabi:separator>
        <tabi:about_feeds>
            This is a web feed, also known as an Atom feed. Subscribe by copying the URL from the address bar into your newsreader. Visit About Feeds to learn more and get started. It's free.
        </tabi:about_feeds>
        <tabi:visit_the_site>
            Visit website
        </tabi:visit_the_site>
        <tabi:recent_posts>
            Recent posts
        </tabi:recent_posts>
        <tabi:last_updated_on>
            Updated on $DATE
        </tabi:last_updated_on>
        <tabi:default_theme></tabi:default_theme>
        <tabi:post_listing_date>date</tabi:post_listing_date>
        <tabi:current_section>cve</tabi:current_section>
    </tabi:metadata><link rel="extra-stylesheet" href="https://blog.bl4nk.kr/skins/lavender.css?h=31ee0a710ed660d122f6" /><title>~/bl4nk - cve</title>
        <subtitle>fill in the bl4nk</subtitle>
    <link href="https://blog.bl4nk.kr/tags/cve/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://blog.bl4nk.kr/tags/cve/" rel="alternate" type="text/html"/>
    <generator uri="https://www.getzola.org/">Zola</generator><updated>2025-05-06T00:00:00+00:00</updated><id>https://blog.bl4nk.kr/tags/cve/atom.xml</id><entry xml:lang="en">
        <title>[CVE-2020-1054] Win32k LPE Vulnerability Analysis</title>
        <published>2025-05-06T00:00:00+00:00</published>
        <updated>2025-05-06T00:00:00+00:00</updated>
        <author>
            <name>bl4nk</name>
        </author>
        <link rel="alternate" href="https://blog.bl4nk.kr/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/" type="text/html"/>
        <id>https://blog.bl4nk.kr/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/</id>
        
            <content type="html">&lt;h2 id=&quot;0x00-introduction&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#0x00-introduction&quot; aria-label=&quot;Anchor link for: 0x00-introduction&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
0x00. Introduction&lt;/h2&gt;
&lt;p&gt;CVE-2020-1054 is an Elevation of Privilege (EoP) vulnerability in &lt;code&gt;Win32k.sys&lt;/code&gt;, the Windows kernel graphics component. It was reported by Netanel Ben-Simon and Yoav Alon of Check Point Research, and bee13oy of Qihoo 360 Vulcan Team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This post is based on &lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://0xeb-bp.com/blog/2020/06/15/cve-2020-1054-analysis.html&quot;&gt;0xeb-bp’s analysis report&lt;/a&gt; and was written to enhance my own understanding of the vulnerability.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;0x01-root-cause-analysis&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#0x01-root-cause-analysis&quot; aria-label=&quot;Anchor link for: 0x01-root-cause-analysis&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
0x01. Root Cause Analysis&lt;/h2&gt;
&lt;h3 id=&quot;crash-analysis&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#crash-analysis&quot; aria-label=&quot;Anchor link for: crash-analysis&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Crash Analysis&lt;/h3&gt;
&lt;p&gt;This vulnerability was identified by a &lt;code&gt;PAGE_FAULT_IN_NONPAGED_AREA&lt;/code&gt; crash within the &lt;code&gt;win32k!vStrWrite01&lt;/code&gt; function. The code that triggered the crash is as follows:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt; argc&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; char&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; *&lt;/span&gt;&lt;span class=&quot;z-l-9 z-d-12&quot;&gt;argv&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;[]&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt;    LoadLibrary&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;user32.dll&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    HDC r0 &lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt; CreateCompatibleDC&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; CPR&amp;#39;s original crash code called CreateCompatibleBitmap as follows&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; HBITMAP r1 = CreateCompatibleBitmap(r0, 0x9f42, 0xa);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; however all following calculations/reversing in this blog will &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; generally use the below call, unless stated otherwise&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; this only matters if you happen to be following along with WinDbg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    HBITMAP r1 &lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt; CreateCompatibleBitmap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;r0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;51500&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;100&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt;    SelectObject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;r0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; r1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-6 z-d-7&quot;&gt;    DrawIconEx&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;r0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;30000010003&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;fffffffffebffffc&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;        0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;6&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;    return&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The bugcheck result upon crashing is:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;PAGE_FAULT_IN_NONPAGED_AREA (50)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Invalid system memory was referenced.  This cannot be protected by try-except.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Typically the address is just plain bad or it is pointing at freed memory.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Arguments:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Arg1: fffff904c7000240, memory referenced.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Arg2: 0000000000000000, value 0 = read operation, 1 = write operation.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Arg3: fffff960000a5482, If non-zero, the instruction address which referenced &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    the bad memory address.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Arg4: 0000000000000005, (reserved)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Some register values may be zeroed or incorrect.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rax=fffff900c7000000 rbx=0000000000000000 rcx=fffff904c7000240&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rdx=fffff90169dd8f80 rsi=0000000000000000 rdi=0000000000000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rip=fffff960000a5482 rsp=fffff880028f3be0 rbp=0000000000000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; r8=00000000000008f0  r9=fffff96000000000 r10=fffff880028f3c40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r11=000000000000000b r12=0000000000000000 r13=0000000000000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;r14=0000000000000000 r15=0000000000000000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;iopl=0         nv up ei ng nz na po cy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;win32k!vStrWrite01+0x36a:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fffff960`000d5482 418b36   mov esi,dword ptr [r14] ds:00000000`00000000=????????&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The crash occurs because the memory address pointed to by the &lt;code&gt;r14&lt;/code&gt; register (&lt;code&gt;0xfffff904`c7000240&lt;/code&gt;) is invalid. &lt;code&gt;r14&lt;/code&gt; is used as the destination address for a write operation. Let’s examine how this address is calculated and if it is controllable.&lt;/p&gt;
&lt;h3 id=&quot;oob-control&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#oob-control&quot; aria-label=&quot;Anchor link for: oob-control&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
OOB Control&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;r14&lt;/code&gt; is calculated using the instruction &lt;code&gt;lea r14, [rcx + rax*4]&lt;/code&gt;. Tracking &lt;code&gt;rcx&lt;/code&gt; and &lt;code&gt;rax&lt;/code&gt; back, we can represent it in pseudo-code:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var_64h = 0x7fffffff; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var_6ch = 0x80000000;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;while ( r11d )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    --r11d;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if ( ebp &amp;gt;= var_6ch &amp;amp;&amp;amp; ebp &amp;lt; var_6ch )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        // oob read/write in here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ++ebp;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ecx += eax;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ultimately, the target address (&lt;code&gt;oob_target&lt;/code&gt;) takes the form of a linear equation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;oob_target = initial_value + loop_iterations * eax&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Through analysis, such as changing argument values during function calls, we can see that each variable is controlled as follows. However, it was noted that no matter how the values were changed, the lower 32 bits of &lt;code&gt;oob_target&lt;/code&gt; were fixed at &lt;code&gt;0xc7000240&lt;/code&gt;, and only the upper 32 bits were controllable.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;loop_iterations&lt;/strong&gt;: Determined by the 5th argument (&lt;code&gt;arg5&lt;/code&gt;) of &lt;code&gt;DrawIconEx&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;loop_iterations = ((1 - arg5) &amp;amp; 0xffffffff) // 0x30&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;eax (increment)&lt;/strong&gt;: Determined by the 1st argument (&lt;code&gt;arg1&lt;/code&gt;) of &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt;.
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lDelta = arg1 // 8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Acts as the offset to move to the next line in memory.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now that &lt;strong&gt;where to write&lt;/strong&gt; is determined, we need to check &lt;strong&gt;what to write&lt;/strong&gt;—what values can be written and how much control we have over them. Examining &lt;code&gt;vStrWrite01&lt;/code&gt; closely reveals that write instructions are executed in the following two places:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// write 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;win32k!vStrWrite01+0x417&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mov     dword ptr [r14],esi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;// write 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;win32k!vStrWrite01+0x461&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;mov     dword ptr [r14],esi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;esi&lt;/code&gt; value undergoes an &lt;strong&gt;OR&lt;/strong&gt; or &lt;strong&gt;AND&lt;/strong&gt; operation with a certain value depending on conditions. Since &lt;strong&gt;OR&lt;/strong&gt; operations are typically used in exploits to increase values or set specific bits, understanding the condition is crucial. The 8th argument of &lt;code&gt;DrawIconEx&lt;/code&gt;, &lt;code&gt;diFlags&lt;/code&gt;, stood out. Checking the official documentation revealed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;DrawIconEx&lt;/code&gt;’s 8th argument (&lt;code&gt;diFlags&lt;/code&gt;) is &lt;code&gt;DI_IMAGE (0x6)&lt;/code&gt;, an &lt;strong&gt;AND&lt;/strong&gt; operation is performed.&lt;/li&gt;
&lt;li&gt;If &lt;code&gt;DrawIconEx&lt;/code&gt;’s 8th argument (&lt;code&gt;diFlags&lt;/code&gt;) is &lt;code&gt;DI_MASK (0x1)&lt;/code&gt;, an &lt;strong&gt;OR&lt;/strong&gt; operation is performed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a result of the analysis, this OOB write vulnerability has unique constraints:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fixed Lower 32 bits&lt;/strong&gt;: The upper 32 bits of the &lt;code&gt;oob_target&lt;/code&gt; address can be controlled via &lt;code&gt;arg5&lt;/code&gt;, but the &lt;strong&gt;lower 32 bits are always fixed to a specific value like &lt;code&gt;0xc7000240&lt;/code&gt;&lt;/strong&gt;. This means the attacker cannot write to an arbitrary address but only to specific locations where the lower address matches.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restricted Write (Bitwise Operation)&lt;/strong&gt;: Instead of overwriting with a desired value, an &lt;strong&gt;AND&lt;/strong&gt; or &lt;strong&gt;OR&lt;/strong&gt; operation is performed on the existing value.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;0x02-exploit&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#0x02-exploit&quot; aria-label=&quot;Anchor link for: 0x02-exploit&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
0x02. Exploit&lt;/h2&gt;
&lt;p&gt;Due to the aforementioned constraints (fixed lower address, bitwise OR operation), conventional exploitation methods are difficult. However, remembering that even a 1-byte NULL overflow (House of Einherjar) allows for exploitation gives us hope. To overcome this, we utilize the &lt;code&gt;SURFOBJ&lt;/code&gt; structure, a Windows kernel bitmap object.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;typedef&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 dhsurf&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x00&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 hsurf&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x08&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 dhpdev&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 hdev&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x18&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    SIZEL sizlBitmap&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 cjBits&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x28&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 pvBits&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x30&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG64 pvScan0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x38&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG32 lDelta&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG32 iUniq&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x44&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ULONG32 iBitmapFormat&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x48&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    USHORT iType&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x4C&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    USHORT fjBitmap&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; 0x4E&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;span&gt; SURFOBJ64&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; sizeof = 0x50&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The fields critical for exploitation are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pvScan0&lt;/code&gt;: Pointer to the actual bitmap data.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sizlBitmap&lt;/code&gt;: Defines the width and height of the bitmap, consisting of two dwords.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;step-1-heap-grooming&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#step-1-heap-grooming&quot; aria-label=&quot;Anchor link for: step-1-heap-grooming&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Step 1. Heap Grooming&lt;/h3&gt;
&lt;p&gt;First, allocate a base &lt;code&gt;SURFOBJ&lt;/code&gt; to be placed at &lt;code&gt;0xfffff900`c7000000&lt;/code&gt;. Then, repeatedly call &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt; to allocate multiple &lt;code&gt;SURFOBJ&lt;/code&gt; structures and bitmap data in the kernel heap (Paged Pool).&lt;/p&gt;
&lt;p&gt;The goal is to groom the heap so that one of them (Target A) is allocated exactly at &lt;code&gt;0xfffff901`c7000000&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.bl4nk.kr/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/image.png&quot; alt=&quot;step 1&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-2-target-selection-oob-write&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#step-2-target-selection-oob-write&quot; aria-label=&quot;Anchor link for: step-2-target-selection-oob-write&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Step 2. Target Selection &amp;amp; OOB Write&lt;/h3&gt;
&lt;p&gt;We are targeting the &lt;code&gt;sizlBitmap&lt;/code&gt; field of Target B. This field defines the width/height of the bitmap. If this value becomes large, the kernel is tricked into thinking Target B is very large.&lt;/p&gt;
&lt;p&gt;Matching Target B’s &lt;code&gt;sizlBitmap&lt;/code&gt; field exactly with &lt;code&gt;oob_target&lt;/code&gt; is tricky. If we don’t manipulate &lt;code&gt;sizlBitmap&lt;/code&gt; precisely in a single write, a BSOD is likely to occur. Therefore, we need to carefully combine the arguments of &lt;code&gt;DrawIconEx&lt;/code&gt; and &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt;. A brute force script was used to find this combination:&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;bruting function arguments...&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; start with size at 0x50000 &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;for&lt;/span&gt;&lt;span&gt; size&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; in&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;50000&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;ffffff&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lDelta&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; =&lt;/span&gt;&lt;span&gt; size&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;8&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt;    #&lt;/span&gt;&lt;span class=&quot;z-l-5 z-d-3&quot;&gt; lDelta is always byte alligned so ignore if not&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;    if&lt;/span&gt;&lt;span&gt; lDelta&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; &amp;amp;&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0f&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; ==&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; 0&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;        for&lt;/span&gt;&lt;span&gt; arg1&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; in&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;fff&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            offset&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; =&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;arg1&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; //&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;20&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; *&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; +&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;240&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;            for&lt;/span&gt;&lt;span&gt; arg2&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; in&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt; range&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                write_target&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; =&lt;/span&gt;&lt;span&gt; offset&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; +&lt;/span&gt;&lt;span&gt; arg2&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; *&lt;/span&gt;&lt;span&gt; lDelta&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;                if&lt;/span&gt;&lt;span&gt; write_target&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; ==&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt; 0x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;70038&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;                    print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;found: size &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;:x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;, offset (arg1) &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;:x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;, lDelta &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;:x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;\&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;                    loop_count (arg2) &lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;z-l-8 z-d-10&quot;&gt;:x&lt;/span&gt;&lt;span class=&quot;z-l-1 z-d-4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;z-l-2 z-d-6&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; arg1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; lDelta&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt; arg2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.bl4nk.kr/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/image-1.png&quot; alt=&quot;step 2&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-3-relative-read-write&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#step-3-relative-read-write&quot; aria-label=&quot;Anchor link for: step-3-relative-read-write&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Step 3. Relative Read/Write&lt;/h3&gt;
&lt;p&gt;Now, Target B bitmap can access memory beyond its allocated region.
Immediately following Target B, another bitmap structure, Target C, should be located.&lt;/p&gt;
&lt;p&gt;Calling &lt;code&gt;SetBitmapBits(Target B, ...)&lt;/code&gt; allows us to overwrite the &lt;code&gt;pvScan0&lt;/code&gt; field of Target C by overflowing from Target B’s data area.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.bl4nk.kr/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/image-2.png&quot; alt=&quot;step 3&quot; /&gt;&lt;/p&gt;
&lt;h3 id=&quot;step-4-arbitrary-read-write&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#step-4-arbitrary-read-write&quot; aria-label=&quot;Anchor link for: step-4-arbitrary-read-write&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Step 4. Arbitrary Read/Write&lt;/h3&gt;
&lt;p&gt;Now, full AAR/AAW is possible using the Target C bitmap.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Set Where&lt;/strong&gt;: Use Target B (Manager) to change Target C’s (Worker) &lt;code&gt;pvScan0&lt;/code&gt; to the desired address.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do What&lt;/strong&gt;: Call &lt;code&gt;GetBitmapBits&lt;/code&gt; or &lt;code&gt;SetBitmapBits&lt;/code&gt; using Target C (Worker) to read or write values of the kernel memory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This completes the &lt;strong&gt;Arbitrary Read/Write Primitive&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;step-5-token-stealing&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#step-5-token-stealing&quot; aria-label=&quot;Anchor link for: step-5-token-stealing&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
Step 5. Token Stealing&lt;/h3&gt;
&lt;p&gt;With AAR/AAW secured, the rest follows standard techniques.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find the current process (&lt;code&gt;EPROCESS&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Find the System process (PID 4) (&lt;code&gt;EPROCESS&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Read the &lt;code&gt;Token&lt;/code&gt; value from the System process and overwrite the current process’s &lt;code&gt;Token&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The current process now has System privileges.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;0x03-conclusion&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#0x03-conclusion&quot; aria-label=&quot;Anchor link for: 0x03-conclusion&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
0x03. Conclusion&lt;/h2&gt;
&lt;p&gt;This vulnerability stems from a combination of complex address calculation logic within the &lt;code&gt;DrawIconEx&lt;/code&gt; graphics function and a lack of argument validation. It demonstrates a creative exploit technique that transforms a restricted OOB write (fixed lower address, bitwise operation) into a powerful AAR/AAW by manipulating &lt;code&gt;SURFOBJ&lt;/code&gt; structures.&lt;/p&gt;
&lt;p&gt;On Windows 7, structure offsets may vary depending on installed security updates (KB), so exploits must detect this dynamically or be adjusted for the specific version.&lt;/p&gt;
&lt;h2 id=&quot;0x04-reference&quot;&gt;&lt;a class=&quot;header-anchor no-hover-padding&quot; href=&quot;#0x04-reference&quot; aria-label=&quot;Anchor link for: 0x04-reference&quot;&gt;&lt;span class=&quot;link-icon&quot; aria-hidden=&quot;true&quot;&gt;&lt;/span&gt;&lt;/a&gt;
0x04. Reference&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://0xeb-bp.com/blog/2020/06/15/cve-2020-1054-analysis.html&quot;&gt;CVE-2020-1054 Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/0xeb-bp/cve-2020-1054&quot;&gt;CVE-2020-1054 PoC (in Rust)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://github.com/KaLendsi/CVE-2020-1054&quot;&gt;CVE-2020-1054 PoC (in C)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap&quot;&gt;CreateCompatibleBitmap function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawiconex&quot;&gt;DrawIconEx function&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&quot;external&quot; rel=&quot;external&quot; href=&quot;https://www.coresecurity.com/core-labs/articles/abusing-gdi-for-ring0-exploit-primitives&quot;&gt;Abusing GDI for ring0 exploit primitives&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
        <summary type="html">Detailed analysis of OOB Write vulnerability in Win32k.sys and exploitation technique using SURFOBJ</summary>
        </entry>
</feed>
