Class: Msf::MCP::Metasploit::MessagePackClient

Inherits:
Object
  • Object
show all
Defined in:
lib/msf/core/mcp/metasploit/messagepack_client.rb

Overview

MessagePack RPC client for Metasploit Framework Implements authentication and API calls using MessagePack serialization

Constant Summary collapse

DEFAULT_ENDPOINT =
'/api/'

Instance Method Summary collapse

Constructor Details

#initialize(host:, port:, endpoint: DEFAULT_ENDPOINT, ssl: true) ⇒ MessagePackClient

Initialize MessagePack client

Parameters:

  • host (String)

    Metasploit RPC host

  • port (Integer)

    Metasploit RPC port

  • endpoint (String) (defaults to: DEFAULT_ENDPOINT)

    API endpoint path (default: DEFAULT_ENDPOINT)

  • ssl (Boolean) (defaults to: true)

    Use SSL (default: true)



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 18

def initialize(host:, port:, endpoint: DEFAULT_ENDPOINT, ssl: true)
  @host = host
  @port = port
  @endpoint = endpoint
  @token = nil
  @http = nil
  @user = nil
  @password = nil
  @retry_count = 0
  @max_retries = 2
  @ssl = ssl
end

Instance Method Details

#authenticate(user, password) ⇒ String

Authenticate with Metasploit RPC

Parameters:

  • user (String)

    Username

  • password (String)

    Password

Returns:

  • (String)

    The resulting token if authentication successful

Raises:



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 36

def authenticate(user, password)
  # Store credentials for automatic re-authentication
  @user = user
  @password = password

  # Send authentication request directly (bypass retry logic)
  request_array = ['auth.login', user, password]
  response = send_request(request_array)

  # Real Metasploit API returns string keys
  if response['result'] == 'success' && response['token']
    @token = response['token']
  elsif response['error']
    raise AuthenticationError, response['error']
  else
    raise AuthenticationError, 'Authentication failed'
  end
end

#call_api(method, args = []) ⇒ Hash, Array

Call Metasploit RPC API method

Parameters:

  • method (String)

    API method name (e.g., ‘module.search’)

  • args (Array) (defaults to: [])

    Arguments to pass to the method (must be an array)

Returns:

  • (Hash, Array)

    API response

Raises:



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 63

def call_api(method, args = [])
  raise ArgumentError, "args must be an Array, got #{args.class}" unless args.is_a?(Array)

  begin
    raise AuthenticationError, 'Not authenticated' unless @token

    # Build request array: [method, token, *args]
    request_array = [method, @token, *args]

    # Send HTTP request
    send_request(request_array)

  rescue AuthenticationError => e
    # It is not possible to reauthenticate if we don't have credentials stored
    raise unless @user && @password
    # If reauthentication succeeded but the token is still invalid, we should not retry indefinitely
    raise unless @retry_count < @max_retries

    @retry_count += 1
    @token = nil

    begin
      wlog({ message: "#{method}': #{e.message}. Attempting to re-authenticate (#{@retry_count}/#{@max_retries})" },
          LOG_SOURCE, LOG_WARN)
      authenticate(@user, @password)
    rescue AuthenticationError => auth_e
      wlog({ message: "Re-authentication failed: #{auth_e.message}" },
          LOG_SOURCE, LOG_WARN)
      if @retry_count < @max_retries
        @retry_count += 1
        @token = nil
        retry
      end
      raise AuthenticationError, "Unable to authenticate after #{@retry_count} attempts: #{auth_e.message}"
    end

    # Retry the original request with new token
    retry
  end

rescue Msf::MCP::Error => e
  elog({ message: 'MessagePack API call error', context: { error: e.message } },
      LOG_SOURCE, LOG_ERROR)
  raise
ensure
  @retry_count = 0
end

#db_creds(options = {}) ⇒ Hash

Get credentials from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options

Returns:

  • (Hash)

    Response with ‘creds’ array



157
158
159
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 157

def db_creds(options = {})
  call_api('db.creds', [options])
end

#db_hosts(options = {}) ⇒ Hash

Get hosts from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options (workspace, limit, offset, etc.)

Returns:

  • (Hash)

    Response with ‘hosts’ array



129
130
131
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 129

def db_hosts(options = {})
  call_api('db.hosts', [options])
end

#db_loot(options = {}) ⇒ Hash

Get loot from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options

Returns:

  • (Hash)

    Response with ‘loots’ array



164
165
166
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 164

def db_loot(options = {})
  call_api('db.loots', [options])
end

#db_notes(options = {}) ⇒ Hash

Get notes from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options

Returns:

  • (Hash)

    Response with ‘notes’ array



150
151
152
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 150

def db_notes(options = {})
  call_api('db.notes', [options])
end

#db_services(options = {}) ⇒ Hash

Get services from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options

Returns:

  • (Hash)

    Response with ‘services’ array



136
137
138
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 136

def db_services(options = {})
  call_api('db.services', [options])
end

#db_vulns(options = {}) ⇒ Hash

Get vulnerabilities from database

Parameters:

  • options (Hash) (defaults to: {})

    Query options

Returns:

  • (Hash)

    Response with ‘vulns’ array



143
144
145
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 143

def db_vulns(options = {})
  call_api('db.vulns', [options])
end

#module_info(type, name) ⇒ Hash

Get module information

Parameters:

  • type (String)

    Module type (‘exploit’, ‘auxiliary’, ‘post’, etc.)

  • name (String)

    Module name

Returns:

  • (Hash)

    Module information



122
123
124
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 122

def module_info(type, name)
  call_api('module.info', [type, name])
end

#search_modules(query) ⇒ Array<Hash>

Search for Metasploit modules

Parameters:

  • query (String)

    Search query

Returns:

  • (Array<Hash>)

    Module metadata



114
115
116
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 114

def search_modules(query)
  call_api('module.search', [query])
end

#shutdownObject

Shutdown client and cleanup



169
170
171
172
173
174
175
# File 'lib/msf/core/mcp/metasploit/messagepack_client.rb', line 169

def shutdown
  @token = nil
  @user = nil
  @password = nil
  @http&.finish if @http&.started?
  @http = nil
end