a_bogus 算法逆向实战:从日志插桩到乱码解析

张开发
2026/4/12 16:18:17 15 分钟阅读

分享文章

a_bogus 算法逆向实战:从日志插桩到乱码解析
1. 初识a_bogus算法第一次看到a_bogus这个参数时我盯着那串44位的乱码看了半天。这玩意儿看起来像base64但又不是长度固定但内容每次请求都变。作为前端加密参数它出现在某音Web端几乎所有重要接口的请求中。记得当时我随手抓了个包发现请求头里带着这么个东西a_bogus: DFSzswVOAATANH89SMHZqF9WX7n6最让人头疼的是这个参数在JS里根本搜不到明文字符串。后来才知道这是典型的JSVMPJavaScript Virtual Machine Protection保护代码被编译成字节码在虚拟机上执行传统的搜索大法完全失效。2. 逆向分析的核心思路面对JSVMP我总结出两条路要么硬刚补环境要么走纯算法还原。补环境需要对JS执行上下文有深刻理解而算法还原则更考验耐心和日志分析能力。我选择了后者因为补环境容易被反调试检测到纯算法还原后代码更轻量能真正理解加密逻辑关键突破口在于插桩日志。我在关键位置插入这样的日志代码console.log([位置1] 索引m${m} 索引r${r} 值p, JSON.stringify(p, (k,v) v window ? undefined : v))这样能在不破坏执行流程的前提下输出所有关键变量的中间状态。记住三个黄金插桩点位运算前后数组操作前后字符串转换点3. 乱码生成逻辑解析通过分析上万行日志我发现a_bogus的核心在于三层乱码转换3.1 第一层时间戳转换初始乱码来自时间戳的位运算let t Date.now(); let n1 t 255; // 取低8位 let n2 (t 8) 255; // 取8-15位 // 关键位掩码操作 let part1 [ (n1 170) | (3 85), // 1700xAA, 850x55 (n1 85) | (3 170), (n2 170) | (66 85), (n2 85) | (66 170) ]; let lm_part1 String.fromCharCode(...part1);这个阶段会生成4字节的乱码头比如ƒBàR。其中170和85这两个魔数反复出现它们的作用是交替提取比特位。3.2 第二层UA参与运算用户代理字符串会被转换成256位的S盒function buildSBox(ua) { let sbox Array(256).fill(0).map((_,i) i); let j 0; for(let i0; i256; i) { j (j sbox[i] ua.charCodeAt(i % ua.length)) % 256; [sbox[i], sbox[j]] [sbox[j], sbox[i]]; // ES6交换语法 } return sbox; }这个S盒会与初始乱码进行异或let sbox buildSBox(navigator.userAgent); let lm_part2 ; for(let i0; i32; i) { let key sbox[(sbox[i] sbox[j]) % 256]; lm_part2 String.fromCharCode(input.charCodeAt(i) ^ key); }3.3 第三层参数混合请求参数会经过双重MD5处理let paramHash md5(md5(queryParams)); let uint8Array new Uint8Array( paramHash.match(/../g).map(h parseInt(h,16)) );最终与前面生成的乱码拼接let finalGarbled lm_part1 lm_part2 uint8ArrayToString(uint8Array);4. 关键位运算拆解a_bogus最核心的加密在于这三组位操作4.1 三字节合并let num (c0 16) | (c1 8) | c2;这步把3个乱码字符合并成24位整数比如ƒ.charCodeAt(0)131 - 00000000 10000011 B.charCodeAt(0)66 - 00000000 01000010 à.charCodeAt(0)224 - 00000000 11100000 合并后: 10000011 01000010 11100000 (0x8342E0)4.2 掩码提取let mask1 (num 0xFC0000) 18; // 0xFC000016515072 let mask2 (num 0x3F000) 12; // 0x3F000258048 let mask3 (num 0xFC0) 6; // 0xFC04032 let mask4 num 0x3F; // 0x3F63这四个掩码分别提取6位数据0x8342E0 0xFC0000 0x800000 0x800000 18 32 (0x20)4.3 字符映射提取的索引会从固定字符串中取字符const CHAR_MAP Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe; let char1 CHAR_MAP.charAt(mask1); // 32-D let char2 CHAR_MAP.charAt(mask2); // 16-F let char3 CHAR_MAP.charAt(mask3); // 11-S let char4 CHAR_MAP.charAt(mask4); // 32-z5. 完整算法还原流程经过两周的逆向分析我整理出完整生成流程收集输入数据let timestamp Date.now(); let ua navigator.userAgent; let params new URLSearchParams(location.search);生成初始乱码let part1 generateTimePart(timestamp); let part2 generateUAPart(ua, part1);处理请求参数let paramHash md5ToUint8(md5(params.toString()));合并乱码let garbled concatParts(part1, part2, paramHash);分段加密let a_bogus ; for(let i0; igarbled.length; i3) { let chunk garbled.substr(i, 3); a_bogus encodeChunk(chunk); }验证长度console.assert(a_bogus.length 44, 长度校验失败);6. 调试技巧与坑点在逆向过程中我踩过几个大坑坑1字节序问题最初没注意charCodeAt返回的是UTF-16编码导致部分Emoji字符处理出错。解决方案function safeCharCodeAt(str, idx) { let code str.charCodeAt(idx); if (code 0xD800 code 0xDBFF) { let hi code; let low str.charCodeAt(idx 1); return (hi - 0xD800) * 0x400 (low - 0xDC00) 0x10000; } return code; }坑2浮点数精度JS的位运算会把操作数转成32位有符号整数遇到大数时会出错// 错误写法 let num 1693911085250 255; // 正确写法 let num BigInt(1693911085250) 255n;坑3环境检测某音会检测navigator属性最简单的绕过方式Object.defineProperty(navigator, webdriver, { get: () false });7. 算法验证与优化最终实现的算法需要满足同一请求参数多次生成结果不同因为含时间戳不同UA生成结果不同参数变化时结果必须变化验证用例// 测试用例 let params { device_platform: web, aid: 6383, channel: channel_pc_web }; // 生成10次验证差异性 let results new Set(); for(let i0; i10; i) { results.add(generateABogus(params)); } console.assert(results.size 10, 时间戳未生效); // 验证UA影响 let ua1 Mozilla/5.0; let ua2 Chrome/120.0.0.0; console.assert( generateABogus(params, ua1) ! generateABogus(params, ua2), UA未影响结果 );性能优化点预计算CHAR_MAP的索引映射缓存UA生成的S盒使用WebWorker并行计算8. 实际应用中的发现在长期观察中发现几个有趣现象时间容差服务器允许±2分钟的时间偏移UA校验必须包含Mozilla/5.0前缀参数顺序对keyvalue的排序敏感最意外的发现是某音其实会根据a_bogus的质量打分。通过分析大量请求我整理出这个评分规则包含有效时间戳30分UA匹配设备类型20分参数哈希正确50分 总分低于80的请求会被限流。逆向工程就像解谜游戏每次成功还原算法都像解开一道数学难题。虽然某音每隔几个月就会更新算法但核心思路始终围绕位运算和哈希展开。掌握这套分析方法后面对其他平台的加密也能快速找到突破口。

更多文章