Skip to content

webeach-learn/math-random-predictor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Math.random() Predictor for V8

A project to predict Math.random() in V8 engine (Chrome, Node.js) using Z3 solver.

🚀 Quick Start

1. Installation

pip install -r requirements.txt

2. Getting Numbers

Open Chrome browser console (F12) or run Node.js:

[...Array(5)].map(() => Math.random())

Example result:

[0.9715627684052326, 0.6786206219892452, 0.35830200404557, 0.8961429686357996, 0.6562514411348932]

3. Insert into Code

Open main.py and replace the sequence array:

sequence = [
    0.9715627684052326,
    0.6786206219892452,
    0.35830200404557,
    0.8961429686357996,
    0.6562514411348932,
]

4. Run

python3 main.py

5. Result

You will get a prediction of the next number:

🎉 [+] SUCCESS! State recovered!

  State 0: 0x1a5c8103c84e7fdb
  State 1: 0x957454ffb940aa7a

[+] PREDICTION OF THE NEXT NUMBER:

  0.10297399847359556

[✓] Done!

📖 How It Works

V8 Algorithm

V8 uses xorshift128+ for random number generation:

  • 128-bit state (two 64-bit numbers)
  • Deterministic algorithm
  • Cache of 64 pre-generated numbers
  • LIFO order (Last-In-First-Out)

Recovery Process

  1. Data Collection: Get 5-10 sequential Math.random() calls
  2. Reversal: Reverse the array (due to LIFO cache)
  3. Mantissa Extraction: Get 52-bit mantissa from each number
  4. Z3 Solver: Solve system of equations to recover state
  5. Prediction: Generate next numbers from recovered state

Key Points

1. LIFO Order

V8 stores numbers in cache and returns them in reverse order:

sequence = sequence[::-1]  # Reverse!

2. Correct Operation Order

First update xorshift128+ state, then compare:

# Update state
se_s1 ^= se_s1 << 23
se_s1 ^= LShR(se_s1, 17)
se_s1 ^= se_s0
se_s1 ^= LShR(se_s0, 26)

# Then compare
solver.add(mantissa == LShR(se_state0, 12))

⚠️ Important Notes

Predicts Only ONE Next Number

Due to V8 cache behavior (LIFO - Last-In-First-Out), the predictor can reliably predict only one next Math.random() number.

Why?

  • V8 generates numbers in one order but returns them in reverse
  • XorShift128+ only works "forward" (no inverse function)
  • To predict multiple numbers, you need to collect the entire cache (~64 numbers)

Solution:
To predict a sequence of numbers, repeat the process:

  1. Get 5 new numbers from Math.random()
  2. Add them to main.py
  3. Run prediction
  4. Repeat for the next number

Works Only for V8

  • ✅ Chrome
  • ✅ Node.js
  • ✅ Edge (Chromium-based)
  • ❌ Firefox (different algorithm)
  • ❌ Safari (different algorithm)

Number Requirements

  • Numbers must be sequential (no intermediate calls)
  • Minimum 5 numbers, recommended 8-10
  • Obtained from one cache (within 64 calls)

Node.js with Fixed Seed

For testing, you can use a fixed seed:

node --random_seed=1337

Then in Node.js:

Array.from(Array(5), Math.random)
// [0.9311600617849973, 0.3551442693830502, 0.7923158995678377, ...]

🔧 Troubleshooting

"FAILED TO RECOVER STATE"

Reasons:

  1. Numbers are not sequential

    • Other Math.random() calls occurred between them
    • Solution: Get numbers at once
  2. Not enough data

    • Less than 5 numbers
    • Solution: Add more numbers (8-10)
  3. Not from V8

    • Using Firefox/Safari
    • Solution: Use Chrome or Node.js

Verify Functionality

Run with test data (with seed):

# In Node.js
node --random_seed=1337
Array.from(Array(5), Math.random)

Use these numbers in main.py - should work!

📚 Technical Details

XorShift128+

s1 = state0
s0 = state1
state0 = s0
s1 ^= s1 << 23
s1 ^= s1 >> 17
s1 ^= s0
s1 ^= s0 >> 26
state1 = s1

Mantissa Extraction

Math.random() returns double in [0, 1):

  1. Add 1.0 → number in [1, 2)
  2. Get bit representation
  3. Extract 52-bit mantissa
  4. Compare with (state0 >> 12)

IEEE 754 Double

[Sign: 1 bit] [Exponent: 11 bits] [Mantissa: 52 bits]

🔗 Links

⚖️ Security

⚠️ Math.random() is NOT cryptographically secure!

For cryptography use:

  • In browser: crypto.getRandomValues()
  • In Node.js: crypto.randomBytes()

V8 Version: Tested on V8 12.4.254.14 (Node.js v22.2.0)
Date: 2026-01-17

About

Math.random() Predictor for V8 (Chrome, Node.js)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published