Hook 是一种钩子技术,在系统没有调用函数之前,钩子程序就先得到控制权,这时钩子函数既可以加工处理(改变)该函数的执行行为,也可以强制结束消息的传递。简单来说,修改原有的 JS 代码就是 Hook。
Hook 技术之所以能够实现有两个条件:
-
客户端拥有
JS
的最高解释权,可以决定在任何时候注入JS
,而服务器无法阻止或干预。服务端只能通过检测和混淆的手段,另 Hook 难度加大,但是无法直接阻止。 -
除了上面的必要条件之外,还有一个条件。就是 JS 是一种弱类型语言,同一个变量可以多次定义、根据需要进行不同的赋值,而这种情况如果在其他强类型语言中则可能会报错,导致代码无法执行。js 的这种特性,为我们 Hook 代码提供了便利。
1. 我们知道在 JavaScript
中 JSON.stringify()
方法用于将JavaScript
对象或值转换为 JSON
字符串,JSON.parse()
方法用于将一个 JSON
字符串转换为JavaScript
对象,某些站点在向web
服务器传输用户名密码时,会用到这两个方法
(function() {
var _stringify = JSON.stringify;
JSON.stringify = function(ps) {
console.log("Hook JSON.stringify ——> ", ps);
debugger;
return _stringify(ps); // 不改变原有的执行逻辑
}
})();
(function() {
var _parse = JSON.parse;
JSON.parse = function(ps) {
console.log("Hook JSON.parse ——> ", ps);
debugger;
return _parse(ps); // 不改变原有的执行逻辑
}
})();
首先定义了一个变量 stringify
保留原始 JSON.stringify
方法,然后重写 JSON.stringify
方法,遇到 JSON.stringify
方法就会执行 debugger
语句,会立即断下,最后将接收到的参数返回给原始的 JSON.stringify
方法进行处理,确保数据正常传输
2. hook XHR
请求
// 如果是正数 表示存在里面
// 如果是-1 表示不在里面
(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);
};
})();
(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);
};
})();
3. Interceptors-拦截器
-
请求拦截器:在发送请求之前,可以借助一些函数来对请求的内容和参数做一些检测。若有问题可以直接取消请求。
-
响应拦截器:当服务器返回响应数据时,响应拦截器会在我们拿到结果前预先处理响应数据。例如对响应数据做一些格式化处理,或者当响应失败时,可以做一些失败提醒和纪录。
// npm install axios
axios = require('axios')
//设置请求拦截器
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功')
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))
4.爬虫常用hook cookie操作
WEBAPI
地址:Web API 接口参考 | MDN
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 钩子用于定位 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