Level: Medium
Tags: picoCTF 2024, Cryptography, browser_webshell_solvable
Author: MATT SUPERDOCK
Description:
This is the Custom Cyclical Cipher!
Download the ciphertext here.
Download the encoder here.
Enclose the flag in our wrapper for submission.
If the flag was "example" you would submit "picoCTF{example}".
Hints:
1. Modern crypto schemes don't depend on the encoder to be secret, but this one does.
Challenge link: https://play.picoctf.org/practice/challenge/407
The given ciphertext
contains the following:
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Cryptography/C3]
└─$ cat ciphertext
DLSeGAGDgBNJDQJDCFSFnRBIDjgHoDFCFtHDgJpiHtGDmMAQFnRBJKkBAsTMrsPSDDnEFCFtIbEDtDCIbFCFtHTJDKerFldbFObFCFtLBFkBAAAPFnRBJGEkerFlcPgKkImHnIlATJDKbTbFOkdNnsgbnJRMFnRBNAFkBAAAbrcbTKAkOgFpOgFpOpkBAAAAAAAiClFGIPFnRBaKliCgClFGtIBAAAAAAAOgGEkImHnIl
And the python source code looks like this (with added line breaks for readability)
import sys
chars = ""
from fileinput import input
for line in input():
chars += line
lookup1 = "\n \"#()*+/1:=[]abcdefghijklmnopqrstuvwxyz"
lookup2 = "ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst"
out = ""
prev = 0
for char in chars:
cur = lookup1.index(char)
out += lookup2[(cur - prev) % 40]
prev = cur
sys.stdout.write(out)
From the code we can see that the encryption is a combination of two cyclic lookup tables of length 40.
To decrypt we need to perform the operations in the reverse order.
We create a first decoding script that looks like this
#!/usr/bin/python
import sys
ciphertext = 'DLSeGAGDgBNJDQJDCFSFnRBIDjgHoDFCFtHDgJpiHtGDmMAQFnRBJKkBAsTMrsPSDDnEFCFtIbEDtDCIbFCFtHTJDKerFldbFObFCFtLBFkBAAAPFnRBJGEkerFlcPgKkImHnIlATJDKbTbFOkdNnsgbnJRMFnRBNAFkBAAAbrcbTKAkOgFpOgFpOpkBAAAAAAAiClFGIPFnRBaKliCgClFGtIBAAAAAAAOgGEkImHnIl'
lookup1 = "\n \"#()*+/1:=[]abcdefghijklmnopqrstuvwxyz"
lookup2 = "ABCDEFGHIJKLMNOPQRSTabcdefghijklmnopqrst"
out = ""
prev = 0
for char in ciphertext:
index_2 = lookup2.index(char)
index_1 = (index_2 + prev) % 40
out += lookup1[index_1]
prev = index_1
sys.stdout.write(out)
Running the script give us the following output
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Cryptography/C3]
└─$ python decode.py
#asciiorder
#fortychars
#selfinput
#pythontwo
chars = ""
from fileinput import input
for line in input():
chars += line
b = 1 / 1
for i in range(len(chars)):
if i == b * b * b:
print chars[i] #prints
b += 1 / 1
Note that:
- The script uses itself as input from the comment on line 3
- Python version 2 is expected from the comment on line 4
We save this output as stage2.py
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Cryptography/C3]
└─$ python decode.py > stage2.py
Finally we run the stage2.py
script and give itself as input, remove newlines with tr -d
and pass the output to printf
to create the flag for us
┌──(kali㉿kali)-[/mnt/…/picoCTF/picoCTF_2024/Cryptography/C3]
└─$ printf "picoCTF{%s}" $(python2 ./stage2.py < stage2.py | tr -d '\n')
picoCTF{<REDACTED>}
For additional information, please see the references below.