• 关于浏览器Devtools的open,close监听


    关于浏览器Devtools的open/close监听

    前言

    常见open行为结果

    • 无限debugger
    • 反复刷新页面
    • 跳转指定页面

    页面跳转:

    *// 类似 HTTP 重定向到菜鸟教程*
    window.location.replace("http://localhost");
    *// 类似点击菜鸟教程的链接(a 标签)*
    window.location.href = "http://localhost";
    

    关闭页面:

    window.close()  // 不过只能由 Window.open() 方法打开的窗口的 window 对象来调用。
    

    通常各个监听行为都使用了setIntervalsetTimeout函数, 不方便debug的时候可以使用 定时器事件断点

    以下是sgcc.com.cn中对于打开devtool行为的处理

        try {
            window.opener = null,  // 返回打开当前窗口的那个窗口的引用
                window.open("", "_self"),  // 这里先使用了, open方法打开当前窗口, 再使用close去关闭
                window.close(),   // 关闭当前窗口, 不过有时候还是会失败(应该与浏览器有关系)
                window.history.back()  // 会话历史记录中向后移动一页, 没有不执行
        } catch (e) {
        }
        setTimeout((function () {
                window.location.href = f.timeOutUrl || 
                  "https://theajack.github.io/disable-devtool/404.html?h=".concat(encodeURIComponent(location.host))
            }
        ), 500)
    

    一些使用了反调试的网站

    TIP: 浏览器的不同可能导致方法在不同的浏览器出现不同的结果

    1. 窗口判断

    方案: 根据浏览器窗口判断

    缺点: 无法监听独立窗口的devtool

    demo: https://sindresorhus.com/devtools-detect/

    代码: sindresorhus/devtools-detect: Detect if DevTools is open and its orientation (github.com)

    const devtools = {
    	isOpen: false,
    	orientation: undefined,
    };
    
    const threshold = 170;
    
    const main = ({emitEvents = true} = {}) => {
    	const widthThreshold = globalThis.outerWidth - globalThis.innerWidth > threshold;
    	const heightThreshold = globalThis.outerHeight - globalThis.innerHeight > threshold;
    	const orientation = widthThreshold ? 'vertical' : 'horizontal';
    
    	if (
    		!(heightThreshold && widthThreshold)
    		&& ((globalThis.Firebug && globalThis.Firebug.chrome && globalThis.Firebug.chrome.isInitialized) || widthThreshold || heightThreshold)
    	) {
    		devtools.isOpen = true;
    		devtools.orientation = orientation;
    	} else {
    
    		devtools.isOpen = false;
    		devtools.orientation = undefined;
    	}
    };
    
    

    2. debugger时间差

    方案: 打开控制台会触发debugger, 导致debugger前后时间差过大; 根据时间差判断是否打开控制台

    缺点: 容易被定位到关键代码位置, 覆盖/重写关键函数即可破解; 使用debugger直接使用永不在此暂停就跳过了这个debug

    相关:

    • demo: https://codepo8.github.io/console-killer/demo.html
    • 代码: https://github.com/codepo8/console-killer
    • 文章: https://dev.to/codepo8/cracking-a-developer-tools-killer-script-2lpl

    具体代码还做了对F12, 右键菜单做了屏蔽,无法在demo中打开控制台; 但是这种无法避免我先打开控制台, 再进行访问地址

    var minimalUserResponseInMiliseconds = 200;
    function check() { 
        console.clear();
        before = new Date().getTime();
        debugger;
        after = new Date().getTime();
        if (after - before > minimalUserResponseInMiliseconds) { 
            document.write(" Dont open Developer Tools. ");
            self.location.replace(
                window.location.protocol + window.location.href.substring(
                    window.location.protocol.length
                )
            );  
        } else { 
            before = null;
            after = null;
            delete before;
            delete after;
        }
        setTimeout(check, 100);
    }
    

    3. 读取元素id

    利用Chrome开发者工具会自动读取元素id的特性,重写getter实现需求
    let element = document.createElement('checkDevTools');
    Object.defineProperty(element, 'id', {
        get: function () {
            /* TODO */
            isDevToolsOpened = true;
        }
    });
    element.__defineGetter__('id', function () {
        isDevToolsOpened = true;
    });
    console.debug(element); //使用console.debug()使打印出的辅助信息默认隐藏
    

    4. performance对象比较性能

    博客: 如何知道 Chrome 控制台何时打开 (guya.net)

    demo: Chrome Developer Tools State (guya.net)

    APi: Performance - Web API | MDN (mozilla.org)

    • **通过performance对象:**可以使用performance对象来检测页面加载的性能。一般情况下,开发者工具的打开会对性能指标产生一些影响,如资源加载时间的延长。因此,可以通过比较某些性能指标的值来判断开发者工具是否打开。
    if (performance.memory && performance.memory.usedJSHeapSize > 0) {
      console.log("Developer tools open"); // 内存使用情况大于0,可能表示开发者工具已打开
    }
    

    5. toString

    对于一些浏览器,比如Chrome、FireFox,如果控制台输出的是对象,则保留对象的引用,每次打开开发者工具的时候都会重新调用一下对象的toString()方法将返回结果打印到控制台(console tab)上。

    所以只需要创建一个对象,重写它的toString()方法,然后在页面初始化的时候就将其打印在控制台上(这里假设控制台还没有打开),当用户打开控制台时会再去调用一下这个对象的toString()方法,用户打开控制台的行为就会被捕获到。

    缺点: 只能捕获到开发者工具处于关闭状态向打开状态转移的过程(先打开devtool再访问网页即可破解)

    var devtools = function() {};
    // var devtools = /./;
    devtools.toString = function() {
      if (!this.opened) {
        alert("Opened");
      }
      this.opened = true;
    }
    
    console.log('%c', devtools);
    

    不过使用这个在新版的 chrome 126.0.6478.127中貌似已经失效了, 我测试theajack/disable-devtool库只能使用窗口判断和性能判断两种方式可以触发这个版本的 chrome.

    三方库:

    1. theajack/disable-devtool

    github: theajack/disable-devtool: Disable web developer tools from the f12 button, right-click and browser menu (github.com)

    demo: Disable web developer tools with one line (theajack.github.io)

    使用的检测方法如下:

      RegToString = 0, // 根据正则检测
      DefineId, // 根据dom id检测
      Size, // 根据窗口尺寸检测
      DateToString, // 根据Date.toString 检测
      FuncToString, // 根据Function.toString 检测
      Debugger, // 根据断点检测,仅在ios chrome 真机情况下有效
      Performance, // 根据log大数据性能检测
    

    sgcc.com.cn 网站使用了这个库

    2. AEPKILL/devtools-detector

    使用了多种检查方式判断

    github: devtools-detector/src/index.ts at master · AEPKILL/devtools-detector (github.com)

    demo: https://blog.aepkill.com/demos/devtools-detector/

    other:

    讨论

  • 相关阅读:
    1. 带你玩转Java之Java基本概括
    【LeetCode】生命游戏
    kubernetes自定义hosts域名解析
    AI标注已达人类水平,RLHF或许将再不需要人类
    在windows上使用VSCode开发linux go程序,使用 Remote-SSH 扩展
    【七夕】七夕孤寡小青蛙究极版?七夕节最终章!
    python知识点的一些归纳
    delphi(XE2)实现图片异形窗体,支持摆放控件
    浏览器面试题及答案【集合目录】
    pip 问题
  • 原文地址:https://blog.csdn.net/qq_50969362/article/details/140407718