爬虫逆向实战(36)-某建设监管平台(RSA,魔改)

一、数据接口分析

主页地址:某建设监管平台

1、抓包

通过抓包可以发现网站首先是请求了一个/prod-api/mohurd-pub/vcode/genVcode的接口,用于获取滑块验证码的图片
在这里插入图片描述
滑块验证之后,请求了/prod-api/mohurd-pub/dataServ/findBaseEntDpPage这个接口,来获取数据
在这里插入图片描述

2、判断是否有加密参数

  1. 请求参数是否加密?
    通过查看“载荷”模块可以发现,这两个接口都是只有一个params的加密参数
    在这里插入图片描述
  2. 请求头是否加密?
  3. 响应是否加密?
  4. cookie是否加密?

二、加密位置定位

1、看启动器

查看启动器发现里面包含异步,所以无法正确找到加密位置
在这里插入图片描述

2、搜索关键字

通过搜索关键字,发现可以搜出来很多位置,无法准确定位到加密位置
在这里插入图片描述

3、Hook

因为请求参数中只有一个params参数,所以网站大概率会使用JSON.stringify方法将明文数据转json之后再加密。
通过hook,我们可以找到加密位置
在这里插入图片描述
同时,可以发现params是进行了双重加密,首先使用W_e().encrypt进行了一次加密(此处有点类似于AES或DES加密,但是通过测试,发现加密结果不一致,所以可能是魔改加密算法),然后将加密结果再使用X_e进行二次加密(此处是标准RSA加密)。

三、扣js代码

W_e().encrypt方法扣出,缺啥补啥即可,X_e方法可以扣网站代码,也可以直接使用标准模块。
注:
此网站的滑块验证码,仅需将缺口距离在第二次数据接口请求时带上即可
源代码:

const JSEncrypt = require('jsencrypt');
const G_e = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC29miF1Wp9XlhCECo+FYpCHad1ipEMgXf4IdgYjMIQwczzo9GXdcZ4eeV+9lkh6+aTqzzU843rdkMt0vrSnujU+GOuDPLfa5LZ6SfanAoysi6xxTX02Xizb3k+Z1USIzm9QAwE+SR1AQ78rGTRFHWFu7OGPkVNeF+vrX3inQTiawIDAQAB";function Jbe(e) {var t = n7(e), n = t[0], o = t[1];return (n + o) * 3 / 4 - o
}function exe(e) {var t, n = n7(e), o = n[0], r = n[1], s = new Xbe(Qbe(e, o, r)), a = 0, l = r > 0 ? o - 4 : o, i;for (i = 0; i < l; i += 4)t = oo[e.charCodeAt(i)] << 18 | oo[e.charCodeAt(i + 1)] << 12 | oo[e.charCodeAt(i + 2)] << 6 | oo[e.charCodeAt(i + 3)],s[a++] = t >> 16 & 255,s[a++] = t >> 8 & 255,s[a++] = t & 255;return r === 2 && (t = oo[e.charCodeAt(i)] << 2 | oo[e.charCodeAt(i + 1)] >> 4,s[a++] = t & 255),r === 1 && (t = oo[e.charCodeAt(i)] << 10 | oo[e.charCodeAt(i + 1)] << 4 | oo[e.charCodeAt(i + 2)] >> 2,s[a++] = t >> 8 & 255,s[a++] = t & 255),s
}
function txe(e) {return Vo[e >> 18 & 63] + Vo[e >> 12 & 63] + Vo[e >> 6 & 63] + Vo[e & 63]
}
function nxe(e, t, n) {for (var o, r = [], s = t; s < n; s += 3)o = (e[s] << 16 & 16711680) + (e[s + 1] << 8 & 65280) + (e[s + 2] & 255),r.push(txe(o));return r.join("")
}
function oxe(e) {for (var t, n = e.length, o = n % 3, r = [], s = 16383, a = 0, l = n - o; a < l; a += s)r.push(nxe(e, a, a + s > l ? l : a + s));return o === 1 ? (t = e[n - 1],r.push(Vo[t >> 2] + Vo[t << 4 & 63] + "==")) : o === 2 && (t = (e[n - 2] << 8) + e[n - 1],r.push(Vo[t >> 10] + Vo[t >> 4 & 63] + Vo[t << 2 & 63] + "=")),r.join("")
}var jc = {};
jc.byteLength = Jbe;
jc.toByteArray = exe;
jc.fromByteArray = oxe;
const O6 = jc;
var Vo = [], oo = [], Xbe = typeof Uint8Array != "undefined" ? Uint8Array : Array, Lu = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
for (var js = 0, Zbe = Lu.length; js < Zbe; ++js)Vo[js] = Lu[js],oo[Lu.charCodeAt(js)] = js;
class V_e {static stringToArrayBufferInUtf8(t) {const n = typeof window == "undefined" ? yd.TextEncoder : window.TextEncoder;return new n().encode(t)}static utf8ArrayBufferToString(t) {const n = typeof window == "undefined" ? yd.TextDecoder : window.TextDecoder;return new n("utf-8").decode(t)}static arrayBufferToBase64(t) {return O6.fromByteArray(t)}static base64ToArrayBuffer(t) {return O6.toByteArray(t)}
}const Sr = V_e, to = 16, Di = Uint8Array.from([214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 20, 194, 40, 251, 44, 5, 43, 103, 154, 118, 42, 190, 4, 195, 170, 68, 19, 38, 73, 134, 6, 153, 156, 66, 80, 244, 145, 239, 152, 122, 51, 84, 11, 67, 237, 207, 172, 98, 228, 179, 28, 169, 201, 8, 232, 149, 128, 223, 148, 250, 117, 143, 63, 166, 71, 7, 167, 252, 243, 115, 23, 186, 131, 89, 60, 25, 230, 133, 79, 168, 104, 107, 129, 178, 113, 100, 218, 139, 248, 235, 15, 75, 112, 86, 157, 53, 30, 36, 14, 94, 99, 88, 209, 162, 37, 34, 124, 59, 1, 33, 120, 135, 212, 0, 70, 87, 159, 211, 39, 82, 76, 54, 2, 231, 160, 196, 200, 158, 234, 191, 138, 210, 64, 199, 56, 181, 163, 247, 242, 206, 249, 97, 21, 161, 224, 174, 93, 164, 155, 52, 26, 85, 173, 147, 50, 48, 245, 140, 177, 227, 29, 246, 226, 46, 130, 102, 202, 96, 192, 41, 35, 171, 13, 83, 78, 111, 213, 219, 55, 69, 222, 253, 142, 47, 3, 255, 106, 114, 109, 108, 91, 81, 141, 27, 175, 146, 187, 221, 188, 127, 17, 217, 92, 65, 31, 16, 90, 216, 10, 193, 49, 136, 165, 205, 123, 189, 45, 116, 208, 18, 184, 229, 180, 176, 137, 105, 151, 74, 12, 150, 119, 126, 101, 185, 241, 9, 197, 110, 198, 132, 24, 240, 125, 236, 58, 220, 77, 32, 121, 238, 95, 62, 215, 203, 57, 72]), L_e = Uint32Array.from([462357, 472066609, 943670861, 1415275113, 1886879365, 2358483617, 2830087869, 3301692121, 3773296373, 4228057617, 404694573, 876298825, 1347903077, 1819507329, 2291111581, 2762715833, 3234320085, 3705924337, 4177462797, 337322537, 808926789, 1280531041, 1752135293, 2223739545, 2695343797, 3166948049, 3638552301, 4110090761, 269950501, 741554753, 1213159005, 1684763257]), Oi = Uint32Array.from([2746333894, 1453994832, 1736282519, 2993693404]);class R_e {constructor(t) {let n = Sr.stringToArrayBufferInUtf8(t.key);if (n.length !== 16)throw new Error("key should be a 16 bytes string");this.key = n;let o = new Uint8Array(0);if (t.iv !== void 0 && t.iv !== null && (o = Sr.stringToArrayBufferInUtf8(t.iv),o.length !== 16))throw new Error("iv should be a 16 bytes string");this.iv = o,this.mode = "cbc",["cbc", "ecb"].indexOf(t.mode) >= 0 && (this.mode = t.mode),this.cipherType = "base64",["base64", "text"].indexOf(t.outType) >= 0 && (this.cipherType = t.outType),this.encryptRoundKeys = new Uint32Array(32),this.spawnEncryptRoundKeys(),this.decryptRoundKeys = Uint32Array.from(this.encryptRoundKeys),this.decryptRoundKeys.reverse()}doBlockCrypt(t, n) {let o = new Uint32Array(36);o.set(t, 0);for (let s = 0; s < 32; s++)o[s + 4] = o[s] ^ this.tTransform1(o[s + 1] ^ o[s + 2] ^ o[s + 3] ^ n[s]);let r = new Uint32Array(4);return r[0] = o[35],r[1] = o[34],r[2] = o[33],r[3] = o[32],r}spawnEncryptRoundKeys() {let t = new Uint32Array(4);t[0] = this.key[0] << 24 | this.key[1] << 16 | this.key[2] << 8 | this.key[3],t[1] = this.key[4] << 24 | this.key[5] << 16 | this.key[6] << 8 | this.key[7],t[2] = this.key[8] << 24 | this.key[9] << 16 | this.key[10] << 8 | this.key[11],t[3] = this.key[12] << 24 | this.key[13] << 16 | this.key[14] << 8 | this.key[15];let n = new Uint32Array(36);n[0] = t[0] ^ Oi[0],n[1] = t[1] ^ Oi[1],n[2] = t[2] ^ Oi[2],n[3] = t[3] ^ Oi[3];for (let o = 0; o < 32; o++)n[o + 4] = n[o] ^ this.tTransform2(n[o + 1] ^ n[o + 2] ^ n[o + 3] ^ L_e[o]),this.encryptRoundKeys[o] = n[o + 4]}rotateLeft(t, n) {return t << n | t >>> 32 - n}linearTransform1(t) {return t ^ this.rotateLeft(t, 2) ^ this.rotateLeft(t, 10) ^ this.rotateLeft(t, 18) ^ this.rotateLeft(t, 24)}linearTransform2(t) {return t ^ this.rotateLeft(t, 13) ^ this.rotateLeft(t, 23)}tauTransform(t) {return Di[t >>> 24 & 255] << 24 | Di[t >>> 16 & 255] << 16 | Di[t >>> 8 & 255] << 8 | Di[t & 255]}tTransform1(t) {let n = this.tauTransform(t);return this.linearTransform1(n)}tTransform2(t) {let n = this.tauTransform(t);return this.linearTransform2(n)}padding(t) {if (t === null)return null;let n = to - t.length % to, o = new Uint8Array(t.length + n);return o.set(t, 0),o.fill(n, t.length),o}dePadding(t) {if (t === null)return null;let n = t[t.length - 1];return t.slice(0, t.length - n)}uint8ToUint32Block(t, n=0) {let o = new Uint32Array(4);return o[0] = t[n] << 24 | t[n + 1] << 16 | t[n + 2] << 8 | t[n + 3],o[1] = t[n + 4] << 24 | t[n + 5] << 16 | t[n + 6] << 8 | t[n + 7],o[2] = t[n + 8] << 24 | t[n + 9] << 16 | t[n + 10] << 8 | t[n + 11],o[3] = t[n + 12] << 24 | t[n + 13] << 16 | t[n + 14] << 8 | t[n + 15],o}encrypt(t) {let n = Sr.stringToArrayBufferInUtf8(t), o = this.padding(n), r = o.length / to, s = new Uint8Array(o.length);if (this.mode === "cbc") {if (this.iv === null || this.iv.length !== 16)throw new Error("iv error");let a = this.uint8ToUint32Block(this.iv);for (let l = 0; l < r; l++) {let i = l * to, c = this.uint8ToUint32Block(o, i);a[0] = a[0] ^ c[0],a[1] = a[1] ^ c[1],a[2] = a[2] ^ c[2],a[3] = a[3] ^ c[3];let u = this.doBlockCrypt(a, this.encryptRoundKeys);a = u;for (let f = 0; f < to; f++)s[i + f] = u[parseInt(f / 4)] >> (3 - f) % 4 * 8 & 255}} elsefor (let a = 0; a < r; a++) {let l = a * to, i = this.uint8ToUint32Block(o, l), c = this.doBlockCrypt(i, this.encryptRoundKeys);for (let u = 0; u < to; u++)s[l + u] = c[parseInt(u / 4)] >> (3 - u) % 4 * 8 & 255}return this.cipherType === "base64" ? Sr.arrayBufferToBase64(s) : Sr.utf8ArrayBufferToString(s)}decrypt(t) {let n = new Uint8Array;this.cipherType === "base64" ? n = Sr.base64ToArrayBuffer(t) : n = Sr.stringToArrayBufferInUtf8(t);let o = n.length / to, r = new Uint8Array(n.length);if (this.mode === "cbc") {if (this.iv === null || this.iv.length !== 16)throw new Error("iv error");let a = this.uint8ToUint32Block(this.iv);for (let l = 0; l < o; l++) {let i = l * to, c = this.uint8ToUint32Block(n, i), u = this.doBlockCrypt(c, this.decryptRoundKeys), f = new Uint32Array(4);f[0] = a[0] ^ u[0],f[1] = a[1] ^ u[1],f[2] = a[2] ^ u[2],f[3] = a[3] ^ u[3],a = c;for (let d = 0; d < to; d++)r[i + d] = f[parseInt(d / 4)] >> (3 - d) % 4 * 8 & 255}} elsefor (let a = 0; a < o; a++) {let l = a * to, i = this.uint8ToUint32Block(n, l), c = this.doBlockCrypt(i, this.decryptRoundKeys);for (let u = 0; u < to; u++)r[l + u] = c[parseInt(u / 4)] >> (3 - u) % 4 * 8 & 255}let s = this.dePadding(r);return Sr.utf8ArrayBufferToString(s)}
}
var j_e = {sm4: R_e
}
function W_e() {const t = {};t.key = "B6*40.2_C9#e4$E3",t['mode'] = 'ecb',t.cipherType = "base64";const n = t, o = j_e['sm4'];return new o(n)
}function get_params(data) {e = W_e().encrypt(JSON.stringify(data))var encrypt = new JSEncrypt();encrypt.setPublicKey(G_e);const o = 117, r = Math['ceil'](e['length'] / o);let s = [];for (let a = 0; a < r; a++) {const l = e.slice(a * o, (a + 1) * o), i = encrypt.encrypt(l);s.push(i)}return s
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C语言】—— 指针一 : 初识指针(上)

【C语言】—— 指针一 &#xff1a; 初识指针&#xff08;上&#xff09; 一、内存和地址1.1、如何理解内存和地址1.2、 如何理解编址 二、指针变量和地址2.1、取地址操作符 &2.2、 指针变量2.3、 解引用操作符 ∗ * ∗2.4、指针变量的大小 三、指针变量类型的意义3.1、 指…

【网络安全】 MSF提权

本文章仅用于信息安全学习&#xff0c;请遵守相关法律法规&#xff0c;严禁用于非法途径。若读者因此作出任何危害网络安全的行为&#xff0c;后果自负&#xff0c;与作者无关。 环境准备&#xff1a; 名称系统位数IP攻击机Kali Linux6410.3.0.231客户端Windows 76410.3.0.234…

计算机考研|408专业课复习教程+注意事项

408其实把真题琢磨透就已经可以了&#xff01;其实大部分考研党复习到最后真题都来不及刷完就要上考场 因为在考研后期时间分配真的很困难&#xff01;特别是数学和408 本人双非科班出身备考408成功上岸&#xff0c;在这里也想给想考408的学弟学妹们一些很中肯的&#xff0c;…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Slider)

滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调节、亮度调节等应用场景。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 无 接口 Slider(options?: SliderOption…

C++Qt学习——QPushButton、QRadioButton(单选按钮)、QCheckBox(复选按钮)

目录 1、QPushButton 1.1、创建一个新的项目&#xff0c;转到UI界面拖一个Push Button 1.2、Push Button的常用信号主要有四个&#xff0c;分别为 clicked(), pressed(), released(), toggled() 1.2.1、按住Push Button右键转到槽&#xff0c;选择信号函数 1.2.2、在Widget…

1.2 课程架构介绍:STM32H5 芯片生命周期管理与安全调试

1.2 课程架构介绍&#xff1a;STM32H5 芯片生命周期管理与安全调试 下面开始学习课程的第二节&#xff0c;简单介绍下STM32H5芯片的生命周期和安全调试&#xff0c;具体课程大家可以观看STM32官方录制的课程&#xff0c;链接&#xff1a;1.2. 课程架构介绍&#xff1a;STM32H5…

闪电网络协议设计思想剖析

1. 引言 闪电网络可能是比特币之上部署的最受期待的技术创新。闪电网络&#xff0c;为由 Joseph Poon 和 Tadge Dryja 于2015年首次提出的支付层&#xff0c;承诺支持&#xff1a; 用户之间几乎无限数量的链下交易&#xff0c;几乎免费&#xff0c;同时利用比特币提供的安全性…

IDEA编译安卓源码TVBox(2)

一、项目结构&#xff1a;主要app和player app结构 二、增加遥控器按键选台 修改LivePlayActivity.java 1、声明变量 public String channelId "";public Timer timer new Timer();public Toast mToast;2、定义方法 private void mToastShow(String s){mToast …

微信小程序-webview分享

项目背景 最近有个讨论区项目需要补充分享功能&#xff0c;希望可以支持在微信小程序进行分享&#xff0c;讨论区是基于react的h5项目&#xff0c;在小程序中是使用we-view进行承载的 可行性 目标是在打开web-view的页面进行分享&#xff0c;那就需要涉及h5和小程序的通讯问…

Unity类银河恶魔城学习记录10-10 p98 UI health bar源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili HealthBar_UI.cs using System.Collections; using System.Collections.G…

计算机毕业设计-基于大数据技术下的高校舆情监测与分析

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、研究背景与意义1.1背景与意义1.2 研究内容 二、舆情监测与分析的关键技术2.1 robot协议对本设计的影响2.2 爬虫2.2.1 工作原理2.2.2 工作流程2.2.3 抓取策略2.3 scrapy架构2.3.1 scrapy&#xff1a;开源爬虫架…

专业无网设备如何远程运维?向日葵远程控制能源场景案例解析

清洁能源领域&#xff0c;拥有庞大的上下游产业链&#xff0c;涉及的相关工业设备门类多、技术覆盖全、行业应用广。在这一领域内&#xff0c;相关专业设备的供应商的核心竞争力除了本身产品的技术能力之外&#xff0c;服务也是重要的一环。 某企业作为致力于节能环保方向的气…

由浅到深认识C语言(7)

该文章Github地址&#xff1a;https://github.com/AntonyCheng/c-notes 在此介绍一下作者开源的SpringBoot项目初始化模板&#xff08;Github仓库地址&#xff1a;https://github.com/AntonyCheng/spring-boot-init-template & CSDN文章地址&#xff1a;https://blog.csdn…

云仓酒庄东莞分公司2024年日常沙龙:葡萄酒文化与品鉴之旅

原标题&#xff1a;云仓酒庄东莞分公司日常沙龙&#xff1a;葡萄酒文化与品鉴之旅&#xff0c;招商新机遇共融 在东莞这座充满活力的城市&#xff0c;云仓酒庄分公司近日举办了一场别开生面的日常沙龙活动。此次活动以葡萄酒文化与品鉴为主题&#xff0c;旨在让参与者深入体验…

Typecho CMS 反序列化漏洞(CVE-2018-18753)复现

1.环境搭建 项目地址&#xff1a;Release Typecho 1.0(14.10.10) typecho/typecho GitHub 安装&#xff1a; 创建数据库typecho create database typecho; 再进入安装程序&#xff0c;输入数据库密码&#xff0c;设置登录密码即可 直接使用即可 2.漏洞分析 install.php文…

[善用佳软]推荐掌握小工具:Json解析的命令行工具jq

前言&#xff1a; 我们在各种生产环境或者开发测试环境中&#xff0c;一定遇到有很多信息都是使用JSON串或者文本文件作为输入的。在没有JQ命令行工具之前&#xff0c;我们要从中获取真正的输入&#xff0c;大都把它复制到文本里头&#xff0c;然后使用文本编辑器进行加工整理…

PytorchAPI的使用及在GPU的使用和优化

API 调用API&#xff1a;和手动实现的思路是一样的。#1&#xff0c;#2这两个步骤是通用的步骤&#xff0c;相当于建立一个模型&#xff0c;之后你具体的数据直接丢进去就行了。只需要按着这样的样式打代码就行&#xff0c;死的东西&#xff0c;不需要你自己创造。 import torc…

【博士每天一篇文献-综述】Communication dynamics in complex brain networks

阅读时间&#xff1a;2023-11-30 1 介绍 年份&#xff1a;2018 作者&#xff1a;Andrea Avena-Koenigsberger&#xff0c;印第安纳大学心理与脑科学系&#xff1b;Bratislav Misic 蒙特利尔神经学研究所&#xff0c;麦吉尔大学 期刊&#xff1a; Nature reviews neuroscience…

【Linux进阶之路】HTTPS = HTTP + S

文章目录 一、概念铺垫1.Session ID2.明文与密文3.公钥与私钥4.HTTPS结构 二、加密方式1. 对称加密2.非对称加密3.CA证书 总结尾序 一、概念铺垫 1.Session ID Session ID&#xff0c;即会话ID&#xff0c;用于标识客户端与服务端的唯一特定会话的标识符。会话&#xff0c;即客…

基于DataX迁移MySQL到OceanBase集群

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…