reimplement exeption.rs
-
Support the three typical exceptions handling systems of windows (SEH, VEH and UEF)
-
SEH: structured exception handler (try/catch, stack items)
-
VEH: vectorized exception handler (API) ntdll!RtlAddVectoredExceptionHandler ntdll!RtlRemoveVectoredExceptionHandler
-
UEF: unhandled exception filter (API) ntdll!RtlSetUnhandledExceptionFilter kernelbase!SetUnhandledExceptionFilter
-
-
implement also the tests to trigger different types of handlers and also resume the execution:
- exception_handler32
- exception_handler64
-
rename emu.feh to emu.uef for the unhandled exception filter
-
implement missing winapis to schedule or free the exception handler.
note: The VEH was totally ok in theory, in the past I tested it with a chunk of guloader.
If the handler return the search constant will jump to next handler in this order:
VEH -> SEH1 -> SEH2 -> ... -> SEHn -> UEF -> terminate process
unhandling:
VEH:
- the api RemoveVectoredExceptionHandler removes the handler
SEH:
- automatically when is triggered. SEH point to next SEH.
UEF:
- SetUnhandledExceptionFilter updates the handler
Responses:
VEH:
- EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
- EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end proces)
SEH:
- EXCEPTION_CONTINUE_EXECUTION (continue and not jump to except)
- EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end process)
- EXCEPTION_EXECUTE_HANDLER (jump to except)
UEF:
- EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
- EXCEPTION_CONTINUE_SEARCH (end process)
64bits SEH:
- is not a stack chain
- search RUNTIME_FUNCTION entry in the .pdata table using BeginAddress ≤ RIP < EndAddress
- in that entry there is the RVA of UNWIND_INFO struct on the .xdata
- at .pdata, 12 bytes of runtime entries:
typedef struct _RUNTIME_FUNCTION {
DWORD BeginAddress;
DWORD EndAddress;
DWORD UnwindInfo; // RVA to UNWIND_INFO at .xdata
} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
- unwind info in the .xdata:
typedef struct _UNWIND_INFO {
UBYTE Version : 3; // always 1
UBYTE Flags : 5; // 0, EHANDLER, UHANDLER, etc.
UBYTE SizeOfProlog;
UBYTE CountOfCodes; // Nº of UNWIND_CODE
UBYTE FrameRegister : 4; // (ie. RBP=5)
UBYTE FrameOffset : 4; // frame scale
UNWIND_CODE UnwindCode[]; // descriptors
// opcional:
// DWORD ExceptionHandler; // RVA to handler if Flags indicate it
// DWORD ExceptionData[]; // extra data for handler
} UNWIND_INFO, *PUNWIND_INFO;