sojson v7网站逆向

本次逆向的目标地址

aHR0cHM6Ly93d3cuMTdxY2MuY29tL2xpc3QuaHRtbD9rZXl3b3JkPSVFOSU5RSU4QiZjYXRlSWQ9NTAwMTE3NDAmc3BtPTEuNS40LTQuNSZwYWdlPTg=

接口地址

GetPageList

接口加密一览

接口请求和调试都是加密的

image-20241111160355463

image-20241111160410136

分析过程

image-20241111160043351

查看调用栈,在send 的地方打点,然后刷新网站,断点停下之后查看,向上查看可以看到有参数组装的过程,其中content 的值为加密过后的参数,

image-20241111161722554

这里可以看到这一行代码

1
_0x963e97 = _0x55c569[_0x5489a3(512, "%cUf")](_0x595165, JSON.stringify(_0x5182a9));
  • _0x5182a9 为参数
  • _0x5489a3(512, “%cUf”) == ‘CmUyU’
  • _0x55c569[‘CmUyU’] == function(_0x4afd55, _0x7b9059) {return _0x4afd55(_0x7b9059);
  • _0x963e97 = _0x595165(JSON.stringify(_0x5182a9))

这里 _0x595165就是加密函数,找到函数定义之后能看到关键词为AES ,打上断点之后,刷新网页。

image-20241111162808157

使用解密函数解密

image-20241111170821600

得到原函数为

1
2
3
4
5
6
7
8
9
10
11
12
13
_0x595165 = function(_0x4d373a) {
var _0x4633f5 = _0xa6527a
, _0x9cc440 = CryptoJS['enc']["Utf8"]['parse'](_0x307ab8)
, _0x989408 = CryptoJS.enc['Utf8']['parse'](_0x4bb657)
, _0x12f1ea = ""
, _0x2dd779 = CryptoJS.enc['Utf8']['parse'](_0x4d373a);
return _0x12f1ea = CryptoJS.AES['encrypt'](_0x2dd779, _0x9cc440, {
iv: _0x989408,
mode: CryptoJS['mode']["CBC"],
padding: CryptoJS['pad']['Pkcs7']
}),
_0x12f1ea['ciphertext']["toString"]();
}

这里可以明显的看到key 为_0x307ab8,iv 为_0x4bb657

找到定义后查看相关变量最终追溯到qccppm 上,全局搜素之后,发现qccppm 变量在html 中,每次刷新都会变,每次都需要访问网页进行提取

image-20241111173337491

image-20241111173533252

分析加密逻辑

1
2
3
4
5
6
7
8
9
_0x963e97 = _0x55c569[_0x5489a3(512, "%cUf")](_0x595165, JSON.stringify(_0x5182a9));
var _0x1c8141 = _0x55c569[_0x5489a3(450, "%Ry%")](_0xad2e02, _0x963e97);
_0x35c44f = {
Content: _0x963e97,
Sign: _0x1c8141,
RsaPubAes: _0x30ed66,
IV: _0x4bb657,
TimesTamp: _0x211530
};

Content == _0x963e97 == _0x595165(JSON.stringify(_0x5182a9)) 参数 0x5182a9 已知,_0x595165 为aes 加密 key,iv 可以拿到

Sign == _0x1c8141 == _0xad2e02(_0x963e97) ,_0xad2e02 位置,但猜测是一个hash 函数

RsaPubAes = _0x30ed66 未知

IV == _0x4bb657 == qccppm.split(‘|’)[1]

TimesTamp == qccppm.split(‘|’)[2]

接下来就要找 _0xad2e02的函数 和_0x30ed66 的生成

找到函数定义

image-20241111180649878

精简以后代码如下

1
2
3
4
5
6
7
8
9
10
  , _0xad2e02 = function(_0x8c7424) {
var _0x47d8cc = _0xa6527a
, _0x4fd74e = KEYUTIL['getKey'](_0x3051cc)
, _0x26889a = new KJUR[('crypto')]["Signature"]({
alg: 'SHA1withRSA'
});
return _0x26889a.init(_0x4fd74e),
_0x26889a['updateString'](_0x8c7424),
hextob64(_0x26889a.sign());
};

这里_0x3051cc 未知,搜索发现KEYUTIL 为jsrsasign 中的方法,是个JavaScript的RSA和ECC加密库

_0x3051cc = ‘—–BEGIN PRIVATE KEY—–\n’ + ‘一串私钥’ + ‘—–END PRIVATE KEY—–’

_0x26d6c0 = “—–BEGIN\x20PUBLIC\x20KEY—– ….”

这里看得出是一对rsa 密钥,_0xad2e02函数为SHA1withRSA 加密

image-20241111184449150

按照同样的思路结果可以精简为

image-20241111184536685

函数解密

ajax 有个特征就是 成功后会回调 success 对应的函数,全局搜索找到对应地址,打上断点,然后刷新。

image-20241112102639127

1
2
3
if (_0x2d811a['Success'] && _0x2d811a["Result"]) {
_0x1a18db == 2 && (_0x2d811a = JSON['parse'](_0x55c569[_0x5df6fc(548, "8E1C")](_0x316c29, _0x2d811a['Result']))),
_0x385fa2 && _0x55c569.TCewr(typeof _0x385fa2, "function") ? _0x55c569.NXSXh(_0x385fa2, _0x2d811a) : console["log"](_0x2d811a);

其中 _0x55c569[_0x5df6fc(548, "8E1C")] === function(_0x2a2c4b, _0x3415f3) {return _0x2a2c4b(_0x3415f3);

这里着重查看_0x316c29 函数全文搜索之后

image-20241112103756549

其中 _0x307ab8_0x4bb657 为 qccppm 的前两个部分,到这里这个网站的加密就全找出来了。


https://kingjem.github.io/2024/11/15/sojson v7网站逆向/
作者
Ruhai
发布于
2024年11月15日
许可协议