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!
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