The blog continues at suszter.com/ReversingOnWindows

May 19, 2012

Test for termination on heap corruption flag in Windbg

This note describes two ways to verify the heap manager settings if the termination on corruption flag is enabled. Both of them require Windbg.
  1. Execute the below command to print the value of the disable break on failure cookie. If the value is zero the termination on heap corruption flag is set, otherwise it's unset. For more details about this see the previous post.
    0:031> db ntdll!RtlpDisableBreakOnFailureCookie L4
    77230098 aa cb 7f 69 ...i
  2. Another way is to execute the following command to print if the termination on heap corruption is enabled.
    0:031> !heap -s
    LFH Key : 0x726d2f4c
    Termination on corruption : DISABLED
I checked the popular browsers (32-bit version) if they have the termination on heap corruption feature enabled. Here is the result.
Internet Explorer: ENABLED
Chrome: ENABLED
Mozilla Firefox: DISABLED
I asked Mozilla what's the reason to not enable this mitigation but haven't heard back from them so far.

May 13, 2012

About termination on heap corruption feature

The following line enables the feature to terminate the process if heap corruption is detected by the Windows heap manager.
BOOL bResult = HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
I created a simple application calling the above function, and loaded it in Windbg to trace how the feature is enabled.

At line 77396d11 there is a check if HeapEnableTerminationOnCorruption, that is 1, is specified.
77396d11 837d0c01        cmp dword ptr [ebp+0Ch],1
77396d15 7507            jne ntdll!RtlSetHeapInformation+0x59 (77396d1e)
77396d17 83259800447700  and dword ptr [ntdll!RtlpDisableBreakOnFailureCookie (77440098)],0
77396d1e 33c0            xor eax,eax
As it can be seen, if HeapEnableTerminationOnCorruption is specified, [RtlpDisableBreakOnFailureCookie] is set to zero.

As the next step, a simple application that intentionally corrupts the heap was created. I placed a breakpoint to see what happens when [RtlpDisableBreakOnFailureCookie] is accessed.

When the breakpoint hit, I got the code snippet below. The caller function was RtlpReportHeapFailure implying heap failure, so I have reason to think the code snippet is not reached unless heap corruption is encountered.

RtlpGetModifiedProcessCookie returns with a cookie value, and I observed that value was the same to the initial value of [RtlpDisableBreakOnFailureCookie].
7740f5ad e8e67cf7ff      call ntdll!RtlpGetModifiedProcessCookie (77387298)
7740f5b2 390598004477    cmp dword ptr [ntdll!RtlpDisableBreakOnFailureCookie (77440098)],eax
7740f5b8 7411            je ntdll!RtlpReportHeapFailure+0x23 (7740f5cb)
7740f5ba 6868424477      push offset ntdll!RtlpHeapFailureInfo (77444268)
7740f5bf 68740300c0      push 0C0000374h
7740f5c4 e8a3f0ffff      call ntdll!RtlReportCriticalFailure (7740e66c)
7740f5c9 eb1a            jmp ntdll!RtlpReportHeapFailure+0x3d (7740f5e5)
7740f5cb 8b4508          mov eax,dword ptr [ebp+8]
7740f5ce 3b0540674477    cmp eax,dword ptr [ntdll!RtlpHeapErrorHandlerThreshold (77446740)]
7740f5d4 7f0f            jg ntdll!RtlpReportHeapFailure+0x3d (7740f5e5)
7740f5d6 e864f1ffff      call ntdll!RtlpPrintErrorInformation (7740e73f)
7740f5db e840f0ffff      call ntdll!RtlIsAnyDebuggerPresent (7740e620)
7740f5e0 84c0            test al,al
7740f5e2 7401            je ntdll!RtlpReportHeapFailure+0x3d (7740f5e5)
7740f5e4 cc              int 3
7740f5e5 5d              pop ebp
7740f5e6 c20400          ret 4
At line 7740f5b2 the cookie value [RtlpDisableBreakOnFailureCookie] is being compared against the return cookie value of RtlpGetModifiedProcessCookie.

I observed the following situations are possible.
  • HeapEnableTerminationOnCorruption is unset, and the heap is corrupted. In that case at line 7740f5b8 the jump is taken and the process might not be immediately terminated.
  • HeapEnableTerminationOnCorruption is set, and the heap is corrupted. In that case at line 7740f5b8 the jump is not taken and the process is to be immediately terminated.

May 12, 2012

Minimum set up to use Windbg from Visual Studio

Below is an example to set up Windbg in Visual C++ 2010 Express.

Select Tools, then select External Tools... in Visual C++. Click on Add and provide the followings.
Title &Windbg
Command C:\Program Files (x86)\Debugging Tools for Windows (x86)\windbg.exe
Arguments -srcpath $(ProjectDir) $(TargetPath)
Initial directory $(TargetDir)
Save the configuration and test if it works. Open a project that builds an executable file. Select Tools, then select Windbg to start the debugger. In the command window type .open example.cpp to load the source code. The source window should pop up with the source file in it. Move the cursor in the source window and press F9 to place a breakpoint.

May 6, 2012

Guide to create Windbg extension in Visual Studio 2010

I'm describing a way to create an extension for Windbg in Visual Studio 2010 Express. The description is applied for the 32-bit version of Windows debugger but the same steps could be easily adopted for the 64-bit debugger. If you're not interested in setting up a Visual Studio configuration, but want a sample extension, you can download one from CodePlex. That one was created using the steps below.

Create an Empty Visual C++ Project and save the solution as sampext. Add sampext.cpp to the project with the following content.
#include "sampext.h"

EXT_DECLARE_GLOBALS();

EXT_CLASS::EXT_CLASS()
{
}
Add sampext.h to the project with the following content.
#pragma once
#include "engextcpp.hpp"

class EXT_CLASS : public ExtExtension
{
protected:

public:
    EXT_CLASS();
    EXT_COMMAND_METHOD(ver);
};
Add ver.cpp to the project file with the following content. This file contains the implementation of the sample command.
#include "ver.h"

EXT_COMMAND(ver,
            "Shows version number of the extension.\n",
            ""
)
{
    g_Ext->Out("Sample Windbg Extension in Visual Studio v0.1\n");
}
Add ver.h, too.
#pragma once

#include "sampext.h"
Add sampext.def that is the definition file.
EXPORTS

;--------------------------------------------------------------------
; Core exports provided by the ExtCpp framework.
;--------------------------------------------------------------------

    DebugExtensionInitialize
    DebugExtensionUninitialize
    DebugExtensionNotify
    help

;--------------------------------------------------------------------
; Extension commands.
;--------------------------------------------------------------------

    ver
Create a folder called sdk in the solution folder.

Copy the inc and lib folders from the sdk folder of Windbg to the sdk folder of the solution.

Set the configuration type of the project to Dynamic Library DLL.

Add $(SolutionDir)sdk\inc to the additional include directories.

Add $(SolutionDir)sdk\lib\i386 to the additional library dependencies.

Add engextcpp.lib to the additional dependencies in the linker input.

Set up the module definition file to samplext.def in the linker input.

The extension is now ready to be built.

May 2, 2012

An example when /sdl flag doesn't work in Visual Studio 11 Beta

Microsoft introduced a new compiler defense in Visual Studio 11 Beta that is to mitigate simple dangling pointer bugs. When the memory has been freed using the delete operator the pointer is set to 0x8123.

Here is an example when 0x8123 set.
    delete [] ptr;
push edi
call dword ptr ds:[12E2094h]
mov eax,8123h
test edi,edi
cmovne edi,eax

However, consider the following code snippet.
void* arr[1];

arr[0] = new BYTE[MAX];

delete [] arr[0];
delete [] arr[0];
I compiled the code and realized there is no sanitization.
push esi
    void* arr[1];

    arr[0] = new BYTE[MAX];
push 7Bh
call dword ptr ds:[12A2090h]
mov esi,eax


    delete [] arr[0];
push esi
call dword ptr ds:[12A2094h]

    delete [] arr[0];
push esi
call dword ptr ds:[12A2094h]
add esp,0Ch


    return 0;
xor eax,eax
pop esi

I asked Microsoft about this issue, and they confirmed that the /sdl flag doesn't work in this scenario. The reason is that in line delete [] arr[0], the expression arr[0] passed into the delete call is dereference. VS11 provides initial support for pointer sanitization when "the expression passed into the delete call does not involve a dereference." For more info see their blog post.
  This blog is written and maintained by Attila Suszter. Read in Feed Reader.