msf的rpc和json-rpc,我该选择哪个?(代码片段)

Akkuman Akkuman     2022-12-25     613

关键词:

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上包装了一层,功能上并没有变化

结论

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

在 JSON-RPC 方法中获取 websocket 连接信息

】在JSON-RPC方法中获取websocket连接信息【英文标题】:GettingwebsocketconnectioninformationinJSON-RPCmethod【发布时间】:2015-04-1419:02:54【问题描述】:我在Websocket上使用JSON-RPC。而且,在RPC方法中(例如,下面示例中的乘法),我需要知道... 查看详情

Swagger 和 json-rpc

】Swagger和json-rpc【英文标题】:Swaggerandjson-rpc【发布时间】:2013-10-2713:52:01【问题描述】:我正在尝试将Swagger-ui用于由php编写的json-rpc服务器。我使用Swagger-PHP为Swagger-ui生成json投诉容器。所以,我对Swagger很陌生,我对这样的方... 查看详情

没有 ASP.NET 的 C# JSON-RPC 网络服务器

】没有ASP.NET的C#JSON-RPC网络服务器【英文标题】:C#JSON-RPCwebserverwithoutASP.NET【发布时间】:2013-04-2909:47:43【问题描述】:我很惊讶我还没有找到一个简单的C#控制台应用程序能够将几个JSON-RPC命令作为服务器来处理。有没有办法通... 查看详情

哪个是码头最好的 json rpc 库?

...问题讨论】:【参考方案1】:真的没有什么好的,因为JSON-RPC协议在任何语言中实现起来都相当简单,所以我认为您可以获取像Gson这样的JSON库,它将对象反序列化/序列化为JSON并创建符合JSON-RPC的请求/ 查看详情

xpages JSON-RPC 服务处理来自回调函数的响应

】xpagesJSON-RPC服务处理来自回调函数的响应【英文标题】:xpagesJSON-RPCServicehandlingresponsefromcallbackfunciton【发布时间】:2014-09-0215:10:47【问题描述】:我有一个slickgrid屏幕(在常规Domino表单上),用户可以在其中选择和更新一些文... 查看详情

python中通过http的json-rpc

】python中通过http的json-rpc【英文标题】:json-rpcoverhttpinpython【发布时间】:2012-02-2515:18:57【问题描述】:一个老问题WhatisthecurrentchoicefordoingRPCinPython?给了我一个不错的PythonJSON-RPC实现可供选择:python-symmetric-jsonrpcrpcbdLadonjsonrpc2-zer... 查看详情

为 java 和 javascript 推荐一个 JSON-RPC 库 [关闭]

】为java和javascript推荐一个JSON-RPC库[关闭]【英文标题】:RecommendaJSON-RPClibraryforjavaandjavascript[closed]【发布时间】:2011-05-2609:16:01【问题描述】:我正在为JSON-RPC寻找一个好的解决方案,无论是在JAVA还是Javascript中(双方,但我并不... 查看详情

在 JSON-RPC 连接上读取多个 JSON 对象

】在JSON-RPC连接上读取多个JSON对象【英文标题】:ReadingmultipleJSONobjectsonaJSON-RPCconnection【发布时间】:2014-06-2823:02:54【问题描述】:我正在制作一个流式API,它处理RPC样式调用以及从服务器到客户端的通知(不是JSON-RPC规范中的... 查看详情

如何使用 JSON-RPC 处理面向对象的 API?

】如何使用JSON-RPC处理面向对象的API?【英文标题】:HowtoapproachanObjectOrientedAPIwithJSON-RPC?【发布时间】:2010-11-2020:07:17【问题描述】:我有一个C#中的API,它不会映射到JSON-RPC,因为JSON-RPC是面向过程的。您将如何在JSON-RPC中表示... 查看详情

具有自定义端点行为的 WCF ChannelFactory (Json-Rpc)

】具有自定义端点行为的WCFChannelFactory(Json-Rpc)【英文标题】:WCFChannelFactorywithCustomEndpointBehavior(Json-Rpc)【发布时间】:2013-08-2317:10:09【问题描述】:我一直在为WCFJson-RpcServiceModel努力工作。我对WCF和WCF可扩展性还很陌生,但最后... 查看详情

Ember 数据 JSON-RPC 请求示例

】Ember数据JSON-RPC请求示例【英文标题】:EmberDataJSON-RPCrequestsExample【发布时间】:2017-05-1112:27:30【问题描述】:我想使用EmberJS和ember-data向我的zabbix服务器发送Post请求我将如何使用JSON-RPC进行查询?在python中我会做这样的事情:H... 查看详情

用于 C++ 的非 GPL JSON-RPC 库 [关闭]

】用于C++的非GPLJSON-RPC库[关闭]【英文标题】:Non-GPLJSON-RPClibraryforC++[closed]【发布时间】:2008-10-3122:53:44【问题描述】:哪些非GPL库可用于用原生C++编写JSON-RPC服务器和客户端?根据http://json-rpc.org/wiki/implementations,似乎只存在一... 查看详情

JSON-RPC,“无法解组对象”

】JSON-RPC,“无法解组对象”【英文标题】:JSON-RPC,"cannotunmarshalobject"【发布时间】:2017-07-0318:50:26【问题描述】:我正在尝试了解JSON-RPC的工作原理,并正在使用Go语言(golang)对其进行测试。Go程序运行良好。它做它应该... 查看详情

使用标准 JSON-RPC 实现的优势

】使用标准JSON-RPC实现的优势【英文标题】:AdvantagesofusingastandardJSON-RPCimplementation【发布时间】:2011-04-0211:22:44【问题描述】:我总是最终使用我自己的JSON-RPC简约包装器(因为它非常简单):与标准库相比,我错过了什么吗?... 查看详情

使用 JSON-RPC 缓存响应

】使用JSON-RPC缓存响应【英文标题】:CachingresponseswithJSON-RPC【发布时间】:2017-05-1108:42:08【问题描述】:在REST中我们可以通过URL缓存响应,但在JSON-RPC中所有数据都是传入的主体,那么我们如何在JSON-RPC中缓存响应?是否可以在... 查看详情

Go & PHP json-rpc 通信

】Go&PHPjson-rpc通信【英文标题】:Go&PHPjson-rpccommunication【发布时间】:2018-05-0219:36:11【问题描述】:我尝试在php和go之间通信JSON-RPC。此示例中的服务器GOhttps://golang.org/pkg/net/rpc/packagemainimport("errors""net/rpc""net""log""net/http")typeA... 查看详情

GAE Go Json-RPC 调用示例

】GAEGoJson-RPC调用示例【英文标题】:GAEGoJson-RPCcallexample【发布时间】:2012-01-1301:09:16【问题描述】:我正在尝试了解如何在GoogleGo中使用将在GoogleAppEngine应用中使用的Json-RPC调用。到目前为止,我知道我应该以某种方式调用rpc.Cli... 查看详情

jsonrpc.js--原生js实现json-rpc协议

...计,那时候自己设计了个消息传递回调过程。最近了解了JSON-RPC协议,更正规,就可以自己实现下。逻辑也不复杂,没有限制底层消息传递的方式,可以应用到更多的场景。在实现中,没有区分服务器端和客户端的概念,获得不... 查看详情