@@ -39,13 +39,72 @@ impl Emu {
3939 /// Support SEH, VEH and UEF
4040 pub fn exception ( & mut self , ex_type : ExceptionType ) {
4141 /*
42- Priority: VEH → SEH → UEF
42+
43+ If the handler return the search constant will jump to next handler in this order:
44+ VEH -> SEH1 -> SEH2 -> ... -> SEHn -> UEF -> terminate process
45+
46+
47+ unhandling:
48+ VEH:
49+ - the api RemoveVectoredExceptionHandler removes the handler
50+ SEH:
51+ - automatically when is triggered. SEH point to next SEH.
52+ UEF:
53+ - SetUnhandledExceptionFilter
54+
55+
56+ Responses:
57+
58+ VEH:
59+ - EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
60+ - EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end proces)
61+
62+ SEH:
63+ - EXCEPTION_CONTINUE_EXECUTION (continue and not jump to except)
64+ - EXCEPTION_CONTINUE_SEARCH (jump to next handler SEH -> UEF -> end process)
65+ - EXCEPTION_EXECUTE_HANDLER (jump to except)
66+
67+ UEF:
68+ - EXCEPTION_CONTINUE_EXECUTION (continue to eip/rip which could be modified)
69+ - EXCEPTION_CONTINUE_SEARCH (end process)
70+
71+ 64bits SEH:
72+ - is not a stack chain
73+ - search RUNTIME_FUNCTION entry in the .pdata table using BeginAddress ≤ RIP < EndAddress
74+ - in that entry there is the RVA of UNWIND_INFO struct on the .xdata
75+
76+
77+ - at .pdata, 12 bytes of runtime entries:
78+
79+ typedef struct _RUNTIME_FUNCTION {
80+ DWORD BeginAddress;
81+ DWORD EndAddress;
82+ DWORD UnwindInfo; // RVA to UNWIND_INFO at .xdata
83+ } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
84+
85+ - unwind info in the .xdata:
86+
87+ typedef struct _UNWIND_INFO {
88+ UBYTE Version : 3; // always 1
89+ UBYTE Flags : 5; // 0, EHANDLER, UHANDLER, etc.
90+ UBYTE SizeOfProlog;
91+ UBYTE CountOfCodes; // Nº of UNWIND_CODE
92+ UBYTE FrameRegister : 4; // (ie. RBP=5)
93+ UBYTE FrameOffset : 4; // frame scale
94+ UNWIND_CODE UnwindCode[]; // descriptors
95+ // opcional:
96+ // DWORD ExceptionHandler; // RVA to handler if Flags indicate it
97+ // DWORD ExceptionData[]; // extra data for handler
98+ } UNWIND_INFO, *PUNWIND_INFO;
99+
100+
43101 */
44102
45103
46104 let addr: u64 ;
47105 let next: u64 ;
48106
107+ // hook
49108 let handle_exception: bool = match self . hooks . hook_on_exception {
50109 Some ( hook_fn) => hook_fn ( self , self . regs ( ) . rip , ex_type) ,
51110 None => true ,
@@ -61,14 +120,14 @@ impl Emu {
61120 return ;
62121 }
63122
123+ // hook replaced handler
64124 if !handle_exception {
65125 log:: info!( "cancelled exception handling from hook." ) ;
66126 return ;
67127 }
68128
129+ // VEH
69130 if self . veh ( ) > 0 {
70- // VEH
71-
72131 addr = self . veh ( ) ;
73132
74133 exception:: enter ( self , ex_type) ;
@@ -79,16 +138,16 @@ impl Emu {
79138 self . set_eip ( addr, false ) ;
80139 }
81140
141+ // SEH
82142 } else if self . seh ( ) > 0 {
83- // SEH
84-
85143
86144 if self . cfg . is_64bits {
87145 // 64bits seh
88146
89147 unimplemented ! ( "check .pdata if exists" ) ;
90148
91149 } else {
150+
92151 // 32bits seh
93152 next = match self . maps . read_dword ( self . seh ( ) ) {
94153 Some ( value) => value. into ( ) ,
0 commit comments