某盾blackbox指纹分析学习

免责声明:

  • 本文章主要用于技术交流学习,作者不承担任何滥用技术所产生的法律责任。如有侵权,请联系作者删除!

流程分析

blackbox值

  • 上面截图函数就是对tokenId做了处理 返回的值就是 使用的 blackbox 需要把这段代码扣下来
// 第一次流程简化
var ooOo0 = [oo0OOo[642][oo0OOo[1037]](oo0OOo[408][oo0OOo[354]](QOOO0[oo0OOo[1274]](0, 1))), QOOO0[oo0OOo[1274]](1, 4), QOOO0[oo0OOo[1274]](4, 14), QOOO0[oo0OOo[1274]](14, 22), QOOO0[oo0OOo[1274]](22, 23)];

// 手动还原后
var ooOo0 = [
    'ghijklmnopqrstuv'['charAt'](
        '0123456789abcdef'['indexOf'](
            '3WPH1725435677YrufaTno6'['substring'](0, 1)
        )
    ),
    '3WPH1725435677YrufaTno6'['substring'](1, 4),
    '3WPH1725435677YrufaTno6'['substring'](4, 14),
    '3WPH1725435677YrufaTno6'['substring'](14, 22),
    '3WPH1725435677YrufaTno6'['substring'](22, 23)
];

// 第二次流程简化
OQO0o = [OOo0o[parseInt(Q0Oo0O(window[OoOoo0[296]][OoOoo0[1385]](), 62))], OOo0o[parseInt(Q0Oo0O(window[OoOoo0[296]][OoOoo0[1385]](), 62))], OOo0o[parseInt(Q0Oo0O(window[OoOoo0[296]][OoOoo0[1385]](), 62))]];

// 手动还原后
function multiplication(data1, data2) {
    return data1 * data2;
}
OQO0o = [
        data[parseInt(
            multiplication(Math['random'](), 62)
        )],
        data[parseInt(multiplication(Math['random'](), 62))],
        data[parseInt(multiplication(Math['random'](), 62))]
    ];

// 处理tokenId
function getTokenId(tokenId) {
    let result = '';
    let data = [
        "A",
        "B",
        "C",
        "D",
        "E",
        "F",
        "G",
        "H",
        "I",
        "J",
        "K",
        "L",
        "M",
        "N",
        "O",
        "P",
        "Q",
        "R",
        "S",
        "T",
        "U",
        "V",
        "W",
        "X",
        "Y",
        "Z",
        "a",
        "b",
        "c",
        "d",
        "e",
        "f",
        "g",
        "h",
        "i",
        "j",
        "k",
        "l",
        "m",
        "n",
        "o",
        "p",
        "q",
        "r",
        "s",
        "t",
        "u",
        "v",
        "w",
        "x",
        "y",
        "z",
        "0",
        "1",
        "2",
        "3",
        "4",
        "5",
        "6",
        "7",
        "8",
        "9"
    ];

    function multiplication(data1, data2) {
        return data1 * data2;
    }
    let list1 = ['ghijklmnopqrstuv'['charAt'](
        '0123456789abcdef'['indexOf'](
            tokenId['substring'](0, 1)
        )
    ),
        tokenId['substring'](1, 4),
        tokenId['substring'](4, 14),
        tokenId['substring'](14, 22),
        tokenId['substring'](22, 23)
    ];
    // console.log(list1);
    let list2 = [
        data[parseInt(
            multiplication(Math['random'](), 62)
        )],
        data[parseInt(multiplication(Math['random'](), 62))],
        data[parseInt(multiplication(Math['random'](), 62))]
    ];
    // console.log(list2);
    // 拼接
    function spliceStr(data1, data2) {
        return data1 + data2;
    }
    result = list1[0]+list1[1]+list2[0]+list1[2]+list2[1]+list1[3]+list2[2]+list1[4];
    return result
}

console.log('3WPH1725435677YrufaTno6')
console.log(getTokenId('3WPH1725435677YrufaTno6'))

// 要注意ghijklmnopqrstuv 等一些固定值是不是变化的
  • 这样就可以通过代码生成blackbox 但是还缺少 tokenId

分析 tokenId

// 这个请求返回的tokenId   
https://fp.tongdun.net/web3_8/r.json?partner=jxhk&app_name=jxhk_web&token_id=cWPH1733109670mouV54Qzf&idf=1733109671990-15403305556&v=nmqSExS4nvV7l39nSgR0OabSEMMu0v0zACJulf3%2FJna%3D&w=EMyZht3WtNwm4HQ%2FZPCyPD7YjboTPsMA0ZUcDsajveL%2BSllDOeXLqMYWZU%2BJElGx&a=soUKxsAasXrEuiAnnlJ85ujsoJfkXXOttfH0L4kc6mmaAcf%2FNvP0lDtP4ZFIqmINg3GTrn3jTFleEAd04sUuoXCwugOG8PWWIps7OlaTLVhUZ6Sob2lKaupeDQYjWsSFJu6Qp%2But%2Bpp4RbRi443LMHGg6sUehOKkGZHfWqtj%2Fhqgq6namcw003fPyIFSIp39ladCqQy7%2BFMfXz2pK41LbXz5hCPSxfwnwQF23QSO2UkQDxUUlBMqx%2BB3eaX7rcCblKKRwesqUnPph2LvB9xJE%2FV4ht4Dp2K08MKVExAeOa1oys93nmEO%2BdjO9JDjSCoOe8lf5Z3vWvcKbIflpmnZRoh0wc27VGkTr746eBPOyNz2eCqDh8%2BMUmqz7L9GusKhDW6Uej33Bb4ruXnZy8hr4LWnjOsmRtgfQSj8MwXmE2vvYK%2F8YQaMntRdMNshgKPnVtgw0TCKA8GA9UNsFsgI1yDJN%2BTap%2BGOj5dJQ%2BzKoze0V1xLSObz5Ot%2F76jSbxb5R7LxKrQlJP7aeRYsbpfgMi8cbeDDDfgUCLorz3Zdm7iTepa7XvWscEhd3BT6i8tMX7wjRBjtCQNi82sEOfkFs55GSm9mOWl7ajFDcbMHR5tE2cyXPPVjcEU0XqILJLRlRUi6QMMPEIvR9XB%2BXzVUZ5OEmhOp36ExniVAciWTGGeyj4tQqdAAB1ME5f2Jz1Nt32Td%2FzDsUAhz2hKIX716y%2B0lQL6NU4hUeogZfrz97QKPS0PDuftpsrKzzSveatSo3j%2FC0Jx4EkoEakkpcWHs12Nx77MIDzgakWGu3FiXAPVkai4IGO3TdxuHrmJ84fpY6QS%2B8wmR%2B%2B2cfWYcL%2FXNetrsnlZAsTXEAwbDPO8sXVwl6qrliVuoYgsBogEShyEfiStxk%2BsdY1POKvrOCvcgkwXKSIFkOASmGUYdPV7MtgidfCZfPCTratSAotplZsAsF2JHcW3Q9lqX%2BicHpI5L1R%2FoUtrMXVhebem1FJQBW9wpQ%2FB61YbhGtvL81%2Bk2n2U1eBnfiSTGJwQANtw&ct=zPnXng%3D%3D

加密分析方案选择

  • 扣代码

// 需要使用ast对js混淆代码还原,替换js进行调试分析,扣取关键代码进行调用生成加密值,分析传入明文值的含义,哪些可以固定,或者被检测
// 这些第一次的环境值 如  
[
    "-",
    "0",
    "41913829c8252e9e775f5241891b77a2|01100100000111000011110011010010000011001010110001111111111011111",
    "808287",
    "-",
    957,
    "48000_2_1_0_2_explicit_speakers",
    480,
    "9fdd23d3687d1d914adcf0bfcbf84b23",
    "1744797361808",
    1920,
    1080,
    "4746e7f5fbc70ef2ccd365c30c93f66a|b0f2202fc3f0f72f424ca4fc6db815df",
    "functiongetParameter(){[nativecode]}",
    "-",
    "-",
    "-",
    "-",
    "-"
]
  • 补环境

需要有相关的js补头的相关经验,或者自己有使用过相关开源的补环境框架,先分析js运行流程,使用挂上代理,运行js看报错信息,
缺啥补啥,尽量使其结果跟浏览器一致,补到运行js可以出加密值,或者关键位置为止,然后还有对相关的浏览器环境检测部分指纹进行对比,防止被检测

td补环境

// 我对ast还原js代码掌握的比较浅,不还原的话分析起来掉头发,而且听分析过td的朋友说,它的加密算法是动态的,所以就尝试用补环境的方式来分析

js运行逻辑简单分析

// 打开控制台  发现 blackbox 已经被打印输出
// 注意单独打开调试窗口,同一个页面打开有些值会被检测到 比如浏览器的一些宽高

// 让AI帮我们分析一下 

// 同盾设备指纹服务(新版)
var _blackbox = "";
(function () {
    window._fmOpt = {
        partner: 'jxhk',
        appName: 'jxhk_web',
        token: 'jxhk' + "-" + new Date().getTime() + "-" + Math.random().toString(16).substr(2),
        fmb: true,
        success: function (data) {
            _blackbox = data;
            console.log('blackbox: ', data)
        },
        fpHost: "https://fp.tongdun.net"
    };
    var cimg = new Image(1, 1);
    cimg.onload = function () {
        _fmOpt.imgLoaded = true;
    };
    cimg.src = "https://fp.tongdun.net/fp/clear.png?partnerCode = jxhk & appName=jxhk_web & tokenId=" + _fmOpt.token;
    var fm = document.createElement('script'); fm.type = 'text/javascript';
    fm.async = true;
    fm.src = ('https:' == document.location.protocol ? 'https://' : 'http://') +
        'static.tongdun.net/v3/fm.js?ver=0.1&t=' + (new Date().getTime() / 3600000).toFixed(0);
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(fm, s);
})();

// 关键就在 fm.js 文件

// 流程大概就清楚了


// 同盾设备指纹服务(新版)
// 定义全局变量_blackbox,用于存储设备指纹数据
var _blackbox = "";

// 使用立即执行函数(IIFE)封装代码,避免污染全局作用域
(function () {
    // 在同盾的全局配置对象window._fmOpt中设置参数
    window._fmOpt = {
        partner: 'jxhk',  // 合作伙伴标识
        appName: 'jxhk_web',  // 应用名称
        // 生成唯一token:合作伙伴+时间戳+16位随机数
        token: 'jxhk' + "-" + new Date().getTime() + "-" + Math.random().toString(16).substr(2),
        fmb: true,  // 是否启用设备指纹的标记
        // 设备指纹生成成功后的回调函数
        success: function (data) {
            _blackbox = data;  // 将生成的设备指纹存入全局变量
            console.log('blackbox: ', data)  // 打印设备指纹(调试用)
        },
        fpHost: "https://fp.tongdun.net"  // 设备指纹服务域名
    };

    // 创建一个1x1像素的隐藏图片(用于跟踪或清除缓存)
    var cimg = new Image(1, 1);
    // 图片加载完成后的回调
    cimg.onload = function () {
        _fmOpt.imgLoaded = true;  // 标记图片已加载
    };
    // 设置图片源URL,携带合作伙伴和应用信息
    cimg.src = "https://fp.tongdun.net/fp/clear.png?partnerCode=jxhk&appName=jxhk_web&tokenId=" + _fmOpt.token;

    // 动态创建script标签加载设备指纹主脚本
    var fm = document.createElement('script');
    fm.type = 'text/javascript';
    fm.async = true;  // 异步加载
    // 根据当前页面协议选择http/https,并添加时间戳参数避免缓存(每小时更新)
    fm.src = ('https:' == document.location.protocol ? 'https://' : 'http://') +
        'static.tongdun.net/v3/fm.js?ver=0.1&t=' + (new Date().getTime() / 3600000).toFixed(0);
    
    // 获取页面第一个script元素
    var s = document.getElementsByTagName('script')[0];
    // 在第一个script标签前插入我们的脚本
    s.parentNode.insertBefore(fm, s);
})();

// 生成加密值发包js代码
fm.js 文件 运行 -> blackbox:  qWPHk1744798953UYMkWnFE9W2

// 那我们只要针对这两段js进行补环境就可以得到我们想要的值了

td补环境

// 建议找个补环境开源框架进行操作,节省时间,也可以自己写(注意原型链的补全和toString检测)

// 挂上代理看报错信息,缺啥补啥,尽量保持和浏览器一致,因为是本地挂代理运行,js的运行逻辑调试几遍也会更清晰

// tdjs访问的一些浏览器api 需要细心对比与浏览器运行出来的值的差异,有差异的地方要看一下会不会检测

// 使用生成blackbox 可以正常登录

我调试用的js关键部分打了断点可以方便分析
通过网盘分享的文件:调试.js
链接: https://pan.baidu.com/s/1sMehqnWLTuaK1gF9huWpaw?pwd=2qfc 提取码: 2qfc 

posted @ 2025-04-16 19:16  郭楷丰  阅读(417)  评论(1)    收藏  举报
Live2D