OverTheWire 'Krypton' Write Up
Level 0 -> Level 1
This is a simple base64 decode of the string S1JZUFRPTklTR1JFQVQ=
. We can use the bash base64 -d
command to decode the string.
┌─[✗]─[user@parrot]─[~]
└──╼ $echo 'S1JZUFRPTklTR1JFQVQ=' | base64 -d
KRYPTONISGREAT
Password: KRYPTONISGREAT
Level 1 -> Level 2
Upon logging in, the data for all the levels is stored in the /krypton
directory. Navigate to /krypton/krypton1
to find the necessary files.
There is a file in here called krypton2
. Let’s cat it out to see the contents.
krypton1@bandit:/krypton/krypton1$ cat krypton2
YRIRY GJB CNFFJBEQ EBGGRA
This is most likely some sort of Caesar cipher, perhaps ROT13? ROT13 shifts each letter by 13 positions, so that A (1) -> N (14), B (2) -> M (15), and so on.
┌─[user@parrot]─[~]
└──╼ $rot13 YRIRY GJB CNFFJBEQ EBGGRA
LEVEL TWO PASSWORD ROTTEN
Password: ROTTEN
Level 2 -> Level 3
There are a bunch of files in /krypton/krypton2
, but krypton3
has the encrypted text that we must decipher. It is encrypted with a Caesar cipher. The level gives us other files to help us solve this, but we might not need it.
krypton2@bandit:/krypton/krypton2$ cat krypton3
OMQEMDUEQMEK
This website allows us to decipher text with any number we feed in: https://cryptii.com/pipes/caesar-cipher
By feeding in our text OMQEMDUEQMEK
, we can brute force our Caesar Cipher. Select Decode
and in the Shift box, keep pressing the up arrow until we see our Plaintext.
Password: CAESARISEASY
Level 3 -> Level 4
Enumeration
There are multiple intercepted messages to help us crack the cipher. With this amount of text, this problem is most likely related to frequency analysis. Let’s cat out what we need to decipher.
krypton3@bandit:/krypton/krypton3$ cat krypton4
KSVVW BGSJD SVSIS VXBMN YQUUK BNWCU ANMJS
Unigrams
Letters in the English language do not occur evenly. Certain letters such as ‘E’, ‘S’, ‘T’ are used more often than ‘Q’, ‘J’, ‘Z’. We can use this to our advantage by conducting a frequency analysis of the intercepted messages and compare the letter frequencies with what is nominal for English in order to find the 1 for 1 substitution that was used. This is a breakdown of the English frequencies.
- E: 12.359%
- T: 8.952%
- A: 8.050%
- O: 7.715%
- N: 6.958%
- I: 6.871%
- H: 6.502%
- S: 6.290%
- R: 5.746%
- D: 4.537%
- L: 4.030%
- U: 2.805%
- M: 2.591%
- C: 2.378%
- W: 2.354%
- F: 2.181%
- Y: 2.119%
- G: 2.042%
- P: 1.682%
- B: 1.494%
- V: 1.032%
- K: 0.853%
- X: 0.145%
- J: 0.127%
- Q: 0.099%
- Z: 0.088%
Using this website https://www.boxentriq.com/code-breaking/frequency-analysis, we can analyze the frequencies of the three messages that we intercepted.
Found 1:
- S: 12.062%
- C: 8.327%
- Q: 8.249%
- J: 7.938%
- U: 7.782%
- B: 6.770%
- G: 6.304%
- N: 5.759%
- D: 5.370%
- Z: 4.436%
- V: 4.358%
- W: 3.658%
- Y: 3.268%
- T: 2.490%
- X: 2.257%
- M: 2.257%
- L: 2.101%
- K: 1.946%
- A: 1.556%
- E: 1.323%
- F: 0.856%
- O: 0.545%
- H: 0.156%
- I: 0.156%
- R: 0.078%
Found 2:
- S: 13.698%
- Q: 10.485%
- J: 8.906%
- N: 7.610%
- U: 7.328%
- B: 7.272%
- D: 6.708%
- G: 6.257%
- C: 4.848%
- W: 3.720%
- Z: 3.326%
- V: 2.988%
- M: 2.537%
- T: 2.086%
- E: 1.917%
- X: 1.860%
- Y: 1.860%
- K: 1.691%
- L: 1.522%
- A: 1.466%
- I: 0.789%
- F: 0.676%
- O: 0.169%
- H: 0.113%
- R: 0.113%
- P: 0.056%
Found 3:
- S: 12.420%
- Q: 10.278%
- J: 8.779%
- G: 7.495%
- C: 7.281%
- N: 6.638%
- B: 6.424%
- U: 5.782%
- D: 4.711%
- V: 4.497%
- W: 3.426%
- Z: 3.426%
- E: 2.784%
- M: 2.570%
- K: 2.570%
- Y: 1.927%
- A: 1.927%
- X: 1.927%
- L: 1.285%
- T: 1.285%
- F: 1.071%
- I: 0.642%
- O: 0.428%
- P: 0.214%
- R: 0.214%
These are the unique letters from the krypton4
file that we need to find the substitutions for:
- S, B, I, D, C, M, J, U, Y, Q, G, X, V, N, A, K, W
We only need to map these letters to find the password. Let’s go through the frequencies of the three messages to find them out.
- S is over 12% in all the three messages, so is most likely mapped to the letter E
- Q is the second most common in two out of the three messages, so is most likely A or T
- J is the third most common in two out of the three messages, so is most likely A or T
The rest of the letters are all similar in frequency. Let’s try finding other ways to find letters.
Bigrams
We can analyze bigrams (pairs of two letters) and trigrams (groups of three letters) using the same website to see which letters appear together frequently.
Most common bigrams (in order): th, he, in, en, nt, re, er, an, ti, es.
Found 1:
- DS: 2.570%
- JD: 2.103%
- SU: 2.025%
- JC: 1.947%
- SN: 1.869%
- CU: 1.713%
- CG: 1.636%
- SW: 1.636%
- UJ: 1.402%
Found 2:
- JD: 3.158%
- DS: 2.200%
- SN: 2.030%
- DQ: 2.030%
- NS: 1.918%
- SU: 1.918%
- QN: 1.805%
- JS: 1.636%
- SW: 1.579%
Found 3:
- JD: 2.790%
- DS: 2.361%
- CG: 2.146%
- SQ: 1.931%
- SN: 1.717%
- NS: 1.717%
- BG: 1.717%
- QG: 1.717%
- GW: 1.717%
- QN: 1.717%
Looking at these frequencies, we can assume:
- JD = TH
- DS = HE
- SQ = EA
- SN = ER
- SU = ES
Trigrams
We can do the same things for groups of three letters.
Most common trigrams (in order): the, and, tha, ent, ing, ion, tio, for, nde, has.
Found 1:
- JDS: 1.481%
- DSN: 0.857%
- QGW: 0.857%
- SUQ: 0.779%
- JCB: 0.779%
- CBG: 0.779%
- DCU: 0.779%
- ZCY: 0.624%
- CYD: 0.624%
- YDS: 0.624%
Found 2:
- JDS: 1.862%
- SQN: 0.903%
- UDQ: 0.677%
- JSN: 0.677%
- SNS: 0.621%
- QNS: 0.621%
- DQF: 0.564%
- QFS: 0.564%
- FSU: 0.564%
- SUY: 0.564%
Found 3:
- JDS: 1.935%
- QGW: 1.505%
- SNS: 0.860%
- CGE: 0.860%
- DSN: 0.645%
- NQG: 0.645%
- GWQ: 0.645%
- JDQ: 0.645%
- UZQ: 0.645%
- SCG: 0.645%
Looking at these frequencies, we can assume:
- JDS = THE
- QGW = AND
- CGE = ING
- DQF = HAS
- CBG = ION
- JCB = TIO
Filling in the Letters
Let’s start solving the letters:
- S = E
- B = O
- I
- D = H
- C = I
- M
- J = T
- U = S
- Y
- Q = A
- G = N
- X
- V
- N = R
- A
- K
- W = D
This is what our passphrase looks like:
- KSVVW BGSJD SVSIS VXBMN YQUUK BNWCU ANMJS
- ?E??D ONETH E?E?E ??O?R ?ASS? ORDIS ?R?TE
We can start filling in the gaps:
-
K = W
-
V = L
-
I = V
-
Y = P
-
X = F
-
M = U
-
KSVVW BGSJD SVSIS VXBMN YQUUK BNWCU ANMJS
-
WELLD ONETH ELEVE LFOUR PASSW ORDIS ?RUTE
WELL DONE THE LEVEL FOUR PASSWORD IS BRUTE
Password: BRUTE
Level 4 -> Level 5
Solving a vignere cipher is easy if you use resources! This link had a great tool to help you auto-solve one of the intercepted messages https://www.boxentriq.com/code-breaking/vigenere-cipher.
We can use the same tool to decode using “frekey” as our key.
Password: CLEARTEXT
Level 5 -> Level 6
This is very similar to the previous level, but we will set a smaller min key length of 3 and max key lenth of 16 to test for many possible options.
We got our answer! We can use “keylength” to decode our password.
Password: RANDOM
Level 6 -> Level 7
This level requires us to break a stream cipher. We are not given any intercepted messages, but we are given an executable that allows us to test the cipher. Let’s use it to our advantage!
File Enumeration
Let’s start by checking to see what files we are given.
krypton6@bandit:/krypton/krypton6$ ls
encrypt6 HINT1 HINT2 keyfile.dat krypton7 onetime README
krypton6@bandit:/krypton/krypton6$ ./encrypt6
usage: encrypt6 foo bar
Where: foo is the file containing the plaintext and bar is the destination ciphertext file.
krypton6@bandit:/krypton/krypton6$ cat ./krypton7
PNUKLYLWRQKGKBE
It looks like we have the executable ready for use, along with its corresponding keyfile. We also have the encrypted password.
Using the Executable
If we can run the executable on our own input, we can potentially crack the key! Let’s start by creating a temp directory to work in. We will also need to create a symlink of the keyfile and give it exec permissions.
krypton6@bandit:/krypton/krypton6$ mktemp -d
/tmp/tmp.NbLQP1FLjD
krypton6@bandit:/krypton/krypton6$ cd /tmp/tmp.NbLQP1FLjD
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ ln -s /krypton/krypton6/keyfile.dat
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ ls
keyfile.dat
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ chmod 777 .
Next, we can create an input of all ‘A’s to test the executable.
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" > input
Finally, let’s run the executable a few times to see how our output reacts.
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ /krypton/krypton6/encrypt6 ./input ./output
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ cat output
EICTDGYIYZKTHNSIRFXYCPFUEOCKRNEICTDGYIYZKTHNSIRFXYCPFUEOC
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ /krypton/krypton6/encrypt6 ./input ./output
krypton6@bandit:/tmp/tmp.NbLQP1FLjD$ cat output
EICTDGYIYZKTHNSIRFXYCPFUEOCKRNEICTDGYIYZKTHNSIRFXYCPFUEOC
It looks like the executable encrypts the text the same way every time it is run. Additionally, we can see a repeated pattern of EICTDGYIYZKTHNSIRFXYCPFUEOCKRN
. Sounds like an easy job for Python!
Decryption
Let’s start by saving our output to a variable and creating an empty list to store our cipher. For each letter in our output, we want to store the difference between the letter and ‘A’ in the list.
>>> output = "EICTDGYIYZKTHNSIRFXYCPFUEOCKRN"
>>> cipher = []
>>> for letter in output:
... cipher.append(ord(letter) - ord("A"))
...
>>> cipher
[4, 8, 2, 19, 3, 6, 24, 8, 24, 25, 10, 19, 7, 13, 18, 8, 17, 5, 23, 24, 2, 15, 5, 20, 4, 14, 2, 10, 17, 13]
We have our cipher! Now, we can use our krypton7 ciphertext and work backwords to get the plaintext.
-
For each letter in the ciphertext, we want to subtract the cipher difference at each respective position.
-
If the new value is less than 65 (the ASCII value of ‘A’), we should add 26 to the value to roll it back to a capital letter.
>>> krypton7 = "PNUKLYLWRQKGKBE"
>>> solution = ""
>>> i = 0
>>> for letter in krypton7:
... c = ord(letter) - cipher[i]
... if c < ord("A"):
... c += 26
... solution += chr(c)
... i += 1
...
>>> solution
'LFSRISNOTRANDOM'
We have our solution!
Password: LFSRISNOTRANDOM
Level 7
We completed the game!
krypton7@bandit:~$ cd /krypton/krypton7
krypton7@bandit:/krypton/krypton7$ ls
README
krypton7@bandit:/krypton/krypton7$ cat README
Congratulations on beating Krypton!