ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

抖音 Web 端 a_bogus、X-Bogus 算法拆解:从浏览器参数到请求签名

抖音 Web 端 a_bogus、X-Bogus 算法拆解:从浏览器参数到请求签名 抖音 Web 端 a_bogus、X-Bogus 算法拆解从浏览器参数到请求签名摘要本文基于本地web目录的四个文件专门拆解抖音 Web 端a_bogus、X-Bogus的参数链路、浏览器环境、JavaScript 签名器和 Python 请求编排。文章只保留结构性信息真实 Cookie、msToken、verifyFp、webid和完整签名统一脱敏。关键词抖音 a_bogus、X-Bogus、六神算法、detail.py、浏览器指纹、请求签名、SM3、RC4、Web 协议分析文章目录抖音 Web 端 a_bogus、X-Bogus 算法拆解从浏览器参数到请求签名先说结论Web 侧不是 Android 七神的同一套代码一、目录里的文件分别做什么二、detail.py 的请求链路三、19ab.js 的 a_bogus 高层流程1. 对输入做固定后缀处理2. 做双重摘要3. 把 UA 与浏览器环境混入字节数组4. 随机掩码、重排与校验5. 使用自定义 64 字符表编码四、pure / 164 两份实现怎么对照a_bogus_pure.jsa_bogus164.js五、浏览器参数为什么比 aweme_id 更容易出问题六、最容易踩的坑1. 把“六神”当作官方固定名称2. 把硬编码 Cookie 当成长期方案3. 只看签名长度4. 忽略随机与时间5. 把 pure.js 当成标准实现6. 只看 HTTP 2007. 忽略 JavaScript 运行时差异七、建议的脱敏调试基线结语真正难的是把浏览器上下文对齐先说结论Web 侧不是 Android 七神的同一套代码“六神”是社区常用称呼不是抖音官方算法名。当前web目录能直接观察到的重点是三条 Web 签名实现线19ab.js导出式调用getABogus由detail.py通过 ExecJS 调用a_bogus_pure.js可读的DualBogusSigner同时提供sign_a_bogus和sign_x_bogusa_bogus164.js另一份同类长签名实现入口是generate_a_bogus。所以本文讨论的是Web 侧的 a_bogus / X-Bogus 请求签名链路不把它和 Android 目录里的 X-Gorgon、X-Khronos、X-Medusa 等字段混成一套更不把本地脚本描述成官方、永久有效或已完成线上验签的实现。图 1从浏览器输入到 a_bogus 生成再到接口响应的高层流程。一、目录里的文件分别做什么文件角色代码中能确认的行为detail.py业务请求编排构造 Query、调用 ExecJS、追加a_bogus、发起 detail GET19ab.js长签名入口getABogus混入参数、data、UA、时间和随机字段再做自定义编码a_bogus_pure.js可读对照实现DualBogusSigner同时提供短签名和长签名接口a_bogus164.js同类历史实现generate_rc4_bb_str→generate_random_str→generate_a_bogus图 2业务入口、浏览器上下文、参数调度和 signer 的职责边界。二、detail.py的请求链路detail.py的核心流程可以压缩成六步准备device_platform、aid、channel、aweme_id等业务参数补齐浏览器语言、平台、屏幕、CPU、内存、网络和版本字段放入webid、msToken、verifyFp、fp等动态上下文用urllib.parse.urlencode序列化 Query调用19ab.js的getABogus(query, data, userAgent)把返回值追加到params[a_bogus]再请求/aweme/v1/web/aweme/detail/。对应的脱敏伪代码如下值全部是占位符params{device_platform:webapp,aid:AID,channel:CHANNEL,aweme_id:AWEME_ID,browser_name:BROWSER,browser_version:VERSION,screen_width:WIDTH,screen_height:HEIGHT,webid:WEBID,msToken:MS_TOKEN,verifyFp:VERIFY_FP,fp:VERIFY_FP,}queryurllib.parse.urlencode(params)a_bogusjs.call(getABogus,query,,USER_AGENT)params[a_bogus]a_bogus responserequests.get(https://www.douyin.com/aweme/v1/web/aweme/detail/,paramsparams,headersREDACTED_HEADERS,)这里有两个工程重点先固定 Query再签名最后追加a_bogus签名后不要再偷偷改变参数顺序、编码或 UA。当前源码把空 Body 传成None而 JavaScript 中又执行data dhzx在 JavaScript 语义下可能把null转成字符串的一部分。这是一个值得单独验证的实现细节不能直接当成服务端协议结论。三、19ab.js的 a_bogus 高层流程19ab.js的getABogus不是简单的 MD5 拼接大致可拆成下面几层1. 对输入做固定后缀处理代码会把 Query 和 data 分别拼接固定后缀再进入后续处理。源码中能看到dhzx字样这类固定后缀属于实现输入的一部分版本变化后可能改变。2. 做双重摘要get_arr内部实现了 SM3 风格的压缩流程get_arr29会分别处理参数串和 data并取摘要中的部分字节参与后续字段组装。文章只解释数据流不展开常量表和可复用签名材料。3. 把 UA 与浏览器环境混入字节数组UA 会经过数组置换、异或和自定义编码同时时间戳、两次时间的微小差值、UA 长度、窗口环境、AID、pageId等字段会进入中间数组。也就是说同一组 Query 换一个 UA、窗口尺寸或时间输出就可能变化。4. 随机掩码、重排与校验代码使用随机字节生成掩码对数组进行重排并计算异或校验再把结果拼成字符串。随机性意味着同一输入不一定得到同一串文本调试时应比较字段长度、字符集和中间阶段而不是硬编码最终值。5. 使用自定义 64 字符表编码最终结果使用定制字符表做 Base64-like 编码形成约 160 字符左右的a_bogus字符串。当前目录的不同实现和历史样例长度并不完全一致不能用“长度正确”代替线上兼容性验证。四、pure / 164 两份实现怎么对照a_bogus_pure.jsDualBogusSigner暴露两条入口sign_a_bogus(query, userAgent)处理 Query、固定后缀、UA、时间字段和窗口环境再做 RC4 与s4表编码sign_x_bogus(query, body)对 Query/Body 做双重摘要组装短载荷、随机 key 和校验字节再用 RC4 与s2表编码。这份文件适合阅读模块边界但审计发现其中的 SM3 压缩实现和标准 SM3 有差异且字段装配与a_bogus164.js并非完全等价。因此它更适合作为实验性对照实现不能直接宣称是真实服务端算法。a_bogus164.js这份代码把流程拆成generate_rc4_bb_str、generate_random_str和generate_a_bogus。它同样会混入 Query、UA、窗口环境、时间、AID、pageId和随机字段再经过 RC4 与自定义 64 表编码。文件末尾带有历史测试调用版本字段、UA 和示例环境互相并不完全一致这也是版本漂移的直接证据。五、浏览器参数为什么比 aweme_id 更容易出问题Web 请求通常可以分成四层业务层aweme_id、接口路径、分页或场景字段版本层device_platform、aid、channel、version_code、version_name能力层屏幕尺寸、CPU 核数、内存、网络类型、浏览器和渲染引擎字段身份层webid、msToken、verifyFp/fp、Cookie 和 referer。这些字段不是越多越好而是要互相一致。例如UA 声称 Chrome 版本与browser_version不匹配Windows 平台与移动端字段混用Query 编码前后发生二次转义签名前使用一个 UA发请求时又换了另一个 UACookie、msToken、verifyFp已过期却只重新生成a_bogus。当前目录还存在历史快照之间的环境不一致detail.py的屏幕/UA 参数、19ab.js内部环境字符串以及pure/164里的固定窗口字段并不完全相同。它们应视为不同版本或实验样例不能拼接成一套“标准环境”。图 3字段名和职责可以展示真实 Cookie、Token、webid 和完整签名不要公开。六、最容易踩的坑1. 把“六神”当作官方固定名称当前目录的代码围绕a_bogus/X-Bogus而不是 Android 七神容器。文章、标题和对外宣传应明确 Web 侧视角。2. 把硬编码 Cookie 当成长期方案detail.py内有完整样式的 Cookie、msToken、verifyFp和webid。它们可能过期、失效或属于特定会话不能原样复制到博客、日志、截图或示例代码。3. 只看签名长度本地函数能返回 16 字符或约 160 字符只能说明输出走通。没有官方 golden vector、服务端对照和目标版本样本时不能把长度、字符集或 Base64 外观当作线上验签。4. 忽略随机与时间a_bogus过程混入Date.now()和随机字段重复运行出现不同结果是预期现象。回归测试应固定输入、记录时间窗口并比较中间摘要与结构。5. 把 pure.js 当成标准实现当前 pure 版本与标准 SM3、a_bogus164.js的字段装配存在差异。它适合做阅读和模块拆分不适合直接宣传成现网通杀方案。6. 只看 HTTP 200需要同时记录 HTTP 状态、业务 JSON、响应体大小、错误字段和分页状态。请求成功返回 200不代表业务层已经接受全部上下文。7. 忽略 JavaScript 运行时差异19ab.js和a_bogus164.js存在隐式全局变量、加载即执行测试输出等写法放进严格模式、CommonJS 或长期驻留进程后可能出现状态污染、重复初始化或ReferenceError。部署前应把函数封装进明确模块隔离随机状态并为目标 Node/ExecJS 运行时单独做回归。七、建议的脱敏调试基线推荐“一条请求、一个 UA、一个固定 Query、一个占位会话”开始记录参数名、编码后 Query 的长度和摘要用WEBID、MS_TOKEN、VERIFY_FP、COOKIE_REDACTED替换敏感值记录a_bogus/X-Bogus的长度、字符集和生成耗时对比签名前 Query 与最终 URL确认只新增预期字段记录 UA、屏幕、平台和版本字段是否一致把服务端响应和版本信息加入 golden case不把本地格式检查写成“永久线上可用”。本地脱敏检查可以验证sign_a_bogus输出约 159 字符、sign_x_bogus输出 16 字符字符集落在自定义 Base64 范围内这只是结构性结果不代表服务端验签通过。结语真正难的是把浏览器上下文对齐真正影响稳定性的是 Query 顺序、URL 编码、UA、窗口环境、时间随机性、动态会话和接口版本能否处在同一条请求链上。本文只对本地web目录做结构化阅读不公开任何可复用凭据也不把实验性实现包装成官方算法。说明版本、页面脚本和服务端策略会变化。本文用于协议阅读、兼容性测试和工程排错真实 Cookie、Token、webid、verifyFp 与完整签名值均不应公开。
返回列表