{"id":43,"date":"2006-08-16T12:35:27","date_gmt":"2006-08-16T17:35:27","guid":{"rendered":"http:\/\/www.nynaeve.net\/?p=43"},"modified":"2019-12-13T17:41:39","modified_gmt":"2019-12-13T22:41:39","slug":"beware-of-custom-unhandled-exception-filters-in-dlls","status":"publish","type":"post","link":"http:\/\/www.nynaeve.net\/?p=43","title":{"rendered":"Beware of custom unhandled exception filters in DLLs"},"content":{"rendered":"<p><a title=\"Debugging a custom unhandled exception filter\" href=\"http:\/\/www.nynaeve.net\/?p=23\">Previously<\/a>, I had discussed some techniques for debugging unhandled exception filters.\u00c2\u00a0 There are some more gotchas relating to unhandled exception filters than just debugging them, though.<\/p>\n<p>The problem with unhandled exception filters is that they are broken by design.\u00c2\u00a0 The API (SetUnhandledExceptionFilter) used to install them allows you to build a chain of unhandled exception filters as multiple images within a process install their own filter.\u00c2\u00a0 While this may seem fine in practice, it actually turns out to be a serious flaw.\u00c2\u00a0 The problem is that there is no support for removing these unhandled exception filters <em>out of order<\/em>.\u00c2\u00a0 If you do so, you often end up with a previous\u00c2\u00a0unhandled exception filter pointer used by some DLL that points to a now-unloaded DLL, because some DLL with an unhandled exception filter was unloaded, but the unhandled exception filter registered after it still has a pointer to the previous filter in the now unloaded DLL.<\/p>\n<p>This turns out to (at best) cause your custom crash handling logic to appear to randomly fail to operate, and at worst, introduce <a title=\"MS06-051, in which unhandled exception filters in IE plugins can be used to run arbitrary code.\" href=\"http:\/\/www.microsoft.com\/technet\/security\/bulletin\/ms06-051.mspx\">serious security holes<\/a> in your program.\u00c2\u00a0 You can read more about the security hole this introduces in <a title=\"Exploiting the Otherwise Non-Exploitable on Windows\" href=\"http:\/\/www.uninformed.org\/?v=4&#038;a=5&#038;t=sumry\">the paper on Uninformed.org<\/a>, but the basic idea is that if unhandled exception filters are unregistered out of order, you have a &#8220;dangling&#8221; function pointer that points to no-mans-land.\u00c2\u00a0 If an attacker can fill your process address space with shell code and then cause an exception (perhaps an otherwise &#8220;harmless&#8221; null pointer dereference that would cause your program to crash), he or she can take control of your process and run arbitrary code.<\/p>\n<p>Unfortunately, there isn&#8217;t a good way to fix this from an application perspective.\u00c2\u00a0 I would recommend just not ever calling the previous unhandled exception filter, as there is no way to know whether it points to the real code that registered it or malicious code that someone allocated all over your process address space (called &#8220;heap spraying&#8221; in exploitation terminology).<\/p>\n<p>You still have to deal with the fact that someone else might later install an unhandled exception filter ahead of yours, though, and then\u00c2\u00a0cause\u00c2\u00a0the unhandled exception filter chain to be broken upstream of you.\u00c2\u00a0 There is no real good solution for this; you might investigate patching SetUnhandledExceptionFilter or UnhandledExceptionFilter to always call you, but you can imagine what would happen if two functions try to do this at the same time.<\/p>\n<p>So, the moral of the story is as follows:<\/p>\n<ol>\n<li>Don&#8217;t trust unhandled exception filters, as the model is brittle and easily breaks in processes that load and unload DLLs frequently.<\/li>\n<li>If you must register an unhandled exception filter, do it in a DLL that is never unloaded\u00c2\u00a0(or even the main .exe) to prevent the unhandled exception filter from being used as an attack vector.<\/li>\n<li>Don&#8217;t try to call the previous unhandled exception filter pointer that you get back from SetUnhandledExceptionFilter, as this introduces a security risk.<\/li>\n<li>Don&#8217;t install an unhandled exception filter from within a plugin type DLL that is loaded in a third party application, and especially don&#8217;t install an unhandled exception filter in a plugin type DLL that gets unloaded on the fly.<\/li>\n<\/ol>\n<p>Unfortunately, it turns out to be even harder than this to not get burned by unhandled exception filter chaining.\u00c2\u00a0 More on that in a future posting.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Previously, I had discussed some techniques for debugging unhandled exception filters.\u00c2\u00a0 There are some more gotchas relating to unhandled exception filters than just debugging them, though. The problem with unhandled exception filters is that they are broken by design.\u00c2\u00a0 The API (SetUnhandledExceptionFilter) used to install them allows you to build a chain of unhandled exception [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,3,5],"tags":[],"_links":{"self":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/43"}],"collection":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=43"}],"version-history":[{"count":1,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":651,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions\/651"}],"wp:attachment":[{"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.nynaeve.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}