Author Topic: 64 bit SEH  (Read 2097 times)

JK

  • Member
  • **
  • Posts: 187
64 bit SEH
« on: July 05, 2020, 02:58:59 AM »
After some reading here and on MSDN, i put the following code together:
Code: [Select]
;*************************************************************************************
;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

JK

  • Member
  • **
  • Posts: 187
Re: 64 bit SEH
« Reply #1 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:
Code: [Select]
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?

_japheth

  • Member
  • **
  • Posts: 108
Re: 64 bit SEH
« Reply #2 on: July 05, 2020, 08:24:21 AM »

Your code is ok.

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

Code: [Select]
  mov rax, ExceptionContinueExecution                 ;should now resume execution at label "Resume"
;  db 0c3h                                             ;ret, prevents "leave" to be inserted, which is unwanted here
  retn
   
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

JK

  • Member
  • **
  • Posts: 187
Re: 64 bit SEH
« Reply #3 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

jj2007

  • Member
  • *****
  • Posts: 13648
  • Assembly is fun ;-)
    • MasmBasic
Re: 64 bit SEH
« Reply #4 on: July 05, 2020, 07:31:32 PM »
Cool, "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.

TouEnMasm

  • Member
  • *****
  • Posts: 1764
    • EditMasm
Re: 64 bit SEH
« Reply #5 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 ?




Fa is a musical note to play with CL

JK

  • Member
  • **
  • Posts: 187
Re: 64 bit SEH
« Reply #6 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.

TouEnMasm

  • Member
  • *****
  • Posts: 1764
    • EditMasm
Re: 64 bit SEH
« Reply #7 on: July 14, 2020, 03:10:34 AM »
 :thumbsup:
Good information,need to be read


Fa is a musical note to play with CL