在逆向工程中,XHR断点是定位关键逻辑的"黄金探测器",本文将通过实战案例解析其核心价值与应用技巧。适合:Web逆向工程师、爬虫开发者、安全研究员。
一、XHR断点的本质:网络请求的"拦截站"
1.1 XHR断点原理图解
图表

代码
flowchart LR
A[网页操作] --> B[发起XHR请求]
B --> C{开发者工具}
C -->|XHR断点| D[暂停JS执行]
D --> E[查看调用栈]
E --> F[定位加密逻辑]
1.2 与传统断点的区别
| 断点类型 | 触发条件 | 逆向效率 | 精准度 |
|---|---|---|---|
| 普通断点 | 特定行代码执行 | 低 | 高 |
| 事件监听断点 | DOM事件触发 | 中 | 中 |
| XHR断点 | 网络请求发起时 | 高 | 高 |
| 异常断点 | 抛出异常时 | 低 | 低 |
二、XHR断点的五大核心作用
2.1 定位加密入口(核心价值)
javascript
// 典型场景:登录请求参数加密
POST /login HTTP/1.1
Content-Type: application/json
{
"username": "admin",
"password": "7f3a8b6c5d...", // 加密后的密码
"sign": "d41d8cd98f00b204e980..." // 动态签名
}
操作流程:
-
在DevTools的XHR Breakpoints中添加
*/login断点 -
触发登录操作
-
在Call Stack中回溯加密逻辑
2.2 追踪数据流路径
图表

代码
sequenceDiagram
participant UI as 用户界面
participant JS as 业务逻辑
participant Crypto as 加密模块
participant Network as 网络层
UI->>JS: 输入原始数据
JS->>Crypto: 调用加密函数
Crypto->>JS: 返回加密数据
JS->>Network: 发起XHR请求
Network-->>JS: 触发XHR断点
2.3 动态修改请求参数
javascript
// 断点触发后修改请求体
console.log("原始请求参数:", requestBody);
// 修改加密参数(测试不同加密结果)
requestBody.sign = "modified_signature_here";
// 跳过加密函数(直接测试原始数据)
// Override send function
XMLHttpRequest.prototype.send = function(originalBody) {
const fakeBody = JSON.stringify({...JSON.parse(originalBody), bypass: true});
return originalSend.call(this, fakeBody);
};
2.4 识别加密算法类型
在断点处检查参数特征:
javascript
// 常见加密特征识别
function detectEncryption(data) {
if (data.match(/[0-9a-f]{64}/)) return "SHA256";
if (data.match(/[0-9a-f]{32}/)) return "MD5";
if (data.includes("=") && data.length % 4 === 0) return "Base64";
if (data.match(/[A-Za-z0-9+\/]{10,}={0,2}/)) return "AES";
return "Unknown";
}
2.5 绕过反调试机制
javascript
// 当遇到反调试时,在XHR断点处注入绕过代码
const antiDebug = setInterval(() => {
if (typeof console !== 'undefined') {
console.clear(); // 清除检测痕迹
}
}, 100);
// 删除检测函数
delete window.DevToolsDetection;
三、XHR断点实战四步法
3.1 精准设置断点策略
| 场景 | 断点设置技巧 | 示例 |
|---|---|---|
| 登录加密 | URL包含关键字 | *login* |
| 数据签名 | 请求方法+路径 | POST */api/sign* |
| 动态令牌 | 查询参数匹配 | URL包含?token= |
| 文件上传 | 特定内容类型 | Content-Type: multipart |
3.2 调用栈分析技巧
javascript
// 典型调用栈结构(自下而上) 0: submitForm() // UI事件处理 1: encryptData() // 业务逻辑层 2: generateSign() // 加密层 3: CryptoJS.AES.encrypt() // 加密库 4: XMLHttpRequest.send() // 断点位置
关键操作:
-
从栈底向上查找第一个非库函数
-
定位到
encryptData或generateSign等业务函数 -
右键选择"Jump to definition"跳转源码
3.3 参数追踪技巧
javascript
// 在Console中追踪参数变化
function traceArguments(fn) {
return function(...args) {
console.group('函数追踪:', fn.name);
console.log('参数:', args);
const result = fn.apply(this, args);
console.log('返回:', result);
console.groupEnd();
return result;
};
}
// 应用追踪
window.encryptData = traceArguments(window.encryptData);
3.4 断点条件过滤
javascript
// 高级断点条件(仅当参数包含特定字段时触发)
(() => {
const origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url) {
this._url = url;
return origOpen.apply(this, arguments);
};
const origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
if (this._url.includes('/api/') && body && body.includes('signature')) {
debugger; // 条件触发断点
}
return origSend.apply(this, arguments);
};
})();
四、企业级案例:破解某电商签名算法
4.1 场景描述
-
目标URL:
https://api.ecommerce.com/search?keyword=手机 -
必要签名:
X-Sign: a1b2c3d4e5f6... -
签名变化:每次请求动态生成
4.2 逆向流程
图表

代码
graph TD
A[设置XHR断点 */search*] --> B[触发搜索操作]
B --> C[在send方法暂停]
C --> D[分析调用栈]
D --> E[定位签名生成函数]
E --> F[参数追踪]
F --> G[算法还原]
4.3 关键代码定位
javascript
// 调用栈中找到核心加密函数
function generateSignature(params) {
// 1. 参数排序
const sorted = Object.keys(params).sort();
// 2. 拼接字符串
let raw = '';
sorted.forEach(k => {
raw += `${k}=${params[k]}&`;
});
// 3. 添加密钥
raw += 'secret_key=ec_2023!';
// 4. MD5哈希
return md5(raw); // 定位到此处
}
4.4 算法还原结果
python
# Python实现签名算法
import hashlib
def generate_sign(params):
sorted_keys = sorted(params.keys())
raw_str = ''.join(f"{k}={params[k]}&" for k in sorted_keys)
raw_str += "secret_key=ec_2023!"
return hashlib.md5(raw_str.encode()).hexdigest()
# 测试
params = {"keyword": "手机", "page": 1}
sign = generate_sign(params) # 输出: 7d5bcd7f4e8a...
五、高级技巧:XHR断点组合拳
5.1 断点+Hook组合
javascript
// 在断点处安装Hook
const _send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
// 1. 捕获请求
console.log("请求URL:", this._url);
// 2. 安装参数生成器Hook
if (this._url.includes('/api/')) {
window.generateSign = function(original) {
return function(params) {
console.log("签名参数:", params);
const result = original(params);
console.log("生成签名:", result);
return result;
}
}(window.generateSign);
}
return _send.call(this, body);
};
5.2 断点+内存dump
javascript
// 在断点处导出内存状态
function dumpMemory() {
const memory = {};
// 捕获全局变量
for (const key in window) {
if (typeof window[key] === 'function') {
memory[key] = window[key].toString();
}
}
// 保存为文件
const blob = new Blob([JSON.stringify(memory)], {type: 'application/json'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'memory_snapshot.json';
a.click();
}
// 在断点控制台执行
dumpMemory();
5.3 断点+环境快照
javascript
// 创建环境快照
class EnvSnapshot {
constructor() {
this.dom = document.documentElement.outerHTML;
this.cookies = document.cookie;
this.storage = JSON.stringify(localStorage);
this.jsState = {};
}
captureJsState() {
// 捕获关键对象
this.jsState = {
crypto: window.crypto.subtle ? 'available' : 'unavailable',
userAgent: navigator.userAgent,
// 添加其他需要捕获的状态
};
}
}
// 断点处使用
const snapshot = new EnvSnapshot();
snapshot.captureJsState();
六、XHR断点对抗技术
6.1 常见反断点策略及破解
| 防御手段 | 破解方案 | 实现代码片段 |
|---|---|---|
| 请求重定向 | Hook Fetch API | window.fetch = origFetch |
| WebSocket传输 | WS断点监听 | WebSocket.prototype.send=function() {debugger} |
| 动态URL | 正则匹配断点 | XHR Breakpoint: */api/* |
| 请求分包 | 请求重组Hook | 合并多个请求后分析 |
6.2 隐身调试模式
javascript
// 在断点处启用隐身模式
Object.defineProperty(window, 'chrome', {
value: undefined,
configurable: false,
writable: false
});
navigator.__defineGetter__('webdriver', () => false);
七、工具推荐:XHR断点增强套件
7.1 浏览器插件
-
XHR Breakpoint Plus(Chrome)
-
支持正则表达式匹配
-
请求内容关键词过滤
-
自动保存请求快照
-
-
Request Catcher(Firefox)
-
可视化请求地图
-
自动生成调用树
-
支持批量断点管理
-
7.2 控制台工具
javascript
// 高级XHR监控脚本
const XHRLogger = {
init() {
this.requests = [];
const origOpen = XMLHttpRequest.prototype.open;
const origSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function(method, url) {
this._method = method;
this._url = url;
this._startTime = Date.now();
return origOpen.apply(this, arguments);
};
XMLHttpRequest.prototype.send = function(body) {
this._body = body;
const index = this.requests.length;
this.addEventListener('load', () => {
const duration = Date.now() - this._startTime;
console.group(`XHR #${index} ${this._method} ${this._url}`);
console.log("Status:", this.status);
console.log("Duration:", duration + 'ms');
console.log("Request:", body);
console.log("Response:", this.responseText);
console.groupEnd();
});
this.requests.push(this);
return origSend.apply(this, arguments);
};
}
};
XHRLogger.init();
结语:XHR断点的战略价值
在逆向工程中,XHR断点如同精准的狙击步枪:
-
直接锁定关键网络请求
-
穿透层层混淆直达核心逻辑
-
提供完整的调用上下文环境
-
支持动态干预请求过程
高级技巧: 在大型逆向工程中,优先使用XHR断点定位入口,再结合函数Hook和堆栈分析深入核心算法,可节省70%以上的分析时间。
你在使用XHR断点时遇到过哪些棘手问题?欢迎在评论区分享你的实战经验!
981

被折叠的 条评论
为什么被折叠?



