~$ Dissecting the KnightCTF Cryptography challenges!
Posted on Jan. 30th, 2022.
Alphabet Knock Code (100 points)
The challenge provided a file called
knock.txt, which contained the following text:
The description for the challenge was the following:
My friend send me this file and told me that C=K, Y=Z and the total number is 24. But I can not understand this. Can you help me?
From the C=K bit, we can extrapolate that this is a variation on the Tap Code, which is a code that is alleged to have been used by prisoners in order to communicate with one another.
The normal tap code works in a 5-by-5 grid like such:
The key to interpreting this cipher is not in the individual taps, but in the pairs of taps: the first set of taps specifies the line of the table, and the second set defines the column of the table, which together point to a letter.
That's all fine and dandy, but we're told the total number is 24, and not 25 like in the 5-by-5 grid. As such we look at the multipliers that make up 24: 2-by-12, 3-by-8 and 4-by-6 (and their transpose matrices).
To get a better idea, we can look at the amount of dots that we have in the provided ciphertext: The first set goes from 1 to 4, the second goes from 1 to 6.
This means we're dealing with a matrix with 4 lines and 6 columns, with two equivalencies (C=K and Y=Z):
From there we are able to split the message into (row, column) pairs:
By transposing the pairs with the values in our matrix, we get:
This spells out
se(c|k)reu(c|k)nighu. This... doesn't make much sense, but we can already guess the result as being secretknight. There must have been an issue with the encryption script.
The final flag was:
Feistival (150 points)
The challenge provided a file called
cipher.txt, which contained the following text:
It also provided a Python file called
enc.py which contained the following script:
Finally, the description for the challenge was the following:
My friend Ridwan is interested into ciphers lately. He sent me the encrypted flag. Can you help me decrypt?
Before launching ourselves in the reversal / decryption process, let us decompose some of the code:
- Line 2 provides us with a function which takes as input a string of characters (
word) and a secondary value (
This function will take the word, convert each character to its ASCII value, XOR that value with the key, then convert it back into ASCII letters.
This is the Feistel operation
- Line 8 opens up the ciphertext and extracts the encrypted flag from within.
- Line 10 splits the flag in 2 distinct parts L and R.
- Line 11 performs the Feistel operation on R, then XORs each of the characters of the result with the value at the same index in L.
- Line 12 performs the Feistel operation on R with value 0.
- Line 14 flips switches L and R, and the next two lines repeats step 4.
- The new flag is written to a new file.
This is in the Cryptography category because it deals with a Feistel Cipher, but it also has a lot to do with programming. We createt
dec.py to perform the opposite operations on the provided ciphertext:
The main takeaway is that the operations in lines 13 to 19 are simply in the reverse order than the original encryption code.
The flag - found in
plain.txt - is:
RSA-One (100 points)
The challenge provided
private.pem, a private key, which looked like this (although some of it is omitted for brevity):
It also provided
flag.enc, the encrypted flag.
My approach to this challenge was to bruteforce all the possible certs that could be generated:
We then attempt to produce a decoded file:
This command lists all the files named
private-[letter].pem, and executes a command to retrieve the new symbol from the file name, then using openssl's rsautl tool to decrypt the file and output it to another. The main idea is that the file that successfully gets decrypted will be of a different size.
We can then use
find ./ -size 0 -print -delete to delete all empty files leaving
decoded-private-a.pem which contains the flag: