CIC invited all undergraduate Computer Science, Software Engineering and Information Technology Students across Canada to participate in a CTF online competition qualifier for a final online contest in August where the top 3 finalists will receive a full stipend for a Master of Applied Cybersecurity (MACSec) at CIC/UNB..

June 29 2019

CIC CTF 2019

This was an interesting little qualifying round CTF – not too hard, not too soft. There were some flag formatting issues, and one challenge that seemed to be a bit broken, but otherwise enough to occupy me for the 8 hours allotted.

{(Find)[thePassword]} (client side, password)

Enter the password to get the flag

The challenge page just has a pop-up prompt saying “Enter the passcode!”, and I cannot open the web inspector in Safari as the page is not fully loaded. Let’s see what it looks like in Burp…not much different.

In opening Burp, however, I switched to Firefox and there the debugger does open to reveal a script:

<script language="JavaScript" type="text/javascript">
var secret;
secret=prompt('Enter the passcode!')
eval(eval('([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]…[this goes on for several pages] []+!+[]]+([][[]]+[])[!+[]+!+[]])'));

OK, so there’s no plain-text password string buried in the pages of brackets, and the function should evaluate this mess. The eval function should evaluate a string as a JS expression, and it’s vulnerable to injection attacks. First, let’s run the inside eval in the console, and we get:

"if(secret == 'keepgoing'){window.location.href= secret+'.html';}"

Using “keepgoing” as the passcode, we are redirected to /keepgoing.html and the flag:


What are they hiding? (steganography)

The picture below has been retreived from a secret communication. We beleive the should be a secret message hidden inside of it, maybe a location or something. But we are not sure. Can you help us figure out what is the secret message?

SHA1: c7add836b233ab2d6465fca1e6c4e18efd9cd0c4

The SHA1 hash of my download matches the provided hash, so that’s good. There’s nothing obvious in the image itself, and nothing interesting comes out of looking at the EXIF metadata. Opening the image in Hex Fiend, we can see a standard 8950 PNG header, and the file contains no 504B 0304 PKZip headers.

Pngcheck comes out clean – it’s a 1024x768 24-bit RGB non-iterlaced image)

Strings was tedious and fruitless, so it’s a good thing I started stegoVeritas running while I reviewed the output. Across several different LSB outputs, we get the flag:


Qr Code!

We have retrieved these pieces of a qr code in an investigation. But it seems some of the pieces are missing. Also, we don't know their correct orientation. (They might be rotated.)
Could you help us figure are what is the hidden message inside this qr code?

SHA1: 2932cba5be9db354bfc9f78bbe79890510da1e96

OK. So, we have an incomplete and jumbled set of QR code chunks. I started by printing the image off, cutting out the pieces and playing with them until I got some sense of their fit. I used http://qr.biz/articles/the_structure_of_qr_code/ to get a sense of the required structure for a QR code.

The nice thing is that the missing pieces are those large corner squares, and the chunks run over the edge of the next piece. The edge bits on the current big square piece tell us that there is minimally a standard line thickness of code at those black bits on the corners. The little square goes in the bottom right corner and there will be a repeating black white row connecting the big squares to one that ultimately ends up in the upper left corner.

So, I figured out how the non-squares pieces fit on paper, copied the image into GIMP, cut the pieces and added them as layers on blank canvas, duplicated the big square twice, fit everything togher, cleaned up the edges where there extra or missing black on the duplicates (as indicated by their neighbours’ black edges) and duplicated the repeat (timing pattern) row to get the following:

Scanning the code with my phone, we get the flag:


Exploit the code! (PHP, source code, exploit)

Find the flag through code exploitation.

The page just consists of:

The flag is just here Try to get the flag :)
Look at the source code!

Looking at the source code:


if(preg_match("/[_]+/", $_GET["flag"]))
die('Try Again :(');
echo "Flag_is:{***********}";
die('Try Again :(');

We can see that it is getting the flag variable in a GET request, which corresponds to the other link

That flag variable gets URL decoded and compared in the second if statement. The only problem is that the first if statement also takes the contents of the URL parameter and if it contains any underscores, the PHP fails out before we get to the second if.

Replacing the underscores with %5F, the URL encoded version, we get the Try Again response.

Testing some different character encoding strategies, we find that these don’t work either:

Unicode U+0005F, U+005F, U+0332, U+FF3F
HEX CODE & #x5f ;
HTML CODE & #95 ;
HTML ENTITY & lowbar ;

Perhaps the whole string needs to be URL encoded:


Nope. Ah…the problem is also that $_GET is decoded automatically. So, perhaps we have to URL encode the already URL encoded text.


That got it!


PDF Forensics (forensics PDF)

Find the hidden Flag! Should be solved in Windows.

Opening the file just gives us the text “Try to see it!”. Looking at the file in Hex Fiend, we can see that there is content after the %%EOF end-of-file marker. Deleting that section and saving the file, we can re-open the file to see the flag: Flag I{ncremental Update}s

With a little reformatting to match previous flags (except for the uppercase F), we get:

Flag{Incremental Updates}

Let’s decode! (cypher encryption)

Just for warming up, let's try to decrypt a simple substitution cipher! Except it's not that simple!
This is an ASCII to ASCII substitution cipher. It means the alphabet is the whole ASCII space (0x00 .. 0x7F). Fortunately, both the message and the cipher just contain printable characters (not control characters).
However, the cipher (or in other words, the message) is case sensitive, and also contains a limited set of punctuations.
The space character is also a part of the alphabet, meaning the space caracter in cipher text is different from space character in the plain text.
All right! Let's get to work!
(Copy and paste the message below into a text editor and start analyzing it!)


OK. Let’s start by replaing the spaces with _ just to keep them straight, since they aren’t real spaces.


From the look of the frequency and placement of E, it’s likely the real space character


The T appears in a trio and ends the cypher, so it’s likely a period


The words we have so far are:


After a bit of playing with likely substitutions, I hypothesised that the opening three words were actually “Lorem ipsum dolor”. A few more logical substitutions to finish off words like “your”, “this”, and “but” and “Congratulations” became a clear enough word to recognise and complete. Finishing off the remaining obvious substitutions, we get:

Lorem ipsum dolor... Congratulations! You decoded this message! Good job! This is your flag{?e?SY buT fun!} Some more gibberish text! Just ignore them.

Giving us a flag that looks something like:

Flag{?eaSY buT fun!} or flag{?eiSY buT fun!}

There is a problem in that the cipher-text “I” could be “a” or “i”. For example, 3YO1PIFGRIFIYOJD is Congratulations, but looking at the section that should decode to “ati”, we have “IFI”.

And the first character in the cipher-text flag is “S” which appears nowhere else in the cypher text. With the ambiguous a/i and the missing character, we’re left with 76 possible combinations of a character that doesn’t appear elsewhere in the text (assuming this one doesn’t repeat a previous character!) and a or i. Since the system doesn’t accept submissions more frequently than 1 per minute, and I reached this point with about 10 minutes left in the competition, this is as far as I got.

APK Forensics (forensics APK Android)

Only the authorized person can see the flag!

This was my first APK challenge, and really my first look at an Android app at all. I started by decoding the file with apktool, got the file unpacked, and started to look through them, but found nothing before running out of time on the competition.

SQLInjection (SQL Injection, login form, table name)

As an admin user you can find the flag hidden in the table name.

The page contains a username field, password field, and login button, and the following:

Limitation: Allowed to send one login request per second! If you try to send more requests in one second, they would be blocked!!!
Hint: The Table name's characters are in {a-z_} and it starts with "tiny".

Entering just ‘ in the username provokes the reponse “Required Fields” Entering admin as the username and ‘ as the password returns “Not True!”, as did a range of variations on ‘ OR ’1=1 # and ‘ OR ’1=1 --. And I ran out of time before being able to try much else.


Score: 900-1100/1800
Rank: ?? (not top 20)