当前位置: 首页 > news >正文

爬虫逆向之瑞数6案例(深圳大学某某附属医院)

本文章中所有内容仅供学习交流使用,不用于其他任何目的。否则由此产生的一切后果均与作者无关!

目标网站:aHR0cHM6Ly9zY2guc3p1LmVkdS5jbi9obnl5Y21zd2ViL2Fubm91bmNlbWVudC9wcmUtcHVyY2hhc2UtcmVzZWFyY2g=

解决的问题

请求体加密:

响应加密:

cookie加密:

1.cookies加密

瑞数6cookie加密

第一步,清空cookie

第二步,开启脚本断点,刷新

加载第一个脚本是我们需要的

第二个脚本也是我们需要扣的

搜索.call,打上断点,如果call被混淆了,就hook cookie跟栈这是生成VM文件的地方

如果脚本没加载首页面。。就手动进入

如图所示,替换文件。网页上页面先固定死。因为会动态变化,方便调试。

所以瑞数6就扣两个文件,然后用吐环境脚本。联调补环境

function get_enviroment(proxy_array) {for (var i = 0; i < proxy_array.length; i++) {handler = '{\n' +'    get: function(target, property, receiver) {\n' +'        console.log("方法:", "get  ", "对象:", ' +'"' + proxy_array[i] + '" ,' +'"  属性:", property, ' +'"  属性类型:", ' + 'typeof property, ' +// '"  属性值:", ' + 'target[property], ' +'"  属性值类型:", typeof target[property]);\n' +// 'if (typeof target[property] == "undefined"){debugger}' +'        return target[property];\n' +'    },\n' +'    set: function(target, property, value, receiver) {\n' +'        console.log("方法:", "set  ", "对象:", ' +'"' + proxy_array[i] + '" ,' +'"  属性:", property, ' +'"  属性类型:", ' + 'typeof property, ' +// '"  属性值:", ' + 'target[property], ' +'"  属性值类型:", typeof target[property]);\n' +'        return Reflect.set(...arguments);\n' +'    }\n' +'}'eval('try{\n' + proxy_array[i] + ';\n'+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}catch (e) {\n' + proxy_array[i] + '={};\n'+ proxy_array[i] + '=new Proxy(' + proxy_array[i] + ', ' + handler + ')}')}
}proxy_array = ['window', 'document', 'location', 'navigator', 'history', 'screen', 'div', 'script']get_enviroment(proxy_array)

补到一般陷入死循环

第一个技巧

往这里打上debugger

node --inspect-brk xxx.js

输入命令行

点击浏览器

即进入联调页面,最好把异常断点打上

断住了

往端口看去,就能清晰看到环境缺失

环境补上

补标签则补对象,标签为对象

如果你不知道找不到哪里,直接联调

打上断点,看看i返回什么,联调。在同网页对比

网页搜这个地方

第二个技巧

调试的时候,会有很多个debugger

要么替换文件过debugger,把_$c9改为_$c9.replaceAll('debugger','')

要么注入代码

然后进入VM文件,VM文件为生成文件,只有VM文件生成时才能打断点,刷新后断点全消失。

i返回一个数组,补上

接下来优先补最后一个undefined,如果补上还运行不了,那就补往上一个undefined

像以上这种不知道可返回可不返回,直接打上debugger,同原网页对比。

补着补着卡住了

一般两种情况,第一种定时器,第二种,代码压缩检测

第三个技巧

清空定时器,并把代码压缩

压缩替换到node环境里,切记别用去掉debugger的文件,可能会有检测

接下来缺失script

其实就是这网页的两个标签,可以自己调试去看看

把script补完后顺利出值,这个值不一定对

测试一下,把ts文件改一下,cookie整理一下改一下

可能会检测这两个,在node环境最好加上这两个

整理

我擦,我边逆向边记录博客一次成功?,而且环境也不算多

一次成功纯属运气好,以下为全部环境

delete __dirname
delete __filenamewindow = global
window.top = global
window.setTimeout = function () {
}
window.setInterval = function () {
}
window.addEventListener = function (agrs){console.log('window->addEventListener->',agrs)
}
window.addEventListener = function (agrs){console.log('window->attachEvent->',agrs)
}
div = {getElementsByTagName: function (args) {console.log('div->getElementsByTagName->', args)if (args == 'i')return []}}
script = {getAttribute:function (args)
{console.log('script->getAttribute->',args)
}}
document = {}
location = {"ancestorOrigins": {},"href": "https://sch.szu.edu.cn/hnyycmsweb/announcement/bidding-information/win-bid-publicity","origin": "https://sch.szu.edu.cn","protocol": "https:","host": "sch.szu.edu.cn","hostname": "sch.szu.edu.cn","port": "","pathname": "/hnyycmsweb/announcement/bidding-information/win-bid-publicity","search": "","hash": ""
}
document.createElement = function (args) {console.log('document->createElement->', args)if (args == 'div') {return div}}
document.appendChild = function (args) {console.log('document->appendChild->', args)
}
document.getElementById = function (args) {console.log('document->getElementById->', args)
}
document.removeChild = function (args) {console.log('document->removeChild->', args)
}
document.addEventListener = function (args) {console.log('document->addEventListener->', args)
}
document.addEventListener = function (args) {console.log('document->addEventListener->', args)
}
document.getElementsByTagName = function (args) {console.log('document->getElementsByTagName->', args)if (args == 'base') {return []}if (args == 'script'){return [script,script]}
}
navigator = {}
navigator.userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36'

第四个技巧

事实上如果是假cookie则先补返回的标签,如果还不行,往这里打debugger

联调对比原网页,是undefined补undefined,不是undefined则和则网页一致

2.请求体参数分析和响应数据解密

事实上有些人在调试代码时,过debugger

第五个技巧

把瑞数的debugger过完,然后翻页想调试。就报这个错误

结果翻不了页,调试不了

这是因为瑞数会在代码中插入 时间差检测执行流完整性校验

如果你在某一行暂停太久(比如你在 debugger 里一步一步走),它会检测到“执行时间异常”;然后触发 自毁逻辑,比如:

故意抛出异常;修改关键变量;让后续解密流程失败,导致页面渲染不出来。

直接VM文件匿名脚本忽略掉

就会出现这个东西

切记,用于瑞数cookie调试时,不能忽略,不然调试不了,直接跳过VM的调试。

这时候直接XHR调试,异步之前,直接扣代码即可

加密方式很容易,包括响应内容的解密。AES加解密,用原生库即可

var CryptoJS = require('crypto-js')
class aY {constructor() {var e = [];this.add = t,this.find = i,this.remove = r,this.count = s,this.showAll = o,this.clear = a,this.sort = l;function t(c, u) {e[c] = u}function i(c) {return e[c]}function r(c) {if (e[c])delete e[c];elsereturn "Not Found"}function s() {var c = 0;for (var u in e)++c;return c}function o() {for (var c in e)console.log(c + "->" + e[c])}function a() {for (var c in e)delete e[c]}function l() {for (var c = new Array, u = Object.keys(e).sort(), d = 0; d < u.length; d++)c.push(u[d] + "=" + e[u[d]]);return c.join("&")}}
}
t = {"pageTag": "MenuId_17","pageNum": 4,"pageSize": 15,"timeReversal": true
}cY = () => {for (var n = [], e = "0123456789abcdef", t = 0; t < 36; t++)n[t] = e.substr(Math.floor(Math.random() * 16), 1);n[14] = "4",n[19] = e.substr(n[19] & 3 | 8, 1),n[8] = n[13] = n[18] = n[23] = "-";var i = n.join("");return i
}
function get(n, e) {var t =null;return t != null && t != "undefined" ? JSON.parse(t) : e}function QK(n, e) {let t = CryptoJS.enc.Utf8.parse(e), i = CryptoJS.enc.Utf8.parse(n), s = CryptoJS.AES.encrypt(i, t, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}).ciphertext.toString().toUpperCase(), o = CryptoJS.enc.Hex.parse(s);return CryptoJS.enc.Base64.stringify(o)
}
const lY = (n, e, t, i, r) => {var s = new aY;s.add("appId", n),s.add("appKey", e),s.add("timestamp", t),s.add("once", i),s.add("data", r);var o = CryptoJS.MD5(s.sort());return o.toString().toUpperCase()
}
function fY(n,e) {const t = new Date().getTime(), i = cY(), r = get('zyy_physical_secretkey', '76D96C41A4178B49'), s = {};return s.once = i,s.appId = '5DB62454F1FA2422DD7BA9DAD8855F6D',s.timestamp = t,s.data = QK(JSON.stringify(e), "76D96C41A4178B49"),s.sign = lY("5DB62454F1FA2422DD7BA9DAD8855F6D", "55F5DB6D7BA942DDAD882454F1FA26D2", t, i, JSON.stringify(e)),s
}
// '3uMu5nQrVbQnXzKAaeUV4AaHpa9FZGV5xB3M0k/K7CEogH8cuLi6jfZILChGltuueW+/RVDyyCrobxtyplVwvS7EH4LXbgiggoPubqAIviw='
// JPNIgdKUQxmqFW50uESIsB9RerDC1hINtBVdxaymXEA=
function eY(n) {e = '76D96C41A4178B49'let t = CryptoJS.enc.Utf8.parse(e);return CryptoJS.AES.decrypt(n, t, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7}).toString(CryptoJS.enc.Utf8).toString()
}

干掉瑞数后,剩下的加解密就非常简单了,

顺利出数据

作者有感:

其实瑞数做习惯了,基本有些东西都不用调试就知道了,

一开始,补window,top,清空定时器,压缩代码

一看到i就补数组,一看script就补两个对象的数组。

一看到base也补数组 navigator必补,包括它的属性,还有.....

瑞数没有原型链检测,相对好补,跟打螺丝没什么区别。

都说瑞数是爬虫逆向的一座大山,等翻过瑞数这座大山后,才发现瑞数只是众多山峰中的一座小峰,逆向真正的挑战远不止于此。像安全产品阿里滑块,极验,易盾等众多验证码轨迹生成更考虑行为像不像人,而不是所谓的加密。甚至有些奇奇怪怪的验证码要自己去训练。。。更有行为验,不是看你“能不能跑”,而是看你“跑得像不像人”。鼠标轨迹、键盘节奏、滚动速度、点击热区、停留时间……一点点偏差就触发风控。一句话,道路还长。


文章转载自:

http://8FepjLqE.dwzwm.cn
http://94C8Oy8T.dwzwm.cn
http://l5BRtKQ9.dwzwm.cn
http://Zzti2UyK.dwzwm.cn
http://VfPnlKGz.dwzwm.cn
http://lNYdH5GQ.dwzwm.cn
http://2xosNr4O.dwzwm.cn
http://E6APeStZ.dwzwm.cn
http://fuqWUXZ4.dwzwm.cn
http://1AepmRpk.dwzwm.cn
http://p4Uphnyr.dwzwm.cn
http://Hm29CiXN.dwzwm.cn
http://4ihG5LVN.dwzwm.cn
http://zJHjROJG.dwzwm.cn
http://Xwa88SO5.dwzwm.cn
http://CtQ5EJ2q.dwzwm.cn
http://LxIj3Fkh.dwzwm.cn
http://P0ZlcqQN.dwzwm.cn
http://wTEmtR07.dwzwm.cn
http://t4iueQBe.dwzwm.cn
http://05zIyE57.dwzwm.cn
http://gCyx1k2f.dwzwm.cn
http://2hC5aGro.dwzwm.cn
http://hBndOClP.dwzwm.cn
http://BV1GUbNZ.dwzwm.cn
http://t5QlD720.dwzwm.cn
http://PZAcZtyG.dwzwm.cn
http://lzfDztQE.dwzwm.cn
http://d4Bb0PlA.dwzwm.cn
http://Zqfa7lDg.dwzwm.cn
http://www.dtcms.com/a/376996.html

相关文章:

  • AWK工具使用与技巧指南
  • Java程序员职业发展路径与转型选择分析报告(2025年)
  • 资产管理软件哪家口碑好
  • 【实战中提升自己完结篇】分支篇之分支之无线、内网安全与QOS部署(完结)
  • 【Qt】PyQt、原生QT、PySide6三者的多方面比较
  • 多级缓存架构
  • 多模态对齐与多模态融合
  • 【MySQL】常用SQL语句
  • 教师节组诗-我不少年师已老,无报师恩仅遥忆
  • 手把手带你推导“逻辑回归”核心公式
  • 当按摩机器人“活了”:Deepoc具身智能如何重新定义人机交互体验
  • solidity得高级语法3
  • PLM 与机器视觉协同:三维模型驱动自动光学检测标准制定
  • vuecli中使用splitchunksplugin提取公共组件,vue单组件使用less scoped处理style,打包会有css顺序冲突警告
  • 元宇宙与旅游产业:沉浸式体验重构旅行全流程
  • 城市道路落叶清扫机设计【三维SW模型】【含9张CAD
  • apache poi 导出复杂的excel表格
  • 海外盲盒APP开发:如何用技术重构“惊喜经济”
  • Linux快速安装JDK1.8
  • 高可用消息队列线程池设计与实现:从源码解析到最佳实践
  • 使用nvm管理node多版本(安装、卸载nvm,配置环境变量,更换npm淘宝镜像)
  • Python 0909
  • 二进制安装MySQL 8.0指南:跨平台、自定义数据路径、安全远程访问配置
  • MySQL - 全表扫描 会发生死锁?
  • 0代码,教你三步搭建AI Agent
  • Flask 前后端分离架构实现支付宝电脑网站支付功能
  • Next.js 客户端渲染 (CSR) 与 Next.js 的结合使用
  • GitHub 镜像站点
  • S7-200 SMART 实战:自动包装控制系统的指令应用拆解(程序部分)
  • 从音频到Token:构建原神角色语音识别模型的完整实践