吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1060|回复: 27
上一主题 下一主题
收起左侧

[Web逆向] 【JS逆向】某审批局加解密逆向分析

  [复制链接]
跳转到指定楼层
楼主
littlewhite11 发表于 2025-3-15 18:44 回帖奖励

文章主要分享的内容是本人在逆向过程中遇到标准加解密算法时使用各种库来模拟还原的一些经验,因本人并不擅长密码学,请路过的各位大佬多多指教。

逆向目标

  • 网址:aHR0cHM6Ly9jcmVkaXQuaGQuZ292LmNuL3h5eHhncy8=
  • 目标:接口参数加密,响应数据解密

抓包分析

进入网站后,点击加载更多,会发送一个xzxkfr数据包。

其中请求参数中的queryContentsign需要逆向分析,nonceStr只是一个随机字符串。

响应头为application/octet-stream,因此响应数据的解密也需要逆向分析。

逆向分析

话不多说,直接开始逆向。

加密

刷新网站,尝试搜索关键词queryContent,在某个JS文件中搜索到。

跳转到文件对应的地方下断,点击加载更多,成功断住,此时,参数queryContent已经生成,为i

我们往前看i如何生成。可以知道i && null != r.headers && "1" === r.headers["C-GATEWAY-QUERY-ENCRYPT"] && n.encryptType === P.ENCRYPT_TYPE.SM4这个条件是成立的,因此会走i = ls.sm4.encrypt(i, e.encryptKey)的逻辑。其实也可以在i = ls.sm4.encrypt(i, e.encryptKey)i = us(i, e.encryptKey)处分别下断后重新请求,然后单步跟,看走哪个函数。

可以看到传入了请求参数的字符串以及SM4加密的key,然后生成了queryContent

我们直接跟进去encrypt函数,其中t是明文,ekey

我们可以通过代码的一些特征去网上搜索或者问AI,看有什么库能够实现这种方式的加密(这里是SM4)。

我就直接贴代码了(因为我已经搜索过了)。

const sm4 = require('sm-crypto').sm4
const msg = '' // 可以为 utf8 串或字节数组
const key = '' // 可以为 16 进制串或字节数组,要求为 128 比特

let encryptData = sm4.encrypt(msg, key) // 加密,默认输出 16 进制字符串,默认使用 pkcs#7 填充(传 pkcs#5 也会走 pkcs#7 填充)
let encryptData = sm4.encrypt(msg, key, {padding: 'none'}) // 加密,不使用 padding
let encryptData = sm4.encrypt(msg, key, {padding: 'none', output: 'array'}) // 加密,不使用 padding,输出为字节数组
let encryptData = sm4.encrypt(msg, key, {mode: 'cbc', iv: 'fedcba98765432100123456789abcdef'}) // 加密,cbc 模式

那我们直接尝试通过nodejs模拟一下。

const sm4 = require('sm-crypto').sm4
const msg = ''  // 明文
const key = ''  // key

console.log(sm4.encrypt(msg, key, {output: 'string'}))

对比一下网页上和本地的执行结果,发现是一致的,那queryContent加密的模拟就完成了。

有的时候并不是那么顺利,可能还需要尝试paddingmode之类的,如果是魔改的,那就另当别论了。

我们继续跟sign的加密逻辑,n.sign = o,且signTypeSM2,那应该是需要跟o = Zi(o = ls.sm2.signature(a, e.appSignPrivateKey, e.appSignPublicKey, e.appId))的逻辑。

其中a是包括queryContent在内的一系列参数组成的字符串,代码可以直接扣。

我们继续跟signature这个函数,可以发现应该是个签名算法。

还是老规矩,网上搜

const sm2 = require('sm-crypto').sm2
const msgString = ''
const privateKey = ''
const userId = ''

let sigValueHex6 = sm2.doSignature(msgString, privateKey, {
    hash: true,
    publicKey,
    userId,  // 默认 userId 为 1234567812345678
})

SM2是一种基于椭圆曲线公钥密码算法的标准,由中国国家密码管理局发布,每次加密时会生成一个新的随机数,且参与密文的生成过程。因此,我们无法确定本地模拟的参数是否正确,那我们可以通过请求接口,如果返回数据了,就表示参数没问题。

SM2的结果有了,那我们还需要跟一下Zi这个函数,才能拿到最终的sign值从而模拟请求接口。

Zi可以直接扣代码就行,需要注意的是,扣代码过程中遇到的XiYi函数内的BigInteger可以通过导库实现,具体还是网上搜索,直接贴代码了。

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)
}

参数模拟完成,我们直接请求接口看能不能返回数据。

可以看到,成功返回数据,说明参数模拟没有问题。

解密

下面我们再看响应数据的解密。

既然接口是xhr请求,那我们就尝试搜索响应拦截器interceptors.response.use,可以在某个JS文件中搜索到。

我们直接跳去源文件,看起来像是个异步,具体就不跟了,解密的逻辑就在下图所指的oo函数,其中r就是响应,e对象包含了解密所需key等信息。

我们直接跟进去oo函数,把一些条件判断去掉后的逻辑代码如下,之后缺什么扣什么就行,t.data是响应的arraybuffer,解密还是用的SM4

// 处理响应数据
var r = t.data
  , n = new DataView(r)
  , i = new Uint8Array(r)
  , s = {}
  , 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)  
  , u = o[0]
  , 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"
});

我们扣代码的时候,并不知道var o = ao(s, e)这里是在验证响应数据的签名,所以会跟着扣。

其中遇到一些需要注意的点是:

Qi函数可以导库实现

// 网页上
function Qi(t) {
    var e = Ai.lib.WordArray.create(t);
    return Ai.MD5(e).toString(Ai.enc.Hex)
}
// 本地模拟
const CryptoJS = require('crypto-js')
function Qi(t) {
    var e = CryptoJS.lib.WordArray.create(t);
    return CryptoJS.MD5(e).toString(CryptoJS.enc.Hex)
}

ji函数在nodejs可以直接模拟

// 网页上
var Pi = "function" == typeof Buffer
var ji = Pi ? function(t) {
    return Buffer.from(t).toString("base64")
}
: function(t) {
    for (var e = [], r = 0, n = t.length; r < n; r += 4096)
        e.push(Ri.apply(null, t.subarray(r, r + 4096)));
    return Hi(e.join(""))
}
// 本地模拟,nodejs 自带 Buffer
var ji = function(){
    return Buffer.from(t).toString("base64")
}

验证签名时的SM2算法

// 网页上
Vr.doVerifySignature(a, Zi(i), e.platformPublicKey, {
    hash: !0,
    userId: e.appId
})
// 本地模拟
const sm2 = require('sm-crypto').sm2
sm2.doVerifySignature(a, Zi(i), e.platformPublicKey, {
    hash: !0,
    userId: e.appId
})

然后就是最终的SM4解密了,既然前面的加密能够在网上搜索到,那解密也不在话下了。

// 网页上
c = kr.sm4.decrypt(function(t) {
    if (!(t instanceof Uint8Array))
        throw new Error("Invalid Uint8Array");
    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"
})
// 本地模拟
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"
})

最后,我们直接模拟请求接口,通过导库实现各种加解密算法,进行最终数据的获取。

我们先对响应进行base64,然后在JS中将base64字符串转为arraybuffer

// 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;
}

模拟请求:

成功!!!

免费评分

参与人数 11威望 +2 吾爱币 +107 热心值 +10 收起 理由
lingdu577 + 1 用心讨论,共获提升!
xw891125 + 1 + 1 我很赞同!
抱歉、 + 1 用心讨论,共获提升!
涛之雨 + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
三滑稽甲苯 + 2 + 1 用心讨论,共获提升!
wzh103103 + 1 用心讨论,共获提升!
时崎-狂三 + 1 + 1 用心讨论,共获提升!
cryb + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
839808961 + 1 谢谢@Thanks!
bai1276 + 1 用心讨论,共获提升!
FitContent + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

沙发
beautiful008 发表于 2025-3-15 19:17
学习一下,感谢大佬分享
3#
sanfengzhang 发表于 2025-3-15 19:26
4#
 楼主| littlewhite11 发表于 2025-3-15 19:31 |楼主
sanfengzhang 发表于 2025-3-15 19:26
看得云里雾里。膜拜大神之中。

多搞就不云里雾里了,我也是个小菜鸡
5#
KaliHt 发表于 2025-3-15 21:19
大佬有比较的完美方法去扣加密代码吗
6#
mzhsohu 发表于 2025-3-15 21:23
不明觉厉~!菜鸡路过~!!!
希望看到完整的视频教程~!!!
7#
 楼主| littlewhite11 发表于 2025-3-15 21:44 |楼主
KaliHt 发表于 2025-3-15 21:19
大佬有比较的完美方法去扣加密代码吗

没有,起码我没有
8#
JMYJ0001 发表于 2025-3-15 22:27
虽然看不懂,但是感觉很厉害,nice!!!!
9#
kowade003 发表于 2025-3-15 22:47
表示看不明白,部分代码能不能用Ai去编写实现呢?
10#
tomjin 发表于 2025-3-15 22:58
感谢大佬分享 666
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-3-17 10:44, Updated at 2025-03-17 10:44:46.

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表