==声明==:本文章仅用作技术交流,爬取网络数据应当合理合法,切勿爬取隐私数据或者高频率并发请求,造成的后果自负!
基本信息
-
网站涉及加密参数:businessData, e-sign, e-content-path
-
逆向涉及技术:webpack框架, sm4加密
-
目标数据: 网站招聘信息
接口寻找
首先打开调试窗口,看看数据接口在哪,首先还是点击翻页抓包
全是如下的数据包,并没有我们想要的数据
那就回到请求数据的初始页面
随便点击一个“IT/互联网”下的“测试工程师”,看一下请求接口数据
这个接口就是接收数据的了
初步判断
看一下这个接口有没有携带什么参数
- 标头
- 载荷
通过对比多次请求的接口,发现这三个参数都是会变化的,有些网站可能对其中的参数不会校验,但经过测试,这些参数都会被后端校验,所以都需要逆向出来。
载荷逆向
先从载荷入手吧(纯个人喜好),最简单的关键字搜索去碰碰运气
找到n先,一般都在这段代码的上面
打个断点调试一下
点进 “_” 这个方法看一看
主要是return后面的代码
这是一个判断式,简单来说 “ ? ” 前面的式子 "sm" === t.type 为真时执行 “ ? ” 和 “ : ” 之间的代码,反之则执行 “ : ” 后面的代码
从开始的代码可以判断出t.type一定是 “sm” 则这个判断式必为真,如下图
那么就是说,我们只需要关注“ ? ” 和 “ : ” 之间的代码,如下
可是事情没有那么简单,首先你并不能明确这段代码 现在 生成的值就是请求接口携带的值,在多次对比生成结果和最终携带的值之后,发现当第 6~7 次停到这段代码时,才是真正的生成位置
判断依据可以是上图标明的 word 具体值,也就是需要加密的 明文值 ,当其中出现 "target":"SEARCH_RESULT_PAGE" 字段时,但每次调试时都需要点个6~7次很烦,所以我们可以用浏览器调试用的 条件断点 功能,操作如下图
-
右键需要断点的位置
-
点击 “添加条件断点”,输入以下条件判断式(当word字段中存在"target":"SEARCH_RESULT_PAGE"时断住)
这样的话每当我们重新请求接口时,浏览器总是会在我们需要的时候断住
实际上这段代码明面上已经告诉我们了,这是那该死的 sm4 加密,不过也有可能魔改了,但不妨碍我们做个实验,因为 sm4 是固定的加密方式,直接网上搜或者问AI都可以获得加密模板,这里我提供了我的加密模板,不用谢
/* 通用sm4加密,已知key和iv的加密代码 */
// 引入sm-crypto库的sm4模块
const { sm4 } = require('sm-crypto'); // npm install sm-crypto
/**
* SM4 CBC模式加密函数(PKCS7填充,128bit密钥,输出hex)
* @param {string} plaintext - 待加密的明文
* @param {string} key - 128bit密钥(hex格式)
* @param {string} iv - 128bit初始向量(hex格式)
* @returns {string} 加密后的hex格式密文
*/
function sm4CbcEncrypt(plaintext, key, iv) {
try {
// SM4 CBC加密(默认使用PKCS7填充)
const ciphertext = sm4.encrypt(
plaintext, // 明文
key, // 128bit密钥(hex)
{
mode: 'cbc', // 运算模式:CBC
iv: iv, // 初始向量(hex)
output: 'hex' // 输出格式:hex
}
);
return ciphertext;
} catch (error) {
console.error('SM4加密失败:', error.message);
throw error;
}
}
用这个模板首先需要固定参数:需要加密的明文信息,key, iv,而这些在JS源码中都能找到
- 明文信息(固定)
- key(暂时固定,后面需要逆向)
- iv(暂时固定,后面需要逆向)
- 正确加密之后的值
- 本地代码生成的值
文本对比完全一致
接下来去看一下 key 和 iv 吧,首先是 key ,它的生成位置在代码上方可以找到
点进 E 方法中看一下
这里直接扣代码了,t可以固定
w 未知
补呗,还能咋整
m函数 未知,下图补充
看着需要补window环境,不过这个 t 的作用除了用作 if 判断,也就个 getRandomValues 方法,我在这里借用了 AI 写了一个和原生浏览器对象 window 下的 getRandomValues 方法一模一样的方法
const nodeCrypto = require('crypto'); // npm install crypto
function getRandomValues(typedArray) {
if (!typedArray || !(typedArray instanceof Uint8Array)) {
throw new TypeError('参数必须是 Uint8Array 类型');
}
// 用 Node.js 原生 randomBytes 生成随机数并写入数组
const randomBuffer = nodeCrypto.randomBytes(typedArray.length);
typedArray.set(randomBuffer);
return typedArray;
}
然后改写成如下代码就行了
还有个 o 方法需要找出来
0_o,看样子是 webpack 框架啊,打个断点看看(打完断点后记得刷新触发)
实锤了,就是 webpack 打包框架,将整个JS文件复制到本地,webpack 源码的逆向操作本文不涉及,可以参考以下文章:
guishou.blog.csdn.net/article/det…
其他的代码就很简单了
最后也是得到了key值
接下来是 iv 值
跟前面的 key 生成的方法一模一样,在此不做赘述。
此时此刻将上面的整合一下,就可以得到载荷 businessData 的值了。
e-sign逆向
这个依旧是关键字搜索
这个 n 有点眼熟,看了一下发现就是 businessData 的值,传递的参数已经解决
看一下 b 方法在哪里定义
也是跟 webpack 有关,好办,直接这样写就行了
var b = global.loader("gGBh").sm3;
var o = b("business" + n + "data"); // o 就是e-sign的值
e-content-path逆向
其实在上面逆向 e-sign 时,眼尖的你应该能看到,e-content-path 参数的生成位置和它在一起
经过反复测试,发现这个 e-content-path 其实和前面 businessData 生成的逻辑有点相似,都不是一步到位的,需要添加 条件判断式,主要判断依据为 t 中的 publicKey 的值,它是固定的
043f4a9673db98fd52a87e087da75ca8d4978748188e29373acc131887d7b78ee89b07364f644352e4cb4029d8330509368b27b10638345c8afd41149626d917aa
在以下位置打上条件断点
这个条件断点要搭配上面调试 businessData 的条件断点,执行顺序是
上面不是很难,看一下 k 函数
根据代码中的条件判断,想必一辈子都只会执行下图标记的代码
所以这个 k 方法可以删删减减,变成下面的样子
v 方法在这
那还说啥,直接这样写就行了
var v = global.loader("gGBh").sm2;
x 在这
这样写
var x = m(32);
C 在这
这样写
var C = m(32);
至此也是生成出来了
结果展示
相信到了这一步,你已经过了所有的难关,就美美地把所有参数整合起来
再通过 python 脚本请求接口获取数据
收工!!!
如有爬虫相关问题,可关注wx公众号“小恰学逆向”,我们一起讨论学习。