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

爬虫攻守道 - 猿人学第20题 - 殊途同归

写在开头

  • 这题也是,自己搞顶多追踪到wasm代码,然后就走不下去了。找了2个参考方案,自己做的过程中还又遇到些新的问题,下面做个记录。
  • 解法1参考文章
  • 解法2参考文章

解法1:追根溯源

  • 在 JS 代码中追踪到 Payload 赋值位置

  • 追踪 Sign 函数,调用的 wasm 代码。这里需要记录一下 var55 和 var56 的值

  • 回到 JS 代码,选中 getStringFromWasm0(r0, r1) 部分,可以看到最终的 sign 已经生成。此时在 console 端口中输入 getStringFromWasm0(1114192, 31) —— 1114192和31 是 var55 和 var56 的值,1个代表内存地址,1个代表偏移量,表示从这个地址取这个长度的字符 —— 可以看到后面加了1串固定的字符串,也就是传说中的 md5 的盐?

  •  到这里也就明白了,sign函数是以 页码,时间戳作为输入,然后加上了固定字符串(盐),拼接后做了 md5 加密。下面是Python 实现代码
# !/usr/bin/env python3
# _*_ coding:utf-8 _*_
"""
@File               : match_20_normal.py
@Project            : S044_YuanRenXue
@CreateTime         : 2023/4/15 18:00
@Author             : biaobro
@Software           : PyCharm
@Last Modify Time   : 2023/4/15 18:00 
@Version            : 1.0
@Description        : None
"""
from urllib.parse import urlencode
import hashlib
import requests
import time"""
关键的JS代码,得到Payload
t = Date.parse(new Date());
var list = {"page": window.page,"sign": window.sign(window.page + '|' + t.toString()),"t": t,
};
"""def get_sign(page, ts):sign = hashlib.md5((str(page) + "|" + str(ts) + 'D#uqGdcw41pWeNXm').encode()).hexdigest()return signall_total = 0
for page in range(1, 6):ts = int(time.time()) * 1000payload = {'page': page,'sign': get_sign(page, ts),'t': ts}url = "https://match.yuanrenxue.cn/api/match/20?" + urlencode(payload)print(url)headers = {'user-agent': 'yuanrenxue.project','cookie': 'sessionid=ntkvbzoagc6tpauaugwk3b0jdrdbuba9'}resp = requests.get(url, headers=headers)# print(resp.text)datas = resp.json()['data']print(datas)p_total = 0for data in datas:p_total = p_total + data['value']all_total = all_total + p_totalprint(all_total)

解法2:举重若轻

  • 这个解法不明白原理,但结合Git 作者给的 Demo 和 参考文章,还是照猫画虎搞出来了。Git 作者提供的代码,无法直接获取字典对象。参考文章提供的代码也需要稍微调整。
  • 这个解法需要准备2个东西,1个是在浏览器 Console 跑的JS代码,1个是 Git 作者提供的 Win Exe 程序。
    • 启动Exe 程序,建议在文件夹中右键选择“在终端中代开”,然后敲入 win64-localhost.exe 运行。
    • 打开浏览器找到第20题页面打开,在Console 端口中输入以下 JS 代码,然后回车
function Hlclient(wsURL) {this.wsURL = wsURL;this.handlers = {};this.socket = {};if (!wsURL) {throw new Error('wsURL can not be empty!!')}this.connect()this.handlers["_execjs"]=function (resolve,param){var res=eval(param)if (!res){resolve("没有返回值")}else{resolve(res)}}
}Hlclient.prototype.connect = function () {console.log('begin of connect to wsURL: ' + this.wsURL);var _this = this;try {this.socket["ySocket"] = new WebSocket(this.wsURL);this.socket["ySocket"].onmessage = function (e) {try{let blob=e.datablob.text().then(data =>{_this.handlerRequest(data);})}catch{console.log("not blob")_this.handlerRequest(blob)}}} catch (e) {console.log("connection failed,reconnect after 10s");setTimeout(function () {_this.connect()}, 10000)}this.socket["ySocket"].onclose = function () {console.log("connection failed,reconnect after 10s");setTimeout(function () {_this.connect()}, 10000)}};
Hlclient.prototype.send = function (msg) {this.socket["ySocket"].send(msg)
}Hlclient.prototype.regAction = function (func_name, func) {if (typeof func_name !== 'string') {throw new Error("an func_name must be string");}if (typeof func !== 'function') {throw new Error("must be function");}console.log("register func_name: " + func_name);this.handlers[func_name] = func;return true}//收到消息后这里处理,
Hlclient.prototype.handlerRequest = function (requestJson) {var _this = this;var result=JSON.parse(requestJson);//console.log(result)if (!result['action']) {this.sendResult('','need request param {action}');return}var action=result["action"]var theHandler = this.handlers[action];if (!theHandler){this.sendResult(action,'action not found');return}try {if (!result["param"]){theHandler(function (response) {_this.sendResult(action, response);})}else{var param=result["param"]try {param=JSON.parse(param)}catch (e){console.log("")}theHandler(function (response) {_this.sendResult(action, response);},param)}} catch (e) {console.log("error: " + e);_this.sendResult(action+e);}
}Hlclient.prototype.sendResult = function (action, response) {var responseJson;if (typeof response == 'string') {try {responseJson = JSON.parse(response);} catch (e) {responseJson = {};responseJson['data'] = response;}} else if (typeof response == 'object') {responseJson = response;} else {responseJson = {};responseJson['data'] = response;}if (Array.isArray(responseJson)) {responseJson = {data: responseJson,code: 0}}if (responseJson['code']) {responseJson['code'] = 0;} else if (responseJson['status']) {responseJson['status'] = 0;} else {responseJson['status'] = 0;}var responseText = JSON.stringify(responseJson);this.send(action + atob("aGxeX14") + responseText);
}// 上面是用于建立环境的源码
// 注入环境后连接通信
// var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz&name=hlg");// 连接通信
var client = new Hlclient("ws://127.0.0.1:12080/ws?group=match20&name=yuanrenxue");// demo_001
// 注册一个方法 第一个参数hello为方法名,
// 第二个参数为函数,resolve里面的值是想要的值(发送到服务器的)
client.regAction("hello1", function (resolve) {//这样每次调用就会返回“好困啊+随机整数”var Js_sjz = "好困啊"+parseInt(Math.random()*1000);resolve(Js_sjz);
})
// 访问接口,获得js端的返回值
// http://localhost:12080/go?group=zzz&name=hlg&action=hello// demo_002
//写一个传入字符串,返回base64值的接口(调用内置函数btoa)
client.regAction("hello2", function (resolve,param) {//这样添加了一个param参数,http接口带上它,这里就能获得var base666 = btoa(param)resolve(base666);
})// demo_003
//假设有一个函数 需要传递两个参数
function hlg(User,Status){return User+"说:"+Status;
}client.regAction("hello3", function (resolve,param) {//这里还是param参数 param里面的key 是先这里写,但到时候传接口就必须对应的上res=hlg(param["user"],param["status"])resolve(res);
})
// url = "http://localhost:12080/go"// 第二个参数为函数,resolve里面的值是想要的值(发送到服务器的)
// param是可传参参数,可以忽略
client.regAction("ShiGuang", function (resolve, param) {t = Date.parse(new Date());var list = {"page": String(param),"sign": window.sign(String(param) + '|' + t.toString()),"t": t,}resolve(list)
})
  • 准备好环境后,就可以写Python 代码进行请求了。以下是 Python 代码
# !/usr/bin/env python3
# _*_ coding:utf-8 _*_
"""
@File               : match_20_jsrpc.py
@Project            : S044_YuanRenXue
@CreateTime         : 2023/4/15 23:06
@Author             : biaobro
@Software           : PyCharm
@Last Modify Time   : 2023/4/15 23:06 
@Version            : 1.0
@Description        : None
"""
import ast
import requestsdef get_params(page):params = {"group": "match20","name": "yuanrenxue","action": "ShiGuang","param": str(page)}try:res = requests.post("http://localhost:12080/go", params=params)res = res.json()print(res)# 这个写法是把# '{"page":"1","sign":"df47c82c991462661cfc3642369039a3","t":1681818656000,"status":0}'# 转换成# {'page': '1', 'sign': 'df47c82c991462661cfc3642369039a3', 't': 1681818656000, 'status': 0}# 否则直接按json 或 字典方式是读不出来的params = ast.literal_eval(res.get("data"))print(params)return paramsexcept:return Falseget_params(1)
  • 运行结果。现在拿到了 sign,再获取页面上的数据就不是问题了。

 

相关文章:

爬虫攻守道 - 猿人学第20题 - 殊途同归

写在开头 这题也是,自己搞顶多追踪到wasm代码,然后就走不下去了。找了2个参考方案,自己做的过程中还又遇到些新的问题,下面做个记录。解法1参考文章解法2参考文章 解法1:追根溯源 在 JS 代码中追踪到 Payload 赋值位…...

4.11日报

synchronized 和 ReentrantLock 区别是什么? synchronized 早期的实现比较低效,对比 ReentrantLock,大多数场景性能都相差较大,但是在 Java 6 中对 synchronized 进行了非常多的改进。 主要区别如下: ReentrantLock …...

【LeetCode每日一题: 1039. 多边形三角剖分的最低得分 | 暴力递归=>记忆化搜索=>动态规划 | 区间dp 】

🍎作者简介:硕风和炜,CSDN-Java领域新星创作者🏆,保研|国家奖学金|高中学习JAVA|大学完善JAVA开发技术栈|面试刷题|面经八股文|经验分享|好用的网站工具分享💎💎💎 🍎座右…...

Okio 网络提速

文章目录网络数据处理流程Page Cache传统 I/O 拷贝的性能问题零拷贝技术DMA 技术零拷贝技术分类mmapsendfilespliceDirect I/O零拷贝技术性能分析小结OkioOkio 的使用Okio 网络提速的原理Okio 总结总结网络数据处理流程 在讲 Okio 之前,为了能更好的了解 Okio 的优…...

自动驾驶企业面临哪些数据安全挑战?

近期,“特斯拉员工被曝私下分享用户隐私”不可避免地成了新闻热点,据说连马斯克也不能幸免。 据相关媒体报道,9名前特斯拉员工爆料在2019年至2022年期间,特斯拉员工通过内部消息系统私下分享了一些车主车载摄像头记录的隐私视频和…...

Doris(2):Doris编译部署

1 Doris编译 Apache Doris提供直接可以部署的版本压缩包:https://cloud.baidu.com/doc/PALO/s/Ikivhcwb5 也可以自行编译压缩包后使用(推荐) 1.1 使用 Docker 开发镜像编译(推荐) 这个是官方文档推荐的,…...

使用MyBatis实现简单查询

文章目录一,创建数据库与表(一)在Navicat里创建MySQL数据库testdb(二)创建用户表 - t_user(三)在用户表里插入3条记录二,案例演示MyBatis基本使用(一)创建Mav…...

C指针(*point)[4]和char *point[4]

char (*point)[4] // 数组指针。 a[3][4] // 先申明二维数组,用它来指向这个二维数组. char *point[4] // 指针数组。 a[4][5] // 一连串的指针. char (*point)[4] // 一个指针,指向有4个元素的数组;占内存大小为 4 个字节 ch…...

【Bard】谷歌的人工智能工具—Bard初体验

文章目录一、Bard介绍二、Bard体验1、加入Bard的候补名单2、登入Bard篇3、使用Bard篇(1)提供三种预选方式✨(2)创作生成各类文案(3)无生成图画能力(4)支持语音转文本输入✨&#xff…...

2022国赛30:windows脚本题解析

大赛试题内容: ( 九) ) 脚本 【任务描述】 为了减少重复性任务的工作量,节省人力和时间,请采用脚本,实现快速批量的操作。 1.在 windows4 上编写 C:\CreateFile.ps1 的 powershell 脚本,创建20 个文件 C:\test\File00.txt 至 C:\test\File19.txt,如果文件存在,则首先删除…...

Excel常用函数公式20例

目录 一、【IF函数条件判断】 二、【多条件判断】 三、【条件求和】 四、【多条件求和】 五、【条件计数】 六、【多条件计数】 七、【条件查找】 八、【多条件查找】 九、【计算文本算式】 十、【合并多个单元格内容】 十一、【合并带格式的单元格内容】 十二、…...

233:vue+openlayers绘制渐变填充色的圆形、多边形

第233个 点击查看专栏目录 本示例的目的是介绍如何在vue+openlayer中绘制带有渐变填充色的圆形、多边形。这里用canvas的方式去渲染,用到了DEVICE_PIXEL_RATIO,设备上的物理像素与设备无关像素 (dips) 之间的比率 (window.devicePixelRatio)。 直接复制下面的 vue+openlayer…...

Flink的窗口机制

窗口机制 tumble(滚动窗口) hop(滑动窗口) session(会话窗口) cumulate(渐进式窗口) Over(聚合窗口) 滚动窗口(tumble) 概念 滚…...

了解分布式Session

大家好,我这名CRUD工程师又来了,最近我的一个同事突然在看分布式Seesion的问题,然后我们两个也是互相讨论了一下,今天我就想着把分布式Session的知识点好好的梳理一下。 在很多系统中,用户的登录功能都是用Session去实…...

仿真创新大赛—国三省一 智能鱼缸(proteus)(stm32)

⏩ 大家好哇!我是小光,嵌入式爱好者,一个想要成为系统架构师的大三学生。 ⏩去年下半年参加了全国仿真创新大赛,也是取得了国赛三等奖,省赛一等奖的好成绩。 ⏩本篇文章对我们的参赛作品《智能鱼缸》做一个简介。 ⏩感…...

【ARMv8 编程】A64 数据处理指令——位域字节操作指令

有些指令将字节、半字或字扩展到寄存器大小,可以是 X 或 W。这些指令存在于有符号(SXTB、SXTH、SXTW)和无符号(UXTB、UXTH)变体中,并且是适当的位域操作指令。 这些指令的有符号和无符号变体都将字节、半字…...

ctfshow 愚人杯菜狗杯部分题目(flasksession伪造ssti)

目录 <1>愚人杯 (1) easy_signin (2) easy_ssti(无过滤ssti) (3) easy_flask(flash-session伪造) (4) easy_php(C:开头序列化数据) <2> 菜狗杯 (1) 抽老婆(flask_session伪造) (2) 一言既出&#xff0c;驷马难追(intval) (3) 传说之下&#xff08;js控制台&…...

linux拓展笔记——【补充学习知识点】

文章目录1. ./configure --prefix中的prefix详解1. ./configure --prefix中的prefix详解 源码的安装一般由3个步骤组成&#xff1a;配置(configure)、编译(make)、安装(makeinstall)。 Configure是一个可执行脚本&#xff0c;在待安装的源码路径下使用命令./configure–help输…...

为何银行各岗位之间的薪酬差别如此之大?

银行里的职位种类相对较多&#xff0c;观观整理了5个最常见的职位&#xff0c;看一下你要申请的职位薪资水平到底是怎样的&#xff1f;根据如信银行考试中心发布&#xff1a; 1、客户经理岗 客户经理分为对公客户经理和对私客户经理&#xff0c;他们的主要工作不同&#xff0…...

TensorFlow 深度学习第二版:1~5

原文&#xff1a;Deep Learning with TensorFlow Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形象&#xff0c;只…...

微前端micro-app的使用

演示效果 子应用的项目 基应用嵌入子应用效果图 目录 前言 一、微前端是什么&#xff1f; 它主要解决了两个问题&#xff1a; 二、使用步骤 1.安装依赖 2.在入口处引入 3.子应用的路由&#xff08;&#xff09; 4.分配一个路由给子应用&#xff08;重要&#xff09;&#xff0…...

【JUC】Java内存模型之JMM

【JUC】Java内存模型之JMM 文章目录【JUC】Java内存模型之JMM1. 概念2. JMM三大特性2.1 可见性2.2 原子性2.3 有序性3. 多线程对变量的读写过程4. 先行发生原则——happens-before4.1 happens-before八条规则4.1.1 次序规则4.1.2 锁定规则4.1.3 volatile变量规则4.1.4 传递规则…...

Win11快速打开便签和使用技巧分享

Win11快速打开便签和使用技巧分享。Win11系统中为用户提供了一个非常实用的系统组件&#xff0c;就是便签功能&#xff0c;使用这个功能可以帮助我们便捷的进行一些重要内容的记录。那么如何去开启开启这个程序来使用呢&#xff1f;来看看以下的详情分享吧。 详细分享&#xff…...

CSS:横向导航栏

横向导航栏&#xff08;盗版导航栏&#xff0c;B站仿写。&#xff09; 原视频链接 <html><head><title>demo</title><style>*{margin: 0;padding: 0;list-style: none;text-decoration: none;}body{display: flex;justify-content: center;a…...

视频动态库测试及心得

视频动态库测试及心得 这几天一直在弄动态库测试&#xff0c;h给的写好的动态库--预处理模块的库。视频处理项目一部分&#xff0c;需要连接实际情况测试。 需求&#xff1a; 1.把实际相机连接到&#xff0c;并读取实时数据流&#xff0c;保存到双循环链表里面; 2.测试背景建模…...

陶泓达:4.18午间欧盘黄金原油最新精准操作建议!

黄金方面&#xff1a; 黄金消息面解析&#xff1a;周一&#xff08;4月17日&#xff09;美市盘中&#xff0c;美国公布的4月纽约联储制造业指数和4月NAHB房产市场指数均超出预期&#xff0c;提振了美联储在5月继续加息的预期。数据公布之后&#xff0c;美元指数加速上扬&#x…...

环境变量相关知识

目录 目录 谢谢你的阅读&#xff0c;这是对我最大的鼓舞 先说结论&#xff1a; 开始论述&#xff1a; 让我们举个例子 相关指令 创建本地变量 创建环境变量 方法一&#xff1a; 方法二&#xff1a; 删除环境变量 子进程中也有环境变量 第一种&#xff1a; 第二种 …...

如何快速入门ChatGPT

作为一个AI模型&#xff0c;ChatGPT并不需要像人一样“学习”&#xff0c;它已经通过大量的训练数据和算法进行了预训练&#xff0c;可以回答广泛的问题。 然而&#xff0c;如果你想学习如何使用ChatGPT来进行对话或者问答&#xff0c;以下是一些建议&#xff1a; 一、了解Ch…...

Akka定时任务schedule()方法

Akka定时任务schedule()方法 文章目录Akka定时任务schedule()方法什么是Akka定时任务schedule()方法&#xff1f;如何使用Akka定时任务schedule()方法&#xff1f;如何在actor外部获取Scheduler对象为什么需要提供一个隐式的ExecutionContext对象&#xff0c;用于执行定时任务&…...

Python实现处理和分析大规模文本数据集,包括数据清洗、标注和预处理

处理和分析大规模文本数据集,包括数据清洗、标注和预处理,是自然语言处理(NLP)中非常重要的一步。Python 是一种非常流行的编程语言,拥有丰富的 NLP 库和工具,可以帮助我们完成这些任务。以下是一个简单的实现示例,包括数据清洗、标注和预处理: import re import nltk…...