Crypto Conspiracy | Part 1 | PicoCTF

Hussain
7 min readJul 20, 2022

--

I am starting a cryptography blog series, where I will undergo various challenges from different CTFs and learning platforms, providing write ups and resources which help me progress further and build concepts.

Part 1 will showcase PicoCTF and its first few cryptography challenges.

1. Mod 26

This is a very simple challenge, where each alphabet of the flag is rotated 13 letter after itself. It’s type of a substitution cipher. You can read further here.

The same algorithm is applied for both encoding and decoding. Online tools like cyberchef have the algorithm built-in, so slapping the encoded flag and selecting rot-13 will give us the flag.

We can even write a simple python script to generate the flag.

Flag: picoCTF{next_time_I’ll_try_2_rounds_of_rot13_wqWOSBKW}

2. Mind your Ps and Qs

This is a RSA challenge, where a text file is provided with the three integer values. e is the public encryption exponent, n is the product of two prime numbers; p and q (n=p*q),which are kept secret, and are ideally very large. c is the encrypted ciphertext.

Decrypt my super sick RSA: c: 964354128913912393938480857590969826308054462950561875638492039363373779803642185 n: 1584586296183412107468474423529992275940096154074798537916936609523894209759157543 e: 65537

The public key consists of modulus n and the public encryption exponent e. (e,n)

In this challenge, the modulus n is very small. The two prime factors can be easily guessed using factordb.

The values are as follows:

p: 2434792384523484381583634042478415057961  
q: 650809615742055581459820253356987396346063

Once we have the values of p and q, which can be used to calculate the value of d. It is called the private key exponent used to decrypt the cipher text.

The private key consists of modulus n and the public encryption exponent d. (d,n)

I won’t cover the math operations, you can get the overview of it from here and here.

Every character of the plain text is first encoded into hexadecimal, then converted into decimal format. The decimal number is then encrypted using the RSA algorithm.

We can write an algorithm to decrypt and then decode the text into plain text, which is our flag.

m is the decrypted number which is then converted into the plain text.

Running the script gives out our flag.

Flag: picoCTF{sma11_N_n0_g0od_73918962}

3. Easy Peasy

The challenge provides a file *otp.py*, running on the remote server. The DOAMIN and PORT of the server can be used to connect and communicate with the program.

Lets analyse the given code:

The first few lines assign the file name to the variable to use later in the program for reading its contents. The length of the contents inside the KEY_FILE file is 50000.

The program starts by calling the startup() function passing 0 as its parameter. The function first reads the content of both the flag and key file.

The length of the flag is calculated, which is then used to extract the key of the same length from the KEY_FILE. There is a variable key_location which stores the last position till the key content is used.

XOR operation is applied between the both flag and key. The values are mapped and the operation is applied using the map() built-in function. The calculated value is in hex. {:x} is a Hex format, lower case format type. Read more about format types here.

The encrypted flag is printed out, and returns the key_location value.

Next, a while loop, with the condition True, if c(key_location) is greater or equal to 0. Under, it calls the function encrypt() passing the c parameter.

The function then asks for the input to encrypt. It then repeats what the last function does. XOR operation between the input value and the key extracted from the KEY_FILE after the key_location(c). The length is the same as the input length. Value of key_location is updated and returned as c. The encrypted text prints out.

Connecting to the server gave us the encrypted flag.

encrypted_flag = 0x0345376e1e5406691d5c076c4050046e4000036a1a005c6b1904531d3941055d

The length of the encrypted flag is 64, which means the plain flag length is 32.

The value of the key_location after the flag supplied is 32, so 49968 more bytes till the starting contents can be used.

python3 -c "print('A'*49968);print('A'*32)" | nc mercury.picoctf.net 41934

We get past all unnecessary key bytes and get the encrypted A’s, which are XOR’d by the same key value which encrypted our flag.

encrypted_As = 2366101d3922231d3979201d3923751d3971751d3927791d3971713a1d392525

Now we can use the inverse XOR method to calculate our key, which can help decrypt the flag.

XOR is used to inverse the XOR. If you have a problem like this:

a = b XOR c; where c and a is known

One can use the XOR operation between a and c to get b.

b = a XOR c

The same is the case here. We know plain_As and encrypted_As, which can help us to figure out the key.

encrypted_As = key XOR plain_As
key = encrypted_As XOR plain_As

Once we have the key, we can use it to XOR the encrypted_flag to find the plain_flag.

plain_flag = key XOR encrypted_flag

You can read more about it here.

Python script to automate it all:

Flag: picoCTF{abf2f7d5edf082028076bfd7a4cfe9a9}

4. The Numbers

The challenge contains a downloadable image.

The images shows the numbers aligned together in a flag format. It is substitution cipher bases on letter number, where A=1, B=2,….Z=26.

16 9 3 15 3 20 6 == PICOCTF
20 8 5 14 21 13 2 5 18 19 13 1 19 15 14 == THENUMBERSMASON

Script:

Flag: picoctf{thenumbersmason}

5. New Caesar

The challenge provides a file *new_ceasar.py* and the encrypted flag.

encrypted_flag = ihjghbjgjhfbhbfcfjflfjiifdfgffihfeigidfligigffihfjfhfhfhigfjfffjfeihihfdieieih

Lets analyse the given code:

The above code confirms that the length of the key is 1, and the value is the character from the first 16 characters of the alphabets.

The function b16_encode() is called with flag as the parameter. It converts each character into ascii decimal value, then encode it to 8 bit binary format.

The binary is divided into two, both octets gets decoded into integer separately. The integer value is used as the index of the ALPHABET. All the characters are concatenated together and returned as the encoded string.

A script to reverse the above function can be created.

Lets get further.

enumerate() method adds a counter to an iterable and returns it in a form of enumerating object. Read more about it here.

The second parameter of the shift() function is always that character key.

The shift() function basically just rotates the character in c. The number of rotation depends on the index number of the key character in the ALPHABET list.

To undo the shift, we can rotate the cipher character the same way, but in negative direction.

Writing a script with both of the functions will get us the flag.

Brute forcing the flag with all possible 16 key possibilities.

Flag: picoCTF{et_tu?_0797f143e2da9dd3e7555d7372ee1bbe}

--

--