Hook 是一种钩子技术,在系统没有调用函数之前,钩子程序就先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,也可以强制结束消息的传递。简单来说,修改原有的 JS 代码就是 Hook。
Hook 技术之所以能够实现有两个条件:
**注意:**JS 变量是有作用域的,只有当被 hook 函数和 debugger 断点在同一个作用域的时候,才能 hook 成功。
1、寻找hook入口
2、编写hook逻辑
3、调试
注:最常用的是hook cookie
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串,在某些站点的加密过程中可能会遇到,以下代码演示了遇到 JSON.stringify() 时,则插入断点:
(function() {
var stringify = JSON.stringify;
JSON.stringify = function(params) {
console.log("Hook JSON.stringify ——> ", params);
debugger;
return stringify(params);
}
})();
定义了一个变量 open
保留原始 XMLHttpRequest.open
方法,然后重写 XMLHttpRequest.open
方法
(function () {
var open = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, url, async) {
if (url.indexOf("analysis") != -1) {
debugger;
}
return open.apply(this, arguments);
};
})();
Interceptors-拦截器
// npm install axios
axios = require('axios')
//设置请求拦截器
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功')
config.timeout = 2000; //修改请求config
config.headers['sign'] = 'lili'
return config;
}, function (error) {
console.log('请求拦截器 失败')
return Promise.reject(error);
});
//设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功')
console.log('调解密函数进行解密数据')
//return response;
return response.data; //修改响应数据
}, function (error) {
console.log('响应拦截器 失败')
return Promise.reject(error);
});
//发送请求
axios.get('http://httpbin.org/get').then(res=>console.log(res))
XMLHttpRequest
XMLHttpRequest
(XHR)对象用于与服务器交互。通过 XMLHttpRequest 可以在不刷新页面的情况下请求特定 URL,获取数据。这允许网页在不影响用户操作的情况下,更新页面的局部内容。XMLHttpRequest
在 AJAX 编程中被大量使用。
方法初始化一个新创建的请求,或重新初始化一个请求。
xhrReq.open(method, url, async);
发送请求。如果请求是异步的(默认),那么该方法将在请求发送后立即返回。
方法接受一个可选的参数,其作为请求主体;如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null。
xhrReq.send(body)
XMLHttpRequest.setRequestHeader()
设置 HTTP 请求头的值。必须在 open()
之后、send()
之前调用 setRequestHeader()
方法。
myReq.setRequestHeader(header, value); // headers['key'] = value
XMLHttpRequest.onreadystatechange
当 readyState
属性发生变化时,调用的事件处理器。
var xhr= new XMLHttpRequest(),
method = "GET",
url = "https://developer.mozilla.org/";
xhr.open(method, url, true);
xhr.onreadystatechange = function () {
if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
console.log(xhr.responseText)
}
}
xhr.send();
WEBAPI
地址:https://developer.mozilla.org/zh-CN/docs/Web/API
Object.defineProperty
为对象的属性赋值,替换对象属性
基本语法:Object.defineProperty(obj, prop, descriptor)
,它的作用就是直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,接收的三个参数含义如下:
obj
:需要定义属性的当前对象;
prop
:当前需要定义的属性名;
Object.defineProperty(user,"age",{
get:function(){
console.log("这个人来获取值了!!");
return count;
},
set:function(newVal){
console.log("这个人来设置值了!!");
count=newVal+1;
}
})
cookie 示范
示范例子:http://q.10jqka.com.cn/
cookie 钩子用于定位 cookie 中关键参数生成位置,以下代码演示了当 cookie 中匹配到了 v
, 则插入断点:
(function () {
var cookieTemp = '';
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.indexOf('v') != -1) {
debugger;
}
console.log('Hook捕获到cookie设置->', val);
cookieTemp = val;
return val;
},
get: function () {
return cookieTemp;
},
});
})();
注:正常hook cookie
操作的时候需要清除下cookie
(function() {
var _constructor = unsafeWindow.Function.prototype.constructor;
// Hook Function.prototype.constructor
unsafeWindow.Function.prototype.constructor = function() {
var fnContent = arguments[0];
if (fnContent) {
if (fnContent.includes('debugger')) { // An anti-debugger is attempting to stop debugging
var caller = Function.prototype.constructor.caller; // Non-standard hack to get the function caller
var callerContent = caller.toString();
if (callerContent.includes(/\bdebugger\b/gi)) { // Eliminate all debugger statements from the caller, if any
callerContent = callerContent.replace(/\bdebugger\b/gi, ''); // Remove all debugger expressions
eval('caller = ' + callerContent); // Replace the function
}
return (function () {});
}
}
// Execute the normal function constructor if nothing unusual is going on
return _constructor.apply(this, arguments);
};
})();