文章目录
- 1. 写在前面
- 2. 接口分析
- 3. 断点分析
- 3. 算法还原
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
最近有位读者找上了作者,需要采集易车网上面一些汽车相关的数据,用以毕业设计使用。据了解读者的情况会一点Python,也懂一点爬虫(但是到什么程度不详~~)
按照描述的话,应该是说在获取详情页数据的时候,接口有参数加密?接下来将本次的分析分享出来供大家参考学习,难度算是入门级,适合各位学习爬虫技术的新手小伙伴们!最后完整的代码也提供给了读者
2. 接口分析
老规矩,这里的话更多车型需要登录才可显示更多数据,打开详情页面,监测一下请求发包,请求头内X-sign应该是加密生成的,如下所示:
X-User-Guid参数的话看着像是用户唯一标识的值,可固定!后面断点分析的时候发现这个参数在CK信息内获取就可以了,如下所示:
然后详情接口buy_car_calculator_info跟同系二手车推荐接口get_recommend_ucar_list只需提交两个参数,分别是cid跟param,参数在响应接口内均可找到,如下所示:
?cid=508¶m={"serialId":"7350"}
?cid=508¶m={"cityId":"201","serialId":"7219","type":1,"count":8}
3. 断点分析
X-sign参数32位,这里大概率还是MD5加密,先全局搜索一下参数,可以直接在JS文件找到,下个断刷新一下,如下所示:
单步跟到s方法内,这个方法是加密核心位置,我们直接把代码拿下来分析一下,如下所示:
function s(e, t) {
var n = "";
if ("headers" == e.encryptType) {
var i = e.data ? JSON.stringify(e.data) : "{}"
, o = r(e, t);
n = "cid=" + t.cid + "¶m=" + i + o + t.timestamp
} else {
var a = [];
a.push("cid=" + t.cid),
a.push("uid=" + t.uid),
a.push("ver=" + t.ver),
a.push("devid=" + (e.deviceId || "")),
a.push("t=" + t.timestamp),
a.push("key=" + t.paramsKey),
n = a.join(";")
}
var s = yicheUtils.md5(n);
return s
}
相信到这里,有经验的小伙伴都知道如何还原了,MD5加密,然后n是加密的对象,其中o是一个固值,请求参数加上o跟时间戳加密生成最终签名,如下所示:
3. 算法还原
下面我们分别使用多种语言来还原一下上面sign加密算法,首先使用Python进行实现,如下所示:
import hashlib
import time
timestamp = str(int(time.time() * 1000))
param = '' # 请求参数
cid = ''
o = '19DDD1FBDFF065D3A4DA777D2D7A81EC'
n = f'cid={cid}¶m={param}{o}{timestamp}'
obj = hashlib.md5()
obj.update(n.encode('utf-8'))
sign = obj.hexdigest()
print(sign)
NodeJS实现方式如下:
const crypto = require('crypto');
const timestamp = new Date().getTime().toString();
const param = '';
const cid = '';
const o = '19DDD1FBDFF065D3A4DA777D2D7A81EC';
const n = `cid=${cid}¶m=${param}${o}${timestamp}`;
const hash = crypto.createHash('md5');
hash.update(n);
const sign = hash.digest('hex');
console.log(sign);
Golang实现方式如下:
package main
import (
"crypto/md5"
"encoding/hex"
"fmt"
"strconv"
"time"
)
func main() {
timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
param := ""
o := "19DDD1FBDFF065D3A4DA777D2D7A81EC"
cid := ""
n := "cid=" + cid + "¶m=" + param + o + timestamp
hash := md5.New()
hash.Write([]byte(n))
sign := hex.EncodeToString(hash.Sum(nil))
fmt.Println(sign)
}
最后作者也是编写了一个完整的爬虫Demo发送给了那位读者,测试结果如下所示: