SEH

!mona seh => pop pop ret ------ short jump => \xeb\x06\x90\x90

Idea

The "JMP ESP" method that we have discussed in the "Classic" section only works for systems older than Windows XP SP1. Starting from SP1 onwards, the exception handler would zero out all the register when a crash occurs. In such case, we need develop SEH-based exploits.

SEH-based Exploits

An SEH-based exploit is made of two tricks:

  1. nSEH is always at ESP + 8. We place a "pop pop ret" gadget in EIP so that the code in nSEH will be executed.

  2. We place a "short jump" in nSEH so that the shellcode on the stack will be executed. Typically, this short jump would be \xeb\x06\x90\x90, which stands for "jumping 6 bytes forward". Here we jump 6 bytes because there are two bytes for padding (\x90\x90) and 4 bytes for current SEH.

Summary

  1. Interact with the application and write a script to verify the existence of stack overflow. To verify that the SEH structure is overwritten, go to View -> SEH chain.

  2. Fuzz the application using pattern and find the offset. Note that the offset we need is offset - 4: the last 4 bytes are for nSEH.

  3. Find a pop pop ret gadget from a library without protection.

  4. Figure out how many bytes to jump (typically 6 bytes forward).

  5. Find all badchars.

  6. Generate shellcode using msfvenom.

  7. Get shell or pop calc.

Payload

payload = ""
payload += "A" * (offset - 4)
payload += "\xeb\x06\x90\x90" # nSEH => jump 6 bytes forward
payload += <pop_pop_ret> # SEH => pop pop ret
payload += nop_sled
payload += shellcode
payload += another_nop_sled
payload += padding

SafeSEH

If SafeSEH is enabled on the target system, the system is going to check if the current SEH is pointing to a valid address in the current library. If not, the system would terminate the program. We have to bypass the SafeSEH protection so that our SEH-based exploit will still work.

If SafeSEH is enabled for some libraries, we just pick a pop pop ret gadget from a non-SafeSEH library. However, if SafeSEH is enabled for all libraries, we won't be able to find a good pop pop ret gadget. Instead, we use pvefindaddr.py to find a pop pop ret alternative:

!pvefindaddr jseh

Typically, you would find some gadget like call dword ptr[ebp+30h]. A big problem here is that the address we find would contain a null byte at the beginning. On Windows XP SP3, this address is 0x00280b0b from unicode.nls. This null byte is an extra barrier for us because we won't be able to provide any input after it. That is, we have to store the shellcode before this address and do a backward long jump to execute the shellcode.

Reference

Last updated