当前位置: 首页 > news >正文

a_bogus纯算(V1.0.1.19-fix.01)逆向全流程:从日志插桩到算法复现

1. 逆向分析a_bogus算法的完整技术流程

最近在研究某平台的接口加密时,遇到了一个叫a_bogus的参数。这个参数看起来像是一串随机字符,但实际上是通过复杂算法生成的。经过一周的逆向分析,我终于搞清楚了它的生成逻辑。下面就把这个完整的逆向过程分享给大家,希望能帮助到有类似需求的开发者。

这个a_bogus参数在V1.0.1.19-fix.01版本中的生成过程相当复杂,涉及到多层加密和转换。整个过程可以分为几个关键步骤:环境准备、日志插桩、数据收集、日志分析和算法复现。我会按照这个顺序详细讲解每个环节的具体操作。

2. 环境准备与日志插桩

2.1 开发环境搭建

首先需要准备好开发环境,我使用的是以下工具组合:

  • 带有DevTools的Edge浏览器
  • VS Code用于查看和分析日志
  • PyCharm用于编写处理脚本

在实际操作中,我发现直接使用浏览器控制台输出的日志量太大,很容易导致浏览器卡死。于是写了一个日志收集和下载的工具函数,这个函数可以将日志分块保存到本地。

// 将对象转为字符串便于存储 get_obj_str = function(one_obj) { try { return JSON.stringify(one_obj, function(k, v) { if (v == window) return 'window'; else if (typeof v == 'function') return `function ${v.name}`; else if (v && v[Symbol.toStringTag]) return `Symbol ${v[Symbol.toStringTag]}`; else return v; }) } catch (e) {}; } // 添加日志并自动分块下载 add_json_str = function(param_name, param) { var add_log = function(log_str) { var save_log = function(textContent, file_name) { const blob = new Blob([textContent], { type: 'text/plain' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = file_name; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); window.URL.revokeObjectURL(url); }, 0); } window.my_code += log_str; if (window.my_code.length >= 1024 * 1024 * 5) { // 每5MB分块 save_log(window.my_code, `logs${window.my_offset}.txt`) window.my_offset += 1; window.my_code = ""; } } add_log(param_name + " = " + get_obj_str(param) + "\n\n"); };

2.2 定位关键函数

通过分析网络请求,我发现a_bogus参数是在bdms模块中生成的。具体定位方法是:

  1. 打开开发者工具,找到包含a_bogus的请求
  2. 在Fetch/XHR筛选器中找到对应的数据包
  3. 查看发起程序的调用栈,发现a_bogus在bdms模块中生成

多次实验后发现,bdms的入口是5704堆栈,出口是index堆栈。a_bogus就是在入口和出口之间生成的。虽然入口和出口有时会变化,但分析方法是一样的。

2.3 关键函数插桩

找到入口后,我们需要在关键函数内部插入日志点。a_bogus的生成主要在d函数内部,所以重点在这里插桩。插桩的技巧是:

  1. 首先在运算操作符加赋值的地方插桩
  2. 观察d函数,发现使用了v和s两个内存栈
  3. 设置条件断点,记录关键变量的值
// 在d函数内部设置的条件断点示例 if (t < 2) if (0 === t) { var r = o[a++]; p -= r; var e = v.slice(p + 1, p + r + 1) , n = v[p--] , d = v[p--]; if ("function" != typeof n) return f = 3, void (l = new TypeError(typeof n + " is not a function")); var y = V.get(n); if (y) h.push([o, i, u, s, c, a, f, l]), g(y[0], d, e, y[1]); else { var m = n.apply(d, e); v[++p] = m // 插桩记录apply调用结果 add_json_str("v_apply",v),add_json_str("s_apply",s),add_json_str(`${get_obj_str(n)}.apply(${get_obj_str(d)}, ${get_obj_str(e)})`,m),false } }

3. 日志分析与算法推导

3.1 日志预处理

收集到的日志文件通常很大,我这次收集的日志超过了1GB。处理这种大文件,VS Code表现很不错。为了减少日志体积,可以进行以下优化:

  1. 替换重复的长字符串为短变量名
  2. 删除不必要的中间数据
  3. 合并多个日志文件

我写了一个Python脚本来处理日志合并和替换:

import os def replace_log(tup_list, log_file_path): data_lines = [] with open(log_file_path, 'r', encoding='utf-8', errors='replace') as file: data_lines = [line.strip() for line in file.readlines()] for i in range(len(data_lines)): if data_lines[i]: for old_str, new_str in tup_list: data_lines[i] = data_lines[i].replace(old_str, new_str) for old_str, new_str in tup_list: data_lines.append(f'{new_str}={old_str}') os.remove(log_file_path) with open(log_file_path, 'w', encoding='utf-8') as file: file.write('\n'.join(data_lines)) # 替换用户代理字符串等长文本 replace_list = [ ('"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0"', 'ua') ] replace_log(replace_list, '/path/log.txt')

3.2 逆向分析a_bogus生成逻辑

分析日志要从a_bogus完全生成的位置开始,然后倒推它的生成过程。我发现a_bogus的生成主要分为几个阶段:

  1. 基础字符串拼接
  2. 多层加密转换
  3. 最终编码处理

具体来说,a_bogus是通过以下步骤生成的:

// a_bogus生成的核心逻辑 function get_raw_ab(lm_get_ab_n, key_str) { var s = "", bw = 0; for (var i = 0; i < lm_get_ab_n.length; i += 3) { var cl = 16; var tcz = 0; var sof = 16515072; for (var j = i; j < i + 3; j++) { if (j < lm_get_ab_n.length) { var tlcy = lm_get_ab_n.charCodeAt(j) & 255; tcz = tcz | (tlcy << cl); cl -= 8; } else { bw += 1; // 计算补位 } } for (var h = 18; h >= (6 * bw); h -= 6) { var tsz = tcz & sof; s += key_str[tsz >> h]; sof = sof / 64; } s += '='.repeat(bw); } return s; }

这个函数的核心是将输入字符串每3个字符一组进行处理,通过位运算和查表生成最终的a_bogus值。其中key_str是一个特殊的编码表:

info_dic = { "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe" }

3.3 关键算法解析

通过分析日志,我发现a_bogus的生成用到了类似Base64的编码方式,但有几点关键区别:

  1. 使用自定义的编码表而非标准Base64表
  2. 输入字符串先经过多层转换
  3. 包含特殊的补位逻辑

具体编码过程如下:

  1. 将输入字符串按3字节分组
  2. 每组24位拆分为4个6位片段
  3. 每个6位片段作为索引查自定义编码表
  4. 根据剩余字节数添加补位字符

逆向这个算法的难点在于理解中间的转换过程。我通过日志发现,在进入编码函数前,原始输入已经经过了多次转换:

原始输入 -> 加密转换1 -> 加密转换2 -> 最终编码 -> a_bogus

4. 算法复现与验证

4.1 复现加密流程

基于日志分析,我逐步复现了整个加密流程。下面是关键步骤的代码实现:

// 生成中间字符串 function get_lm_g_ab(lm_g_lm_n) { var fixed_sz256_n = [194, 249, 255, 165, 114, 67, 251, 187, 174, 231, 164, 237, 124, 235, 68, 83, 206, 79, 142, 167, 30, 77, 0, 93, 118, 29, 32, 161, 2, 171, 243, 179, 42, 170, 223, 119, 98, 222, 219, 57, 245, 135, 197, 13, 186, 202, 88, 184, 214, 12, 76, 185, 116, 74, 54, 53, 104, 208, 158, 163, 82, 173, 253, 240, 172, 63, 191, 207, 25, 15, 201, 203, 215, 236, 183, 233, 145, 127, 72, 6, 16, 10, 228, 35, 232, 159, 66, 168, 108, 71, 217, 75, 33, 155, 112, 128, 36, 24, 138, 50, 211, 23, 107, 14, 247, 137, 175, 242, 234, 157, 199, 49, 139, 85, 81, 17, 180, 86, 120, 78, 51, 205, 169, 148, 181, 3, 94, 106, 252, 220, 150, 47, 151, 84, 212, 18, 149, 182, 100, 123, 121, 156, 154, 152, 126, 204, 60, 133, 132, 248, 7, 91, 58, 59, 20, 97, 113, 117, 131, 46, 250, 224, 21, 73, 146, 31, 193, 69, 140, 125, 9, 39, 89, 5, 65, 141, 218, 80, 1, 70, 64, 166, 87, 189, 55, 147, 22, 26, 143, 61, 144, 99, 92, 44, 129, 130, 227, 103, 90, 192, 198, 244, 136, 101, 246, 153, 56, 38, 4, 178, 221, 162, 134, 37, 111, 28, 216, 96, 102, 210, 254, 196, 195, 230, 241, 62, 11, 122, 52, 40, 41, 229, 226, 225, 48, 45, 160, 105, 8, 115, 34, 43, 209, 95, 239, 190, 188, 109, 27, 19, 176, 213, 200, 238, 177, 110]; var z = 0; var st = ""; for (var i = 0; i < lm_g_lm_n.length; i++) { var a = (i + 1) % 256; var c = fixed_sz256_n[a]; z = (z + c) % 256; var e = fixed_sz256_n[z]; fixed_sz256_n[a] = e; fixed_sz256_n[z] = c; var g = (e + c) % 256; var h = lm_g_lm_n.charCodeAt(i); var j = fixed_sz256_n[g]; var k = h ^ j; var l = String.fromCharCode(k); st += l; } return st; }

4.2 完整算法实现

将各个步骤组合起来,就得到了完整的a_bogus生成算法:

function generate_a_bogus(dpf, ua) { // 1. 初始化变量和编码表 var info_dic = { "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe" }; // 2. 生成随机数种子 Math.random = function() { return 0.5 }; // 固定随机数便于调试 // 3. 多层加密转换 var lm_get_lm = generate_lm(dpf, ua); var lm_get_ab_tail = get_lm_g_ab(lm_get_lm); var lm_get_ab_head4 = generate_head4(); var lm_get_ab = lm_get_ab_head4 + lm_get_ab_tail; // 4. 最终编码 var a_bogus = get_raw_ab(lm_get_ab, info_dic.s4); return a_bogus; }

4.3 验证算法准确性

为了验证算法的正确性,我对比了生成的a_bogus和实际请求中的值:

// 测试用例 var test_ab = generate_a_bogus(dpf, ua); console.log(test_ab === "O7UfhzU7dNmfCdMbuKpByXrUzhVMrPSyaiTobOMTSDTGT1tbUSN2EcGaJooLiiLyRbB0ie3H0ETMGDVcKsUkZK9pKmZDuPsS5G2nVg0L0qwXYzhsLqRiCh0Fww0C8RtL-5cRi1WRIssx1EAl9qIDABIaH5Pq-O8pRrZVp/YycDcWpBgTVx/CenzWfwj=");

5. 关键技术与难点解析

5.1 自定义编码算法

a_bogus使用的编码算法与Base64类似但有重要区别:

  1. 编码表完全不同
  2. 输入预处理更复杂
  3. 包含额外的加密步骤

核心编码函数的关键部分:

for (var h = 18; h >= (6 * bw); h -= 6) { var tsz = tcz & sof; s += key_str[tsz >> h]; sof = sof / 64; }

这段代码将24位数据分成4个6位片段,然后查表编码。sof初始值为16515072(0xFC0000),每次右移6位。

5.2 多层加密转换

在进入最终编码前,原始数据经过了多层转换:

  1. 用户代理(UA)字符串加密
  2. 请求参数(dpf)加密
  3. 时间戳混合运算
  4. 随机数生成

这些转换使得直接猜测a_bogus的生成逻辑变得非常困难。

5.3 动态密钥数组

算法中使用了一个256字节的固定数组作为加密密钥:

var fixed_sz256_n = [194, 249, 255, 165, ... , 177, 110];

这个数组虽然固定,但它的生成过程相当复杂,通过多步数学运算和位操作得到。

6. 实际应用中的注意事项

6.1 时间戳的影响

在逆向过程中,我发现a_bogus的生成与时间戳密切相关。即使其他参数完全相同,不同时间生成的a_bogus也会不同。这增加了逆向的难度,也说明服务端可能在校验时间有效性。

6.2 随机数的处理

算法中使用了Math.random()生成随机数,但在实际请求中,这些随机数被固定了。这意味着:

  1. 服务端可能不校验随机性
  2. 可以使用固定值代替随机数
  3. 但随机数的存在增加了逆向难度

6.3 参数更新机制

在测试中发现,即使使用完全相同的参数,生成的a_bogus在一段时间后也会失效。这表明:

  1. 服务端可能定期更换加密参数
  2. 需要动态更新算法中的某些固定值
  3. 完全逆向的算法可能需要定期维护

7. 完整实现代码

以下是完整的a_bogus生成算法实现,包含了所有关键步骤:

function generate_full_a_bogus(dpf, ua) { // 1. 初始化编码表 const info_dic = { "s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=", "s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=", "s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=", "s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe", "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe" }; // 2. 固定随机数便于调试 Math.random = function() { return 0.5 }; // 3. 生成加密所需的中间数据 const t1 = Date.now(); const t2 = t1 - 1 + Math.floor(Math.random() * 3); const t3 = t1 + Math.floor(Math.random() * 12) + 4; const t4 = t1 + Math.floor(Math.random() * 900) + 100; // 4. 多层加密转换 const lm_get_EP = generate_lm_g_EP(ua); const EP = get_raw_ab(lm_get_EP, info_dic.s3); const eEP = enc_sum(EP); const eedp = enc_sum(enc_sum(dpf + 'dhzx')); // 5. 生成最终a_bogus const szenc_o95 = generate_szenc_o95(t1, t2, t3, t4, eedp, eEP); const szenc_tail = get_szenc_tail(szenc_o95); const szenc = generate_szenc_head8().concat(szenc_tail); const lm_get_lm = get_list_str(szenc); const lm_get_ab_tail = get_lm_g_ab(lm_get_lm); const lm_get_ab = generate_lm_g_ab_head4() + lm_get_ab_tail; const a_bogus = get_raw_ab(lm_get_ab, info_dic.s4); return a_bogus; }

8. 逆向经验总结

通过这次对a_bogus算法的完整逆向,我总结了几点重要经验:

  1. 系统性分析:从结果倒推,逐步分析每个中间步骤
  2. 日志优化:合理处理日志,减少干扰信息
  3. 模块化验证:将复杂算法拆分为多个小模块分别验证
  4. 动态调试:结合断点调试和日志分析,理解执行流程
  5. 耐心细致:复杂算法逆向需要极大的耐心和细心

这个案例也展示了现代Web应用如何通过多层加密和混淆来保护接口安全。作为开发者,理解这些机制不仅能帮助我们解决爬虫问题,也能提升自身的安全开发能力。

最后需要强调的是,本文的技术内容仅供学习研究之用。在实际应用中,请遵守相关法律法规和网站的使用条款。逆向工程应该以学习和提升技术为目的,而不是用于非法用途。

http://www.jsqmd.com/news/640611/

相关文章:

  • Unlock-Music音乐解锁工具实战:打破平台限制的音乐自由秘籍
  • 告别网盘限速困扰:八大网盘直链解析工具的终极解决方案
  • Xilinx FPGA未使用管脚的默认电平设置方法
  • private-vue的springboot项目介绍
  • Qt高DPI适配实战:从模糊到清晰的界面跨屏方案
  • Cursor Pro免费使用指南:3步解锁AI编程助手完整功能
  • 强化学习玩转目标检测:从决策建模到工业实战
  • 图像识别实战项目
  • 别让电容拖后腿!手把手教你用Multisim仿真分析放大电路的频率响应(附波特图实战)
  • 如何使用Imageflow查询字符串API:轻松实现动态图像变换的完整指南
  • 实战教程:星图平台私有化部署Qwen3-VL:30B,实现本地AI多模态能力
  • 优惠码还有余量!HOW 2026 免费通票抓紧领取
  • 如何让SketchUp设计轻松进入3D打印世界?
  • Jitsi Meet合规性指南:GDPR与HIPAA合规配置实践
  • 4.13学习进度
  • 终极Covenant API开发指南:从零开始扩展自定义功能的完整教程
  • UART接收机设计:如何通过过采样策略提升波特率容错性
  • RabbitMQ系列03 - AMQP分层与协议流转
  • 20252403 2025-2026-2 《Python程序设计》实验2报告
  • 终极Sacred版本升级指南:从旧版本平滑迁移到最新版本的完整教程
  • 深入解析流水线技术:从基本概念到冒险问题的实战解决方案
  • UE4SS技术架构深度解析:从注入原理到虚幻引擎逆向工程完整解决方案
  • 终极指南:DefectDojo多租户架构如何在大型组织中实现资源共享和隔离
  • 5分钟掌握uBlock Origin:让你的浏览器速度提升60%的终极广告拦截方案
  • 大数据分析监测可视化平台
  • 解锁数据科学新境界 —— Jupyter Notebook的革命性工具Text2Code
  • 云原生周刊:Kubernetes v1.36 前瞻
  • LLVM实战:如何用Graphviz可视化你的数据流图(DFG)
  • 如何安装Profanity?从源码到部署的快速入门教程
  • 哪个GEO平台覆盖的AI渠道最多?2026年TOP5服务商盘点,出海与国内增长团队都该看这份对比 - 速递信息