GS

GS

  • Comments 21

My name is Hongwei Qi and I am a Software Design Engineer in Test on the Visual C++ compiler code generation team. In this post I want to share with you the enhancements planned for the GS feature in Visual Studio 2010. 

Evolution of GS

 

A lot of code written in C and C++ has vulnerabilities that leave their users open to buffer overrun attacks. There are two major reasons for this. One reason is that the languages provide unfettered access to the vulnerable memory; the other reason is that developers make mistakes. The simple fact is that even following the best practices and performing quality checks, by the end of the day, no developers can get 100 percent of their code right all the time. Thus, additional built-in layers of defense to help track down vulnerable areas of code are in order. The Visual C++ compiler’s GS switch, which is on by default, is one of the built-in defenses designed to mitigate the buffer overrun attacks.

The GS switch was first provided in Visual Studio .NET 2002. It detects certain kinds of stack buffer overruns and terminates the process at runtime. When code is compiled by the compiler, the GS switch injects a cookie in a function’s stack just before its return address. The cookie enables the runtime to compare the value at the beginning and at the end of a function. If the value has changed, a buffer overrun has occurred, and it is no longer safe to run the application. Since the GS switch was first made available in Visual Studio .NET 2002, it has been constantly evolving. Visual Studio .NET 2003 SP1 added SafeSEH support.  In Visual Studio 2005, the improvements included parameter shadowing - making a shadow copy of a pointer parameter into a local variable. This step can help mitigate pointers that reside on the parameter stack from being exploited through a buffer overrun. In Visual Studio 2005 SP1, a new pragma, strict_gs_check, was added, which makes GS more aggressive by checking any function that has an address-taken local variable.

Here are some good links to refer to regarding GS switch:

·         http://msdn.microsoft.com/en-us/library/8dbf701c.aspx

·         http://msdn.microsoft.com/en-us/library/aa290051.aspx

·         http://msdn.microsoft.com/en-us/library/bb507721.aspx

 

A great witness to the success of GS switch

The ability of the GS switch to mitigate buffer overruns was first put to the test in 2003. Soon after the release of Windows Server 2003, a new virus, the Blaster worm, invaded thousands of computers. But the Blaster worm was not able to hijack applications that ran on Windows Server 2003. The reason was because the code for Windows Server 2003 had been compiled by using the Visual C++ compiler. And as a result of having the GS switch, the code had been scrutinized and had foiled the attempted invasion.

GS Enhancement in VC++ 2010

Building on the many successes of the GS switch in the past and in alignment with Microsoft’s commitment to increase security around its products and to provide development tools that would enable its customers to do the same, the VC++ compiler team is proactively working to refine and enhance the abilities of the GS switch. There are two key areas that have been addressed. One is to apply the existing GS technologies to a wider scope of protected functions. The other is to optimize away the unneeded security cookies for the functions that are safe from buffer overruns through GS analysis improvement.

Widen the protection scope:

In the current GS heuristic, the algorithms determining whether to emit a security GS cookie, primarily protects those vulnerable functions which have local string buffer (character based array). A GS buffer is defined as an array whose element size is one or two bytes, and where the size of the whole array is at least five bytes, or any buffer allocated with _alloca.  Note that byte arrays and ushort arrays are protected too, since the GS heuristic does not treat them differently from char/wchar. Functions which have local array and the array element size is bigger than two bytes, like array of ints, longs, and structs, etc., are not guarded and are open to potential buffer overruns.

While with the widened scope of GS switch feature, most kinds of buffers and data structures are going to be protected. Using the existing MSDN example, when you compile the following code with /GS, with the current GS heuristic, no GS cookie is inserted on the stack, because the buffer element data type is an unsigned integer, although the buffer is subject to being overrun. However with the widened GS switch, GS cookie will be injected to protect the return address.

unsigned int * ReverseArray(unsigned int *pdwData, size_t cData)

{

   // *** This buffer is subject to being overrun!! ***

   unsigned int dwReversed[20];

   // Reverse the array into a temporary buffer

   for (size_t j=0, i = cData; i ; --i, ++j)

      // *** Possible buffer overrun!! ***

      dwReversed[j] = pdwData[i]; 

 

   // Copy temporary buffer back into input/output buffer

   for (size_t i = 0; i < cData ; ++i)

       pdwData[i] = dwReversed[i];

 

   return pdwData;

}

 

GS Optimization:

As we can see using the widened GS protection allows developers to ensure that their applications benefit from the GS mitigation in a much greater variety of stack buffer overflow scenarios. However one concern you might have is whether this will affect the applications’ performance since, in order to protect the function’s return address, extra code is inserted into the prolog and epilog of a function with a GS buffer:

In the function prolog, place security cookie on stack between return address and local variables:

 

push           ecx

mov            eax, DWORD PTR ___security_cookie

xor              eax, esp

mov            DWORD PTR __$ArrayPad$[esp+4], eax

 

In the function epilog, check the security cookie is not changed:

 

mov            ecx, DWORD PTR __$ArrayPad$[esp+4]

xor              ecx, esp

call              @__security_check_cookie@4

pop             ecx

ret               0

 

Stack reordering also causes extra code size, and parameter shadowing causes extra instructions to be inserted in the prolog.  Theoretically, those extra instructions and calls might affect the performance matrix on both execution time and code size. However if the compiler improves its analytical ability and can better identify the functions where no GS cookie is needed, then the performance gain you get through reducing the unneeded guarding should offset the performance lost due to widening the range of protection. This is the second area we have been addressing.  For instance, the current GS switch will inject a security cookie for the function Bar() in the following example, neglecting the fact that the function Bar() is safe from buffer overrun. While with the enhanced GS, the compiler can track all the local GS buffers and the pointer parameters usage information and identify that array string[20] in Bar() is immune from a buffer overrun attack, so the compiler won’t emit a security cookie for Bar().

 

#include <memory.h>

#include <stdlib.h>

#include <stdio.h>

 

#define BUFFERSIZE  40

wchar_t Buff[BUFFERSIZE] = L"Hello";

 

void foo(wchar_t *p, int count){

    memcpy(p, Buff, (count * sizeof(*p)));

}

 

void bar() {

    wchar_t string[20];

    foo(string, _countof(string));

    wprintf(string);

}

 

int main(){

    bar();

    return 0;

}

 

Additionally, we are going to introduce a new declspec allowing a developer to selectively disable GS protection from a particular function. Marking a function as __declspec(safebuffers)  tells the compiler that the buffers in this function are safe and it does not need security cookie protection.  We are going to provide users the option to choose different level of GS protections through /GS:n: /GS:1 is equivalent to the existing /GS in VC++ 2005 and 2008 and /GS:2 is the widened scope protection. /GS is the compiler’s default setting and maps to /GS:2.

Conclusion:

With the continuing enhancement of the Visual C++ compiler and the GS switch, VC++ compiler team is one step further to help the customers improve the security and reliability of their applications. 

 

Thank you,

Hongwei Qi

Note*: The widened scope of GS switch feature will be in VC++ 2010 beta1 release and the GS Optimization will be in post beta1.

  • PingBack from http://blog.a-foton.ru/index.php/2009/03/20/gs/

  • Looks like the Bar function contains a format string vulnerability?

  • El blog del equipo de Visual C++ de Microsoft ha publicado una muy interesante entrada sobre trampas

  • when is VC++ 2010 beta1 release?

  • regarding this comment: "Looks like the Bar function contains a format string vulnerability?"

    I don't see a problem with it.

  • You need to really, really improve GS since right now it's useless. Just the other day, I wrote several tests involving buffer overrun and GS didn't catch a single one. I see no point in bloating the code just for a feature so poorly implemented. Now you say you're going to bloat code and destroy performance even further! You people are insane.

    How about instead spending your time making a profiler and code checker that isn't complete rubbish and adding it to VS 2010 Pro? Hint, check out Boundschecker. Blows anything you guys have done out of the water. Only problem is that they charge $4000 for it.

    Right now, it seems Microsoft is just intent on completely missing the point of using C/C++ and in screwing over the developers once again. Thanks in advance.

  • In the compiler you currently have, only char and wchar arrays are protected by GS.  If you found a problem with such arrays, we would certainly like to know about so we can fix the problem.

    Protecting arrays of other types, such as int's, has been added to the compiler that ships with the upcoming BETA of dev10.

  • Friday, March 20, 2009 3:26 PM by Hongwei Qi

    # re: GS

    regarding this comment: "Looks like the Bar function contains a format string vulnerability?"

    I don't see a problem with it.

    ------------------------------------------

    If you want to print some thing out, it's more secure to write it like

    wprintf("%s", string);

  • Joe - slightly abrasively said... but I do agree with your sentiment and I keep asking this questions as well:

    "How about instead spending your time making a profiler and code checker that isn't complete rubbish and adding it to VS 2010 Pro? Hint, check out Boundschecker. Blows anything you guys have done out of the water. Only problem is that they charge $4000 for it."

  • It seems that it's becoming a tradition for comments to include outlandish requests such as "include a 4000$ profiler/checker in a 600$ product".

    I have a better idea Joe, why don't you write your own and then release it as opensource so we can all benefit?

    GS is useful and you get it for free with VC++. I'd rather have that and use Boundschecker / Purify if and when I need it, rather than having to pay 1500$ for VC++ Bug Hunter Edition.

  • >>> if the compiler improves its analytical ability and can better identify the functions where no GS cookie is needed, then the performance gain you get through reducing the unneeded guarding should offset the performance lost due to widening the range of protection.

    Nice jedi mind trick. "We'll add X instructions to your code. But then we'll optimize away X/2 instructions. The X/2 instructions we optimized away will cancel the X/2 instructions we ended up adding, so your code is just as fast as it was".

  • The statement level profiler was included in VS6.0 as a standard built in (no extra cost) feature.  Please add it to VS10 or at least VS10 professional as a standard buit in (no extra cost) feature.  

  • My name is Tony and i'm a hacker from Russia. Please turn off GS feature (and if possible SafeSEH etc) in next release of MSVC. It is very difficult to gain money, my family need more food.

    At least it is up to user - if she will not switch it ON - that is only her problem. Right?

    Both Microsoft and I will be fine.

    p.s. And by the way. Please contact guys from Windows dev.team - is it possible to turn off DEP and ASLR by default?

  • Is there some way to improve GS, while accommodating the needs of somebody like Tony, yet benefiting all our end users?  Some sort of win-win-win compromise?

    One of the fantastic things about this blog is the amazing (dare I say "unrivaled") transparency.

    - Kudos yet again

  • to_be_defined: Using your argument we could start chucking features right and left. Why have any features at all?

    The point is that Microsoft does make a profiler and it's absolutely horrible. They are also pumping this /GS feature which is next to useless. They also have a memory leak detector which is also next to useless. Given how many other things Visual Studio does well, the extremely poor implementation of these features are very glaring.

    The other point is that Microsoft spends a tremendous amount of time and effort on extremely fringe features. They have ignored C++ for years and now claim to be returning to it. Yet many of the things they are concentrating on are still fringe instead of things that should have been a natural evolution of the VC++ 6.0 product.

    What is the difference between VS Standard and VS Pro? Pro offers Windows Mobile support and remote debugging. Big deal and big ripoff. Now if Pro offered a non-crappy profiler and memory checker, I'd upgrade.

Page 1 of 2 (21 items) 12