爬虫&逆向--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、逆向请求加密操作的注解

爬虫的本质就是通过代码,自动化获取大量数据,所以在之前的一些小案例中当我们仅仅修改页码相关的字段类似:pageNo=3修改为pageNo=1等就能自动获取多个页面的数据;如果嵌套到循环中,就可以自动的获取更多页面的数据;截至到第五步:逆向案例之JS逆向响应解密,我们已经可以把服务器返回的数据进行解密了,但是在发送请求时,我们按照之前的逻辑更新pageNo等页码相关的字段再次获取数据提示错误,所以很明显对应的请求也是做了加密处理,所以我们需要在爬虫代码中也模仿浏览器的加密操作,做和浏览器相同的操作,然后在发送给服务器即可。

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