Hack The Boo 2023: SpookyCheck
Writeup for the “SpookyCheck” challenge created by Hack The Box for the Hack The Boo 2023 CTF.
For this challenge, a Python compiled file is provided: rev_spookycheck.zip
1
check.pyc: Byte-compiled Python module for CPython 3.11, timestamp-based, .py timestamp: Mon Sep 4 15:32:51 2023 UTC, .py size: 656 bytes
Using pycdc, we can try to decompile the file, but we encounter an error.
1
2
3
4
5
6
7
8
9
10
11
12
# Source Generated with Decompyle++
# File: check.pyc (Python 3.11)
KEY = b'SUP3RS3CR3TK3Y'
CHECK = bytearray(b'\xe9\xef\xc0V\x8d\x8a\x05\xbe\x8ek\xd9yX\x8b\x89\xd3\x8c\xfa\xdexu\xbe\xdf1\xde\xb6\\')
def transform(flag):
return enumerate(flag)()
def check(flag):
Error decompyling check.pyc: vector::_M_range_check: __n (which is 2) >= this->size() (which is 2)
Using pycdas, we can manually examine the bytecode instructions. The function that validates the flag is as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[Disassembly]
0 RESUME 0
2 BUILD_LIST 0
4 LOAD_FAST 0: .0
6 FOR_ITER 54 (to 116)
8 UNPACK_SEQUENCE 2
12 STORE_FAST 1: i
14 STORE_FAST 2: f
16 LOAD_FAST 2: f
18 LOAD_CONST 0: 24
20 BINARY_OP 0 (+)
24 LOAD_CONST 1: 255
26 BINARY_OP 1 (&)
30 LOAD_GLOBAL 0: KEY
42 LOAD_FAST 1: i
44 LOAD_GLOBAL 3: NULL + len
56 LOAD_GLOBAL 0: KEY
68 PRECALL 1
72 CALL 1
82 BINARY_OP 6 (%)
86 BINARY_SUBSCR
96 BINARY_OP 12 (^)
100 LOAD_CONST 2: 74
102 BINARY_OP 10 (-)
106 LOAD_CONST 1: 255
108 BINARY_OP 1 (&)
112 LIST_APPEND 2
114 JUMP_BACKWARD 55
116 RETURN_VALUE
In summary, the function transforms each byte of the flag before comparing it with the corresponding value from the CHECK variable like this:
1
2
3
4
5
byte += 24
byte &= 255
byte ^= key[index % len(key)]
byte -= 74
byte &= 255
We can then write a small script to reverse this operation in order to obtain the flag.
1
2
3
4
5
6
7
8
9
10
11
12
13
KEY = b'SUP3RS3CR3TK3Y'
CHECK = bytearray(b'\xe9\xef\xc0V\x8d\x8a\x05\xbe\x8ek\xd9yX\x8b\x89\xd3\x8c\xfa\xdexu\xbe\xdf1\xde\xb6\\')
for index, byte in enumerate(CHECK):
byte += 74
byte &= 255
byte ^= KEY[index % len(KEY)]
byte &= 255
byte -= 24
byte &= 255
print(chr(byte), end='')
print()
1
2
$ python3 decode_spookycheck.py
HTB{mod3rn_pyth0n_byt3c0d3}
This post is licensed under CC BY 4.0 by the author.