How hackers reverse Math.random()

Zanzlanz2,475 words

Full Transcript

If you could detect patterns in 

random chance - control the very essence of luck - what could you do?

Impossibly lucky things? Log into lost accounts? Win a jackpot every time?

Today I'll try this. We'll see how computers generate random numbers, learn how 

to reverse the generators to exploit them, and I don't know, get a few jackpots along the way When your computer is picking a 

random number - in almost every case, it's actually picking it from a 

totally predictable sequence. It's just that the sequence is usually billions 

of numbers long. Good luck remembering that! These sequences come from surprisingly 

short math formulas that run each time your computer wants a random number.

Here's one of the simplest ones. Ok so, you want to log in to an old account of 

yours. But, you forgot your password. And when you try to reset your password... it's asking 

for a 6 digit code that it sent to your old email address. And you don't have that email any 

more. And to make matters worse, it says you have only 1 attempt left to login or otherwise 

it'll delete your account forever. Oh boy. At first you feel hopeless. But then you find out, the 6-digit code is generated by this 

formula. And that gives you an idea. When I was 14 years old, I found this 

equation online just like many others did. And I just wanted something that could 

generate random numbers, so I yoinked it for my games, and didn't think much of it.

But like, is it actually good at generating random numbers? Why these specific 

values? And of course: can we hack it? We'll use the random numbers to generate a 

picture. And if it looks like pure static noise, then it's good. If we see 

obvious patterns, then it's bad. We'll start with the number 1 and put 

it into the input of our equation. So, 1 times 9301, plus 49297, modulo 233280. Modulo 

just means, if our number reaches 233280, then we just wrap it back around starting from 0. I like 

to think about it kind of like the game Asteroids, where when things go off the screen, they 

appear on the other side again, back at 0. We can make the lowest number 

black, and the highest white, and now we can visualize the random number.

To give the grey square a friend, we'll generate the next random number just by feeding our 

last one back into the formula. Bop boop beep, and this time it surpasses the modulus over two 

thousand times, but we'll end up with 127215. Then we just do it again. And again. And there's every 

number this generator can make before it repeats. As you can see, there aren't many obvious 

patterns here. Which is pretty impressive. But it doesn't mean there aren't any patterns 

at all. Because if I choose a different grid size to display the numbers on, you can 

see some lines forming. But yeah overall, it's not bad for how simple it is!

This type of random number generator is called a Linear Congruential Generator. 

Congruential... what a weird word. And just to show how important these specific 

numbers are... if we add just 1 to this first number, look how repetitive it is now. To find 

numbers that might work well as a generator, we can adhere to the Hull–Dobell Theorem's 

three rules. So I wrote code to do just that, and now we have a random number generator, 

generator! Kind of disappointingly, most have obvious patterns, but when it actually reveals 

a good one, it feels like I invented something, I love it. I'm naming this one: Zanzlanz's 

Football Formula. Feel free to use it. But yeah it's good to pick values from the list of 

proven good ones. Which "Football" is definitely not on. But let's stick with it. Actually 

let's hack it, create a reverse function, so we can completely undo the randomness.

Normally, it'd be pretty easy to solve for the previous value. You just subtract the offset 

and divide by the multiplier. Unfortunately, you just can't do division when there's 

a modulus in the way. Or can you? You know how division is the opposite of 

multiplication? Like, if x times 2 is y, then y divided by 2 is x. But when you're 

wrapping numbers around a modulus, sadly, this doesn't work. But it just so happens that 

when you have a coprime modulus, if you find just the right number to multiply Y by here, it's 

guaranteed to equal X. Like to undo the times 2 here inside of a modulo 5, we can multiply by 3. 

It's weird, I know. But it's the missing link that allows us to invert our random number generator.

In our example, the right number works out to be 179509. This is called the 

modular multiplicative inverse. So you've just written the inverse random number 

generator. You can't access your old email address to get the secret 6-digit code to unlock your 

account, but you can create a new account with an email you do have access to. It sends you a secret 

code. Quickly, you enter it into your reverse random number generator, and it spits out the 

previous secret code that the website generated: the one to your original account.

Dramatically, you say: I'm in. But was that a realistic scenario? Maybe. I mean 

PHP, a programming language running most websites, has a function called lcg_value, which uses 

a similar number generator to what we just hacked. It's possible a site uses that to 

generate codes, but it would be unsafe. A much more common technique for generating 

random numbers... uses xor-shift. Let's hack it. There were hundreds of thousands of games 

made in Flash, and most of them that need random numbers, use the built-in "random()" 

or "Math.random()" functions. And as usual, that makes them susceptible to hacking.

Without changing any code, and without using a debugger or cheat engine, there 

are multiple ways to manipulate and exploit Flash's random number generator.

Let us look at a XOR-shift random number generator and see if it's better than last one 

we looked at? And how do we invert these things? XOR-ing and shifting are both concepts meant 

for the ol' 1s and 0s, so we'll be taking our normal number input and converting it 

to binary. Instead of 0s and 1s though, I'll just display it as black and white squares.

Okay, what does this code do? Well it combines two copies of our input number, but one of 

them is shifted over by 13 spaces to the left. And the combination of it looks like 

this. That's the XOR operation, meaning, exclusive-or. The output is white only if one or 

the other inputs are white, but not if both are. It's kind of like if you ever used the 

difference or invert blending mode in a drawing program. Which is always fun to play with.

But yeah that's all that this line does of code does. Shifts, and XORs. The full algorithm 

actually does it two more times. The next time, it shifts the result 17 spaces 

to the right. And then it does it one more time, shifting 5 spaces to the left.

And when we plot the results of this random number generator just like before, we can indeed see 

that the resulting image looks like random noise. And since computers love working with 1s and 0s, 

this algorithm is typically faster than the linear congruential generator we looked at earlier. So as 

you can imagine, this algorithm is very popular! But when I first saw this I was like, 

it seems hopeless to ever get back the original number after messing everything 

up with XOR-shifts. But it turns out, XOR-ing is a very reversible process. If 

you XOR one thing, with something else, you can get back the original just by doing it 

again. Neat! How does that help in our case? Well let's look at an example, where we XOR-shift 

the input to the left by 7 spaces. Notice how these 7 bits were not affected at all by 

the XOR-shift. The rest of them were. So, by XOR-shifting these 7 bits again, we'll at 

least get back the original state of 7 more. Which means we can now use those 7 to repeat 

the XOR-shift again. And again, and again, until we successfully undone the entire 

XOR-shift. It's totally reversible! Yay! There are two equivalent ways of doing this. 

First, is just XOR-shifting the final state over by increments of 7. And second, is by XOR-shifting 

the previous state twice as far each time. It's all the same; we get back the original value.

Alright. Here's our original random number generator, and then here's the inverse function.

But that's Xorshift32. There's 64, 128, star, plus, plus plus, xoshiro, 

xoroshiro, and so many more. Some of the techniques I showed are used in 

reversing these random number generators, but each one ends up being its 

own big puzzle to figure out. JavaScript uses Xorshift128+. And it 

is reversible. Either you can use Z3, a framework where you basically describe 

the problem with code, and Z3 searches the problem space for a way to solve it. Shout out to 

PwnFunction for demonstrating this brilliantly. Or you can code the inverse by hand, as 

Scott Contini wrote about a few months ago. Minecraft uses Xoroshiro128++. And 

there are active efforts to reverse it, but it is a significantly more difficult problem. But what does Flash Player use to generate 

random numbers? Reversing it could affect speedrunning Flash games, or allow us to 

reveal rare aspects of classic Flash games. Flash uses a linear feedback 

shift register to randomize a seed number. Then it does a combination 

of XOR-shift and ... subtractshift. And then something sort of like our 

linear congruential generator, except polynomial oooh. And then another 

XOR-shift subtractshift thing, why not. With a little effort, each step of this 

random number generator is reversible. In 2017, Dango wrote the reverse function. In 

2019, George Teşeleanu wrote a paper optimizing it. A speedrunner named Koong implemented a 

full working demo, then Randomno archived the test files. I went to try them out myself, but it 

sounds like Koong lost the original project files. So I tried decompiling the archived version, but 

unfortunately it was only working 50% of the time due to a bug with the decompiler. So I found 

and reported the bug, and it was quickly fixed. So finally, I am now fully in control 

over Flash's next random number. So which should it be? Out of all the numbers what 

could I possibly have chosen for it to display? ...it doesn't even matter, you already imagined 

what I chose. So I'm going to go in and change it to 1234 instead. Alright, there we go.

So my brother has a knack for finding four-leaf clovers. I've never found one 

myself, only the boring 3-leaf kind. So just to get a sense of how my 

brother feels on a typical afternoon, I'll override my luck on a classic game about 

finding four-leaf clovers. 7 of them, to be exact. Using the hacked random number generator, I 

identify a seed that always returns low numbers 7 times in a row. This will force most of the 

4-leaf clovers to be at the top of the field. As a surprise bonus, this is also usually results in 

discovering the same exact seed number each time. Yay! All 7 out of 7. ...wait.

But all this kind of relies on forcing Flash player to generate certain random 

numbers. So in this demo, I will detect and predict random numbers just by observing the game 

itself. No seed number manipulation or anything. This is the Flash version of Minesweeper, 

and my goal is to predict all 99 mines in expert mode, without manipulating 

its random number sequence at all. And here's what I did. I created a 

program that allows me to input the location of mines in a beginner puzzle. 

Then, my program scours billions of seeds in the search for one that could generate 

the same exact puzzle. Once it finds one, it predicts the mine locations of the 

next expert puzzle to generate in Flash. Ok, I've flagged every mine. 

Let's see if we got it right! Whooa, it actually worked. Obviously this all 

just feels like cheating and ruins the game, but at the same time, I feel like 

a wizard of luck. It's kinda scary. The funny thing is though, as I was reimplementing 

the expert mode generator, I found a bug in the source code that means it will only ever generate 

mines in these locations. I think this exploit is way more useful than being able to just 

reverse the random number generator. Jeez. So I guess my advice to developers isn't 

to worry so much about which random number generator to use. I mean, definitely use ones 

labeled cryptographically secure if you're writing a login system or something. But if you're 

generating numbers offline on someone's computer, you can pretty much guarantee it's hackable 

to some degree. I would suggest just being more concerned about the simple things, 

like not leaking data between programs, like Flash did. Or not coding in exploitable 

patterns, like the Minesweeper game. And, maybe just be a little bit more suspicious of speedruns; 

sometimes people can be a bit too lucky. Isn't that right, me getting 5 jackpots in a row in 

my spin-the-wheel game I made when I was 11? Look I spent hours trying to beat my own 

highscore on Spin the Wheel. I just wanted to know how it's possible. How did 11-year-old me 

get so get lucky with a score of 1026? But like, he certainly didn't manipulate Flash's 

random number generator to win a Jackpot. Twice. Three times, four times, five times 

in a row! Obviously this score doesn't count, but it's still cool to feel insanely lucky.

On that note, the last game I manipulated was a Flash slot machine. Mostly because it 

looks cool, but. Turns out the earliest possible opportunity you have to get all 

7s is after 5 pulls, so the random number generator has to carefully coordinate 15 numbers 

to achieve this final, unreasonably lucky spin. Alright, I think that's all out of my system 

now. I'd only gamble if the odds are under my complete control. As so should you! But I 

really should try to find a real four-leaf clover one of these days, that sounds nice.

There's gotta be a clover in here some where. Well hey thanks so much for watching. And 

if you subscribe, I'll see you next month!

Need a transcript for another video?

Get free YouTube transcripts with timestamps, translation, and download options.

Transcript content is sourced from YouTube's auto-generated captions or AI transcription. All video content belongs to the original creators. Terms of Service · DMCA Contact

How hackers reverse Math.random() - YouTube Transcript | ...