# 0xL4ugh Snake Writeup For this RE challenge we're given a text file that contains some python bytecode. A quick google search '_python bytecode instruction set_' brings us to this page: [Disassembler for Python bytecode](https://docs.python.org/3/library/dis.html). Great, there's a complete list with [general instructions](https://docs.python.org/3/library/dis.html#opcode-NOP) that we can use as a reference. Analyzing the bytecode we can see that the first two 'blocks' of instructions: ``` LOAD_CONST 1 (0) LOAD_CONST 0 (None) IMPORT_NAME 0 (base64) STORE_FAST 0 (base64) ``` and ``` LOAD_CONST 1 (0) LOAD_CONST 2 (('Fernet',)) IMPORT_NAME 1 (cryptography.fernet) IMPORT_FROM 2 (Fernet) STORE_FAST 1 (Fernet) POP_TOP ``` import the `base64` and `cryptography.Fernet` libraries. The next two lines are assignments to local variables. ``` LOAD_CONST 3 (b'gAAAAABj7Xd90ySo11DSFyX8t-9QIQvAPmU40mWQfpq856jFl1rpwvm1kyE1w23fyyAAd9riXt-JJA9v6BEcsq6LNroZTnjExjFur_tEp0OLJv0c_8BD3bg=') STORE_FAST 2 (encMessage) ``` This time we're calling `base64.b64decode` method on the loaded constant before we're assigning it to a local variable. ``` LOAD_FAST 0 (base64) LOAD_METHOD 3 (b64decode) LOAD_CONST 4 (b'7PXy9PSZmf/r5pXB79LW1cj/7JT6ltPEmfjk8sHljfr6x/LyyfjymNXR5Z0=') CALL_METHOD 1 STORE_FAST 3 (key_bytes) ``` Now we're creating a list ``` BUILD_LIST 0 STORE_FAST 4 (key) ``` and looping over key_bytes ``` LOAD_FAST 3 (key_bytes) 40 GET_ITER >> 42 FOR_ITER 9 (to 62) 44 STORE_FAST 5 (k_b) 46 LOAD_FAST 4 (key) 48 LOAD_METHOD 4 (append) 50 LOAD_FAST 5 (k_b) 52 LOAD_CONST 5 (160) 54 BINARY_XOR 56 CALL_METHOD 1 58 POP_TOP 60 JUMP_ABSOLUTE 21 (to 42) ``` XORing each byte from key_bytes with 160 (0xa0) and appending the result inside the `key` variable. Next instruction block ``` LOAD_GLOBAL 5 (bytes) LOAD_FAST 4 (key) CALL_FUNCTION 1 STORE_FAST 4 (key) LOAD_FAST 1 (Fernet) LOAD_FAST 4 (key) CALL_FUNCTION 1 STORE_FAST 6 (fernet) ``` casts `key` list into a `bytes` object, and creates a `fernet` object of type `Fernet` with `key` as the parameter. Finally, we're decrypting the message and printing it out ``` LOAD_FAST 6 (fernet) LOAD_METHOD 6 (decrypt) LOAD_FAST 2 (encMessage) CALL_METHOD 1 LOAD_METHOD 7 (decode) CALL_METHOD 0 STORE_FAST 7 (decMessage) LOAD_GLOBAL 8 (print) LOAD_FAST 7 (decMessage) CALL_FUNCTION 1 POP_TOP LOAD_CONST 0 (None) RETURN_VALUE ``` Now that we understand what's going on we can write a simple script to get the flag! ```python3 from cryptography.fernet import Fernet import base64 encMessage = b'gAAAAABj7Xd90ySo11DSFyX8t-9QIQvAPmU40mWQfpq856jFl1rpwvm1kyE1w23fyyAAd9riXt-JJA9v6BEcsq6LNroZTnjExjFur_tEp0OLJv0c_8BD3bg=' key_bytes = base64.b64decode(b'7PXy9PSZmf/r5pXB79LW1cj/7JT6ltPEmfjk8sHljfr6x/LyyfjymNXR5Z0=') key = list() for k_b in key_bytes: k_b ^= 160 key.append(k_b) key = bytes(key) f = Fernet(key) decMessage = f.decrypt(encMessage) print(decMessage) ``` ```bash $ python3 snake.py b'FLAG{FLY_L1k3_0xR4V3N}'