Codegate CTF is an annual global white hat hacking competition held annually in Seoul, South Korea since 2008. This year, I participated Codegate CTF Final competition as a member of CLGT-Meepwn, a CTF team consisting of vnsecurity.net's members and students from local university in Vietnam.
My teammates and I qualified as “Senior Competition” finalists (there is another “Junior Competition” category for students) after competing against hundreds of teams from more than 70 countries around the world during a 48-hour preliminary online competition.
The final contest lasted non-stop for 20 hours in the main ballroom of the COEX International hotel in Gangnam district.
Even though the room was loaded with people, it was much quieter than you might think since everyone was fully concentrating on the game challenges. I was not an exception. My teammates and I seldom ate. Instead, like most teams, most of our stamina came from energy drinks.
This year there were four challenge categories: web, exploit (aka pwn), reverse engineering , and miscellaneous (basically all the stuff that doesn’t fit into any other category). My main responsibility was the miscellaneous category, while my teammates focused of the other three. The first task was the most challenging to me. I was only given a binary file with no information. After inspecting the data using a hex editor, I was pretty sure it was a digital signal raw data. My task was to decode it. I used Goldwave to inspect the waveform (see figure 1), and quickly recognized it as a simple amplitude-shift-keying modulation.
Figure 1: waveform of the digital signal being transmitted
I started by making a quick google search, but couldn’t find the tool that I needed. So I decided to write a decoder myself in Python. After spending a few hours of (dirty) coding, plus some guessing of higher level data representation, I was able to see the flag being transmitted: D0_nOT_4CeS5_To_mY_cAR!! I guess this is a protocol used in car control systems, but I’m not sure as I don’t own a car. (Sponsors, if you are reading this, please contact us).
The second task was to bypass the given restricted shell to read the flag. While the server would accept and execute input as a shell command, before doing so it would validate and drop commands if any of the following characters “$&./<>?bgiknps” were found. That meant that the set of valid commands was very limited. I used the eval statement, combined with shell backtick and “echo -e" to bypass the character restriction.. For example, the command “id” (invalid because of the ‘i') could be sent to server as eval `echo -e “\\x69\\x64”' and treated as a valid command.
The third challenge was to guess the correct password out of nothing to get the flag. The challenge server asked for a password. If I sent the correct password, the server would reply with a flag, otherwise it kept responding as ‘wrong’. After trying like a thousand times to guess, I realized that the server responded a little bit more slowly if I guessed a correct character at the correct offset. For example, if we assume the password was “secret”, the server would only require 10ms to determine if “xxxxxx” was wrong because it stopped checking at the first character. But it might need 20ms to respond to “sxxxxx” because the first character was correct (even though it still responded that the password was wrong) and it stopped checking at second character. This is a classic side-channel-attack used to collect a password by measuring the response time. I wrote a script to guess the whole password automatically, one character at a time. 30 minutes later, my script captured the flag.
During the last few hours we were exhausted, and we were not able to capture any more flags. We finished the game in sixth place. It wasn’t as good as we had hoped, but we were satisfied at having solved all the miscellaneous challenges. Kudos to winning team PPP, as they planted the third US flag onto the Codegate’s Hall of Fame and brought home the 30M KRW reward.