Tags: pwn reversing 


[link to original writeup](https://github.com/babaiserror/ctf/tree/main/%5B210813-16%5D%20ReallyAwesomeCTF%202021#lego-car-generator-pwnreversing-350-pts)

The encrypter takes an input and an output. It also generates a 4-byte random number, xor's it with the 4 bytes of the input; then, using `rngNext32`, it generates the next random number to xor with the next 4 bytes of the input, and so on.

LCG, the acronym for the challenge, also stands for Linear Congruential Generator, which is a type of pseudonumber generator. It is also how `rngNext32` generates the next number:

void rngNext32(int *param_1)
*param_1 = *param_1 * 0x17433a5b + -0x481e7b5d;

Finally, we know the first 4 bytes of the flag (6 to be exact, but we don't need that much) - `'ract'`. We can figure out the original seed used for the encryption of `secret` by xoring the secret and the first four bytes of the flag. Using the secret, we can get the next random number used for encryption, and so on, to get the full flag.


with open('secret', 'rb') as f:
get_seed = True
data = f.read(4)
flag = b'ract'
seedb = b''
while data:
if get_seed: # figure out seed
for i in range(4):
seedb += (flag[i]^data[i]).to_bytes(1,'big')
seed = int.from_bytes(seedb, 'big')
get_seed = False
else: # get flag
seedb = seed.to_bytes(4, 'big')
for i in range(len(data)):
flag += (seedb[i]^data[i]).to_bytes(1,'big')
seed = (seed*0x17433a5b-0x481e7b5d)&0xFFFFFFFF
data = f.read(4)