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

JS逆向 - 某程 w-payload-source 纯算与补环境实战剖析

1. 逆向目标与核心参数解析

这次我们要破解的目标是某程网站航班查询接口中的关键加密参数w-payload-source。这个参数出现在请求头中,看起来像是一串经过复杂处理的字符串,比如102!by0EACXB4jiQ...这样的格式。在实际测试中发现,如果直接修改或删除这个参数,服务器会返回403错误,说明它起到了重要的身份校验作用。

通过抓包分析可以看到,这个参数有几个明显特征:开头固定带有102!前缀,后面跟着的字符串长度不固定,但总是Base64字符集的组合。更关键的是,每次刷新页面时这个值都会变化,说明它可能包含了时间戳、随机因子或浏览器指纹等动态元素。在逆向工程中,这类参数通常有两种破解思路:要么完全还原它的生成算法(纯算),要么模拟浏览器环境让它自然生成(补环境)。

2. 快速定位加密入口的技巧

实战中定位加密逻辑最快的方法就是搜索关键字符串。在开发者工具的Sources面板中,全局搜索w-payload-source,通常能直接找到设置该参数的代码位置。在我这次的案例中,发现它在XMLHttpRequest.setRequestHeader方法中被设置。

更高效的做法是在Network面板找到该请求,右键选择"Search in headers"功能。定位到具体代码后,可以观察到类似这样的调用链:

window.c_sign.toString(params) -> Bt(params) -> z_charCodeAt(z_array)

其中c_sign是个关键函数,通过toString()方法转换输入参数。这里有个技巧:在控制台输入window.c_sign.toString查看函数体,会发现它来自一个独立的c-sign.js文件。

3. 补环境的核心思路与实现

补环境的本质就是让JS代码"感觉"自己运行在真实的浏览器环境中。首先需要把c-sign.js文件完整保存下来,然后在Node.js或补环境框架中运行。这时候通常会遇到各种报错,比如navigator.plugins未定义、window.callPhantom不存在等。

我常用的补环境方案是这样的结构:

// 基础浏览器环境 const fakeWindow = { navigator: { plugins: [], mimeTypes: [], hardwareConcurrency: 4, platform: 'Win32' }, screen: { width: 1920, height: 1080 } } // 代理检测点 const handler = { get(target, prop) { console.log(`读取 ${prop}`); return target[prop] || undefined; }, has(target, prop) { console.log(`检测 ${prop}`); return true; // 让所有属性检测都通过 } } window = new Proxy(fakeWindow, handler);

特别注意要补全这些关键点:

  • BOM检测window.outerWidthwindow.name
  • DOM检测document.documentElement.clientWidth
  • Canvas指纹HTMLCanvasElement.prototype.toDataURL
  • WebGL渲染WebGLRenderingContext.prototype.getParameter

4. 纯算法还原的详细步骤

当补环境遇到困难时,纯算法还原就是终极解决方案。通过分析Bt()函数的执行流程,发现最终结果是由多个部分拼接而成:

  1. 随机因子:8位随机字符串F,用做盐值
  2. 请求体签名:对POST数据计算MD5,再拼接F后二次加密
  3. 环境指纹:包括:
    [ "536870911", // 特征码 "", // 插件信息 Date.now(), // 时间戳 -new Date().getTimezoneOffset()/60, // 时区 "1", // 全局变量检测 "09031147110931135002" // 客户端ID ]

关键的加密转换发生在z_charCodeAt()函数中:

function z_charCodeAt(arr) { const result = []; for (let str of arr) { for (let i=0; i<str.length; i++) { result.push(str.charCodeAt(i) & 255); } result.push(0); // 每个字符串后加0分隔 } return result; }

最终通过Base64编码的salt字符串进行位移运算:

let output = "102!"; for(let i=0; i<bytes.length; ) { const h = bytes[i++]; const k = bytes[i++] || NaN; const b = bytes[i++] || NaN; const p = h >> 2; let T, F, K; const V = h & 3; // 三字节转四字符的逻辑 if(!isNaN(k)) { T = (V << 4) | (k >> 4); if(!isNaN(b)) { F = ((k & 15) << 2) | (b >> 6); K = b & 63; } else { F = (k & 15) << 2; K = 64; } } else { T = V << 4; F = K = 64; } output += salt[p] + salt[T] + salt[F] + salt[K]; }

5. 常见检测点与绕过方案

在实际操作中会遇到各种环境检测,这里列举几个典型的:

  1. PhantomJS检测

    // 检测window.callPhantom 'callPhantom' in window // 需要返回false
  2. Chrome扩展检测

    // 检测chrome对象 typeof chrome !== 'undefined' // 需要根据实际情况处理
  3. 字体指纹检测

    // 检测可用字体 document.fonts.check('12px Noto Sans')
  4. WebGL渲染检测

    // 通过canvas获取WebGL指纹 const canvas = document.createElement('canvas'); const gl = canvas.getContext('webgl'); gl.getParameter(gl.VENDOR);

对于这些检测,我的经验是:

  • 使用Proxy代理关键对象
  • 对不确定的属性返回合理默认值
  • 保持属性访问的顺序和次数与真实浏览器一致

6. 实战中的调试技巧

在逆向过程中,有几个调试技巧特别实用:

  1. 断点策略

    • Object.defineProperty上设断点,捕获属性定义
    • Function.prototype.toString设断点,发现隐藏函数
  2. 日志记录

    // 记录所有属性访问 const log = []; const handler = { get(target, prop) { log.push(`GET ${prop}`); return Reflect.get(target, prop); } } window = new Proxy(window, handler);
  3. 差异对比

    • 在真实浏览器和控制台分别运行代码
    • 对比关键变量的值差异
  4. 性能优化

    // 加速补环境执行 delete window.performance; window.performance = { now: () => Date.now() };

7. 完整实现方案

结合纯算和补环境的优势,最终的解决方案可以这样设计:

  1. 环境准备阶段

    // 固定环境参数 const env = { timezone: -8, plugins: [], webglVendor: 'Google Inc. (Intel)' };
  2. 核心算法实现

    function generatePayload(queryParams) { // 1. 生成随机因子 const F = randomString(8); // 2. 计算请求体签名 const bodyHash = md5(JSON.stringify(queryParams)); const K = customMd5(`${bodyHash}-${F}`, 31); // 3. 构建环境数组 const z = [ "536870911", "", Date.now().toString(), env.timezone.toString(), "1", "09031147110931135002" ]; // 4. 字符编码转换 const bytes = z_charCodeAt(z); // 5. Base64编码转换 return encodeWithSalt(bytes); }
  3. 请求发送示例

    const payload = generatePayload({ depdate: '2025-12-26', cabin: 'Y_S_C_F' }); fetch('/online/list', { headers: { 'w-payload-source': payload } });

这种混合方案既避免了纯补环境的性能开销,又比纯算法还原更易维护。在实际项目中,建议先尝试补环境方案,遇到难以模拟的检测点再针对性进行算法还原。

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

相关文章:

  • 嘎嘎降AI标准模式和深度改写模式对比:什么情况下用哪个
  • 保姆级教程:用PyTorch 1.13+Win11搞定MSTAR数据集分类(附完整代码)
  • 350M模型也能这么强:Granite-4.0-H-350M效果展示,Ollama一键部署
  • MySQL死锁实战:从索引缺失到锁超时的深度解析与优化
  • 从TCGA数据到生存分析三线表:R语言Cox回归实战全解析
  • 3大突破!Get Shit Done如何让AI开发者效率提升50%
  • Visual C++ 2015运行库安装指南:解决msvcp140.dll缺失报错
  • 用Isaac Sim的Action Graph给ROS2机器人发布激光雷达数据:一个完整的传感器仿真流程
  • 完整构建流程:从CMake配置到PyPI分发的nanobind项目部署
  • 告别冯·诺依曼瓶颈:手把手拆解SRAM、ReRAM、Flash三大存算一体芯片的实战差异
  • 告别网络卡顿!Visual Studio 2022离线安装NuGet包的3种实战方法(含Blend)
  • CoPaw快速上手:5分钟在Windows搭建本地AI助手
  • OpenClaw技能扩展指南:为百川2-13B-4bits模型添加自定义自动化模块
  • YimMenu:GTA5增强工具完全使用指南
  • SAP销售发票自动生成会计凭证的3种实战配置(含权限分配避坑指南)
  • 别再只盯着YOLOv5了!聊聊FPN、PANet这些‘特征融合’老将如何帮你搞定小目标检测
  • 社交媒体数据采集难题的Python解决方案:TikHub API SDK深度解析
  • 高效锂电池升降压方案:PW2224实现3.3V稳定输出的设计要点
  • AUTOSAR通信栈实战:拆解PDUR与SOME/IP-TP模块的交互时序与配置要点
  • 昇腾NPU加速实战:Docker部署MindIE-Service完整流程与性能调优技巧
  • Odoo合同自动化如何解决企业文档管理痛点:从纸质流程到数字化签署的转型实践
  • 别再只会用Excel了!用Python的NumPy和SciPy做曲线拟合,5分钟搞定实验数据处理
  • CAPL实战指南:如何构建并发送带计数器的自定义周期报文
  • PID算法实战指南:从理论到应用的深度解析
  • 造相-Z-Image-Turbo 快速入门:10分钟在CSDN星图平台完成首次图像生成
  • Ceph 17.2 实战:基于cephadm的单节点集群快速部署与验证
  • msvcp140.dll缺失怎么修复?2026年正确的解决步骤
  • Java 中不使用 Math.sqrt() 判断完全平方数的方法
  • 零基础如何选择PMP和软考?2025年考证避坑指南(含最新政策解读)
  • 3步快速搞定AtlasOS中Xbox控制器驱动问题完整攻略