# Snakes and Ladders
## Description
```The flag is fqtbjfub4uj_0_d00151a52523e510f3e50521814141c. The attached file may be useful.```
Category: Reversing
## Analysis
Let's see what's in `main.py`:
```pythondef xor(s1,s2):    return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2))
def encrypt(a):    some_text = a[::2]
    randnum = 14    text_length = len(some_text)    endtext = ""    for i in range(1, text_length + 1):      weirdtext = some_text[i - 1]      if weirdtext >= "a" and weirdtext <= "z":          weirdtext = chr(ord(weirdtext) + randnum)          if weirdtext > "z":              weirdtext = chr(ord(weirdtext) - 26)      endtext += weirdtext    randtext = a[1::2]
    xored = xor("aaaaaaaaaaaaaaa", randtext)    hex_xored = xored.encode("utf-8").hex()
    return endtext + hex_xored
def decrypt(msg):    raise NotImplementedError
def main():    opt = input("Would you like to [E]ncrypt or [D]ecrypt? ")    if opt[:1].lower() == "e":        msg = input("Enter message to encrypt: ")        print(f"Encrypted message: {encrypt(msg)}")    elif opt[:1].lower() == "d":        msg = input("Enter message to decrypt: ")        print(f"Decrypted message: {decrypt(msg)}")
if __name__ == "__main__":    main()```
Alright, we just have to implement `decrypt()` to undo the transformations we see in `encrypt()`. Let's see what happens when we encrypt a message.
```bashkali@kali:~/Downloads$ python3 main.pyWould you like to [E]ncrypt or [D]ecrypt? eEnter message to encrypt: helloworldEncrypted message: vzccz040d161305kali@kali:~/Downloads$ python3 main.pyWould you like to [E]ncrypt or [D]ecrypt? eEnter message to encrypt: aaaaaaaaEncrypted message: oooo00000000kali@kali:~/Downloads$ python3 main.pyWould you like to [E]ncrypt or [D]ecrypt? eEnter message to encrypt: bbbbEncrypted message: pp0303```
`encrypt()` takes the provided input string and splits it into 2 strings:
1) `some_text` with the even letters (starting from 0), which gets passed into a loop that applies ROT-14 on the lowercase letters.
2) `randtext` with the odd letters (starting from 1), which gets XOR'd with a static string and converted to a string of hex values.
After those steps are done, it returns the concatenation of the 2 resulting strings.
## Solution
It would have been nice if there was a delimiter of some sort to separate the 2 strings. Oh well, we just need the flag, so I'll add the space in manually. Implement the `decrypt()` function to reverse the transformations described above, with a space separating the 2 strings.
```pythonimport binascii
def xor(s1,s2):    return ''.join(chr(ord(a) ^ ord(b)) for a, b in zip(s1, s2))
def unxor(s1,s2):    return ''.join(chr(ord(a) ^ b) for a, b in zip(s1, s2))
def encrypt(a):      some_text = a[::2]
    randnum = 14    text_length = len(some_text)    endtext = ""    for i in range(1, text_length + 1):      weirdtext = some_text[i - 1]      if weirdtext >= "a" and weirdtext <= "z":          weirdtext = chr(ord(weirdtext) + randnum)          if weirdtext > "z":              weirdtext = chr(ord(weirdtext) - 26)      endtext += weirdtext    randtext = a[1::2]
    xored = xor("aaaaaaaaaaaaaaa", randtext)    hex_xored = xored.encode("utf-8").hex()
    return endtext + ' ' + hex_xored
def decrypt(msg):    # let's just throw a space in there manually, that seems easier.    endtext, hex_xored = msg.strip().rstrip().split(" ")
    randnum = 14    some_text = ""    for i in range(1, len(endtext) + 1):        weirdtext = endtext[i - 1]        if weirdtext >= "a" and weirdtext <= "z":            weirdtext = chr(ord(weirdtext) - randnum)            if weirdtext < "a":                weirdtext = chr(ord(weirdtext) + 26)        some_text += weirdtext     xored = binascii.unhexlify(hex_xored)    randtext = unxor("aaaaaaaaaaaaaaa", xored)
    cleartext = "\n"    for a, b in zip(some_text, randtext):        cleartext += a + b
    return cleartext
def main():     opt = input("Would you like to [E]ncrypt or [D]ecrypt? ")    if opt[:1].lower() == "e":        msg = input("Enter message to encrypt: ")        print(f"Encrypted message: {encrypt(msg)}")    elif opt[:1].lower() == "d":        msg = input("Enter message to decrypt: ")        print(f"Decrypted message: {decrypt(msg)}")
if __name__ == "__main__":    main()```
Test some known input:
```bashkali@kali:~/Downloads$ python3 solve.py Would you like to [E]ncrypt or [D]ecrypt? eEnter message to encrypt: helloworldEncrypted message: vzccz 040d161305kali@kali:~/Downloads$ python3 solve.py Would you like to [E]ncrypt or [D]ecrypt? dEnter message to decrypt: vzccz 040d161305Decrypted message: helloworld```
Now we just have to run the flag from the description through it, with the extra space:
```bashkali@kali:~/Downloads$ perl -e 'print "d\n" . "fqtbjfub4uj_0_d 00151a52523e510f3e50521814141c\n"' | python3 solve.py Would you like to [E]ncrypt or [D]ecrypt? Enter message to decrypt: Decrypted message: ractf{n3v3r_g0nn4_g1v3_y0u_up}```
The flag is:
```ractf{n3v3r_g0nn4_g1v3_y0u_up}```
