js逆向——返回加密数据的处理

布の哥 2024-08-31 11:03:02 阅读 79

一、确定爬取目标

今日受害者网站:https://jzsc.mohurd.gov.cn/data/company

我们的目标是爬取该网站列表页当中的企业信息

二、数据抓包分析

首先刷新网页进行抓包,观察一下数据在哪个数据包当中被返回(获取返回数据)

结果发现返回的都是一串看不懂的密文

搜索数据包中的文字也没有找到任何信息

​ 

这说明我们收到的响应数据是加密后的结果,返回客户端之后由客户端解密拿到明文字符串展示在前端当中,所以我们才能在网页看到有效的信息

因此现在就需要对返回的响应数据进行解密(decrypt)

三、js逆向分析

我们直接搜索decrypt,在所有可疑的位置打上断点

注意:像css/axios//jquery/react这种可以直接pass;但是app/chunk不能pass

另外一个js文件也不能放过

​ 

然后我们重新刷新网页,来再次发送请求

这样就定位到了解密的关键位置,不难发现是使用AES-CBC模式进行的加密解密

此外还有2处断点是具体的加密细节,可以直接忽略(取消断点)

​ 

既然是AEC-CBC进行加密解密

那么我们就重点关注3个参数:密文(n),密钥(f),iv(m)

<code>a = d.a.AES.decrypt(n, f, {

iv: m,

mode: d.a.mode.CBC,

padding: d.a.pad.Pkcs7

}

往上观察发现密钥和iv都是直接静态给出了

​ 

但是我们在使用之前需要验证一下值是否正确

结果发现密钥的值竟然和js代码当中给的不一致!

​ 

我们往下翻,原来是在执行解密之前key的值被重新修改了.......

看来还是得小心点留个心眼啊😂😂😂

​ 

这样数据解密的步骤我们已经分析完了,现在还有一个问题就是我怎么知道返回的7个XHR数据包哪一个是列表页展示的、我们希望得到的目标数据呢?

其实很简单.....

法一:你可以一个个爬取尝试(排除法)

而且几个过小/过大的文件肯定不是,剩下几个慢慢排除即可

法二:

在调试窗口观察到目标数据之后,点击网络面板,观察哪个数据接口返回了数据

其实根据名字也能猜个大概,因为我们想要要获取列表页数据,那么list?pg=0,pgsz=15就显得很可疑了😂😂

现在我们还需要确认一件事,就是这个网站使用的AES-CBC是不是标准的AES算法,这将决定我们需不需要扣代码

不妨在在线加密解密网站测试一下

能够正确解密,说明使用的是标准的AES算法

而且通过观察,js代码没有特别需要扣的地方,都是使用的库当中自带函数

<code>function b(t) {

var e = d.a.enc.Hex.parse(t)

, n = d.a.enc.Base64.stringify(e)

, a = d.a.AES.decrypt(n, f, {

iv: m,

mode: d.a.mode.CBC,

padding: d.a.pad.Pkcs7

})

, r = a.toString(d.a.enc.Utf8);

return r.toString()

}

四、代码编写

下面就是愉快的编码环节了

第一步是正确拿到返回的加密数据

import execjs

from loguru import logger

import requests

headers = {

"Connection": "keep-alive",

"Pragma": "no-cache",

"Cache-Control": "no-cache",

"accessToken": "",

"timeout": "30000",

"sec-ch-ua-mobile": "?0",

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Core/1.94.253.400 QQBrowser/12.6.5678.400",

"v": "231012",

"Accept": "application/json, text/plain, */*",

"sec-ch-ua-platform": "^\\^Windows^^",

"Sec-Fetch-Site": "same-origin",

"Sec-Fetch-Mode": "cors",

"Sec-Fetch-Dest": "empty",

"Referer": "https://jzsc.mohurd.gov.cn/data/company",

"Accept-Language": "zh-CN,zh;q=0.9"

}

url = "https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list"

params = {

"pg": "0",

"pgsz": "15",

"total": "0"

}

response = requests.get(url, headers=headers, params=params)

print(response.text)

print(response)

然后在vscode当中脱离浏览器环境编写解密的js代码,并完成测试

var CryptoJS = require('crypto-js');

function decrypt_aes_cbc(arg_key,arg_iv,arg_text){

// utf-8串转word数组

var key = CryptoJS.enc.Utf8.parse(arg_key);

// 16进制数转word数组

var e = CryptoJS.enc.Hex.parse(arg_text);

// 将e转为base64字符串

var n = CryptoJS.enc.Base64.stringify(e);

var a = CryptoJS.AES.decrypt(n, key, {

iv: CryptoJS.enc.Utf8.parse(arg_iv),

mode: CryptoJS.mode.CBC,

padding: CryptoJS.pad.Pkcs7

});

return a.toString(CryptoJS.enc.Utf8).toString()

}

//测试

//console.log(decrypt_aes_cbc('Dt8j9wGw%6HbxfFn','0123456789ABCDEF',"5588a9e126c91a28cc2f6813e37933690edae8a89a2a40f9ee87399a0fa435be5ec9333788e282e9b9cf6c5b7b8d92dcf0f09279c62908f4d6ce72a06dd3e9f2"))

最后在pycharm当中调用js代码即可

with open('aes_cbc.js','r',encoding='utf-8') as f:code>

ctx = execjs.compile(f.read())

decry_data = ctx.call('decrypt_aes_cbc','Dt8j9wGw%6HbxfFn','0123456789ABCDEF',response_string)

print("解密后的数据为:",decry_data)

结果报错:

1)UnicodeDecodeError: 'gbk' codec can't decode byte 0xac in position 62: illegal multibyte sequence

2)AttributeError: 'NoneType' object has no attribute 'replace'

为此只需要在execjs库的上面添加如下代码,确保js代码执行时编码环境为utf-8:

<code>import subprocess

from functools import partial

subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")code>

 

再次运行,顺利拿到解密后的列表数据 

 

完整代码:

<code>import subprocess

from functools import partial

subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")code>

import execjs

import requests

headers = {

"Connection": "keep-alive",

"Pragma": "no-cache",

"Cache-Control": "no-cache",

"accessToken": "",

"timeout": "30000",

"sec-ch-ua-mobile": "?0",

"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Core/1.94.253.400 QQBrowser/12.6.5678.400",

"v": "231012",

"Accept": "application/json, text/plain, */*",

"sec-ch-ua-platform": "^\\^Windows^^",

"Sec-Fetch-Site": "same-origin",

"Sec-Fetch-Mode": "cors",

"Sec-Fetch-Dest": "empty",

"Referer": "https://jzsc.mohurd.gov.cn/data/company",

"Accept-Language": "zh-CN,zh;q=0.9"

}

url = "https://jzsc.mohurd.gov.cn/APi/webApi/dataservice/query/comp/list"

params = {

"pg": "0",

"pgsz": "15",

"total": "0"

}

response = requests.get(url, headers=headers, params=params)

response_string = response.text

# print(response.text)

# print(response)

with open('aes_cbc.js','r',encoding='utf-8') as f:code>

ctx = execjs.compile(f.read())

decry_data = ctx.call('decrypt_aes_cbc','Dt8j9wGw%6HbxfFn','0123456789ABCDEF',response_string)

print("解密后的数据为:",decry_data)

ok,今天的你就到此为止吧,我们下期再见~ 



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。