# PicoCTF - New Caesar ###### tags: `PicoCTF` `CTF` `Crypto` Challenge: [New Caesar](https://play.picoctf.org/practice/challenge/158?category=2&page=1) ## Source code ::: spoiler source code ```python= import string LOWERCASE_OFFSET = ord("a") ALPHABET = string.ascii_lowercase[:16] def b16_encode(plain): enc = "" for c in plain: binary = "{0:08b}".format(ord(c)) enc += ALPHABET[int(binary[:4], 2)] enc += ALPHABET[int(binary[4:], 2)] return enc def shift(c, k): t1 = ord(c) - LOWERCASE_OFFSET t2 = ord(k) - LOWERCASE_OFFSET return ALPHABET[(t1 + t2) % len(ALPHABET)] flag = "redacted" key = "redacted" assert all([k in ALPHABET for k in key]) assert len(key) == 1 b16 = b16_encode(flag) enc = "" for i, c in enumerate(b16): enc += shift(c, key[i % len(key)]) print(enc) ``` ::: ## Recon 1. Hint in the code It gave two hints in the code that represented by `assert` 1.1 The key must in the first 16 character of alphabet strings, that is, the key is composed of `a~p`. 1.2 The key length is just 1 2. Encode to binary Then it encodes each character to hex and split it in the middle. Then map the value to alphabet sequence, that is, `a` $\to$ `0` `b` $\to$ `1` ... `o` $\to$ `14` `p` $\to$ `15` 3. Shift string This process is just like `rot n` that it shift the concatenated strings with `n` characters. ## Exploit - Recover 1. Guess it shift `n` character First, we can guess the `n` value for example 1. And then we try to shift it back. 2. Regroup and Re-mapping Then we can represent the shifted string as binary. If the length of the binary value is equal to `8`, that means we can regroup it to a real strings as ascii. 3. Then repeat 16 times Here is the 16 outcomes... ```bash et_tu?_23217b54456fb10e908b5e87c6e89156 v`@`CDCBHsFEEFGwsBAvJAIsFvIHtGvIJBFG qQqTUTSYWVVWXSR[RZWZYXZ[SWX §§¨befedjhgghidclckhkjikldhi ©¸¸¹svwvu{¦yxxyzª¦ut©}t|¦y©|{§z©|}uyz ºÉ¤Éʤ·»·º·º¸º ËÚµÚÛµÈÌÈËÈËÉË ÜëÆëì¦Æ©ª©¨®Ù¬««¬­ÝÙ¨§Ü §¯Ù¬Ü¯®Ú­Ü¯ ¨¬­ íü×üý·×º»º¹¿ê½¼¼½¾îê¹¸í±¸°ê½í°¿ë¾í°±¹½¾ ÈèËÌËÊÀûÎÍÍÎÏÿûÊÉþÂÉÁûÎþÁÀüÏþÁÂÊÎÏ ``` Seems the first one is quite normal. And we got the flag... Flag: `picoCTF{et_tu?_23217b54456fb10e908b5e87c6e89156}` :::spoiler whole exploit ```python!= import string LOWERCASE_OFFSET = ord("a") ALPHABET = string.ascii_lowercase[:16] cipher_flag = "apbopjbobpnjpjnmnnnmnlnbamnpnononpnaaaamnlnkapndnkncamnpapncnbannaapncndnlnpna" def binToHexa(n): bnum = int(n) temp = 0 mul = 1 count = 1 hexaDeciNum = ['0'] * 100 i = 0 while bnum != 0: rem = bnum % 10 temp = temp + (rem*mul) if count % 4 == 0: if temp < 10: hexaDeciNum[i] = chr(temp+48) else: hexaDeciNum[i] = chr(temp+55) mul = 1 temp = 0 count = 1 i = i+1 else: mul = mul*2 count = count+1 bnum = int(bnum/10) if count != 1: hexaDeciNum[i] = chr(temp+48) if count == 1: i = i-1 hex_string = '' while i >= 0: hex_string += hexaDeciNum[i] i = i-1 if hex_string == '': hex_string = '00' return hex_string tmp = "" guess_strings = "" for i in range(1, 16): for e in cipher_flag: tmp += "{0:04b}".format((ord(e) - LOWERCASE_OFFSET + i) % len(ALPHABET)) if len(tmp) % 8 == 0: guess_strings += chr(int(binToHexa(tmp), 16)) tmp = "" tmp = "" print(guess_strings) guess_strings = "" :::