JS逆向实战:抖音__ac_signature参数逆向与脚本开发

JS逆向实战:抖音__ac_signature参数逆向与脚本开发

前篇文章《JS逆向实战:某音a_bogus参数逆向,从抓包到Python刷播放量脚本全记录》我们讲解了抖音a_bogus参数的逆向过程。这篇接着来讲抖音的另一个加密参数__ac_signature

另外,上篇文章的 Python课件代码 忘记放下载链接了,后台看到不少粉丝私信问我要。既然大家这么感兴趣,我就顺便优化了一下,推出了抖音推流助手Pro_v1.2,下载链接放在文末,这次保证不会忘记了。

图1:抖音推流助手Pro_v1.2界面预览

本文目录

  1. 参数分析:为什么要搞定_signature
  2. 准备工作:两个浏览器插件
  3. 抓包分析:__ac_signature的生成流程
  4. 油猴脚本:拦截cookie定位加密入口
  5. 堆栈分析:找到加密核心函数
  6. 代码扣取:提取加密算法逻辑
  7. 环境补全:适配Node.js运行环境
  8. 本地验证:成功生成47位_signature
  9. 获取源码

一、参数分析:为什么要搞定_signature

以视频播放量+1这个接口为例,要动态生成临时身份cookie(即 ttwid),需要先拿到 __ac_nonce,然后用它生成 __ac_signature,最后携带 __ac_signature 去请求页面,才能从响应头中获取到 ttwid

图2:原理图

所以 __ac_signature 是获取 ttwid 的关键参数。这个参数是抖音用于请求签名验证的核心加密参数之一,和之前讲过的 a_bogus 类似。不搞定它,就无法拿到有效的临时身份cookie,后续的播放量+1接口也无法正常请求。

二、准备工作:两个浏览器插件

这一节我们会用到两个浏览器插件:

插件作用
Cookie-Editor管理/删除cookie,方便测试
油猴(Tampermonkey)插桩调试,拦截cookie设置
图3:Cookie-Editor和油猴插件

至于具体怎么安装,这里就不多说了,你可以去问问豆包。

三、抓包分析:__ac_signature的生成流程

首先,打开任意一个视频作品页面,用Cookie-Editor插件查看,会发现__ac_signature的值已经被设置了。

操作步骤:

  • 用Cookie-Editor插件删除所有cookie
  • 打开浏览器抓包工具,刷新页面
  • 将筛选条件切换到文档,并勾选保留日志
图4:抓包分析__ac_signature生成流程

观察抓包结果,可以看到请求这个视频作品时发生了2次请求:

请求顺序说明
第一次请求响应头中设置了 __ac_nonce
第二次请求请求cookie中携带了 __ac_nonce 和 __ac_signature,响应头返回 ttwid

结论: __ac_nonce → 生成 __ac_signature → 请求获取 ttwid,环环相扣。想要拿到 ttwid,就必须先把 __ac_signature 这个参数搞定。

四、油猴脚本:拦截cookie定位加密入口

与其全局搜索__ac_signature,不如直接写个油猴脚本进行监控。

油猴脚本代码:

// ==UserScript==
// @name         抖音 __ac_signature 断点捕获
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  当 __ac_signature 被写入 cookie 时自动断下
// @author       You
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    const cookieDesc = Object.getOwnPropertyDescriptor(Document.prototype, 'cookie') ||
                       Object.getOwnPropertyDescriptor(HTMLDocument.prototype, 'cookie');

    Object.defineProperty(document, 'cookie', {
        get: cookieDesc.get,
        set: function(value) {
            if (value && value.includes('__ac_signature')) {
                debugger;
            }
            cookieDesc.set.call(this, value);
        },
        configurable: true
    });
})();

操作步骤:

  • 安装上述脚本并开启监控
  • 用Cookie-Editor删除所有cookie
  • 刷新页面

页面加载时,只要cookie被设置,脚本就会自动断下。

图5:油猴脚本成功拦截cookie设置

五、堆栈分析:找到加密核心函数

断点命中后,查看调用堆栈,向下追溯找到_f3函数。

进入_f3函数后,定位到当前页面文件中的核心代码:

        function _f3(e, t, o) {
            try {
                o && (window.sessionStorage && window.sessionStorage.setItem(e, t),
                window.localStorage && window.localStorage.setItem(e, t));
                var n = 31536e6;
                document.cookie = e + "=; expires=Mon, 20 Sep 1970 00:00:00 UTC; path=/;" + (window.location.protocol == 'https:' ? 'SameSite=None; Secure;' : ''),
                document.cookie = e + "=" + t + "; expires=" + new Date((new Date).getTime() + n).toGMTString() + "; path=/;" + (window.location.protocol == 'https:' ? 'SameSite=None; Secure;' : '')
            } catch (e) {}
        }
        window.byted_acrawler.init({
            aid: 99999999,
            dfp: 0
        });
        var __ac_nonce = _f2("__ac_nonce")
          , __ac_signature = window.byted_acrawler.sign("", __ac_nonce);
        _f3("__ac_signature", __ac_signature),
        _f3("__ac_referer", document.referrer || "__ac_blank", !0);
        try {
            sessionStorage.setItem("__ac_ns", performance.timing.navigationStart)
        } catch (e) {}
        ;window.location.reload();

代码分析:

  • _f3函数负责在cookie中设置__ac_signature的值
  • __ac_signature是通过window.byted_acrawler.sign函数,使用__ac_nonce参数生成的
  • 跟进sign函数后发现,加密算法逻辑在当前页面的另一个<script>标签中
图6:堆栈分析找到_f3函数和byted_acrawler.sign

六、代码扣取:提取加密算法逻辑

找到加密算法逻辑后,将所有相关代码扣取下来,保存为_signature.js

修改代码:

_signature.js文件中搜索else if (A > -1),在第一个匹配位置添加以下代码:

else if (A > -1)
{
    if (S.length == 8)
        window.byted_acrawler = S[3][0];
    return [1, S[R--]] 
}

作用说明: 这段代码将加密函数导出到全局变量window.byted_acrawler,方便后续在Node.js环境中调用。

七、环境补全:适配Node.js运行环境

创建一个env.js文件,用于补全浏览器基础环境:

// env.js
window = global;

location = {
    "ancestorOrigins": {},
    "removeItem": function(){},
    "getItem": function(){},
    "href": "https://www.douyin.com/video/7620763641189339642",
    "origin": "https://www.douyin.com",
    "protocol": "https:",
    "host": "www.douyin.com",
    "hostname": "www.douyin.com",
    "port": "",
    "pathname": "/video/7620763641189339642",
    "search": "",
    "hash": ""
};

document = {
    "location": location,
    "cookie": "",
    "referrer": "https://www.douyin.com/video/7356927761941925120",
};

navigator = {
    "webdriver": false,
    "userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36',
    "platform": "Win32",
    "appCodeName": "Mozilla",
    "appName": "Netscape",
    "appVersion": "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36',
    "language": "zh-CN",
    "product": "Gecko",
    "productSub": "20030107",
    "vendor": "Google Inc.",
    "vendorSub": "",
    "cookieEnabled": true,
    "hardwareConcurrency": 12,
    "connection": "NetworkInformation",
    "downlink": 10
};

八、本地验证:成功生成47位_signature

最后创建一个main.js,先调用byted_acrawler.init初始化对象,再调用sign函数生成__ac_signature

// main.js
require('./env');
require('./_signature');

window.byted_acrawler.init({
    aid: 99999999,
    dfp: 0
});

var __ac_nonce = "06a17dd1c00004c526e88";
var __ac_signature = window.byted_acrawler.sign("", __ac_nonce);

console.log('✅ __ac_nonce:', __ac_nonce);
console.log('✅ __ac_signature:', __ac_signature);
console.log('✅ 长度:', __ac_signature.length);

可以看到生成的__ac_signature长度为47位,与浏览器中生成的长度完全一致。

图7:Node.js运行结果,成功生成47位_signature

九、获取源码

👉获取完整代码课件:抖音推流助手Pro v1.2.zip

🔔后续代码持续更新,欢迎关注公众号【孤狼网络科技】

温馨提示:如在安装或使用过程中遇到问题,或发现bug,欢迎反馈交流。

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注