PicoCTF 2018, part 1 through 10


After the previous CTF challenge (Infosec Institute n00bs CTF Labs) I felt like doing another. I came across PicoCTF 2018, and this one had a much more sophisticated system and way more challenges. The CTF part is still intermediate level, however I felt like that would suit my experience with these challenges.

To me, it was important that I could apply my programming and reversing skills in challenges, and possibly learn a few things more. I'm a software engineer and Linux fan-boy, which has been my focus for most of my life. I have used my engineering skills many times trying to secure things, but I want to understand common security flaws more; hence the CTF challenges.

This post enlists the write-ups for problems 1 through 10 - more will follow. After a while, the posts will become smaller as the write-ups become more substantial. View the related posts below for more parts of this series.

Forensics Warmup 150 points

This one is a very easy start, I believe it introduces you to how flags are formatted. The hints and description almost completely tell you what to do; download a zip file and unzip it. You will find a JPEG with the flag in a very colorful display.

flag: picoCTF{welcome_to_forensics}

Forensics Warmup 250 points

Another very easy one. The challenge description tells you that the PNG cannot be opened, and in the hints you'll find a question related a utility to detect a file's actual type (disregarding the extension). Nontheless, I downloaded the file and my code editor (Atom) properly displays it, as it does not rely on image file extension.

Anyhow, for completeness I used the file flag.png command line and see that it is in fact a JPEG, not a PNG. I rename flag.png to flag.jpg, but that's just for the sake of doing the assignment.

flag: picoCTF{extensions_are_a_lie}

General Warmup 150 points

This one is even easier than the previous one, but I've seen a tonne of hexadecimal data in my day. The challenge description contains the answer, and I recognize the letter that's represented in hexadecimal 0x41:

If I told you your grade was 0x41 in hexadecimal, what would it be in ASCII?

0x41 in hexadecimal is 65 in decimal, which is the ASCII character code for A.

flag: picoCTF{A}

General Warmup 250 points

This is a slow start. I'm new to the CTF challenges world, but in my honest opinion these first warmup assignments are a bit too easy. I think the n00bs CTF by Infosec Institute was a bit more suiting, even though it was for beginners as well. As for this challenge, converting a decimal number to binary is trivial.

Can you convert the number 27 (base 10) to binary (base 2)?

In Python, this would only take a print(bin(27)), but when approached directly you simply set the bit for 16, 8, 2 and 1. This results in 11011

flag: picoCTF{11011}

General Warmup 350 points

A very similar challenge to the previous one, but now we convert a hexadecimal number to decimal.

What is 0x3D (base 16) in decimal (base 10).


flag: picoCTF{61}

Resources50 points

The resources page they link in the description contains the flag.

We put together a bunch of resources to help you out on our website! If you go over there, you might even find a flag! https://picoctf.com/resources

flag: picoCTF{xiexie_ni_lai_zheli}

Reversing Warmup 150 points

This one is interesting, but I'll get to that. First and foremost, the challenge is again quite trivial. Login to a shell and execute a command.

Throughout your journey you will have to run many programs. Can you navigate to /problems/reversing-warmup-1_2_a237211c4be8902c67102f827027e633 on the shell server and run this program to retreive the flag?

Which is quite easy, because you can simply run the program they ask you to run and you are presented the next flag. I found that the shell on their website was extremely slow though, so I decided to try and connect to that server (it is mentioned above) through SSH. We actually found another flag when we did, for a future challenge I bet, so I thought it would be safe to store that flag as well in case it only shows it once: future flag: picoCTF{who_n33ds_p4ssw0rds_38dj21}

Anyhow, upon executing the command we get the flag for this challenge too!

flag: picoCTF{welc0m3_t0_r3VeRs1nG}

Reversing Warmup 250 points

A standard base64 decode assignment, use any tool you like to decode the input they provide.

Can you decode the following string dGg0dF93NHNfczFtcEwz from base64 format to ASCII?

For this, I like using Python, but an online decode website is probably quicker.

import base64

print(str(base64.standard_b64decode("dGg0dF93NHNfczFtcEwz"), "utf-8"))

flag: picoCTF{th4t_w4s_s1mpL3}

Crypto Warmup 175 points

This challenge asks you to decrypt a ciphertext to plaintext, by using a "truth table".

Crpyto can often be done by hand, here's a message you got from a friend, llkjmlmpadkkc with the key of thisisalilkey. Can you use this table to solve it?.

This tabula reminds me of the Vigenère Cipher, and I don't like doing things by hand. This is why I used code from this gist to decrypt the message, which shows us that the flag is 'SECRETMESSAGE'.

# https://gist.github.com/dssstr/aedbb5e9f2185f366c6d6b50fad3e4a4
def decrypt(ciphertext, key):
    key_length = len(key)
    key_as_int = [ord(i) for i in key]
    ciphertext_int = [ord(i) for i in ciphertext]
    plaintext = ''
    for i in range(len(ciphertext_int)):
        value = (ciphertext_int[i] - key_as_int[i % key_length]) % 26
        plaintext += chr(value + 0x41) # or 0x61 for lower case 
    return plaintext

print(decrypt("llkjmlmpadkkc", "thisisalilkey"))


Crypto Warmup 275 points

This challenge asks you to decode a rot13 encoded string, which is something I have seen in the Infosec Institute's n00bs CTF as well.

Cryptography doesn't have to be complicated, have you ever heard of something called rot13? cvpbPGS{guvf_vf_pelcgb!}

This can be solved by defining a translation between rot13 and plaintext. This definition is commonly available, but can be precalculated as well. If you don't want to use a translation, you can simply rotate the values manually - but I prefer the lookup dictionary.

# The rot13 encoded data
content = "cvpbPGS{guvf_vf_pelcgb!}"

# Define a translation dictionary from one rot definition to another
def maketrans_compat(source, destination):
    assert len(source) == len(destination), "length of data not equal"
    return dict(zip(list(source), list(destination)))

# Translate input to a new string based on the contents of the trans dictionary
def translate(input, trans):
    return ''.join(map(lambda c: trans[c] if c in trans else c, input))

rot13 = maketrans_compat(

# Translate and display
print(translate(content, rot13))

flag: picoCTF{this_is_crypto!}

Related articles