Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
First Commit!
  • Loading branch information
stephenfewer committed Apr 21, 2011
0 parents commit 41bcc4b
Show file tree
Hide file tree
Showing 12 changed files with 3,380 additions and 0 deletions.
245 changes: 245 additions & 0 deletions OllyHeapTrace.bdsproj

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions OllyHeapTraceGroup.bdsgroup
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<BorlandProject>
<PersonalityInfo>
<Option>
<Option Name="Personality">Default.Personality</Option>
<Option Name="ProjectType"></Option>
<Option Name="Version">1.0</Option>
<Option Name="GUID">{F65F2A2F-3057-443F-9415-22DE0E9A2AAE}</Option>
</Option>
</PersonalityInfo>
<Default.Personality>

<Projects>
<Projects Name="OllyHeapTrace.dll">OllyHeapTrace.bdsproj</Projects>
<Projects Name="Targets">OllyHeapTrace.dll</Projects>
</Projects>
<Dependencies/>
</Default.Personality>
</BorlandProject>
58 changes: 58 additions & 0 deletions Readme.txt
@@ -0,0 +1,58 @@
OllyHeapTrace v1.1 (18 July 2008)

By Stephen Fewer of Harmony Security (www.harmonysecurity.com)

----[About]-------------------------------------------------------------
OllyHeapTrace is a plugin for OllyDbg (version 1.10) to trace the heap
operations being performed by a process. It will monitor heap
allocations and frees for multiple heaps, as well as operations such as
creating or destroying heaps and reallocations. All parameters as well
as return values are recorded and the trace is highlighted with a unique
colour for each heap being traced.

The primary purpose of this plugin is to aid in the debugging of heap
overflows where you wish to be able to control the heap layout to
overwrite a specific structure such as a chunk header, critical section
structure or some application specific data. By tracing the heap
operations performed during actions you can control (for example opening
a connection, sending a packet, closing a connection) you can begin to
predict the heap operations and thus control the heap layout.

----[Usage]-------------------------------------------------------------
Simply install the plugin and activate OllyHeapTrace when you wish to
begin tracing heap operations. OllyHeapTrace will automatically create
the breakpoints needed (RtlAllocateHeap, RtlFreeHeap, RtlCreateHeap,
RtlDestroyHeap, RtlReAllocateHeap, RtlSizeHeap, GetProcessHeap and
RtlInitializeCriticalSection, RtlDeleteCriticalSection) and record the
relevant information when these breakpoints are hit. To view the
heap trace select the OllyHeapTrace Log.

Double clicking on any row in the OllyHeapTrace Log window will bring
you to the callers location in the OllyDbg disassembly window. The
recorded heap trace is highlighted with a unique colour for each heap
being traced. Right clicking on any row will give you some options such
as to view the heap chunks data or the heap itself (only a raw dump of
the memory is given, no parsing of the heap structures is performed).
You can also filter out unwanted information if you are only concerned
with a specific heap.

OllyHeapTrace has been successfully tested on:
+ Windows 2000 SP4
+ Windows XP SP3
+ Windows Server 2003 SP2
+ Windows Vista SP1
+ Windows Server 2008 SP1

----[License]-----------------------------------------------------------
The OllyHeapTrace source code is available under the GPLv3 license,
please see the included file gpl-3.0.txt for details.

----[Changelog]---------------------------------------------------------
v1.1 - 18 July 2008
+ Bug fix in RtlSizeHeap and InitializeCriticalSection hooks.
+ Added hooks for RtlDeleteCriticalSection, RtlInitializeCriticalSection
+ Allow plugin to enable even when all hooks are not created.
+ Removed ability to see 8 bytes before heap chunk.

v1.0 - 14 December 2007
+ Initial release
Binary file added bin/OLLYDBG.LIB
Binary file not shown.
Binary file added bin/OllyHeapTrace.dll
Binary file not shown.
674 changes: 674 additions & 0 deletions gpl-3.0.txt

Large diffs are not rendered by default.

Binary file added screenshot1.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/OllyHeapTrace.res
Binary file not shown.
1,599 changes: 1,599 additions & 0 deletions src/Plugin.h

Large diffs are not rendered by default.

194 changes: 194 additions & 0 deletions src/hooks.c
@@ -0,0 +1,194 @@
//---------------------------------------------------------------------------
// OllyHeapTrace - A Heap Tracer plugin for OllyDbg
// By Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// Copyright (c) 2008 Stephen Fewer of Harmony Security
//---------------------------------------------------------------------------
#include <stdio.h>
//#include <stdlib.h>

#include "hooks.h"

extern DWORD dwProcessHeap;

struct HEAPFLAGS
{
DWORD dwValue;
const char * cpName;
};
//---------------------------------------------------------------------------
struct HEAPFLAGS flags[] = {

{ HEAP_GENERATE_EXCEPTIONS, "HEAP_GENERATE_EXCEPTIONS" },
{ HEAP_NO_SERIALIZE, "HEAP_NO_SERIALIZE" },
{ HEAP_ZERO_MEMORY, "HEAP_ZERO_MEMORY" },

{ NULL, NULL }
};
//---------------------------------------------------------------------------
VOID ResolveHeapFlags( DWORD dwFlags, char * cpOutput )
{
int iCount = 0, i = 0;
memset( cpOutput, 0, MAX_PATH );

while( flags[i].cpName != NULL )
{
if( dwFlags & flags[i].dwValue == flags[i].dwValue )
{
if( iCount > 0 )
strcat( cpOutput, " | " );
strcat( cpOutput, flags[i].cpName );
iCount++;
}
i++;
}

if( iCount == 0 )
strcat( cpOutput, "0" );
}
//---------------------------------------------------------------------------
BOOL DefaultDWORD_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "0x%.8X", pRegisters->r[REG_EAX] );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL DefaultINT_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "%d", pRegisters->r[REG_EAX] );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL DefaultBOOL_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "%s", (pRegisters->r[REG_EAX] ? "TRUE" : "FALSE" ) );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlInitializeCriticalSection_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
DWORD dwParameter;
Readmemory( &dwParameter, pRegisters->r[REG_ESP]+4, 4, MM_SILENT );
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlInitializeCriticalSection( 0x%.8X )", dwParameter );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlDeleteCriticalSection_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
DWORD dwParameter;
Readmemory( &dwParameter, pRegisters->r[REG_ESP]+4, 4, MM_SILENT );
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlDeleteCriticalSection( 0x%.8X )", dwParameter );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlAllocateHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
char cFlagsOutput[MAX_PATH];
DWORD dwParameters[3];
Readmemory( &dwParameters, pRegisters->r[REG_ESP]+4, 12, MM_SILENT );
ResolveHeapFlags( dwParameters[1], (char *)&cFlagsOutput );
if( dwProcessHeap != NULL && dwParameters[0] == dwProcessHeap )
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlAllocateHeap( GetProcessHeap(), %s, %d )", cFlagsOutput, dwParameters[2] );
else
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlAllocateHeap( 0x%.8X, %s, %d )", dwParameters[0], cFlagsOutput, dwParameters[2] );
pLogData->dwHeap = dwParameters[0];
pLogData->dwHeapBlockSize = dwParameters[2];
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlAllocateHeap_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
pLogData->dwHeapBlock = pRegisters->r[REG_EAX];
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "0x%.8X", pLogData->dwHeapBlock );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlReAllocateHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
char cFlagsOutput[MAX_PATH];
DWORD dwParameters[4];
Readmemory( &dwParameters, pRegisters->r[REG_ESP]+4, 16, MM_SILENT );
ResolveHeapFlags( dwParameters[1], (char *)&cFlagsOutput );
if( dwProcessHeap != NULL && dwParameters[0] == dwProcessHeap )
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlReAllocateHeap( GetProcessHeap(), %s, 0x%.8X, %d )", cFlagsOutput, dwParameters[2], dwParameters[3] );
else
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlReAllocateHeap( 0x%.8X, %s, 0x%.8X, %d )", dwParameters[0], cFlagsOutput, dwParameters[2], dwParameters[3] );
pLogData->dwHeap = dwParameters[0];
pLogData->dwHeapBlockSize = dwParameters[3];
pLogData->dwHeapBlock = dwParameters[2];
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlFreeHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
char cFlagsOutput[MAX_PATH];
DWORD dwParameters[3];
Readmemory( &dwParameters, pRegisters->r[REG_ESP]+4, 12, MM_SILENT );
ResolveHeapFlags( dwParameters[1], (char *)&cFlagsOutput );
if( dwProcessHeap != NULL && dwParameters[0] == dwProcessHeap )
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlFreeHeap( GetProcessHeap(), %s, 0x%.8X )", cFlagsOutput, dwParameters[2] );
else
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlFreeHeap( 0x%.8X, %s, 0x%.8X )", dwParameters[0], cFlagsOutput, dwParameters[2] );
pLogData->dwHeap = dwParameters[0];
pLogData->dwHeapBlock = dwParameters[2];
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlCreateHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
char cFlagsOutput[MAX_PATH];
DWORD dwParameters[3];
Readmemory( &dwParameters, pRegisters->r[REG_ESP]+4, 12, MM_SILENT );
ResolveHeapFlags( dwParameters[0], (char *)&cFlagsOutput );
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlCreateHeap( %s, %d, %d )", cFlagsOutput, dwParameters[1], dwParameters[2] );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlCreateHeap_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "0x%.8X", pRegisters->r[REG_EAX] );
pLogData->dwHeap = pRegisters->r[REG_EAX];
return TRUE;
}
//---------------------------------------------------------------------------
BOOL GetProcessHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
snprintf( pLogData->cMessage, BUFFER_SIZE, "GetProcessHeap()" );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL GetProcessHeap_Return( LPLOGDATA pLogData, t_reg * pRegisters )
{
dwProcessHeap = pRegisters->r[REG_EAX];
snprintf( pLogData->cReturnMessage, BUFFER_SIZE, "0x%.8X", dwProcessHeap );
pLogData->dwHeap = dwProcessHeap;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlDestroyHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
DWORD dwParameter;
Readmemory( &dwParameter, pRegisters->r[REG_ESP]+4, 4, MM_SILENT );
if( dwProcessHeap != NULL && dwParameter == dwProcessHeap )
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlDestroyHeap( GetProcessHeap() )" );
else
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlDestroyHeap( 0x%.8X )", dwParameter );
pLogData->dwHeap = dwParameter;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL RtlSizeHeap_Call( LPLOGDATA pLogData, t_reg * pRegisters )
{
char cFlagsOutput[MAX_PATH];
DWORD dwParameters[3];
Readmemory( &dwParameters, pRegisters->r[REG_ESP]+4, 12, MM_SILENT );
ResolveHeapFlags( dwParameters[1], (char *)&cFlagsOutput );
if( dwProcessHeap != NULL && dwParameters[0] == dwProcessHeap )
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlSizeHeap( GetProcessHeap(), %s, 0x%.8X )", cFlagsOutput, dwParameters[2] );
else
snprintf( pLogData->cMessage, BUFFER_SIZE, "RtlSizeHeap( 0x%.8X, %s, 0x%.8X )", dwParameters[0], cFlagsOutput, dwParameters[2] );
pLogData->dwHeap = dwParameters[0];
pLogData->dwHeapBlock = dwParameters[2];
return TRUE;
}
//---------------------------------------------------------------------------

65 changes: 65 additions & 0 deletions src/hooks.h
@@ -0,0 +1,65 @@
//---------------------------------------------------------------------------
// OllyHeapTrace - A Heap Tracer plugin for OllyDbg
// By Stephen Fewer of Harmony Security (www.harmonysecurity.com)
// Copyright (c) 2008 Stephen Fewer of Harmony Security
//---------------------------------------------------------------------------
#ifndef HOOKS_H
#define HOOKS_h

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "Plugin.h"

#pragma nopackwarning

#define BUFFER_SIZE 256

typedef struct _LOGDATA
{
DWORD dwAddress;
DWORD dwSize;
DWORD dwType;

DWORD dwCallerAddress;
DWORD dwThreadId;
DWORD dwHeap;
DWORD dwHeapBlock;
DWORD dwHeapBlockSize;
char cMessage[BUFFER_SIZE];
char cReturnMessage[BUFFER_SIZE];
BOOL bReturnMessageSet;
int iHookIndex;

} LOGDATA, * LPLOGDATA;

typedef BOOL (* HOOK_FUNC)( LPLOGDATA pLogData, t_reg * pRegisters );

struct HOOK
{
const char * cpModuleName;
const char * cpFunctionName;
DWORD dwFunctionAddress;
HOOK_FUNC handle_call;
HOOK_FUNC handle_return;
};

BOOL DefaultDWORD_Return( LPLOGDATA, t_reg * );
BOOL DefaultBOOL_Return( LPLOGDATA, t_reg * );
BOOL DefaultINT_Return( LPLOGDATA, t_reg * );

BOOL RtlInitializeCriticalSection_Call( LPLOGDATA, t_reg * );
BOOL RtlDeleteCriticalSection_Call( LPLOGDATA, t_reg * );

BOOL RtlAllocateHeap_Call( LPLOGDATA , t_reg * );
BOOL RtlAllocateHeap_Return( LPLOGDATA , t_reg * );
BOOL RtlReAllocateHeap_Call( LPLOGDATA , t_reg * );
BOOL RtlFreeHeap_Call( LPLOGDATA , t_reg * );
BOOL RtlCreateHeap_Call( LPLOGDATA , t_reg * );
BOOL RtlCreateHeap_Return( LPLOGDATA, t_reg * );
BOOL GetProcessHeap_Call( LPLOGDATA , t_reg * );
BOOL GetProcessHeap_Return( LPLOGDATA, t_reg * );
BOOL RtlDestroyHeap_Call( LPLOGDATA, t_reg * );
BOOL RtlSizeHeap_Call( LPLOGDATA, t_reg * );

#endif

0 comments on commit 41bcc4b

Please sign in to comment.