The MASM Forum

General => The Campus => Topic started by: JK on July 05, 2020, 02:58:59 AM

Title: 64 bit SEH
Post by: JK on July 05, 2020, 02:58:59 AM
After some reading here and on MSDN, i put the following code together:

;*************************************************************************************
;assemble 64                                           ;UASM
;*************************************************************************************


option casemap : none
option win64: 15
OPTION STACKBASE : RBP


include <windows.inc>

includelib kernel32.lib
includelib user32.lib


;*************************************************************************************
;*************************************************************************************


.code
ExceptionFilter PROTO


TestEx PROC FRAME:ExceptionFilter
;*************************************************************************************
; create gpf and try to handle it
;*************************************************************************************


Try = $                                               ;start address
  xor rax, rax
  mov [rax], rax                                      ;gpf
End_Try = $                                           ;end address


Resume:
  invoke MessageBoxA, 0, CSTR("works"), CSTR("test"), 0
  invoke ExitProcess, 0
  ret


Catch::
  lea rax, Resume
  mov [r8].CONTEXT.Rip_, rax                          ;change the context so execution resumes at label "Exit"
  mov rax, ExceptionContinueExecution                 ;should now resume execution at label "Resume"


;int 3                                                 ;debuggger breakpoint
  add rsp, 8
  db 0c3h                                             ;ret, prevents "leave" to be inserted, which is unwanted here


TestEx ENDP


;*************************************************************************************


ExceptionFilter PROC
;*************************************************************************************
; rcx = Exception_Record, rdx = EstablisherFrame, r8 = CONTEXT, r9 = DispatcherContext
;*************************************************************************************


  lea rax, Try
  cmp [rcx].EXCEPTION_RECORD.ExceptionAddress,rax     ;check start address
  jl Do_not_handle

  lea rax, End_Try
  cmp [rcx].EXCEPTION_RECORD.ExceptionAddress,rax     ;check end address
  jg Do_not_handle


  jmp Catch                                           ;handle code inside the proc

   
Do_not_handle:
  mov rax, ExceptionContinueSearch
  ret


ExceptionFilter ENDP


;*************************************************************************************


END TestEx



My ultimate goal is to be able to decide, if an app must be terminated or can continue and act accordingly. I don´t need nested Try blocks. In some cases the app must be terminated, i can make a log, display an error message or the like and exit gracefully- this works (not included in the demo code). In some other cases it makes sense just to continue at a different location. This is what the code tries to do - and it seems to work too. The code runs into "Catch", RIP is overwritten in the CONTEXT record with the address of "Resume", so the code resumes execution here after the "RET".

Is this a correct approach or are there bugs or traps i didn´t notice so far?


JK
Title: Re: 64 bit SEH
Post by: JK on July 05, 2020, 05:14:32 AM
Playing with the code i realize that i don´t actally need an extra procedure (ExceptionFilter), i can code this:

TestEx PROC FRAME:Catch
;*************************************************************************************
; create gpf and try to handle it
;*************************************************************************************


Try = $                                               ;start address
  xor rax, rax
  mov [rax], rax                                      ;gpf
End_Try = $                                           ;end address


Resume:
  invoke MessageBoxA, 0, CSTR("works"), CSTR("test"), 0
  invoke ExitProcess, 0
  ret


Catch:
  lea rax, Resume
  mov [r8].CONTEXT.Rip_, rax                          ;change the context so execution resumes at label "Exit"
  mov rax, ExceptionContinueExecution                 ;should now resume execution at label "Resume"
  db 0c3h                                             ;ret, prevents "leave" to be inserted, which is unwanted here


TestEx ENDP


"Frame" points to a label inside the procedure, where all handling is possible. Could it be that easy?
Title: Re: 64 bit SEH
Post by: _japheth on July 05, 2020, 08:24:21 AM

Your code is ok.

Instead of using "db", it's more readable to use RETN:


  mov rax, ExceptionContinueExecution                 ;should now resume execution at label "Resume"
;  db 0c3h                                             ;ret, prevents "leave" to be inserted, which is unwanted here
  retn
   
Title: Re: 64 bit SEH
Post by: JK on July 05, 2020, 06:28:57 PM
Thanks for the confirmation!

Cool, "RETN" doesn´t cause "LEAVE" to be added under the hood - thanks again. I have read some nightmare stories about 64 bit SEH, but to me the basics seem pretty staightforeward. It´s except for how to set the handler address essentially the same as in 32 bit.


JK
Title: Re: 64 bit SEH
Post by: jj2007 on July 05, 2020, 07:31:32 PM
Quote from: JK on July 05, 2020, 06:28:57 PMCool, "RETN" doesn´t cause "LEAVE" to be added under the hood

In fact, ret is an internal MASM macro that takes info from the PROLOGUE macro to insert leave and pop used regs. In contrast, RETN and RETN nn are pure instructions.

It's useful to keep that mind also if you have multiple RET in a procedure. Often, at least in 32-bit land, you get shorter code when keeping one of them and let the others jmp to it.
Title: Re: 64 bit SEH
Post by: TouEnMasm on July 13, 2020, 11:09:44 PM
Perhaps this one had no soluce,in 64 bits
;LINK : fatal error LNK1246: '/SAFESEH' incompatible avec l'ordinateur cible 'x64' ; link without '/SAFESEH'
This option is needed to use hook in 64 bits using a particular SEGMENT
Quote
PARTAGE   SEGMENT DWORD COMMON SHARED 'DATA'
   hHook dq 0
   hWnd dq 0         ;limité en taille
PARTAGE   ENDS
On msdn,I find a sample(c++) using menu to Hook,but he fall on a  syntax abyss with SIZE_T
Any help on that ?




Title: Re: 64 bit SEH
Post by: JK on July 14, 2020, 02:31:00 AM
According to MSDN (https://docs.microsoft.com/en-us/cpp/build/reference/safeseh-image-has-safe-exception-handlers?view=vs-2019) "/safeseh" is valid only for 32 bit, it´s not supported in 64 bit.
Title: Re: 64 bit SEH
Post by: TouEnMasm on July 14, 2020, 03:10:34 AM
 :thumbsup:
Good information,need to be read