爬虫逆向实战(二十四)--某鸟记录中心
一、数据接口分析
主页地址:某鸟记录中心
1、抓包
通过抓包可以发现数据接口是front/record/search/page
2、判断是否有加密参数
- 请求参数是否加密?
通过查看“载荷”模块可以发现,请求参数是加密的
- 请求头是否加密?
通过查看“请求标头”可以发现Requestid
和Sign
是加密参数,并且有一个Timestamp
时间戳
- 响应是否加密?
通过查看“响应”模块可以发现,响应中的数据是加密数据
- cookie是否加密?
无
二、加密位置定位
1、加密参数以及请求头加密
(1)看启动器
查看启动器发现里面有一个pullData的调用堆栈,点进去查看
点进去后,可以看出,此处是发送ajax请求的位置,在此处下断点,再次翻页获取数据,发现可以断住,但是此处是明文数据,所以加密位置不在这里。
(2)搜索关键字
因为“载荷”是一整个密文,没有关键字,所以无法搜索
(3)hook
因为“载荷”是一整个密文,所以网站大概率会使用JSON.stringify
将数据转换为json字符串再进行加密,所以我们可以hookJSON.stringify
,hook代码:
var my_stringify = JSON.stringify;
JSON.stringify = function (params) {debuggerconsole.log("json_stringify params:",params);return my_stringify(params);
};
运行hook代码,再次获取数据,发现可以断住
继续调试执行,可以发现,网站是使用ajaxSetup
设置了ajax请求的全局配置,请求头和加密参数都是在此处进行赋值的。
2、响应数据
(1)hook
因为响应加密数据一般都是json数据加密,所以解密后会使用JSON.parse
进行解密,所以我们可以对JSON.parse
进行hook
hook代码段:
var my_parse = JSON.parse;
JSON.parse = function (params) {debuggerconsole.log("json_parse params:",params);return my_parse(params);
};
运行hook代码,再次获取数据,发现可以断住明文
接着调试执行,就可以找到解密位置
三、扣js代码
1、加密参数及请求头
将定位到的加密位置的代码扣出,可以发现网站的数据加密是使用的JSEncrypt
模块进行的RAS加密,所以我们可以直接使用标准模块进行加密,但是网站使用的encrypt.encryptUnicodeLong
方法,node.js中是没有的,所以我们还需要将这个方法扣出来。下方请求头加密使用的md5,我们同样可以使用标准模块进行加密。
2、响应数据
将定位到的解密位置的代码扣出,进入到网站的解密方法BIRDREPORT_APIJS.decode
中,可以发现,网站是使用的AES解密的,所以我们可以使用标准的AES模块进行解密。
JavaScript源码:
const JSEncrypt = require('jsencrypt');var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64pad = "=";function hex2b64(h) {var i;var c;var ret = "";for (i = 0; i + 3 <= h.length; i += 3) {c = parseInt(h.substring(i, i + 3), 16);ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);}if (i + 1 == h.length) {c = parseInt(h.substring(i, i + 1), 16);ret += b64map.charAt(c << 2);} else if (i + 2 == h.length) {c = parseInt(h.substring(i, i + 2), 16);ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);}while ((ret.length & 3) > 0) {ret += b64pad;}return ret;
}JSEncrypt.prototype.encryptUnicodeLong = function (string) {var k = this.getKey();//根据key所能编码的最大长度来定分段长度。key size - 11:11字节随机padding使每次加密结果都不同。var maxLength = ((k.n.bitLength() + 7) >> 3) - 11;var subStr = "", encryptedString = "";var subStart = 0, subEnd = 0;var bitLen = 0, tmpPoint = 0;for (var i = 0, len = string.length; i < len; i++) {//js 是使用 Unicode 编码的,每个字符所占用的字节数不同var charCode = string.charCodeAt(i);if (charCode <= 0x007f) {bitLen += 1;} else if (charCode <= 0x07ff) {bitLen += 2;} else if (charCode <= 0xffff) {bitLen += 3;} else {bitLen += 4;}//字节数到达上限,获取子字符串加密并追加到总字符串后。更新下一个字符串起始位置及字节计算。if (bitLen > maxLength) {subStr = string.substring(subStart, subEnd)encryptedString += k.encrypt(subStr);subStart = subEnd;bitLen = bitLen - tmpPoint;} else {subEnd = i;tmpPoint = bitLen;}}subStr = string.substring(subStart, len)encryptedString += k.encrypt(subStr);return hex2b64(encryptedString);
};const CryptoJS = require('crypto-js')function getUuid() {var s = [];var a = "0123456789abcdef";for (var i = 0; i < 32; i++) {s[i] = a.substr(Math.floor(Math.random() * 0x10), 1)}s[14] = "4";s[19] = a.substr((s[19] & 0x3) | 0x8, 1);s[8] = s[13] = s[18] = s[23];var b = s.join("");return b
}function sort_ASCII(a) {var b = new Array();var c = 0;for (var i in a) {b[c] = i;c++}var d = b.sort();var e = {};for (var i in d) {e[d[i]] = a[d[i]]}return e
}function url2json(a) {var b = /^[^\?]+\?([\w\W]+)$/, reg_para = /([^&=]+)=([\w\W]*?)(&|$|#)/g, arr_url = b.exec(a), ret = {};if (arr_url && arr_url[1]) {var c = arr_url[1], result;while ((result = reg_para.exec(c)) != null) {ret[result[1]] = result[2]}}return ret
}function dataTojson(a) {var b = [];var c = {};b = a.split('&');for (var i = 0; i < b.length; i++) {if (b[i].indexOf('=') != -1) {var d = b[i].split('=');if (d.length == 2) {c[d[0]] = d[1]} else {c[d[0]] = ""}} else {c[b[i]] = ''}}return c
}const serialize = function (a) {var b = [];for (var p in a)if (a.hasOwnProperty(p) && a[p]) {b.push(encodeURIComponent(p) + '=' + encodeURIComponent(a[p]))}return b.join('&')
};
var paramPublicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvxXa98E1uWXnBzXkS2yHUfnBM6n3PCwLdfIox03T91joBvjtoDqiQ5x3tTOfpHs3LtiqMMEafls6b0YWtgB1dse1W5m+FpeusVkCOkQxB4SZDH6tuerIknnmB/Hsq5wgEkIvO5Pff9biig6AyoAkdWpSek/1/B7zYIepYY0lxKQIDAQAB";
var encrypt = new JSEncrypt();
encrypt.setPublicKey(paramPublicKey);function get_params() {var b_data = 'page=1&limit=20&taxonid=&startTime=&endTime=&province=&city=&district=&pointname=%E6%B2%B3%E5%8D%97&username=&serial_id=&ctime=&taxonname=&state=&mode=0&outside_type=0'var c = Date.parse(new Date());var d = getUuid();var e = JSON.stringify(sort_ASCII(dataTojson(b_data || '{}')));b_data = encrypt.encryptUnicodeLong(e);var f = CryptoJS.MD5(e + d + c).toString();return [{timestamp: c.toString(),requestId: d.toString(),sign: f.toString()}, b_data]
}var key = '3583ec0257e2f4c8195eec7410ff1619';
var iv = 'd93c0d5ec6352f20'
apijs_decode = function(a) {var b = CryptoJS.enc.Utf8.parse(key);var c = CryptoJS.enc.Utf8.parse(iv);var d = CryptoJS.AES.decrypt(a, b, {iv: c,mode: CryptoJS.mode.CBC,padding: CryptoJS.pad.Pkcs7});return d.toString(CryptoJS.enc.Utf8)}function get_data(r_data) {var decode_str = apijs_decode(r_data);return JSON.parse(decode_str)
}
相关文章:

爬虫逆向实战(二十四)--某鸟记录中心
一、数据接口分析 主页地址:某鸟记录中心 1、抓包 通过抓包可以发现数据接口是front/record/search/page 2、判断是否有加密参数 请求参数是否加密? 通过查看“载荷”模块可以发现,请求参数是加密的 请求头是否加密? 通过查…...

【操作系统】中断和异常
中断的作用 CPU上会执行两种程序:内核程序和应用程序 在适合的情况下,操作系统内核会把CPU的使用权主动让给应用程序,“中断”是让操作系统内核夺回CPU使用权的唯一途径(用户态转内核态)。 中断技术保证了并发。 中…...

锁策略、原子编程CAS 和 synchronized 优化过程
前言 锁冲突:两个线程获取一把锁,一个线程阻塞等待,一个线程加锁成功。 目录 前言 一、锁策略 (一)乐观锁和悲观锁 (二)重量级锁和轻量级锁 (三)自旋锁和挂起等待…...

【WINAPI】文件读写操作问题
问题描述 在利用WINAPI中的WriteFile和ReadFile函数进行文件读写操作时,出现无法正常读写文件报错。 分析问题 查阅WINAPI源码,查看参数列表各个参数的数据类型。 发现其中第二个参数,也就是需要写进文件的真实数据,其数据类型…...

【LeetCode-中等题】148. 排序链表
文章目录 题目方法一:集合排序(核心是内部的排序)方法二: 优先队列(核心也是内部的排序)方法三:归并排序(带递归) 从上往下方法四:归并排序(省去递…...

Ceph EC pg backfill run
pg的backfill请求也是发送到osd的work queue中与业务IO一起竞争。 PGRecovery::run backfill 57 void PGRecovery::run( 58 OSD *osd, 59 OSDShard *sdata, 60 PGRef& pg, 61 ThreadPool::TPHandle &handle) 62 { 63 osd->do_recovery(pg.get(), epoch_queued…...

腾讯云服务器地域怎么选?广州上海北京?
腾讯云服务器地域有什么区别?怎么选择比较好?地域选择就近原则,距离地域越近网络延迟越低,速度越快。关于地域的选择还有很多因素,地域节点选择还要考虑到网络延迟速度方面、内网连接、是否需要备案、不同地域价格因素…...

Apple Configurator iphone ipad 设备管控 描述文件使用方法
一、准备 App Store 下载安装 Apple Configurator 二、Apple Configurator 注册组织, -----------这个组织可以是个人,或者其它组织导出-------再导入进来: 三、描述文件配置:“” 根据管控需求进行配置 “” 四、使用 Ap…...

Linux 管道(pipe)用法
在 Linux 中,管道(pipe)是一种特殊的机制,用于连接一个进程的标准输出到另一个进程的标准输入。通过使用管道,可以将一个命令的输出直接传递给另一个命令进行处理,实现了进程之间的通信和数据传输。 管道的…...

元素隐式具有 “any“ 类型,因为类型为 “string“ 的表达式不能用于索引类型
今天在写ts文件的过程中,我遍历了一个对象,然后取值的时候发现爆红,如下图👇 经过我一通排查(原因我对ts也不是很熟练),了解到大致意思是说key的值类型不是string类型,在javascript中是默认给你…...

34、springboot切换内嵌Web服务器(Tomcat服务器)与 生成SSL证书来把项目访路径从 HTTP 配置成 HTTPS
知识点1:springboot切换内嵌Web服务器(Tomcat服务器) 知识点2:生成SSL证书来把项目访路径从 HTTP 配置成 HTTPS ★ Spring Boot默认的Web服务器(Tomcat) ▲ 基于Servlet的应用(使用Spring MV…...

3种CSS实现背景图片全屏铺满自适应的方式
01 margin:0px; background: url(images/bg.png) no-repeat; background-size:100% 100%; background-attachment:fixed; url(images/beijing.png)——图片路径的位置; no-repeat—— 图片不重复; center 0px——center是距离页面左边的定位…...

M1 Pro 利用docker 搭建pytho2的开发环境,以vscode连接开发为例
使用 M1 Pro (不支持python2的安装)开发,需要使用 Python 2.7 的环境,在使用 pyenv 安装 Python 2 时遇到了各种奇怪的问题。最终,我决定使用 Docker 搭建开发环境,并使用 VS Code 连接到本地容器。以下是详…...

MySQL概述,架构原理
一.MySQL简介 MySQL是一个关系型数据库管理系统,由瑞典的MySQL AB公司开发,后被oracle公司收购,MySQL是当下最流行的关系型数据库管理系统之一,在WEB应用方面,MySQL是最好的RDBMS(Relational Database Man…...

Three.js实现模型,模型材质可拖拽效果 DragControls
Three.js提供了一个拖拽的API DragControls 用于实现模型材质拖拽效果 DragControls:是一个用于在Three.js中实现拖拽控制的辅助类。它简化了在Three.js中实现拖拽物体的过程。 DragControls的构造函数接受三个参数: objects:一个包含需要…...

机器学习笔记之优化算法(二十)牛顿法与正则化
机器学习笔记之优化算法——再回首:牛顿法与正则化 引言回顾:经典牛顿法及其弊端牛顿法:算法步骤迭代过程中可能出现的问题正则化 Hessian Matrix \text{Hessian Matrix} Hessian Matrix与相应问题 引言 本节我们介绍经典牛顿法在训练神经网络过程中的迭…...

【Go 基础篇】深入探索:Go语言中的切片遍历与注意事项
嗨,Go语言学习者!在我们的编程旅程中,切片(Slice)是一个极其重要的工具。它可以帮助我们处理各种类型的数据,从而让我们的代码更加灵活和高效。本文将围绕Go语言中切片的遍历方法以及在遍历时需要注意的事项…...

一些经典的SQL语句
查sql中as的用法搜索到的一些经典的sql语句 convert(2008-11-20 18:03:50) In:等值连接,用来查找多表相同字段的记录 Not In:非等值连接,用来查找不存在的记录 Inner join:内连接,主要用来查找都符合条件的记录 Left join:左连接ÿ…...

〔018〕Stable Diffusion 之 批量替换人脸 篇
✨ 目录 🎈 下载插件🎈 插件基础使用🎈 基础使用效果🎈 批量处理图片🎈 多人脸部替换 🎈 下载插件 如果重绘图片的时候,你只想更换人物面部的话,可以参考这篇文章扩展地址ÿ…...

Unity字符串性能问题
前言 分享一些通过书籍和网络学到的知识 每次动态创建一个string,C#都会在堆内存分配一个内存用来分配字符串,因为C#没有对字符串的缓存机制,会导致每次连接、切割、组合的时候都会申请新的内存,并且抛弃原来的内存,等…...

深入浅出SSD:固态存储核心技术、原理与实战(文末赠书)
名字:阿玥的小东东 学习:Python、C/C 主页链接:阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 内容简介 作者简介 使用Python做一个计算器 本期赠书 近年来国家大力支持半导体行业࿰…...

关于layui+php,三级联动-编辑回显的问题。
注 忍不住吐槽一波。都什么年代了。现在都前后端分离,但是公司老项目非得用tplayui。。 代码如下 layui.use([form], function () {var form layui.form;//php代码渲染页面的时候,将一级分类id和二级分类id带过来,存到页面input框中&#x…...

lua的函数
1.一个示例实现列表的元素的求和 [root]# more funcAdd.lua function add(a)local sum 0for i 1,#a dosum sum a[i]endreturn sum enda {1,2,3,4,5,6}local sum add(a)print(sum)...

pytorch/tensorflow 直接给张量中的某个位置的值赋值,操作不可导。
问题:给一个tensor A中[i,j],赋值p。直接操作A[i,j]p可能会导致值覆盖,操作不可导。 解决方案:通过引入一个额外的mask实现。 mask[i,j] 0 mask tf.convert_to_tensor(mask, dtypetf.float32) A (A * mask) (p * (1-mask))p…...

如何使用CSS实现一个平滑滚动到页面顶部的效果(回到顶部按钮)?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 平滑滚动到页面顶部的效果(回到顶部按钮)⭐ 创建HTML结构⭐ 编写CSS样式⭐ 编写JavaScript函数⭐ 添加滚动事件监听器⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右…...

【RuoYi移动端】uniApp导入和引用uView2.0插件
一、打开uiew官网 安装 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架uView UI,是 uni-app 生态最优秀的 UI 框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水https://uviewui.com/components/install.html 也可直…...

etcd 备份还原
etcd 备份还原 查看 etcdctl 是否已经安装 # quick check if etcdctl is available or not ETCDCTL_API3 etcdctl --help | head安装 etcdctl # 获取 etcd 版本信息 kubectl exec -it etcd-master -n kube-system -- /bin/sh -c ETCDCTL_API3 /usr/local/bin/etcd --version…...

LInux之chrony服务器
目录 场景 重要性 LInux的两个时钟 硬件时钟 系统时钟 NTP协议 Chrony介绍 定义 组成 --- chronyd和chronyc 安装与配置 安装 Chrony配置文件分析 同步时间服务器 chronyc命令 chronyc sources输出分析 其它命令 查看时间服务器的状态 查看时间服务器是否在线 …...

《Flink学习笔记》——第七章 处理函数
为了让代码有更强大的表现力和易用性,Flink 本身提供了多层 API 在更底层,我们可以不定义任何具体的算子(比如 map,filter,或者 window),而只是提炼出一个统一的“处理”(process&a…...

Nacos基础(3)——nacos+nginx 集群的配置和启动 端口开放 nginx反向代理nacos集群
目录 引出nacos集群nginx反向代理nacos集群停止单例nacos准备8848和8858修改cluster.conf配置【配置】修改启动配置文件【配置】开放8858的端口分别以集群方式启动【启动】前端访问查看生产者测试8858nacos nginx反向代理配置代理tcp代理http启动nginx反向代理容器生产者访问测…...