RPC浅析,加密数据解析
个人总结
其实就是HOOK注入wbsocket 链接创建服务端和客户端进行通信,直接调用js代码中的加密方法
将结果通过浏览器客户端传入服务端。一种比较好实用的一种技术
https://blog.csdn.net/qq_36759224/article/details/123082574
(搬运记录下)
RPC,英文 RangPaCong,中文让爬虫,旨在为爬虫开路,秒杀一切,让爬虫畅通无阻!
开个玩笑,实际上 RPC 为远程过程调用,全称 Remote Procedure Call,是一种技术思想而非一种规范或协议。RPC 的诞生事实上离不开分布式的发展,RPC 主要解决了两个问题:
1.解决了分布式系统中,服务之间的互相调用问题;2.RPC 使得在远程调用时,像本地调用一样方便,让调用者感知不到远程调用的逻辑。
RPC 的存在让构建分布式系统更加容易,相比于 HTTP 协议,RPC 采用二进制字节码传输,因此也更加高效、安全。在一个典型 RPC 的使用场景中,包含了服务发现、负载、容错、网络传输、序列化等组件
RPC 技术是非常复杂的,对于我们搞爬虫、逆向的来说,不需要完全了解,只需要知道这项技术如何在逆向中应用就行了。
RPC 在逆向中,简单来说就是将本地和浏览器,看做是服务端和客户端,二者之间通过 WebSocket 协议进行 RPC 通信,在浏览器中将加密函数暴露出来,在本地直接调用浏览器中对应的加密函数,从而得到加密结果,不必去在意函数具体的执行逻辑,也省去了扣代码、补环境等操作,可以省去大量的逆向调试时间。我们以某团网页端的登录为例来演示 RPC 在逆向中的具体使用方法。(假设你已经有一定逆向基础,了解 WebSocket 协议,纯小白可以先看看K哥以前的文章)
import sys
import asyncio
import websocketsasync def receive_massage(websocket):while True:send_text = input("请输入要加密的字符串: ")if send_text == "exit":print("Exit, goodbye!")await websocket.send(send_text)await websocket.close()sys.exit()else:await websocket.send(send_text)response_text = await websocket.recv()print("\n加密结果:", response_text)start_server = websockets.serve(receive_massage, '127.0.0.1', 5678) # 自定义端口
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
var ws = new WebSocket("ws://127.0.0.1:5678"); // 自定义端口ws.onmessage = function (evt) {console.log("Received Message: " + evt.data);if (evt.data == "exit") {ws.close();} else {ws.send(utility.getH5fingerprint(evt.data))}
};
然后我们需要把客户端代码注入到网页中,这里方法有很多,比如抓包软件 Fiddler 替换响应、浏览器插件 ReRes 替换 JS、浏览器开发者工具 Overrides 重写功能等,也可以通过插件、油猴等注入 Hook 的方式插入,反正方法很多,对这些方法不太了解的朋友可以去看看K哥以前的文章,都有介绍。
这里我们使用浏览器开发者工具 Overrides 重写功能,将 WebSocket 客户端代码加到加密的这个 JS 文件里并 Ctrl+S 保存,这里将其写成了 IIFE 自执行方式,这样做的原因是防止污染全局变量,不用自执行方式当然也是可以的。
/* ==================================
# @Time : 2022-02-14
# @Author : 微信公众号:K哥爬虫
# @FileName: sekiro.js
# @Software: PyCharm
# ================================== */(function () {'use strict';function SekiroClient(wsURL) {this.wsURL = wsURL;this.handlers = {};this.socket = {};// checkif (!wsURL) {throw new Error('wsURL can not be empty!!')}this.webSocketFactory = this.resolveWebSocketFactory();this.connect()}SekiroClient.prototype.resolveWebSocketFactory = function () {if (typeof window === 'object') {var theWebSocket = window.WebSocket ? window.WebSocket : window.MozWebSocket;return function (wsURL) {function WindowWebSocketWrapper(wsURL) {this.mSocket = new theWebSocket(wsURL);}WindowWebSocketWrapper.prototype.close = function () {this.mSocket.close();};WindowWebSocketWrapper.prototype.onmessage = function (onMessageFunction) {this.mSocket.onmessage = onMessageFunction;};WindowWebSocketWrapper.prototype.onopen = function (onOpenFunction) {this.mSocket.onopen = onOpenFunction;};WindowWebSocketWrapper.prototype.onclose = function (onCloseFunction) {this.mSocket.onclose = onCloseFunction;};WindowWebSocketWrapper.prototype.send = function (message) {this.mSocket.send(message);};return new WindowWebSocketWrapper(wsURL);}}if (typeof weex === 'object') {// this is weex env : https://weex.apache.org/zh/docs/modules/websockets.htmltry {console.log("test webSocket for weex");var ws = weex.requireModule('webSocket');console.log("find webSocket for weex:" + ws);return function (wsURL) {try {ws.close();} catch (e) {}ws.WebSocket(wsURL, '');return ws;}} catch (e) {console.log(e);//ignore}}//TODO support ReactNativeif (typeof WebSocket === 'object') {return function (wsURL) {return new theWebSocket(wsURL);}}// weex 和 PC环境的websocket API不完全一致,所以做了抽象兼容throw new Error("the js environment do not support websocket");};SekiroClient.prototype.connect = function () {console.log('sekiro: begin of connect to wsURL: ' + this.wsURL);var _this = this;// 不check close,让// if (this.socket && this.socket.readyState === 1) {// this.socket.close();// }try {this.socket = this.webSocketFactory(this.wsURL);} catch (e) {console.log("sekiro: create connection failed,reconnect after 2s");setTimeout(function () {_this.connect()}, 2000)}this.socket.onmessage(function (event) {_this.handleSekiroRequest(event.data)});this.socket.onopen(function (event) {console.log('sekiro: open a sekiro client connection')});this.socket.onclose(function (event) {console.log('sekiro: disconnected ,reconnection after 2s');setTimeout(function () {_this.connect()}, 2000)});};SekiroClient.prototype.handleSekiroRequest = function (requestJson) {console.log("receive sekiro request: " + requestJson);var request = JSON.parse(requestJson);var seq = request['__sekiro_seq__'];if (!request['action']) {this.sendFailed(seq, 'need request param {action}');return}var action = request['action'];if (!this.handlers[action]) {this.sendFailed(seq, 'no action handler: ' + action + ' defined');return}var theHandler = this.handlers[action];var _this = this;try {theHandler(request, function (response) {try {_this.sendSuccess(seq, response)} catch (e) {_this.sendFailed(seq, "e:" + e);}}, function (errorMessage) {_this.sendFailed(seq, errorMessage)})} catch (e) {console.log("error: " + e);_this.sendFailed(seq, ":" + e);}};SekiroClient.prototype.sendSuccess = function (seq, 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;}responseJson['__sekiro_seq__'] = seq;var responseText = JSON.stringify(responseJson);console.log("response :" + responseText);this.socket.send(responseText);};SekiroClient.prototype.sendFailed = function (seq, errorMessage) {if (typeof errorMessage != 'string') {errorMessage = JSON.stringify(errorMessage);}var responseJson = {};responseJson['message'] = errorMessage;responseJson['status'] = -1;responseJson['__sekiro_seq__'] = seq;var responseText = JSON.stringify(responseJson);console.log("sekiro: response :" + responseText);this.socket.send(responseText)};SekiroClient.prototype.registerAction = function (action, handler) {if (typeof action !== 'string') {throw new Error("an action must be string");}if (typeof handler !== 'function') {throw new Error("a handler must be function");}console.log("sekiro: register action: " + action);this.handlers[action] = handler;return this;};function guid() {function S4() {return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);}return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());}var client = new SekiroClient("ws://127.0.0.1:5620/business-demo/register?group=rpc-test&clientId=" + guid());client.registerAction("getH5fingerprint", function (request, resolve, reject) {resolve(utility.getH5fingerprint(request["url"]));})})();
相关文章:
RPC浅析,加密数据解析
个人总结 其实就是HOOK注入wbsocket 链接创建服务端和客户端进行通信,直接调用js代码中的加密方法 将结果通过浏览器客户端传入服务端。一种比较好实用的一种技术 https://blog.csdn.net/qq_36759224/article/details/123082574 (搬运记录下ÿ…...
光速论文能用吗 #媒体#知识分享#学习方法
光速论文是一个非常有效的论文写作、查重降重工具,它的使用非常简单方便,而且功能强大,是每个写作者必备的利器。 首先,光速论文具有强大的查重降重功能,能够快速检测论文中的抄袭部分,帮助作者避免不必要的…...
智慧工地解决方案,智慧工地项目管理系统源码,支持大屏端、PC端、手机端、平板端
智慧工地解决方案依托计算机技术、物联网、云计算、大数据、人工智能、VR&AR等技术相结合,为工程项目管理提供先进技术手段,构建工地现场智能监控和控制体系,弥补传统方法在监管中的缺陷,最线实现项目对人、机、料、法、环的全…...
【前端寻宝之路】学习和使用label标签
🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| 💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-2nm9oQQVtSL8hDS1 {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...
项目————网络聊天室
服务器 #include <myhead.h> typedef struct msg{char flag;char name[20];char cont[128]; }msg_t;typedef struct link{struct sockaddr_in cin;struct link* next; }link_t;void do_login(int sfd,msg_t msg,link_t *L,struct sockaddr_in cin){link_t* pL;if(sendto…...
【计算机网络】基本概念
基本概念 IP 地址端口号协议协议分层封装分用客户端服务器请求和响应两台主机之间的网络通信流程 IP 地址 概念:IP 地址主要是用于唯一标识网络主机、其他网络设备(如路由器)的网络地址。简单来说,IP地址用来唯一定位主机。格式&…...
Redis入门到实战-第七弹
Redis实战热身Sets篇 完整命令参考官网 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://redis.io/Redis概述 Redis是一个开源的(采用BSD许可证),用作数据库、缓存、消息代理和流…...
图像处理学习笔记(一)
本文主要介绍,以供读者能够理解该技术的定义、原理、应用。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:ISP处理 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就…...
duckdb学习-1
DuckDB is a fast in-process analytical database DuckDB supports a feature-rich SQL dialect complemented with deep integrations into client APIs 在notebook中使用duckdb 安装 pip install duckdb 示例代码: #> pip install jupysql #> pip install duckdb-en…...
GEE高阶案例——Landsat/Sentinel/MODIS影像进行缨帽变换一行代码实现
本教程的主要目的是利用eemont中的tasseledCap()的函数进行缨帽变换实现。 在 eemont 中,可使用扩展到 ee.Image 和 ee.ImageCollection 对象的 tasseledCap 方法计算缨帽亮度、绿度和湿度组件。只需从支持的平台加载图像,然后使用 tasseledCap 添加分量带即可。 代码: !p…...
数独游戏(c++题解)
题目描述 给出一个的表格,部分格子已经填好数。请填完所有空白格子,使得表格每一行、每一列、每个的九宫格,都恰好填满这9个数字。 输入格式 9行9列的方阵状态,0代表空格。 输出格式 输出完成后的方阵状态,每一个…...
【开发方案】Android 应用双卡搜网功能
一、功能简介 需求:开机自动开始搜网并显示网络列表 那么就不能将相关类做成单例,不能将subId、phoneId等卡相关的属性作为UI、服务的全局变量。 二、流程设计 NetworkSelectReceiver:监听开机广播,触发拉起搜网服务 NetworkOperatorService:搜网服务,完成后调起用户…...
图论基础|深度优先dfs、广度优先bfs
dfs 与 bfs 区别 提到深度优先搜索(dfs),就不得不说和广度优先搜索(bfs)有什么区别 先来了解dfs的过程,很多录友可能对dfs(深度优先搜索),bfs(广度优先搜索…...
Python从入门到精通秘籍十七
一、Python的构造方法 在Python中,构造方法是一个特殊的方法,用于创建和初始化类的实例。构造方法的名称是__init__(),它在创建对象时自动调用。 下面是一个示例代码来详细解释Python的构造方法: class Person:def __init__(se…...
Java——抽象类和接口
目录 1.抽象类 1.概念: 2.语法 3.特性 2.接口 1.概念 2.语法 3.特性 1.抽象类 1.概念: 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的…...
React—— props校验(非typescript校验类型)
非typescript环境下,当我们在封装组件的时候,接受props时传入的内容,需要做类型检测,那我们可以用props校验进行类型的检查。 props校验允许在创建组件的时候,就约定props的格式、类型等 实现步骤: 导入 …...
Go——map操作及原理
一.map介绍和使用 map是一种无序的基于key-value的数据结构,Go语言的map是引用类型,必须初始化才可以使用。 1. 定义 Go语言中,map类型语法如下: map[KeyType]ValueType KeyType表示键类型ValueType表示值类型 map类型的变量默认…...
网络安全实训Day9
写在前面 访问控制和防火墙桌面端安全检测与防御 网络安全实训-网络安全技术 网络安全概述 访问控制 定义:通过定义策略和规则来限制哪些流量能经过防火墙,哪些流量不能通过。本质是包过滤 可以匹配的元素 IP协议版本 源区域和目的区域 源IP地址和目…...
kubernetes实战(1)之虚拟机centos搭建k8s集群
一,环境准备 centos7系统,每个系统2c2g,40g,centos7下载地址:centos-7.9.2009-isos-x86_64安装包下载_开源镜像站-阿里云 # 每个节点分别设置对应主机名 hostnamectl set-hostname master hostnamectl set-hostname …...
基于python+vue分类信息服务平台移动端的设计与实现flask-django-php-nodejs
分类信息服务平台是在Android操作系统下的应用平台。为防止出现兼容性及稳定性问题,框架选择的是django,Android与后台服务端之间的数据存储主要通过MySQL。用户在使用应用时产生的数据通过 python等语言传递给数据库。通过此方式促进分类信息服务平台信…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
