Capture the flag (CTF)

Solutions to net-force cryptography CTF challenges

Pranshu Bajpai
April 9, 2015 by
Pranshu Bajpai

Cryptanalysis refers to the study of ciphers with the objective of breaking the code and obtaining plaintext (sensible) information. While older cryptosystems such as Caesar cipher depended on the secrecy of the encrypting algorithm itself, modern cryptosystems assume adversarial knowledge of algorithm and the cryptosystem. The promise of secrecy is offered by a protected key, which is crucial for the decryption of ciphertext within a practical timeframe. During cryptanalysis, we do not have the key and are required to obtain the corresponding plaintext.

In the challenges below, we focus on discovering patterns in the ciphertext to comprehend how encryption transpired. Unlike hashing, encryption is not a one-way process, so we can reverse it to obtain the plaintext. Brute force is the last choice during cryptanalysis, since modern ciphers can have extremely large key sizes. While solving these challenges, you should refrain from mindless brute forcing or using automated tools as far as possible. Instead, it is best to study the cryptosystem as intricately as possible and develop code breaking skills along the way.

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.

About net-force cryptography challenges

These challenges require that you locate passwords concealed in the ciphertexts provided. The CTF challenges are arranged in order of increasing complexity, and you can attempt them in any order. Each challenge depends on a variety of cryptographic techniques and requires logical thinking to arrive at a solution.

Spoiler Alert!!

Please be advised that the following content provides solutions to the intriguing cryptographic challenges on Net-Force. It would be unavailing to read further without having tried your absolute best at the challenges first.

Solutions to cryptographic challenges 1 to 8

Cryptography challenge 1, level 301: "Crypto basics"

This first challenge is a starter challenge to get us acquainted with the concept of cryptography and cryptanalysis and is hence very straight forward. We are provided a string of characters that we need to decrypt to obtain the plaintext message [Figure 1].

Figure 1

If you are familiar with base64 encode text, the trailing '=' signs are a dead giveaway that the string requires base64 decoding. To base64 decode this string in Linux, we use the 'base64' utility [Figure 2]:

Figure 2

After base64 decoding, we still have a ciphertext that appears to be the result of a simple rotation cipher. We wrote a small Python script that brute forced the rotations for us until we could read plaintext. Alternatively, you could use one of the online rotation cipher decryption tools to get the plaintext [Figure 3].

Figure 3

Note: A frequently asked question that students have about base64 encoded text is: does it always end with an '=' sign? The answer is 'No'. An '=' sign is used as padding to ensure that the resulting base64 encoded string is of optimum length. However if it is already of proper length, then no padding is required and you would not see an '=' sign at the end of it. Thus, do not depend on identifying base64 encoded strings on the basis of trailing '=' signs.

Password: crypto

Cryptography challenge 2, level 302: "Substitution...."

This next challenge will be a little confusing to people who do not speak Dutch, as the resulting "plaintext" would be in Dutch. The title suggests that it is a simple substitution cipher which becomes easy to solve with a known plaintext attack.

Figure 4

In the beginning, while mapping ciphertext to given plaintext, we know 5 substitutions: "o": "l", "g": "e", "r": "u", "t": "z", and "z": "t". We write a small Python dictionary that makes these substitutions in the ciphertext, and we now have partial plaintext [Figure 5].

Figure 5

From here on we depend on locating patterns and adding new mappings as we learn them. For example, the last word could be 'netforce', which would mean that we need to map: "d":"f", "l":"o", "u":"r", and "a":"c".

Now, a pattern emerges. We notice that if 'r' is mapped to 'u', then 'u' would be mapped to 'r'. Using this knowledge, we can make further substitutions until we obtain the plaintext Dutch message [Figure 6].

Figure 6

This Python script is available at GitHub.

Google translate then shows us a rough translation of this Dutch message:

"nice huh `s substitution cipher me password for the challenge page netforce"

Password: netforce

Cryptography challenge 3, level 307: "Sea Code"

This code should be familiar to most if not all. The dots and dashes are a dead giveaway that this is Morse code. If there was any doubt, the title 'sea code' confirms this. You can decode this Morse code manually or use one of the online Morse code decoders.

After decoding, the resulting plaintext is: THEPASSWORDFORTHISLEVELISWELLDONE

Password: welldone

Cryptography challenge 4, level 305: "XOR crypt"

This challenge presents us 2 long binary sequences and asks us to combine them, while the title of the challenge says 'XOR' [Figure 7].

Figure 7

It becomes clear that we are required to perform bitwise XOR on these 2 binary sequences. We combine these using bitwise XOR and convert the resulting binary sequence into ASCII to obtain the plaintext using a Python script [Figure 8].

Figure 8

This Python script is available at Github.

Password: bin

Cryptography challenge 5, level 304: "Check out the tables...."

This challenge presents us with partially comprehensible ciphertext. If you have some knowledge of cryptography, the title's reference to 'tables' should indicate that this is some form of a transposition cipher.

Figure 9

In a transposition cipher, you rearrange the characters instead of making substitutions as in the case of a substitution cipher. We begin by locating what is possibly the starting point of the plaintext sentence, 'thisisatra', and move on from there. Shortly, the order of transposition becomes obvious and we have the decrypted plaintext [Figure 10].

Figure 10

Password: columns

Cryptography challenge 6, level 308: "Viva la France"

This challenge is asking us to perform a known plaintext attack since a piece of ciphertext and corresponding plaintext is provided to us. After close inspection of both, we notice that while at first 't' was mapped to 'v', later in the string 't' was mapped to 'r' [Figure 11]. This suggests that we are dealing with a polyalphabetic cipher—most likely a Vigenère cipher.

Figure 11

It is possible to obtain the key based on a known plaintext attack using programming. Here, we use a Vigenère cipher analyzer online that revealed the key instantly with the known plaintext [Figure 12].

Figure 12

The key used was 'cryptoguy'. Looking at this Vigenère tablet, we can see how plaintext characters were mapped to ciphertext using the characters in the key. For example, Figure 13 shows how the first plaintext character 't' was mapped to a 'v' using the first letter in the key, that is, 'c'. Please note that the Vigenère key repeats itself during the encryption process.

Figure 13

Note: The Vigenère cipher is a popular and simple example of a polyalphabetic cipher. Hence, after noticing the polyalphabetic cipher, Vigenère should be our first guess regarding the encryption algorithm. Also note that the title mentions France. This is actually a hint, since the Vigenère cipher was given by a Frenchman, Blaise de Vigenère.

Password: cryptoguy

Cryptography challenge 7, level 303: "SUPER cipher"

This next challenge presents us with a string to decrypt, and this ciphertext string contains some numbers as well. At first glance, all the preserved spaces and word lengths suggest that this is another substitution cipher.

Figure 14

Our first clue to the challenge was observing a pattern in the ciphertext that was similar to the patterns encountered before in the plaintexts of other challenges. The decrypted plaintext string in challenges usually says something like: "the password to the challenge page is ******". Observing the ciphertext, it is highly probable that the 1st word is 'the' (which would mean that the 4th word is also 'the'), the 2nd word is 'password', and the 5th word is 'challenge'. The fact that the ciphertext repeats characters just like the possible plaintext suggests that this is a monoalphabetic substitution cipher. For example, the probable plaintext word 'password' contains 2 's's, and the corresponding ciphertext word 'q5tt/>/>lse' contains 2 't's, and at the right spot. This means we can map 't' to 's' during decryption. Similarly, we can form associations for other characters in the plaintext and the ciphertext. From these associations, we were able to obtain partial plaintext [Figure 15].

Figure 15

After observation, it is obvious that 'i' has been mapped to '2'. Hence, the plaintext we know so far becomes: "the password for the challenge site is: el**e".

The possible password could be 'elite', which would make sense. However, the challenge site rejected this password. This required further evaluation of ciphertext, which revealed another pattern. The pattern has something to do with 'leetspeak'. The leetspeak for 't' is '7', 7 incremented by 1 is 8, which is the ciphertext character. Similarly, leetspeak for 'i' is '1', 1 incremented by 1 is 2, which is the ciphertext character. Knowing that leetspeak is involved in the encryption, we arrive at '3lit3', which is the correct password.

Password: 3lit3

Cryptography challenge 8, level 306: "DECrypt challenge"

This challenge presents us with a long string of numbers that we are required to decrypt. The hint in the title (DEC) suggests that this has something to do with decimals. A close inspection of the ciphertext reveals a pattern of '909' repeating within the string [Figure 16].

Figure 16

After numerous attempts, we were not able to associate a meaning with '909' in context of the ciphertext. Consequently, we decided to remove it from the ciphertext. We used Python's replace function to remove all occurrences of '909' from the ciphertext. We were left with:


Using the hint given in the title, decimal, we treated this sequence as a string of decimals. To do this, we used Python's strip function to remove all '909' and store the resulting decimals in a list. Now, we have:

['84', '104', '101', '112', '97', '115', '115', '119', '111', '114', '100', '105', '115', '100', '101', '99', '99', '111', '110', '118', '101', '114', '116']

Next, after converting these decimals to corresponding ASCII characters using the chr function in Python, we had the plaintext message [Figure 17].

Figure 17

This Python script is available at Github.

Password: decconvert


After being dormant for some time, the Net-Force community is accepting new members again and is under new management. These cryptographic challenges at Net-Force were well thought out and intriguing. If you are new to cryptanalysis, these exercises put you on a rapid learning curve with challenges that increase in complexity as you move forward.

Cryptanalysis is a process of trial-and-error, and normally it would take several attempts before you comprehend patterns in complex challenges. The solutions above discuss only successful attempts for the sake of brevity. If you enjoyed these, consider attempting more captivating challenges at Net-Force to test or build your skills in security.

What should you learn next?

What should you learn next?

From SOC Analyst to Secure Coder to Security Manager — our team of experts has 12 free training plans to help you hit your goals. Get your free copy now.


Pranshu Bajpai
Pranshu Bajpai

Pranshu Bajpai (MBA, MS) is a researcher with a wide range of interests. He

has authored several papers in international journals and has been

consistently hired by top organizations to create technical content. He has

been a technical reviewer for several books. Currently, he also does

independent research for InfoSec Institute. In his free time, he enjoys

listening to classic rock while blogging at

You can contact him at bajpai [dot] pranshu [at] gmail [dot] com or