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. 大数据及hadoop简要概念

    大数据 大数据简要概念 指无法在一定时间范围内用常规软件工具进行捕捉.管理和处理的数据集合.需要新处理模式,才能具有更强的决策力.洞察发现力和流程优化能力的海量.高增长率和多样化的信息资产. 大数据作 ...

  2. cmake添加版本号

    vVersion.cmake文件内容如下: #vversion.cmake #vDateTime string(TIMESTAMP vDateTime "%Y%m%d-%H%M%S" ...

  3. java 中类为啥要序列化

    java里为什么要序列化?http://zhidao.baidu.com/link?url=7_wAQ8eAl28vcJPE5OKM5Y0Bo4aINNQokHhRmI9XPszEoTO5QF-gNb ...

  4. MD5中使用16进制

    MD5中使用16进制消息摘要 分类: java_secruity2012-12-28 13:11 719人阅读 评论(0) 收藏 举报 消息摘要 由于数据在计算机中的表示,最终以二进制的形式存在,所以 ...

  5. EFCore.Sharding(EFCore开源分表框架)

    EFCore.Sharding(EFCore开源分表框架) 简介 引言 开始 准备 配置 使用 按时间自动分表 性能测试 其它简单操作(非Sharing) 总结 简介 本框架旨在为EF Core提供S ...

  6. Spring Cloud 系列之 Gateway 服务网关(三)

    本篇文章为系列文章,未读第一集的同学请猛戳这里: Spring Cloud 系列之 Gateway 服务网关(一) Spring Cloud 系列之 Gateway 服务网关(二) 本篇文章讲解 Ga ...

  7. Vue【你知道吗?】

    前言 Vue的由来 Vue最早发布于2014年左右,作者是美中国学生尤雨溪.Vue 的定位就是为前端开发提供一个低门槛,高效率,但同时又能够伴随用户成长的框架 尤雨溪谈Vue.js :缔造自由与真我 ...

  8. python os模块获取指定目录下的文件列表

    bath_path = r"I:\ner_results\ner_results" dir_list1 = os.listdir(bath_path) for dir1 in di ...

  9. Caused by: java.lang.NumberFormatException: For input string: " 60"

    原因 原原因:string转int 格式出错 解决:我的输入文件格式在根据“,”分割完之后多出了一个空格,我想要的是“60” 但是分割完之后是“ 60”所以导致格式转换不匹配.

  10. C语言字符数组超细讲解

    看到标题,有不少朋友会想:字符数组不也是数组吗?为什么要单独拿出来讲哩?莫非它是朵奇葩? 哈哈,确实,一起来认识一下这朵数组界的奇葩吧! 一.字符数组的定义.引用.初始化 大家好!我是字符数组,看我的 ...