// ==UserScript== // @name 逆向脚本工具 // @license false // @namespace https://bbs.tampermonkey.net.cn/ // @version 1.2.1 // @description 逆向脚本工具js逆向,支持菜单控制解除无限debug和F12限制 // @author manji // @require https://scriptcat.org/lib/637/1.3.0/ajaxHooker.js // @require https://scriptcat.org/lib/721/1.0.1/gmCookie.js // @require https://scriptcat.org/lib/513/2.1.0/ElementGetter.js // @require https://fastapi.work321.cn/apps1/js/package/JsBarcode.all.min.js // @require https://fastapi.work321.cn/apps1/js/pingduoduo/res_anti-content.js // @match http*://*/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_cookie // @run-at document-start // @connect pinduoduo.com // ==/UserScript== /* ==UserConfig== hook配置: header_name: title: Header Name description: 请输入需要hook的Header名称 type: text default: "X-Requested-With" json_stringify操作: title: JSON Stringify description: 是否启用JSON Stringify的hook操作 type: switch default: false json_parse操作: title: JSON Parse description: 是否启用JSON Parse的hook操作 type: switch default: false javascript_eval: title: Javascript Eval description: 是否启用Javascript Eval的hook操作 type: switch default: false function_hook: title: Function Hook description: 是否启用Function Hook的hook操作 type: switch default: false url_hook: title: URL Hook description: 是否启用URL Hook的hook操作 type: text default: cookie_hook: title: Cookie Hook description: 是否启用Cookie Hook的hook操作 type: text default: disable_infinite_debug: title: 解除无限 Debugger description: 启用后自动绕过 debugger 反调试(如无限断点) type: switch default: true enable_devtools: title: 解除 F12 / DevTools 限制 description: 启用后恢复右键、F12、Ctrl+Shift+I 等开发者工具功能 type: switch default: true ==/UserConfig== */ (function () { 'use strict'; // hook教程:https://mp.weixin.qq.com/s/E99i02-2ZzkIBH1mcX8q_A // ============================== // 🔓 解除无限 debugger(可选) // ============================== const disableInfiniteDebug = GM_getValue('hook配置.disable_infinite_debug', true); if (disableInfiniteDebug) { (function () { // 覆盖 eval const originalEval = window.eval; window.eval = function (src) { if (typeof src === 'string') { src = src.replace(/debugger;?/g, ''); } return originalEval(src); }; // 覆盖 Function 构造器 const originalFunction = window.Function; window.Function = function (...args) { if (args.length > 0) { const lastArg = args[args.length - 1]; if (typeof lastArg === 'string') { args[args.length - 1] = lastArg.replace(/debugger;?/g, ''); } } return originalFunction.apply(this, args); }; // 屏蔽包含 debugger 的 setTimeout/setInterval const wrapTimer = (origTimer) => function (fn, delay, ...rest) { if (typeof fn === 'function') { const str = fn.toString(); if (str.includes('debugger')) { // 创建一个无 debugger 的新函数 const cleanStr = str.replace(/debugger;?/g, ''); try { fn = new Function(...(cleanStr.match(/function\s*\(([^)]*)\)/)?.[1]?.split(',')?.map(s => s.trim()) || []), cleanStr.replace(/^[^{]*{|}$/g, '')); } catch (e) { // 若无法解析,直接跳过执行 return; } } } return origTimer.call(this, fn, delay, ...rest); }; window.setTimeout = wrapTimer(window.setTimeout); window.setInterval = wrapTimer(window.setInterval); })(); } // ============================== // 🛠️ 解除 F12 / DevTools 限制(可选) // ============================== const enableDevTools = GM_getValue('hook配置.enable_devtools', true); if (enableDevTools) { (function () { // 恢复快捷键 document.addEventListener('keydown', function (e) { // F12 if (e.keyCode === 123) { e.stopImmediatePropagation(); e.preventDefault(); return false; } // Ctrl+Shift+I / J if (e.ctrlKey && e.shiftKey && (e.keyCode === 73 || e.keyCode === 74)) { e.stopImmediatePropagation(); e.preventDefault(); return false; } // Ctrl+U if (e.ctrlKey && e.keyCode === 85) { e.stopImmediatePropagation(); e.preventDefault(); return false; } }, true); // 使用捕获阶段,优先拦截 // 恢复右键、选择、复制等 document.oncontextmenu = null; document.onselectstart = null; document.ondragstart = null; document.oncopy = null; document.oncut = null; document.onpaste = null; // 清理常见反调试钩子 window.onerror = null; window.onbeforeunload = null; })(); } // Cookie Hook 用于定位 Cookie 中关键参数生成位置, // 以下代码演示了当 Cookie 中匹配到了 __dfp 关键字, 则插入断点: cookie_hook = GM_getValue('hook配置.cookie_hook',''); if(cookie_hook){ cookie_name = cookie_hook.toString().trim(); const origDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') || Object.getOwnPropertyDescriptor(document.__proto__.constructor.prototype, 'cookie'); const originalGetter = origDescriptor.get; const originalSetter = origDescriptor.set; Object.defineProperty(document, 'cookie', { configurable: false, enumerable: true, get: function() { return originalGetter.call(document); }, set: function(val) { if (val.toLowerCase().includes(cookie_name.toLowerCase())) { debugger; } console.log('Set Cookie:', val); return originalSetter.call(document, val); } }); }; // URL Hook 用于定位请求 URL 中关键参数生成位置, // 以下代码演示了当请求的 URL 里包含 login 关键字时,则插入断点 url_hook = GM_getValue('hook配置.url_hook',''); console.log('URL的Hook操作:',url_hook); if(url_hook){ url_hook = url_hook.toString().trim().toLowerCase(); var open = window.XMLHttpRequest.prototype.open; window.XMLHttpRequest.prototype.open = function (method, url, async) { if (url.toLowerCase().indexOf(url_hook) != 1) { debugger; } return open.apply(this, arguments); }; }; // function_hook 以下代码执行后,所有的函数操作都会在控制台打印输出将要执行的 JS 源码: function_hook = GM_getValue('hook配置.function_hook','') console.log('function的hook操作:',function_hook); if(function_hook==true){ // 保存原始方法 window.__cr_fun = window.Function; // 重写 function var myfun = function() { var args = Array.prototype.slice.call(arguments, 0, -1).join(","), src = arguments[arguments.length - 1]; console.log(src); console.log("=============== Function end ==============="); debugger; returnwindow.__cr_fun.apply(this, arguments); } // 屏蔽js中对原生函数native属性的检测 myfun.toString = function() { returnwindow.__cr_fun + "" } Object.defineProperty(window, 'Function', { value: myfun }); }; // JavaScript eval() 函数的作用是计算 JavaScript 字符串,并把它作为 脚本代码来执行。 // 如果参数是一个表达式,eval() 函数将执行表达式。 // 如果参数是 Javascript 语句,eval() 将执行 Javascript 语句,经常被用来动态执行 JS。 // 以下代码执行后,之后所有的 eval() 操作都会在控制台打印输出将要执行的 JS 源码: javascript_eval = GM_getValue('hook配置.javascript_eval','') console.log('javascript_eval的hook操作:',javascript_eval); if(javascript_eval == true){ // 保存原始方法 window.__cr_eval = window.eval; // 重写 eval var myeval = function(src) { console.log(src); console.log("=============== eval end ==============="); debugger; returnwindow.__cr_eval(src); } // 屏蔽 JS 中对原生函数 native 属性的检测 var _myeval = myeval.bind(null); _myeval.toString = window.__cr_eval.toString; Object.defineProperty(window, 'eval', { value: _myeval }); }; // JSON.parse() 方法用于将一个 JSON 字符串转换为对象,在某些站点的加密过程中可能会遇到, // 以下代码演示了遇到 JSON.parse() 时,则插入断点: json_pars = GM_getValue('hook配置.json_parse操作',''); console.log('json_pars的hook操作:',json_pars); if(json_pars == true){ var parse = JSON.parse; JSON.parse = function(params) { console.log("Hook JSON.parse ——> ", params); debugger; return parse(params); } }; // JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串,在某些站点的加密过程中可能会遇到, // 以下代码演示了遇到 JSON.stringify() 时,则插入断点 json_stringify = GM_getValue('hook配置.json_stringify操作',''); console.log('json_stringify的hook操作:',json_stringify); if(json_stringify == true){ var stringify = JSON.stringify; JSON.stringify = function(params) { console.log("Hook JSON.stringify ——> ", params); debugger; return stringify(params); } }; // Header Hook 用于定位 Header 中关键参数生成位置 // headers_hook = GM_getValue('hook配置.headers_hook','').toString().trim(); header_name = GM_getValue('hook配置.header_name','') console.log("header需要hook的字段名称:",header_name); if( header_name){ header_name = header_name.toString().trim().toLowerCase(); var org = window.XMLHttpRequest.prototype.setRequestHeader; window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) { if (key.toLowerCase() == header_name) {debugger;}; // if(key.indexOf(header_name) != 1){debugger;}; console.log("header_name:",key,"-->>","value:",value); return org.apply(this, arguments); }; } })()