【技术深水区】抖音 WEB 端逆向:从零到一拿下 a_bogus 参数

前言

a_bogus 相比于之前的 x-bogus,这家伙隐藏得更深,而且裹挟着 JSVMP 混淆,让很多想要抓取数据的同学头疼不已。

注意 :本文仅用于技术学习与交流,请勿用于非法爬取商业数据,所有后果自负。

一、什么是 a_bogus?

在抖音的 WEB 端请求中,a_bogus 是一个必不可少的请求签名参数

它的作用类似于一张"动态身份证",服务端会根据请求的 URL、参数、环境指纹等计算出签名,只有签名正确,服务器才返回真实数据。如果你直接复制浏览器里的请求链接,或者单纯注释掉 a_bogus,返回的数据要么是空的,要么直接是 403。

二、逆向分析环境准备

正式开始之前,你需要具备以下基础(如果你已经是大佬,请跳过):

  • 熟悉浏览器的开发者工具 (Network 面板、Sources 面板)。
  • 掌握 XHR 断点条件断点日志断点 的用法。
  • 了解基础的 JavaScript 语法。
  • 知道如何利用 curlconverter 将请求转换为 Python 代码。

三、实战拆解:追踪 a_bogus 的生成逻辑

1. 选取目标接口

以抖音的关键词搜索接口 为例:

复制代码
https://www.douyin.com/aweme/v1/web/general/search/single/

这个接口用于搜索视频内容,参数复杂且加密严密,是逆向分析的绝佳对象。

2. 接口参数分析

打开浏览器开发者工具,刷新页面,在 Network 面板中找到上述接口。

复制它的 cURL(bash),使用 curlconverter.com 转换为 Python 代码,方便我们测试。

观察请求参数,你会发现除了常规的 keyword、offset 等参数外,还有两个让人头疼的变量:msTokena_bogus

分别注释掉这两个参数进行请求,发现缺了任何一个都会导致请求失败。本文我们重点攻克 a_bogus

3. 定位加密位置

3.1 全局搜索失效

直接在 Sources 面板搜索 a_bogus,发现代码被混淆,根本搜不到明文。这说明抖音做了代码混淆,我们需要换一种思路------XHR 断点

3.2 使用 XHR 断点

在 Sources 面板右侧,找到 XHR/fetch Breakpoints ,点击 +,输入接口路径的关键词 general/search/single。

设置好后刷新页面,页面会自动断在发送请求的代码处。 3.3 分析堆栈调用

断下来后,查看右侧的 Call Stack (调用堆栈)。

堆栈是从下往上执行的,我们需要找到 生成 a_bogus 的那个堆栈帧。

  • 往下翻堆栈,找到 请求参数中还没有 a_bogus 的地方。
  • 往上翻,找到 请求参数中已经有了 a_bogus 的地方。

这两个位置之间的某个函数,就是加密函数。关键点 :不要只找一个堆栈就停下,要逐个查看作用域(Scope)中的 params 或 data 对象,看是否有 a_bogus 字段。

4. 精细调试:日志断点与条件断点

最终,我们定位到了一个混淆很严重的 JS 文件(通常是 bdms.js 之类的),代码看起来像这样:

复制代码
var result = s.apply(b, u);

这个地方很难一眼看出 s 是干什么的,但我们可以设置日志断点

在 s.apply(b, u) 这行右键,选择 Add logpoint ,输出内容设为:

复制代码
返回值:{result}

刷新页面,看控制台打印的日志,你会发现有很多 true、false、数字以及字符串

观察那些字符串,你会惊奇地发现:

  • 短的那一串看起来像是我们请求的 URL 参数拼接。
  • 长的那一串长度大约在 160 位左右,看起来就是我们要找的 a_bogus。

为了精准定位,我们可以设置条件断点 :比如当返回值长度大于 150 时再断下来。

复制代码
result.length > 150

最终,我们找到了生成 a_bogus 的核心函数,它在 e 函数内部。

四、补环境与代码封装

找到核心函数后,将 bdms.js 文件下载到本地。

1. 补环境

直接运行这段 JS 会报错,因为缺少浏览器环境(window, document, navigator 等)。我们需要模拟这些环境:

python 复制代码
window = global;
delete global;
delete Buffer;

window.requestAnimationFrame = function(){};
XMLHttpRequest = function() {};

document = {}
navigator = {};

screen = {
    availHeight: 816,
    availLeft: 0,
    availTop: 0,
    availWidth: 1536,
    colorDepth: 24,
    height: 864
}

2. 导出加密函数

分析函数调用逻辑,发现 e 函数被调用时的参数 u 包含了很多环境信息(如 UA、屏幕宽高等)和请求参数。

我们可以将其封装成一个标准的 getSign 函数,只接收 params 字符串作为入参:

python 复制代码
function getSign(params) {
    u = [
        0,
        1,
        14,
        params,
        "",
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0"
    ]

    var r = window.sign_z._v;
    return (0,window.sign_z._u)(r[0], u, r[1], r[2], this)
}

这样,在 Python 中调用 execjs 执行这段代码,输入参数字符串,就能得到 a_bogus 了。

五、最终测试

复制代码
# 伪代码示例`
`import execjs`
`import requests`

`with` `open('douyin.js',` `'r', encoding='utf-8')` `as f:`
`    ctx = execjs.compile(f.read())`

`params_str =` `"device_platform=webapp&aid=6383&keyword=飞驰人生2..."`
`a_bogus = ctx.call('getSign', params_str)`

`print(a_bogus)`  `# 输出类似:mXmZMdzgdDfiDDWX5VcLfY3q6WB3Y/R30CPYMD2f7dVr...

将生成的 a_bogus 塞回请求参数中,你会发现数据正常返回了。

写在最后

看到这你已经对抖音 WEB 端的加密参数 a_bogus 有了比较深的理解。

  • 但是,抖音的反爬体系是动态更新的:msToken 和 a_bogus 的算法是否会变?
  • 补环境的时候是否需要更多指纹?
  • 如果被封 IP 了怎么办?

逆向是一场无止境的博弈。

想直接拿到稳定、高并发、低延迟的解决方案,可以查看我的主页,有封装好的 API 接口和完整的 SDK。

如果你有定制需求,也欢迎直接私信我。

相关推荐
万少17 分钟前
Vibe Coding不停歇,移动端 TRAE SOLO 让你用手机也能编程啦
前端·javascript·后端
landyjzlai37 分钟前
蓝迪哥玩转Ai(8)---端侧AI:RK3588 端侧大语言模型(LLM)开发实战指南
人工智能·python
kyriewen1140 分钟前
WebAssembly:前端界的“外挂”,让C++代码在浏览器里跑起来
开发语言·前端·javascript·c++·单元测试·ecmascript
烛衔溟1 小时前
TypeScript 接口的基本使用 —— 定义对象形状
前端·javascript·typescript
铁皮饭盒2 小时前
成为AI全栈 - 第3课:路由 RESTful Elysia 状态码 设计规范
前端·后端·全栈
顾昂_2 小时前
Web 性能优化完全指南
前端·面试·性能优化
我叫黑大帅2 小时前
如何通过 Python 实现招聘平台自动投递
后端·python·面试
其实防守也摸鱼3 小时前
CTF密码学综合教学指南--第九章
开发语言·网络·python·安全·网络安全·密码学·ctf
砚底藏山河3 小时前
Python量化开发:2026最佳实时股票数据API接口推荐与对比
开发语言·windows·python
前端程序媛-Tian3 小时前
前端 AI 提效实战:从 0 到 1 打造团队专属 AI 代码评审工具
前端·人工智能·ai