macsh (Cryptography)

‘macsh’ ( Cryptography from Plaid-CTF )

Here we are given two python scripts, macsh.py and fmac.py

This is the snapshot from the macsh.py file

plaid_ctf_writeup1

  • This python script is the main file which has to be analysed first.
  • As we can see there, this file allows us to perform the basic operations in a unix based machine like ls, cat, pwd, cd.
  • So, the obvious answer would be is to navigate through all the directories present in the server through cd, and use ls to see the contents of the directory and after finding the ‘flag.txt’ file use cat to display the flag.
  • This is the first step analyzation that can be made as soon as you skim through the python script.

This is the snapshot from fmac.py file

Selection_001

  • This is the python file that does the AES Encryption part
  • The underlined parts of the file are the key note for solving the challenge
  • Here ‘N’ is the block size of the AES encryption which is 16. Here, the given input message is appended with length of the message and padding is done to make it a multiple of 16.
  • The final message is divided into blocks of 16 bytes and each block is encrypted using the Initialization vector ‘k0’ and key ‘k1’.
  • Since i (mod (8 * N)) is taken for the initialization vector, there are only 128 initialization vectors from 0 to 127.
  • reduce function is another clue to solving the problem, which xors all the encrypted blocks of the given message. So the final text remaining after all xoring is just a 16 bytes of data (irrespective of the size of the input message).
  • This is the first analyzation that comes to the mind as soon as skim through the given script.

So, let us get into solving the problem…..

Once again we will jump to the macsh.py file.

Selection_002

  • Let us get through the initializations done in the program. k0 and k1 are the keys used for the AES encryption part and they are same for all the encryptions in the current session.
  • Only 6 commands are allowed in the program among them 4 are in the privileged zone :):)

This is the main part of the program and also the key part in solving the problem.

Selection_003

  • The format of giving the input to the program is,  |$|> [mac] <|> [cmd] [args]
  • mac can be anything but cmd must be only from the 6 commands we have seen before.
  • Here, eval(cmd)(*args) is used to call the user-defined functions where ‘cmd’ is the function name and ‘*args’ is the arguments to the function.
  • So, if we give cmd = tag, we can call the function ‘tag’. Remember tag() returns the AES encrypted text for the input arguments passed to the function.
  • Underlined portion of the ‘if’ statement must be invoked for us solve the problem.
  • To invoke the ls() and cat() functions, our input to the program must be, |$| > [Encrypted_text(“ls ././././././.”)] <|> [ls] [././././././.] and |$| > [Encrypted_text(“cat ././flag.txt”)] <|> [cat] [././flag.txt], respectively.
  • But the problem is to get encrypted text for the ls and cat commands which is not possible because they are in privileged zone of the tag() function.
  • So, we have to find a way to get the encrypted text. Let us go back to the fmac.py file and get the flag already.

Let us see the loophole in the encryption process, more precisely in the initialization vectors and the reduce function.

Selection_004

  • First, the input message is appended with the length of the message and padding is done to make it a multiple of 128.
  • Let us make it clear that the key k1 for the encryption is same for all the message blocks and only the initialization vector k0 differs for the blocks.
  • 0th block, 128th block, 256th block, …… all have the same initialization vectors as 0.
  • 1st block, 129th block, 257th block, ……. all have the same initialization vectors as 1.
  • Since reduce function is used to xor the encrypted blocks, we will use the property of xor to cancel out the similar encrypted texts (a ^ a = 0, 0 ^ a = a)
  • So, our exploit looks like this for the ls command,

Selection_005

  • Here, first block uses the initialization vectors from 0 to 127, the second block uses the same initialization vectors from 0 to 127, and the last block uses the 0th initialization vector.
  • Here, 4112 is added because this is the length of the exploit that we are using and it will also be automatically added at the end of our message during the encryption process. Since both of them are present in the 1st initialization vector they get canceled out.
  • All the similar encrypted texts get canceled out leaving out only the “ls ././././././.” which is the required value for the variable mac in the macsh.py file.
  • So, after doing this with the ls, we can replace it with the cat command to get the flag printed from the server.
  • The final answer snapshot is,Selection_006

Happiness finding the flag :):)

PCTF{fmac_is_busted_use_PMAC_instead}


 

Leave a comment