The spree of exploits on Windows has led to the creation of a certain type of exploit protection mechanism on Windows. Protection from things like buffer overflow, heap overwrite and return originated exploits have been deployed on Windows compilers and OS.

They can be either OS specific or compiler based protections. EMET can be used to apply some of these protections on Windows binaries.

According to Microsoft:

“The Enhanced Mitigation Experience Toolkit (EMET) is a utility that helps prevent vulnerabilities in software from being successfully exploited. EMET achieves this goal by using security mitigation technologies. These technologies function as special protections and obstacles that an exploit author must defeat to exploit software vulnerabilities. These security mitigation technologies do not guarantee that vulnerabilities cannot be exploited. However, they work to make exploitation as difficult as possible to perform.”

Compiler protections included in MSVC are:

/GF enable read-only string pooling     /Gm[-] enable minimal rebuild

/Gy[-] separate functions for linker    /GS[-] enable security checks

/GR[-] enable C++ RTTI                  /GX[-] enable C++ EH (same as /EHsc)

/EHs enable C++ EH (no SEH exceptions)  /EHa enable C++ EH (w/ SEH exceptions)

/EHc extern "C" defaults to nothrow     

/Qfast_transcendentals generate inline FP intrinsics even with /fp:except

/GL[-] enable link-time code generation /GA optimize for Windows Application

/Ge force stack checking for all funcs  /Gs[num] control stack checking calls

/Gh enable _penter function call        /GH enable _pexit function call

/GT generate fiber-safe TLS accesses    /RTC1 Enable fast checks (/RTCsu)

/RTCc Convert to smaller type checks    /RTCs Stack Frame runtime checking

/RTCu Uninitialized local usage checks  

/clr[:option] compile for common language runtime, where option is:
    pure - produce IL-only output file (no native executable code)
    safe - produce IL-only verifiable output file
    oldSyntax - accept the Managed Extensions syntax from Visual C++ 2002/2003
    initialAppDomain - enable initial AppDomain behavior of Visual C++ 2002
    noAssembly - do not produce an assembly

/Gd __cdecl calling convention          /Gr __fastcall calling convention

/Gz __stdcall calling convention        /GZ Enable stack checks (/RTCs)

/QIfist[-] use FIST instead of ftol()   

/hotpatch ensure function padding for hotpatchable images

/arch:<SSE|SSE2|AVX> minimum CPU architecture requirements, one of:
    SSE - enable use of instructions available with SSE enabled CPUs
    SSE2 - enable use of instructions available with SSE2 enabled CPUs
    AVX - enable use of Intel(R) Advanced Vector Extensions instructions

/Qimprecise_fwaits generate FWAITs only on "try" boundaries, not inside "try"

/Qsafe_fp_loads generate safe FP loads

So it makes exploitation difficult but does not ultimately protect against it.

Ethical Hacking Training – Resources (InfoSec)

Stack-Based OverRun Detection (GS)

This is the oldest and most famous protection available in Visual C++. The goal of the /GS compiler flag is simple: reduce the chance that maleficent code will execute correctly. The /GS option is on by default in Visual C++ 2003 and later, and it detects certain kinds of stack smash at run time. It goes about doing this by including a desultory number in a function’s stack just before the return address on the stack, and when the function returns, the function epilogue code checks this value to ascertain it has not transmuted. If the cookie, as it’s called, has been mutated, execution is halted.

So GS stack cookie basically protects against tampering of return addresses. Now let’s go into detail how it works:

Consider the following C code compiled using /GS parameter of Microsoft C compiler:

{c]
#include

void vuln()
{
unsigned char x[10] = {0};
int i = 0;
while (i != 100)
x[i++] = ‘A’;
}
int main(int argc, char **agrv)
{
vuln();
}
[/c]

If we compile it using MSVC switch /GS it would get the GS stack-based protection embedded. Let’s see what is added at the vuln function for GS stack protection.

Stack Cookie Resides soon after Saved EBP i.e EBP-4 as shown in the IDA disassembly:

As you can see in the beginning of the prologue of the function, the __security_cookie is retrieved and xored with EBP. So if the attacker had to overwrite the return address he needs to guess the __security_cookie as clearly we see that it will also get overwritten. Now let’s see how it is generated and if it contains enough randomness in order to be secure.

This value is generated in ___security_init_cookie() function which looks like:

___security_init_cookie proc near       ; CODE XREF: $LN26#p
.text:0040267F
.text:0040267F PerformanceCount= LARGE_INTEGER ptr -10h
.text:0040267F SystemTimeAsFileTime= _FILETIME ptr -8
.text:0040267F
.text:0040267F                 mov     edi, edi
.text:00402681                 push    ebp
.text:00402682                 mov     ebp, esp
.text:00402684                 sub     esp, 10h
.text:00402687                 mov     eax, ___security_cookie
.text:0040268C                 and     [ebp+SystemTimeAsFileTime.dwLowDateTime], 0
.text:00402690                 and     [ebp+SystemTimeAsFileTime.dwHighDateTime], 0
.text:00402694                 push    ebx
.text:00402695                 push    edi
.text:00402696                 mov     edi, 0BB40E64Eh
.text:0040269B                 mov     ebx, 0FFFF0000h
.text:004026A0                 cmp     eax, edi
.text:004026A2                 jz      short loc_4026B1
.text:004026A4                 test    ebx, eax
.text:004026A6                 jz      short loc_4026B1
.text:004026A8                 not     eax
.text:004026AA                 mov     dword_408004, eax
.text:004026AF                 jmp     short loc_402716
.text:004026B1 ; ---------------------------------------------------------------------------
.text:004026B1
.text:004026B1 loc_4026B1:                             ; CODE XREF: ___security_init_cookie+23#j
.text:004026B1                                         ; ___security_init_cookie+27#j
.text:004026B1                 push    esi
.text:004026B2                 lea     eax, [ebp+SystemTimeAsFileTime]
.text:004026B5                 push    eax             ; lpSystemTimeAsFileTime
.text:004026B6                 call    ds:GetSystemTimeAsFileTime
.text:004026BC                 mov     esi, [ebp+SystemTimeAsFileTime.dwHighDateTime]
.text:004026BF                 xor     esi, [ebp+SystemTimeAsFileTime.dwLowDateTime]
.text:004026C2                 call    ds:GetCurrentProcessId
.text:004026C8                 xor     esi, eax
.text:004026CA                 call    ds:GetCurrentThreadId
.text:004026D0                 xor     esi, eax
.text:004026D2                 call    ds:GetTickCount
.text:004026D8                 xor     esi, eax
.text:004026DA                 lea     eax, [ebp+PerformanceCount]
.text:004026DD                 push    eax             ; lpPerformanceCount
.text:004026DE                 call    ds:QueryPerformanceCounter
.text:004026E4                 mov     eax, dword ptr [ebp+PerformanceCount+4]
.text:004026E7                 xor     eax, dword ptr [ebp+PerformanceCount]
.text:004026EA                 xor     esi, eax
.text:004026EC                 cmp     esi, edi
.text:004026EE                 jnz     short loc_4026F7
.text:004026F0                 mov     esi, 0BB40E64Fh
.text:004026F5                 jmp     short loc_402707
.text:004026F7 ; ---------------------------------------------------------------------------
.text:004026F7
.text:004026F7 loc_4026F7:                             ; CODE XREF: ___security_init_cookie+6F#j
.text:004026F7                 test    ebx, esi
.text:004026F9                 jnz     short loc_402707
.text:004026FB                 mov     eax, esi
.text:004026FD                 or      eax, 4711h
.text:00402702                 shl     eax, 10h
.text:00402705                 or      esi, eax
.text:00402707
.text:00402707 loc_402707:                             ; CODE XREF: ___security_init_cookie+76#j
.text:00402707                                         ; ___security_init_cookie+7A#j
.text:00402707                 mov     ___security_cookie, esi
.text:0040270D                 not     esi
.text:0040270F                 mov     dword_408004, esi
.text:00402715                 pop     esi
.text:00402716
.text:00402716 loc_402716:                             ; CODE XREF: ___security_init_cookie+30#j
.text:00402716                 pop     edi
.text:00402717                 pop     ebx
.text:00402718                 leave
.text:00402719                 retn
.text:00402719 ___security_init_cookie endp

Firstly, it will compare __security_cookie with the default value:

mov     edi, 0BB40E64Eh
mov     ebx, 0FFFF0000h

And if matched it will continue to generate a random one. The random value for __security_cookie is generated as a combination of xors for time, processid, threadid, tickcount and QueryPerformanceCounter() values.

And then xored and multiplied.

or      eax, 4711h
shl     eax, 10h

In the epilogue of a function protected by GS stack cookie you will see a call to __security_check_cookie() function which verifies the __security_cookie, and if it is manipulated the process terminates. So done in this way before returning to the attacker controlled area which leverages ret instruction is prevented.

SAFESEH

SAFESEH was added from Windows XP Sp2. It is an operating system protection technique by which we can protect against SEH overwrites. This technique isn’t available on 64 bit systems, as 64 bit Windows uses a different mechanism for exception handling, which is quite similar to what is used on SAFESEH.

A binary is only protected by SAFESEH only if it is explicitly mentioned on the PE header. To check the existence of that header, we can use the Dumpbin tool by Microsoft by using the following command line:

dumpbin sample.exe /LOADCONFIG

File Type: EXECUTABLE IMAGE

  Section contains the following load config:

            00000048 size
                   0 time date stamp
                0.00 Version
                   0 GlobalFlags Clear
                   0 GlobalFlags Set
                   0 Critical Section Default Timeout
                   0 Decommit Free Block Threshold
                   0 Decommit Total Free Threshold
            00000000 Lock Prefix Table
                   0 Maximum Allocation Size
                   0 Virtual Memory Threshold
                   0 Process Heap Flags
                   0 Process Affinity Mask
                   0 CSD Version
                0000 Reserved
            00000000 Edit list
            00408310 Security Cookie
            00407840 Safe Exception Handler Table
                   3 Safe Exception Handler Count

Safe Exception Handler Table

Address
——–
00402390
00403FD0
00405040

When an exception occurs, th exception is transferred to the SAFESEH handler in ntdll.dll and it checks if the exception target is present in the SAFESEH list. Following is the implementation of RtlCaptureImageExceptionValues on Windows XP sp2.

If the target address isn’t present in the list, then RtlCallKernel32UnhandledExceptionFilter is called to terminate the program.