CyberStudents Wordmark

trng

Category

Points

Author

Reverse engineering

120

k

kolmus

Solves (31)

1Profile Picture for trixaitrixai12/18 7:14 pm
2Profile Picture for unpwnblunpwnbl12/18 7:31 pm
3Profile Picture for andreww4364andreww436412/18 8:37 pm
4Profile Picture for minipifminipif12/19 1:09 am
5Profile Picture for godlyavengergodlyavenger12/19 2:03 am
6Profile Picture for snokkisnokki12/19 2:35 am
7Profile Picture for andreicatandreicat12/19 3:53 am
8Profile Picture for damian.28damian.2812/19 4:51 am
9Profile Picture for vuxnx_91621vuxnx_9162112/19 5:21 am
10Profile Picture for _vow__vow_12/19 1:29 pm
11Profile Picture for pligonsteinpligonstein12/19 3:34 pm
12Profile Picture for __landon__landon12/19 5:27 pm
13Profile Picture for .hackboredzz.hackboredzz12/19 10:01 pm
14Profile Picture for _4n3s_4n3s12/20 10:18 am
15Profile Picture for raul_26raul_2612/20 11:13 am
16Profile Picture for mr_mphmr_mph12/20 4:13 pm
17Profile Picture for tudortudor12/21 2:02 pm
18Profile Picture for silence_silence_12/22 3:09 am
19Profile Picture for test123450604test12345060412/22 6:07 am
20Profile Picture for rotzkokowskirotzkokowski12/22 3:21 pm
21Profile Picture for .mindsystem.mindsystem12/22 4:14 pm
22Profile Picture for awdyan_awdyan_12/23 3:41 pm
23Profile Picture for ryuun1cornryuun1corn12/23 4:00 pm
24Profile Picture for zarnex__zarnex__12/23 5:43 pm
25Profile Picture for elijah5399elijah539912/25 9:51 am
26Profile Picture for monstermanyana_47633monstermanyana_4763312/25 3:04 pm
27Profile Picture for captainblcaptainbl12/26 12:46 pm
28Profile Picture for mattewastakenmattewastaken12/26 1:24 pm
29Profile Picture for isee9917isee991712/27 12:39 am
30Profile Picture for f00varf00var12/27 4:01 am
31Profile Picture for papa9995papa999512/27 9:54 am

Description

True random numbers can’t hurt you … they’re not real. (Or are they?)

It looks like somebody is trying to hide your presents? Can you go trace them back and figure out their secrets?

Connect using nc ctf.csd.lol 5040.

Attachments

Hint

There are no penalties for viewing hints. Hints are released 12 hours and 24 hours after the challenge releases.

Submit flag

Discuss this challenge with others in #🎄丨advent-of-ctf on our Discord server.

Write-up

raul_26 (Fl4gged)'s write-up was selected as the best write-up submitted for this challenge.

View this write-up on GitHub

First, I opened the binary in binary ninja and saw the main function:

Main function disassembly

And this additional function:

Function `sub_1249` disassembly

Basically, this program encodes a random number by iterating 1,000,000 times over it and applying the sub_1249() function. To get the flag, it is needed to "guess" the random number before this encoding process. To reverse the encoding, I used this article, which explains how to break xor shift. Let's take the example from the article:

y = x ^ (x >> 3)

y is known, and x needs to be found. Let's say y and x are both 8 bits and represent each bit as a letter:

y = ijklmnop

x = abcdefgh

From y = x ^ (x >> 3) it can be said that:

(eq1)

abcdefgh  ^
000abcde
--------
ijklmnop

It can be seen that ijk=abc since a^0=a, so just by looking at y the first 3 bits of x are known. In the article, there are more details on how they found the following formula:

x = y ^ (y >> 3) ^ (y >> 6)

But basically it states that (remember the x and y notations):

(eq2)

abclmnop  ^
000abclm  ^
000000ab
--------
abcdefgh

Alright, the first 3 bits make sense, what about the rest, why is this true? Well, looking at (eq1) l=a^d and we want to get d, which is the initial bit of x (we are looking for x remember?) so by doing l^a we get d. For m n the similar logic is applied. Finally, for the last two bits it is known that o=g^d and l=a^d, thus from (eq2) we have g^d^a^d^a which is exactly g (similar logic is for the last bit). In the article, there is also a more general formula:

x = y;
for (i = 1; i * shift < bitSize; i++)
  x ^= y >> (i * shift);

This is the most important part. In this case the bitSize is 64 so to reverse the encoding I did:


import numpy as np

def reverse_sub_1249(data_4010):

     a = data_4010 ^ (data_4010 >> 9) ^ (data_4010 >> 18) ^ (data_4010 >> 27) ^ (data_4010 >> 36) ^ (data_4010 >> 45) ^ (data_4010 >> 54) ^ (data_4010 >> 63)
     z = a  ^ (a << 7) ^ (a << 14) ^ (a << 21) ^ (a << 28) ^ (a << 35)  ^ (a << 42)  ^ (a << 49)  ^ (a << 56)  ^ (a << 63)
     return z



data_4010 = np.uint64(0xe415efccd9f117c4)

for i in range(0,1000000):
    data_4010 = reverse_sub_1249(data_4010)
print(f"Recovered x: {data_4010:#016x}")

Basically, I just applied the general formula and did the calculations in the opposite order. The numpy function just bounds the variable data_4010 to not exceed 64 bits. Then I just connected to the server, used the encoded hex values printed as input for my program, and got the secret number.

Flag: csd{M47H_15nT_7H4t_5cARY_N0w_15_I7?}

Need help with a challenge? Is a challenge broken? DM @ModMail in our Discord server.