Author Topic: SEH problem  (Read 244 times)

minor28

  • Member
  • **
  • Posts: 133
SEH problem
« on: September 20, 2021, 07:57:00 PM »
Hi,
I'm trying to figure out how SEH works and have written the following code. If I comment out the line that causes the exception it works but exit code is -1 not 0. Else the execution jumps to the ExceptHandler. The problem is the RtlUnwindEx function. An exception is thrown and I cannot figure out what is wrong.
Code: [Select]
OPTION DOTNAME                          ; required for macro files
option casemap:none                     ; case sensitive

include \masm32\include64\win64.inc     ; main include file
include \masm32\macros64\vasily.inc     ; main macro file
include \masm32\macros64\macros64.inc   ; auxillary macro file

STACKFRAME                              ; create a default stack frame

include \masm32\m64lib\m64lib.inc       ; include file for m64lib library

; ------------------------
; system API include64 files
; ------------------------
include \masm32\include64\kernel32.inc
include \masm32\include64\user32.inc
include \masm32\include64\msvcrt.inc

; ------------------------
; system API library files
; ------------------------
includelib \masm32\lib64\msvcrt.lib


dataSEH segment para ".data"
dataSEHStart label near

dataSEH ends

.data

.data?
retValue qword ?
exceptRecord EXCEPTION_RECORD <>

ExceptHandler proto

_SEH textequ <0>
__try macro
local try
try equ $

dataSEH segment
qword try
dataSEH ends
endm

__except macro
local except
except equ $+5

dataSEH segment
qword except
dataSEH ends
.code
%jmp near ptr @end
%@start:
endm

__endtryexcept macro
local endtryexcept
endtryexcept equ $

dataSEH segment
qword endtryexcept
dataSEH ends
.code
%@end:
endm

.code

entry_point proc frame:ExceptHandler
.endprolog

lea rax,dataSEHStart

__try
mov rax,0
mov rax,[rax]

__except
lea r8,exceptRecord
invoke __imp_printf,"exception code: %xh",qword ptr [r8].EXCEPTION_RECORD.ExceptionCode
   
__endtryexcept
invoke __imp_printf,"It works"

leave
xor rax,rax
call ExitProcess
ret
entry_point endp

OPTION PROLOGUE:PROLOGUEDEF
OPTION EPILOGUE:EPILOGUEDEF
ExceptHandler proc
local pExceptionRecord:ptr
local EstablisherFrame:qword
local pContextRecord:ptr
local pDispatcherContext:ptr

mov pExceptionRecord,rcx
mov EstablisherFrame,rdx
mov pContextRecord,r8
mov pDispatcherContext,r9

invoke RtlMoveMemory,addr exceptRecord,pExceptionRecord,sizeof EXCEPTION_RECORD

sub rsp, 16h
mov rcx,EstablisherFrame
lea rdx,dataSEHStart
add rdx,8
mov rdx,[rdx]
mov r8,pExceptionRecord
lea r9,retValue
mov rax,pContextRecord
mov [rsp+20h],rax
mov rax, pDispatcherContext
    mov rax, [rax].DISPATCHER_CONTEXT.HistoryTable
    mov [rsp+28h], rax
call RtlUnwindEx
add rsp, 16h

xor eax,eax
mov rsp,rbp
pop rbp
    ret
ExceptHandler endp

end

Is there anyone who can explain what the problems are.

Best regards

minor28

  • Member
  • **
  • Posts: 133
Re: SEH problem
« Reply #1 on: October 02, 2021, 07:12:33 PM »
The problem is not solved yet. Now I have three functions. An ordinary entry_point function, a TestProc function with a guarded part and an exception handler.

Code: [Select]
STACKFRAME
entry_point proc
local buf[30h]:byte
local var:qword

mov rdi,500h ;to test preservation
mov rsi,300h

invoke lstrcpy,addr buf,"First string from entry_point\n"

lea rax,buf
mov var,rax

invoke TestProc,addr retValue,EXCEPTION_UNWIND,500h,addr buf,addr var

invoke __imp_printf,addr buf

invoke ExitProcess,0

ret
entry_point endp

Now to the TestProc function.
Code: [Select]
NOSTACKFRAME
TestProc proc frame:ExceptHandler arg1:ptr, arg2:qword, arg3:dword, pBuf:ptr, pVar:ptr
push_reg rbp
mov rbp,rsp
set_frame rbp,0
    push_reg rsi
    push_reg rdi
    alloc_stack 20h+30h
.endprolog

mov pBuf,r9
mov arg3,r8d
mov arg2,rdx
mov arg1,rcx

mov rdi,600h
mov rsi,400h
__try
mov rax,0
mov rax,[rax] ;exception
__except
invoke lstrcat,r9,"exception appended\n"
__endtryexcept

invoke lstrcat,r9,"string appended\n\n"
pop rdi
    pop rsi

add rsp,20h+30h
leave
pop r9 ;jmp back instead of return
jmp r9
ret
TestProc endp

If exception is comment out it works. However if the function has locals or/and arguments there is no ret compiled. Must be a bug. Insted pop and jmp.
So far it might be solved. Now to the exception handler

Code: [Select]
STACKFRAME
ExceptHandler proc pExceptionRecord:ptr,EstablisherFrame:qword,pContextRecord:ptr,pDispatcherContext:ptr

mov rcx,pExceptionRecord
.if dword ptr [rcx].EXCEPTION_RECORD64.ExceptionFlags == EXCEPTION_NONCONTINUABLE ; = 1
invoke ExitProcess,0
.EndIf

invoke RtlMoveMemory,addr exceptRecord,pExceptionRecord,sizeof EXCEPTION_RECORD
invoke RtlMoveMemory,addr exceptContext,pContextRecord,sizeof CONTEXT

mov rcx,EstablisherFrame
lea rdx,dataSEHStart
add rdx,8
mov rdx,[rdx]
lea r8,exceptRecord
mov r9,0 ;retValue
lea rax,exceptContext
mov [rsp+20h],rax
mov rax,pDispatcherContext
    mov rax,qword ptr [rax].DISPATCHER_CONTEXT.HistoryTable
    mov [rsp+28h],rax
call RtlUnwindEx

invoke ExitProcess,1 ;if ok, should not come here

    ret
ExceptHandler endp

Whatever I do the execution either goes to ExitProcess or back to the handler till it exits
Does anyone know anything about how to solve this?

Here is the code. I use vs2019 community.