Points: 436
Solves: 58
In this we were given chall.txt
which contains the bytecodes of a python
program.
Running file
on the file really threw me of because, well...
❯ file chall.txt
chall.txt: Dyalog APL transfer
Eventually I didn't see any connection between this and Dyalog, and went to GPT, who told me that it was python bytecode and reconstructed it
Now it didn't reconstruct it properly, and it was a pretty bad idea to rely on it anyway. In the future, it's not very hard to reconstruct it by hand. Here are some resources to help you
and something I found really useful was
The specific place where GPT was stumbling was
0 LOAD_GLOBAL 1 (NULL + random)
2 LOAD_ATTR 2 (getrandbits)
4 LOAD_CONST 1 (32)
6 CALL 1
8 load_fast 0 (i)
10 load_const 2 (195894762)
12 binary_op 12 (^)
14 LOAD_CONST 3 (322420958)
16 BINARY_OP 12 (^)
18 BINARY_OP 5 ()
20 LOAD_CONST 4 (2969596945L)
22 BINARY_OP 5 ()
24 STORE_FAST 1 (password)
It reconstructed this as
return (random.getrandbits(32) ^ 195894762 ^ 322420958) % 2969596945
Which clearly is wrong. What actually is happening is that
0 LOAD_GLOBAL 1 (NULL + random)
2 LOAD_ATTR 2 (getrandbits)
4 LOAD_CONST 1 (32)
6 CALL 1
is getting a 32-bit random number.
8 load_fast 0 (i)
10 load_const 2 (195894762)
12 binary_op 12 (^)
14 LOAD_CONST 3 (322420958)
16 BINARY_OP 12 (^)
is just doing i ^ 195894762
and then XORING that with 322420958
Now a tricky part was BINARY_OP 5
. Apparently this is multiplication (*)
.
Till python v3.10 the bytecodes were BINARY_MULTIPLICATION
etc, but in v3.11
they were changed to BINARY_OP x
. I had to visit some forum
threads to
realise this, and then I confirmed this with Dis This. Which gives us the final math expression as
return (random.getrandbits(32) * ((i ^ 195894762) ^ 322420958) * 2969596945)
Now lets get to the actual exploit. What the challenge is basically an exploit
of python's random
module. random
uses the Mersenne
Twister
Pseudo Random Number Generator ("Praise our RNG gods"), which is predictable if
you have information of 624 contiguous outputs.
The python randcrack
module helps us execute this exploit. We have been given essentially an
infinite sequence of numbers generated by random
that we pass into
randcrack
then. Finally once we confirm randcrack
is able to predict the
numbers, we sent a predicted number to the challenge to get the flag :)
server is now down so I can't get the flag :(
sorry I was so slow