# 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.defprocess(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.raiseInvalidRequest.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)
endrescueParseError, 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)
rescueRpcError=> 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
# 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.defprocess_request(request)
beginif!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 =nilend response
rescueArgumentErrorraiseInvalidParams.new
rescueMsf::RPC::Exception=> e
raiseApplicationServerError.new(e.message, data: { code: e.code })
endend
可以看到 @command.execute,往下跟我们会发现出现了好几个,往上看能发现
1
2
3
4
5
# Set the command.# @param command [RpcCommand] the command used by the Dispatcher.defset_command(command)
@command = command
end
# 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.defexecute(method, params)
result = execute_internal(method, params)
result = post_process_result(result, method, params)
result
end
我们先看看 post_process_result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...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 valuedefpost_process_result(result, method, params)
# post-process payload module result for JSON outputif 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