{"id":656,"date":"2008-09-29T15:38:39","date_gmt":"2008-09-29T13:38:39","guid":{"rendered":"https:\/\/alax.info\/blog\/?p=656"},"modified":"2008-10-02T22:00:11","modified_gmt":"2008-10-02T20:00:11","slug":"gs-buffer-security-check","status":"publish","type":"post","link":"https:\/\/alax.info\/blog\/656","title":{"rendered":"\/GS Buffer Security Check"},"content":{"rendered":"<p>Microsoft C++ compiler offers a buffer security check option since quite a long ago. It adds so called &#8220;security cookies&#8221; onto stack and checks them to be not modified by code in order to early-detect stack buffer overflow conditions. <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/8dbf701c.aspx\">The compiler option \/GS<\/a> is enabled by default in Release configurations and is not applicable to debug code (which has optimizations disabled).<\/p>\n<p>Here comes the trouble: release code might show unexpected message box &#8220;Buffer overrun detected!&#8221;. I have never seen such after years of development and tens of thousands of lines of code written, but luckily there are colleagues who can contribute a challenging issue to investigate.<\/p>\n<p><a href=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/09\/29-image001.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-657\" title=\"Buffer overrun detected!\" src=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/09\/29-image001-300x128.png\" alt=\"\" width=\"300\" height=\"128\" srcset=\"https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/09\/29-image001-300x128.png 300w, https:\/\/alax.info\/blog\/wp-content\/uploads\/2008\/09\/29-image001.png 419w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>The message is shown through C runtime&#8217;s __crtMessageBoxA function and is not only annoying and angering the customer, it also stops application operation and terminates it:<\/p>\n<blockquote><p>By default, an application that fails a security check displays a dialog box that states &#8220;Buffer overrun detected!&#8221; When the dialog box is closed, the application terminates.<\/p><\/blockquote>\n<p>However it is possible to override this behavior:<\/p>\n<blockquote><p>The CRT library offers the developer an option to use a different handler that would react to the buffer overrun in a manner more sensible to the application. The function, <strong>__set_security_error_handler<\/strong>, is used to install the user handler by storing the user-defined handler in the <em>user_handler<\/em> variable<\/p><\/blockquote>\n<p>In my case we would be overriding this to trace call stack at the issue point. However, let us see first what other conditions might cause a message box. CRT source has the following occurrences for__crtMessageBoxA:<\/p>\n<ul>\n<li>assert.c &#8211; assertion failure, which normally only applies to debug code<\/li>\n<li>crt0msg.c &#8211; _NMSG_WRITE function, typically for a fatal run time error messages<\/li>\n<li>crtlib.c &#8211; _CRTDLL_INIT fails to start on a Win32s system (VER_PLATFORM_WIN32s)<\/li>\n<li>crtmbox.c &#8211; implementation of __crtMessageBoxA (which is, among other things binds to API functions on runtime instead of static linking)<\/li>\n<li>dbgrpt.c &#8211; CrtMessageWindow function, applies to debug code only<\/li>\n<li>secfail.c &#8211; __security_error_handler function, the \/GS thing<\/li>\n<\/ul>\n<p>So it appears that hopefully \/GS failure is the only surprising condition to display an unexpected message box.<\/p>\n<p>OK, let us just see what we got finally here. Using the MSDN sample code and overriding default check failure handler:<\/p>\n<pre>int main()\r\n{\r\n\t_set_security_error_handler(report_failure); \/\/ &lt;&lt;---------------- Override\r\n\t\/\/ declare buffer that is bigger than expected\r\n\tchar large_buffer[] = \"This string is longer than 10 characters!!\";\r\n\tvulnerable(large_buffer);\r\n}<\/pre>\n<p>Private handler is:<\/p>\n<pre>void __cdecl report_failure(int code, void*)\r\n{\r\n\tATLTRACE2(atlTraceGeneral, 0, _T(\"Security Error Handler: Code %d\\n\"), code);\r\n\tCONTEXT Context = { CONTEXT_CONTROL };\r\n\tif(GetCurrentThreadContext(&amp;Context))\r\n\t\tCDebugTraceCallStack::TraceCallStack(Context);\r\n}<\/pre>\n<p>and finally output:<\/p>\n<pre>BufferSecurityCheckSample.cpp(20): report_failure: Security Error Handler: Code 1\r\n  BufferSecurityCheckSample!0x00402a2d report_failure (+ 125) [c:\\buffersecuritychecksample\\buffersecuritychecksample.cpp, 22] (+ 10) @00400000\r\n  BufferSecurityCheckSample!0x00403d56 __security_error_handler (+ 48) [f:\\vs70builds\\6030\\vc\\crtbld\\crt\\src\\secfail.c, 79] (+ 6) @00400000\r\n  BufferSecurityCheckSample!0x00402e1d report_failure (+ 25) [f:\\vs70builds\\6030\\vc\\crtbld\\crt\\src\\secchk.c, 117] (+ 9) @00400000\r\n<span style=\"color: #ff0000;\"><strong>  BufferSecurityCheckSample!0x0040142c vulnerable (+ 44) [c:\\buffersecuritychecksample\\buffersecuritychecksample.cpp, 36] (+ 11) @00400000\r\n<\/strong><\/span>  BufferSecurityCheckSample!0x00404019 mainCRTStartup (+ 371) [f:\\vs70builds\\6030\\vc\\crtbld\\crt\\src\\crt0.c, 259] (+ 18) @00400000\r\n  kernel32!0x7c817067 RegisterWaitForInputIdle (+ 73) @7c800000<\/pre>\n<p>The log file would immediately show the source of the run time problem.<\/p>\n<p>See Also:<\/p>\n<ul>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/8dbf701c.aspx\">\/GS (Buffer Security Check)<\/a><\/li>\n<li><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa290051.aspx\">Compiler Security Checks In Depth<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft C++ compiler offers a buffer security check option since quite a long ago. It adds so called &#8220;security cookies&#8221; onto stack and checks them to be not modified by code in order to early-detect stack buffer overflow conditions. The compiler option \/GS is enabled by default in Release configurations and is not applicable to&hellip; <\/p>\n<p><a class=\"moretag\" href=\"https:\/\/alax.info\/blog\/656\">Read the full article<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,21],"tags":[487,38,131,130],"class_list":["post-656","post","type-post","status-publish","format-standard","hentry","category-atl","category-seriously","tag-atl","tag-c","tag-compiler","tag-crt"],"_links":{"self":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/656","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/comments?post=656"}],"version-history":[{"count":0,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/posts\/656\/revisions"}],"wp:attachment":[{"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/media?parent=656"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/categories?post=656"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/alax.info\/blog\/wp-json\/wp\/v2\/tags?post=656"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}