csdocs/devs/scraping/devtools_detectors.md

4.6 KiB

label order icon
Devtools detector 997 /static/tool.png

TL;DR: You are going to get fucked by sites detecting your devtools, the easiest bypass for this is using a web sniffer extension

Many sites use some sort of debugger detection to prevent you from looking at the important requests made by the browser.

You can test the devtools detector here Code for the detector found here

How are they detecting the tools?

One or more of the following methods are used to prevent devtools in the majority of cases (if not all):

1. Calling debugger in an endless loop. This is very easy to bypass. You can either right click the offending line (in chrome) and disable all debugger calls from that line or you can disable the whole debugger.

2. Attaching a custom .toString() function to an expression and printing it with console.log(). When devtools are open (even while not in console) all console.log() calls will be resloved and the custom .toString() function will be called. Functions can also be triggered by how dates, regex and functions are formatted in the console.

This lets the site know the millisecond you bring up devtools. Doing const console = null and other js hacks have not worked for me (the console function gets cached by the detector).

If you can find the offending js responsible for the detection you can bypass it by redifining the function in violentmonkey, but I recommend against it since it's often hidden and obfuscated. The best way to bypass this issue is to re-compile firefox or chrome with a switch to disable the console.

3. Running a while (true) {} loop when the debugger object is present? Looks something like this in the wild:

function _0x39426c(e) {
    function t(e) {
        if ("string" == typeof e)
            return function(e) {}
            .constructor("while (true) {}").apply("counter");
        1 !== ("" + e / e).length || e % 20 == 0 ? function() {
            return !0;
        }
        .constructor("debugger").call("action") : function() {
            return !1;
        }
        .constructor("debugger").apply("stateObject"),
        t(++e);
    }
    try {
        if (e)
            return t;
        t(0);
    } catch (e) {}
}
setInterval(function() {
    _0x39426c();
}, 4e3);

This function can be tracked down to this script

I do not actually know how this works, but the loop seems gets triggered in the presence of a debugger. Either way this instantly freezes the webpage in firefox and makes it very unresponsive in chrome and does not rely on console.log(). You could bypass this by doing const _0x39426c = null in violentmonkey, but this bypass is not doable with heavily obfuscated js.

How to bypass the detection?

If you just want to see the network log that is possible with extensions, see Web Sniffer

I tracked down the functions making devtools detection possible in the firefox source code and compiled a version which is undetectable by any of these tools.

  • Linux build

  • Windows build

  • Mac build

  • about:config devtools.console.bypass disables the console which invalidates method 2.

  • about:config devtools.debugger.bypass completely disables the debugger, useful to bypass method 3.

If you want to compile firefox yourself with these bypasses you can, using the line changes below in the described files.

BUILD: 101.0a1 (2022-04-19) ./devtools/server/actors/thread.js At line 390

  attach(options) {
    let devtoolsBypass = Services.prefs.getBoolPref("devtools.debugger.bypass", true);
    if (devtoolsBypass)
        return;

./devtools/server/actors/webconsole/listeners/console-api.js At line 92

observe(message, topic) {
let devtoolsBypass = Services.prefs.getBoolPref("devtools.console.bypass", true);
if (!this.handler || devtoolsBypass) {
  return;
}

./browser/app/profile/firefox.js At line 23

// Bypasses
pref("devtools.console.bypass", true);
pref("devtools.debugger.bypass", true);