DynRio and SEH

41 views
Skip to first unread message

Holger Unterbrink

unread,
May 11, 2025, 6:53:43 AMMay 11
to DynamoRIO Users
Hi, I have two questions, hope I didn't missed that here or in the docs.

a) does anyone has an idea if there is a way to pass/forward such exception to the instrumented binary (I know worst case I can skip this code and not instrument it, but there are several cases where it would be better/easier to pass the exceptions if possible. Also I played a bit with event_exception() but it didn't worked ?

CONTEXT* ctx2;
SIZE_T debugger_attached = 0;
__try {
__writeeflags(__readeflags() | 0x100);  // Set TF flag aka set CPU to single step
__nop(); // trigger exception in single step mode
}
__except (ctx2 = (GetExceptionInformation())->ContextRecord,
debugger_attached = (ctx2->ContextFlags & CONTEXT_DEBUG_REGISTERS) ?
ctx2->Dr0 | ctx2->Dr1 | ctx2->Dr2 | ctx2->Dr3 : 0,
EXCEPTION_EXECUTE_HANDLER)
{
if (debugger_attached) {
printf("[ANTI-X] [INTEGRITY CHECK FAIL] Exception test: Hardware breakpoints detected!\n");
}
else {
printf("[ANTI-X] [SUCCESS] Exception test: No hardware breakpoints detected.\n");
}
}

b) is there any way to recognize if somthing like this happens, even with debugging on I do not see an error msg which is clear to me which tells me that an exception occured ? The execution just ends without any error msg at the point where the exception occurs.

C:\tools\DynamoRIO-Windows-11.3.0/ext\lib64\debug/drmgr.dll=0x00007ff747300000>
[TRACER] [DEBUG] [dr_client_main] dr_client_main started on Windows.
[TRACER] [DEBUG] [dr_client_main] dr_client_main started on x86_64.
[TRACER] [DEBUG] [dr_client_main] DynamoRio Manager initialized.
[TRACER] [DEBUG] [dr_client_main] Client DLL used  = C:\Users\hunte\source\repos\test1\x64\Release\test1.dll
[TRACER] [DEBUG] [dr_client_main] PID              = 8796 (0x225c)
[TRACER] [DEBUG] [dr_client_main] Processname      = anti_x.exe
[TRACER] [DEBUG] [dr_client_main] Initalization done.
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: dynamorio.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: test1.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: drmgr.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: anti_x.exe:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: VCRUNTIME140.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: KERNELBASE.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: ucrtbase.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: KERNEL32.dll:
[TRACER] [DEBUG] [event_module_load_trace_instr] Process PID 8796 (anti_x.exe) module loaded: ntdll.dll:
<CURIOSITY : instr_get_opcode(instr_new) != instr_get_opcode(instr_old) in file D:\a\dynamorio\dynamorio\core\win32\callback.c line 2082
version 11.3.0, build 1
-no_dynamic_options -client_lib 'C:\Users\hunte\source\repos\test1\x64\Release\test1.dll;0;' -client_lib64 'C:\Users\hunte\source\repos\test1\x64\Release\test1.dll;0;' -code_api -probe_api -stack_size 56K -max_elide_jmp 0 -max_elide_call 0 -no_inline_ignored_syscalls -native_exec_default_list '' -no_native_exec_managed_c
C:\tools\DynamoRIO-Windows-11.3.0/lib64\debug\dynamorio.dll=0x0000000015000000
C:\Users\hunte\source\repos\test1\x64\Release\test1.dll=0x00007ff7472e0000
C:\WINDOWS/system32/KERNEL32.dll=0x0000021d00080000
C:\WINDOWS/system32/KERNELBASE.dll=0x0000021d00150000
C:\tools\DynamoRIO-Windows-11.3.0/ext\lib64\debug/drmgr.dll=0x00007ff747300000>
<CURIOSITY : instr_new == instrlist_first(ilist) || instr_new == instr_get_next(instrlist_first(ilist)) in file D:\a\dynamorio\dynamorio\core\win32\callback.c line 2085
version 11.3.0, build 1
-no_dynamic_options -client_lib 'C:\Users\hunte\source\repos\test1\x64\Release\test1.dll;0;' -client_lib64 'C:\Users\hunte\source\repos\test1\x64\Release\test1.dll;0;' -code_api -probe_api -stack_size 56K -max_elide_jmp 0 -max_elide_call 0 -no_inline_ignored_syscalls -native_exec_default_list '' -no_native_exec_managed_c
C:\tools\DynamoRIO-Windows-11.3.0/lib64\debug\dynamorio.dll=0x0000000015000000
C:\Users\hunte\source\repos\test1\x64\Release\test1.dll=0x00007ff7472e0000
C:\WINDOWS/system32/KERNEL32.dll=0x0000021d00080000
C:\WINDOWS/system32/KERNELBASE.dll=0x0000021d00150000
C:\tools\DynamoRIO-Windows-11.3.0/ext\lib64\debug/drmgr.dll=0x00007ff747300000>
<Cleaning hooked Nt wrapper @0x00007ff9fce059b0 sysnum=0x1d3>
[ANTI-X] Function address: 0x7FF7A72D10A0
[ANTI-X] Function size: 110
[ANTI-X] CRC32: D98CD40B
[ANTI-X] [SUCCESS] CRC32 matches! Function code is ok.
[ANTI-X] [SUCCESS] No debugger detected.
[ANTI-X] DR0: 0x0000000000000000
[ANTI-X] DR1: 0x0000000000000000
[ANTI-X] DR2: 0x0000000000000000
[ANTI-X] DR3: 0x0000000000000000
[ANTI-X] DR6 (status): 0x00000000
[ANTI-X] DR7 (control): 0x00000000
[ANTI-X] [SUCCESS] GetThreadContext: No hardware breakpoints detected.

C:\Users\hunte\source\repos\test1\x64\Release>



Derek Bruening

unread,
May 13, 2025, 1:40:11 PMMay 13
to Holger Unterbrink, DynamoRIO Users
DR assumes the exception goes through KiUserExceptionDispatcher, where DR will see it and call the callbacks registered with dr_regsiter_exception_event().
You're saying the single-step trap was not detected by DR?  Is there some new behavior on new Windows kernels that doesn't go through KiUserExceptionDispatcher?

--
You received this message because you are subscribed to the Google Groups "DynamoRIO Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dynamorio-use...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/dynamorio-users/ef3e4147-9d4e-43b9-bd98-53d27c5b806en%40googlegroups.com.

Holger Unterbrink

unread,
May 14, 2025, 3:08:47 AMMay 14
to DynamoRIO Users
Yes, DynamoRio just stops executing. No error message or hint. The latter is a good question, the system I am testing it on is the latest Win11 with default settings. They definetely change some stuff, one thing I discovered earlier (but probably indepent of this issue) is that someone forget to update the !chkimg function in winddbg with the new FG dispatch(?) function inserted in the SCP page. Now you always see a bunch of ntdll!_guard_... functions modified when you do a !chkimg.

0:019> !chkimg -d ntdll
    7ffe133ab000-7ffe133ab002  3 bytes - ntdll!_guard_dispatch_icall_fptr
[ 30 76 32:40 60 42 ]
    7ffe133ab008-7ffe133ab00a  3 bytes - ntdll!_guard_xfg_check_icall_fptr (+0x08)
[ d0 0a 2c:40 61 42 ]
    7ffe133ab010-7ffe133ab012  3 bytes - ntdll!_guard_xfg_dispatch_icall_fptr (+0x08)
[ 60 76 32:40 60 42 ]
    7ffe133ab018-7ffe133ab01a  3 bytes - ntdll!_guard_xfg_table_dispatch_icall_fptr (+0x08)
[ 60 76 32:40 60 42 ]
12 errors : ntdll (7ffe133ab000-7ffe133ab01a)

Even it is likely not relevant for this issue, I thought I mention it in case someone else runs into it.

Holger Unterbrink

unread,
May 14, 2025, 3:12:15 AMMay 14
to DynamoRIO Users
I am offsite the rest of the week, I ll look deeper into the SEH when I am back.

Holger Unterbrink

unread,
May 19, 2025, 12:44:49 PMMay 19
to DynamoRIO Users
procdump -e 1 -x . drrun.exe  -debug -- "C:\Users\hunte\source\repos\anti_x\x64\Release\anti_x_with_SEH.exe"
(I run it with procdump this time to see if there is any exception not handled by DR, does that make sense?)

 drrun with -debug flag shows the following:
...

[ANTI-X] DR3: 0x0000000000000000
[ANTI-X] DR6 (status): 0x00000000
[ANTI-X] DR7 (control): 0x00000000
[ANTI-X] [SUCCESS] GetThreadContext: No hardware breakpoints detected.                                                               <==== last valid output of the target application
<curiosity: rex.w on OPSZ_6_irex10_short4!>                                              
<Stopping application C:\Users\hunte\source\repos\anti_x\x64\Release\anti_x_with_SEH.exe (15020)>
[18:35:16] Process Exit: PID 10912, Exit Code 0xc0000005
[18:35:16] The process has exited.
[18:35:16] Dump count not reached.

It looks like it has an issue with this single step exception, simple default SEH code (see below) works fine, it does not break up.

If I comment out the single step exception code, DR (even with a client) works fine:
--- snip ---
// Check for hardware breakpoint again with a different trick  (this breaks DynamoRio)  
//CONTEXT* ctx2;
//SIZE_T debugger_attached = 0;
//__try {
// __writeeflags(__readeflags() | 0x100);  // Set TF flag aka set CPU to single step
// __nop(); // trigger exception in single step mode
//}
//__except (ctx2 = (GetExceptionInformation())->ContextRecord,
// debugger_attached = (ctx2->ContextFlags & CONTEXT_DEBUG_REGISTERS) ?
// ctx2->Dr0 | ctx2->Dr1 | ctx2->Dr2 | ctx2->Dr3 : 0,
// EXCEPTION_EXECUTE_HANDLER)
//{
// if (debugger_attached) {
// printf("[ANTI-X] [INTEGRITY CHECK FAIL] Exception test: Hardware breakpoints detected!\n");
// }
// else {
// printf("[ANTI-X] [SUCCESS] Exception test: No hardware breakpoints detected.\n");
// }
//}
--- snip ---


Simple default SEH code that runs fine under drrun:

--- snip ---
printf("[ANTI-X] triggering an exception...\n");  
__try {
char* p = NULL;
*p = 0; // This will cause an access violation exception
printf("[ANTI-X] This should never be reached due to the exception\n");
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DWORD code = GetExceptionCode();
printf("[ANTI-X] Exception caught: %s (0x%08X)\n", DescribeException(code), code);
}
printf("[ANTI-X] Exception triggert.\n");
--- snip ---

Derek Bruening

unread,
May 22, 2025, 11:26:29 PMMay 22
to Holger Unterbrink, DynamoRIO Users
Single-step requires special handling. The Windows handling was added by https://github.com/DynamoRIO/dynamorio/commit/47b56c854bd8d4137dad54e5cc124ab983ecb370 targeting https://github.com/DynamoRIO/dynamorio/issues/2144. Does the test added by that commit (security-win32.singlestep) pass on your machine?

Holger Unterbrink

unread,
May 26, 2025, 5:00:21 AMMay 26
to DynamoRIO Users
I never worked with the tests, but is this what you mean ?

C:\tools\dynamorio-git\build\suite\tests\bin>security-win32.singlestep.exe
start of test, count = 0
single step exception
end of test, count = 3

Holger Unterbrink

unread,
May 26, 2025, 5:09:00 AMMay 26
to DynamoRIO Users
same with drrun:

C:\tools\dynamorio-git\build\suite\tests\bin>drrun.exe -- security-win32.singlestep.exe

start of test, count = 0
single step exception
end of test, count = 3

Reply all
Reply to author
Forward
0 new messages