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

JS逆向之瑞数6案例(某某大学华南附属医院)

目录

解决的问题

1.cookies加密

第一个技巧

第二个技巧

第三个技巧

第四个技巧

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

第五个技巧


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

目标网站: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 __filename window = 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则和网页一致

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

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

第五个技巧

把瑞数的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]; else return "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://www.jsqmd.com/news/953267/

相关文章:

  • 2026年6月北京宣传片拍摄公司推荐:五大榜单专业评测案例性价比高选择指南 - 品牌推荐
  • 纯内容驱动的电影推荐系统:零用户行为,全靠TF-IDF与余弦相似度
  • LongCat-Flash-Chat-FP8架构设计哲学:美团大模型的技术创新
  • GewisLab/CNEnvAir源成分谱应用:PMF/CMB模型数据准备指南
  • Python自动化抢票技术深度解析:大麦网秒杀系统架构设计与实现原理
  • Medium数据科学内容筛选指南:出版物与标签的工程化鉴别法
  • CANN/asc-devkit同步控制函数
  • 从仿真误差到精准结果:深入解读FDTD中Q值计算的两种核心算法(低Q腔 vs 高Q腔)
  • 生产级多维聚合:从Pandas groupby到可审计可扩展的分析基建
  • Windows终极优化神器:WinUtil完整指南 - 一键解决系统卡顿与软件安装烦恼
  • 2025-2026年北京宣传片拍摄公司推荐:五大口碑评测专业案例与适用场景 - 品牌推荐
  • MusicFree插件终极指南:5分钟打造你的专属音乐宇宙
  • ShaderGraph避坑指南:从代码Shader转视觉化编程,我踩过的那些‘节点’坑
  • 如何快速实现AI设计转代码:Figma-Context-MCP完整使用教程
  • use-mcp:React开发者的终极MCP连接解决方案
  • CANN/asc-devkit: Reg矢量存储对齐接口
  • 避坑指南:QT调用周立功CAN库(zlgcan.dll)时,设备初始化、波特率设置的那些常见错误与排查方法
  • 音频可视化神器Sonic Visualiser:从零开始的音乐分析完整指南
  • AI提示驱动三维建模:用自然语言生成可打印OpenSCAD代码
  • 博尚机械树枝粉碎机:全型号参数表,支持按需定制,全国3-7天发货! - 会飞的懒猪
  • STM32F407双CAN触发式IAP升级工程:含FreeRTOS多任务APP与独立IAP引导程序
  • PDMS管道设计效率翻倍:手把手教你安装NakiPipeline插件(附常见错误排查)
  • 【Java基础知识 2】开发环境配置及idea的下载配置
  • 从理论到实践:welcome_tutorials神经网络库使用完全指南 [特殊字符]
  • 别再对着官方文档发愁了!手把手教你用Java解密抖音用户手机号(附完整代码)
  • Linux用户必看!3步创建Umi-OCR桌面快捷方式,告别繁琐命令行
  • 2026年6月钢格板厂家推荐:五大专业评测工程荷载防变形性价比高价格 - 品牌推荐
  • 深入ZYNQ7000的PL中断:手把手配置AXI GPIO中断,并解决IRQ_F2P只能高电平/上升沿触发的问题
  • DeepSeek-R1实战避坑指南:MoE架构、Tokenizer与Agent工程陷阱
  • STM32F103裸机移植CanFestival-3全记录:从源码下载到心跳包测试(附对象字典生成工具避坑)