JavaScript 逆向分析中的常用 Hook 技术详解
在 JavaScript 逆向工程中,Hook(钩子)技术是定位关键逻辑、拦截数据生成、调试加密函数的核心手段。通过修改或监控原生方法的行为,我们可以深入理解目标网站的运行机制。本文整理了 11 种常见的 Hook 技术,并附上实用示例代码,适用于油猴脚本(Tampermonkey)、浏览器调试及安全研究场景。
📌 提示:以下代码建议在浏览器控制台或用户脚本中使用,用于辅助分析,切勿用于非法用途。
01. DOM 操作 Hook
通过修改 DOM 元素的属性或样式,实现对页面行为的干预,常用于隐藏元素、触发事件或篡改界面状态。
// 修改元素属性
document.getElementById('elementId').setAttribute('attrName', 'attrValue');
// 修改元素样式
document.getElementById('elementId').style.color = 'red';
document.getElementById('elementId').style.display = 'none';
02. Cookie 操作 Hook
用于监控 document.cookie
的读写操作,定位 Cookie 中关键字段(如 __dfp
、token
)的生成位置。
Object.defineProperty
方式一:使用 (function () {
'use strict';
let cookieTemp = '';
Object.defineProperty(document, 'cookie', {
set: function (val) {
if (val.includes('__dfp')) {
debugger; // 断点触发
}
console.log('Hook 捕获到 Cookie 设置 ->', val);
cookieTemp = val;
return val;
},
get: function () {
return cookieTemp;
}
});
})();
__defineSetter__
(已废弃,兼容旧环境)
方式二:使用 (function () {
'use strict';
var org = document.__lookupSetter__('cookie');
document.__defineSetter__('cookie', function (cookie) {
if (cookie.includes('__dfp')) {
debugger;
}
org = cookie;
});
document.__defineGetter__('cookie', function () {
return org;
});
})();
⚠️ 注意:
__defineSetter__
已被弃用,推荐使用Object.defineProperty
。
03. 事件监听 Hook
监听用户交互事件(如点击、输入),用于追踪行为触发逻辑。
// 监听按钮点击
document.getElementById('buttonId').addEventListener('click', function () {
console.log('按钮被点击!');
// 可在此注入自定义逻辑
});
也可用于监听 copy
、input
、submit
等敏感事件。
04. AJAX 请求拦截 Hook
通过重写 XMLHttpRequest.prototype.send
,拦截所有 AJAX 请求,便于分析参数与加密逻辑。
// 保存原始方法
XMLHttpRequest.prototype._send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function (data) {
console.log('拦截到 AJAX 请求,发送数据:', data);
// 可在此修改 data 或插入断点
debugger;
// 继续执行原方法
this._send.apply(this, arguments);
};
05. 函数替换 Hook
替换全局函数以插入日志或断点,常用于追踪加密函数调用。
// 保存原始函数
const originalFunction = window.encryptData;
// 替换为自定义函数
window.encryptData = function (...args) {
console.log('encryptData 被调用,参数:', args);
debugger;
// 调用原函数并返回结果
return originalFunction.apply(this, args);
};
06. HTTP Header 操作 Hook
监控 setRequestHeader
,定位如 Authorization
、X-Token
等关键头部字段的设置位置。
(function () {
const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
if (key === 'Authorization') {
console.log('检测到 Authorization Header:', value);
debugger;
}
// 继续执行原方法
return originalSetRequestHeader.apply(this, arguments);
};
})();
07. URL 请求地址 Hook
在 XMLHttpRequest.open
中检测请求 URL,用于定位登录、加密接口等关键请求。
(function () {
const originalOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url, async) {
if (url.includes('login')) {
console.log('拦截到包含 "login" 的请求:', url);
debugger;
}
return originalOpen.apply(this, arguments);
};
})();
🔍 注意:
indexOf("login") != -1
才是正确判断,原文!= 1
有误,已修正。
08. JSON.stringify Hook
监控 JSON.stringify
调用,常用于分析加密前的数据结构。
(function () {
const originalStringify = JSON.stringify;
JSON.stringify = function (params) {
console.log('Hook JSON.stringify ——> ', params);
debugger;
return originalStringify(params);
};
})();
09. JSON.parse Hook
监控 JSON.parse
,用于查看解密后或响应返回的原始数据。
(function () {
const originalParse = JSON.parse;
JSON.parse = function (params) {
console.log('Hook JSON.parse ——> ', params);
debugger;
return originalParse(params);
};
})();
10. eval 函数 Hook
eval
常用于动态执行加密代码,Hook 它可查看被加密的 JS 源码。
(function () {
// 保存原始 eval
window.__cr_eval = window.eval;
// 自定义 eval 包装函数
const myeval = function (src) {
console.log('eval 执行代码:\n', src);
console.log('=============== eval end ===============');
debugger;
return window.__cr_eval(src);
};
// 模拟原生 toString,绕过检测
const _myeval = myeval.bind(null);
_myeval.toString = function () {
return 'function eval() { [native code] }';
};
// 重新定义 window.eval
Object.defineProperty(window, 'eval', {
value: _myeval,
writable: false,
configurable: false
});
})();
11. Function 构造函数 Hook
监控通过 new Function()
创建的函数,常用于反混淆。
(function () {
// 保存原始 Function 构造函数
window.__cr_fun = window.Function;
// 重写 Function
const myfun = function () {
const args = Array.from(arguments);
const lastArg = args.pop(); // 最后一个参数是函数体
console.log('Function 构造函数调用,函数体:\n', lastArg);
console.log('=============== Function end ===============');
debugger;
return new window.__cr_fun(...args, lastArg);
};
// 模拟原生 toString 行为
myfun.toString = function () {
return window.__cr_fun.toString();
};
// 重新定义 Function
Object.defineProperty(window, 'Function', {
value: myfun,
writable: false,
configurable: false
});
})();
总结
技术 | 用途 | 关键点 |
---|---|---|
DOM 操作 | 控制页面元素 | 属性/样式修改 |
Cookie Hook | 定位 Cookie 生成 | Object.defineProperty |
事件监听 | 跟踪用户行为 | addEventListener |
AJAX 拦截 | 分析请求参数 | 重写 send /open |
函数替换 | 调试加密函数 | 保存原函数引用 |
Header Hook | 定位认证头 | setRequestHeader |
URL Hook | 拦截关键请求 | open 方法重写 |
JSON.stringify/parse | 查看数据结构 | 前后数据对比 |
eval / Function | 反混淆动态代码 | 绕过 native 检测 |