Killer Queen CTF 2021

jazz [232 pts]

9xLmMiI2znmPam’D_A_1:RQ;Il*7:%i”.R<


jazz{D34D_0N_T1|\/|3_3vgy90N51Fob1s}


tl;dr

Introduction

jar file can be decompiled with jd-gui. Encryption function does the following (rewritten to Python):

def encrypt(flag):
    temp = [158 - ord(c) for c in flag]
    print(temp)
    ciphertext = ""
    for i in range(len(temp) // 2):
        t1, t2 = temp[2 * i], temp[2 * i + 1]
        ciphertext += chr((2 * t1 - t2 + 153) % 93 + 33)
        ciphertext += chr((t2 - t1 + 93) % 93 + 33)
    return ciphertext

So it first subtracts each character from 158 and then enters a loop where it adds two characters at a time based on some math performed on the two next characters from temp.

We can reverse this to create a decryption function. This is a bit difficult since we in the above function really now want to extract t1 and t2 from the two next characters in the ciphertext. We look at the first line:

ciphertext += chr((2 * t1 - t2 + 153) % 93 + 33)  # call this c1

Reversing this, we get

c1 = chr((2 * t1 - t2 + 153) % 93 + 33)
ord(c1) = (2 * t1 - t2 + 153) % 93 + 33
ord(c1) - 33 = (2 * t1 - t2 + 153) % 93  # let's ignore the modulo for now
ord(c1) - 33 - 153 = 2 * t1 - t2  # call this x

from the next line:

ciphertext += chr((t2 - t1 + 93) % 93 + 33)  # call this c2

we get

c2 = chr((t2 - t1 + 93) % 93 + 33)
ord(c1) = (t2 - t1 + 93) % 93 + 33
ord(c1) - 33 = t2 - t1 + 93  # ignore modulo again
ord(c1) - 33 - 93 = t2 - t1  # call this y

So now we have an expression for t2 - t1 and 2 * t1 - t2 – two equations with two unknowns. If we just add them, we get

(t2 - t1) + (2 * t1 - t2) = t1 = x + y

and knowing t1, we get

(t2 - t1) + t1 = t2 = y + t1

So now we (almost) have the two original characters! All there is left is we need to take the result modulo 93 in some of the cases (we don’t know which, that was lost when doing the original modulo in the encryption). Instead, we just do modulo on each and subtract them from 158 to reverse the final part. And if this result is above 127 (not ASCII), then we know we shouldn’t have done modulo on this, so we subtract 93 again. See script below:

def decrypt(ciphertext):
    temp = []
    for i in range(len(ciphertext) // 2):
        c1, c2 = ciphertext[2 * i], ciphertext[2 * i + 1]
        x = ord(c1) - 33 - 153  # reversing first equation
        y = ord(c2) - 33 - 93   # reversing second equation
        t1 = x + y              # solve two equations with two unknowns
        t2 = y + t1
        temp.extend([t1, t2])
    flag = ""
    for n in temp:
        r = 158 - (n % 93)  # do modulo before subtracting
        if r > 127:  # except when you shouldn't have!
            r -= 93  # then fix
        flag += chr(r)
    return flag

Inputting the encrypted flag to this gives us back the original flag (minus the final curly brace due to an odd length flag)

jazz{D34D_0N_T1|\/|3_3vgy90N51Fob1s}

____

1 November 2021
Tags: <rev/>