Pixels Camp Quizshow Challenge #3
Or how we went behind the Quizmaster’s back
PS: Both the challenge and this post were done by me and Fernando as a team.
I was still messing around with the previous cow-related madness when the third Pixels Camp Quizshow challenge was released. Still at my office, my head was completely filled with code, both from the golf challenge and from a full week of my actual job.
That’s my best excuse for how I reacted to this:
This challenge seemed to consist on a series of image-based clues, where each one would lead me to the next (at least that part I got right).
I had seem the image before, but just couldn’t quite figure out where.
My first reaction was to go do some research on steganography. I didn’t know much about the subject but I was sure there was some hidden content on that image. I spent more than an hour on this, mostly blaming the fact that it was friday, and I was tired.
After digging up the most obscure steganography tools, something hit me, and I tried a quick Google Images Search (in case you don’t know about it: it searches the web using an image as input instead of text).
The results immediately made go back and try “facebook” as the answer (that’s what the image is representing, literally). The fact that it was the right answer only served to make me more frustrated about how I spent this past hour.
Breaking the system
A couple more images went by, as I was solving this with Fernando. By the third answer we saw a pattern:
So far, this was a list of social networks.
The other interesting point was the URL. The link for the second question was http://quizchallenges.pixels.camp/ch3/01-facebook.html. So if only we knew the possible answers for later questions, we could skip the whole thing!
The only logical conclusion was this:
<form action=”” onsubmit=”document.location=’02-’+document.getElementById(‘s’).value.replace(/ /g,’_’).toLowerCase() + ‘.html’;return false;”>
The snippet confirmed our suspicions: there wasn’t any type of validation or server side logic. It was simply attempting to navigate to another page. We could read a string, build the expected URL and throw an HTTP GET request at it.
To try the response for challenge n, all we had to do was make a request to the url http://quizchallenges.pixels.camp/ch3/$(n+1)-$answer.html. Now, this $(n+1) part is a bit tricky, because if you want the answer to challenge 2, the URL was 02. We assumed, 10 would not be 010, which later revealed to be true. Validating the response was as simple as checking if the response status was a 200.
The code for this can all be found on GitHub, and was put together in about 30 minutes, so we won’t go into detail here.
Most of the time we dedicated to the script was about gathering data sets to feed it. Curiously enough, the one that had more hits was one that Fernando dubbed as ”just a random list of the top of my head of everyday apps”. You’re getting predictable, quizmaster.
The script read newline separated values from a file. It worked at first but it was slow.
For each question, we needed to try hundreds of different requests (with the data set growing as we constantly added more). This could obviously take a while, so we looked for the quickest and easiest way to speed it up.
While Fernando kept looking for random lists too feed our data sets, I made a quick & dirty system:
- A split script that would merge all data sets into a single file, remove duplicates, and split them again into X new files, with 50 entries each;
- A run script. This would call X instances of the original script, one for each new data file, all running in parallel;
As we grew the data set, we kept trying and trying, and eventually got most of them.
While all this was happening, we would also do our own attempts (again, Google Images Search was extremely useful). Some answers such as “angry birds” and “chrome” took us a while, because we were failing to see that these were more than just social networks. Still, we reached the end pretty quickly.
The Quiz Master strikes back
Only after figuring out the last answer did we notice we would need all previous ones as well. We spent a couple of minutes cursing at the Quiz Master, and then proceeded to covering our holes.
The most difficult one ended up being “pokemon go”. It turns out, we tried both “pokemon” and “pokemongo” and a bunch of other variations, and eventually gave up on that line of though altogether.
So after finally figuring it out (with some tips from an old Codebits friend!), we can only finish this post with a quick thought: