Capture The Flag Challenges from Cyber Security Base with F-Secure

The Univeristy of Helsinki (Finnland) created an online course on mooc.fi called Cyber Security Base with F-Secure where I participated. Although I don't need it, you get 10 ECTS credits for participating. The course contains five parts and the last part is a CTF (Capture The Flag), which this blog post is about. The CTF gives only one credit (worth around 27 hours of work) and I spent a lot more, but I completed all tasks. The CTF itself (described here) links to the 20 challenges. Participating requires signup for the course, but maybe the university opens it later for everyone. If not, read the challenges here. For most you don't need anything else than the description. In some cases you need an image (which you also find here) or a link to a program (while available you can still download it). Only the three "bank" challenges require that the site is still available. I'll describe here the individual challenges and how I solved them. For some I received some hints in the challenge group chat and I'll mention this as well where I did.

The 20 challenges were divided into three categories (9 Easy, 8 Medium and 3 Hard). Initially you could only see the 9 Easy ones and to get to the next level (Medium), you had to complete all 9 Easy ones first. The same applied to open up the Hard level (complete all Medium first). To get your 1 ECTS credit, you had to complete all Easy and at least 7 out of the 8 Medium ones (80%).

Every challenge shows how many people solved it and who was first alongside the challenge. After the Easy ones were released, the Medium ones were released a day later and the Hard ones again a day later, with the intention that "everyone has a chance to get his/her name into one of the tasks". This didn't really work though, as the time of release was not clear. Also, the Easy ones were released one day too late over night and the next morning all were solved by someone already of course. For the Medium and Hard ones, I was simply too slow, although I had opened the category on time. In one case (I think it was either "Cyber monkeys strike back!" or "Forgot the password?") I was only seconds too late for being first. No chance for the hard ones being first though, although I had all Medium ones on time when the Hard ones were posted.

Summary

Overall I liked the challenges. I did not like the delaying of the CTF, because I prepared my time for the initial dates. Then it was delayed to take place on Easter. Not a good time, but anyway, I cancelled all my family vacation plans and prepared to start then - only to hear that it was delayed again. Then it was announced for the 24 of April 2017, a day where I have free the whole day (local public holiday) and the entire day nothing. No update, no delay. And when I finally go to bed (ok, just before midnight is maybe a bit early), then the next day I see that the Easy challenges were released without notice and of course all already solved. I also didn't like that there were so many non-technical tasks, like data harvesting from movie characters and the instructions not clear (2800 names?) or three different steganography challenges without getting prepared for that. I think that many of these tasks were not covered in the course, but things that were covered did not appear in the CTF. I missed for example a SQLi task. It would've been easy to set one up (read-only). Or getting a pcap file for analysis. Or exploiting a program over the network where you can analyze the source code and find a vulnerability. Or in the hard challenges a real reverse engineering task, but maybe that would've been to hard, as assembly was not covered in the course or might have been a level too high for the expected audience. Finding the right tool for stego is not really challenging, it's more frustrating. But overall I did learn a lot and it's a great relief that I was able to solve everything, even if in some cases getting some tiny hints from others. I learned to know some Linux tools (many challenges were Linux based, although I could avoid setting up a Linux VM until almost the end). I also learned to use gdb, steganalysis, using hash crackers and fuzzers. Although I knew most of that, I had very little or no practical experience with these things. I have never before participated in a CTP and this was a very good experience. I am much better prepared for a future one now.

Did you participate too? If yes, what were your feelings? Did you take a completely different approach in one of the challenges? Any mistakes in my write-up? Feel free to comment.
If you'd like to contact me personally, I'm @e4ch on Twitter.

Title image for all solved

Now without further ado, let's go to the individual challenges:

Easy

Cats

Description: "Something is not quite as it should be in this image. Can you find it? http://sec-mooc-1.cs.helsinki.fi/cats/537c93da-0be9-45da-85f4-857ac2b33f8d/cat.jpg"

cat.jpg from the first cats challenge

I think this was the easiest one for everyone, as more than 210 users solved this challenge.
Solution: This is a steganography challenge, which means that something is hidden in the image. It's a jpg file. If you open the file with a hex editor (I'm using the free HxD editor in the old version 1.7.7.0), then at the end you find some added text. If you're familiar with the jpg file format, then you know that the main data is finished after the marker FF F9, so anything behind it will usually get ignored. You find there the hidden text \a{HiddenCatFlag01}\a and the text between the brackets is our first flag.
Hex Editor (HxD) showing the cat image with the flag at the end

Crack the password

Description: "Can you figure out the password? The binary file should work in 64-bit Linuxes.http://sec-mooc-1.cs.helsinki.fi/password/f375b6e1-a9f7-415f-a31d-9344eedaea4d/password_checker"

Solution: As I have a Windows system as my main system, I didn't want to set up a Linux VM just for this challenge. The first thing I did was to open it up with a hex editor. I only found the text "Enter the password :" and "You entered correct password" and "You entered incorrect password" and a story "Far far away, behind...". So I thought the password was probably hashed or something a bit easier. So I started the reverse engineering work on it. First I opened it with IDA Pro (demo), but it complained that it's a 64-bit binary that is not supported in the demo version. Then I opened it in Hopper (Windows version 2.8.7) where I have a license for it. Unfortunately newer versions of Hopper don't exist on Windows. Hopper is factors cheaper than IDA Pro, but it now only exists on Mac (and a bit less supported also on Linux). It's a good alternative if you want to start reversing binaries. I couldn't see any password string on first sight though, so I thought I give Snowman a try. It's a decompiler, which helps with these tasks and gives you essentially the source code. This is the first time I'm using Snowman and I didn't find out why there are two different executables, but the nocode.exe is the one that is working with this binary.

decompiling with Snowman
Opening the file in the free version of Microsoft Visual Studio 2015 and scrolling to the middle of the file shows the checking code:
password comparison in the first password_checker tool
This code clearly shows the correct password, which is also the correct flag. I wondered why this is clear-text here, but why it was not visible in the hex editor, so I had a look again.
password_checker in HxD
And there it was. I don't know how I could have overlooked this the first time. Anyway, challenge solved.

A simple hashing scheme

Description: "Simple hashing involves encoding of strings of characters for example "hash" -> hex 68617368 -> dec 1751217000. A hash function takes in strings of variable length and transforms them into fixed length strings. A simple example would be to take modulus 16 of the string. What would the mod be for string "flagc""
Solution: Ok, so first we have to convert the text to hex values. We can either look up the hex values for the five characters and append them. But I was too lazy and used an online string to hex converter. So we get the hex values 666c616763. We can now use the built-in Windows 10 Calculator, switch to "Programmer" mode, switch to hex and enter that number. We see that this is 439'904'986'979 in decimal. The calculator has a Mod function built-in, so Mod 16 results in 3. It's actually even much easier; we can just take the last digit of the hex value, which is also '3'. We wouldn't even need to convert the entire text, just the last character 'c' is 0x63, so the right-most character is 3 and that is also the correct flag. As an example this is nice, but it's of course not a real hashing function, as you can change the beginning of the text without changing the hash.

Super advanced encryption

Description: "Our advanced cyber monkeys have invented an encryption scheme that's supposedly impossible to crack. Can you prove them wrong? Ciphertext: "PloreFrphevglOnfrSyntN"."
Solution: Now this immediatly looks familiar to me. It's probably a substitution cipher. Probably ROT13. Let's try that with an online tool for ROT13:
So this gives us immediately the correct flag. Easy one.
The only problem there was that this flag did not get accepted. Only one person had solved it. Looks like a bug. And indeed, later someone told me in the public chat room that there is a bug, but entering the encrypted text as flag works. So I solved it that way too. A bit cheating, but with a broken challenge (and I did solve it first) this seems a legit way to mark it as complete. I think the challenge got fixed later.

Hidden in script

Description: "CyberBank (https://cyber-bank.testmycode.io/) should have a hidden debugging mode in their Javascript code which should leak their secret backend key. Can you find it?"
Solution: Ok, let's open the site first.
Cyber Bank start page
View source shows a simple HTML page with one single CSS and on JS include.
So I downloaded the JS file and when opening it in Notepad, we see this mess:
JS include file of Cyber Bank
So in order to read anything there, we need to beautify it. The nice site jsbeautifier helps us with this. Remove the default checkbox "Space before" and change the first dropdown to "Indent with a tab character", then paste the content into the input area (overwriting the data in there) and click the Beautify button. Then copy the result into a new file and save it. When you paste it, you already see a text "cyberdebugmode", which is the hint given in the challenge. Opening this file in the free version of Microsoft Visual Studio, we can see this code:
cyberdebugmode in Cyber Bank
Just next to it, you already see an URL /nothing_to_see_here.json, so let's open that URL.
hidden URL in cyberdebugmode
So there you see the backend-key. Entering this key is already our flag and this challenge is solved.
Additionally I wanted to know what this code does. It is a bit obfuscated. But you can easily de-obfuscate it by replacing the variable _0xfbfd[n] with the string from the array.
deobfuscated cyberdebugmode (click to enlarge)
Now you can see that this code downloads the data from that URL by using an XHR (XMLHttpRequest), checking the response and parsing the JSON data and getting the value for the backend key. I tried to enable the cyberdebugmode by commenting out the "if (localStorage["cyberdebugmode"] == "true") {" as you can see in the screenshot above, but nothing changed. I was too lazy to investigate more, as I already had the flag.

Admin panel

Description: "Rumour has it that CyberBank (https://cyber-bank.testmycode.io/) has a secret admin panel containing top secret information. Your client wants you to find it and to 'obtain' its secrets. The panel supposedly leaked previously when a popular search engine accidentally indexed it. However, security has been tightened since then."
Solution: First I had a look at the site of course:
Start page of the Cyber Bank

First I checked if there was anything on Google still cached for this site, but I could only find the start page. Then I tried Bing. Then the Internet Archive (Wayback Machine). Nothing.
So I read the challenge again. It clearly mentions something with search engines. So after a bit of thinking, I thought "Let's have a look at the robots.txt file." Opening this, we get a nice hint:
robots.txt of Cyber Bank
So let's open this new URL.
Admin Panel of Cyber Bank
So here we have our flag.
Much after I solved it, I saw a lot of hints for this one on the chat, so I think most users managed to solve this.
Only after having solved this second bank challenge, I realized that you could log in. But the content there was blocked until the Medium challenges were open, so nothing special I have missed. Well, almost. Someone else discovered a real admin site being user-accessible, so that way he could prepare for the third bank challenge by increasing his money even before the challenge. But this was fixed anyway before the third bank challenge opened.

Alice's crypto party

Description: "Alice has chosen two primes p=45000023 and q=52000031 for her RSA modulus n and an encryption exponent e=3. She receives a cryptotext 7 that has been encrypted with her public key. What is the plaintext?"
Solution: Ok, we had this in our course. Asymmetric RSA cryptography. We even had exercises to it, but they were multiple choice. Now here we have a real example. Let's do the math.
Before I solved it, someone spoiled that he used WolframAlpha to solve it. WolframAlpha is a mathematics tool where you can enter english text and it tries to interpret it. So the first thing I tried was to enter RSA(p=45000023, q=52000031) and let WolframAlpha work on it. Luckily it did not understand our crypto query (I also tried several variations).
So we need to go back to our course Advanced Topics, Cryptography (or Internet) and find how to solve this. The chapters 1.6 and 1.7 of our course explain Public-key cryptography and RSA. At the end of chapter 1.6 there is a task to calculate "log_3 7 mod 100", where the correct multiple-choice answer is 15. During the course I struggled a bit, because log3(7) is not an integer, but 1.7712.., but then I found out that with the term "log_3 7 mod 100" they actually mean "solve for x: 3^x mod 100=7". With that knowledge, let's go back to the RSA challenge.
I looked instead at the first Google result for explaining RSA with simple numbers. We have p and q, so we also have:
Windows Calculator can handle this. Now we need φ:
We already have an integer e=3 that is greater than 1 and smaller than φ. Now the complicated part: We need to find d, so that e·d = 1 (mod φ). The footnote says the calculation should be done so that d=e^-1 mod φ. This calculation is similar to the logn calculation above. But we don't really have to understand this, how the modular inversion really works, as that doesn't really matter for here. With the given numbers, we have:
This is where WolframAlpha can help us. Entering it there gives us the following result:
The second term is φ and we already know that multiplications by φ can get removed, because we use "mod φ". So we now know that d=1'560'001'662'667'107. Now we have all required numbers to do the decryption. With the ciphertext c=7 we have the formula
This is our flag. Let's verify it by doing the encryption. The ciphertext is:
So this seems to be correct. Maybe they intentionally created a small ciphertext number - many people probably expected then a small cleartext message number as well, which is wrong in this case.

Awkward Ending Syndrome

Description: "A Canadian Born person named Chad has received the mysterious message "3B953347892900C95858A5C16FD8DFB0920DF37294CBC3313AAB85608D32328D" that has been encrypted with his key "000102030405060708090A0B0C0D0E0F". Unfortunately, Chad forgot which encryption scheme he is using. Can you decrypt the message?"
Solution: From our course we already know that this is probably AES. Especially as the key is so short. So let's try some online tools.
Somehow I landed first on the site http://aes.online-domain-tools.com/, but it never showed any useful result, even with the correct selections (input as hex etc.).
So I went to search other sites. Then I found http://aesencryption.net/ and that looked promising, because there I can set the key width. Counting the bits in the key I got 128 and I selected that in the dropdown. No useful result there either.
Then I came to http://extranet.cryptomathic.com/aescalc/index and there I had to select an IV, which I didn't have. So I used the default zero-value string and I tried with that. The result was a hex string. So I had to convert that hex string to a text and I used the tool http://www.online-toolz.com/tools/text-hex-convertor.php for that. Unfortunately only the first half of the text was decrypted that way:
Wrong result for Awkward Ending Syndrome

It looks like many people had this problem.
Remembering how AES works, I remembered that we have many different modes, so I looked that up. Wikipedia has a nice description of the different block cipher modes.
Going back to the site AES Calculator, we just have to switch from the default ECB to CBC and it returns a nice result already in hex mode:
Correct cipher mode for Awkward Ending Syndrome
Converting that into a text:
Awkward Ending Syndrome Flag

Now finally we have our flag. It would probably also have be possible to guess just the last missing character, so I wonder how many people have done that.

Save the Day

Description: "A critical production system needs maintenance but everyone has forgotten how to access the system. The management has hired you to hack the system and to provide them a way to get back in! Unfortunately, due to budgetary constraints, you all you were given was this log file: http://sec-mooc-1.cs.helsinki.fi/logs/60f3e5fe-bb7b-488c-ac81-15af3f8d41c6/log.gz Can you save the day and recover the administrative access?"
Solution: First you have to download and decompress the file of course. This gives you a huge 208MB text file, which you can impossibly manually scan or even view. So the exercise is probably to test how you can handle big log files. I have Microsoft SQL-Server installed, so it would be easy to handle this there, but I thought I use just standard tools and used Microsoft Access for this.
So I selected External Data / Text File and went through a bunch of import screens:
Microsoft Access Import Screen 1
Microsoft Access Import Screen 2
Microsoft Access Import Screen 3
Microsoft Access Import Screen 4
Microsoft Access Import Screen 5
Unfortunately, after the import was completed, I got a bunch of import errors:
Microsoft Access Import Errors
It looks like one field (qry) is too long and gets truncated. So I had to repeat this again and set a different data type. Instead of 'short text' I had to use 'long text'. Then the import worked.
Our hint cannot be in the IP address or in the status codes or user agent, so we should concentrate on the qry field. So I selected DISTINCT on that field (by using GROUP BY, because DISTINCT doesn't work on long text fields). That reduced the 1'098'868 records to 6'251 rows. Still too many to manually check. Scrolling through the list, I noticed that many entries are pretty much the same, just with a different appID value, like in this screenshot:
Many similar rows
So I had to filter those out by writing a small query:
Query in Microsoft Access to filter away the similar entries
This now leaves us with 856 distinct HTTP queries (plus the 5 ones that we filtered away). This is an amount we can handle manually.
My first approach was to look at these extremely long ones, especially because they start with /administrator in the URL. But looking closer into them, it seems these are attempts to plant a backdoor onto the system. You can see that if you look at the payload in the query, which posts a base64 encoded file onto the system. Actually many of these returned a 200 OK, so I wonder if they could successfully infect the system. But this is not the flag, so let's ignore these long entries.
We can either manually scroll through the list or filter by "admin" in the text and also filter out the backdoor implant ones, then we have 61 distinct queries remaining. The longest one, clearly stands out:
Flag for Save the Day
And there we have our flag.

Medium

Hack a Bank

Description: "The marketplace in CyberBank (https://cyber-bank.testmycode.io/) has information for sale that your 'friend' requires. Sadly, you lack the necessary funds to acquire this information. Use your hacking skills to obtain more currency and obtain the information."
Solution: This is the same CyberBank as in the Easy challenge. Therefore we now need to log in. Logging in with our course credentials, we get presented a screen with transactions and an account balance of exactly €1000.- (the screenshot shows my account after solving the challenge, so the amount is different):
Login screen of our Cyber Bank
Then we see in the menu that there is a Marketplace where someone sells a product for €1200.-. The only problem is that we don't have that amount of money. Then there is a Convert Money screen, where you can convert Euros into Cyber Money and vice versa:
Cyber Bank Conversion Screen
As we have no other options left to interact with the bank, this must be our entrance. So I've set up the free edition of Burp Suite. As our bank uses SSL/TLS and HSTS, I had to set that up correctly according to Burp documentation first. So I played around with converting money. The conversions are safe, all checks are done on the server side, even if the checks for 'amount too low' etc. are done with client-side JavaScript, but checked again on the server. Interfering with the values was always catched on ther server. So no cheating with negative values or fractions or things like that. But after converting back and forth some Euros, I noticed that I had less total money in my account. So that is something I had to investigate further. For example, after converting one Euro from the screenshot above, after conversion, I had this status:
Cyber Bank Conversion Screen after converting one Euro
So both values (Euros and Cyber money) get rounded to two decimal points in your account. I tried a lot more to interfere with the fractions while converting, but everything seems to be handled fine. It's just that after converting the amount is rounded. I first thought that converting back and forth is not the same exchange rate, as usual with banks, so trading a lot would lose money. But 1/32 is exactly 0.03125, so it should not be possible to lose money. But if I only get credited for 0.03, then the rest is gone. Could I do the opposite? I started calculating and created an Excel sheet.
Currency Conversion Cheat Sheet
So the best amount to change is 4.00 EUR and you get 0.13 Cyber for it. Converting 0.13 Cyber back to EUR gets you 4.16 EUR. Ok, so we have a plan. I didn't want to manually convert that by clicking around. So I looked into Burp on how to automate that. The form of course uses a session cookie so that it knows which account to associate this with. Additionally, there is a CSRF token that is validated. So my plan was to automate that with Burp so that I first get the status page and then do the conversion with the updated values. I couldn't figure out quickly on how to automate that with Burp, but I noticed that neither the session cookie nor the CSRF token get invalidated by using them, although new values get issued. So it looks like this Cyber Bank has three vulnerabilities (conversion rate problem and the two values that don't get invalidated). I left the repeater running in Burp for the manual 4 EUR conversion until I had no money left, then manually converted the Cyber Money back to Euros and everything again. Actually I could do it at the same time; let the repeater running while Burp was converting 4 EUR to Cyber all the time and me converting 10 Cybers back to Euros every 10 seconds or so. This didn't take too long until I had 2112.24 Euros and could buy the deal in the Marketplace:
Flag for our bank2 challenge
And there we have our flag. I didn't try what would happen if I bought it a second time, but probably nothing special would happen. I intentionally got much more than the required 1200 Euros, because I thought I might need the money in a future challenge again and when you only have 4 Euro left, it's much harder to get back to a big amount.
Doing such a rounding error attack didn't feel like the right solution, especially because I had to issue so many web requests, almost DoS'ing the server, but the organizer confirmed that this was the right way to solve it. After I solved it, there were many questions about this in the chat and others also didn't feel that this is the right solution. Also I saw then hints like "if you can lose money, you can win it too, right?". I didn't need that hint though.

Cyber monkeys strike back!

Description: "Our cyber monkeys try to be clever and invented a better scheme for encryption. Or did they? Can you prove them wrong? Ciphertext: "WsvylMywolcnsVumyZfuaXW""
Solution: This doesn't look more complicated as the ROT13 one from the Easy challenges. But only that ROT13 doesn't work here. The website for rot13 has a nice dropdown where you can change ROT level. Clicking through the first few values, the following gets revealed:
Cyber monkeys 2
So there we have our flag. Not really Medium level. This was solved in less than two seconds after activating it. But no chance for me. I didn't even finish reading the challenge when it was already solved.

Fuzzy calculator

Description: "Our startup has developed an advanced calculator app for 64-bit Linuxes. Unfortunately, the app has a serious memory safety problem. What is more, our competitors have a similar products without these kind of problems. We have act quickly before the market reacts and gets too much stacked against us. Can you trace down the exact point where the problem occurs? http://sec-mooc-1.cs.helsinki.fi/clock/a2f79db3-c910-482e-baa2-b4da7b3caa99/clock (Note that the address should include all leading zeroes and the hexadecimal prefix e.g. 0x0000000000000001)"
Solution: The "note" was added later by the way, because many people had difficulties solving this. I solved it as last of the Medium challenges, because this one requires you to set up a fuzzer, so I probably need a Linux VM, which I didn't have so far. So I downloaded Kali VM for Hyper-V and set up a new VM. For this write-up I'm doing this all again, to make sure I don't miss any installation step.
After importing the VM files into Hyper-V, I configured it (16GB memory, 4 CPUs, GPU, networking). Then after startup, add the correct keyboard layout and start Terminal. Download AFL from Firefox and open it with the Archive Manager and extract the afl-2.41b folder to root. Also download the clock binary to root (the default working folder). Make the clock program executable with chmod +x clock.
cd to the afl folder and make it. cd to the subfolder qemu_mode and run the script ./build_qemu_support.sh. It will fail with "libtool not found". Install it with apt-get install libtool-bin. After trying again, you'll get the error "automake not found". Install it with apt-get install automake. After trying again, you'll get the error "bison not found". Install it with apt-get install bison. After trying again, you'll get the error "glib2 not found". Install it with apt-get install libgtk2.0-dev. Update your whole system with apt-get update and then retry running the script ./build_qemu_support.sh. This will now run for a while.
cd back up one level into the afl folder. Create the two folders testcase_dir and findings_dir (mkdir command). In the testcase_dir, create a file init.txt with the content 1+1 and a line break. You can create that with vi init.txt, press 'i' for insert mode, write the text and return, then :wq and enter to save and close vi.
running afl-fuzz
The -Q parameter is to use qemu (which we built above), because afl cannot work with non-instrumented binaries, or only in dumb mode, which we want to avoid. After starting afl, I noticed that it didn't find any crashes, but only more paths. While afl was running, I spent the time to read a bit in the short manual. There it clearly says "Note that afl-fuzz starts by performing an array of deterministic fuzzing steps, which can take several days, but tend to produce neat test cases. If you want quick & dirty results right away - akin to zzuf and other traditional fuzzers - add the -d option to the command line." So we also need to specify the -d option if we want some fast results. I mentioned in the chat to some people having problems that "afl initially builds trees for several days, but that the manual knows how to fix this". Unfortunately this was completely spoiled later by others, so that everyone was told to use "-d" without thinking of what it is for and why. Anyway, after 20 minutes or so, we have more then enough unique crashes.
afl-fuzz showing 21 unique crashes after 20 minutes
Now let's break afl with Ctrl-C. In the folder findings_dir/crashes you should find the unique crashes with names starting with "id:". Copy any of these files three folders up into the root folder and with the name crashdata.txt. Verify that this input is crashing the calculator.
verifying that the afl-fuzz crash is reproducible
Then start clock with gdb to get more details about the crash:
Replicating the crash in gdb and getting the flag
And here we have our flag. Let's verify that address. I've not done that, but simply tried the address. But as I cannot verify it anymore, we'll see that when we open this up in Hopper (old version v2.8.7 for Windows), we see this code:
Crash location in Hopper
You can see there that this is the memcpy routine and in there the rep movsq command, which does the actual copying. So this seems plausible. It doesn't explain why it crashes though. More information can be found in the Snowman decompilation, but that is out of scope for here and I was too lazy to investigate further.

Killing hashes

Description: "Real hash functions are harder to crack but can be achieved with brute force of your own or someone else's. Can you crack this hash? ef16ab3c539a766ecbe30eb008032e16"
Solution: I didn't want to start setting up hash-cracking rigs for a medium level task, so I started googling this hash value. Unfortunately this could not be found. The only result was a Pastebin entry with some password leak where user iiswahyudi_80@yahoo.com was using this password for that leaked resource (altzona.com) at some point in time, hopefully not now anymore. It's unrelated, but the domain name where this leaked from has just expired a few days ago (26-April-2017).
No Google results for given hash
After some further googling, I found an MD5 database which did have the result:
Hash value lookup site
So there you have it; Bundaita, which is our easy gotten flag.

In-laws of cyber monkeys

Description: "One of our cyber monkeys got a cipher text from his in-laws and cannot read it. Can you crack this ciphertext "dzluin hzuwna bok gwn qibt zd wzkknoqibt"?"
Solution: Now this looks again like another substitution cipher. ROT13 doesn't work and neither of the other ROT values. After some googling, I landed on https://www.guballa.de/substitution-solver, but even with the switch to English it didn't find a correct result.
So I started substitution on pen&paper. First I looked up lists of the most frequent words and then tried around. As this was a lot of work, I decided to look again for some helper tool.
Then I found the page http://substitution.webmasters.sk/simple-substitution-cipher.php, which helps you with your manual work. You can set specific characters to new ones. But after using it a bit, I noticed that it doesn't detect when two characters are set to map to the same character. So it should "unset" the other one. As this was not working as expected, I googled a bit more and found http://quipqiup.com/, an automatic solver that returned the correct result immediatly.
Auto-solver for substitution cipher
Luckily the default setting is "auto". With the setting "statistics" it finds some other interesting and valid sentences. But anyway, here we find our flag.

queenrulez

Description: "Charles's password is queenrulez2000 and the hash value of that password is 'bf078b4812ac9e58b486b8f75ba968ba4f18b502'. After attending Alice's crypto party, Charles changes his password, but keeps the beginning of the password the same and only changes the four numbers in the end to other numbers. The hash value of the new password is '3ede8b7d2e4c4fc26529ba543a6c4414793dc502'."
Solution: For this hashing task, I actually did not want to set up a new Linux environment with a hashing rig. The task says to only test 10'000 passwords. Also, we first had to find out which kind of hash this is. So I created a text file on Windows with the content queenrulez2000 and opened the properties window:
Properties of a text file containing queenrulez2000
So we can see that it's a regular SHA-1 hash. That is HashTab by the way.
Then I wrote a quick&dirty C application that writes 10'000 files with all this content:
Program to write 10'000 files containing queenrulezNNNN
Of course I didn't want to click through the properties of every file. I don't remember which tool I used during the CTF, but Microsoft's FCIV (File Checksum Integrity Verifier) works fine for that:
FCIV Command
Opening this file in Notepad and searching for the hash returns the filename and the correct number.
Finding the right hash in Notepad
Therefore we now know that the correct password is queenrulez5215 and we have our flag.

Forgot the password?

Description: "It just happens that I forgot my password. Can you help me figure it out? The binary file should work in 64-bit Linuxes. http://sec-mooc-1.cs.helsinki.fi/password_2/d61c9826-9914-41cd-94a3-ad68b5872a57/password_checker_2"
Solution: As mentioned earlier for the first password challenge, I simply used Snowman to decompile this first:
Running Snowman to decompile password_checker_2
Opening the generated file in Visual Studio, we see this code:
Decompiled sourcecode of password_checker_2
You can see that the expected password is going through a function b64_decode. At another place you see a typical base64 lookup table. So we have even the function name and we can clearly see a string Q29ycmVjdFBhc3N3cmRBQUFC there. Let's run this through some online base64 decoding tool:
base64 decoding the solution of password_checker_2
I've done this within maybe 20 seconds, but I was still too late for being first. The others probably found it in the hexdump. When I posted my solution, I was third, with maybe one or two seconds too late. This was my only chance. No luck. Anyway, here we have the flag.
It could've been made a bit more difficult by using a custom base64 character order.

Curious cat

Description: "Something is hidden behind the cat. What could it be? Can you help? http://sec-mooc-1.cs.helsinki.fi/curious_cat/5e988c05-5858-479d-ab80-38b745bec57c/cat02.jpg (Editor's note: some people have reported that solving this is not possible on Windows so if you run into problems, consider switching to Linux.)"
This is the one that got me. It took me many many hours to find the solution and I got quite some help to get it solved on the first day, being ready on time for the Hard category.
cat02.jpg from the second steganography task
Solution: Well, first I had a look at the hex editor of course. In there was, like in the first riddle, a comment after the end of the file:
HxD view of cat02.jpg
So we can see the following text: \a{Search deeper. You might need a "passphrase"}\a.
First I guessed that the solution might be "passphrase" or a derivative of that sentence. But I couldn't find anything that worked. I searched for the original cat image and found one, but only in a too low resolution, so I couldn't compare the data. During that first day I thought a lot about what they could have done there. I googled a bit during the day or commute time and found some tricks of putting a .rar file at the end. This was not the case here though. I also ran the cat image against some steganography tools, but they only found "data at the end". When I removed that text after the "FF D9", then nothing was found. Others were having similar problems and mentioned a tool. So I went also through my list of already checked tools. Among them was steghide, but it required a passphrase. That matched the hint, so I was then pretty sure that this was the right tool, but it just didn't work. Therefore I complained loud on the chat channel and among many other things, I told that "passphrase" as password is not working. I actually meant this as flag, but Henrik Nygren from the organizers heard that and confirmed me that "passphrase" is the correct password for the tool. As I told him I was using steghide, he confirmed that it's the right tool and I was "probably just using the wrong parameters". He offered even more help, but I thought with the correct tool and correct password, "what else could go wrong?" and didn't want more help. I verified my parameters and it was indeed not working as intended:
Steghide on Windows is failing
I had one more idea - trying the same on Linux. It took me a while to download Kali and create a VM, but it was worth it:
Steghide on Linux works
So there we have the flag. I told that to Henrik and he added the comment to the task, so that from then on all others knew that it fails on Windows. I bit later (for the cat3 challenge below) I stumbled over the following comment:
Comment that Steghide doesn't work
Well, that explains it. Of course I'm using Windows 10 with 64GB RAM not in 32-bit mode, because 32-bit means a hardware-wise limited to 4GB RAM. Does a Windows 10 in 32-bit even still exist?
After I completed this, someone (who had solved this challenge before me) told me he simply used the web version of steghide. Yeah, too late for me. But that would've worked on Windows of course.
So after completing this one, I quickly did the fuzzing task where I used the just installed Kali environment and then I could upgrade to the higher league of the Hard challenges.

Hard

Too curious cats

Description: "Cats are curious by nature and this cat was more or less curious on his travels. He came back home but he brought something with him. Not ticks but something is hidden in this image. Can you find it? http://sec-mooc-1.cs.helsinki.fi/cat_3/fd8101ef-bfce-4a68-8895-7d8406dc0941/cat03.bmp"
The f***ing cat3

Solution: This is the last of the three Hard challenges I solved. It took me the entire week after solving the Medium challenges on the first day. I started with looking at the hex editor like the two other challenges, but nothing to be found there. Then I started studying the bitmap file format and went through every byte; first the file header with 14 bytes (I'm not going into details here), then the DIB header with all details that I documented, and at 0x36 the image data started. Because the image width was 955 pixel, the height 855 pixel and the bitcount 24 pixel (only one plane), I calculated a total size of 955x855x3 byte (plus 0x36 for the header stuff). But the image was larger. The data after the bitmap data looked unsuspicious and like the other bitmap data. But as it was larger, I took that data and converted that to an image of a width that looked good with the data. Unfortunately nothing special came out there, just some nice shades of black. I concluded that there must be some rounding somewhere, maybe on the line ends, so that the image data is larger. I found out that every line has to be divisible by 4 and our image, with a width of 955 pixels and 3 byte per pixel would be 2865 bytes per row, so not divisible by 4. Therefore we need to add 3 bytes per row. I manually checked the first few rows and these bytes were all zero, but overall, maybe in row 100, there could be data? We have a total of 3x855 or 2565 bytes in there, so maybe something is hiding in there? So I wrote a C# program to print out that data:
C# program to print out line paddings
The values were all hardcoded, customized for cat03, but for such a challenge this is probably ok. Nothing in there though, all bytes were zero. I then found the original cat image on the Internet through a reverse image search. I wanted to compare the data, but unfortunately that was not possible. The original image is a bit bigger, so the resolution would be ok (compared to the cat2 image that was available only in a small resolution), but the original image was a jpg file. I converted that anyway to the exact same size and a bmp file. I then changed my program to calculate the differences:
C# code to calculate image differences
I expected not a 100% match, but something that shows that there is something in the image. I got a grey image with not much in it. When enhancing the differences, it looked like this:
Enhanced cat3 delta (comparing cat3.bmp with original jpg)
You can still clearly see that there is a cat there and you can also see that there are differences in the squares, which probably come from the fact that we're comparing against a jpg, which is handling colors on a square-level. So not much to gain from there.
One online Image Steganography site, which showed graphically the hidden bits in the lowest bit, also indicated that there is something:
Image Steganopgraphy site hinting that there is data in the lowest bit of each pixel
Then I stumbled over the page of guillermito2. This gives a little technical background, especially about hiding data in the lowest bit values. The most interesting part is the Chi-Square analysis, which always detects the hidden data. All the referenced tools were not available anymore though and as I knew there was something in the image, there was not much to gain if I found out that there is actually data there.
So I adapted my program so that it picks up the lowest bit and joins it with the next seven ones to form a byte and then writes that out:
C# code to extract the lowest bit of each image color pixel and write it out to bytes
This got me a big file with a lot of 0xFF values in it, but no text at all. I know from the studying of the header data that the colors are in the order of blue, green, red. So I tried also to read the data in the order RGB and also with the most significant bit coming from the image first, but no luck.
Then someone on the chat channel told me that there is a tool for this. So I started searching for tools.
I found the following lists of steganography tools:
  • EasyBMP (from easybmp.sourceforge): message "not this tool" (so not steganographed with this tool)
  • futureboy.us: "Error. may not contain data or wrong password"
  • Mobilefish: only works with png
  • ImageHide: "BMP file does not seem to contain hidden data"
  • TextToColor (from null-byte.wonderhowto.com): gibberish text file, no flag in it
  • hide.bmp (github/amant): nothing found
  • Xiao Stenography (nakasoft): "does not contain any data"
  • Image Steganography: "image is either corrupted or invalid"
  • steghide: requires passphrase (and only runs in Win32)
  • StgP SteganographXPlus: requires PIN, nothing found
  • rSteg: png only
  • SSuite Picsel: nothing
  • OpenStego: "extracted successfully" but extracted file is empty
  • ImgStegano: crashes
  • QuickStego: "no hidden text"
  • Camouflage: no context menu
  • SilentEye: software n/a
  • OpenPuff: wants passwords
  • OurSecret: software n/a
  • Shussh!: software n/a
  • Steganofile: requires PIN
  • Clotho: "no hidden data found"
  • StegoStick: crash on 64-bit
  • Anubis: doesn't start
  • StegSetup (Dound's Steganography): incompatible software
  • SteganPEG: jpg only
  • SteganographXPlus: software n/a
  • JHide: produces empty file
  • Crypture_2: "invalid password"
  • FIRA2: requires password
  • Shainy: result nothing
  • Hide&Reveal: nothing found in all modes
  • Trojan: "has no data"
  • Protable SteganoG: "no data found"
  • HexaStego-BMP: gets data flag, gibberish in file
  • Steg: "extraction failed"
  • DeEggerEmbedder: "no hidden file"
  • Hallucinate: "not a hallucinated file"
  • Steganography Tools (rRMS, StegoTool, S-Tools): requires key
  • BMPSecrets: site down, tool n/a
  • StegoShare: nothing found
  • DarkCryptTC: add-in for TotalCommander
  • DeepSound: mostly for sound files
  • ImageSpyer G2: installer crashes
  • StegaMail: "no stegamail found"
  • Steganographic Laboratory (VSL): crashes when opening a file
  • Steganography Studio 10.2: nothing found
So I gave up pretty much on using any further tools, as I went through two or three of these lists mentioned above. As most of these tools were for Windows, I also searched for Linux tools and found the list mentioned above for Kali, but it also only contained tools that I already tested.

At this point I was pretty lost and complained loud on the chat channel. Someone mentioned that he solved it on Linux and someone else gave me the hint "this method is almost like tripping on acid". Later in the discussion, others chimed in and mentioned "almost like LSD". So first I googled around there, tried more image enhancing in Photoshop and all that. Finally I felt a bit like this one:
https://s-media-cache-ak0.pinimg.com/originals/e5/8f/6a/e58f6ac90fe249713c8f0111896d295b.gif

As I was told that it was solved on Linux and all the tools I had tried were mainly for Windows, I searched again, but this time Linux steganography tools only and only those that supported bmp files. There were not that many tools around and most of them I tested already. Maybe another tool that sounded similar like another drug? So I googled for other drugs (I'm probably on some wanted list now). I then came across zsteg on github and that sounded interesting, but there was no binary available. The github documentation says to install it with "gem install zsteg", but that crashes with "ERROR: Failed to build gem native extension.".
I am not a Linux guy and I have no idea how to fix this, but I really wanted to try out this tool. So I hacked in random commands from various Stackoverflow pages etc. I ran the following commands:
  • apt-get install ruby-dev zlib1g-dev liblzma-dev
  • gem install rails
  • \curl -L https://get.rvm.io | bash -s stable --ruby
  • source /usr/local/rvm/scripts/rvm
  • rvm get stable --autolibs=enable
  • rvm install ruby-2.3.0 (build fails)
  • gem install zsteg (now it works!)
I have no idea what I have done here. If you do and know the correct way to install that crap, please add a comment.
UPDATE: User NullPointerException pointed out that the correct way to install zsteg is the following single command:
  • gem install rake zsteg
I can confirm that this works on a clean Kali installation.
So I ran zsteg with the "get everything" command and searched for something in the result:
Solution for cat3
And there we have our flag! Finally! It's the value without the $ at the beginning and it was accepted on my first try. This was the hardest challenge of all. Looking closer at the results, it looks like this tool is doing exactly the same as what my initial custom tool was doing; getting the lowest 1 bit (lsb) data in the bgr order in xy order from the file. This is exactly what I was doing as well. I wonder why I didn't get any such data. Do you find any error in my code above?
Now I also know what this other guy meant with "almost like tripping on acid". I already found out that acid=LSD and now I know that that was a hint for lsb, which I pretty much already knew at that time. With this one solved as last one, I can finally relax.
On the last day of the CTF, in the chat it was spoiled that the "data is in the lsb". Compared to the LSD and acid hint I got, this was probably much easier for the late solvers. But actually it was clear from the beginning, that the data is in the lsb.
After the CTF I also chatted with someone who solved this challenge and he told me he found this an 'easy' one. What you can do in images like this one (which are mainly black&white) is to create a yes/no map of all pixels checking if there is any color in it or if they are perfectly grey/black/white. Usually the stego-data is spread across the subpixels of different color, so you would "see" where the data is. Then it's only a question of ordering the data correctly.

Cannot get in

Description: "One of our cyber m0nkeys has forgotten his nix password. He is a fantasy fan so the password is likely a character in either LotR or GoT. That leaves us with roughly 2800 characters with first and last names to try at least and that is if he has not tried to be sneaky with the names. Can you help our monkey? Here is the unshadowed information "cybersecbase:$6$LwmDTb98$dAMmGCkiIakUVtT.bhYujjHGAwCd3un9KdYwfEDdJef/H9Q62mKFpOIA84.W0yDOiXKr4T7Gwpgw2JjD.4yGK.:1000:1000:csb,,,:/home/cybersecbase:/bin/bash""
Solution: This was one of the harder ones, mainly because it gives false clues. First it took me about 1-2 hours to find out what LotR and GoT means. First I thought that was part of the password and the guy added these characters (letters) to his password or something like that. When I googled for these terms some famous movies popped up, which I luckily also had heard of before. Then I made the connection that these two abbreviations were from Lord of the Rings and from Game of Thrones. Later in the chat this was spoiled by others and everyone was talking about it.
Anyway, to start, I manually harvested names from wikipedia and wikia. As I was not sure if character names or actor names were looked for, I collected both. Finally I had around 400 names together and I had no idea how the task creator got to 2800 characters. Anyway, I tried around a lot with John the Ripper. As it was mentioned that something was done to the words, I had to apply some word mangling rules. But JtR was simply too slow in my Kali VM. It didn't use GPU and ran at about 900 hashes/s, which was far too slow. So I tried to run it on Windows, but there JtR is so outdated that it does not support GPU at all. So I turned to hashcat. This was nice and fast, but I also saw comments that there must be far more names available. As I know now, the names on wikipedia do not contain the searched name. GoT comes from a book series, but I'm not sure if the searched name is actually in GoT or from another book. At this point I was pretty lost, so I thought someone real might be a fantasy fan and have used that password before, so I downloaded the 22-billion real passwords list (24GB) and tried all those (unmodified). Actually I tried only those with length 8-40 which are valid for WLAN to speed it up. No luck there either.
Then I found a page http://awoiaf.westeros.org/index.php/List_of_characters, which I parsed half-manually/half-automated into a text list. Then I worked on cleaning up that list manually; where there were three names, I created both variations out of it etc. At the end I had about 2400 names (only characters, no actors). Then I added the characters from LotR from http://lotr.wikia.com/wiki/List_of_the_Lord_of_the_Rings_film_trilogy_characters_and_cast_members and probably from other places too. After creating that list, I had about 2800 names, but it was not what I wanted. Many of the LotR characters have names with accents and umlauts and dashes and whatnot. I don't know what is expected of that in a password. I included it anyway, but I don't even know the switches in hashcat to set the character set to support these names. Also from the GoT list, nearly half of them were not a first name+last name, like the task requested. If we limit ourselves to just first name+last names, I don't know if you will ever reach 2800 names, much less if we limit it to the GoT book and not the entire series.
I also didn't know how this cyber m0nkey mangled with his password and what casing he was using and if there was a space or something else between the names. So I took just all the names, copied them with and without the space inbetween, converted them to all lowercase, all uppercase and all reversed case (and original, first letter in upper case). That left me with 21'100 names. That had to be mangled with somehow. I tried all the default rulesets, especially the l33t rules with no luck. Then I tried the bigger rulesets and among them the d3ad0ne.rule ruleset, which finally worked.
successful hashcat command
I left this running over night and went to bed at 3am. Luckily I found a nice surprise the next morning after having run for 1.5 hours or so:
hashcat successful running result
Luckily I had a GTX1080 graphics card helping me to get to 111'100 hashes/s. But yes, this finally worked. I didn't like this challenge, because it was not very technical. At least I got some experience with JtR and hashcat, which is good.

Cracking the lost password

Description: "Can you figure out the password? The binary file should work in 64-bit Linuxes. http://sec-mooc-1.cs.helsinki.fi/password_3/ac964116-534f-488c-8cbe-3c4326d5b6d1/password_3"
Solution: When this solution was released, I thought I might be lucky and get my name in there first. I immediately ran it against Snowman, like the other two password binaries, but the result was an empty decompilation file. When I opened it with Hopper, Hopper crashed immediately. And IDA Pro demo complained that it is a 64-bit binary which is not supported in the demo version. Looking at the hex dump also didn't reveal much. It looked like encrypted or something, although some texts were visible, like "enter password" or something like that. So I started with gdb. I never really used gdb before, so it was a good idea to start with that. I also have no experience with Linux systems, so that was all new to me. Funny to see that others have solved that within a few minutes after release though. Anyway, I first had to find out how to set a breakpoint with gdb at the first instruction, when there are no symbols. StackExchange and other places helped me there.
I ran the following commands:
  • gdb password_3
  • break *0 (somehow sets a breakpoint at the start)
  • r (runs from start until breakpoint)
  • layout asm (shows current code in a nice layout)
  • delete 1 (delete initial breakpoint)
  • break *0x400d34
  • stepi (until 0x800b50)
  • break *0x800be3
  • etc.
So I learned my way through gdb. At the beginning there is a syscall to sys_mmap, allocating memory at 0x800000 and then copying some code there and the execution continues there. That's probably why Hopper failed. When it jumped back, I had a look at the data in memory. I wasn't able to dump the code from there, but I hoped that I could now see the password in clear-text somewhere in memory. Instead of that I stumbled over some text entries with the name "UPX". I remembered that from others when talking about reverse engineering malware. UPX is a packer. So I thought I could maybe unpack this binary somehow. I started searching for UPX unpacker software until I finally found out that this is preinstalled in Kali.
Solution for password_3
There is the flag. So finally this one solved too. This was the first of the hard ones that I solved.

Comments

  1. Very nice work! I like this write up and got to know some new tools, and got new points of view. Thank you for that. I allso would like to know of there is correct way to install zsteg. :)

    ReplyDelete

Post a Comment

Popular posts from this blog

Capture The Flag Challenges from Cyber Security Base with F-Secure 2017/2018

Insomni'hack Teaser 2018 CTF