<?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="ko">
    <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>
            이것은 웹 피드이며, Atom 피드로도 알려져 있습니다. 주소 표시 줄의 URL을 뉴스 리더로 복사하여 구독하세요. About Feeds를 방문하여 자세히 알아보고 시작하세요. 무료입니다.
        </tabi:about_feeds>
        <tabi:visit_the_site>
            웹사이트 방문하기
        </tabi:visit_the_site>
        <tabi:recent_posts>
            최근 게시물
        </tabi:recent_posts>
        <tabi:last_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/ko/tags/cve/atom.xml" rel="self" type="application/atom+xml"/>
    <link href="https://blog.bl4nk.kr/ko/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/ko/tags/cve/atom.xml</id><entry xml:lang="ko">
        <title>[CVE-2020-1054] Win32k LPE 취약점 분석</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/ko/blog/cve-2020-1054-win32k-lpe-vulnerability-analysis/" type="text/html"/>
        <id>https://blog.bl4nk.kr/ko/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는 Windows 커널 그래픽 컴포넌트인 &lt;code&gt;Win32k.sys&lt;/code&gt;에서 발생하는 권한 상승(Elevation of Privilege) 취약점이다. Check Point Research의 Netanel Ben-Simon, Yoav Alon과 Qihoo 360 Vulcan Team의 bee13oy에 의해 보고되었다.&lt;/p&gt;
&lt;p&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;0xeb-bp의 분석 보고서&lt;/a&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;이 취약점은 &lt;code&gt;win32k!vStrWrite01&lt;/code&gt; 함수 내부에서 &lt;code&gt;PAGE_FAULT_IN_NONPAGED_AREA&lt;/code&gt; 크래시를 발생시키며 확인되었다. 크래시가 발생한 코드는 다음과 같다.&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;크래시 발생 시 bugcheck 결과는 다음과 같다.&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;여기서 &lt;code&gt;r14&lt;/code&gt; 레지스터가 가리키는 메모리 주소(&lt;code&gt;0xfffff904`c7000240&lt;/code&gt;)가 유효하지 않아 크래시가 발생한다. &lt;code&gt;r14&lt;/code&gt;는 쓰기 작업의 타겟 주소(Destination)로 사용되는데, 이 주소가 어떻게 계산되는지, 컨트롤 가능한지 살펴보자.&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;는 다음과 같은 &lt;code&gt;lea r14, [rcx + rax*4]&lt;/code&gt; 명령어로 계산된다. 다시 &lt;code&gt;rcx&lt;/code&gt;와 &lt;code&gt;rax&lt;/code&gt;를
추적하기 위해 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;결국 타겟 주소(&lt;code&gt;oob_target&lt;/code&gt;)는 다음과 같은 1차 방정식 꼴이 된다.&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;함수 호출 시 인자값을 바꾸는 등 분석을 통해 각 변수는 다음과 같이 제어된다는 사실을 알 수 있다. 하지만 아무리 값을 바꿔도 &lt;code&gt;oob_target&lt;/code&gt;의 하위 32비트는 &lt;code&gt;0xc7000240&lt;/code&gt;으로 고정되고 상위 32비트만 제어가 가능했다고 한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;loop_iterations (반복 횟수)&lt;/strong&gt; : &lt;code&gt;DrawIconEx&lt;/code&gt;의 5번째 인자(&lt;code&gt;arg5&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 (증가량)&lt;/strong&gt; : &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt;의 1번째 인자(&lt;code&gt;arg1&lt;/code&gt;)에 의해 결정
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lDelta = arg1 // 8&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;메모리 상에서 다음 라인으로 이동하는 오프셋 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이제 이 &lt;strong&gt;where to write&lt;/strong&gt;가 결정되었으니 &lt;strong&gt;what to write&lt;/strong&gt;, 즉 어떤 값을 쓸 수 있는지, 그 값을 얼마나 제어할 수 있는지를 확인해야 한다. &lt;code&gt;vStrWrite01&lt;/code&gt;을 자세히 확인해보면 다음 두 부분에서 write 명령이 수행된다.&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;&lt;code&gt;esi&lt;/code&gt; 값은 조건에 따라 어떤 값과 &lt;strong&gt;OR&lt;/strong&gt;이나 &lt;strong&gt;AND&lt;/strong&gt; 연산을 하게 된다. Exploit 과정에서 주로 값을 증가시키거나 특정 비트를 켜기 위해 &lt;strong&gt;OR&lt;/strong&gt; 연산을 사용하므로 조건을 파악하는 것이 중요한데, &lt;code&gt;DrawIconEx&lt;/code&gt;의 8번째 인자인 &lt;code&gt;diFlags&lt;/code&gt;가 눈에 띄었다고 한다. 공식 문서를 확인해보니 다음과 같은 사실을 알 수 있었다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DrawIconEx&lt;/code&gt;의 8번째 인자(&lt;code&gt;diFlags&lt;/code&gt;)가 &lt;code&gt;DI_IMAGE (0x6)&lt;/code&gt;이면 &lt;strong&gt;AND&lt;/strong&gt; 연산&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DrawIconEx&lt;/code&gt;의 8번째 인자(&lt;code&gt;diFlags&lt;/code&gt;)가 &lt;code&gt;DI_MASK (0x1)&lt;/code&gt;이면 &lt;strong&gt;OR&lt;/strong&gt; 연산&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;분석 결과, 이 OOB write 취약점은 매우 독특한 제약 사항을 가지고 있다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;하위 32비트 고정&lt;/strong&gt; : &lt;code&gt;oob_target&lt;/code&gt; 주소의 상위 32비트는 &lt;code&gt;arg5&lt;/code&gt;를 통해 제어할 수 있지만, &lt;strong&gt;하위 32비트는 항상 &lt;code&gt;0xc7000240&lt;/code&gt;과 같은 특정 값으로 고정&lt;/strong&gt;된다. 즉, 공격자가 원하는 임의의 주소에 값을 쓸 수 있는 것이 아니라, 하위 주소가 맞는 특정 위치에만 쓸 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;제한적인 쓰기 (Bitwise Operation)&lt;/strong&gt; : 원하는 값을 덮어쓰는(Overwrite) 것이 아니라, 기존 값에 &lt;strong&gt;AND&lt;/strong&gt; 또는 &lt;strong&gt;OR&lt;/strong&gt; 연산을 수행한다.&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;위에서 언급한 제약 사항(하위 주소 고정, Bitwise OR 연산) 때문에 일반적인 방법으로는 exploit이 어렵다. 하지만 1-byte NULL overflow(House of Einherjar)만으로도 exploit이 가능하다는 것을 상기하면 힘이 난다고 한다. 이를 극복하기 위해 Windows 커널의 비트맵 객체인 &lt;code&gt;SURFOBJ&lt;/code&gt; 구조체를 이용한다.&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;이 중 exploit에 중요한 필드는 다음과 같다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pvScan01&lt;/code&gt; : 실제 비트맵 데이터를 가리키는 포인터&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sizlBitmap&lt;/code&gt; : 비트맵의 가로(width)와 세로(height), 두 개의 dword로 구성&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;먼저 기준이 될 Base SURFOBJ를 할당하여 &lt;code&gt;0xfffff900`c7000000&lt;/code&gt; 주소에 위치시킨다. 이후 &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt;을 반복 호출하여 커널 힙(Paged Pool)에 &lt;code&gt;SURPOBJ&lt;/code&gt; 구조체와 비트맵 데이터를 다수 할당한다.&lt;/p&gt;
&lt;p&gt;힙 레이아웃을 조정하여 그 중 하나가(Target A) 정확히 &lt;code&gt;0xfffff901`c7000000&lt;/code&gt; 주소에 할당되도록 힙을 그루밍하는 것이 목표이다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.bl4nk.kr/ko/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;우리가 노리는 것은 Target B의 &lt;code&gt;sizlBitmap&lt;/code&gt; 필드이다. 이 필드는 비트맵의 가로/세로 크기를 정의한다. 이 값이 커지게 되면 커널은 Target B 비트맵의 크기가 매우 크다고 착각하게 된다.&lt;/p&gt;
&lt;p&gt;이 과정에서 Target B의 &lt;code&gt;sizlBitmap&lt;/code&gt; 필드를 &lt;code&gt;oob_target&lt;/code&gt;과 정확히 일치시키는 것이 까다롭다. 단 한번의 쓰기로 정확히 &lt;code&gt;sizlBitmap&lt;/code&gt;을 조작하지 않으면 BSOD가 발할 확률이 높다. 따라서 &lt;code&gt;DrawIconEx&lt;/code&gt;와 &lt;code&gt;CreateCompatibleBitmap&lt;/code&gt;의 인자를 잘 조합해야 하는데, 이 조합을 찾아내기 위해 다음과 같이 brute force 스크립트를 작성했다고 한다.&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/ko/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;이제 Target B 비트맵은 자신의 할당된 메모리 영역을 넘어서 접근할 수 있게 되었다.
Target B 바로 뒤에는 또 다른 비트맵 구조체 Target C가 위치해 있을 것이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SetBitmapBits(Target B, ...)&lt;/code&gt; 함수를 호출하면 Target B의 데이터 영역을 넘어 Target C의 &lt;code&gt;pvScan0&lt;/code&gt; 필드를 덮어쓸 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.bl4nk.kr/ko/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;이제 Target C 비트맵을 이용해 완전한 AAR/AAW가 가능하다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Where 설정&lt;/strong&gt; : Target B(Manager)를 이용하여 Target C(Worker)의 &lt;code&gt;pvScan0&lt;/code&gt;을 원하는 주소로 변경한다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What 실행&lt;/strong&gt; : Target C(Worker)를 이용해 &lt;code&gt;GetBitmapBits&lt;/code&gt;, &lt;code&gt;SetBitmapBits&lt;/code&gt;를 호출하면 커널 주소의 값을 읽거나 쓸 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;이것이 바로 &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;AAR/AAW가 확보되었으니 나머지는 일반적인 기법을 사용한다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;현재 프로세스(&lt;code&gt;EPROCESS&lt;/code&gt;)를 찾는다.&lt;/li&gt;
&lt;li&gt;System 프로세스(PID 4)의 &lt;code&gt;EPROCESS&lt;/code&gt;를 찾는다.&lt;/li&gt;
&lt;li&gt;System 프로세스의 &lt;code&gt;Token&lt;/code&gt; 값을 읽어와서 현재 프로세스의 &lt;code&gt;Token&lt;/code&gt; 값을 덮어쓴다.&lt;/li&gt;
&lt;li&gt;이제 현재 프로세스는 System 권한을 갖게 된다.&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;이 취약점은 &lt;code&gt;DrawIconEx&lt;/code&gt;라는 그래픽 함수 내부의 복잡한 주소 계산 로직과 인자 검증 부재가 결합되어 발생한 취약점이다. 제한된 OOB write(고정된 하위 주소, Bitwise 연산)를 &lt;code&gt;SURFOBJ&lt;/code&gt; 구조체 조작을 통해 강력한 AAR/AAW로 전환하는 창의적인 exploit 기법을 보여준다.&lt;/p&gt;
&lt;p&gt;Windows 7 환경에서는 보안 업데이트(KB) 설치 여부에 따라 구조체 오프셋이 달라질 수 있으므로, exploit 작성 시 이를 동적으로 탐지하거나 버전에 맞춰 수정해야 한다.&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">Win32k.sys에서 발생하는 OOB Write 취약점과 SURFOBJ를 이용한 공격 기법 상세 분석</summary>
        </entry>
</feed>
