爬虫逆向实战(二十四)--某鸟记录中心

一、数据接口分析

主页地址:某鸟记录中心

1、抓包

通过抓包可以发现数据接口是front/record/search/page
在这里插入图片描述

2、判断是否有加密参数

  1. 请求参数是否加密?
    通过查看“载荷”模块可以发现,请求参数是加密的
    在这里插入图片描述
  2. 请求头是否加密?
    通过查看“请求标头”可以发现RequestidSign是加密参数,并且有一个Timestamp时间戳
    在这里插入图片描述
  3. 响应是否加密?
    通过查看“响应”模块可以发现,响应中的数据是加密数据
    在这里插入图片描述
  4. cookie是否加密?

二、加密位置定位

1、加密参数以及请求头加密

(1)看启动器

查看启动器发现里面有一个pullData的调用堆栈,点进去查看
在这里插入图片描述
点进去后,可以看出,此处是发送ajax请求的位置,在此处下断点,再次翻页获取数据,发现可以断住,但是此处是明文数据,所以加密位置不在这里。
在这里插入图片描述

(2)搜索关键字

因为“载荷”是一整个密文,没有关键字,所以无法搜索

(3)hook

因为“载荷”是一整个密文,所以网站大概率会使用JSON.stringify将数据转换为json字符串再进行加密,所以我们可以hookJSON.stringify,hook代码:

var my_stringify = JSON.stringify;
JSON.stringify = function (params) {
    debugger
    console.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) {
    debugger
    console.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)
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/94542.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Studio开发之路 (五)导入OpenCV以及报错解决

一、步骤 官网下载opencv包&#xff08;我下的是4.7.0&#xff09;并解压&#xff0c;openvc官网 先创建一个空项目&#xff0c;简单跑一下能正常输出helloworld 点击file->new->Import Module选择解压之后的opencv-android-sdk文件夹中的SDk文件夹&#xff0c; modu…

docker搭建owncloud,Harbor,构建镜像

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 拉取镜像 docker pull owncloud docker pull mysql:5.6 2、安装搭建私有仓库 Harbor 1.下载docker-compose 2.安装harbor 3.编辑 harbor.yml文件 使用./intall.sh安装 4.登录 3、编写Dockerfile制作Web应用系…

Java 程序打印 OpenCV 的版本

我们可以使用 Java 程序来使用 OpenCV。 OpenCV 的使用需要动态库的加载才可以。 加载动态库 到 OpenCV 的官方网站上下载最新的发布版本。 Windows 下载的是一个可执行文件&#xff0c;没关系&#xff0c;这个可执行文件是一个自解压程序。 当你运行以后会提示你进行解压。…

解决抖音semi-ui的Input无法获取到onChange事件

最近在使用semi-ui框架的Input实现一个上传文件功能时遇到了坑&#xff0c;就是无法获取到onChange事件&#xff0c;通过console查看只是拿到了一个文件名。但若是把<Input>换成原生的<input>&#xff0c;就可以正常获取到事件。仔细看了下官方文档&#xff0c;发现…

Windows 转 mac 记录

初次从Windows转mac可能会不适应&#xff0c;建议先看看 【6分钟搞定MacBook】不懂时无所适从&#xff0c;学会后越用越爽&#xff01;_哔哩哔哩_bilibili 我主要是做一些补充记录 1、Windows的右键等于mac的双击触控板、control单击触控板 2、运行中的应用下方会有一个点&…

时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比

时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比 目录 时序预测 | MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比效果一览基本描述程序设计参考资料 效果一览 基本描述 MATLAB实现基于PSO-BiLSTM、BiLSTM时间序列预测对比。 1.Matlab实现PSO-BiLSTM和BiLSTM…

微信小程序分享后真机参数获取不到和部分参数不能获取问题问题解决

微信小程序的很多API&#xff0c;都是BUG&#xff0c;近期开发小程序就遇到了分享后开发工具可以获取参数&#xff0c;但是真机怎么都拿不到参数的问题 一、真机参数获取不到问题解决 解决方式&#xff1a; 在onLoad(options) 中。 onLoad方法中一定要有options 这个参数。…

Python爬虫框架之快速抓取互联网数据详解

概要 Python爬虫框架是一个能够帮助我们快速抓取互联网数据的工具。在互联网时代&#xff0c;信息爆炸式增长&#xff0c;人们越来越需要一种快速获取信息的方式。而Python爬虫框架就能够帮助我们完成这个任务&#xff0c;它可以帮助我们快速地从互联网上抓取各种数据&#xf…

Java并发编程第6讲——线程池(万字详解)

Java中的线程池是运用场景最多的并发框架&#xff0c;几乎所有需要异步或并发执行任务的程序都可以使用线程池&#xff0c;本篇文章就详细介绍一下。 一、什么是线程池 定义&#xff1a;线程池是一种用于管理和重用线程的技术&#xff08;池化技术&#xff09;&#xff0c;它主…

Python爬虫追踪新闻事件发展进程及舆论反映

目录 实现方案 1. 确定目标新闻源&#xff1a; 2. 确定关键词&#xff1a; 3. 使用网络爬虫获取新闻内容&#xff1a; 4. 提取和分析新闻文章&#xff1a; 5. 追踪新闻事件的发展进程&#xff1a; 6. 监测舆论反映&#xff1a; 7. 数据可视化&#xff1a; 完整代码示例…

【DEVOPS】Jenkins使用问题 - 控制台输出乱码

0. 目录 1. 问题描述2. 解决方案3. 最终效果4. 总结 1. 问题描述 部门内部对于Jenkins的使用采取的是Master Slave Work Node的方式&#xff0c;即作为Master节点的Jenkins只负责任务调度&#xff0c;具体的操作由对应的Slave Work Node去执行。 最近团队成员反馈一个问题&a…

基于 OV5640 摄像头理论知识讲解-成像和采样原理

基于OV2640/ OV5640 的图像采集显示系统系列文章目录&#xff1a; &#xff08;1&#xff09;基于 OV5640 摄像头理论知识讲解-成像和采样原理 &#xff08;2&#xff09;基于 OV5640 摄像头理论知识讲解-数字接口和控制接口 &#xff08;3&#xff09;基于 OV5640 摄像头理论知…

未来科技城携手加速科技 共建集成电路测试公共服务平台!

8月26日&#xff0c;2023未来产业发展大会在杭州未来科技城国际会议中心开幕&#xff01;会上&#xff0c;发布了未来科技城培育发展未来产业行动计划&#xff0c;启动了未来产业发展共同体&#xff0c;进行了未来产业公共服务平台签约仪式。未来科技城与加速科技签约共建集成电…

系列十三、idea创建文件自动生成作者信息

File>Settings>Editor>File and Code Templates>Includes>File Header /*** Author : 一叶浮萍归大海* Date: ${DATE} ${TIME}* Description: */

24 WEB漏洞-文件上传之WAF绕过及安全修复

目录 WAF绕过上传参数名解析:明确哪些东西能修改?常见绕过方法&#xff1a;符号变异-防匹配( " ;)数据截断-防匹配(%00 ; 换行)重复数据-防匹配(参数多次)搜索引擎搜索fuzz web字典文件上传安全修复方案 WAF绕过 safedog BT(宝塔) XXX云盾 宝塔过滤的比安全狗厉害一些&a…

Django(9)-表单处理

django支持使用类创建表单实例 polls/forms.py from django import forms class NameForm(forms.Form):your_nameforms.CharField(label"Your name",max_length100)这个类创建了一个属性&#xff0c;定义了一个文本域&#xff0c;和它的label和最大长度。 polls/vi…

云服务器(Centos7系统)配置JAVA+mysql+tomcat 环境

文章主要内容来源云服务器&#xff08;Centos7系统&#xff09;部署javaweb项目&#xff08;二&#xff09;配置JAVAmysqltomcat 环境_man_zuo的博客-CSDN博客 模仿途中遇到的问题 连接无效 有时连接无法下载&#xff0c;可能是过期了&#xff0c;将其更换为官网给的下载连接即…

Java11(集合)

集合 1.集合框架 用于存储数量不等的多个对象&#xff0c;还可用于保存具有映射关系的关联数组 Java集合可分为Collection和Map两种体系 Collection接口 Set:元素无序&#xff0c;不可重复的集合----&#xff08;类似数学中的集合&#xff09; List:元素有序&#xff0c;可重…

入门vue——创建vue脚手架项目 以及 用tomcat和nginx分别部署vue项目(vue2)

入门vue——创建vue脚手架项目 以及 用tomcat和nginx分别部署vue项目&#xff08;vue2&#xff09; 1. 安装npm2. 安装 Vue CLI3. 创建 vue_demo1 项目&#xff08;官网&#xff09;3.1 创建 vue_demo1 项目3.1.1 创建项目3.1.2 解决 sudo 问题 3.2 查看创建的 vue_demo1 项目3…

上门服务系统|上门服务软件开发|上门服务改善生活质量的便捷之选

随着现代生活的快节奏和社交距离的需求&#xff0c;我们越来越渴望能够以更便捷、高效的方式获得我们所需的服务。为了满足这一需求&#xff0c;我们公司开发了一款创新的上门服务系统&#xff0c;旨在将便利与质量相结合&#xff0c;为您提供无与伦比的体验。 无论您是忙碌的白…