{"id":4719,"date":"2018-04-01T00:03:13","date_gmt":"2018-04-01T00:03:13","guid":{"rendered":"http:\/\/www.hexacorn.com\/blog\/?p=4719"},"modified":"2018-04-02T00:12:15","modified_gmt":"2018-04-02T00:12:15","slug":"curious-case-of-the-conhost-exe-and-condrv-sys","status":"publish","type":"post","link":"https:\/\/www.hexacorn.com\/blog\/2018\/04\/01\/curious-case-of-the-conhost-exe-and-condrv-sys\/","title":{"rendered":"Curious case of the conhost.exe and condrv.sys"},"content":{"rendered":"<p><strong>Update<\/strong><\/p>\n<p>After I posted the question to Twitter, <a href=\"https:\/\/twitter.com\/aionescu\">Alex Ionescu<\/a> (god of NT kernel internals, for those who don&#8217;t know) <a href=\"https:\/\/twitter.com\/aionescu\/status\/980235215766343680\">suggested<\/a> that it could be an export by ordinal from the ntoskrnl.exe. It was not the case in this scenario, but it&#8217;s a very good direction for investigation and I didn&#8217;t think of it when I encountered the issue.<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/04\/condrv_twit1.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-4724\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/04\/condrv_twit1.png\" alt=\"\" width=\"572\" height=\"798\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/04\/condrv_twit1.png 572w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/04\/condrv_twit1-215x300.png 215w\" sizes=\"(max-width: 572px) 100vw, 572px\" \/><\/a><\/p>\n<p>Following on that lead I dug deeper. Further inspection of the condrv.sys driver confirmed that at least 2 functions from ntoskrnl.exe are imported by the ordinal (0x0001, and 0x0002):<\/p>\n<pre>-&gt;Import Table\r\n 1. ImageImportDescriptor:\r\n OriginalFirstThunk: 0x0000A1AC\r\n TimeDateStamp: 0x00000000 (GMT: Thu Jan 01 00:00:00 1970)\r\n ForwarderChain: 0x00000000\r\n Name: 0x0000AA04 (\"ntoskrnl.exe\")\r\n FirstThunk: 0x00002088\r\n\r\nOrdinal\/Hint API name\r\n ------------ ---------------------------------------\r\n 0x00FF \"ExReleasePushLockExclusiveEx\"\r\n\r\n\r\n 0x0002  &lt;------- import by ordinal\r\n 0x05C1 \"ObCloseHandle\"\r\n 0x067F \"PsGetProcessImageFileName\"\r\n 0x0001  &lt;------- import by ordinal<\/pre>\n<p>so Alex&#8217;s explanation points us in a right direction, except the issue is the import table of condrv.sys, not the export table of ntoskrnl.exe; IDA somehow assumes the names of the &#8216;guessed&#8217; service functions based on the ordinals and does it wrongly &#8211; this is what causes confusion and ends up with us staring at an incorrect disassembly.<\/p>\n<p><strong>Old Post<\/strong><\/p>\n<p>A few months back I came up with an idea to find out how the conhost.exe process is spawn by the OS to co-exist with pretty much every single console applications on the system.<\/p>\n<p>I theorized that if I find out how it is spawn, I may be able to possibly influence this process and make it behave differently from the expected (wishful thinking that perhaps I could find a way to run this process anytime I want and hijack it for e.g. process hollowing or sth along these lines).<\/p>\n<p>After looking at the code of the AllocConsole function (which is a prime suspect here as it allocates consoles after all), I eventually landed in the code that calls NtDeviceIoControlFile with the IOCTL 0x500037.<\/p>\n<p>Quick google search followed and I re-visited an excellent posts from FireEye:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.fireeye.com\/blog\/threat-research\/2017\/08\/monitoring-windows-console-activity-part-one.html\">https:\/\/www.fireeye.com\/blog\/threat-research\/2017\/08\/monitoring-windows-console-activity-part-one.html<\/a><\/li>\n<li><a href=\"https:\/\/www.fireeye.com\/blog\/threat-research\/2017\/08\/monitoring-windows-console-activity-part-two.html\">https:\/\/www.fireeye.com\/blog\/threat-research\/2017\/08\/monitoring-windows-console-activity-part-two.html<\/a><\/li>\n<\/ul>\n<p>where the very same conhost.exe spawning mechanism is also described, although briefly.<\/p>\n<p>So, there is a way to launch a conhost.exe process bypassing all the WinExec\/ShellExecute\/ShellExecuteEx\/CreateProcess\/CreateProcessInternal\/etc. API layer. Still, there is no easy way to obtain the handle to that process so the malware that would try to use it would still need to find that process and hijack it. It looks like OS designers took the malicious bit into account and made it a bit harder for the coders to abuse it.<\/p>\n<p>The reason for this post is not the mechanism itself, but the curious issue I encountered while analysing the condrv.sys driver. It is the driver that actually receives the IOCTL\u00a00x500037 and processes it, calling the ZwCreateUserProcess routine in the end, at least, this is my working hypothesis at the moment.<\/p>\n<p>Why hypothesis?<\/p>\n<p>When you analyze the the driver w\/o symbols, the system routine the driver calls to launch conhost.exe is not ZwCreateUserProcess, but ExAcquireRundownProtection. A very strange choice. It is only applying the .pdb file to IDA will allow to map that call to ZwCreateUserProcess. Could it be an intentional way to obfuscate the calls? Or, am I missing something? I will admit my kernel mode analysis skills are really rusty.<\/p>\n<p>Ideas, anyone?<\/p>\n<p>This is what I see inside the condrv.sys without symbols (see that 2nd functions):<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv1.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-4720\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv1.png\" alt=\"\" width=\"781\" height=\"121\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv1.png 781w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv1-300x46.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv1-768x119.png 768w\" sizes=\"(max-width: 781px) 100vw, 781px\" \/><\/a><\/p>\n<p>and with symbols:<\/p>\n<p><a href=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2.png\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-4721\" src=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2.png\" alt=\"\" width=\"1106\" height=\"119\" srcset=\"https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2.png 1106w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2-300x32.png 300w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2-768x83.png 768w, https:\/\/www.hexacorn.com\/blog\/wp-content\/uploads\/2018\/03\/condrv2-1024x110.png 1024w\" sizes=\"(max-width: 1106px) 100vw, 1106px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Update After I posted the question to Twitter, Alex Ionescu (god of NT kernel internals, for those who don&#8217;t know) suggested that it could be an export by ordinal from the ntoskrnl.exe. It was not the case in this scenario, &hellip; <a href=\"https:\/\/www.hexacorn.com\/blog\/2018\/04\/01\/curious-case-of-the-conhost-exe-and-condrv-sys\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[36,44],"tags":[],"_links":{"self":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/4719"}],"collection":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/comments?post=4719"}],"version-history":[{"count":5,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/4719\/revisions"}],"predecessor-version":[{"id":4735,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/posts\/4719\/revisions\/4735"}],"wp:attachment":[{"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/media?parent=4719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/categories?post=4719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.hexacorn.com\/blog\/wp-json\/wp\/v2\/tags?post=4719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}