diff --git a/.gitignore b/.gitignore index 144efaa72..0086a5a21 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,10 @@ yarn-error.log # vscode .vscode -#yarn +# idea +.idea + +# yarn yarn.lock # vuepress diff --git "a/docs/05.\350\204\232\346\234\254\345\221\275\344\273\244/01.\350\276\205\345\212\251\350\204\232\346\234\254/01.JS HOOK.md" "b/docs/05.\350\204\232\346\234\254\345\221\275\344\273\244/01.\350\276\205\345\212\251\350\204\232\346\234\254/01.JS HOOK.md" index d4838345b..472a056ac 100644 --- "a/docs/05.\350\204\232\346\234\254\345\221\275\344\273\244/01.\350\276\205\345\212\251\350\204\232\346\234\254/01.JS HOOK.md" +++ "b/docs/05.\350\204\232\346\234\254\345\221\275\344\273\244/01.\350\276\205\345\212\251\350\204\232\346\234\254/01.JS HOOK.md" @@ -5,9 +5,22 @@ permalink: /pages/js-hook article: false --- +::: details 什么是 Hook? +Hook 中文译为钩子,在程序中可以将其理解为“劫持”,我们可以通过 Hook 技术来劫持某个对象,把这个对象的程序拉出来替换成我们自己改写的代码片段,修改参数或替换返回值,从而控制它与其他对象的交互。 + +
+通俗来讲,Hook 其实就是拦路打劫,马邦德带着老婆,出了城,吃着火锅,还唱着歌,突然就被麻匪劫了,张麻子劫下县长马邦德的火车,摇身一变化身县长,带着手下赶赴鹅城上任。Hook 的过程,就是张麻子顶替马邦德的过程。 + +![](https://z1.ax1x.com/2023/11/02/piKZdwd.png) +::: + +::: warning +收录的 Hook 脚本有限,若需要 Hook 其他函数,可参考 [MDN Web API](https://developer.mozilla.org/zh-CN/docs/Web/API) 自行编写。 +::: + ## Hook Cookie -::: danger 注意 +::: danger 不推荐方法二,部分特性可能正准备或者已经从相关的 web 标准中移除,参考文档:[MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__) ::: @@ -15,7 +28,7 @@ article: false ```javascript (function () { - var cookieCache = ""; + let cookieCache = ""; Object.defineProperty(document, "cookie", { set: function (val) { console.log("Hook set cookie => ", val); @@ -36,7 +49,7 @@ article: false ```javascript (function () { - var cookieCache = document.cookie.__lookupSetter__("cookie"); + let cookieCache = document.cookie.__lookupSetter__("cookie"); document.__defineSetter__("cookie", function (val) { console.log("Hook set cookie => ", val); if (val.indexOf("spiderapi.cn") !== -1) { @@ -56,7 +69,7 @@ article: false ```javascript (function () { - var headerCache = window.XMLHttpRequest.prototype.setRequestHeader; + let headerCache = window.XMLHttpRequest.prototype.setRequestHeader; window.XMLHttpRequest.prototype.setRequestHeader = function (key, value) { console.log("Hook set header %s => %s", key, value); if (key === "spiderapi.cn") { @@ -69,14 +82,18 @@ article: false ## Hook Debugger +::: tip +无限 debugger 生成的形式比较多样,常见于构造函数、定时器和 eval 里,可根据实际场景进行调整。 +::: + ```javascript (function () { - var constructorCache = Function.prototype.constructor; + let constructorCache = Function.prototype.constructor; Function.prototype.constructor = function (string) { if (string === "debugger") { - console.log("Hook constructor debugger!") + console.log("Hook constructor debugger!"); return function () {}; } return constructorCache(string); @@ -88,13 +105,13 @@ article: false ```javascript (function () { - var setIntervalCache = setInterval + let setIntervalCache = setInterval; setInterval = function (func, delay) { if (func.toString().indexOf("debugger") !== -1) { - console.log("Hook setInterval debugger!") + console.log("Hook setInterval debugger!"); return function () {}; } - return setIntervalCache(func, delay) + return setIntervalCache(func, delay); }; })(); ``` @@ -103,10 +120,10 @@ article: false ```javascript (function () { - var setTimeoutCache = setTimeout; + let setTimeoutCache = setTimeout; setTimeout = function (func, delay) { if (func.toString().indexOf("debugger") !== -1) { - console.log("Hook setTimeout debugger!") + console.log("Hook setTimeout debugger!"); return function () {}; } return setTimeoutCache(func, delay); @@ -118,10 +135,10 @@ article: false ```javascript (function () { - var evalCache = window.eval; + let evalCache = window.eval; window.eval = function (string) { - if(string.includes("debugger")){ - console.log("Hook eval debugger!") + if (string.includes("debugger")) { + console.log("Hook eval debugger!"); } return evalCache(string.replace(/debugger\s*;?/g, "")); }; @@ -137,8 +154,8 @@ article: false ```javascript (function () { - var openCache = window.XMLHttpRequest.prototype.open; - window.XMLHttpRequest.prototype.open = function(method, url) { + let openCache = window.XMLHttpRequest.prototype.open; + window.XMLHttpRequest.prototype.open = function (method, url) { console.log("Hook xhr method => %s, url => %s", method, url); if (url.indexOf("spiderapi.cn") !== -1) { debugger; @@ -151,58 +168,60 @@ article: false ## Hook fetch ```javascript -(function() { - var fetchCache = Object.getOwnPropertyDescriptor(window, "fetch") +(function () { + let fetchCache = Object.getOwnPropertyDescriptor(window, "fetch"); Object.defineProperty(window, "fetch", { value: function (url) { - console.log("Hook fetch url => ", url) + console.log("Hook fetch url => ", url); debugger; - return fetchCache.value.apply(this, arguments) + return fetchCache.value.apply(this, arguments); } - }) + }); })(); ``` ## Hook JSON.stringify ```javascript -(function() { - var stringifyCache = JSON.stringify; - JSON.stringify = function(params) { +(function () { + let stringifyCache = JSON.stringify; + JSON.stringify = function (params) { console.log("Hook JSON.stringify => ", params); debugger; return stringifyCache(params); - } + }; })(); ``` ## Hook JSON.parse ```javascript -(function() { - var parseCache = JSON.parse; - JSON.parse = function(params) { +(function () { + let parseCache = JSON.parse; + JSON.parse = function (params) { console.log("Hook JSON.parse => ", params); debugger; return parseCache(params); - } + }; })(); ``` ## Hook Function +::: tip 以下代码执行后,所有的函数操作都会在控制台打印输出将要执行的 JS 源码。 +::: ```javascript -(function() { +(function () { let FunctionCache = window.Function; - let newFunction = function() { + let newFunction = function () { let src = arguments[arguments.length - 1]; console.log("Hook Function => ", src); debugger; return FunctionCache.apply(this, arguments); }; - newFunction.toString = function() { + newFunction.toString = function () { return FunctionCache.toString(); }; })(); @@ -211,11 +230,11 @@ article: false ## Hook WebSocket ```javascript -(function() { +(function () { let sendCache = WebSocket.prototype.send; - WebSocket.prototype.send = function (data){ + WebSocket.prototype.send = function (data) { console.info("Hook WebSocket send => ", data); - return sendCache(data) + return sendCache(data); }; })(); ``` @@ -223,35 +242,39 @@ article: false ## Hook String.prototype.split ```javascript -String.prototype.splitCache = String.prototype.split; -String.prototype.split = function(separator, limit){ - console.log("Hook String.prototype.split separator => %s, limit => %s", separator, limit); - str = this.toString(); - if(str.includes("spiderapi.cn")) { - debugger; - } - return str.splitCache(separator, limit) -} +(function () { + String.prototype.splitCache = String.prototype.split; + String.prototype.split = function (separator, limit) { + console.log("Hook String.prototype.split separator => %s, limit => %s", separator, limit); + let str = this.toString(); + if(str.includes("spiderapi.cn")) { + debugger; + } + return str.splitCache(separator, limit) + }; +})(); ``` ## Hook console ```javascript -consoleCache = console.log -console.log = function(msg) { - consoleCache("Hook console.log =>", msg); - if(msg === "spiderapi.cn") { - debugger; - } - consoleCache(msg) -} +(function () { + let consoleCache = console.log; + console.log = function (msg) { + consoleCache("Hook console.log =>", msg); + if(msg === "spiderapi.cn") { + debugger; + } + consoleCache(msg); + }; +})(); ``` ## Hook eval ```javascript (function () { - var evalCache = window.eval; + let evalCache = window.eval; window.eval = function (string) { console.log("Hook eval =>", string); debugger; @@ -263,28 +286,18 @@ console.log = function(msg) { })(); ``` -## Hook setInterval +## Hook onbeforeunload -```javascript -(function () { - var setIntervalCache = setInterval; - setInterval = function (func, delay) { - console.log("Hook setInterval func => %s, delay => %s", func, delay); - debugger; - return setIntervalCache(func, delay); - }; -})(); -``` - -## Hook setTimeout +::: tip +onbeforeunload 事件在即将离开当前页面(刷新或关闭)时触发。Hook 此事件可阻断跳转,使其留在当前页面,通常用来应对网站打开 F12 就跳转页面的情况。 +::: ```javascript (function () { - var setTimeoutCache = setTimeout; - setTimeout = function (func, delay) { - console.log("Hook setTimeout func => %s, delay => %s", func, delay); + window.onbeforeunload = function () { + console.log("Hook window.onbeforeunload."); debugger; - return setTimeoutCache(func, delay); + return false; }; })(); ``` @@ -294,7 +307,7 @@ console.log = function(msg) { ```javascript (function () { let RegExpCache = RegExp; - RegExp = function(pattern, flags) { + RegExp = function (pattern, flags) { console.log("Hook RegExp pattern => %s, flags => %s", pattern, flags); debugger; return RegExpCache(pattern, flags); @@ -305,9 +318,9 @@ console.log = function(msg) { ## Hook Canvas ```javascript -(function() { +(function () { let createElementCache = document.createElement; - document.createElement = function(tagName) { + document.createElement = function (tagName) { console.info("Hook createElement tagName => ", tagName); if(tagName === "canvas") { debugger; @@ -320,9 +333,9 @@ console.log = function(msg) { ## Hook createElement ```javascript -(function() { - var createElementCache = document.createElement; - document.createElement = function(tagName) { +(function () { + let createElementCache = document.createElement; + document.createElement = function (tagName) { console.info("Hook createElement tagName => ", tagName); if(tagName === "div") { debugger; @@ -335,11 +348,11 @@ console.log = function(msg) { ## Hook getElementById ```javascript -(function() { - var getElementByIdCache = document.getElementById; - document.getElementById = function(id) { +(function () { + let getElementByIdCache = document.getElementById; + document.getElementById = function (id) { console.info("Hook getElementById id => ", id); - if(id === "spiderapi") { + if (id === "spiderapi") { debugger; } return getElementByIdCache(id); @@ -350,11 +363,11 @@ console.log = function(msg) { ## Hook setAttribute ```javascript -(function() { - var setAttributeCache = window.Element.prototype.setAttribute; - window.Element.prototype.setAttribute = function(name, value) { +(function () { + let setAttributeCache = window.Element.prototype.setAttribute; + window.Element.prototype.setAttribute = function (name, value) { console.info("Hook setAttribute name => %s, value => %s", name, value); - if(name === "spiderapi") { + if (name === "spiderapi") { debugger; } return setAttributeCache(name, value); @@ -362,6 +375,32 @@ console.log = function(msg) { })(); ``` +## Hook setInterval + +```javascript +(function () { + let setIntervalCache = setInterval; + setInterval = function (func, delay) { + console.log("Hook setInterval func => %s, delay => %s", func, delay); + debugger; + return setIntervalCache(func, delay); + }; +})(); +``` + +## Hook setTimeout + +```javascript +(function () { + let setTimeoutCache = setTimeout; + setTimeout = function (func, delay) { + console.log("Hook setTimeout func => %s, delay => %s", func, delay); + debugger; + return setTimeoutCache(func, delay); + }; +})(); +``` + ## 清除定时器 ```javascript @@ -371,19 +410,19 @@ for (let i = 1; i < 99999; i++) window.clearInterval(i); ## Hook 固定随机变量 ```javascript -(function() { +(function () { let timeNow = 1697906773742; Date.now = function now() { return timeNow }; Date.parse = function () { return timeNow }; Date.prototype.valueOf = function () { return timeNow }; Date.prototype.getTime = function () { return timeNow }; Date.prototype.toString = function () { return timeNow }; - Performance.prototype.now = function now(){ return Number((timeNow + "").slice(8))} + Performance.prototype.now = function now() { return Number((timeNow + "").slice(8))}; Math.random = function random() { return 0.08636862211354912 }; - window.crypto.getRandomValues = function getRandomValues(array32, ...args){ + window.crypto.getRandomValues = function getRandomValues(array32, ...args) { return array32 - } + }; })(); ``` @@ -391,10 +430,10 @@ for (let i = 1; i < 99999; i++) window.clearInterval(i); ```javascript (function () { - var oldFunc = func; - func = function(arguments){ - console.log(arguments) - return oldFunc.apply(arguments) + let oldFunc = func; + func = function (arguments) { + console.log(arguments); + return oldFunc.apply(arguments); }; })(); ``` \ No newline at end of file