Skip to main content

Day 5: Bamboozled

challenge description
We've finally located the elves' inner sanctum! But there's a passcode lock, and it seems 
to resist our attempts to analyse it. Can you get us in? All we know is that the elves speak English...

Decompiling Python

We are provided with a Python 3.8 pyc compiled bytecode. Since both my local machine and Kali VM is running Python version 3.9+, decompiling it with uncompyle6 is impossible! I had to resort to spinning up a Python3.8 docker machine to decompile it and obtain the source.

Bamboozled?

The decompilation result was astonishing. It wasn't even Python code. (No wonder online decompilers fail...) It is actually Python dis...

 L.   2         0  JUMP_FORWARD          4  'to 4'
2 LOAD_GLOBAL 99 99
4_0 COME_FROM 0 '0'
4 LOAD_GLOBAL sum
6 LOAD_FAST 'password'
8 LOAD_CONST 0
10 LOAD_CONST 3
12 BUILD_SLICE_2 2
14 BINARY_SUBSCR
16 CALL_FUNCTION_1 1 ''
18 LOAD_CONST 222

L. 3 20 COMPARE_OP !=
22 POP_JUMP_IF_FALSE 28 'to 28'
24 LOAD_GLOBAL exit
26 LOAD_CONST -1
28_0 COME_FROM 22 '22'

L. 4 28 CALL_FUNCTION_1 1 ''
30 POP_TOP
32 LOAD_FAST 'password'
34 LOAD_CONST 0
36 BINARY_SUBSCR
38 LOAD_FAST 'password'
40 LOAD_CONST 1
42 BINARY_SUBSCR
44 BINARY_XOR
46 LOAD_FAST 'password'
48 LOAD_CONST 2
50 BINARY_SUBSCR
52 BINARY_XOR
54 LOAD_CONST 94

L. 5 56 COMPARE_OP !=
58 POP_JUMP_IF_FALSE 64 'to 64'
60 LOAD_GLOBAL exit
62 LOAD_CONST -1
64_0 COME_FROM 58 '58'

L. 6 64 CALL_FUNCTION_1 1 ''
66 POP_TOP
68 LOAD_GLOBAL sum
70 LOAD_FAST 'password'
72 LOAD_CONST 1
74 LOAD_CONST 4
76 BUILD_SLICE_2 2
78 BINARY_SUBSCR
80 CALL_FUNCTION_1 1 ''
82 LOAD_CONST 273

L. 7 84 COMPARE_OP !=
86 POP_JUMP_IF_FALSE 92 'to 92'
88 LOAD_GLOBAL exit
90 LOAD_CONST -1
92_0 COME_FROM 86 '86'
# <snip>

The entire dis file is split into 2 main category. The sum and xor category. With my limited dis knowledge, it seems like it is taking the password and doing a substring of the first 3 characters (password[0:3]) and checking if the sum of the characters equals to 222. It then checks if the xor of the 3 characters gives 94.

A good guess would be to try HTB and viola! Both the sum and XOR works perfectly. Since the entire program does the same 2 functions, we can effectively ignore the XOR since the sum is sufficient. It works on a sliding window, moving the window by 1 each time. Meaning, the next time sum for password[1:4] is check, so on and so forth.

Scripting

We can quickly script to generate the password quickly!

f = open('out.txt', 'r')

sum = []
xor = []

flag = list('HTB')

lines = f.readlines()

for i in range(0, len(lines)):
l = lines[i]
if 'CALL_FUNCTION_1' in l:
if 'LOAD_CONST' in lines[i+1]:
sum.append(lines[i+1].split()[2])
elif 'BINARY_XOR' in l:
if 'LOAD_CONST' in lines[i+1]:
xor.append(lines[i+1].split()[2])

start_inx = 0
for i in range(1, len(sum)):
summ = sum[i]
calc = int(summ) - ord(flag[start_inx+i]) - ord(flag[start_inx+1+i])
flag.append(chr(calc))

print(''.join(flag))

Flag

HTB{pyth0n_d155453mbl3r5_a1nt_50_h4rd_t0_br34k!}