msf的rpc有两种调用方式,那么我们应该调用哪一个呢?

其中restful接口暂且不谈,这个rest api其实是简单对接了一下msf的后端数据库,这个自己也能读数据库来做,这个以后有时间再谈

首先说下这个json-rpc,json-rpc是metasploit5.0推出的一个功能,采用json作为交互格式,例如

akkuman@DESKTOP-MFL946C ~> curl -k -X POST -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer f622f07405f68533c549bc11838c9f1b6b1f14ba5caae75fb726da071b73f8315aaf3b9b0186fc51" -d '{"jsonrpc": "2.0", "method": "core.version", "id": 1 }' http://192.168.174.136:8081/api/v1/json-rpc
{"jsonrpc":"2.0","result":{"version":"5.0.87-dev-2dc26db9e1","ruby":"2.6.6 x86_64-linux 2020-03-31","api":"1.0"},"id":1}

而以前的msf的rpc是采用msgpack作为交互格式,除了没有json方便之外还有什么其他的区别吗?

答案是没有的

我们看看源码

lib/msf/core/rpc/json/dispatcher.rb

    # Process the JSON-RPC request.
# @param source [String] the JSON-RPC request
# @return [String] JSON-RPC response that encapsulates the RPC result
# if successful; otherwise, a JSON-RPC error response.
def process(source)
begin
request = parse_json_request(source)
if request.is_a?(Array)
# If the batch rpc call itself fails to be recognized as an valid
# JSON or as an Array with at least one value, the response from
# the Server MUST be a single Response object.
raise InvalidRequest.new if request.empty?
# process batch request
response = request.map { |r| process_request(r) }
# A Response object SHOULD exist for each Request object, except that
# there SHOULD NOT be any Response objects for notifications.
# Remove nil responses from response array
response.compact!
else
response = process_request(request)
end
rescue ParseError, InvalidRequest => e
# If there was an error in detecting the id in the Request object
# (e.g. Parse error/Invalid Request), then the id member MUST be
# Null. Don't pass request obj when building the error response.
response = self.class.create_error_response(e)
rescue RpcError => e
# other JSON-RPC errors should include the id from the Request object
response = self.class.create_error_response(e, request)
rescue => e
response = self.class.create_error_response(ApplicationServerError.new(e), request)
end # When a rpc call is made, the Server MUST reply with a Response, except
# for in the case of Notifications. The Response is expressed as a single
# JSON Object.
self.class.to_json(response)
end

里面的响应是使用 process_request,往下跟

lib/msf/core/rpc/json/dispatcher.rb

    # Validate and execute the JSON-RPC request.
# @param request [Hash] the JSON-RPC request
# @returns [RpcCommand] an RpcCommand for the specified version
# @raise [InvalidParams] ArgumentError occurred during execution.
# @raise [ApplicationServerError] General server-error wrapper around an
# Msf::RPC::Exception that occurred during execution.
# @returns [Hash] JSON-RPC response that encapsulates the RPC result
# if successful; otherwise, a JSON-RPC error response.
def process_request(request)
begin
if !validate_rpc_request(request)
response = self.class.create_error_response(InvalidRequest.new)
return response
end # dispatch method execution to command
result = @command.execute(request[:method], request[:params]) # A Notification is a Request object without an "id" member. A Request
# object that is a Notification signifies the Client's lack of interest
# in the corresponding Response object, and as such no Response object
# needs to be returned to the client. The Server MUST NOT reply to a
# Notification, including those that are within a batch request.
if request.key?(:id)
response = self.class.create_success_response(result, request)
else
response = nil
end response
rescue ArgumentError
raise InvalidParams.new
rescue Msf::RPC::Exception => e
raise ApplicationServerError.new(e.message, data: { code: e.code })
end
end

可以看到 @command.execute,往下跟我们会发现出现了好几个,往上看能发现

    # Set the command.
# @param command [RpcCommand] the command used by the Dispatcher.
def set_command(command)
@command = command
end

说明 @command 是一个 RpcCommand 类对象,但是出现了好几个这样的类,这里我们可以通过断点或者打印 @command 来判断,关于怎么在msf上下断调试以后有时间再写文章

我这里是通过打印,发现是 Msf::RPC::JSON::V1_0::RpcCommand 类,定位到这个类的 execute 方法

lib/msf/core/rpc/json/v1_0/rpc_command.rb

      # Invokes the method on the receiver object with the specified params,
# returning the method's return value.
# @param method [String] the RPC method name
# @param params [Array, Hash] parameters for the RPC call
# @returns [Object] the method's return value.
def execute(method, params)
result = execute_internal(method, params)
result = post_process_result(result, method, params) result
end

我们先看看 post_process_result

...
MODULE_EXECUTE_KEY = 'module.execute'
PAYLOAD_MODULE_TYPE_KEY = 'payload'
PAYLOAD_KEY = 'payload'
...
# Perform custom post processing of the execute result data.
# @param result [Object] the method's return value
# @param method [String] the RPC method name
# @param params [Array, Hash] parameters for the RPC call
# @returns [Object] processed method's return value
def post_process_result(result, method, params)
# post-process payload module result for JSON output
if method == MODULE_EXECUTE_KEY && params.size >= 2 &&
params[0] == PAYLOAD_MODULE_TYPE_KEY && result.key?(PAYLOAD_KEY)
result[PAYLOAD_KEY] = Base64.strict_encode64(result[PAYLOAD_KEY])
end result
end

可以看到这个函数的功能大致上就是假如请求的json-rpc是生成可执行文件,就base64再返回,而rpc因为使用的msgpack,所以直接返回的二进制流

然后我们看看主要的调用函数 execute_internal

      # Internal method that invokes the method on the receiver object with
# the specified params, returning the method's return value.
# @param method [String] the RPC method name
# @param params [Array, Hash] parameters for the RPC call
# @raise [MethodNotFound] The method does not exist
# @raise [Timeout::Error] The method failed to terminate in @execute_timeout seconds
# @returns [Object] the method's return value.
def execute_internal(method, params)
group, base_method = parse_method_group(method) method_name = "rpc_#{base_method}"
method_name_noauth = "rpc_#{base_method}_noauth" handler = (find_handler(@legacy_rpc_service.handlers, group, method_name) || find_handler(@legacy_rpc_service.handlers, group, method_name_noauth))
if handler.nil?
raise MethodNotFound.new(method)
end if handler.respond_to?(method_name_noauth)
method_name = method_name_noauth
end ::Timeout.timeout(@execute_timeout) do
params = prepare_params(params)
if params.nil?
return handler.send(method_name)
elsif params.is_a?(Array)
return handler.send(method_name, *params)
else
return handler.send(method_name, **params)
end
end
end

可以看到先经过处理之后,调用了 @legacy_rpc_service 得到 handler,而这个 legacy_rpc_service 则又是调用了原始 rpc 了,然后调用 send 方法来调用rpc,所以json-rpc实际上就是在原始rpc上包装了一层,功能上并没有变化

结论

两者功能相同,用哪个看个人喜好

msf的rpc和json-rpc,我该选择哪个?的更多相关文章

  1. 測试JSON RPC远程调用(JSONclient)

    #include <string> #include <iostream> #include <curl/curl.h> /* 标题:JSonclient Auth ...

  2. RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大、最高效的方法之一。它为在分布式计算环境中运行的几乎所有应用程序提供基础。

    RPC 编程 使用 RPC 编程是在客户机和服务器实体之间进行可靠通信的最强大.最高效的方法之一.它为在分布式计算环境中运行的几乎所有应用程序提供基础.本文介绍 RPC 客户机和服务器之间基本的事件流 ...

  3. 拥抱.NET Core,跨平台的轻量级RPC:Rabbit.Rpc

    不久前发布了一篇博文".NET轻量级RPC框架:Rabbit.Rpc",当初只实现了非常简单的功能,也罗列了之后的计划,经过几天的不断努力又为Rabbit.Rpc增加了一大波新特性 ...

  4. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V3 -- 远程方法调用 整合 Spring

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V3——RPC -- 远程方法调用 及 null的传输 + Spring 服务提供商: 1. 配置 rpc03_server.xml 注入 服务提供 ...

  5. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V4 -- 远程方法调用 整合 Spring 自动注册

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V4——RPC -- 远程方法调用 + Spring 自动注册 服务提供商: 1. 配置 rpc04_server.xml 注入 服务提供商 rpc ...

  6. C# -- 高性能RPC框架:Socean.RPC

    简介 Socean.RPC是一个.Net下的高性能RPC框架,框架以高性能.高稳定性为目标,底层基于socket,无第三方库引用,代码简洁,总代码量大约在2000行,框架性能较高,在普通PC上测试,长 ...

  7. 应答流式RPC 请求流式RPC 向流式RPC 流式RPC的三种具体形式

    https://mp.weixin.qq.com/s/pWwSfXl71GQZ3KPmAHE_dA 用Python进行gRPC接口测试(二) 大帆船 搜狗测试 2020-02-07   上期回顾:用P ...

  8. RPC原理及RPC实例分析

    在学校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 1 2 3 4 5 6 public class ...

  9. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V1 -- 本地方法调用

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——RPC -- 本地方法调用:不通过网络 入门 1. RPCObjectProxy rpcObjectProxy = new RPCObjec ...

随机推荐

  1. 使用 RestTemplate 进行第三方Rest服务调用

    1. 前言 RestTemplate 是 Spring 提供的一个调用 Restful 服务的抽象层,它简化的同 Restful 服务的通信方式,隐藏了不必要的一些细节,让我们更加优雅地在应用中调用 ...

  2. 记一次pgsql中查询优化(子查询)

    记一次pgsql的查询优化 前言 这是一个子查询的场景,对于这个查询我们不能避免子查询,下面是我一次具体的优化过程. 优化策略 1.拆分子查询,将需要的数据提前在cte中查询出来 2.连表查询,直接去 ...

  3. AJ学IOS 之CoreLocation指南针小应用

    AJ分享,必须精品 一:效果图示 简单的用到CoreLocation获取方位做的指南针小应用 二:制作思路 具体用到了CoreLocation相关的知识,请看上一篇博客有写 然后获取方向不需要进行授权 ...

  4. ViewStub

    在书上了解了ViewStub,但只是带过两笔,没能了解.在网上搜索了一些资料,虽然很多文章都讲得比较完善,但是觉得可能是表达的原因,导致某个点上我理解错误,慢慢的才算比较清楚的认识ViewStub. ...

  5. sublime text3添加并修改编译系统

    版权声明:本文为CSDN博主「肥宅_Sean」的原创文章,遵循 CC 4.0 BY-SA 版权协议,原文链接 方法工具 -> 编译系统 -> 新建编译系统 按ctrl+s保存.(注意,这里 ...

  6. C语言二维数组超细讲解

    用一维数组处理二维表格,实际是可行的,但是会很复杂,特别是遇到二维表格的输入.处理和输出. 在你绞尽脑汁的时候,二维数组(一维数组的大哥)像电视剧里救美的英雄一样显现在你的面前,初识数组的朋友们还等什 ...

  7. kubernetes的Statefulset介绍

    StatefulSet是一种给Pod提供唯一标志的控制器,他可以保证部署和扩展的顺序. Pod一致性 包含次序(启动和停止次序).网络一致性.此一致性和Pod相关.与被调度到哪个Node节点无关. 稳 ...

  8. pytorch 中交叉熵损失实现方法

  9. 三本毕业(非科班),四次阿里巴巴面试,终拿 offer(大厂面经)

    作者:gauseen 原文:https://github.com/gauseen/blog 公众号:「学前端」,只搞技术不搞广告文,欢迎关注~ 第一次 20:00 电话一面 - 自我介绍 - 对公司工 ...

  10. sqlilab less15-17

    less15 试了很多符号,页面根本不显示别的信息,猜测为盲注 可是怎么检测闭合? 万能密码登录 最终试出来'闭合 uname=1' or 1=1 # 接下来就要工具跑 less16 同上用万能密码试 ...