Skip to content

Instantly share code, notes, and snippets.

@Kebap
Forked from soatok/idleon.md
Created March 28, 2024 20:37
Show Gist options
  • Save Kebap/ce1740845f2acbaff04d6c143e7fc238 to your computer and use it in GitHub Desktop.
Save Kebap/ce1740845f2acbaff04d6c143e7fc238 to your computer and use it in GitHub Desktop.
Legends of IdleOn RNG Manipulation

Disclosure Timeline

Note: All dates are in YYYY-MM-DD format (as per ISO 8601 and other standards).

Date Action
2023-07-06 Emailed lava at lavaflame2 dot com with these details and a recommended fix.
2023-08-06 A month later, I follow up just asking if Lava has received my messages.
2023-11-15 Additional follow-up email
2023-11-15 Mentioned knowing an exploit in Discord, passed details onto moderator (Hotair)
2023-11-15 Additional follow-up email (as I cannot DM lava)
2024-01-16 Given a lack of repsonse after more than 6 months, public disclosure.

Screenshots are also available for some of my outreach attempts.

Exploit

This is easiest to do in the browser version of the game. You can use a Google Account for both Steam and Web in order to load an existing account in the web mode. Easy peasy.

Press F12 to open your developer tools. Run the following code:

// Make a native copy of your browser's Math.random function
Math.originalRandom = Math.random

// Now replace it
Math.random = () => Math.originalRandom() / 100000000000;

Open the Arcade. Press Launch. Notice all of the balls always fall to the right. You can score unlimited jackpots.

There are some other use cases where you want high numbers. There are yet others where you want to pingpong between high and low numbers for the desired effect.

Math.originalRandom = Math.random;
Math.lowRandom = function() {
    return Math.originalRandom() / 100000000000;
}

Math.highRandom = function() {
    return 1 - Math.lowRandom();
}


let breakCycle = false;
function luckyCycle() {
  return setTimeout(function() {
    if (breakCycle) return;
    // console.log('rng on');
    Math.random = Math.lowRandom;
    return setTimeout(function() {
      //console.log('rng off');
      Math.random = Math.highRandom;
      return setTimeout(luckyCycle, 30000);
    }, 30000);
  });
}

Then you can just Math.random = /* desired other function, such as Math.lowRandom */ your way to winning big.

Impact

Mitigation

Lava could mitigate this risk with one line of code, followed by a search and replace:

+ const LavaMath = Object.freeze(Math)

And then replace any calls to Math.random with LavaMath.random, and then this would no longer be possible.

(Yes, I included this one-liner in my email to Lava in July 2023.)

Advanced Exploit

Compile Chromium with a custom RNG that returns a low value (less than 0.000001) 9/10 times, then defers to the normal LCG the rest of the time. You'll win most luck-based things (Arcade Balls, Gaming Plants, etc.).

The mitigation I suggest doesn't defend against this, but using a secure RNG instead of Math.random would likely generate farier numers anyway.

Update

The /r/idleon mods censored the link to this Gist from their subreddit (Archive).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment