爬虫&逆向--Day13&Day14--JS逆向核心案例(响应入口定位、JS逆向响应解密、JS逆向请求加密)
一、JS逆向课程介绍
逆向核心案例
-- JS逆向流程(原理)
--请求加密
--响应解密
逆向基础案例
--扣JS
--webpack
--补环境
-- 瑞数
-- 原型链
-- 滑块
-- Akamai
-- JSVMP
学习方法:
复盘课上项目
准备链接:
案例链接:https://ggzyfw.fujian.gov.cn/business/list/
-- 为了保持环境一致,避免出现不必要的问题,建议使用Google浏览器无痕模式
破解网站:https://www.swhysc.com/swhysc/news/company
快速生成爬虫代码:https://curlconverter.com/
-- 既是根据Ajax发送的请求链接的基本信息请求参数,请求体,请求头等,快速生成爬虫代码
画图网站:https://excalidraw.com/
--可以根据需要画出结构图
二、逆向案例之基本爬虫
补充知识点:
浏览器 --> 服务器发送请求有两种模式:
模式一:服务器从数据库取出来的数据,有可能直接把数据在服务器侧,就把数据塞到页面中,然后直接把该页面进行返回。比如:百度热搜,热搜的数据就嵌在页面中,这时候就需要把该页面爬下来,然后用正则、XPass什么的对页面进行解析获取页面源码中的数据, ---这个是少数情况
模式二:浏览器向服务器发送一个请求,服务器先给浏览器返回一个页面(只有页面布局),但是核心数据没有,这个时候浏览器就需要通过Ajax再次发送请求,单独获取页面数据,再把数据加载到页面中。所以我们正常只需要进行对Ajax进行破解就好了,不需要进行正则什么的;需要用到正则、Xpass什么是数据嵌在页面中的。---该模式属于正常的大多数模式
1.1、技能一:学习排除干扰请求
通过点击页码获取的单个Ajax接口,除了单个参数页码不一样其他都一致
1.2、技能二:根据获取的接口,构建基础爬虫代码,发送请求
问题一:content-type:请求体的数据格式
res = requests.post(url=url, json=data, headers=header)
问题二:因为请求体全部内容已经复制包含,那提示的:接口请求签名错误,肯定是在请求头中,所以补充portal-sign
import requests # 基础爬虫,既是模仿Ajax发送数据请求,获取和浏览器一样的返回数据 # URL 请求方式 请求头 请求参数-get 请求体-post # 请求头 headers = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36", "portal-sign":"7c7cc7c720e63b573b1827244fd0cf12" } # 请求URL url = "https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo" # 请求体-post 点击复制--复制object data = { "pageNo": 3, "pageSize": 20, "total": 2755, "AREACODE": "", "M_PROJECT_TYPE": "", "KIND": "GCJS", "GGTYPE": "1", "PROTYPE": "", "timeType": "6", "BeginTime": "2025-02-08 00:00:00", "EndTime": "2025-08-08 23:59:59", "createTime": "", "ts": 1754618383170 } # 发送请求 # res = requests.post(url, data=data, headers=headers) data 会默认把请求体按照urlencoded去处理 参数校验错误 res = requests.post(url, json=data, headers=headers) # 所以,我们这里需要使用json处理 print(res.text) # 逆向--就是破解算法,算法是什么,就是各种加密 处理响应结果的加密
1.3、技能三:快速生成爬虫代码:https://curlconverter.com/
import requests headers = { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://ggzyfw.fujian.gov.cn', 'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'portal-sign': '30b786c2f4b4e6fa6b2c7e0da2b9bae9', 'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } json_data = { 'pageNo': 1, 'pageSize': 20, 'total': 2757, 'AREACODE': '', 'M_PROJECT_TYPE': '', 'KIND': 'GCJS', 'GGTYPE': '1', 'PROTYPE': '', 'timeType': '6', 'BeginTime': '2025-02-08 00:00:00', 'EndTime': '2025-08-08 23:59:59', 'createTime': '', 'ts': 1754622577806, } url = "https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo" response = requests.post(url, headers=headers, json=json_data) print(response.text)
点击接口 --> 右键:复制 --> 选择:以cURL(bash)格式复制
三、逆向案例之响应入口定位
2.1、技能一:JS逆向流程(原理)
1、发送第一次请求:当通过浏览器第一次访问服务器获取数据
2、HTML+CSS+JS:服务器就会从数据库把浏览器第一次访问需要获取的HTML和CSS还有JS一起打包发送给浏览器,
其中HTML和CSS的浏览器页面布局相关,所以爬虫可以忽略;但是在返回的数据包中还有JS,JS是一种脚本语言,来自服务器,作用就是跟页面的动态事件相关,比如:弹窗、点击页码向后端发送Ajax请求获取分页数据等。【爬虫逆向重点关注通过JS向后端发送的Ajax请求数据和响应数据】
3.1、目标Ajax请求(浏览器):当页面渲染完成以后,我们通过点击【页码】发送Ajax请求,定位我们需要爬取的接口链接,
4.1、响应的Json数据(浏览器):服务器返回点击页码获取的新数据,返回的数据是加密的
3.2、目标Ajax请求(爬虫代码):通过Python代码模仿浏览对服务器进行发送请求,获取加密的响应数据
4.2、响应的Json数据(爬虫代码):通过Python代码模拟浏览器发送Ajax请求,获取服务器返回的加密数据
以上流程到此,已经获取到了服务器返回的数据,但是返回的数据是加密的,逆向既是对返回的数据进行解密,所以我们后续只需要重点关注【对返回的数据进行解密即可】,既然浏览器可以把加密的数据正常渲染,那么必定有一块JS代码是专门用来解密返回的数据的,所以我们需要定位到该段JS代码,并且通过代码模拟解密的过程,破解返回的加密数据
2.2、解密代码定位
1、搜索--嫌疑代码
通过以上操作,如果搜索:【 decrypt 】 定位到26个匹配行;如果搜索:【 decrypt( 】 定位到2个匹配行,然后在定位到的2个匹配行上打断点----{确定了两个嫌疑犯},然后再次点击页码进行确定是那个代码块,当点击完页码以后,那个断点卡住了就证明走了定位的那个方法----【确定了那个嫌疑犯才是罪魁祸首】,这个时候就找到了JS代码中针对返回的加密数据的处理方式,
2、定位嫌疑代码
3、分析解密代码
4、如何确定这段代码就是我们想要的呢?
e = h.a.enc.Utf8.parse(r["e"]) 得知 e 就是一个固定值,32位长度的字符串:"EB444973714E4A40876CE66BE45D5930" AES的key值
n = h.a.enc.Utf8.parse(r["i"]) 得知 i 就是一个固定值,16位长度的字符串:"B5A8904209931867" AES的iv值
t 是需要解密的数据{服务器返回的加密数据}
备注:加密知识可以参考 爬虫&逆向--Day08--加密算法
问题一:入口定位方式都有那些
-- 关键字搜索
-- 方法关键字
-- encrypt 加密
-- decrypt 解密 该案例解密使用的定位方式
-- key关键字(最高频)
-- headers关键字
-- 路径关键字
-- 拦截器关键字
-- 请求堆栈 标版,比较稳的一种方式,但是效率低
-- hook
四、逆向案例之Python逆向响应解密
import base64 from Crypto.Cipher import AES import json from Crypto.Util.Padding import unpad import requests headers = { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://ggzyfw.fujian.gov.cn', 'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'portal-sign': '95a50c89ade7a5a73c03127e52ea5a2c', 'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } json_data = { 'pageNo': 2, 'pageSize': 20, 'total': 2795, 'AREACODE': '', 'M_PROJECT_TYPE': '', 'KIND': 'GCJS', 'GGTYPE': '1', 'PROTYPE': '', 'timeType': '6', 'BeginTime': '2025-02-11 00:00:00', 'EndTime': '2025-08-11 23:59:59', 'createTime': '', 'ts': 1754900503314, } response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data) # 这个获得的是字符串类型,所以不能操作,我们需要获取Json类型 # print(response.text) # print(type(response.text)) # <class 'str'> # 基于Python实现AES算法进行解密 # response.json() 获取的是字典类型 # print(type(response.json())) # <class 'dict'> # response.json().get("Data") 然后在get对应的key data = response.json().get("Data") # 先base64解码得到需要解密的数据,在进行解密 【知识点补充一】 data = base64.b64decode(data) k = "EB444973714E4A40876CE66BE45D5930".encode() # key可能是16位的,也可能是32位的, iv = "B5A8904209931867".encode() # iv一定是16位的 .encode()是一定要它的字节串 # 创建aes的对象 使用上面的一套 k 和 iv 既可以进行加密,也可以进行解密 aes_obj = AES.new(key=k, mode=AES.MODE_CBC, iv=iv) # AES解密 data = aes_obj.decrypt(data) # 得到的是b'xxx' 字节, data.decode()字节转字符串直接 # print("data::::", data) # 得到二进制字节数据 # data:::: b'{\r\n }\r\n ]\r\n}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' # data_str = data.decode() # 把二进制字节数据,转化为字符串 # 因为AES加密要求数据的长度必须是块大小的倍数,所以数据长度不足,需要进行填充(Padding) # json.loads(unpad(data, AES.block_size).decode('utf-8')) data_str = unpad(data, AES.block_size).decode('utf-8') # 因为AES带有填充,所以需要先用unpad去除填充 # print("data_str::::", data_str) # 把解密开的数据进行反序列化 字符串转字典 data_dict = json.loads(data_str) # print("data_dict::::", data_dict) # 所有的数据都在列表Table中,所以我们便利Table列表 print(data_dict.get("Table")) for i in data_dict.get("Table"): # 获取每个文件的NAME名称 print(i.get("NAME")) """ 【知识点补充一】 Base64编码,是由64个字符组成编码集:26个大写字母A~Z,26个小写字母a~z,10个数字0~9,符号“+”与符号“/” base64编码示例 # 将原始数据转化为二进制/字节数据 data = "you".encode("utf-8") print(data) # b'you' # 把字节转化成b64 bs = base64.b64encode(data).decode() print(bs) # eW91 base64解码示例 s = "eW91" ret = base64.b64decode(s) print(ret) # 正确 b'you' """
""" 【知识点补充二】 二进制字节---字符串 unpad(data, AES.block_size).decode('utf-8') 字符串---对象 json.loads(data_str) """
五、逆向案例之JS逆向响应解密
背景:由于本案例解密的JS代码块比较简单,所以我们可以通过上面的第四步:逆向案例之Python逆向响应解密 进行解密操作,但是当我们遇到JS解密代码比较繁琐和复杂的时候再用Python代码进行破解就比较麻烦,所以我们就需要把对应的解密代码块直接扣出来,在浏览器外部使用node进行运行。
5.1、确定JS中的解密代码块是那部分
5.2、补充和安装第三方依赖库 npm install crypto-js
如果没有安装crypto-js 需要安装一下 npm install crypto-js
JS中使用npm Python中使用pip 区别是:npm 放到当前目录下 pip放到全部python的安装包里面去
5.3、根据不考虑代码逻辑,只考虑在不改变代码逻辑的基础上,尽可能的代码替换和平移 替换 key 和 iv
5.4、测试扣出来的JS代码是否可行,如果可行后续就方便在Python中直接调用
5.5、在Python代码中调用JS解密代码,进行解密操作
备注: 有些有些中文不兼容问题 可能导致在执行 js_code_compile.call("b", data) Python调用JS代码时报错误,需要做如下操作
pip uninstall pyexecjs
pip install pyexecjs2
更新一下模块
5.6、创建的JS代码块文件:05案例基于JS的响应解密.js
/* JS中的 require() 类似Python中的import,导入第三方标准库 crypto-js const cryptoJs 给导入的第三方标准库起一个名字,叫:cryptoJs 如果没有安装crypto-js 需要安装一下 npm install crypto-js JS中使用npm Python中使用pip 区别是:npm 放到当前目录下 pip放到全部python的安装包里面去 */ const cryptoJs = require("crypto-js") function b(t) { var e = cryptoJs.enc.Utf8.parse("EB444973714E4A40876CE66BE45D5930") , n = cryptoJs.enc.Utf8.parse("B5A8904209931867") , a = cryptoJs.AES.decrypt(t, e, { iv: n, mode: cryptoJs.mode.CBC, padding: cryptoJs.pad.Pkcs7 }); return a.toString(cryptoJs.enc.Utf8) } /* 以上的这段代码,我们无需关注代码的业务流程,只需要直接运行缺什么环境依赖,补什么环境依赖。 经过对比和了解,enc和AES都是标准库,所以我们无需研究enc和AES,在上面直接导入JS中的标准库即可 把上方代码中的 h.a 全部更换为: */ // 使用服务器返回的加密数据,进行对如上的代码进行测试 // data = "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" // console.log(b(data)) // 调用修改后的加密方法,获取解密数据
5.7、创建的Python代码文件:04案例基于JS的响应解密.py
import execjs import requests headers = { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://ggzyfw.fujian.gov.cn', 'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', 'portal-sign': 'e289a313d00e3c58fc562cf2d9f257fa', 'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } json_data = { 'pageNo': 1, 'pageSize': 20, 'total': 0, 'AREACODE': '', 'M_PROJECT_TYPE': '', 'KIND': 'GCJS', 'GGTYPE': '1', 'PROTYPE': '', 'timeType': '6', 'BeginTime': '2025-02-11 00:00:00', 'EndTime': '2025-08-11 23:59:59', 'createTime': '', 'ts': 1754910932790, } response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data) # print(response.text) # 基于JS实现AES算法进行解密 # 先打开,然后逐行读取JS代码 with open("05案例基于JS的响应解密.js", encoding="utf-8") as f: js_code = f.read() # execjs.compile 编译这个js代码 创建编译器 js_code_compile 可以调用JS代码中的任意一个函数 js_code_compile = execjs.compile(js_code) data = response.json().get("Data") # print("data:::",data) # 调用JS代码中的b函数,把data作为参数进行传递 res = js_code_compile.call("b", data) print(res) """ pip uninstall pyexecjs pip install pyexecjs2 更新一下模块 """
六、逆向案例之JS逆向请求加密
6.1、逆向请求加密操作的注解
6.2、定位本地JS代码中针对请求加密生成portal-sign的代码块,然后在爬虫中进行复现即可【MD5和Base84区别】
问题一:理论上我们定位加密,应该是搜索encrypt,但是该案例不可行
问题二:要求:每个人必须得认识md5值,base64值
--MD5值位数是固定的长度是32位的,
portal-sign:首先是32位,其次构成是0-9、a-f,没有f以后的字母是典型的MD5值
--base64位数是4的倍数,没固定的长度,数据越长位数越长
特点:base64只包含:0-9、a-z、A-Z / +
而且MD5是摘要算法,不是加密算法,所以我们如果想破解portal-sign就不应该搜索encrypt加密,AES、DES、RSA这些是加密算法,搜索encrypt是可以的,如果是MD5搜索encrypt正常是搜索不出来的。所以看到是MD5加密,就不应该去搜encrypt。
不相信你也可以搜索encrypt或者搜索MD5,首先是全局搜索,然后打断点,然后进行请求发送,一套流程走下来,会发现并没有走断点。所以以上的这些搜索都是不可用的,这时候我们就需要换个搜索方式:key关键字
在通过key关键字进行搜索的时候,该关键字越古怪越好,这样就方便在众多的代码中一眼找到定位到,如果key关键字不是很好找,还有个方式,就是搜索我们需要定位的比如Portal-Sign附近的比较怪异的词,然后迂回的方式在定位到我们的目标key,反正不管用什么手段目的只有一个,既是定位到我们需要找到的定位的那个key。
6.2.1、定位key关键词所在的JS代码中的位置
6.2.2、确定加密方法并进入
备注:到此其实我们就又回到了之前讲的,有两种处理方式,方式一用Python代码去模拟该加密,方式二直接扣JS代码进行环境补充平替,这里我们选择方式二。
6.2.3、扣出加密的JS代码,在外部使用node进行运行,缺什么环境补什么环境,方便后期使用Python代码进行调用
6.3.4、根据缺什么补什么的理念,使用node运行测试代码,报如下错误
问题一:拿任何的变量,断点需要在当前环境下,拿任何变量的值需要保证断点在当前函数内,所以我们想要哪一行的变量值,我们就把断点断在对应的行上
问题二:环境依赖,根据代码的依赖关系,补全环境
备注:同样的内容,MD5生成的内容是一样的
console.log(cryptoJs.MD5("123456").toString()) //e10adc3949ba59abbe56e057f20f883e /* 备注: cryptoJs.MD5("123456").toString() 调用的是toString s(n).toLocaleLowerCase() 调用的是toLocaleLowerCase 因为所使用的第三方库不一样,所以在进行MD5操作的时候调用的具体方法也会出现不一致的情况,属于正常 */
经过以上的确定和判断,我们可以直接使用我们的第三方库cryptoJs,替换方法n
由于数据data是一致的,所以数据通过MD5加密处理后的生成结果也必定是一致的,所以两边的结果应该是一致的
6.2.5、创建的JS代码块文件:05案例基于JS的响应解密.js
//****************************************************响应解密******************************* /* JS中的 require() 类似Python中的import,导入第三方标准库 crypto-js const cryptoJs 给导入的第三方标准库起一个名字,叫:cryptoJs 如果没有安装crypto-js 需要安装一下 npm install crypto-js JS中使用npm Python中使用pip 区别是:npm 放到当前目录下 pip放到全部python的安装包里面去 */ const cryptoJs = require("crypto-js") function b(t) { var e = cryptoJs.enc.Utf8.parse("EB444973714E4A40876CE66BE45D5930"), n = cryptoJs.enc.Utf8.parse("B5A8904209931867"), a = cryptoJs.AES.decrypt(t, e, { iv: n, mode: cryptoJs.mode.CBC, padding: cryptoJs.pad.Pkcs7 }); return a.toString(cryptoJs.enc.Utf8) } /* 以上的这段代码,我们无需关注代码的业务流程,只需要直接运行缺什么环境依赖,补什么环境依赖。 经过对比和了解,enc和AES都是标准库,所以我们无需研究enc和AES,在上面直接导入JS中的标准库即可 把上方代码中的 h.a 全部更换为: */ // 使用服务器返回的加密数据,进行对如上的代码进行测试 // data = "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" // console.log(b(data)) // 调用修改后的加密方法,获取解密数据 //****************************************************请求加密******************************* function l(t, e) { return t.toString().toUpperCase() > e.toString().toUpperCase() ? 1 : t.toString().toUpperCase() == e.toString().toUpperCase() ? 0 : -1 } function u(t) { for (var e = Object.keys(t).sort(l), n = "", a = 0; a < e.length; a++) if (void 0 !== t[e[a]]) if (t[e[a]] && t[e[a]] instanceof Object || t[e[a]] instanceof Array) { var i = JSON.stringify(t[e[a]]); n += e[a] + i } else n += e[a] + t[e[a]]; return n } function d(t) { for (var e in t) "" !== t[e] && void 0 !== t[e] || delete t[e]; var n = "B3978D054A72A7002063637CCDF6B2E5" + u(t); return cryptoJs.MD5(n).toString() } // 测试代码 // data = { // "ts": 1754982379972, // "pageNo": 2, // "pageSize": 20, // "total": 2800, // "AREACODE": "", // "M_PROJECT_TYPE": "", // "KIND": "GCJS", // "GGTYPE": "1", // "PROTYPE": "", // "timeType": "6", // "BeginTime": "2025-02-12 00:00:00", // "EndTime": "2025-08-12 23:59:59", // "createTime": "" // } // // console.log(d(data)) //console.log(cryptoJs.MD5("123456").toString()) //e10adc3949ba59abbe56e057f20f883e /* 备注: cryptoJs.MD5("123456").toString() 调用的是toString s(n).toLocaleLowerCase() 调用的是toLocaleLowerCase 因为所使用的第三方库不一样,所以在进行MD5操作的时候调用的具体方法也会出现不一致的情况,属于正常 */
6.2.6、创建的Python代码文件:06案例基于JS的响应解密.py
import execjs import requests import time headers = { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://ggzyfw.fujian.gov.cn', 'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', # 'portal-sign': 'e289a313d00e3c58fc562cf2d9f257fa', 这个就不在需要了 'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } # 获取当前时间戳 # time.time() 10位的浮点型,所以需要乘以1000 # int(time.time()*1000) 在用int转换把小数点后面的删掉,等到13位的整型 # str(int(time.time()*1000)) 如何需要可以再次转换成字符串,【本案例不需要,本案例是数字所以转到int即可】 now = int(time.time()*1000)
json_data = { 'pageNo': 2, 'pageSize': 20, 'total': 0, 'AREACODE': '', 'M_PROJECT_TYPE': '', 'KIND': 'GCJS', 'GGTYPE': '1', 'PROTYPE': '', 'timeType': '6', 'BeginTime': '2025-02-11 00:00:00', 'EndTime': '2025-08-11 23:59:59', 'createTime': '', 'ts': now, } # (1)请求加密:基于json_data生成sign值 # 先打开,然后逐行读取JS代码 with open("05案例基于JS的响应解密.js", encoding="utf-8") as f: js_code = f.read() # 获取JS代码的编译器 js_compile = execjs.compile(js_code) # 通过JS代码编译器,调用d方法 sign = js_compile.call("d", json_data) # print("sign:::", sign) # 把生成的sign写入到请求头中 headers["portal-sign"] = sign response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data) print(response.text)
七、综合以上,最终代码如下
7.1、Python文件:07JS逆向最终版.py
07JS逆向最终版.py
import execjs import requests import time # 把冗余代码提出来 # 先打开,然后逐行读取JS代码 with open("05案例基于JS的响应解密.js", encoding="utf-8") as f: js_code = f.read() # 获取JS代码的编译器 js_code_compile = execjs.compile(js_code) headers = { 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'zh-CN,zh;q=0.9', 'Connection': 'keep-alive', 'Content-Type': 'application/json;charset=UTF-8', 'Origin': 'https://ggzyfw.fujian.gov.cn', 'Referer': 'https://ggzyfw.fujian.gov.cn/business/list/', 'Sec-Fetch-Dest': 'empty', 'Sec-Fetch-Mode': 'cors', 'Sec-Fetch-Site': 'same-origin', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36', # 'portal-sign': 'e289a313d00e3c58fc562cf2d9f257fa', 这个就不在需要了 'sec-ch-ua': '"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', } def get_one_page(page): # 获取当前时间戳 # time.time() 10位的浮点型,所以需要乘以1000 # int(time.time()*1000) 在用int转换把小数点后面的删掉,等到13位的整型 # str(int(time.time()*1000)) 如何需要可以再次转换成字符串,【本案例不需要,本案例是数字所以转到int即可】 now = int(time.time() * 1000) json_data = { 'pageNo': page, 'pageSize': 20, 'total': 0, 'AREACODE': '', 'M_PROJECT_TYPE': '', 'KIND': 'GCJS', 'GGTYPE': '1', 'PROTYPE': '', 'timeType': '6', 'BeginTime': '2025-02-11 00:00:00', 'EndTime': '2025-08-11 23:59:59', 'createTime': '', 'ts': now, } # (1)请求加密:基于json_data生成sign值 """ 冗余代码 # 先打开,然后逐行读取JS代码 with open("05案例基于JS的响应解密.js", encoding="utf-8") as f: js_code = f.read() # 获取JS代码的编译器 js_compile = execjs.compile(js_code) """ # 通过JS代码编译器,调用d方法 sign = js_code_compile.call("d", json_data) # print("sign:::", sign) # 把生成的sign写入到请求头中 headers["portal-sign"] = sign response = requests.post('https://ggzyfw.fujian.gov.cn/FwPortalApi/Trade/TradeInfo', headers=headers, json=json_data) # print(response.text) # (2)响应解密:基于JS实现AES算法进行解密 """ 冗余代码 # 先打开,然后逐行读取JS代码 with open("05案例基于JS的响应解密.js", encoding="utf-8") as f: js_code = f.read() # 获取JS代码的编译器 js_code_compile = execjs.compile(js_code) """ data = response.json().get("Data") # 调用JS代码中的b函数,把data作为参数进行传递 res = js_code_compile.call("b", data) print("res:::", res) def main(): for i in range(1, 6): time.sleep(2) get_one_page(i) main()
7.2、JS文件:05案例基于JS的响应解密.js
05案例基于JS的响应解密.js //****************************************************响应解密******************************* /* JS中的 require() 类似Python中的import,导入第三方标准库 crypto-js const cryptoJs 给导入的第三方标准库起一个名字,叫:cryptoJs 如果没有安装crypto-js 需要安装一下 npm install crypto-js JS中使用npm Python中使用pip 区别是:npm 放到当前目录下 pip放到全部python的安装包里面去 */ const cryptoJs = require("crypto-js") function b(t) { var e = cryptoJs.enc.Utf8.parse("EB444973714E4A40876CE66BE45D5930"), n = cryptoJs.enc.Utf8.parse("B5A8904209931867"), a = cryptoJs.AES.decrypt(t, e, { iv: n, mode: cryptoJs.mode.CBC, padding: cryptoJs.pad.Pkcs7 }); return a.toString(cryptoJs.enc.Utf8) } /* 以上的这段代码,我们无需关注代码的业务流程,只需要直接运行缺什么环境依赖,补什么环境依赖。 经过对比和了解,enc和AES都是标准库,所以我们无需研究enc和AES,在上面直接导入JS中的标准库即可 把上方代码中的 h.a 全部更换为: */ // 使用服务器返回的加密数据,进行对如上的代码进行测试 // data = "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" // console.log(b(data)) // 调用修改后的加密方法,获取解密数据 //****************************************************请求加密******************************* function l(t, e) { return t.toString().toUpperCase() > e.toString().toUpperCase() ? 1 : t.toString().toUpperCase() == e.toString().toUpperCase() ? 0 : -1 } function u(t) { for (var e = Object.keys(t).sort(l), n = "", a = 0; a < e.length; a++) if (void 0 !== t[e[a]]) if (t[e[a]] && t[e[a]] instanceof Object || t[e[a]] instanceof Array) { var i = JSON.stringify(t[e[a]]); n += e[a] + i } else n += e[a] + t[e[a]]; return n } function d(t) { for (var e in t) "" !== t[e] && void 0 !== t[e] || delete t[e]; var n = "B3978D054A72A7002063637CCDF6B2E5" + u(t); return cryptoJs.MD5(n).toString() } // 测试代码 // data = { // "ts": 1754982379972, // "pageNo": 2, // "pageSize": 20, // "total": 2800, // "AREACODE": "", // "M_PROJECT_TYPE": "", // "KIND": "GCJS", // "GGTYPE": "1", // "PROTYPE": "", // "timeType": "6", // "BeginTime": "2025-02-12 00:00:00", // "EndTime": "2025-08-12 23:59:59", // "createTime": "" // } // // console.log(d(data)) //console.log(cryptoJs.MD5("123456").toString()) //e10adc3949ba59abbe56e057f20f883e /* 备注: cryptoJs.MD5("123456").toString() 调用的是toString s(n).toLocaleLowerCase() 调用的是toLocaleLowerCase 因为所使用的第三方库不一样,所以在进行MD5操作的时候调用的具体方法也会出现不一致的情况,属于正常 */
八、今日作业
破解网站:https://www.swhysc.com/swhysc/news/company