{"id":96366,"date":"2017-06-09T07:00:00","date_gmt":"2017-06-09T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96366"},"modified":"2019-03-13T01:12:43","modified_gmt":"2019-03-13T08:12:43","slug":"20170609-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170609-00\/?p=96366","title":{"rendered":"The case of the longjmp from nowhere trying to open a registry key"},"content":{"rendered":"<p>The crash telemetry team brought our attention to a bug a few weeks before the Creators Update was supposed to be released, and based on the high hit count of 3 million crashes in the past 30 days, the bug was marked &#8220;Blocking engineering sign-off&#8221;. <\/p>\n<p>Life is always exciting when you get a &#8220;Blocking engineering sign-off&#8221; bug. <\/p>\n<p>Here&#8217;s the relevant excerpt from the crashing stack. Let&#8217;s see what we can make of it: <\/p>\n<pre>\nntdll!RtlFailFast2\nntdll!RtlGuardCheckLongJumpTarget+0x72f9f\nntdll!RtlGuardRestoreContext+0x360\nntdll!RtlUnwindEx+0x767\n0x00007ff7`26040a5a\n0x00007ff7`25fcb0c6\n0x00007ff7`25fc9bf8\n0x00007ff7`25fc9d23\n0x00007ff7`25fc9f27\n0x00007ff7`25fe1d17\n0x00007ff7`25fdfd7f\n0x00007ff7`25fca5f1\n0x00007ff7`25fca645\n0x00007ff7`25fcae25\n0x00007ff7`25fca870\n0x00007ff7`25fc27be\n0x00007ff7`25fc6aaf\n0x00007ff7`25fcab3d\n0x00007ff7`25fe11ef\n0x00007ff7`25fca5f1\n0x00007ff7`25fca645\n0x00007ff7`25fcae25\n0x00007ff7`25fca870\n0x00007ff7`25fc27be\n0x00007ff7`25fe949c\n0x00007ff7`25fe93e6\n0x00007ff7`25fe6709\n0x00007ff7`25fe6200\nntdll!KiUserApcDispatch+0x2e\nntdll!ZwOpenKeyEx+0x14\nKERNELBASE!Wow64pNtOpenKeyInternal+0x16\nKERNELBASE!Wow64NtOpenKey+0x7c\nKERNELBASE!LocalBaseRegOpenKey+0x1bc\nKERNELBASE!RegOpenKeyExInternalW+0x13b\nKERNELBASE!RegOpenKeyExW+0x19\nwindows_storage!SHGetMachineGUID+0x83\n...\n<\/pre>\n<p>Working upward, the storage system is trying to read the machine GUID, so it&#8217;s opening the <code>HKEY_<\/code><code>LOCAL_<\/code><code>MACHINE\\<\/code><code>Software\\<\/code><code>Microsoft\\<\/code><code>Cryptography<\/code> registry key. That <code>Reg&shy;Open&shy;Key&shy;ExW<\/code> call eventually reached the kernel at <code>Zw&shy;Open&shy;Key&shy;Ex<\/code>, and then somehow a user-mode asynchronous procedure call (APC) got dispatched back into the user-mode thread. That user APC executed a lot of code that got injected into the process, not associated with a DLL. It reached a point where it encountered an exception, and the operating system is trying to unwind the exception but something goes wrong with the unwind when it wants to check a long jump target: The jump target is not valid, so the process crashes with a fail-fast exception: Incorrect exception unwind information is not a recoverable error, and it may indicate the presence of malware. <\/p>\n<p>There are multiple levels of mystery here. The first level of mystery is this chunk of code not associated with a DLL. How did it get into our process? This particular process was <code>Runtime&shy;Broker.exe<\/code>, which isn&#8217;t as promiscuous as <code>explorer.exe<\/code> with respect to shell extensions and other third-party extension points, nor is it a common target for code injection. <\/p>\n<p>Second, why is opening a registry key dispatching user-mode APCs? This is not called out in the documentation, and it is not something expected in general. Dispatching user-model APCs is not something you do just for fun. It creates a situation where code is running inside the context of unrelated code. If a critical section was held at the time <code>Reg&shy;Open&shy;Key&shy;ExW<\/code> was called, that critical sction is still being held when the APC is run, and you are now in danger of creating a deadlock. This is why functions which processes APCs usually make you opt into APCs explicitly: <code>SleepEx<\/code>, <code>Wait&shy;For&shy;Single&shy;Object&shy;Ex<\/code>, and <code>Msg&shy;Wait&shy;For&shy;Multiple&shy;Objects&shy;Ex<\/code> don&#8217;t process APCs unless you say you want them to, and the non-<code>Ex<\/code> versions never process APCs. <\/p>\n<p>The third mystery is why the injected code is performing a <code>longjmp<\/code>. The exception being propagated is <code>0x80000026<\/code> which is <code>STATUS_<\/code><code>LONGJUMP<\/code>: &#8220;A long jump has been executed.&#8221; <\/p>\n<p>The mystery code is trying to perform a <code>longjmp<\/code>. Thats right, a <code>longjmp<\/code>. Apparently we are still running code written in 1970. <\/p>\n<p>We contacted the registry team for assistance, and they recognized this issue. They suspect that some third-party registry filter driver (perhaps a game&#8217;s anti-cheat software) is monitoring attempts to access any registry keys under <code>HKEY_<\/code><code>LOCAL_<\/code><code>MACHINE\\<\/code><code>Software\\<\/code><code>Microsoft\\<\/code><code>Cryptography<\/code> and scheduling user-mode APCs as part of its processing. That APC then runs into a situation where it decides to try to <code>longjmp<\/code> out of its normal processing, but the <code>longjmp<\/code> buffer is either corrupted, or the long jump target has not been registered as a <a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/mt637065(v=vs.85).aspx\">control flow guard<\/a> jump target, so the exception dispatching code says, &#8220;No way, I&#8217;m not dispatching this exception.&#8221; <\/p>\n<p>The registry team noted that the vast majority of the crashes are coming from machines running the Anniversary Update, not the Creators Update, so this likely not a case of the Creators Update making a change that exacerbated a pre-existing problem, and the &#8220;Blocking engineering sign-off&#8221; marking should be removed. Furthermore, even though there were three million hits over the past 30 days, the crashes were not uniformly-distributed. Rather, the issue spiked and then died down within a week. This suggests that the third party recognized the issue and put out their own fix. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Close your eyes and jump.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-96366","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Close your eyes and jump.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96366","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=96366"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96366\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=96366"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96366"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96366"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}