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

【困难】 猿人学web第一届 第18题 jsvmp 洞察先机

文章目录

  • 数据接口分析
  • 还原加密参数
  • 插桩调试
  • 分析日志
    • 插桩补充
  • python 代码

数据接口分析

数据接口 https://match.yuanrenxue.cn/match/18data
在这里插入图片描述

请求参数
{page: 页码, t: 时间戳, v: 加密值}在这里插入图片描述
请求第一页不需要携带 t, v 参数
在这里插入图片描述

cookie
只需要携带 sessionid
在这里插入图片描述

只要 还原加密字段 v

还原加密参数

查看数据接口对应的 request 栈
在这里插入图片描述
下断点,点击页码请求数据,会在对应的位置断住
在这里插入图片描述
断住后单步执行到, xml.open 方法是被重写过的,跟进去
在这里插入图片描述
代码是压缩成一行的
拿到本地格式化再折叠
可以很明显的看到是一个自执行函数
这个自执行函数传入的参数就是这个 vmp 对应的指令
在这里插入图片描述

继续跟栈,可以找到这个 vmp 对应的解释器
在这里插入图片描述
将断点放到最后一行
在这里插入图片描述
单步进去,这个函数就是对应的解释器
在这里插入图片描述

解决 vmp 最有效的办法就是插桩看日志,根据日志的信息 进行合理的猜测 / 还原

插桩调试

插桩应该插在:
运行了方法,同时使用变量接收的位置 xxx = xxx(xxx, xxx) 或 xxx.apply(xxx, [xxx])
又或者是 return 语句后面 进行了计算操作 xxx1 + xxx2 (运算操作)

在这个解释器有很多符合这两个特征的地方
这里只插关键的位置

搜索 27 == __U
这个 return语句后进行了运算操作在这里插入图片描述
这里是三元表达式,如果想知道进行了什么运算操作的花可以将这里的 三元表达式还原成 if
插入条件断点
在这里插入图片描述
这里的代码是用 ast 还原后再重新生成的 (ast 真方便 /dog)
对应的代码 ↓

if(33==(v_=vv_)){console.log(27,"V_ instanceof y_;",V_,y_,V_ instanceof y_)V_ instanceof y_;}else{if(23==v_){console.log(27,"V_ in y_;",V_,y_,V_ in y_)V_ in y_;}else{if(19==v_){console.log(27,"V_ + y_;",V_,y_,V_+y_)V_+y_;}else{if(46==v_){console.log(27,"V_ - y_;",V_,y_,V_-y_)V_-y_;}else{if(14==v_){console.log(27,"V_ / y_;",V_,y_,V_/y_)V_/y_;}else{if(31==v_){console.log(27,"V_ * y_;",V_,y_,V_*y_)V_*y_;}else{if(32==v_){console.log(27,"_y_(V_, y_);",V_,y_,_y_(V_,y_))_y_(V_,y_);}else{if(27==v_){console.log(27,"V_ % y_;",V_,y_,V_%y_)V_%y_;}else{if(25==v_){console.log(27,"V_ < y_;",V_,y_,V_<y_)V_<y_;}else{if(2==v_){console.log(27,"V_ <= y_;",V_,y_,V_<=y_)V_<=y_;}else{if(16==v_){console.log(27,"V_ > y_;",V_,y_,V_>y_)V_>y_;}else{if(42==v_){console.log(27,"V_ >= y_;",V_,y_,V_>=y_)V_>=y_;}else{if(40==v_){console.log(27,"V_ & y_;",V_,y_,V_&y_)V_&y_;}else{if(39==v_){console.log(27,"V_ != y_;",V_,y_,V_!=y_)V_!=y_;}else{if(21==v_){console.log(27,"V_ !== y_;",V_,y_,V_!==y_)V_!==y_;}else{if(47==v_){console.log(27,"V_ | y_;",V_,y_,V_|y_)V_|y_;}else{if(50==v_){console.log(27,"V_ ^ y_;",V_,y_,V_^y_)V_^y_;}else{if(26==v_){console.log(27,"V_ == y_;",V_,y_,V_==y_)V_==y_;}else{if(37==v_){console.log(27,"V_ === y_;",V_,y_,V_===y_)V_===y_;}else{if(8==v_){console.log(27,"V_ << y_;",V_,y_,V_<<y_)V_<<y_;}else{if(18==v_){console.log(27,"V_ >> y_;",V_,y_,V_>>y_)V_>>y_;}else{if(1==v_){console.log(27,"V_ >>> y_;",V_,y_,V_>>>y_)V_>>>y_;}else{console.log(27,"void 0;",V_,y_,void 0)void 0;}}}}}}}}}}}}}}}}}}}}}};false

搜索 48 == __U
这个 return 语句后面执行了 apply 方法在这里插入图片描述
插入条件断点
在这里插入图片描述
对应的代码 ↓

if(__V(_, ___(u_), 0, 0, _u__).name){console.log(48, __V(_, ___(u_), 0, 0, _u__).name, 'apply', y__(____));
}else{console.log(48, 'function(){}', 'apply', y__(____));
};false

搜索 32 == __U
这个 return 语句后面执行了 apply 方法在这里插入图片描述
插入条件断点
在这里插入图片描述
对应的代码↓

if(yU_ instanceof Function){console.log(32, yU_.name, yU_[_v].name, ...__)
}else{console.log(32, yU_, yU_[_v].name, ...__)
};false

其实还少了两个地方的桩没有插,后面有补充,最好补上
在 目录 日志分析下的 插桩补充目录,点击跳转过去即可

分析日志

插好桩以后,点击页码进行请求 会生成对应的日志(第1, 5页不会进行加密)
生成日志后,将日志保存到本地在这里插入图片描述
在出现密文后的日志全部删除,不需要分析在这里插入图片描述
这里就是生成的密文,和请求字段的密文是一致在这里插入图片描述在这里插入图片描述

替换掉无意义的内容
在这里插入图片描述
在这里插入图片描述

从头开始分析(这里只分析关键信息)

这一段指令集的目的是生成 鼠标轨迹数组
在页面一直滑动会一直生成这几段日志
在这里插入图片描述
910为鼠标在页面上 x 轴的位置
226 为鼠标在页面上 y 轴的位置
滑动鼠标,那么两个坐标的值会与 m 相加 (move)
按下鼠标左键,那么两个坐标的值会与 d 相加 (down)
抬起鼠标左键,那么两个坐标的值会与 u 相加 (up)
在对应数组的后面执行了 shift 方法
那么这个数组的值就为
[‘912m226’, ‘911m226’, ‘910m226’, ‘910d226’, ‘910u226’]

这段指令是判断你是否点击了第一页或第五页(第一页和第五页不执行后续的加密逻辑)
在这里插入图片描述
其实…这个和还原加密没有关系 /dog(不皮了,后面只分析和加密相关的日志)

执行了 Date.now()方法获取 时间戳
将这个 时间戳 除以 1000
使用 parseInt 将这个时间戳转化为 整数
生成了 t 参数(请求参数的 t 字段)
在这里插入图片描述

使用 toString(16) 将这个数值转化为 十六进制字符串(‘66d9f991’)
将获取的十六进制字符串再相加(‘66d9f991’ + ‘66d9f991’)
使用 slice 方法取索引为 从 0 开始,从 16 结束的字符(‘66d9f99166d9f991’.slice(0,16))
结果为 ‘66d9f99166d9f991’
在这里插入图片描述
验证
在这里插入图片描述

获取页码与 “|” 相加 (2 + “|”)
获取了轨迹数组并转化为字符串 ([…].toString())
将前面的操作得到的结果再一起相加 (2 + “|” + […].toString())
‘2|912m226,911m226,910m226,910d226,910u226’
在这里插入图片描述

这两个操作分别将上面生成的两个参数进行了解码,是接下来用于加密用的在这里插入图片描述在这里插入图片描述
对应 nodejs 的操作
Crypto.enc.Latin1.parse(‘66d9f99166d9f991’)
Crypto.enc.Latin1.parse(‘2|912m226,911m226,910m226,910d226,910u226’)

全局搜索 encrpyt
查看搜索到的第一个 encrypt
在这里插入图片描述
加密方式是 AES 加密,加密时需要传入 密文,密钥,iv向量
对应着传入的 3 个参数,可以看打印 32 日志的输出方式在这里插入图片描述

先来查看密文
是 Crypto.enc.Latin1.parse(‘2|912m226,911m226,910m226,910d226,910u226’) 的结果在这里插入图片描述
在这里插入图片描述

再来查看密钥
是 Crypto.enc.Latin1.parse(‘66d9f99166d9f991’) 的结果
在这里插入图片描述
在这里插入图片描述

iv 的值与密钥的值一致

接下来加密验证下结果是否一样
在这里插入图片描述

Crypto = require('crypto-js')
let text = Crypto.AES.encrypt(Crypto.enc.Latin1.parse('2|912m226,911m226,910m226,910d226,910u226'), Crypto.enc.Latin1.parse('66d9f99166d9f991'), {iv: Crypto.enc.Latin1.parse('66d9f99166d9f991'),  // iv 向量// 下面的参数可以填也可以不填,加密模式默认为 cbc, 填充方式默认为 pkcs7// mode: Crypto.mode.CBC, // 加密模式// padding: Crypto.pad.Pkcs7, // 填充方式
})
console.log(text.toString())

得到的结果与浏览器的一致
在这里插入图片描述
在这里插入图片描述

插桩补充

插桩的点其实有问题,比如为什么我知道是 AES 加密,为什么我知道哪个是 key,哪个是 iv
其实少插了两处桩

全局搜索 18 == _U
插入日志点
18, v_
, V__在这里插入图片描述
对应的日志在这里插入图片描述
这就是我为什么知道 密文,密钥 和 iv 的原因

还有一处地方插桩后是可以看得到 字符串 AES 的,但是我忘记在哪里了,这也是我为什么是 AES 加密 Latin1解码的原因,感兴趣的可以自己插桩找找

分析验证完之后 就可以编写 python 代码

python 代码

首先获取 2,3,4,5 页对应的鼠标轨迹数组,将最后两个参数中的 m 替换成 d 和 u 即可
第2页:[‘905m206’, ‘905m207’, ‘905m208’, ‘905d209’, ‘905u211’]
第3页:[‘950m203’, ‘950m204’, ‘950m206’, ‘950d208’, ‘950u210’]
第4页:[‘1004m209’, ‘1004m208’, ‘1004m207’, ‘1004d208’, ‘1004u209’]
第5页:[‘1052m197’, ‘1052m199’, ‘1052m200’, ‘1051d201’, ‘1051u203’]

js代码

Crypto = require('crypto-js')
function sdk(page){let slideArr;switch (page){case 2:slideArr = ['905m206', '905m207', '905m208', '905d209', '905u211']break;case 3:slideArr = ['950m203', '950m204', '950m206', '950d208', '950u210']break;case 4:slideArr = ['1004m209', '1004m208', '1004m207', '1004d208', '1004u209']break;case 5:slideArr = ['1052m197', '1052m199', '1052m200', '1051d201', '1051u203']break;}let encryptStr = Crypto.enc.Latin1.parse(page + "|" + slideArr.toString())let timeStrap = parseInt(Date.now() / 1000)let key_iv = Crypto.enc.Latin1.parse(timeStrap.toString(16) + timeStrap.toString(16));let v = Crypto.AES.encrypt(encryptStr, key_iv, {iv: key_iv,mode: Crypto.mode.CBC, // 加密模式padding: Crypto.pad.Pkcs7, // 填充方式}).toString()return {'page': page,'t': timeStrap,'v': v}
}

python 代码

import timeimport requests
import execjsheaders = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
}
cookies = {"sessionid": "你的sessionId",
}def call_js(file_name, func_name, *args):with open(file_name, mode='r', encoding='utf-8') as f:js_code = execjs.compile(f.read())return js_code.call(func_name, *args)def get_match18(page_):url = "https://match.yuanrenxue.cn/match/18data"params = {}if page_ > 1:params = call_js('18.js', 'sdk', page_)else:params['page'] = page_response = requests.get(url, headers=headers, cookies=cookies, params=params)print(response.json()['data'])return response.json()['data']if __name__ == '__main__':nums = 0for page in range(1, 6):nums_list = get_match18(page)for num in nums_list:nums += num['value']print('page: ', page, 'nums: ', nums)

相关文章:

【困难】 猿人学web第一届 第18题 jsvmp 洞察先机

文章目录 数据接口分析还原加密参数插桩调试分析日志插桩补充 python 代码 数据接口分析 数据接口 https://match.yuanrenxue.cn/match/18data 请求参数 {page: 页码, t: 时间戳, v: 加密值} 请求第一页不需要携带 t, v 参数 cookie 只需要携带 sessionid 只要 还原加密字段…...

IDEA Maven 源修改为国内阿里云镜像的正确方式

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…...

OpenCV 旋转矩形边界

边界矩形是用最小面积绘制的&#xff0c;所以它也考虑了旋转。使用的函数是**cv.minAreaRect**()。 import cv2 import numpy as npimgcv2.imread(rD:\PythonProject\thunder.jpg) img1cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) print(img.dtype) ret,threshcv2.threshold(img1,1…...

人车防撞系统安全生产方案

根据《市场监管总局关于2021~2023年全国特种设备安全状况的通告》数据显示&#xff1a;2023年&#xff1a;全国共发生特种设备事故和相关事故71起&#xff0c;其中死亡69人。包含叉车在内的场(厂)内专用机动车辆事故29起、死亡28人&#xff0c;占事故总数的40.85%、死亡人数的4…...

开放式耳机哪个牌子好?长文传授6招秘籍,彻底远离坑货!

​大家好&#xff0c;作为一位专注于评测各类数码产品的博主&#xff0c;今天我特别推荐开放式耳机作为我们日常的首选。这种耳机以其独特的设计&#xff0c;避免了传统耳机长时间佩戴可能带来的不适和感染风险。开放式耳机佩戴简便且稳固&#xff0c;尤其适合热爱跑步和运动的…...

vue2和vue3双向绑定的原理

Vue.js 的双向绑定是 Vue 框架的核心特性之一&#xff0c;它允许数据和视图之间保持同步。虽然 Vue 2 和 Vue 3 都实现了双向绑定&#xff0c;但它们在实现细节上有所不同。 Vue 2 双向绑定的原理 在 Vue 2 中&#xff0c;双向绑定主要依赖于 Object.defineProperty 和观察者…...

别为大文件烦恼!mp4文件太大怎么变小?3个管用方法

你是否曾经遇到过mp4视频文件过大的困扰&#xff1f;每当想要分享或存储mp4文件时&#xff0c;巨大的文件就成了阻碍。明明感觉感觉没占用多少空间&#xff0c;但是设备却常常出现空间过满警告。 没多少空间的设备真是让人大为恼火&#xff0c;没人想多花一份钱买设备。那么只…...

cocotb的接收和发送逻辑,还是没有弄明白

发送有两种方式 1、定义这样的发 通过前缀连接DUT里面的信号 发送的时候&#xff0c;通过.去访问就可以 2、如果是AXI总线&#xff0c;可以直接调用cocotb的库文件 AXIS总线可以包含以下的信号 通过这个类&#xff0c;可以产生一个AXIS的一帧数据 类的实现大概如下 然后也…...

XXL-JOB调度中心与执行器

XXL-JOB是一个轻量级的分布式任务调度平台&#xff0c;主要由调度中心和执行器两部分组成。下面详细讲解调度中心与执行器的功能和作用。 调度中心 调度中心是XXL-JOB的核心组件&#xff0c;负责任务的调度管理。其主要功能包括&#xff1a; 任务管理&#xff1a;调度中心提供…...

Notepad++ 8.6.9 (代码编辑) 绿色版

Notepad编辑器是一款非常流行的编辑软件&#xff0c;对于技术白菜来说&#xff0c;有这么个神器真是方便多了&#xff0c;Notepad界面简洁明了&#xff0c;而且可以定制界面&#xff0c;又支持多国语言&#xff0c;是站长们的得力助手。免费、开源、绿色&#xff0c;对中文支持…...

【例003】利用MATLAB绘制有趣平面图形

题目&#xff1a; 用 ezplot 画出由方程 sin ⁡ ( x 2 m y 2 1000 ) cos ⁡ ( x y ) \sin(x^2\frac{my^2}{1000})\cos(xy) sin(x21000my2​)cos(xy) 确定隐函数的图形。 求解&#xff1a; 我们分别取m为100&#xff0c;1000,10000不同的值&#xff0c;绘制不同情况下的图…...

Ignis公链探索生态建设新范式:产业区块链与GameFi双轨驱动

Ignis公链凭借其独特的技术架构&#xff0c;选择了产业区块链与GameFi这两个赛道作为生态建设的双轮驱动&#xff0c;逐步形成了一个多元化的Web3生态系统。 一、产业区块链的革新&#xff1a;Vessel Chain的成功案例 在产业区块链领域&#xff0c;Ignis公链通过推出Vessel Ch…...

河南测绘资质申请中的技术装备需求

技术装备要求概览 购置与测绘业务相适应的技术设备&#xff1a;需要购置与测绘业务相适应的技术设备&#xff0c;如全站仪、水准仪、GNSS接收机等。 需要建立技术装备清单&#xff0c;并确保这些设备处于良好的工作状态。 技术装备的精度要求&#xff1a;GNSS接收机、全站仪…...

如何使用C# 读写西门子PLC

在C# WPF应用程序中,与西门子S7系列PLC进行通信是一个常见的需求,尤其是在工业自动化领域。以下是三种实现WPF上位机与西门子S7系列PLC通信同步的方式,每种方式都提供了代码实例、优缺点和使用场景。 1. 使用S7.Net库 代码示例: // 创建PLC连接 var plc = new S7.Net.Pl…...

反向沙箱-安全上网解决方案

随着信息化的发展&#xff0c;企业日常办公越来越依赖互联网。终端以及普通PC终端在访问互联网过程中&#xff0c;会遇到各种各样不容忽视的风险&#xff0c;例如员工主动故意的数据泄漏&#xff0c;后台应用程序偷偷向外部发信息&#xff0c;木马间谍软件的外联&#xff0c;以…...

尚品汇-延迟插件实现订单超时取消(四十五)

目录&#xff1a; &#xff08;1&#xff09;延迟插件封装 &#xff08;2&#xff09;基于延迟插件测试 如何保证消息幂等性&#xff1f; &#xff08;3&#xff09;改造订单service-order模块-实现订单超时取消 &#xff08;1&#xff09;延迟插件封装 把消息带过去&#…...

欺诈文本分类检测(十一):LLamaFactory多卡微调

1. 引言 前文训练时都做了一定的编码工作&#xff0c;其实有一些框架可以支持我们零代码微调&#xff0c;LLama-Factory就是其中一个。这是一个专门针对大语言模型的微调和训练平台&#xff0c;有如下特性&#xff1a; 支持常见的模型种类&#xff1a;LLaMA、Mixtral-MoE、Qw…...

SprinBoot+Vue健康管管理微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…...

C++基础类容详解

目录 知识点1 C的概述 1 C的特征 2 C程序的编辑、编译和执行 3 第一个C源程序 4 面向对象程序设计思想 4.1 面向对象程序设计思想初始 4.2 面向对象程序设计思想的核心 知识点2 C对C的扩展 1 作用域访问运算符(::) 2 名称空间域 2.1 创建名称空间域 2.2 已有名称空间…...

python基础(16面试题附答案一)

python系列文章目录 python基础&#xff08;01变量&数据类型&运算符&#xff09; python基础&#xff08;02序列共性&#xff09; python基础(03列表和元组) python基础&#xff08;04字符串&字典&#xff09; python基础&#xff08;05集合set&#xff09; pytho…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

鸿蒙(HarmonyOS5)实现跳一跳小游戏

下面我将介绍如何使用鸿蒙的ArkUI框架&#xff0c;实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...

快速排序算法改进:随机快排-荷兰国旗划分详解

随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...

机器学习的数学基础:线性模型

线性模型 线性模型的基本形式为&#xff1a; f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法&#xff0c;得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...

李沐--动手学深度学习--GRU

1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...

Qt Quick Controls模块功能及架构

Qt Quick Controls是Qt Quick的一个附加模块&#xff0c;提供了一套用于构建完整用户界面的UI控件。在Qt 6.0中&#xff0c;这个模块经历了重大重构和改进。 一、主要功能和特点 1. 架构重构 完全重写了底层架构&#xff0c;与Qt Quick更紧密集成 移除了对Qt Widgets的依赖&…...