JS逆向|某音滑块captchaBody分析
字数 1104 2025-08-22 12:22:15

某音滑块captchaBody逆向分析教学文档

逆向目标

目标网址:aHR0cHM6Ly9jcmVkaXQuaGQuZ292LmNuL3h5eHhncy8= (Base64编码)

主要目标:

  1. 分析接口参数加密(queryContent和sign)
  2. 分析响应数据解密(application/octet-stream格式)

抓包分析

  1. 点击"加载更多"时发送xzxkfr数据包

  2. 需要逆向的参数:

    • queryContent:请求参数
    • sign:请求签名
    • nonceStr:随机字符串(无需逆向)
  3. 响应头为application/octet-stream,需要逆向解密

加密参数分析

queryContent加密

  1. 加密流程:

    • 条件判断:"1" === r.headers["C-GATEWAY-QUERY-ENCRYPT"]n.encryptType === P.ENCRYPT_TYPE.SM4
    • 使用SM4加密:i = ls.sm4.encrypt(i, e.encryptKey)
  2. SM4加密实现:

const sm4 = require('sm-crypto').sm4
const msg = '' // 明文
const key = '' // 密钥
let encryptData = sm4.encrypt(msg, key) // 默认输出16进制字符串,使用pkcs#7填充

// 可选参数:
let encryptData = sm4.encrypt(msg, key, {
  padding: 'none', // 不使用padding
  output: 'array', // 输出字节数组
  mode: 'cbc',     // CBC模式
  iv: 'fedcba98765432100123456789abcdef' // IV向量
})
  1. 本地模拟验证:
const sm4 = require('sm-crypto').sm4
const msg = '' // 明文
const key = '' // 密钥
console.log(sm4.encrypt(msg, key, {output: 'string'}))

sign签名

  1. 签名流程:

    • n.sign = o
    • 签名类型为SM2:o = ls.sm2.signature(a, e.appSignPrivateKey, e.appSignPublicKey, e.appId)
    • a是由queryContent等参数组成的字符串
  2. SM2签名实现:

const sm2 = require('sm-crypto').sm2
const msgString = '' // 待签名数据
const privateKey = '' // 私钥
const publicKey = '' // 公钥
const userId = '' // 用户ID(默认为1234567812345678)

let sigValueHex6 = sm2.doSignature(msgString, privateKey, {
  hash: true,
  publicKey,
  userId
})
  1. 签名后处理函数Zi
const BigInteger = require('jsbn').BigInteger;

function Xi(t) {
  return new BigInteger(t, 10).toString(16)
}

function Yi(t) {
  return new BigInteger(t, 16).toString(10)
}

响应数据解密

  1. 解密流程:

    • 响应拦截器interceptors.response.use中找到解密逻辑
    • 主要解密函数oo,使用SM4解密
  2. 响应数据处理:

// 处理响应数据
var r = t.data // arraybuffer
var n = new DataView(r)
var i = new Uint8Array(r)
var s = {}
var a = 40

// 分割数据
D.forEach(function(t, e) {
  var r = n.getInt32(4 * e)
  s[t] = i.subarray(a, a + r)
  a += r
})

// 验证签名
var o = ao(s, e)
var u = o[0]
var h = o[1]
if (!u) return Promise.reject(new Error("验签失败"))

// SM4解密
var c = "{}"
c = kr.sm4.decrypt(
  function(t) {
    for (var e = "", r = 0; r < t.length; r++) {
      var n = t[r].toString(16)
      1 === n.length && (n = "0" + n)
      e += n
    }
    return e
  }(s.body),
  e.encryptKey,
  {output: "string"}
)
  1. 辅助函数实现:
// Qi函数(MD5哈希)
const CryptoJS = require('crypto-js')
function Qi(t) {
  var e = CryptoJS.lib.WordArray.create(t)
  return CryptoJS.MD5(e).toString(CryptoJS.enc.Hex)
}

// ji函数(Base64编码)
var ji = function(t) {
  return Buffer.from(t).toString("base64")
}

// SM2验签
const sm2 = require('sm-crypto').sm2
sm2.doVerifySignature(a, Zi(i), e.platformPublicKey, {
  hash: !0,
  userId: e.appId
})

// SM4解密
const sm4 = require('sm-crypto').sm4
sm4.decrypt(
  function(t) {
    for (var e = "", r = 0; r < t.length; r++) {
      var n = t[r].toString(16)
      1 === n.length && (n = "0" + n)
      e += n
    }
    return e
  }(s.body),
  e.encryptKey,
  {output: "string"}
)
  1. Base64转ArrayBuffer:
function base64ToArrayBuffer(base64) {
  var binary_string = atob(base64)
  var len = binary_string.length
  var bytes = new Uint8Array(len)
  for (var i = 0; i < len; i++) {
    bytes[i] = binary_string.charCodeAt(i)
  }
  return bytes.buffer
}

关键点总结

  1. 加密算法

    • 请求参数使用SM4加密
    • 签名使用SM2算法
    • 响应数据使用SM4解密
  2. 依赖库

    • sm-crypto:SM2/SM4算法实现
    • jsbn:大整数处理
    • crypto-js:MD5哈希
  3. 注意事项

    • SM2每次加密会生成新的随机数,本地验证需通过接口返回判断
    • 响应数据需要先分割处理后再解密
    • 注意各种数据格式转换(ArrayBuffer、Hex、Base64等)
  4. 验证方法

    • 对比网页和本地加密结果是否一致
    • 通过实际接口请求验证参数是否正确
    • 检查解密后的数据是否符合预期格式

完整流程

  1. 构造请求参数
  2. 使用SM4加密queryContent
  3. 使用SM2生成签名sign
  4. 发送请求获取加密响应
  5. 处理响应数据(分割、验签)
  6. 使用SM4解密响应体
  7. 解析最终数据

通过以上步骤,可以完整实现该接口的加密请求和响应解密流程。

某音滑块captchaBody逆向分析教学文档 逆向目标 目标网址: aHR0cHM6Ly9jcmVkaXQuaGQuZ292LmNuL3h5eHhncy8= (Base64编码) 主要目标: 分析接口参数加密(queryContent和sign) 分析响应数据解密(application/octet-stream格式) 抓包分析 点击"加载更多"时发送 xzxkfr 数据包 需要逆向的参数: queryContent :请求参数 sign :请求签名 nonceStr :随机字符串(无需逆向) 响应头为 application/octet-stream ,需要逆向解密 加密参数分析 queryContent加密 加密流程: 条件判断: "1" === r.headers["C-GATEWAY-QUERY-ENCRYPT"] 且 n.encryptType === P.ENCRYPT_TYPE.SM4 使用SM4加密: i = ls.sm4.encrypt(i, e.encryptKey) SM4加密实现: 本地模拟验证: sign签名 签名流程: n.sign = o 签名类型为SM2: o = ls.sm2.signature(a, e.appSignPrivateKey, e.appSignPublicKey, e.appId) a 是由queryContent等参数组成的字符串 SM2签名实现: 签名后处理函数 Zi : 响应数据解密 解密流程: 响应拦截器 interceptors.response.use 中找到解密逻辑 主要解密函数 oo ,使用SM4解密 响应数据处理: 辅助函数实现: Base64转ArrayBuffer: 关键点总结 加密算法 : 请求参数使用SM4加密 签名使用SM2算法 响应数据使用SM4解密 依赖库 : sm-crypto :SM2/SM4算法实现 jsbn :大整数处理 crypto-js :MD5哈希 注意事项 : SM2每次加密会生成新的随机数,本地验证需通过接口返回判断 响应数据需要先分割处理后再解密 注意各种数据格式转换(ArrayBuffer、Hex、Base64等) 验证方法 : 对比网页和本地加密结果是否一致 通过实际接口请求验证参数是否正确 检查解密后的数据是否符合预期格式 完整流程 构造请求参数 使用SM4加密queryContent 使用SM2生成签名sign 发送请求获取加密响应 处理响应数据(分割、验签) 使用SM4解密响应体 解析最终数据 通过以上步骤,可以完整实现该接口的加密请求和响应解密流程。