Techwiki:SEH64
Contents
Function Table
The function table can be found in the .pdata section of the executable. It's an array of RUNTIME_FUNCTION structures. NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] is the corresponding data directory entry. It's VirtualAddress member points to the beginning of this section, it's Size member divided by sizeof(RUNTIME_FUNCTION) gives the numer of entries.
typedef struct _RUNTIME_FUNCTION { ULONG BeginAddress; ULONG EndAddress; ULONG UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
BeginAddress is the RVA of the beginning of the corresponding function. EndAddress is the RVA of the end of the corresponding function. UnwindData is the RVA of the UNWIND_INFO structure belonging to this function.
All RUNTIME_FUNCTION entries are sorted, beginning with the smallest address and never overlapping. There may be gaps though. If an address is not found inside the table, it is supposed to be a leaf function and RSP points to the functions return address.
The table that corresponds to a certain address can be found using
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionTable( IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PULONG Length);
The function entry can be found by using
PRUNTIME_FUNCTION NTAPI RtlLookupFunctionEntry( IN DWORD64 ControlPc, OUT PDWORD64 ImageBase, OUT PUNWIND_HISTORY_TABLE HistoryTable);
Unwind Data
The UnwindData member of the RUNTIME_FUNCTION entry is the RVA of an UNWIND_INFO structure.
typedef struct _UNWIND_INFO { UBYTE Version:3; UBYTE Flags:5; UBYTE SizeOfProlog; UBYTE CountOfCodes; UBYTE FrameRegister:4; UBYTE FrameOffset:4; UNWIND_CODE UnwindCode[1]; /* union { OPTIONAL ULONG ExceptionHandler; OPTIONAL ULONG FunctionEntry; }; OPTIONAL ULONG ExceptionData[]; */ } UNWIND_INFO, *PUNWIND_INFO;
Version
- Should be 1
Flags
- Can be can be one of the following values
#define UNW_FLAG_NHANDLER 0 #define UNW_FLAG_EHANDLER 1 #define UNW_FLAG_UHANDLER 2 #define UNW_FLAG_??? 3 #define UNW_FLAG_CHAININFO 4
SizeOfProlog
- Size of the functions prolog in bytes.
CountOfCodes
- Number of UNWIND_CODE entries in this structure.
FrameRegister
FrameOffset
ExceptionHandler
- RVA of the language specific handler. See below.
ExceptionData
- This data is specific to the language specific handler and a pointer to this data is passed to the handler in the DISPATCHER_CONTEXT structure.
The exception handler for RtlpExecuteHandlerForUnwind (RtlpUnwindHandler) has a Flags value of 3. The handler is responsible for collided unwinds, see http://www.nynaeve.net/?p=107
The Language specific handler
This function must correspond to the following prototype:
typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE)( IN PEXCEPTION_RECORD ExceptionRecord, IN ULONG64 EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PDISPATCHER_CONTEXT DispatcherContext);
_C_specific_handler
In this case ExceptionData is a SCOPE_TABLE structure.
typedef struct _SCOPE_TABLE { ULONG Count; struct { ULONG BeginAddress; ULONG EndAddress; ULONG HandlerAddress; ULONG JumpTarget; } ScopeRecord[1]; } SCOPE_TABLE, *PSCOPE_TABLE;
=== _Cxx
C++ exceptions
- lead to a flag 3
- unwind data is:
- RVA of the language handler (msvcr90.__CxxFrameHandler3)
int __CxxFrameHandler3( EHExceptionRecord * pExcept, EHRegistrationNode * pRN, void * pContext, void * pDC); struct EHExceptionRecord { EXCEPTION_RECORD ExceptionRecord; ??? }; struct EHRegistrationNode (FIXME: this is x86) { EHRegistrationNode *prev; DWORD ehhandler_code; DWORD id; DWORD saved_ebp; };
- RVA of some data in the rdata segment
typedef struct { DWORD unknown00; // 0x19930522 DWORD unknown04; // 0x2 RVA Data1; // points to DATA1 in .rdata DWORD unknown0c; // 0x1 RVA Data2; // points to DATA2 in .rdata DWORD unknown14; // 8 RVA Data3; // points to DATA3 in .rdata DWORD unknown1c; // 0x28 DWORD unknown20; // 0 DWORD unknown24; // 0 } DATA0; typedef struct { DWORD dw0; // 0xffffffff DWORD dw1; // 0 DWORD dw2; // 0xffffffff DWORD dw3; // 0 } DATA1; typedef struct { DWORD dw0; // 0 DWORD dw1; // 0 DWORD dw2; // 1 DWORD dw3; // Number of catch blocks RVA Data4; // points to array of DATA4 in .rdata, one for each catch } DATA2; typedef struct { RVA ThrowingFunction; DWORD dw04; // 0xffffffff RVA ScopeBegin; DWORD dw0c; // 0x0 RVA EndScope; DWORD dw14; // 0xffffffff RVA Sub1; DWORD dw1c; // 0 RVA Sub2; DWORD dw1c; // 1 RVA Sub3; DWORD dw1c; // 0 ... more RVA/DWORD combinations for more catch blocks } DATA3; typedef struct { DWORD dw0; // 0 RVA Data5; // points to .data DWORD dw2; // 0x24 RVA HandlerFunc; DWORD dw4; // 0x38 } DATA4;
References
- MSDN: Unwind Data Definitions in C
- MSDN: RUNTIME_FUNCTION Structure
- MSDN: RtlLookupFunctionEntry Function
- MSDN: UNWIND_INFO Structure
- MSDN: The Language Specific Handler
- Collided Unwinds
- Unwind Helpers for MASM
- MSDN: EXCEPTION_RECORD Structure
- SEH exceptions on Windows CE (ARM) *2
- Lifetime of an exception