拼多多电商数据anti-content参数逆向实战

// 实战案例:拼多多电商数据逆向实战(Anti-Content生成)

// 网址:https://mobile.pinduoduo.com/

概述

拼多多作为国内主流电商平台,其网页端和移动端的数据接口都采用了严格的反爬虫机制。其中 anti-content 参数是一个重要的反爬虫签名参数,用于验证请求的合法性,防止恶意爬取和数据抓取。

网页分析

1759990258925-6e325d1d-0899-4961-bcf9-16cb996ddd61.png

1759990293890-f8351022-1757-4641-a5c4-af3313e26731.png

1759990374756-40837a5b-5118-45d3-8e43-7c3bd4c8e25c.png

1759990485176-1aff7259-3bd8-418f-bcd6-39ca9917b624.png

1759990608315-37e02f81-fdd7-4005-b36c-fc058bfcbc1e.png

1759990643148-7e5f8048-9e9a-4461-aab2-2de7db560dfe.png

1759990732837-8c27e360-53b9-4f6c-8060-88b1b2cbbc63.png

1759990777541-0b8d3835-71c0-4ac8-b1bd-5b6389b7581b.png

1759990826087-c85bdf27-e768-4c7d-9cdf-2b1088b65bf3.png

1759990871138-105d7888-f23e-41fb-b0a6-bcacff3e63ae.png

1759990976076-2514dbf3-f9bd-4b4b-84bf-420db6717189.png

1759991028552-fa12893a-f5ba-4270-93cf-b23a1d5d28c5.png

1759991048170-1af6facd-443a-4be4-bd91-738aef133bb1.png

1759991088297-a370468d-ab57-42fd-9fcd-99f52da7ba0a.png

技术要点

2.1 核心难点

  • 动态加密:anti-content 参数是动态生成的,每次请求都会变化
  • 代码混淆:相关JavaScript代码经过高度混淆和压缩
  • 多重加密:采用了多种加密算法组合
  • 环境检测:包含浏览器环境指纹检测

环境补全实现

3.1 基础环境配置

代理监控系统

4.1 代理实现函数

function setProxy(proxyObjArr) {
    for (let i = 0; i < proxyObjArr.length; i++) {
        const handler = `{
            get: function(target, property, receiver) {
                console.log("方法:", "get  ", "对象:", "${proxyObjArr[i]}", 
                          "  属性:", property, "  属性类型:", typeof property, 
                          ", 属性值:", target[property], 
                          ", 属性值类型:", typeof target[property]);
                return target[property];
            },
            set: function(target, property, value, receiver) {
                console.log("方法:", "set  ", "对象:", "${proxyObjArr[i]}", 
                          "  属性:", property, "  属性类型:", typeof property, 
                          ", 属性值:", value, 
                          ", 属性值类型:", typeof target[property]);
                return Reflect.set(...arguments);
            }
        }`;
        
        eval(`try {
            ${proxyObjArr[i]};
            ${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});
        } catch (e) {
            ${proxyObjArr[i]} = {};
            ${proxyObjArr[i]} = new Proxy(${proxyObjArr[i]}, ${handler});
        }`);
    }
}

4.2 代理对象配置

proxy_array = [
    'window',
    'canvas'
    // 可根据需要添加其他对象
]
setProxy(proxy_array)

代码分析

5.1 模块加载器结构

!function(t) {
    var n = {};  // 模块缓存对象
    
    function r(e) {  // 模块加载函数
        if (n[e]) return n[e].exports;
        var o = n[e] = {
            i: e,
            l: !1,
            exports: {}
        };
        return t[e].call(o.exports, o, o.exports, r),
        o.l = !0,
        o.exports
    }
    
    // 暴露各种工具方法
    r.m = t,        // 模块数组
    r.c = n,        // 缓存对象
    r.d = function(t, n, e) {  // 定义导出属性
        r.o(t, n) || Object.defineProperty(t, n, {
            enumerable: !0,
            get: e
        })
    },
    r.r = function(t) {  // 标记为ES模块
        "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
            value: "Module"
        }),
        Object.defineProperty(t, "__esModule", {
            value: !0
        })
    },
    r.t = function(t, n) {  // 模块转换
        // 处理不同模块格式的转换
    },
    r.n = function(t) {  // 获取默认导出
        var n = t && t.__esModule ? function() {
            return t.default
        } : function() {
            return t
        };
        return r.d(n, "a", n),
        n
    },
    r.o = function(t, n) {  // 检查属性是否存在
        return Object.prototype.hasOwnProperty.call(t, n)
    },
    r.p = "",  // 公共路径
    window.rrr = r  // 暴露到全局对象
}

5.2 核心加密模块

([function(t, n, r) {
    "use strict";
    var e = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? 
        function(t) { return typeof t } : 
        function(t) { /* 类型判断逻辑 */ };
    
    // 实际的加密逻辑在这里
    var anti_content = (new window.rrr(4))().messagePack()
    console.log(anti_content)
}])

逆向思路

6.1 定位关键代码

  1. 全局搜索:在浏览器开发者工具中搜索 anti-content、anti_content 等关键词
  2. 调用栈分析:通过XHR断点追踪参数生成过程
  3. Hook技术:拦截相关函数调用获取加密逻辑

6.2 定位关键代码

从代码片段可以看出:

  • 使用 window.rrr(4) 获取加密模块
  • 调用 messagePack() 方法生成 anti-content
  • 整个加密过程封装在模块化的结构中

完整代码

补环境的另一种实现思路

插件安装包

1755507308603-e06939f2-3c19-477d-828f-1e22311cd077.png

1755507287490-bf7263ac-6fb5-4280-bd6f-053eff0075cf.png

常见问题解决

7.1 环境补全不完整

现象:报错提示某些属性未定义
解决

  1. 检查报错信息中缺失的对象/属性
  2. 在环境初始化部分添加对应的模拟代码
  3. 使用代理监控确认属性访问情况