devtools-detector 反hook 反检测 源码实现

devtool-detector 项目

检测手段

  • function.toString, regexp.toString()等(详细见他的源码)

效果

image

nop掉检测

  • 将以下代码注入到浏览器最前面执行即可

const originalSymbol =  Symbol('hookMethod');
    // copy original function 
    function copyFunction(fn){
        return typeof fn === "function" && Object.create(fn).__proto__;
    }
    function hookMethod(object, prop, newHandler){
       const originalHandler =  copyFunction(object[prop]);
       if (!originalHandler) return;
       newHandler[originalSymbol] = originalHandler;
       object[prop] = function(){
            return newHandler.apply(this, arguments);
       };
    }
    const methods = ['debug', 'info', 'log', 'error', 'table', 'dir'];
    methods.forEach(key=>{
        hookMethod(console, key, function handler(fn){
            if(typeof fn === "function" && fn.name === "devtoolsTestFunction"){
                handler[originalSymbol]("function devtoolsTestFunction.toString() get called")
                return;
            }
            /*
            \src\checkers\performance.checker.ts
            大数组打印耗时检测, 如果不打开控制台, 耗时直接为0了
            这里发现是大数组后先返回,然后setTimeout执行打印。
            既避开了检测,又可以正常打印。
            */
            if (Array.isArray(fn) && fn.length === 50){
                setTimeout(function(){
                    return handler[originalSymbol].apply(this, arguments);
                });
                return
            }
            return handler[originalSymbol].apply(this, arguments);
            
        })
    });



    // disable console.clear function call

    hookMethod(console, "clear", function(){

    });
    /*
    动态构造debugger检测
    */
    hookMethod(Function.prototype, "constructor", function handler(code){
        arguments[0] = code.replace("debugger", "")
        return handler[originalSymbol].apply(this,arguments );
    });

    hookMethod(window, "eval", function handler(code){
        arguments[0] = code.replace("debugger")
        return handler[originalSymbol].apply(this,arguments );
    });

    /*
    reg.toString 检测
    */
    Object.defineProperty(RegExp.prototype, "toString", {
        set(val){
            /*
            由于打包工具的存在,这里实际的代码可能会有变化, 重写 RegExp.prototype.toString 极为少见,这里选择nop掉
            */ 
        }
    })

    /*
    date.toString 检测
    */
 
    Object.defineProperty(Date.prototype, "toString", {
 
        set(handler){
            /*
            new Date().toString() 还是蛮常用的(自定义formatter啥的),所以这里不能nop 掉, 但目前没啥好方法,先nop吧

            */
        }
    })

posted @ 2025-04-04 09:33  re大法好  阅读(143)  评论(0)    收藏  举报