3

I would like to know the best way to detect when a method or function is directly called through the console. As far as I currently understand, it's not possible to directly detect it on identical function calls, but using the .call() and .apply() methods of a function I can pass additional data through the this object.

Given the following code structure:

(function(){
    var Player = {money: 0};
    window.giveMoney = function(amount){
        if (this.legit !== true)
            throw new Error("Don't try to cheat!");

        Player.money += amount;
    }
})();

I could call the function using

window.giveMoney.call({legit: true}, 300);

in my actual code to tell a direct call from the console and my own code apart, but this is obviously not fool-proof, since the same code can also be executed from the console to achieve the desired effect.

I would want a way to be able to call the function from both places and then tell the locations of the call apart. If there's no way to do that, what's the best way to try and prevent the execution anyway? Is it best to just not expose any methods at all, and keep everything inside a single closed-off anonymous function?

SeinopSys
  • 8,787
  • 10
  • 62
  • 110
  • 4
    no matter what you do, it is on the client side, it will never be safe. dont waste time on that. – bto.rdz Jan 17 '15 at 14:30
  • The code I'm asking help with is from a JS game that only runs client-side, offline. – SeinopSys Jan 17 '15 at 14:31
  • 3
    It's impossible to prevent a user from calling your function. You sent him its source, he just needs to execute it. If you want to make it non-trivial to execute it from the console, yes don't expose it (module pattern) but don't try to go further. – Bergi Jan 17 '15 at 14:32
  • 1
    And all the games that runs on the client side can be hacked – bto.rdz Jan 17 '15 at 14:32
  • Put all your variables and functions into a closure so that user can not call it in console. – tsh Jan 17 '15 at 14:34
  • 1
    Just like **bto.rdz** stated earlier, javascript **is client side**, and **whatever you do, there is always a way to undo it**, so if you are trying to prevent cheating then **perhaps you should consider using a server side language like php or asp instead.** – ilgaar Jan 17 '15 at 14:35
  • 1
    @igaar that isn't nexcessarilly true. If your JS code is written correctly using closures and modules then short of buggering up the memory I don't see how you can do a deep dive and change the variables. That is the very nature of closures. – Sukima Jan 17 '15 at 15:05
  • 3
    @Sukima the very nature of debugger though is changing anything you want in runtime. Debugger is not afraid of closures. – Olga Jan 17 '15 at 16:39

3 Answers3

4

To prevent global access make sure your code is in a closure. If you want to expose an API you can do so using the module pattern.

Closure

(function() {
  var Game = {};
  Game.giveMoney = function(money) {
    console.log('Gave money (' + money + ')');
  };
})();

Wrap all your private code in an IIFE (Immediately Invoked Function Expression) which will lock it up into a closure.

Module

Then expose only custom functions back out of the closure so you can use them on the console (with supervision of course).

window.Game = (function() {
  var player = {
    money: 500;
  };
  player.giveMoney = function(money) {
    console.log('Gave money (' + money + ')');
    player.money += money;
  };
  player.takeMoney = function(money) {
    console.log('Took money (' + money + ')');
    player.money -= money;
  };

  return {
    giveMoney: function(money) {
      console.error('Don\'t Cheat! A fine was charged.');
      player.takeMoney(Math.floor(player.money / 0.05));
    }
  };
})();

window.Game.giveMoney(200);
Community
  • 1
  • 1
Sukima
  • 9,965
  • 3
  • 46
  • 60
  • This also prevents the user from redefining window.Game.giveMoney, because once they do they will have lost the closure. Win! – Sukima Jan 17 '15 at 15:07
  • 1
    What is to prevent the user from inserting a breakpoint (e.g. in Chrome Dev Tools Source Panel), and calling the method with desired parameters then and there. Not really console proof. – Olga Jan 17 '15 at 16:33
  • @Olga if that is a concern then you have more problems then attempting to prevent it. Seriously how is that different from decompiling byte code. I can see the use of a console being interesting like it is in [cookie clicker](http://cookieclicker.wikia.com/wiki/Cheating), but if it is to prevent tampering then I think the design requirements need to be reassesed. – Sukima Jan 17 '15 at 18:25
  • @Sukima I only wanted to point out the possibility, didn't want to sound harsh. It is also much easier than decompiling byte code =) – Olga Jan 19 '15 at 11:10
  • @Olga Debugger can be detected by measuring execution time. (Unfortunately it is just an another layer for the attacker to beat) – vlp Oct 19 '15 at 22:29
0

You can spool all function calls through a central access point with a boolean variable, that can serve as a indicator whether the call is from a console or not....

var maths = {
    add: function(p1,p2)
    {
        console.log(p1,p2);
    }
}

var invoker = {
    invoke: function(fu,isconsole)
    {
        if(isconsole)
        {
            console.log("Called from console");
        }

        //invokes the function with all parameters intact
        fu;
    }
}

//Call without console
invoker.invoke(maths.add(2,3));

//Call with console
invoker.invoke(maths.add(2,3),true);

Hope it helps!!!

Hemant
  • 1,999
  • 2
  • 12
  • 8
0

You can use the monitor() command in the console to monitor when a function is called. https://developer.chrome.com/devtools/docs/commandline-api#monitorfunction

Just run monitor(functionName); and whenever the function is called it will output a message in the console.

jaredwilli
  • 11,762
  • 6
  • 42
  • 41
  • That link goes to some overview and doesn’t explain how to use the “monitor” command. MDN does not offer any search results for that function either. Could you expand on what you mean by this answer and possibly how to access it in all browsers? – Sukima Jul 11 '23 at 13:36