I am trying to manually handle a C++ exception ,caused by dynamically loaded code, through a VEH handler.At first I capture the exception with VEH then perform a stackwalk then call the __c_specific_handler to see if there is an actual handler and at last I need to make a call to RtlUnwindEx to actually call the catch callback. Reading at Skywing’s study on X64 exception handling (http://www.nynaeve.net/?p=110) I find this:
Consolidation unwinds are a special form of unwind that is indicated to RtlUnwindEx with a special exception code, STATUS_UNWIND_CONSOLIDATE.
This exception code changes RtlUnwindEx’s behavior slightly; it suppresses the behavior of substituting the
TargetIp argument to RtlUnwindEx with the unwound context’s Rip value.
Make a local copy of the passed-in context record.Treating ExceptionRecord->ExceptionInformation[0] as a callback function, this callback function is called (given a single argument pointing to the ExceptionRecord provided to RtlRestoreContext).
The return address of the callback function is treated as a new Rip value to place in the context that is about to be restored.
The context is restored as normal after the Rip value is updated based on the callback’s decision.
The callback routine pointed to by ExceptionRecord->ExceptionInformation[0] has the following signature:Returns a new RIP value to be used in the restored context.
typedef ULONG64 (* PFRAME_CONSOLIDATON_ROUTINE)(
__in PEXCEPTION_RECORD ExceptionRecord
);Frame consolidation unwinds are typically used in conjunction with C++ try/catch/throw support.
This is my attempt to do it (this is just the last part inside VEH handler):
auto language_handler = RtlVirtualUnwind(UNW_FLAG_EHANDLER, imagebase, (DWORD64)frames[i], lookup, &context, &handler_data, &establisher_frame, NULL);
DISPATCHER_CONTEXT new_dc = {};
new_dc.ControlPc = (DWORD64)frames[i];
new_dc.ImageBase = imagebase;
new_dc.FunctionEntry = lookup;
new_dc.EstablisherFrame = establisher_frame;
new_dc.TargetIp = reinterpret_cast<uint64_t>(&lookup);
new_dc.ContextRecord = ex->ContextRecord;
new_dc.LanguageHandler = language_handler;
new_dc.HandlerData = handler_data;
DISPATCHER_CONTEXT new_dcc = {};
auto result = language_handler(ex->ExceptionRecord, (void*)establisher_frame, ex->ContextRecord, &new_dc);
if (result == EXCEPTION_EXECUTE_HANDLER) {
EXCEPTION_RECORD EH;
EH.ExceptionCode = STATUS_UNWIND_CONSOLIDATE;
EH.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
EH.NumberParameters = 1;
EH.ExceptionInformation[0] = ;
RtlUnwindEx((void*)establisher_frame, frames[i],&EH,NULL,ex->ContextRecord,NULL);
return EXCEPTION_CONTINUE_EXECUTION;
}
My problem is that I am unable to find out what this parameter EH.ExceptionInformation[0] = ;
should contain.
If someone has tried this in the past, let me know