1.作用域
1.1 定于
作用域( scope)规定了变量能够被访问的“范围”,离开了这个“范围″变量使不能被访问
1.2 分类
1.2.1局部作用域
1.2.1.1 函数作用域
在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

1.2.1.2 块作用域
在 Javascript中使用仆}包裏的代码称为代码块,代码块内部声眀的变量外部将【有可能】无法被访问。


1.2.2全局作用域
| <script>标签和js文件的【最外层】就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。全局作用域中声明的变量,任何其它作用域都可以被访问 |

1.3 作用域链
作用域链本质上是底层的变量查找机制。
- 在函数被执行时,会优先查找当前函数作用域中查找变量
- 如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域

1.4 闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包=内层函数+外层函数的变量
先看个简单的代码:



1.5 变量提升

2.函数
2.1 函数的参数



2.2 箭头函数

| es6 -> js的新版本,新特性 |
| var fn=(形参) =>{函数体}; |
| fn(); |
| |
| var gn =a=>{}; |
| |
| var fn=(a,b)=>{ |
| return a+b; |
| } |
| var fn=(a,b)=>a+b; |
2.3 关于storage


2.4 关于promise



2.5 prototype


2.6 call和apply的应用

2.7 hook


2.7.1 页面最早加载代码Hook时机
在source里 用dom事件断点的script断点
然后刷新网页,就会断在第一个js标签,这时候就可以注入代码进行hook
监听 键盘 与 鼠标 事件
| |
| |
| |
| |
| |
| |
| |
| |
| |
| document.onkeydown = function() { |
| if (window.event && window.event.keyCode == 123) { |
| |
| event.keyCode = 0; |
| event.returnValue = false; |
| |
| window.close(); |
| window.location = "about:blank"; |
| } |
| } |
| ; |
| |
| document.oncontextmenu = function () { return false; }; |
| |
| |
| document.onmousedown = function(evt){ |
| |
| if(evt.button == 2){ |
| alert('监听到鼠标右键被按下') |
| evt.preventDefault() |
| return false; |
| } |
| } |
| |
| |
| |
| var h = window.innerHeight, w = window.innerWidth; |
| window.onresize = function(){ |
| alert('改变了窗口高度') |
| } |
| |
| |
| (function() { |
| |
| 'use strict'; |
| |
| Object.defineProperty(document, 'onselectstart', { |
| set: function(val) { |
| console.log('Hook捕获到选中设置->', val); |
| return val; |
| } |
| }); |
| |
| Object.defineProperty(document,'oncontextmenu',{ |
| set:function(evt){ |
| console.log("检测到右键点击"); |
| return evt |
| } |
| }); |
| })(); |
| |
webpack hook 半自动扣
| |
| |
| window.zhiyuan = f; |
| window.wbpk_ = ""; |
| window.isz = false; |
| f = function(r){ |
| if(window.isz) |
| { |
| |
| window.wbpk_ = window.wbpk_ + r.toString()+":"+(e[r]+"")+ ","; |
| } |
| return window.zhiyuan(r); |
| } |
| |
| |
| |
| |
| function o(t) { |
| |
| if (n[t]) |
| return n[t].exports; |
| var i = n[t] = { |
| i: t, |
| l: !1, |
| exports: {} |
| }; |
| console.log("被调用的 >>> ", e[t].toString()); |
| |
| |
| bb += `"${t}":${e[t].toString()},` |
| return e[t].call(i.exports, i, i.exports, o), |
| i.l = !0, |
| i.exports |
| } |
| bz = o; |
| |
如果只是调用模块,不用模块里面的方法, 那么直接获取调用模块的时候所有加载过的模块,进行拼接
document下的createElement()方法的hook,查看创建了什么元素
| (function() { |
| 'use strict' |
| var _createElement = document.createElement.bind(document); |
| document.createElement = function(elm){ |
| |
| if(elm == 'body'){ |
| debugger; |
| } |
| return _createElement(elm); |
| } |
| })(); |
之前我不知道我用的是 var _createElement = document.createElement 导致一直报错 Uncaught TypeError: Illegal invocation
原来是需要绑定一下对象 var _createElement = document.createElement.bind(document);
| |
| var code = function(){ |
| var org = window.XMLHttpRequest.prototype.setRequestHeader; |
| window.XMLHttpRequest.prototype.setRequestHeader = function(key,value){ |
| if(key=='Authorization'){ |
| debugger; |
| } |
| return org.apply(this,arguments); |
| } |
| } |
| var script = document.createElement('script'); |
| script.textContent = '(' + code + ')()'; |
| (document.head||document.documentElement).appendChild(script); |
| script.parentNode.removeChild(script); |
| |
请求hook 当请求的url里包含MmEwMD时,则插入断点
| |
| var code = function(){ |
| var open = window.XMLHttpRequest.prototype.open; |
| window.XMLHttpRequest.prototype.open = function (method, url, async){ |
| if (url.indexOf("MmEwMD")>-1){ |
| debugger; |
| } |
| return open.apply(this, arguments); |
| }; |
| } |
| var script = document.createElement('script'); |
| script.textContent = '(' + code + ')()'; |
| (document.head||document.documentElement).appendChild(script); |
| script.parentNode.removeChild(script); |
| |
docuemnt.getElementById 以及value属性的hook
| |
| document.getElementById = function(id) { |
| var value = document.querySelector('#' + id).value; |
| console.log('DOM操作 id: ', id) |
| try { |
| |
| Object.defineProperty(document.querySelector('#'+ id), 'value', { |
| get: function() { |
| console.log('getting -', id, 'value -', value); |
| return value; |
| }, |
| set: function(val) { |
| console.log('setting -', id, 'value -', val) |
| value = val; |
| } |
| }) |
| } catch (e) { |
| console.log('---------华丽的分割线--------') |
| } |
| return document.querySelector('#' + id); |
| } |
| |
| |
过debugger 阿布牛逼
| |
| function Closure(injectFunction) { |
| return function() { |
| if (!arguments.length) |
| return injectFunction.apply(this, arguments) |
| arguments[arguments.length - 1] = arguments[arguments.length - 1].replace(/debugger/g, ""); |
| return injectFunction.apply(this, arguments) |
| } |
| } |
| |
| var oldFunctionConstructor = window.Function.prototype.constructor; |
| window.Function.prototype.constructor = Closure(oldFunctionConstructor) |
| |
| window.Function.prototype.constructor.toString = oldFunctionConstructor.toString.bind(oldFunctionConstructor); |
| |
| var oldFunction = Function; |
| window.Function = Closure(oldFunction) |
| |
| window.Function.toString = oldFunction.toString.bind(oldFunction); |
| |
| var oldEval = eval; |
| window.eval = Closure(oldEval) |
| |
| window.eval.toString = oldEval.toString.bind(oldEval); |
| |
| |
| var oldGeneratorFunctionConstructor = Object.getPrototypeOf(function*() {}).constructor |
| var newGeneratorFunctionConstructor = Closure(oldGeneratorFunctionConstructor) |
| newGeneratorFunctionConstructor.toString = oldGeneratorFunctionConstructor.toString.bind(oldGeneratorFunctionConstructor); |
| Object.defineProperty(oldGeneratorFunctionConstructor.prototype, "constructor", { |
| value: newGeneratorFunctionConstructor, |
| writable: false, |
| configurable: true |
| }) |
| |
| |
| var oldAsyncFunctionConstructor = Object.getPrototypeOf(async function() {}).constructor |
| var newAsyncFunctionConstructor = Closure(oldAsyncFunctionConstructor) |
| newAsyncFunctionConstructor.toString = oldAsyncFunctionConstructor.toString.bind(oldAsyncFunctionConstructor); |
| Object.defineProperty(oldAsyncFunctionConstructor.prototype, "constructor", { |
| value: newAsyncFunctionConstructor, |
| writable: false, |
| configurable: true |
| }) |
| |
| |
| var oldSetAttribute = window.Element.prototype.setAttribute; |
| window.Element.prototype.setAttribute = function(name, value) { |
| if (typeof value == "string") |
| value = value.replace(/debugger/g, "") |
| |
| oldSetAttribute.call(this, name, value) |
| } |
| ; |
| var oldContentWindow = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "contentWindow").get |
| Object.defineProperty(window.HTMLIFrameElement.prototype, "contentWindow", { |
| get() { |
| var newV = oldContentWindow.call(this) |
| if (!newV.inject) { |
| newV.inject = true; |
| core.call(newV, globalConfig, newV); |
| } |
| return newV |
| } |
| }) |
| |
| |
过debugger—1 constructor 构造器构造出来的
| var _constructor = constructor; |
| Function.prototype.constructor = function(s) |
| |
| |
| |
| |
| return _constructor(s); |
| } |
| |
过debugger—2 eval的
| (function() { |
| 'use strict'; |
| var eval_ = window.eval; |
| window.eval = function(x) { |
| eval_(x.replace("debugger;", " ; ")); |
| } |
| ; |
| window.eval.toString = eval_.toString; |
| } |
| )(); |
| |
JSON HOOK
| var my_stringify = JSON.stringify; |
| JSON.stringify = function (params) { |
| |
| console.log("json_stringify params:",params); |
| return my_stringify(params); |
| }; |
| |
| var my_parse = JSON.parse; |
| JSON.parse = function (params) { |
| |
| console.log("json_parse params:",params); |
| return my_parse(params); |
| }; |
对象属性hook 属性自定义
| |
| (function(){ |
| |
| 'use strict' |
| |
| Object.defineProperty(document,'cookie',{ |
| |
| set: function(val){ |
| |
| debugger; |
| console.log('Hook捕获到set-cookie ->',val); |
| return val; |
| } |
| }) |
| })(); |
| |
cookies - 1 (不是万能的 有些时候hook不到 自己插入debugger)
| var cookie_cache = document.cookie; |
| |
| Object.defineProperty(document, 'cookie', { |
| get: function() { |
| console.log('Getting cookie'); |
| return cookie_cache; |
| }, |
| set: function(val) { |
| console.log("Seting cookie",val); |
| var cookie = val.split(";")[0]; |
| var ncookie = cookie.split("="); |
| var flag = false; |
| var cache = cookie_cache.split("; "); |
| cache = cache.map(function(a){ |
| if (a.split("=")[0] === ncookie[0]){ |
| flag = true; |
| return cookie; |
| } |
| return a; |
| }) |
| } |
| }) |
cookies - 2
| |
| var code = function(){ |
| var org = document.cookie.__lookupSetter__('cookie'); |
| document.__defineSetter__("cookie",function(cookie){ |
| if(cookie.indexOf('TSdc75a61a')>-1){ |
| debugger; |
| } |
| org = cookie; |
| }); |
| document.__defineGetter__("cookie",function(){return org;}); |
| } |
| var script = document.createElement('script'); |
| script.textContent = '(' + code + ')()'; |
| (document.head||document.documentElement).appendChild(script); |
| script.parentNode.removeChild(script); |
| |
| |
| |
window attr
| |
| |
| var window_flag_1 = "_t"; |
| var window_flag_2 = "ccc"; |
| |
| var key_value_map = {}; |
| var window_value = window[window_flag_1]; |
| |
| |
| Object.defineProperty(window, window_flag_1, { |
| get: function(){ |
| console.log("Getting",window,window_flag_1,"=",window_value); |
| |
| return window_value |
| }, |
| set: function(val) { |
| console.log("Setting",window, window_flag_1, "=",val); |
| |
| window_value = val; |
| key_value_map[window[window_flag_1]] = window_flag_1; |
| set_obj_attr(window[window_flag_1],window_flag_2); |
| }, |
| |
| }); |
| |
| function set_obj_attr(obj,attr){ |
| var obj_attr_value = obj[attr]; |
| Object.defineProperty(obj,attr, { |
| get: function() { |
| console.log("Getting", key_value_map[obj],attr, "=", obj_attr_value); |
| |
| return obj_attr_value; |
| }, |
| set: function(val){ |
| console.log("Setting", key_value_map[obj], attr, "=", val); |
| |
| obj_attr_value = val; |
| }, |
| }); |
| } |
eval/Function
| |
| window.__cr_eval = window.eval; |
| var myeval = function(src) { |
| |
| console.log(src); |
| console.log("========= eval end ==========="); |
| return window.__cr_eval; |
| } |
| |
| var _myeval = myeval.bind(null); |
| _myeval.toString = window.__cr_eval.toString; |
| Object.defineProperty(window, 'eval',{value: _myeval}); |
| |
| window._cr_fun = window.Function |
| var myfun = function(){ |
| var args = Array.prototype.slice.call(arguments, 0, -1).join(","), src = arguments[arguments.lenght -1]; |
| console.log(src); |
| console.log("======== Function end ============="); |
| return window._cr_fun.apply(this, arguments) |
| } |
| |
| myfun.toString = function() {return window._cr_fun + ""} |
| Object.defineProperty(window, "Function",{value: myfun}) |
eval 取返回值
| _eval = eval; |
| eval = (res)=>{ |
| res1 = res |
| return _eval(res) |
| } |
| |
| eval(xxxxxxxxx) |
| |
| eval = new Proxy(eval,{ |
| |
| |
| apply: (target,_,arg)=>{ |
| |
| |
| console.log(arg[0]) |
| } |
| }) |
| |
| |
| |
| eval( |
| (function(){return "我是包子 自己执行了"})() |
| ) |
| |
| |
| |
websocket hook
| |
| var my_stringify = JSON.stringify; |
| JSON.stringify = function (params) { |
| |
| console.log("json_stringify params:",params); |
| return my_stringify(params); |
| }; |
| |
| var my_parse = JSON.parse; |
| JSON.parse = function (params) { |
| |
| console.log("json_parse params:",params); |
| return my_parse(params); |
| }; |
| |
| |
| |
| window._WebSocket = window.WebSocket; |
| |
| |
| window._WebSocket.prototype.send = function (data) { |
| console.info("Hook WebSocket", data); |
| return this.send(data) |
| } |
| |
| Object.defineProperty(window, "WebSocket",{value: WebSocket}) |
| |
hook 正则 —— 1
| (function () { |
| var _RegExp = RegExp; |
| RegExp = function (pattern, modifiers) { |
| console.log("Some codes are setting regexp"); |
| debugger; |
| if (modifiers) { |
| return _RegExp(pattern, modifiers); |
| } else { |
| return _RegExp(pattern); |
| } |
| }; |
| RegExp.toString = function () { |
| return "function setInterval() { [native code] }" |
| }; |
| })(); |
| |
hook 正则 2 加在sojson头部过字符串格式化检测
| (function() { |
| var _RegExp = RegExp; |
| RegExp = function(pattern, modifiers) { |
| if (pattern == decodeURIComponent("%5Cw%2B%20*%5C(%5C)%20*%7B%5Cw%2B%20*%5B'%7C%22%5D.%2B%5B'%7C%22%5D%3B%3F%20*%7D") || pattern == decodeURIComponent("function%20*%5C(%20*%5C)") || pattern == decodeURIComponent("%5C%2B%5C%2B%20*(%3F%3A_0x(%3F%3A%5Ba-f0-9%5D)%7B4%2C6%7D%7C(%3F%3A%5Cb%7C%5Cd)%5Ba-z0-9%5D%7B1%2C4%7D(%3F%3A%5Cb%7C%5Cd))") || pattern == decodeURIComponent("(%5C%5C%5Bx%7Cu%5D(%5Cw)%7B2%2C4%7D)%2B")) { |
| pattern = '.*?'; |
| console.log("发现sojson检测特征,已帮您处理。") |
| } |
| if (modifiers) { |
| console.log("疑似最后一个检测...已帮您处理。") |
| console.log("已通过全部检测,请手动处理debugger后尽情调试吧!") |
| return _RegExp(pattern, modifiers); |
| } else { |
| return _RegExp(pattern); |
| } |
| } |
| ; |
| RegExp.toString = function() { |
| return _RegExp.toString(); |
| } |
| ; |
| } |
| )(); |
| |
hook canvas (定位图片生成的地方)
| (function() { |
| 'use strict'; |
| let create_element = document.createElement.bind(doument); |
| |
| document.createElement = function (_element) { |
| console.log("create_element:",_element); |
| if (_element === "canvas") { |
| debugger; |
| } |
| return create_element(_element); |
| } |
| })(); |
setInterval 定时器
| (function() { |
| setInterval_ = setInterval; |
| console.log("原函数已被重命名为setInterval_") |
| setInterval = function() {} |
| ; |
| setInterval.toString = function() { |
| console.log("有函数正在检测setInterval是否被hook"); |
| return setInterval_.toString(); |
| } |
| ; |
| } |
| )(); |
| |
setInterval 循环清除定时器
| for(var i = 0; i < 9999999; i++) window.clearInterval(i) |
console.log 检测例子 (不让你输出调试)
| var oldConsole = ["debug", "error", "info", "log", "warn", "dir", "dirxml", "table", "trace", "group", "groupCollapsed", "groupEnd", "clear", "count", "countReset", "assert", "profile", "profileEnd", "time", "timeLog", "timeEnd", "timeStamp", "context", "memory"].map(key=>{ |
| var old = console[key]; |
| console[key] = function() {} |
| ; |
| console[key].toString = old.toString.bind(old) |
| return old; |
| } |
| ) |
检测函数是否被hook例子
| if (window.eval == 'native code') { |
| console.log('发现eval函数被hook了 开始死循环'); |
| } |
模拟sleep函数,实现Date的时间增加
| var saf, saf_class; |
| !function() { |
| var v = console.log |
| , n = Function |
| , t = "prototype" |
| , e = "toString" |
| , o = n[e] |
| , i = Symbol("(".concat("", ")_", (Math.random() + "")[e](36))) |
| , c = function() { |
| try { |
| return "function" == typeof this && this[i] || o.call(this); |
| } catch (n) { |
| return v("[ERROR toString]", this + ''), |
| ""; |
| } |
| }; |
| function r(n, t, e) { |
| Object.defineProperty(n, t, { |
| enumerable: !1, |
| configurable: !0, |
| writable: !0, |
| value: e |
| }); |
| } |
| delete n[t][e], |
| r(n[t], e, c), |
| r(n[t][e], i, "function toString() { [native code] }"), |
| saf = function(n, m) { |
| return r(n, i, `function ${m ? m : n.name || ""}() { [native code] }`), |
| n; |
| } |
| ; |
| }(); |
| |
| var v_Date = Date |
| var sleep_number = 0 |
| function sleep(number) { |
| sleep_number += number; |
| Date = function(_Date) { |
| var bind = Function.bind; |
| var unbind = bind.bind(bind); |
| function instantiate(constructor, args) { |
| return new (unbind(constructor, null).apply(null, args)); |
| } |
| var names = Object.getOwnPropertyNames(_Date); |
| for (var i = 0; i < names.length; i++) { |
| if (names[i]in Date) |
| continue; |
| var desc = Object.getOwnPropertyDescriptor(_Date, names[i]); |
| Object.defineProperty(Date, names[i], desc); |
| } |
| function Date() { |
| var date = instantiate(_Date, [v_Date.now() + sleep_number]); |
| |
| return date; |
| } |
| Date.prototype = _Date.prototype |
| return saf(Date); |
| }(v_Date); |
| } |
| |
hook Array.concat
| BaseArrayConcat = Array.prototype.concat |
| |
| hook_concat = function(a){ |
| console.log('concat-hook:', JSON.stringify(a)) |
| let result = BaseArrayConcat.apply(this, a); |
| result.concat = hook_concat; |
| return result |
| } |
| ce.concat = hook_concat |
| |
控制台检测
| var _0x383ee0 = new Date(); |
| |
| var _0x465be6 = 0; |
| |
| _0x383ee0["toString"] = function () { |
| _0x465be6++; |
| console.log(arguments[0]) |
| if (_0x465be6 == 2) { |
| return ""; |
| } |
| }; |
| |
| console["log"](_0x383ee0); |
2.8 jsonp
| |
| obj = re .compile(r"\(?P<code>.*)\)",re.S) |
| code = obj .search(resp.text).group('code') |
| print(json.loads(code)) |

2.9 axios

【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2023-08-07 爬爬《五》:爬虫入门与urllib&requests
2021-08-07 如何用ajax 实现点击下拉框传值到后台并返回页面渲染