python爬虫HMAC加密案例:某企业信息查询网站

声明:
该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关

一、找出需要加密的参数
  1. js运行 atob(‘aHR0cHM6Ly93d3cucWNjLmNvbS93ZWIvc2VhcmNoP2tleT0lRTQlQjglODclRTglQkUlQkUlRTklOUIlODYlRTUlOUIlQTI=’) 拿到网址,F12打开调试工具,点击分页找到 search/searchMultit 请求,鼠标右击请求找到Copy>Copy as cUrl(cmd)
  2. 打开网站:https://spidertools.cn/#/curl2Request,把拷贝好的curl转成python代码
    在这里插入图片描述
  3. 新建qichacha.py文件,把代码复制到该文件内,把请求中的参数拷贝给data,请求中的data参数换成json,运行文件,发现请求成功并成功获取到数据
    在这里插入图片描述
  4. 然后把代码中header、cookie注释调试后会发现一个虽生成的header、QCCSESSID是加密的
    在这里插入图片描述
  5. 在请求cookies中分析得知 ,QCCSESSID是后端生成的可以不用管
    在这里插入图片描述
二、定位参数加密位置
  1. 由于加密的header是动态生成的,显然使用关键字搜索无法定位到,直接切换到sources,添加XHR拦截 search/searchMulti
    在这里插入图片描述
  2. 一直点击跳到下一个函数,会看到作用域header里面已经没有请求头,在代码里又看到熟悉的参数 x-pid,可以尝试的分析里面的代码
    在这里插入图片描述
  3. 鼠标悬浮到 o.default 找到该函数的位置,会发现里面有个header 赋值的代码,在该代码打上断点
    在这里插入图片描述
  4. 结束此次断点调试,点击分页重新发送请求,鼠标悬浮到 i 上发现有随机生成的 header,并且很容易就找到 i = (0, a.default)(t, e.data),l = (0, r.default)(t, e.data, (0, s.default)()),i 是header的key,l是header的value
    在这里插入图片描述
三、扣出加密代码
  1. 创建qichacha.js文件,用于放扣出的js代码
  2. 先把 header 的 key 和 value 扣出来,i = (0, a.default)(t, e.data),l = (0, r.default)(t, e.data, (0, s.default)()),把 t、e.data 在控制台打印出来会发现 t 是请求路径,e.data是请求参数
    在这里插入图片描述在这里插入图片描述
  3. 扣出加密header的key:i = (0, a.default)(t, e.data)
  • 根据第二步已经知道 t 是请求路径,e.data是请求参数,所以只要扣出 a.default 就行, 把 a.default 打印出来会发现,a.default是方法
    在这里插入图片描述
  • 点击打印出的 a.default 方法,会快速找到该方法的位置,会发现只有 o.default、a.default是值得注意的方法,其他都是js语法,在方法内部打上断点,并把 s 方法扣到qichacha.js,把 a.default 换成 s
    在这里插入图片描述在这里插入图片描述
  • 开始扣出 s 方法中的 o.default:结束本次调试,点击分页重新发送请求,鼠标悬浮到 o.default,点击蓝色部分找到该方法,会再次发现 o.default 方法在该代码打上断点,并把 r 方法 js扣到qichacha.js,并把 s 中 o.default 替换成 r
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
  • 结束本次断点,点击分页重新发送请求,一直点击跳到断店调试,看到 e 是路径+参数的字符串时,鼠标悬浮到 r 方法中的 o.default,点击蓝色部分找到该方法,会发现是个HMAC加密
    在这里插入图片描述在这里插入图片描述
  • 分析是哪种 HMAC 加密,在控制台分别打印出:加密数据 e、加密密钥 t、解密结果(0,o.default)(e, t).toString(),打开网站 https://www.dute.org/hmac?ref=search,输入密钥 、加密数据,加密算法是 HMAC SHA 512
    在这里插入图片描述在这里插入图片描述
  • 根据 HMAC SHA 512 算法完成 r 方法,经过测试相同的加密数据和加密密钥,解密结果相同,至此 s 方法中的 o.default 完全扣出,至此 s 方法中的 o.defaul 完全扣出
    在这里插入图片描述
  • 开始扣出 s 方法中的 a.default:分析 s 方法中的 a.default,点击蓝色部分找到该方法,会发现是个 r 方法,里面值得注意的是 o.default,其他都是js语法,在 for循环打上断点,,并把 r 方法 js扣到 qichacha.js 因为和之前 r 方法冲突命名为 r1,并把 s 中 a.default 替换成r1
    在这里插入图片描述在这里插入图片描述
  • 结束本次断点,点击分页重新发送请求,一直点击跳到断店调试,看到 r 方法停止调试,在控制台输出 o.default,把打印结果复制出来,补全 r1 方法,至此 s 方法中的 a.default 完全扣出
    在这里插入图片描述
  • 验证结果 i = (0, a.default)(t, e.data),删除除了 e.headers[i] = l 之外的其他断点,点击第一页发送请求,把 i 打印控制台,再运行 qichacha.js 文件打印 i,对比两个 i 会发现两个之一样
    在这里插入图片描述在这里插入图片描述
  1. 扣出加密header的key:l = (0, r.default)(t, e.data, (0, s.default)())
  • 根据第二步已经知道 t 是请求路径,e.data是请求参数,所以只要扣出 r.default 、r.default 就行
  • 点击分页重新发送请求,鼠标悬浮到 s.default,点击蓝色部分找到该方法,会发现 _default 方法,该方法中都是 js 语法,只需把该函数拷贝出来就行,拷贝出来后命名为 s1,把 s.default 换成 s1
    在这里插入图片描述在这里插入图片描述在这里插入图片描述
  • 测试 s1 方法会发现,报 windows.tid 为 undefined的错误,切换到提示工具 Elements ,全局搜索 windows.tid 会发现该值是固定的值,把该值赋值下来替换 s1 并删除 s1
    在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述
  • 开始扣出 r.default 方法:鼠标悬浮到 r.defaul,点击蓝色部分找到该方法,会发现一个 s 方法,会发现只有 o.default、a.default是值得注意的方法,其他都是js语法,在方法内部打上断点,并把 s 方法扣到qichacha.js 命名为 s1,把 r.default 换成 s1
    在这里插入图片描述在这里插入图片描述
  • 仔细分析 s1 会发现和之前的 s 方法类似,可以先试着,把 s1 方法中的 o.default、a.default 替换成之前的 r、r1
    在这里插入图片描述
  • 测试 s1 方法:把 n、i、(0,o.default)(n + “pathString” + i + t, (0,a.default)(n)) 输出控制台,把 n、i、tid值传给 s1 并打印出来,发现同样的参数,得到值一样,说明 s1 内部的 o.default、a.default 确实是 r、r1,结束断点调试
    在这里插入图片描述
四、验证结果
  1. 修改qichacha.js,把 t、par作为参数传给 main 方法,并运行文件,打印出生成的 key、value
    在这里插入图片描述
  2. 点击第一页重新请求,在控制台输出 i、l,对比发现值都是一样的
    在这里插入图片描述
  3. 修改 qichacha.py 文件,运行文件,数据获取成功
    在这里插入图片描述
五、最终代码
  1. qichacha.js
var cryptoJs = require('crypto-js')

var r = function (e, t) {
    var hmacSha512 = cryptoJs.HmacSHA512(e, t);
    return hmacSha512.toString()
};

var r1 = function () {
    var o = {
        "n": 20,
        "codes": {
            "0": "W",
            "1": "l",
            "2": "k",
            "3": "B",
            "4": "Q",
            "5": "g",
            "6": "f",
            "7": "i",
            "8": "i",
            "9": "r",
            "10": "v",
            "11": "6",
            "12": "A",
            "13": "K",
            "14": "N",
            "15": "k",
            "16": "4",
            "17": "L",
            "18": "1",
            "19": "8"
        }
    };
    for (var e = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase(), t = e + e, n = "", i = 0; i < t.length; ++i) {
        var a = t[i].charCodeAt() % o.n;
        n += o.codes[a]
    }
    return n
};

var s = function () {
    var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
        , t = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase()
        , n = JSON.stringify(e).toLowerCase();
    return r(t + n, r1(t)).toLowerCase().substr(8, 20)
};

var s1 = function () {
    var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}
        , t = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : ""
        , n = (arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : "/").toLowerCase()
        , i = JSON.stringify(e).toLowerCase();
    return r(n + "pathString" + i + t, r1(n))
};

function main(t, par) {
    var i = s(t, par);
    var l = s1(t, par, 'f7d239d312096b665fd9e4a46e603592');
    return {key: i, value: l}
}

var t = '/api/search/searchmulti';
var par = {
    "searchKey": "万达集团",
    "pageIndex": 1,
    "pageSize": 20,
}
console.log(main(t,par))
  1. qichacha.py
import requests
import execjs
import furl

headers = {
    "authority": "www.qcc.com",
    "accept": "application/json, text/plain, */*",
    "accept-language": "zh-CN,zh;q=0.9",
    "cache-control": "no-cache",
    "content-type": "application/json",
    "origin": "https://www.qcc.com",
    "pragma": "no-cache",
    "referer": "https://www.qcc.com/web/search?key=^%^E4^%^B8^%^87^%^E8^%^BE^%^BE^%^E9^%^9B^%^86^%^E5^%^9B^%^A2",
    "sec-ch-ua": "^\\^Google",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "^\\^Windows^^",
    "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/119.0.0.0 Safari/537.36",
    "x-requested-with": "XMLHttpRequest",
    "x-pid": "30ccc65659628b892fb5c1c99a083a95",
    # "43d930d400d14394164a": "87ae6559513fa06d04d868f1a98d6e48637c09c76415caadecdd28f8e52f9912bca862cce00619ae312b20a57701dcf7858063dd9bb071fad27c01076e24be9d",
}
cookies = {
    "QCCSESSID": "eaa3818b5a849d53ca70e37dac",
    "qcc_did": "fe88cac5-6065-4d4d-bdc6-f642aea5386b"
}
url = "https://www.qcc.com/api/search/searchMulti"
data = {
    "searchKey": "万达集团",
    "pageIndex": 2,
    "pageSize": 20
}

with open('qichacha.js','r') as js_file:

    js = execjs.compile(js_file.read())
    url_info = furl.furl(url)
    get_headers = js.call('main',str(url_info.path),data)

    headers[get_headers['key']] = get_headers['value']
    print(headers)

    response = requests.post(url, headers=headers, cookies=cookies, json=data)

    print(response.text)
    print(response)

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

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

相关文章

基于PHP的动漫周边购物系统

有需要请加文章底部Q哦 可远程调试 基于PHP的动漫周边购物系统 一 介绍 此动漫周边购物系统系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。用户可注册登录&#xff0c;购物下单&#xff0c;评论等。管理员登录后台可对动漫周边商品&#xff0c;用户…

JVM中判断对象是否需要回收的方法

在堆里面存放着Java 世界中几乎所有的对象实例&#xff0c;垃圾收集器在对堆进行回收前&#xff0c;第一件事情就是要确定这些对象之中哪些还“ 存活 ” 着&#xff0c;哪些已经 “ 死去 ”。 引用计数算法 引用计数法是一种内存管理技术&#xff0c;它是通过对每个对象进行引用…

实现el-input-number数字框带单位

实现的效果展示&#xff0c;可以是前缀单位&#xff0c;也可以是后缀单位。实现的思路就是动态修改伪元素 ::before 和 ::after 的 content值 实现二次封装数字框的代码如下&#xff1a; <template><el-input-numberref"inputNumber"v-model"inputVal…

某60区块链安全之Call函数簇滥用实战二学习记录

区块链安全 文章目录 区块链安全Call函数簇滥用实战二实验目的实验环境实验原理实验内容实验步骤EXP利用 Call函数簇滥用实战二 实验目的 学会使用python3的web3模块 学会并区分以太坊call、staticcall、delegatecall三种函数调用的特点 找到合约漏洞进行分析并形成利用 实验…

linux CentOS7.6安装jenkins(小白版本)

前言 本人是一个前端开发者&#xff0c;由于有时候需要发版自己的东西&#xff0c;所以想搞一个Jenkins玩玩&#xff0c;看了网上好多教程&#xff0c;但是都不是针对小白的&#xff0c;比如linux怎么输入&#xff0c;怎么结束&#xff0c;自己也是搞了好久踩了好多坑 所以记录…

大数据预处理技术

文章目录 前言 大数据技术成为前沿专业 也是现在甚至未来的朝阳产业&#xff0c;大数据有分别是 数据预处理 数据存储 大数据处理和分析 数据可视化 部分组成 &#xff0c;大数据行业有数据则称王&#xff0c;大数据的核心是数据本身 怎么获取有价值的数据呢&#xff1f;本章讲…

七天.NET 8操作SQLite入门到实战 - 第三天SQLite快速入门

前言 今天我们花费一个小时快速了解SQLite数据类型、SQLite常用命令和语法。 七天.NET 8操作SQLite入门到实战详细教程 第一天 SQLite 简介第二天 在 Windows 上配置 SQLite环境 EasySQLite项目源码地址 GitHub地址&#xff1a;https://github.com/YSGStudyHards/EasySQLite&…

Cookie、Session、CBV加装饰器的三种方法

【0】cookie、session和Token的发展史 【1】Cookie的形式 存储形式&#xff1a;k&#xff1a;v键值对存储位置&#xff1a;客户端缺点&#xff1a;不安全&#xff0c;信息可能会泄露 【2】session的形式 标识符&#xff0c;表示我是当前用户加密出来的数据对敏感信息进行加密…

github访问失败

1. 问题场景 今天了解到notepad可以安装许多插件&#xff0c;但是自动下载插件时总是失败&#xff0c;这些插件的下载源都是github&#xff0c;将地址复制到浏览器也打不开&#xff0c;所以查了下github的访问问题&#xff0c;目前插件已正常下载。 2. 解决方法 gitee上搜索…

[项目管理-33/创业之路-87/管理者与领导者-127]:如何提升自己项目管理的能力和水平

目录 前言&#xff1a; 一、项目经理的角色定位 1.1 项目经理的职责 1.2 不同矩阵类型的项目&#xff0c;项目经理的职责 1.3 项目经理的角色定位 1.4 项目经理的发展路径 二、项目经理项目理论和知识结构 三、软件项目经理在计算机水平的提升 四、项目经理业务知识的…

基于JavaWeb+SSM+Vue家庭记账本微信小程序系统的设计和实现

基于JavaWebSSMVue家庭记账本微信小程序系统的设计和实现 源码获取入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 1.1选题背景 互联网是人类的基本需求&#xff0c;特别是在现代社会&#xff0c;个人…

elasticsearch 7安装

问题提前报 max virtual memory areas error max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 如果您的环境是Linux&#xff0c;注意要做以下操作&#xff0c;否则es可能会启动失败 1 用编辑工具打开文件/etc/sysctl.conf 2 …

Eclipse常用设置-乱码

在用Eclipse进行Java代码开发时&#xff0c;经常会遇到一些问题&#xff0c;记录下来&#xff0c;方便查看。 一、properties文件乱码 常用的配置文件properties里中文的乱码&#xff0c;不利于识别。 处理流程&#xff1a;Window -> Preferences -> General -> Ja…

孟德尔随机化 MR入门基础-简明教程-工具变量-暴露

孟德尔随机化&#xff08;MR&#xff09;入门介绍和分章分享&#xff08;暂时不解读&#xff09; 大家好&#xff0c;孟德尔随机化大火&#xff0c;但是什么是孟德尔随机化&#xff0c;具体怎么实操呢 这没有其他教程的繁冗&#xff0c;我这篇讲最基础的孟德尔随机化的核心步…

洛谷 P4552 [Poetize6] IncDec Sequence

挺好的一道思维题。 分析 因为是对区间修改&#xff0c;多次修改肯定会超时&#xff0c;很容易想到差分。 那么原题的对区间修改就可以转换为下面三个操作&#xff08;均在差分数组中&#xff09;&#xff1a; 1. 任选一个数1 2. 任选一个数-1 3. 任选两个数1和-1 进一步考…

【JVM精讲与GC调优教程(概述)】

如何理解虚拟机(JVM)跨语言的平台 java虚拟机根本不关心运行在其内部的程序到底是使用何种编程语言编写的,他只关心“字节码”文件。 java不是最强大的语言,但是JVN是最强大的虚拟机。 不存在内存溢出? 内存泄露? JAVA = (C++)–; 垃圾回收机制为我们打理了很多繁琐的…

idea修改行号颜色

前言 i当idea用了深色主题后&#xff0c;发现行号根本看不清&#xff0c;或者很模糊 例如下面这样 修改行号颜色 在IntelliJ IDEA中&#xff0c;你可以根据自己的喜好和需求定制行号的颜色。下面是修改行号颜色的步骤&#xff1a; 打开 IntelliJ IDEA。 转到 “File”&…

机器视觉公司为什么宁愿高薪招新人,也不愿加薪留老员工?老员工特殊时间特殊照顾,新人必须常照顾

​职场常出现的“薪酬倒挂”现象。其实这是正常的职场规律&#xff0c;实际上是企业管理不得不面对的一种选择。 很多企业宁愿老员工离职也不加薪&#xff0c;却高薪请新员工&#xff1f;这就是职场上的鲶鱼效应&#xff0c;一些高层领导认为一个企业&#xff0c;老员工好比沙…

Redis入门指南学习笔记(3):Redis高级特性

一.前言 上一篇博客对Redis常用的数据结构进行了详细介绍。Redis除了丰富的数据类型支持&#xff0c;还包含许多高级特性&#xff0c;例如事务、内存驻留策略、排序、消息队列等&#xff0c;本文将对这些进行逐一介绍。 二.事务 Redis同样包含事务&#xff08;transaction&a…

MongoDB的常用操作以及python连接MongoDB

一,MongoDB的启动 mongod --dbpath..\data\db mongodb注意同时开两个窗口&#xff0c;不要关&#xff01; 二, MongoDB的简单使用 简单介绍一下mongoDB中一些操作 show dbs: 显示所有数据库 show databases: 显示所有数据库 use xxxx: 使用指定数据库/创建数据库&#xff08…