资讯动态

复杂反爬全方位拆解:逆向分析、动态Cookie与签名校验

发布时间:2026/8/30 10:40:33 来源:尧图企业网站定制
做了这么多年逆向分析我遇到过的反爬手段并不算少。设备指纹、动态Token、行为验证、字体反爬、WebAssembly混淆基本都碰到过。但有一次分析某个动漫资源站点的反爬机制时我还是被一组“看起来平平无奇”的脚本代码卡住了。问题不在于技术多新而在于它把环境检测、Cookie生成、签名校验三层逻辑全部耦合在一起局部看每个环节都不复杂整体一组合就变得很难追踪。这段经历说明一个事实资深逆向工程师要练的不只是某个脱壳技巧或某段解密算法而是一套系统化拆解复杂反爬的思路。本文会从这次案例出发聊一聊复杂反爬的技术构成、逆向分析流程、常见排查路径以及站在防御方如何设计一套更可靠的反爬体系。内容适合有一定爬虫或逆向基础、想系统提升分析能力的开发者也适合正在维护反爬体系、想知道攻击方如何思考的技术人员。1. 复杂反爬为什么会让人在逆向过程中卡住1.1 反爬让人难受的点不是算法而是链路很多初学者以为反爬难在加密算法复杂比如某个网站用了AES、RSA甚至国密只要会解密就能跑通。但真实项目里算法复杂只是其中一个因素。真正让人头疼的是多层校验之间的耦合关系。举个例子。一个请求要携带动态签名TokenToken的生成依赖浏览器环境变量环境变量又被一段混淆代码修改过而混淆代码的入口藏在异步加载的脚本里。你在Network面板看到的只是一个常规请求但请求背后已经走完了好几层状态机。如果从请求直接去找签名字段会看到签名已经生成却很难定位它是在哪个时机、由哪个函数、基于哪些输入生成的。所以我常说遇到复杂反爬先不要急着翻混淆代码先画链路图。把请求从发起、经过中间件、到达后端再到返回结果的路径梳理清楚才知道反爬的校验点分散在哪里。1.2 先把反爬机制按技术类型做个归类经验证明拿到一个反爬案例第一步是判断它属于哪一类。下面是常见反爬机制的分类基于我在多个站点中的观察整理成速查表。反爬类型常见表现检测环节分析难度设备指纹生成canvas指纹、WebGL指纹、AudioContext指纹前端采集后端比对中动态Cookie首次请求返回一段脚本执行后生成CookieSet-Cookie 前端计算中高行为检测鼠标轨迹、点击频率、停留时长、滚动速度前端采集后端建模高字体反爬自定义字体映射文字显示正常但HTML源码是乱码CSS font-face中环境混淆检测window、navigator、document等对象属性前端脚本检查中接口签名请求参数带sign、token、timestamp前后端共同计算高WebAssembly把核心算法编译成wasm模块加载wasm字节码执行高行为验证滑块、点选、智能验证码第三方风控SDK高这张表的用途是快速缩小排查范围。例如发现Cookie一直在变化优先考虑动态Cookie或环境混淆如果请求参数存在sign且每次值不同优先考虑接口签名。1.3 组合式反爬正在成为标准做法组合式反爬把多道防线串起来每一道防线的校验结果都可能影响下一道。攻击方如果想绕过不能只解决某一个点而是要把整条链路跑通。这就是“单独看每个环节都不复杂连起来却让人头疼”的原因。防御方选择组合式反爬核心不是为了绝对不可破解而是为了增加攻击者的时间成本。反爬从来不是让所有爬虫消失而是让低成本的批量采集失去收益。明白了这一层再看那些“让人恶心”的脚本心态就会平稳很多它不是无解的迷宫只是为了把你挡在时间成本之外。2. 一次Web逆向分析的完整拆解流程2.1 第一步分清数据接口、身份校验和访问频率三类问题拿到一个具体目标后先把问题归类。数据接口类问题关注的是数据如何返回、字段如何加密身份校验类问题关注的是Token、Cookie、签名如何生成和校验访问频率类问题关注的是IP、账号、设备维度上的频率限制。这三类问题的分析思路完全不同。身份校验需要断点调试和调用栈分析数据接口需要关注响应体的解密逻辑访问频率则需要检测限流阈值和缓存策略。如果混在一起排查会浪费大量时间。以一个动漫资源站为例它的反爬设计通常包含三层浏览器环境检测身份、动态生成请求签名鉴权、基于IP和指纹的限流频率。三者耦合后任何一个环节缺失请求就会被拦截。2.2 第二步从Network面板定位关键请求打开浏览器开发者工具在Network面板中先做一次正常访问并把请求按资源类型分组。需要重点关注以下几类请求文档请求Document可能承载首屏渲染逻辑。XHR或Fetch请求通常是数据接口也是签名参数最集中的地方。Script请求动态加载的JS文件加密或签名逻辑往往在这里。Cookie相关响应头观察服务端是否下发Set-Cookie。实际操作中可以用关键字过滤请求列表例如接口路径中常见的/api/、/list、/search。也可以在控制台里覆盖window.fetch和XMLHttpRequest记录所有出入站请求。// 在浏览器Console中执行记录所有fetch请求 const originalFetch window.fetch; window.fetch function (...args) { const url typeof args[0] string ? args[0] : args[0].url; if (url.includes(/api/)) { console.log([fetch], url); console.trace(); } return originalFetch.apply(this, args); };这段代码用于观察一个页面里哪些请求会携带敏感参数在处理自己维护的站点时也非常实用。需要注意的是覆盖全局函数在真实调试完成后要手动恢复否则会影响页面正常运行。2.3 第三步用关键词搜索和Hook断点锁定JS逻辑定位到可疑请求后下一步是找到生成签名或Cookie的脚本。常用方法有两种。第一种是全文搜索在Sources面板中按CtrlShiftF打开全局搜索输入sign、token、cookie、deviceId等关键词找到所有出现的文件后逐个排查。第二种是Hook断点。当已经确定某个函数可能参与生成签名时可以在Console里先覆盖它打印参数和调用栈。// 假设在脚本里看到了getSign函数 if (typeof window.getSign function) { const originalGetSign window.getSign; window.getSign function (...args) { console.log([hook] getSign called, args:, args); console.trace(); return originalGetSign.apply(this, args); }; }这里的核心逻辑是先给可疑函数加一层代理观察它的入参、出参和调用来源。调用栈能告诉你这个函数是被谁调用的从而反向定位到更上层的逻辑。2.4 第四步验证分析结论形成可复现结果分析完签名生成逻辑后需要验证结论。常见做法是在本地写一段脚本模拟浏览器环境生成同样的签名然后请求接口测试。这一步最考验细节因为签名可能依赖随机数、时间戳、环境变量或服务端下发的参数。验证时要注意要在同一时间窗口内请求避免timestamp过期。要保证Cookie和签名使用同一个session。要考虑请求头的顺序、大小写和Referer是否会被校验。要排除服务端对IP、User-Agent的校验。验证通过后把整个分析过程整理成文档或脚本方便后续回溯。这个环节非常关键因为很多人会卡在“理论上分析通了但一请求就失败”的状态问题往往出在一些容易被忽略的请求头或Cookie上。3. JavaScript逆向中躲不开的几类关键套路3.1 动态Cookie和签名参数怎么识别动态Cookie是一种很常见的反爬手段典型流程是浏览器首次访问页面时服务端返回一段脚本脚本在本地生成一个Cookie值后续请求必须携带这个Cookie否则被拒绝。识别动态Cookie的方法是在Network面板里找到首次请求的响应查看是否有Set-Cookie响应头并确认这个Cookie值是否在页面脚本执行后才会被写入document.cookie。如果是就需要找到生成该Cookie的JS代码。签名参数更容易识别通常出现在接口请求的Query参数或Request Body中常见字段名包括sign、token、ts、nonce、deviceId。例如下面这种结构{ url: /api/list, params: { page: 1, ts: 1710000000, nonce: abc123, sign: a1b2c3d4e5f67890 } }签名参数的特征是每次请求值不同且与时间戳、请求体内容或某个动态变量相关。定位到之后就可以重点分析它是由哪些字段拼接、再经过什么算法生成的。3.2 环境检测window、navigator、canvas这些对象在查什么环境检测是前端反爬最常用的技术通过读取浏览器环境属性来判断访问者是不是真实浏览器。下面是常见的检测对象和用途。检测对象检测目的常见反爬用途navigator.userAgent判断User-Agent是否正常识别HeadlessChromenavigator.webdriver判断是否由WebDriver驱动标记自动化客户端window.chrome判断浏览器是否完整真实Chrome会返回特定结构canvas.toDataURL读取canvas渲染指纹识别同一浏览器设备WebGLRenderer读取GPU信息设备指纹组合AudioContext读取音频处理特性设备指纹组合navigator.languages检查语言配置识别异常环境环境检测的难点不在于读懂某一行代码而在于它往往被拆分成多个小函数分散在多个脚本文件中。搜索关键字navigator、window.chrome、canvas时会弹出大量结果需要结合调用栈判断真正影响请求校验的那一条分支。3.3 混淆代码的三种常见形态JS混淆的主要目的是增加可读性难度。常见形态有三种。第一种是字符串加密把代码里的关键字和常量转换成数组下标或Base64字符串运行时才还原。var key [c3VwZXJfc2VjcmV0, sign, token]; // 运行时解码 function decode(idx) { return atob(key[idx]); }第二种是控制流平坦化把原来的顺序执行逻辑改成一个while循环加switch分发打断阅读顺序。// 控制流平坦化的简化示意 let pc 0; while (true) { switch (pc) { case 0: let a hello; pc 1; break; case 1: let b world; pc 2; break; case 2: return a b; } }第三种是虚拟机保护把原函数编译成自定义字节码再通过一个解释器执行。遇到这种情况直接静态分析成本很高一般需要动态调试在解释器执行到关键操作时观察寄存器或栈上的数据。3.4 一个最小示例从混淆代码里找回判断逻辑假设有一段混淆后的代码我们需要定位它是否在检测webdriver。混淆后会大量使用异或、解码函数和间接调用。// 简化的混淆后代码 function _0x3f2a(_0x4b5e, _0x2c3d) { return _0x4b5e.split().reverse().join() _0x2c3d; } var check _0x3f2a(redrivbew, ); if (navigator[check]) { // 命中webdriver执行反爬逻辑 }这里navigator[webdriver]被拆成了字符串反转和拼接。在真实代码里这种手法的表现更隐蔽可能配合数组下标、中文编码甚至动态属性名。分析时最好的办法不是手动解码而是用浏览器环境执行后打印关键对象的属性值再用断点观察条件分支走向。4. 别只想着穿透别人的反爬还要知道反爬该怎么设计4.1 从攻击方视角切回防御方视角做了多年逆向后我发现一个很有价值的思维转换当你花了很多时间分析别人家的反爬接下来应该反过来思考如果自己维护的系统遇到同样的攻击能不能扛住。前端反爬的防御价值不在于“绝对安全”而在于提高攻击门槛。设计原则很简单服务端能校验的不依赖前端判断能动态变化的不使用固定值能由风控判定行为的不要只依赖单点Cookie。4.2 服务端要做签名校验、风控、限流和日志审计服务端是反爬的最后一道防线。一个较完整的服务端校验流程至少包含四块内容。签名校验用于确认请求参数没有被篡改通常会根据时间戳、随机数、业务参数和一个服务端秘钥计算HMAC签名。限流用于控制单位时间内单个IP、设备或账号的请求数量。风控引擎综合多维度信息给请求打分分数越高越可能是机器行为。日志审计用于记录异常的请求特征方便后续回调策略。下面是签名校验的伪代码示例# 伪代码服务端校验签名 def verify_request(request): if not check_timestamp(request.ts, max_age300): return False if not check_nonce(request.nonce): return False expected_sign hmac_sign( secretAPP_SECRET, paramsrequest.params, ) if not hmac.compare_digest(expected_sign, request.sign): return False return True这里的关键点是签名过期时间要设置合理过期太短会影响正常用户体验太长则容易给重放攻击留空间签名内容要把所有参与请求的参数包进来否则攻击者依然可以修改非签名字段。4.3 前端JS加固的几个可落地点前端加固不能保证绝对安全但可以提高分析成本。可以从这几个方向落地。使用WebAssembly承载签名或环境检测算法增加静态分析的难度。把关键环境判断拆分到多个脚本和函数中避免一个函数完成所有检测。加入反调试逻辑检测浏览器开发者工具是否打开但要注意不能影响正常用户体验。对Cookie生成逻辑增加随机量和过期机制不让签名长时间有效。使用Service Worker或异步加载延迟环境检测增加调用链的复杂度。需要提醒的是前端加固应该把主要精力放在“动态化”和“服务端校验”上而不是堆砌大量难以维护的混淆代码。混淆代码会拖慢页面性能也容易引入兼容性问题。4.4 Web反爬的简化架构示例一个可落地的Web反爬架构前端走的是特征采集后端走的是策略判断。下面用结构图说明但这里不用Mermaid只以文本形式列出链路。用户浏览器 - Nginx/WAF层IP限流、UA校验、基础拦截 - API网关统一鉴权、签名校验、请求日志 - 应用服务业务逻辑、Token验证、权限控制 - 风控引擎设备指纹、行为分数、黑白名单 - 数据层缓存、限流规则、审计日志这个架构的核心思想是分层防御。即使某一层被穿透后续层仍能拦截。5. 那些让人“恶心”的异常现象和排查路径5.1 现象一刷新页面后Cookie总是不一致有些站点在刷新页面后每次返回的Cookie都会变化。原因通常是服务端使用了动态Cookie下发机制或者Cookie里的某个字段是由前端脚本基于随机值生成的。排查步骤清除所有Cookie重新访问页面。在Network面板中记录首次响应的Set-Cookie。观察页面加载后document.cookie中的值是否被修改。搜索JS中写Cookie相关的代码。常见结论是服务端下发的只是一个临时票据前端脚本会生成一个新的签名值并覆盖Cookie。此时需要单独分析生成这个Cookie的函数。问题现象常见原因检查方式处理建议刷新后Cookie变化前端动态生成并覆盖对比Set-Cookie和document.cookie定位写Cookie的脚本并分析生成逻辑第一次访问成功后续失败会话绑定失效检查Cookie和签名是否配对重新获取Cookie或更新签名5.2 现象二本地调试正常线上访问失败本地用浏览器访问一切正常但用脚本访问就失败这是最典型的组合式反爬场景。原因通常是服务端同时校验了浏览器指纹、Cookie和接口签名脚本环境缺少某个关键属性。排查时先做排除法用同一套Cookie在浏览器和脚本中分别发起相同请求逐项对比请求头、Cookie、签名参数是否一致。然后检查浏览器指纹相关的字段例如User-Agent、Accept-Language、Referer并通过调试工具观察navigator对象是否完整。5.3 现象三浏览器可以访问脚本请求却被拒绝这种情况多发生在服务端风控检测到请求频率或行为与真实用户不匹配时。此时即使浏览器里复制的请求头、Cookie、签名都正确脚本仍会被限流。建议按频率测试将请求间隔从1秒调整到3秒、5秒、10秒观察是否仍然被拦截。如果间隔拉大后请求成功说明命中了限流策略。此时要合理控制请求频率或者使用代理IP并配合随机延时。5.4 一套可以复用的排查顺序遇到反爬拦截建议按下面的优先级排查不要一开始就去翻混淆代码。检查基础请求头User-Agent、Referer、Origin是否缺失或异常。检查Cookie是否存在动态字段是否与正常浏览器一致。检查接口参数是否有sign、token、ts等签名参数。检查请求频率是否因访问速度过快触发限流。检查执行环境浏览器和脚本环境在指纹上有哪些差异。检查IP维度目标IP是否已经进入黑名单或异常名单。按这个顺序排查能覆盖80%的普通反爬问题。6. 逆向分析的合规边界这条线要清楚6.1 哪些场景下逆向分析是合理合法的逆向分析本身是一种技术能力在多个场景下是合理且必要的。对自己拥有或得到授权的系统做安全测试。在浏览器兼容性分析中检查第三方SDK的行为。为了数据迁移或系统集成分析自有接口的交互逻辑。在CTF竞赛、漏洞挖掘、学术研究中使用逆向知识。分析恶意代码、研究攻击手法用于防御和应急响应。这些场景的共同点是分析对象已经授权或者分析目的属于安全研究和防御。6.2 哪些行为容易踩到法律红线以下行为存在明显法律风险无论技术能力多强都应该避免。未经授权爬取并商业化使用他人数据。绕过会员体系、付费墙、版权保护机制。破坏或干扰目标系统的正常运行。盗用或逆向他人的商业接口用于恶意竞争。传播绕过工具、破解方法或攻击性代码。在写作和技术分享时也要注意不提供可直接用于攻击的完整代码。偏向原理分析和防御建议的内容更有价值也更安全。6.3 给学习和研究者的几点建议如果你刚开始接触逆向分析建议用一个自己搭建的靶场或开源项目作为训练对象而不是直接拿线上商业站点练手。可以在本地部署一套带反爬的Demo应用然后尝试分析它的签名逻辑、Cookie生成和风控策略。这样的练习既安全又能覆盖大多数复杂反爬的核心技术点。等能力提升后再参与正规的众测或授权渗透项目更加稳妥。7. 学习路线和最佳实践建议7.1 由浅入深的一条学习路线逆向分析是一个需要长期积累的方向建议按下面顺序学习。基础阶段掌握HTML、CSS、JavaScript、浏览器开发者工具。抓包阶段熟练使用Chrome Network、Charles或Fiddler查看和分析请求。调试阶段掌握断点、条件断点、Hook、调用栈查看方法。混淆对抗阶段学习AST、JS反混淆工具和字节码概念。协议进阶理解HTTP、HTTPS、WebSocket、HTTP/2的交互流程。高阶阶段学习WebAssembly、Android APK逆向、SO库分析。风控阶段理解设备指纹、行为建模、验证码原理。每一阶段都建议配合实际案例练习。没有真实场景只靠读文档很难形成分析直觉。7.2 几个值得长期坚持的实践习惯积累下来的经验告诉我有下面几个习惯的开发者成长速度会明显更快。第一每分析一个案例都要画链路图把请求、Cookie、签名、环境检测串起来。第二每写完一次分析结论都要问自己“如果服务端换一种校验方式这个结论还成立吗”。第三把常用的Hook脚本、搜索命令、调试技巧沉淀成自己的工具库。第四重视日志和调用栈而不是只关注结果值。另一个容易被忽视的点是版本管理。分析脚本和分析文档即使比较零散也建议放进Git仓库。很多项目隔几个月再回头看只有当时的记录能帮你快速恢复上下文。7.3 面向实际项目的执行建议如果要在实际项目中应用这些分析能力建议先定义清楚目标。是保护自己的接口还是做一次授权范围内的安全评估又或是排查某个第三方组件的异常行为。目标不同采用的工具和分析深度都有差异。在生产环境部署反爬时始终记住这条原则服务端校验是第一优先级前端混淆只是增加障碍不是安全边界。把签名校验、限流、风控、日志审计做扎实才能支撑长期稳定的数据安全体系。回到最开始那个案例。那个让我卡住的反爬站点最终并没有靠某个“神器”或“大招”破解。真正解决问题的是把环境检测、Cookie生成、请求签名三条链路分开整理然后用断点动态观察逐步缩小范围。这种“拆解链路 动态验证”的方法才是应对复杂反爬最可靠的能力。希望你读完这篇内容后也能带着这套思路去面对下一个难点。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价