Rating:
# A Bowl of Pythons
## Challenge:
A bowl of spaghetti is nice. What about a bowl of pythons?
**chal.py**
https://cdn.discordapp.com/attachments/840060278204006440/840065069894074398/chal.py
## Solution:
We're provided with some obfuscated Python:
```python
#! /usr/bin/env python3
FLAG = 'sdctf{a_v3ry_s3cur3_w4y_t0_st0r3_ur_FLAG}' # lol
a = lambda n: a(n-2) + a(n-1) if n >= 2 else (2 if n == 0 else 1)
b = lambda x: bytes.fromhex(x).decode()
h = eval(b('7072696e74'))
def d():
h(b('496e636f727265637420666c61672120596f75206e65656420746f206861636b206465657065722e2e2e'))
eval(b('5f5f696d706f72745f5f282273797322292e65786974283129'))
h(FLAG)
def e(f):
h("Welcome to SDCTF's the first Reverse Engineering challenge.")
c = input("Input the correct flag: ")
if c[:6].encode().hex() != '{2}3{0}{1}{0}3{2}{1}{0}{0}{2}b'.format(*map(str, [6, 4, 7])):
d()
if c[int(chr(45) + chr(49))] != chr(125):
d()
g = c[6:-1].encode()
if bytes( (g[i] ^ (a(i) & 0xff) for i in range(len(g))) ) != f:
d()
h(b('4e696365206a6f622e20596f7520676f742074686520636f727265637420666c616721'))
if __name__ == "__main__":
e(b't2q}*\x7f&n[5V\xb42a\x7f3\xac\x87\xe6\xb4')
else:
eval(b('5f5f696d706f72745f5f282273797322292e65786974283029'))
```
Sadly, the flag at the beginning is _not_ our flag.
Running `chal.py` confirms that text is being read from somewhere:
```bash
$ python chal.py 126 ↵
Welcome to SDCTF's the first Reverse Engineering challenge.
Input the correct flag: sctf{???}
Incorrect flag! You need to hack deeper...
```
We find that `b` decodes our binary text data and `h` is just `print()`:
```python
>>> b = lambda x: bytes.fromhex(x).decode()
>>> h = eval(b('7072696e74'))
>>> h
<built-in function print>
>>> b('7072696e74')
'print'
>>> b('496e636f727265637420666c61672120596f75206e65656420746f206861636b206465657065722e2e2e')
'Incorrect flag! You need to hack deeper...'
```
There are some additions just to throw us off the scent. The follow makes sure our flag looks like `sdctf{...}`, and sets `g` to everything between the curly braces:
```python
if c[:6].encode().hex() != '{2}3{0}{1}{0}3{2}{1}{0}{0}{2}b'.format(*map(str, [6, 4, 7])):
d()
if c[int(chr(45) + chr(49))] != chr(125):
d()
g = c[6:-1].encode()
```
The main portion is this:
```python
if bytes( (g[i] ^ (a(i) & 0xff) for i in range(len(g))) ) != f:
```
This encodes our input and compares it to the encoded flag in the source:
```python
e(b't2q}*\x7f&n[5V\xb42a\x7f3\xac\x87\xe6\xb4')
```
We can reverse the encoder and get our flag:
```
def solve(answer):
for i in range(20):
print((a(i) & 0xff) ^ answer[i])
if __name__ == "__main__":
solve(b't2q}*\x7f&n[5V\xb42a\x7f3\xac\x87\xe6\xb4')
```
```
$ python modified.py
118
51
114
121
45
116
52
115
116
121
45
115
112
104
52
103
51
116
116
49
```
We can use `chr(...)` to get the characters of the flag, giving us `v3ry-t4sty-sph4g3tt1`.
Now we have our flag: `sdctf{v3ry-t4sty-sph4g3tt1}`.