{"id":294,"date":"2022-10-30T19:34:19","date_gmt":"2022-10-30T18:34:19","guid":{"rendered":"https:\/\/areyou1or0.it\/?p=294"},"modified":"2022-10-30T19:49:39","modified_gmt":"2022-10-30T18:49:39","slug":"hevd-windows-kernel-exploitation-5-uninitialized-stack-variable","status":"publish","type":"post","link":"https:\/\/areyou1or0.it\/index.php\/2022\/10\/30\/hevd-windows-kernel-exploitation-5-uninitialized-stack-variable\/","title":{"rendered":"HEVD Windows Kernel Exploitation 5: Uninitialized Stack Variable"},"content":{"rendered":"\n<p>Before I start talking about the 4th vulnerability on HEVD (Uninitialized Stack Variable), I&#8217;ll give a summary of what we&#8217;ve learned so far:<\/p>\n\n\n\n<ul><li>With Stack Overfow:&nbsp;&nbsp;put your shellcode in userland in an allocated memory and execute in kernelland<\/li><li>With Arbitraty Overwrite: writing the value pointed by what to the memory location referenced by where<\/li><li>With Null Pointer Dereference:&nbsp;writing to a pointer location where the value of the pointer is NULL and used by an application that points to a valid memory location<\/li><li>With Unitialized Stack Variable,&nbsp;we will control the data on the&nbsp;<strong>kernel stack<\/strong>&nbsp;from&nbsp;<strong>user mode<\/strong>&nbsp;using an uninitialized stack variable<\/li><\/ul>\n\n\n\n<h2>Source Code Review<\/h2>\n\n\n\n<p>As always we&#8217;ll check the C code first to understand where the vulnerability lies:<\/p>\n\n\n\n<p>The structure of the code is the same, defines some variables and datatypes, shows the vulnerable vs secure code and triggers the vulnerability, then defines IOCTL code.&nbsp;<\/p>\n\n\n\n<p>The author mentions in the source code that in the secure version, UninitializedMemory variable is initialized to a value. However in the vulnerable version, it&#8217;s not initialized and later called in the &nbsp;the&nbsp;callback()&nbsp;function, which leads to this vulnerability.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"490\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-5-1024x490.png\" alt=\"\" class=\"wp-image-300\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-5-1024x490.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-5-300x143.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-5-768x367.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-5.png 1368w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2>Finding the IOCTL Code:<\/h2>\n\n\n\n<p>Got to Functions, select IrpDevideIOCTLHandler, in the text view scroll down until you see the call for&nbsp;UninitializedStackVariableIoctlHandler<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"236\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-3-1024x236.png\" alt=\"\" class=\"wp-image-298\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-3-1024x236.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-3-300x69.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-3-768x177.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-3.png 1050w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll follow the arrows for the function loc_15171A above and will see the following jmp statement.<\/p>\n\n\n\n<p>We&#8217;ll add 4 bytes to find the ICOTL to 0x22202B which will give us 0x22202F<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"267\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1024x267.png\" alt=\"\" class=\"wp-image-295\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1024x267.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-300x78.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-768x200.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image.png 1068w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In order to see our affect in actions, we&#8217;ll put a breakpoint in windbg with !HEVD+0x571A for the function&nbsp;&nbsp;loc_15171A (1 in the address = a base address of&nbsp;&nbsp;0x00010000 so we can remove it in the breakpoint)<\/p>\n\n\n\n<h2>Initial Exploit:<\/h2>\n\n\n\n<p>We&#8217;ll create the initial exploit with the IOCTL code to verify the vulnerability. My code is pretty same as the last times so shouldn&#8217;t be a shocker:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td>import struct, sys, ctypes<br>from ctypes import *<br>from subprocess import *<br>&nbsp;<br>## DLL<br>kernel32 = windll.kernel32&nbsp;&nbsp;&nbsp;<br>psapi = windll.Psapi<br>ntdll = windll.ntdll<br>&nbsp;<br>handle = kernel32.CreateFileA(&#8220;\\\\\\\\.\\\\HackSysExtremeVulnerableDriver&#8221;, 0xC0000000, 0, None, 0x3, 0, None)<br>&nbsp;<br>if not handle or handle == -1:<br>&nbsp;&nbsp;&nbsp;&nbsp;print &#8220;[+] Cannot get device handle&#8230;.. Try again.&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;sys.exit(0)<br>&nbsp;<br>buffer = &#8220;\\xb0\\xb0\\xd0\\xba&#8221;<br>&nbsp;<br>kernel32.DeviceIoControl(handle, 0x22202f, buffer, len(buffer), None, 0, byref(c_ulong()), None)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>On windbg, write the following commands<\/p>\n\n\n\n<ul><li>!sym noisy<\/li><\/ul>\n\n\n\n<ul><li>.reload<\/li><li>lm m H*<\/li><li>bp&nbsp;!HEVD+0x571A<\/li><li>g<\/li><\/ul>\n\n\n\n<p>when we run the code, we hit the breakpoint which verifies the IOCTL code:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"976\" height=\"128\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-6.png\" alt=\"\" class=\"wp-image-301\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-6.png 976w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-6-300x39.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-6-768x101.png 768w\" sizes=\"(max-width: 976px) 100vw, 976px\" \/><\/figure>\n\n\n\n<p>Let&#8217;s change the value for the buffer variable and check windbg again:<\/p>\n\n\n\n<h2>Source Code Analysis on IDA:<\/h2>\n\n\n\n<p>Let&#8217;s see in IDA again what does this function do:<\/p>\n\n\n\n<p>If you follow the IOCTL handler for this function,&nbsp;<\/p>\n\n\n\n<ul><li>we see our user buffer put in ecx following a<strong>&nbsp;test ecx, ecx<\/strong>&nbsp;statement.&nbsp;<\/li><li>If we fail jz statement, we&#8217;ll follow the red lines meaning we&#8217;ll trigger the vulnerability<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"622\" height=\"710\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-10.png\" alt=\"\" class=\"wp-image-305\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-10.png 622w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-10-263x300.png 263w\" sizes=\"(max-width: 622px) 100vw, 622px\" \/><\/figure>\n\n\n\n<p>If you double click on TriggerUninitializedStackVariable, we&#8217;ll see what&#8217;s going on in the Graph view:<\/p>\n\n\n\n<ul><li>We have a call to ProbeForRead and then&nbsp;<\/li><li>we load the value 0xBAD0B0B0 into eax<\/li><li>cmp esi (or our user provided buffer) and the&nbsp;arbitrary static value<\/li><\/ul>\n\n\n\n<p>We see that here we\u2019re loading a value of&nbsp;0xBAD0B0B0&nbsp;into&nbsp;eax&nbsp;and then executing a&nbsp;cmp&nbsp;between that value and&nbsp;esi. This is probably a compare between our user provided buffer and&nbsp;0xBAD0B0B0&nbsp;.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"749\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-1024x749.png\" alt=\"\" class=\"wp-image-303\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-1024x749.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-300x220.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-768x562.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-1536x1124.png 1536w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8-1568x1147.png 1568w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-8.png 1588w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>If our user provided buffer value is the magic value (0xBAD0B0B0),&nbsp;we fail the jnz statement (as the value is 0), we&#8217;ll go with red (the short path) and execute the followings:<\/p>\n\n\n\n<ul><li>we put eax into stack (eax was 0xBAD0B0B0&nbsp;as we ended up here after the cmp esi,eax &#8211;&gt; jnz statement)<\/li><li>offset to the&nbsp;UninitializedStackVariableObjectCallback&nbsp;entity into stack<\/li><\/ul>\n\n\n\n<p>If you right click on UninitializedStackVariableObjectCallback&nbsp;, the hex value is 86670 which is the address of the callback function<\/p>\n\n\n\n<p>In summary, when we take this path, we put 2 initialized variable values onto stack<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"162\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1-1024x162.png\" alt=\"\" class=\"wp-image-296\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1-1024x162.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1-300x47.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1-768x122.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-1.png 1188w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>If we take the second path, we&#8217;ll eventually do the followings:<\/p>\n\n\n\n<p>cmp [ebp+UninitializedStackVariable.Callback], edi&nbsp;<\/p>\n\n\n\n<p>As long as the function pointer is not initialized to NULL &amp; we don&#8217;t provide the magic value as our user value, we&#8217;ll end up with the red flag to call [ebp+var_108]<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"519\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7-1024x519.png\" alt=\"\" class=\"wp-image-302\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7-1024x519.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7-300x152.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7-768x389.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7-1536x778.png 1536w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-7.png 1560w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>If we right click on the value, it shows 108 in hex. So we will call whatever is located at &#8216;ebp-108&#8217;. The purpose here is get a pointer to shellcode at the address &#8216;ebp-108&#8217;.&nbsp;<\/p>\n\n\n\n<h2>Finding Offset:<\/h2>\n\n\n\n<p>On windbg, write the following commands once again:<\/p>\n\n\n\n<ul><li>!sym noisy<\/li><\/ul>\n\n\n\n<ul><li>.reload<\/li><li>lm m H*<\/li><li>bp&nbsp;!HEVD+0x571A<\/li><li>g<\/li><li>dps esp<\/li><\/ul>\n\n\n\n<p>trigger the vulnerability again and run the following command in windbg:<\/p>\n\n\n\n<p>kd&gt; !thread<\/p>\n\n\n\n<p>See that Kernel&nbsp;Stack Init is 0x82b7ded0&nbsp;and &amp;UninitializedStackVariable.Callback <\/p>\n\n\n\n<p>kd&gt; ?&lt; Kernel&nbsp;Stack Init&gt;-&lt;&amp;UninitializedStackVariable.Callback&gt;<\/p>\n\n\n\n<p>this will give us the offset 00000504 which means when we put&nbsp;our data at an offset of&nbsp;0x504&nbsp;from&nbsp;Stack Init, we can hijack the&nbsp;Instruction Pointer.<\/p>\n\n\n\n<h2>Kernel Stack Spraying:<\/h2>\n\n\n\n<p>We can do this using the API call&nbsp;&nbsp;NtMapUserPhyiscalPages&nbsp;to spray a pointer value onto the stack repeatedly. You can find the API documentation here:&nbsp;&nbsp;<\/p>\n\n\n\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/memoryapi\/nf-memoryapi-mapuserphysicalpages\">https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/memoryapi\/nf-memoryapi-mapuserphysicalpages<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"604\" height=\"224\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-2.png\" alt=\"\" class=\"wp-image-297\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-2.png 604w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-2-300x111.png 300w\" sizes=\"(max-width: 604px) 100vw, 604px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll have the following parameter values for the corresponding reasons:<\/p>\n\n\n\n<ul><li>Page Array: none&nbsp;<\/li><li>NumberofPages: 1024<\/li><li>VirtualAddress: pointer address&nbsp;<\/li><\/ul>\n\n\n\n<p>We can spray upto&nbsp;1024*sizeof(ULONG_PTR)&nbsp;using this&nbsp;API.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"95\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-9-1024x95.png\" alt=\"\" class=\"wp-image-304\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-9-1024x95.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-9-300x28.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-9-768x71.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-9.png 1382w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>We&#8217;ll put a breakpoint&nbsp;on the last instruction of&nbsp;<strong>NtMapUserPhysicalPages&nbsp;<\/strong>routine and then run the final script:<\/p>\n\n\n\n<p>kd &gt;bp nt!NtMapUserPhysicalPages<\/p>\n\n\n\n<p>kd&gt; bp nt!NtMapUserPhysicalPages +0x5be<\/p>\n\n\n\n<p>kd&gt; g<\/p>\n\n\n\n<p>kd&gt; !thread<\/p>\n\n\n\n<p>Once the breakpoint is hit, we will get Kernel&nbsp;<strong>Stack Init<\/strong>&nbsp;address and find that value at an offset of&nbsp;<strong>0x504<\/strong>.<\/p>\n\n\n\n<p>kd&gt; !thread<\/p>\n\n\n\n<h2>Final Code:<\/h2>\n\n\n\n<p>As always, I&#8217;ll summarize what our final exploit will have before I show it all in one place:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"745\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/Screenshot-2022-10-30-at-19.36.24-1-1024x745.png\" alt=\"\" class=\"wp-image-321\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/Screenshot-2022-10-30-at-19.36.24-1-1024x745.png 1024w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/Screenshot-2022-10-30-at-19.36.24-1-300x218.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/Screenshot-2022-10-30-at-19.36.24-1-768x559.png 768w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/Screenshot-2022-10-30-at-19.36.24-1.png 1528w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>When we run the code, we get the shell as&nbsp;<strong>NT AUTHORITY\\SYSTEM<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"884\" height=\"350\" src=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-4.png\" alt=\"\" class=\"wp-image-299\" srcset=\"https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-4.png 884w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-4-300x119.png 300w, https:\/\/areyou1or0.it\/wp-content\/uploads\/2022\/10\/image-4-768x304.png 768w\" sizes=\"(max-width: 884px) 100vw, 884px\" \/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Before I start talking about the 4th vulnerability on HEVD (Uninitialized Stack Variable), I&#8217;ll give a summary of what we&#8217;ve learned so far: With Stack Overfow:&nbsp;&nbsp;put your shellcode in userland in an allocated memory and execute in kernelland With Arbitraty Overwrite: writing the value pointed by what to the memory location referenced by where With&hellip; <a class=\"more-link\" href=\"https:\/\/areyou1or0.it\/index.php\/2022\/10\/30\/hevd-windows-kernel-exploitation-5-uninitialized-stack-variable\/\">Continue reading <span class=\"screen-reader-text\">HEVD Windows Kernel Exploitation 5: Uninitialized Stack Variable<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[21],"tags":[],"_links":{"self":[{"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/posts\/294"}],"collection":[{"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/comments?post=294"}],"version-history":[{"count":8,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/posts\/294\/revisions"}],"predecessor-version":[{"id":322,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/posts\/294\/revisions\/322"}],"wp:attachment":[{"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/media?parent=294"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/categories?post=294"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/areyou1or0.it\/index.php\/wp-json\/wp\/v2\/tags?post=294"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}