I don't know shite about:

Reveal the hackerman with js getters and setters

Hook into changing object properties for debugging

In this example we're observing a realtime hack of your own video game. Someone managed to sneak some code into your brand new "first-person-hack-and-slay-roguelite-moba" that gives players a pretty high level from the start. You dislike this new "feature" because it takes all the fun out of "the grind for earning xp". So you sally forth to find the culprit inside your codebase.

You know that the hacker is somehow directly increasing the level property in your game. You just have to find out how exactly they increased it.

Emoji Parade

Just recently you've added a small widget to your game, that logs an "Emoji Parade" onto the screen. You were quite satisfied with its look. But something tells you this code may do more than just logging an "Emoji Parade". But how can you prove it? 🤔

▶️ Run the replit below to see the hack in action

Getter and Setters

JavaScript offers a way to control the assignment and retrieval of existing object properties. You can use getters and settters to "do something" if someone directly accesses the property or assigns something to it.

To see how the level changes over time we replace the level property on the game with a set and get function.

function monkeyPatchLevelProperty(game, logTrace = false){

      log = logTrace ? console.trace : console.log; // ignore this. This is only relevant for the logs

      let _level = game.level;

      Object.defineProperty(game, 'level', {
      get: function() {
        log("level up 🔥",_level);
        return _level;
      },
        set: function(newLevel) {
         _level = newLevel;
        }
      });

      game.isMonkeyPatched = true; // ignore this. This is only relevant for the logs
  }

First we define a new variable where the level value can live let _level = game.level; and set it to the current value of game.level Then Object.defineProperty allows us to change the level property to a getter and seter.

In the get function we're logging the current level if the game.level property gets accessed. We then return the current value of our new _level variable so the code relying on it still behaves as expected.

In the set function we're only recreating the expected behaviour behind setting game.level except we're saving the value in _level instead of game.level

▶️ Open Replit and Uncomment // monkeyPatchLevelProperty(game); to see how the getter logs every time someone accessed game.level▶️ Pass in true as a second parameter to monkeyPatchLevelProperty() and you'll see a stacktrace for each time game.level gets accessed

And this is how we reveal. The hacker is increasing the level +1 every 50ms on line 14 inside "/hack.js". 🥸