Search code examples
windbgmasmsehmasm64

How to set an exception using masm64?


How can i access the exception chain (SEH) using masm64?

Using masm32, I get the first exception looking into fs:[0]

But when I checked in Windbg if fs:[0] still pointed at the first exception in x64, I figured that it wasn't.

I'd like to set an exception in x64 the same way I did in x86. Is it feasible (maybe looking at gs register)?


Solution

  • If this is coding related then you use

    ml64seh PROC FRAME:ExceptionFilter 
    

    this adds your exception handler to .PDATA section RUNTIME_FUNCTION

    if this is how to find this exception handler in windbg when the exception has been raised

    use !exchain command

    or if you want to find it before executing a specific function use .fnent command

    a sample for x64 seh and finding it in windbg is as follows

    ;assemble and link with 
    ;ml64 /Zi ml64seh.asm /link /debug /entry:ml64seh /subsystem:console
    
    .data
    safeplace DWORD ?
    
    .code
    
    ExceptionFilter PROC 
        jmp Handler 
    ExceptionFilter ENDP
    
    PUBLIC ml64seh
    
    ml64seh PROC FRAME:ExceptionFilter
    .ENDPROLOG
        mov rax, 0
        mov [rax], rax ;access violation
        jmp exit
    Handler::
        lea rax, safeplace
        mov [r8+078h], rax ; replacing rax in exception handler so access is possible
        mov rax, 0
        ret
    Exit:
        ret 
    ml64seh ENDP
     
    END
    

    run without stopping in windbg

    :\>cdb -g ml64seh.exe
    (2aa0.3024): Access violation - code c0000005 (first chance)
    ml64seh!ml64seh+0x7:
    00007ff7`0e3b1029 488900          mov     qword ptr [rax],rax ds:00000000`00000000=????????????????
    0:000>
    

    it crashed and broke now locating exception handlers

    0:000> .fnent .
    Debugger function entry 0000020b`e36c47a8 for:
    (00007ff7`0e3b1022)   ml64seh!ml64seh+0x7   |  (00007ff7`0e3b32b0)   ml64seh!$xdatasym
    
    BeginAddress      = 00000000`00001022
    EndAddress        = 00000000`00001042
    UnwindInfoAddress = 00000000`000032b0
    
    Unwind info at 00007ff7`0e3b32b0, c bytes
      version 1, flags 3, prolog 0, codes 0
      handler routine: ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005), data 0 <<<<<<<<<
      
      
    0:000> !exchain
    3 stack frames, scanning for handlers...
    Frame 0x00: ml64seh!ml64seh+0x7 (00007ff7`0e3b1029)
      ehandler ml64seh!ILT+0(ExceptionFilter) (00007ff7`0e3b1005) <<<<<<<<<<<<
    Frame 0x02: ntdll!RtlUserThreadStart+0x21 (00007ffe`213c26a1)
      ehandler ntdll!_C_specific_handler (00007ffe`213fc720)
    0:000>
    

    lets see if we go to the handler and return back to re access the faulting place

    0:000> bp . 
    0:000> bp 00007ff7`0e3b1005
    0:000> bl
     0 e 00007ff7`0e3b1029     0001 (0001)  0:**** ml64seh!ml64seh+0x7
     1 e 00007ff7`0e3b1005     0001 (0001)  0:**** ml64seh!ILT+0(ExceptionFilter)
     
     
    0:000> g
    Breakpoint 1 hit
    ml64seh!ILT+0(ExceptionFilter):
    00007ff7`0e3b1005 e916000000      jmp     ml64seh!ExceptionFilter (00007ff7`0e3b1020)
    
    
    0:000> g
    Breakpoint 0 hit
    ml64seh!ml64seh+0x7:  is accessible now
    00007ff7`0e3b1029 488900          mov     qword ptr [rax],rax ds:00007ff7`0e3b4000=0000000000000000 
    0:000>
    

    btw you can use dumpbin or linker to spit out all the unwindinfos in a specific binary using -unwindinfo switch

    :\>dumpbin /unwindinfo ml64seh.exe
    Microsoft (R) COFF/PE Dumper Version 14.29.30146.0
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
    Dump of file ml64seh.exe
    
    File Type: EXECUTABLE IMAGE
    
    Function Table (1)
    
               Begin    End      Info      Function Name
    
      00000000 00001022 00001042 000032B0  ml64seh
        Unwind version: 1
        Unwind flags: EHANDLER UHANDLER
        Size of prologue: 0x00
        Count of codes: 0
        Handler: 00001005 @ILT+0(ExceptionFilter)