News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

SEH problem

Started by minor28, September 20, 2021, 07:57:00 PM

Previous topic - Next topic

minor28

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.

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

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.


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.

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


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.