定义
Hook 技术又叫做钩子函数,在系统没有调用该函数之前,钩子程序就先捕获该消息,钩子函数先得到控制权这时钩子函数既可以加工处理(改变)该函数的执行行为,还可以强制结束消息的传递 简单来说,就是把系统的程序拉出来变成我们自己执行代码片段。
函数中常用方法,统一管理
// 使用前
function oldFun (errCode) {
if (errCode) {
if (errCode === '001') {
console.log('错误一');
} else if (errCode === '002') {
console.log('错误二');
} else if (errCode === '003') {
console.log('错误三');
}
}
}
// 使用后
const code = {
'001': '错误一',
'002': '错误二',
'003': '错误三'
};
function newFun (errCode) {
if (errCode) {
console.log(code[errCode]);
}
}
// 使用
newFun('002');// 输出错误二
函数hook公式
Function的函数
const old_alert = alert;
console.log('旧alert方法toString打印:', old_alert.toString()); // 输出结果:旧alert方法toString打印: function alert() { [native code] }
// 重写函数
alert = function () {
console.log('开始弹窗', JSON.stringify(arguments));
return old_alert.apply(this, arguments);
}
// 函数上做alert防hook检测
alert.toString = function () {
return 'function alert() { [native code] }'
}
// 原型链上做alert防hook检测
const old_prototype_alert = Function.prototype.toString.call;
Function.prototype.toString.call = function (arg) {
if (arg === alert) {
return 'function alert() { [native code] }'
}
return old_prototype_alert(arg);
}
alert('abc');
console.log('函数上做hook做防检测:', alert.toString()); // 输出结果:hook做防检测: function alert() { [native code] }
console.log('原型链上做hook做防检测:', Function.prototype.toString.call(alert)); // 输出结果:hook做防检测: function alert() { [native code] }
自定义函数
function func (a, b) {
return a + b;
}
const old_func = func;
func = function () {
console.log('执行func方法,参数为:', JSON.stringify(arguments));
return old_func.apply(this, arguments);
}
func(1, 2); // 输出 3
原型链hook
String.prototype.split_old = String.prototype.split;
String.prototype.split = function (value) {
str = this.toString();
console.log('开始执行字符串截取');
// debugger;
return str.split_old(value);
};
JSON hook
//将 JavaScript 值转换为 JSON 字符串
(function () {
var stringify = JSON.stringify;
JSON.stringify = function (params) {
console.log("Hook JSON.stringify ——> ", params);
debugger;
return stringify(params);
}
})();
// 将字符串解析成对象,多用于返回加密数据
(function () {
var parse = JSON.parse;
JSON.parse = function (params) {
console.log("Hook JSON.parse ——> ", params);
debugger;
return parse(params);
}
})();
对象中属性hook
const lsData = {
name: 'abc'
}
let oldName = lsData.name;
Object.defineProperty(lsData, 'name', {
get: function () {
console.log('开始【获取】lsData的name属性:', oldName);
return oldName;
},
set: function (val) {
console.log('开始【赋值】lsData的name属性:', val);
oldName = val
return val;
}
})
一键快速hook框架
(() => {
const $toString = Function.toString
const myFunction_toString_symbol = Symbol('('.concat('', ')_', (Math.random()) + '').toString(36))
const myToString = function () {
return typeof this === 'function' && this[myFunction_toString_symbol] || $toString.call(this)
}
function set_native (func, key, value) {
Object.defineProperty(func, key, {
enumerable: false,
configurable: true,
writable: true,
value: value
})
}
delete Function.prototype.toString
set_native(Function.prototype, "toString", myToString)
set_native(Function.prototype.toString, myFunction_toString_symbol, "function toString() { [native code] }")
globalThis.func_set_native = (func) => {
set_native(func, myFunction_toString_symbol, `function ${func.name || ''}() { [native code] }`)
}
}).call(this);
window.dta = {}
Function.prototype.hook = function (onEnter, onLeave, context, Funcname) {
if (!onEnter) {
onEnter = function (warpper) {
var args = warpper.args;
console.log(args)
}
}
if (!onLeave) {
onLeave = function (retval) {
console.log(retval)
}
}
// btoa.hook()
var _context = context || window;
var FuncName = this.name || Funcname;
if (!FuncName) {
console.error("hook function name is empty!")
return false
}
window.dta[FuncName] = this;
_context[FuncName] = function () {
var args = Array.prototype.slice.call(arguments, 0)
var _this = this
var warpper = {
args
}
onEnter.call(_this, warpper)
// this -> window
var retval = window.dta[FuncName].apply(this, warpper.args)
var hook_retval = onLeave.call(_this, retval)
if (hook_retval) {
return hook_retval
}
return retval
}
Object.defineProperty(_context[FuncName], "name", {
get: function () {
return FuncName
}
})
func_set_native(_context[FuncName])
}
console.log("quick hook start")
```