Windows SEH Overflow (EasyChat)

Scenario

You have been tasked by your red team manager, to refresh your Windows exploit development skills. Specifically, he provided you with a machine (172.16.5.120) that features a vulnerable to SEH overflow version of the EasyChat server. An exploit skeleton* is also provided to you. Your task is to fully exploit the SEH-based overflow vulnerability of the EasyChat server.

*Find below the exploit skeleton that causes the application to crash.

import os, sys, socket
ip = "172.16.5.120"
port = 80
socket = socket.socket(socket.AF_INET , socket.SOCK_STREAM)
socket.connect((ip , port))
buffer = "A" * 725
request = "POST /registresult.htm HTTP/1.1\r\n\r\n"
request += "Host: 172.16.5.1"
request += "User-Agent: Mozilla/5.0 (X11; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0"
request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
request += "Accept-Language: en-US,en;q=0.5"
request += "Accept-Encoding: gzip, deflate"
request += "Referer: http://172.16.5.1/register.ghp"
request += "Connection: close"
request += "Content-Type: application/x-www-form-urlencoded"
request += "UserName=" + buffer +"&Password=test&Password1=test&Sex=1&Email=x@&Icon=x.gif&Resume=xxxx&cw=1&RoomID=4&RepUserName=admin&submit1=Register"
socket.send(request)
data = socket.recv(4096)
print data
socket.close()

Goals

  • Fully exploit the vulnerable EasyChat server

  • Spawn calc.exe as a proof of concept

What you will learn

  • Exploiting SEH-based stack overflows

  • ImmunityDbg

  • Mona.py

  • Python

  • Notepad++

Network Configuration & Credentials

  • Vulnerable machine: 172.16.5.120

SOLUTIONS

Below, you can find solutions for each task. Remember though that you can follow your own strategy (which may be different from the one explained in the following lab).

Task 1: Recognize the exploitable conditions

Let's try to figure out if we are really dealing with an SEH-based overflow and also, what offset exactly is needed to overflow the SEH. Let's launch the application (You might need to click the confirmation window before it starts listening for incoming connections).

Content Image

Let's attach a debugger to the EasyChat process, as follows.

Content Image

After attaching, remember to press Run (F9) since the application will be in a paused state.

Let's now launch the exploit against the application.

Content Image

Let's also pass the exception to the application.

Content Image

It certainly looks like the EIP can be controlled via SEH overwrite.

Feel free to use Immunity's "View -> SEH chain" functionality yourself to witness the SEH overwrite.

Task 2: Find offset to the seh/eip

Let's try to figure out the offset to the SEH structure using Mona's pattern_create, as follows.

Content Image

We can find the complete pattern inside the Immunity Debugger folder on a file called pattern.txt. The default Immunity Debugger location is:

C:\Program Files\Immunity Inc\Immunity Debugger

Let's add the pattern into ours exploit, as follows.

Content Image

After we restart the application and reattach the debugger, we launch the latest exploit. Once an exception is encountered, it is passed to the application.

Content Image

To identify the offset, we pass the displayed EIP to Mona's pattern_offset.

Content Image

We now know that we need to overwrite 221 bytes. This is until the current SEH. If you recall, there is also an nSEH record before the SEH, which is also 4-bytes long. We should thus remember that we start overwriting the exception handler structure at 217 bytes. Let's modify the buffer and launch the modified exploit against the target in order to confirm if our calculations were correct.

Content Image

Before passing the exception to the program, let's go to view -> SEH chain.

Content Image

We can see that the SEH structure was properly overwritten. Also, we can scroll down the stack view to see it.

Content Image

After passing the exception to the program, we successfully overwrite EIP with C's

Content Image

Task 3: Move the execution flow past the SEH entry

The next thing that will be required during the SEH exploitation, is the POP-POP-RET gadget. We can quickly find it using mona, as follows.

Content Image

Since the output is pretty large, you can also find it in the default Immunity Debugger directory as an seh.txt file.

Content Image

Let's choose any gadget that ends with a regular ret (ret X will corrupt the stack) and let's incorporate it into the exploit. Moreover, since the gadget will cause the program to start executing whatever is in the nSEH, let's place breakpoints there so in case we successfully alter the execution flow, we will know about it.

Content Image

Upon encountering an exception, do not immediately pass it to program. Let's first scroll down the stack and find the overwritten SEH structure. Go to the SEH pointer and right-click. Select "Follow in disassembler" from the drop-down menu.

Content Image

You can see the instructions that are placed at this address (exactly those that were members of the chosen gadget).

Content Image

Select the first POP instruction and right-click it. From the drop-down menu select Breakpoint -> Memory, on access.

Content Image

As the breakpoint is placed, we can now pass the exception (Shift + F9) to the program. The execution will stop exactly at this instruction. From this point onwards, we will use the Step Into (F7) instruction, that makes the debugger go just to next instruction.

Content Image

After pressing F7, we will land at the second POP instruction. We can see that the stack value was popped to the respective register. Press F7 once again, so you land on the RET instruction.

Content Image

As we already know, RET causes the program to execute whatever the stack pointer is now pointing to. What is that? First, make sure you have your stack window aligned to ESP. Right-click on the ESP address and choose "Follow in Stack"

Content Image

Now, right click on the top address on the stack and choose "Follow in Dump"

Content Image

You can observe that those breakpoints that were put in the place of the nSEH, are now going to be executed.

Content Image

Press Step Into once again.

Content Image

And we are executing the breakpoints!

Now, since we know that the nSEH can be executed, we should change it to something useful, that will help us omit the SEH pointer and start executing whatever lies past it.

We can use the standard trick of short jump-ing 6 bytes forward. The opcodes for it are:

EB 06. In order to pad the remaining 2 bytes, we can use NOPs. This translates to the following.

Content Image

Moreover, we add a shellcode placeholder containing one break point. If we will be able to reach the shellcode, the debugger will stop.

Let's launch the exploit and pass the exception to the program. We are executing shellcode!

Content Image

Task 4: Discover any bad characters

Before we implement the final shellcode, let's check for the presence of bad characters. We will send a buffer of all ASCII's instead of shellcode.

Content Image

After passing the exception to the program, we can inspect the stack for malformed bytes. There are two (\x25 and \x2b) which were changed to some other bytes.

Content Image

Task 5: Finalize the exploit

Knowing which characters are bad for this software, we can finally generate shellcode using msfvenom. We can also add it to the exploit, replacing the single breakpoint.

  • msfvenom -p windows/exec cmd=calc.exe exitfunc=thread -b "\x00\x25\x2b" -f c

Content Image

Let's launch the latest exploit against the software without attaching a debugger to it. Calc should show up!

Content Image

Last updated