1. 爬虫逆向实战技巧与核心知识解析
作为一名长期从事爬虫开发的工程师,逆向工程是绕不开的核心技能。今天我将分享一些在实战中积累的爬虫逆向技巧,这些经验大多来自真实项目中的踩坑与总结,希望能帮助你在逆向过程中少走弯路。
1.1 JavaScript逆向基础要点
在Web逆向中,JavaScript是最常遇到的"对手"。掌握以下几个基础概念能让你更快定位关键逻辑:
- constructor的特殊性:这是类的构造函数,当使用new创建实例时自动调用。在逆向中,很多加密逻辑会隐藏在constructor中。例如:
javascript复制class Crypto {
constructor() {
this.key = 'secret_key'; // 关键加密密钥常在这里初始化
}
encrypt(data) {
// 加密逻辑
}
}
-
Base64编码处理:window.btoa()方法将ASCII字符串转为Base64,其逆向方法是atob()。但要注意,这不是加密,只是编码转换。实战中常见于简单混淆的参数传递。
-
加密类型识别:
- 对称加密:加解密使用相同密钥,如AES、DES
- 非对称加密:公钥加密私钥解密,如RSA
- 识别技巧:查看是否有明显的publicKey/privateKey变量,或密钥长度(RSA密钥通常较长)
-
自执行函数:这种匿名函数会立即执行,常见形式有:
javascript复制(function(){...})(); !function(){...}(); +function(){...}();它们常被用来封装核心逻辑,防止变量污染全局作用域。
1.2 开发者工具的高级用法
当目标网站禁用F12时,可以尝试以下方法打开开发者工具:
- 右键检查元素(部分网站只禁用了F12)
- 浏览器右上角菜单 → 更多工具 → 开发者工具
- 快捷键组合:Ctrl+Shift+I(Windows)或Cmd+Opt+I(Mac)
- 独立窗口模式:打开开发者工具后,点击右上角的"分离"图标
提示:某些网站会检测开发者工具,此时可以使用移动设备模拟模式(Ctrl+Shift+M)绕过检测。
1.3 加密逻辑的快速验证技巧
当遇到疑似MD5等标准加密时,可以这样验证:
- 在代码断点处记录加密前的原始值和加密结果
- 在自己的NodeJS环境中使用对应库加密相同原始值
- 比较两者结果是否一致
例如:
javascript复制// 目标网站加密结果
const targetHash = '5d41402abc4b2a76b9719d911017c592';
// 本地验证
const crypto = require('crypto');
const localHash = crypto.createHash('md5').update('hello').digest('hex');
console.log(targetHash === localHash); // true则表示加密算法一致
1.4 参数加密的常见位置
网站加密通常出现在以下位置:
| 参数类型 | 加密位置 | 示例 | 逆向难度 |
|---|---|---|---|
| Cookie参数 | document.cookie设置处 | token=encryptedValue | 中高 |
| URL查询参数 | 请求发起前的处理函数 | /api?sign=encrypted | 中 |
| POST表单数据 | XMLHttpRequest.send()前 | 高 | |
| WebSocket消息 | 消息发送前的处理 | ws.send(encrypted) | 高 |
1.5 高效断点调试策略
逆向时断点设置要有策略性:
- XHR断点:适合同步请求,在Chrome开发者工具的Sources → XHR Breakpoints中添加接口URL
- DOM断点:对特定元素设置,右键 → Break on → attribute modifications
- 事件监听断点:在Sources → Event Listener Breakpoints中勾选对应事件
- 条件断点:右键断点 → Edit breakpoint,设置触发条件
注意:异步调用堆栈中,XHR断点可能失效,此时应改用常规断点跟调用栈。
1.6 Webpack逆向专项技巧
Webpack打包的代码逆向有其特殊性:
- 定位加载器:对类似
.call(this,n(11))的调用下断点,刷新整个页面而非仅重发请求 - 查找模块:在控制台输入
n并查看输出,可以找到模块加载器的入口 - 导出函数:webpack通常将模块导出为
__webpack_exports__,可以在此查找关键函数 - 模块映射:搜索
webpackJsonp或__webpack_require__找到模块ID与函数的映射关系
1.7 Cookie参数分析要点
分析Cookie时注意:
- HttpOnly标记:这种Cookie由服务器设置,前端JS无法读取,通常不包含加密逻辑
- Secure标记:仅通过HTTPS传输,抓包时需使用SSL解密
- 过期时间:Session Cookie在浏览器关闭后失效,持久化Cookie有明确Expires
- 加密特征:长度固定、字符分布均匀的Value值可能经过加密
1.8 全局搜索技巧
当遇到HTML中的加密数据时:
- 检查元素属性如id、data-*等
- 复制这些值到源代码中全局搜索(Ctrl+Shift+F)
- 搜索时尝试去掉引号或部分字符,提高命中率
- 对于压缩代码,搜索时可以省略空格和换行
1.9 静态密钥的处理
当发现加密key不随请求变化时:
- 直接复制key值保存备用
- 验证key是否硬编码在JS中
- 检查key是否来自某个固定API接口
- 即使key固定,也要注意其使用方式(如是否拼接时间戳等)
1.10 对抗无限debugger
网站常用的反调试手段及破解方法:
-
构造函数递归:
javascript复制function Debugger() { debugger; return new Debugger(); } new Debugger();破解:在函数定义处断点,执行前将其置空:
javascript复制Debugger = function(){}; -
定时器检测:
javascript复制setInterval(function(){ if(console.log.toString() !== 'function log() { [native code] }'){ location.href = 'about:blank'; } }, 1000);破解:重写console.log或直接清除定时器
-
多文件分散:反调试代码分散在多个JS文件中,需要耐心查找并逐个置空
1.11 CSRF Token的获取
CSRF Token通常出现在:
- 页面meta标签:
<meta name="csrf-token" content="value"> - 表单隐藏字段:
<input type="hidden" name="_token" value="..."> - 全局JS变量:
window.csrfToken = '...' - Cookie中:但通常与HttpOnly配合使用,此时需要解析Set-Cookie头
2. 爬虫逆向实战案例解析
2.1 案例一:电商平台价格加密破解
背景:某电商平台商品价格通过JS加密,HTML中显示为<span class="price" data-enc="aGVsbG8=">***</span>。
逆向过程:
- 全局搜索
data-enc,找到数据处理逻辑 - 发现使用Base64编码,但直接解码结果不符预期
- 进一步分析发现是先ROT13再Base64
- 验证解码逻辑:
javascript复制function decodePrice(enc) { const rot13 = str => str.replace(/[a-zA-Z]/g, c => String.fromCharCode((c <= 'Z' ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26)) return atob(rot13(enc)); }
关键点:不要假设编码后直接就是目标值,可能有多重处理。
2.2 案例二:视频网站签名参数逆向
背景:某视频网站API请求需要sign参数,每次请求值都不同。
分析步骤:
- XHR断点定位到请求发起位置
- 回溯调用栈找到签名生成函数
- 发现是HMAC-SHA256算法
- 关键参数按固定顺序拼接:
javascript复制const sign = hmacSha256(apiPath + timestamp + userId, secretKey);
解决方案:
- 提取secretKey(在webpack模块863中)
- 按照相同逻辑本地生成sign
- 注意timestamp必须是当前服务器时间,需要同步
2.3 案例三:WebSocket协议逆向
背景:实时股票数据通过WebSocket传输,消息体加密。
破解过程:
- 使用Chrome的WS过滤功能捕获连接
- 发现握手阶段有密钥交换
- 消息使用AES-CBC模式加密
- 在WebSocket初始化代码中找到IV生成逻辑
- 最终解密:
javascript复制const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv); let decrypted = decipher.update(encrypted, 'hex', 'utf8'); decrypted += decipher.final('utf8');
3. 常见问题与解决方案
3.1 加密逻辑无法复现
问题现象:本地生成的签名与服务端校验不通过。
排查步骤:
- 检查参数顺序是否完全一致
- 验证编码格式(UTF-8/Base64/Hex等)
- 检查时间戳精度(秒/毫秒)
- 查看是否有未注意的默认参数
- 使用完全相同的环境(如NodeJS版本、库版本)
3.2 反爬虫机制触发
常见反爬手段:
- 请求频率限制
- 行为检测(鼠标移动、点击模式)
- TLS指纹识别
- WebGL渲染指纹
解决方案:
- 合理设置请求间隔(随机化更佳)
- 使用真实浏览器环境(Puppeteer/Playwright)
- 自定义TLS指纹(需底层修改)
- 轮换代理IP
3.3 代码混淆严重
应对策略:
- 使用AST解析工具反混淆
- 重点跟踪关键字符串的引用
- 查找入口点(如事件监听、网络请求)
- 使用Source Map(如果存在)
3.4 性能优化技巧
- 缓存解密结果:对静态密钥的加密结果可以缓存
- 并行处理:使用Worker线程处理CPU密集型解密
- 懒加载:非必要不逆向,优先尝试模拟正常请求
- 工具链:构建自动化逆向管道(拦截→分析→生成代码)
4. 安全与法律注意事项
在实施爬虫逆向时,必须注意:
- 遵守robots.txt:尊重网站的爬虫协议
- 控制请求频率:避免对目标服务器造成负担
- 数据使用限制:仅用于合法用途,不侵犯隐私
- 商业用途风险:部分数据可能受版权保护
- 技术防御边界:不破坏网站防护措施
重要提示:本文技术分享仅用于安全研究和合法爬虫开发,请勿用于任何非法用途。实际项目中建议与目标网站沟通获取合法数据接口。