An Autonomous Zone

An autonomous zone to promote an exchange of ideas, skills, and experiences with computer (in)security.

An Autonomous Zone header image 2

Windows Overflows

July 6th, 2008 · 1 Comment

So – I’ve been playing with buffer overflows (bofs) on win2k3 and XP sp2 lately (I really mean executables compiled with the /GS flag in Visual Studio .NET 2003 and later).

I guess the purpose of this post is to see how others might be doing/trying some techniques…

And please – if any of this stuff below is incorrect post something to straighten me out.

Starting with techniques and using overflows in win NT and 2000:

I think Vinnie Liu did a great job to summarize a common technique for bouncing back to shellcode on the stack for the earlier platforms:

Unfortunately, the base address of the Windows stack is not as predictable as the base address of the stack found on UNIX systems. What this means is that on a Windows system, it is not possible to
consistently predict the location of the payload; therefore, returning directly to the stack in Windows is not a reliable technique between systems. Yet the shellcode is still on the stack and must be reached.
This is where the second method, using a shared library trampoline, becomes useful to us.
The idea behind shared library bouncing is to use the current process environment to guide EIP to the payload regardless of its address in memory. The trick of this technique involves examining the values of
the registers to see if they point to locations within the attack string located on the stack. If we find a register that contains an address in our attack string, we can copy the value of this register
into EIP, which now points to our attack string. The process involved with the shared library method is somewhat more complex than returning directly to the stack. Instead of overwriting the return address with an address on the stack, the return address is overwritten with the address of an instruction that will copy the value of the register pointing to the payload into the EIP register.

http://www.syngress.com/book_catalog/327_SSPC/sample.pdf

So, easy enough – assuming that the register EAX points to some payload on the stack you just overwrite the EIP with a CALL EAX and then you’ll be bounced into your payload.

Then the next step for windows bofs came in the form of SEH (Structured Exception Handler) overwrites. This allows cross-platform and more reliable exploits in general.

Generally the idea is to overwrite the stack further than the buffer, past the return address, and onto the SEH chain. Then one can use a same jump back method to our shellcode as described above. The only difference is instead of using a register to bounce off of (like CALL EAX) we find a “pop,pop,ret” address and place that in the SE Handler.

Now we finally come to Win2k3 and XP sp2 exploit techniques.

So for Win2k3 MS introduced stack protection into the system by way of the new compiler option “/GS.”

/GS is the security cookie (or canary) that is placed in front of the saved return address when a function is called.

According to Litchfield’s paper:

http://www.nextgenss.com/papers/defeating-w2k3-stack-protection.pdf

If a buffer local to that function is overflowed then, on the way to overwriting the saved return address, the cookie is also overwritten. Before the function returns the cookie is checked against an
authoritative version of the cookie stored in the .data section of the module where the function resides. If the cookies do not match then it is assumed that the buffer has been overflowed and the process is
stopped. This security mechanism is provided by Visual Studio .NET – specifically the GS flag which is turned on by default.

Fortunately there’s a way around this.

It involves the use of SEH once again.

First we look at what happens when we overwrite the cookie:

If a local buffer is overflowed and the cookie is overwritten what happens? Well, when the check is performed and it fails the code checks to see if a security handler has been defined. This security
handler exists so that the program’s developers can take actions such as log things before terminating the process if they see fit. A pointer to this handler is stored in the .data section of the module

According to the above snippet the SEH is still used – only MS did some tweaks to this as well on Win2k3 / sp2…

When overflowing stack based buffers on Windows platforms one of the mechanisms available to the attacker to gain control of the process is to overwrite this EXCEPTION_REGISTRATION structure – setting the pointer to the handler to a block of code or an instruction that will redirect the flow of execution back to the buffer.

(…)

Microsoft has recognized this as a problem and with Windows 2003 Server structured exception handling has been modified in an attempt to prevent such attacks. Exception handlers are now registered and the addresses of any handlers in a module are stored in the Load
Configuration Directory of the module. When an exception occurs, before the handler is executed its address is checked against the list of registered handlers and it will not be executed if no match is
found. If however the address of the handler, as taken from the EXCEPTION_REGISTRATION structure, is outside the address range of a loaded module then it is still executed.

So the trick now on Win2k3 / sp2 is to overwrite the SE Handler pointer with an address that is outside the range of a loaded module and points to a block of code or instruction that allows us to get
back into the EXCEPTION_REGISTRATION structure (specifically the “Pointer to next SEH record” pointer).

If, however, we examine the state of the stack on the calling of an exception handler we can find many pointers to the EXCEPTION_RGISTRATION structure that has been overflowed:

ESP + 8 + 14 + 1C + 2C +44 +50
EBP + 0C + 24 + 30 – 04 – 0C – 18

Table 1.

If an attacker can find an instruction that executes a

CALL DWORD PTR [ESP+NN]
CALL DWORD PTR [EBP+NN]
CALL DWORD PTR [EBP-NN]
JMP DWORD PTR [ESP+NN]
JMP DWORD PTR [EBP+NN]
JMP DWORD PTR [EBP-NN]

where NN is one of the offsets found in Table 1 above, at an address outside of the address range of a loaded module then it will be executed on the event of an exception. This will redirect the flow of
execution to the “owned” exception registration structure.

The other alternative is to find a “pop reg, pop reg, ret” instruction block outside of the address range of a loaded module.

So to sum it up for win2k3/sp2 boxes – we have to overwrite the buffer, EIP, and finally the SE Handler then from there we shove an address from an unloaded module that is either an appropriate offset
from EBP or ESP, or we can shove a pop,pop,ret value in there. From there it will bounce off of the address in the unloaded module back to our _EXCEPTION_REGISTRATION structure (one byte before the SE Handler – the Pointer to next SEH record) – meanwhile the address to our payload is in the Pointer to next SEH record -> profit.

So, there should be a few addresses that we (an attacker) can use to bounce back into the SEH handler structure (a proper offset address from EBP/ESP or a pop,pop,ret) that is in an unloaded module.

Litchfield has some code in the appendix of his paper that does this. One snippet is code that injects dll’s into a process and the other is the dll that scans the memory space of a process looking for these
sacred values/addresses that we can use.

However, I changed it up just a bit. From the Readme.txt file in my archive:

code.c is a dll that sweeps the address space of an executable (after being injected into it’s process space) looking for good values to shove into the SE Handler (like pop,pop,ret’s and proper offsets from Litchfield’s paper) to use in getting around the /GS flag.

I use injc.exe instead of the loader provided by Litchfield in his paper because in Litchfield’s you need to supply the process ID of the exe that you want to inject into. This does not fare well when the exe is a command-line program that completes in a short (milliseconds) time.

I also modified Litchfield’s code.dll a bit (just the dll entry function).

Using the injc.exe – it is possible to inject the dll at the target programs start-up.

Example:

injc.exe -c code.dll hello.exe

This will result in a results.txt file with acceptable offsets to use in the SE Handler to bounce back into the Exception_Registration structure on the stack.

It is important to note that the results.txt file will contain the proper opcodes to use – but out of all of these, we need to filter out the values that are in mapped memory segments which are marked as non-exec.

You can get my version of this thing here.

Cheers,

Chuck B.

Tags: Exploitation

1 response so far ↓

  • 1 neeko // Nov 13, 2008 at 1:29 am

    Thanks for this. I’ve only recently began studying “the Windows world” and I found your post very informative and accessible even for someone with very little Windows background.

Leave a Comment