在调试器中步过INT3和INT1指令的时候,由于调试器通常会处理这些调试中断,所以异常处理例程默认情况下将不会被调用,Debugger Interrupts就利用了这个事实。这样壳可以在异常处理例程中设置标志,通过INT指令后如果这些标志没有被设置则意味着进程正在被调试。
另外,kernel32!DebugBreak()内部是调用了INT3来实现的,有些壳也会使用这个API。
示例
这个例子在异常处理例程中设置EAX的值为0xFFFFFFFF(通过CONTEXT6记录)以此来判断异常处理例程是否被调用:
; set exception handler
push .exeception_handler
push dword [fs:0]
mov [fs:0],esp
;reset flag(EAX) invoke int3
xor eax,eax
int3
;restore exception handler
pop dword [fs:0]
add esp,4
; check if the flag had been set
test eax,eax
je .debugger_found
:::
.exeception_handler:
;EAX = ContextRecord
mov eax,[esp+0xc]
;set flag (ContextRecord.EAX)
mov dword [eax+0xb0],0xffffffff
;set ContextRecord.EIP
inc dword [eax+0xb8]
xor eax,eax
retn
对策
由于调试中断而导致执行停止时,在OllyDbg中识别出异常处理例程(通过视图->SEH链)并下断点,然后Shift+F9将调试中断/异常传递给异常处理例程,最终异常处理例程中的断点会断下来,这时就可以跟踪了。
另外,kernel32!DebugBreak()内部是调用了INT3来实现的,有些壳也会使用这个API。
示例
这个例子在异常处理例程中设置EAX的值为0xFFFFFFFF(通过CONTEXT6记录)以此来判断异常处理例程是否被调用:
; set exception handler
push .exeception_handler
push dword [fs:0]
mov [fs:0],esp
;reset flag(EAX) invoke int3
xor eax,eax
int3
;restore exception handler
pop dword [fs:0]
add esp,4
; check if the flag had been set
test eax,eax
je .debugger_found
:::
.exeception_handler:
;EAX = ContextRecord
mov eax,[esp+0xc]
;set flag (ContextRecord.EAX)
mov dword [eax+0xb0],0xffffffff
;set ContextRecord.EIP
inc dword [eax+0xb8]
xor eax,eax
retn
对策
由于调试中断而导致执行停止时,在OllyDbg中识别出异常处理例程(通过视图->SEH链)并下断点,然后Shift+F9将调试中断/异常传递给异常处理例程,最终异常处理例程中的断点会断下来,这时就可以跟踪了。
PEB.NtGlobal
14:31
585
0


