RtlQueryProcessHeapInformation As Anti-Dbg Trick

April 14, 2009

Hi,

Directly derived from the previous trick, RtlQueryProcessHeapInformation could be used as Anti-Dbg Trick.

Starting by RtlQueryProcessDebugInformation.

NTSTATUS
NTAPI
RtlQueryProcessDebugInformation(
IN ULONG  ProcessId,
IN ULONG  DebugInfoClassMask,
IN OUT PDEBUG_BUFFER  DebugBuffer);

This function loads all heap blocks of the process into DebugBuffer according to the informations that we want and that could be specified throughout DebugInfoClassMask. If we implement RtlQueryProcessDebugInformation in this way

void QueryDbgBufferMethod(void)
{
PDEBUG_BUFFER buffer;
NTSTATUS ntStatus;

buffer = RtlCreateQueryDebugBuffer(0,FALSE);

ntStatus = RtlQueryProcessDebugInformation(GetCurrentProcessId(),
PDI_HEAPS|PDI_HEAP_BLOCKS,
buffer);

The function according to the chosen mask will internally execute an call for heap functions, let’s see what happens inside this function.

__stdcall RtlQueryProcessDebugInformation(x, x, x)
7C9638EB                 mov     edi, edi
7C9638ED                 push    ebp
7C9638EE                 mov     ebp, esp
7C9638F0                 sub     esp, 44h
7C9638F3                 mov     eax, [ebp+14] ;EAX = DebugMassk
7C9638F6                 push    ebx
7C9638F7                 push    esi
7C9638F8                 mov     esi, [ebp+arg_8] ;ESI = DEBUG_BUFFER
7C9638FB                 xor     ebx, ebx
7C9638FD                 mov     [esi+20h], eax
7C963900                 mov     eax, [esi+24h]
7C963903                 cmp     eax, ebx
7C963905                 push    edi
7C963906                 mov     [ebp+var_4], ebx
7C963909                 mov     [ebp+var_8], ebx
7C96390C                 jz      short loc_7C963924
..
7C963924                 mov     dword ptr [esi+24h], 60h
7C96392B                 mov     eax, large fs:18h
7C963931                 mov     edi, [ebp+arg_0]
7C963934                 cmp     [eax+20h], edi
7C963937                 jz      short loc_7C963987
7C963939                 test    byte ptr [ebp+arg_4+3], 80h
7C96393D                 jz      short loc_7C963987
7C96393F                 test    byte ptr [ebp+0Ch], 41h
7C963943                 jz      short loc_7C963987
..
7C963987                 mov     eax, large fs:18h
7C96398D                 cmp     [eax+20h], edi
7C963990                 jz      loc_7C963A8E
7C963996                 cmp     [ebp+var_8], ebx

..

Here DebugMask Switch Cases:

7C963AA7                 test    byte ptr [ebp+arg_4], 2
7C963AAB                 jz      short loc_7C963ABA
7C963AAD                 push    esi
7C963AAE                 call    _RtlQueryProcessBackTraceInformation
7C963AB3                 cmp     eax, ebx
7C963AB5                 mov     [ebp+var_4], eax
7C963AB8                 jnz     short loc_7C963ADC
7C963ABA                 test    byte ptr [ebp+arg_4], 20h
7C963ABE                 jz      short loc_7C963ACD
7C963AC0                 push    esi

7C963AC1                 call    _RtlQueryProcessLockInformation
7C963AC6                 cmp     eax, ebx
7C963AC8                 mov     [ebp+var_4], eax
7C963ACB                 jnz     short loc_7C963ADC
7C963ACD                 test    byte ptr [ebp+arg_4], 1Ch ; DebugMask = PDI_HEAPS|PDI_HEAP_BLOCKS (Our Case)
7C963AD1                 jz      short loc_7C963ADC
7C963AD3                 push    esi   ;DEBUG_BUFFER
7C963AD4                 call    _RtlQueryProcessHeapInformation
7C963AD9                 mov     [ebp+var_4], eax

As you can see when we use DebugMask = PDI_HEAPS|PDI_HEAP_BLOCKS, is only called
RtlQueryProcessHeapInformation, function that takes only DEBUG_BUFFER as parameter, this means that this function is only applicable for the Current Process since does not take PID.

; __stdcall RtlQueryProcessHeapInformation(x)
7C963249                 push    58h
7C96324B                 push    offset stru_7C963708
7C963250                 call    __SEH_prolog
7C963255                 push    4
7C963257                 mov     ebx, [ebp+arg_0]
7C96325A                 push    ebx     ;DEBUG_BUFFER
7C96325B                 call    _RtlpCommitQueryDebugInfo
7C963260                 mov     edi, eax
7C963262                 mov     [ebp+var_48], edi
7C963265                 test    edi, edi
7C963267                 jnz     short loc_7C963270
7C963269                 mov     eax, C0000017h ;EAX = STATUS_NO_MEMORY
7C96326E                 jmp     short loc_7C9632CD
7C963270                 mov     [ebx+38h], edi
7C963273                 call    _RtlpAcquireHeapListLock
7C963278                 and     [ebp+ms_exc.disabled], 0
7C96327C                 push    ebx

7C96327D                 push    offset _RtlpQueryProcessEnumHeapsRoutine 7C963282                 call    _RtlEnumProcessHeaps
7C963287                 mov     [ebp+var_20], eax
7C96328A                 test    eax, eax
7C96328C                 jl      loc_7C963422
7C963292                 test    byte ptr [ebx+20h], 8
7C963296                 jz      loc_7C963426
7C96329C                 mov     esi, _RtlpGlobalTagHeap
7C9632A2                 mov     [ebp+var_28], esi
7C9632A5                 cmp     dword ptr [esi+3Ch], 0
7C9632A9                 jz      short loc_7C9632E5
7C9632AB                 push    40h
7C9632AD                 push    ebx
7C9632AE                 call    _RtlpCommitQueryDebugInfo
7C9632B3                 mov     [ebp+var_4C], eax
7C9632B6                 test    eax, eax
7C9632B8                 jnz     short loc_7C9632D5
7C9632BA                 mov     [ebp+var_20], 0C0000017h
7C9632C1                 or      [ebp+ms_exc.disabled], 0FFFFFFFFh
7C9632C5                 call    sub_7C9636FE ; RtlpReleaseHeapListLoc
7C9632CA                 mov     eax, [ebp+var_20]
7C9632CD                 call    __SEH_epilog
7C9632D2                 retn    4

RtlQueryProcessHeapInformation essentially fills DEBUG_BUFFER by taking informations from heap blocks. RtlpCommitQueryDebugInfo prepairs buffer by calling NtAllocateVirtualMemory, if RtlpCommitQueryDebugInfo fails the error
(0xC0000017 – STATUS_NO_MEMORY with consequent corrupted DEBUG_BUFFER) propagates throughout  RtlQueryProcessHeapInformation and finally (if used) RtlQueryProcessDebugInformation. So if you use these functions it’s a best practice to implement a check for this error, especially if you are working in applications that walks heap. Finally here the check anti-dbg.

void QueryProcessHeapMethod(void)
{
PDEBUG_BUFFER buffer;

buffer = RtlCreateQueryDebugBuffer(0,FALSE);

RtlQueryProcessHeapInformation(buffer);

if (buffer->RemoteSectionBase == (PVOID) 0x50000062)
MessageBoxA(NULL,”Debugged”,”Warning”,MB_OK);
else
MessageBoxA(NULL,”Not Debugged”,”Warning”,MB_OK);
}

defs.h

extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlQueryProcessHeapInformation(
IN PDEBUG_BUFFER  DebugBuffer
);

The presence of RemoteXxx members is given to the fact that we need to avoid ther risk of a DeadLock that could happen when RtlQueryProcessDebugInformation request a remote information and consequently the debugger receives the thread start routine.

See you to the next post.. 🙂


Something about RtlQueryProcessDebugInformation

April 12, 2009

Hi,

Just a precisation, as you can see in the code I used psapi.lib, this is obviously not necessary for the code that I reported here, but can be used to enumerate all processes and by passing their PID to RtlQueryProcessDebugInformation we can inspect if there are debugged running processes It’s important to implement a check for the return value of RtlQueryProcessDebugInformation cause, for some PIDs it fails and we have a non sense DEBUG_BUFFER and a consequent non sense DEBUG_HEAP_INFORMATION. Implement a check for 0xC0000008 and 0xC0000017

See you to the next post.. 🙂


RtlQueryProcessDebugInformation as Anti-Dbg Trick

April 11, 2009

The Essay

The following paper will uncover some interesting undocumented

functions relative to Windows Heap Enumeration.

RtlCreateQueryDebugBuffer
RtlQueryProcessDebugInformation
RtlDestroyQueryDebugBuffer

Here the prototypes for each function:

PDEBUG_BUFFER
NTAPI
RtlCreateQueryDebugBuffer(
IN ULONG  Size,
IN BOOLEAN  EventPair);


NTSTATUS
NTAPI
RtlQueryProcessDebugInformation(
IN ULONG  ProcessId,
IN ULONG  DebugInfoClassMask,
IN OUT PDEBUG_BUFFER  DebugBuffer);


NTSTATUS
NTAPI
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER  DebugBuffer);

RtlCreateQueryDebugBuffer allocates buffer for storing heap data in case of success, it returns pointer to allocated debug buffer. Here the declaration of debug buffer:

typedef struct _DEBUG_BUFFER {
HANDLE  SectionHandle;
PVOID  SectionBase;
PVOID  RemoteSectionBase;
ULONG  SectionBaseDelta;
HANDLE  EventPairHandle;
ULONG  Unknown[2];
HANDLE  RemoteThreadHandle;
ULONG  InfoClassMask;
ULONG  SizeOfInfo;
ULONG  AllocatedSize;
ULONG  SectionSize;
PVOID  ModuleInformation;
PVOID  BackTraceInformation;
PVOID  HeapInformation;
PVOID  LockInformation;
PVOID  Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;

After the buffer allocation we can call the Heap Process Debug Information, we can call RtlQueryProcessDebugInformation to load all heap blocks of the process. This function loads entire heap nodes and corresponding heap blocks of the process. Debug Buffer contains the pointer to heap information structure at offset 0x38. First parameter of this heap structure is node count and after that it contains array of DEBUG_HEAP_INFORMATION structure which represent each heap node.

typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0x00
ULONG Flags; // 0x04
USHORT Granularity; // 0x08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0x10
ULONG TagCount; // 0x14
ULONG BlockCount; // 0x18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0x38
PVOID Blocks; // 0x3C Heap block pointer for this node.
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;

As you should know a debugged process presents different flags respect a not debugged one, here the sample anti-dbg code:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Psapi.h>
#include “defs.h”

#pragma comment(lib,”ntdll.lib”)
#pragma comment(lib,”psapi.lib”)

void QueryDbgBufferMethod(void)
{
PDEBUG_BUFFER buffer;
NTSTATUS ntStatus;

buffer = RtlCreateQueryDebugBuffer(0,FALSE);

ntStatus = RtlQueryProcessDebugInformation(GetCurrentProcessId(),
PDI_HEAPS|PDI_HEAP_BLOCKS,
buffer);

PDEBUG_HEAP_INFORMATION heapInfo = PDEBUG_HEAP_INFORMATION(PULONG(buffer->HeapInformation) + 1);

if (heapInfo->Flags == 0x50000062)
MessageBoxA(NULL,”Debugged”,”Warning”,MB_OK);
else
MessageBoxA(NULL,”Not Debugged”,”Warning”,MB_OK);

RtlDestroyQueryDebugBuffer(buffer);
}

and here ‘defs.h

typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)

typedef struct _DEBUG_BUFFER {
HANDLE SectionHandle;
PVOID  SectionBase;
PVOID  RemoteSectionBase;
ULONG  SectionBaseDelta;
HANDLE  EventPairHandle;
ULONG  Unknown[2];
HANDLE  RemoteThreadHandle;
ULONG  InfoClassMask;
ULONG  SizeOfInfo;
ULONG  AllocatedSize;
ULONG  SectionSize;
PVOID  ModuleInformation;
PVOID  BackTraceInformation;
PVOID  HeapInformation;
PVOID  LockInformation;
PVOID  Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;

typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0x00
ULONG Flags; // 0x04
USHORT Granularity; // 0x08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0x10
ULONG TagCount; // 0x14
ULONG BlockCount; // 0x18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0x38
PVOID Blocks; // 0x3C
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;

// RtlQueryProcessDebugInformation.DebugInfoClassMask constants
#define PDI_MODULES                       0x01
#define PDI_BACKTRACE                     0x02
#define PDI_HEAPS                         0x04
#define PDI_HEAP_TAGS                     0x08
#define PDI_HEAP_BLOCKS                   0x10
#define PDI_LOCKS                         0x20

extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlQueryProcessDebugInformation(
IN ULONG  ProcessId,
IN ULONG  DebugInfoClassMask,
IN OUT PDEBUG_BUFFER  DebugBuffer);

extern “C”
__declspec(dllimport)
PDEBUG_BUFFER
__stdcall
RtlCreateQueryDebugBuffer(
IN ULONG  Size,
IN BOOLEAN  EventPair);
extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER  DebugBuffer);

See you to the next post.. 🙂


Backdoor.Win32.UltimateDefender Reverse Engineering

December 8, 2008

Hi,

I’ve released Backdoor.Win32.UltimateDefender.gtz Reverse Engineering on my Website:

http://evilcry.netsons.org/tuts/Mw/Backdoor-UltimateDefender.pdf

Regards,

Giuseppe ‘Evilcry’ Bonfa’


SetUnhandledExceptionFilter Anti Debug Trick

July 24, 2008

Hi,

SetUnhandledExceptionFilter() Anti Debug Trick is frequently used, especially in Malware Applications. Around here there are various plugins for Olly that allows the Reverser to trasparently debug this kind of protection, so there is not a real necessity add other words about the mere practical part.

Due to the fact that today, too many young reversers uses a ton of plugins anti – anti – xxx without knowing how internally they works, I decided to expose here SetUnhandledExceptionFilter() Anti Debug Trick from Internals.

First of all, what is SetUnhandledExceptionFilter() ? according to MSDN documentation:

Enables an application to supersede the top-level exception handler of each thread of a process.

After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.

And this is the Syntax:

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
__in  LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
);

lpTopLevelExceptionFilter is a pointer to top-level exception filter function that will be called whenever the UnhandledExceptionFilter function gets control, and the process is not being debugged. A value of NULL for this parameter specifies default handling within UnhandledExceptionFilter.

Usually, in absence of an UnhandledExceptionFilter the topmost handler called when an uncatched exception occours, is the default one provided by Windows Itself, the classical MessageBox that advices the user that an Unhandled Exception has occured.

But Windows allow programs to use custom Handlers for UnhandledException. The core of the trick is here, if the application is NOT debugged, the application is able to call the Custom Handler, but if the application IS debugged the Custom Handler will be never called.

The possibility of cognitive differentiation make obviously able the target application to apply a series of countemeasures against debugging, from detection to code hidding.

Just remember that due to the architecture of Windows Exception Handling, in every case is called UnhlandledExceptionFilter() function, and this will our point of attack (for anti – anti dbg trick).

This is the general inner meccanism of SetUnhandledExceptionFilter(), going more deep we observe the call stack of the first thread of any Win32 application, we can see that execution in every case is reported to BaseProcess, here the pseudo definition:

VOID BaseProcessStart( PPROCESS_START_ROUTINE pfnStartAddr )
{
    __try
    {
        ExitThread( (pfnStartAddr)() );
    }
    __except( UnhandledExceptionFilter( GetExceptionInformation()) )
    {
        ExitProcess( GetExceptionCode() );
    }
}

The same thing happens for threads, by referencing to BaseThreadStart:

VOID BaseThreadStart( PTHREAD_START_ROUTINE pfnStartAddr, PVOID pParam )
{
    __try
    {
        ExitThread( (pfnStartAddr)(pParam) );
    }
    __except( UnhandledExceptionFilter(GetExceptionInformation()) )
    {
        ExitProcess( GetExceptionCode() );
    }
}

All that happens inside BaseProcessStart() and BaseThreadStart() for what previously said, will be passed to the UnhandledExceptionFilter().

It’s now time to see what really is UnhandledExceptionFilter(), according to MSDN:

An application-defined function that passes unhandled exceptions to the debugger, if the process is being debugged. Otherwise, it optionally displays an Application Error message box and causes the exception handler to be executed. This function can be called only from within the filter expression of an exception handler.

Syntax

LONG WINAPI UnhandledExceptionFilter(
  __in  struct _EXCEPTION_POINTERS *ExceptionInfo
);

Became clear that UnhandledExceptionFilter represents the last choise for processing unhandled exceptions, so the Debugger Presence surely is located inside this function, let’s see a simplified version of this function:

LONG UnhandledExceptionFilter( EXCEPTION_POINTERS* pep )
{
    DWORD rv;

    EXCEPTION_RECORD* per = pep->ExceptionRecord;

    if( ( per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ) &&
         ( per->ExceptionInformation[0] != 0 ) )
    {
        rv = BasepCheckForReadOnlyResource( per->ExceptionInformation[1] );

        if( rv == EXCEPTION_CONTINUE_EXECUTION )
            return EXCEPTION_CONTINUE_EXECUTION;
    }

    DWORD DebugPort = 0;

    rv = NtQueryInformationProcess( GetCurrentProcess(), ProcessDebugPort,
                                    &DebugPort, sizeof( DebugPort ), 0 );

    if( ( rv >= 0 ) && ( DebugPort != 0 ) )
    {
        // Yes, it is -> Pass exception to the debugger
        return EXCEPTION_CONTINUE_SEARCH;
    }

    // Is custom filter for unhandled exceptions registered ?

    if( BasepCurrentTopLevelFilter != 0 )
    {
        // Yes, it is -> Call the custom filter

        rv = (BasepCurrentTopLevelFilter)(pep);

        if( rv == EXCEPTION_EXECUTE_HANDLER )
            return EXCEPTION_EXECUTE_HANDLER;

        if( rv == EXCEPTION_CONTINUE_EXECUTION )
            return EXCEPTION_CONTINUE_EXECUTION;
    }   

}

As you can see, inside UnhandledExceptionFilter() is called NtQueryInformationProcess() that has as first parameter our process and next DebugPort, this is done to know if the process is debugged.

All that we have to do to obtain an apparently undebugged process is to modify the first parameter (last pushed at debugging time), in other words we have to change the retur value of GetCurrentProcess() from 0xFFFFFFFF to 0x00000000.

So remember, when you have to overcome a SetUnhandledExceptionFilter() just put a Breakpoint for UnhandledExceptionFilter() and go inside this function to modify the previously exposed parameter 🙂

Thanks to Oleg Starodumov for pseudocodes 🙂

See you to the next blog post.. 🙂


Disabling VS JIT and Prepairing WinDBG for Unknown Exceptions

May 22, 2008

Hi,

Often when you’re working on bug hunting, VS’s JIT Debugger became totally unusable cause it hasn’t a refined mechanism of exception inspection and no great aids for Post-Mortem Debugging, so became necessary to switch to the actual Lord of Debuggers..WinDbg (obviously after Sacred SoftICE :))so let’s disable the VS JIT that in case of crash will acts as the Handler of the occured Unhandled Exception.

Open VS Tools->Options->Debugging -> Just-In-Time Debugging and disable Native, Managed and Script

Now every application that crashes has not a debugger that handles the exception, let’s actualize WinDbg as JIT Debugger.

Go into WinDbg directory (Debugging Tools for Windows) and type

windbg -I

Now if all is ok a success MessageBox shoud appear.

Now try to cause an unhandled exception, for example by calling a buggy application, if Windbg popups it means that all works fine.

Now could happen that the unhandled exception is Unknown and windbg breaks when the execution is finished so we don’t have great information, no exception informations of reg/stack infos, but is here the power of windbg we can set Event Filters for all kind of exceptions known or not.

For example Unknown exception – code e0000001 (first chance)

We can put directly a break point when this unknown exception happens! 🙂

by typing:

>sxe e0000001

>g

To remove breakpoint type:

>sxd e0000001

See you to the next post.. 🙂


Symbol Type Viewer 32Bit/64Bit Nice Tool

March 16, 2008

Hi

Today I’ve finded a great tool,Symbol Type Viewer 32Bit/64Bi


Symbol Type Viewer is a tool which makes it possible to easily
visualize the types which can be defined in the symbols of the modules of the
systems Microsoft Windows 32/64bit. Moreover, it makes it possible to convert ( pdb, exe, sys)these informations for the C language (.h) and the disassembler IDA of DataRescue
(.idc).

Link here

See you to the next post.. 🙂