# 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}'