Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/post/meterpreter/command_mapper.rb
Views: 11784
# -*- coding: binary -*-12require 'rex/post/meterpreter/extension_mapper'3require 'rex/post/meterpreter/core_ids'4require 'rex/post/meterpreter/client_core'56module Rex7module Post8module Meterpreter910class CommandMapper11@@cached_tlv_types = {}1213# Get the numeric command ID for the specified command name.14#15# @param [String] name The name of the command to retrieve the ID for. This16# parameter is case insensitive.17# @return [Integer, nil] The command ID or nil if the name does not exist.18def self.get_command_id(name)19name = name.downcase2021return nil unless name.include?('_')2223mod_name, cmd_name = name.split('_', 2)24if mod_name == 'core'25mod = Rex::Post::Meterpreter26else27mod = Rex::Post::Meterpreter::ExtensionMapper.get_extension_module(mod_name)28end2930return nil unless mod3132const_name = "COMMAND_ID_#{mod_name.upcase}_#{cmd_name.upcase}"33return nil unless mod.const_defined?(const_name)3435mod.const_get(const_name)36end3738# Get the string command name for the specified command ID.39#40# @param [Integer] id The ID of the command to retrieve the name for.41# @return [String, nil] The command name or nil if the ID does not exist.42def self.get_command_name(id)43extension_id = id - (id % COMMAND_ID_RANGE)44if extension_id == Rex::Post::Meterpreter::ClientCore.extension_id # this is the meterpreter core which is not exactly an extension.45mod = Rex::Post::Meterpreter46else47mod_name = Rex::Post::Meterpreter::ExtensionMapper.get_extension_name(extension_id)48mod = Rex::Post::Meterpreter::ExtensionMapper.get_extension_module(mod_name)49end5051return nil unless mod5253command_name = mod.constants.select { |c| c.to_s.start_with?('COMMAND_ID_') }.find { |c| id == mod.const_get(c) }5455return nil unless command_name5657command_name.to_s.delete_prefix('COMMAND_ID_').downcase58end5960# Get all of the string command names for the specified extensions.61#62# @param [Array<String>] extensions The names of the extensions to retrieve63# all of the command names for. The extension names are case insensitive. If64# no extensions are specified, all extensions will be enumerated.65# @return [Array<String>] An array of all of the enumerated command names.66def self.get_command_names(*extensions)67self.get_commands(*extensions).keys68end6970# Get a hash of all command name strings mapped to their numeric IDs.71#72# @param [Array<String>] extensions The names of the extensions to retrieve73# all of the commands for. The extension names are case insensitive. If74# no extensions are specified, all extensions will be enumerated.75# @return [Hash<String, Integer>] An hash of all of the enumerated commands.76def self.get_commands(*extensions)77extensions = ['core'] + Rex::Post::Meterpreter::ExtensionMapper.get_extension_names if extensions.empty?7879commands = {}80extensions.each do |mod_name|81mod_name = mod_name.downcase8283if mod_name == 'core'84mod = Rex::Post::Meterpreter85else86begin87mod = Rex::Post::Meterpreter::ExtensionMapper.get_extension_module(mod_name)88rescue RuntimeError89next90end91end9293constants = mod.constants.select { |name| name.to_s.start_with?("COMMAND_ID_#{mod_name.upcase}") }94commands.merge!(constants.map { |name| [name.to_s.delete_prefix('COMMAND_ID_').downcase, mod.const_get(name)] }.to_h)95end9697commands98end99100101# Get the TLV Type symbols that are defined with the value102# Potential return values are [], [:TLV_TYPE_A], and [:TLV_TYPE_A, :PACKET_TYPE_B]103#104# Returning an array is a solution to having multiple TLV types having the same value, as documented here:105# https://github.com/rapid7/metasploit-framework/issues/16267106#107# @param Integer value The value of the TLV type to retrieve the TLV type names for.108# @return [Array<Symbol>] An array of symbols of all TLV types that are defined with the value. Can be empty.109def self.get_tlv_names(value)110return @@cached_tlv_types[value] unless @@cached_tlv_types[value].nil? || @@cached_tlv_types[value].empty?111112# Default to arrays that contain TLV Types, so that we only deal with one data type113@@cached_tlv_types = Hash.new { |h, k| h[k] = Set.new }114115available_modules = [116::Rex::Post::Meterpreter,117*::Rex::Post::Meterpreter::ExtensionMapper.get_extension_klasses,118# Railgun is a special case that defines extra TLV_TYPES inside an extension119Rex::Post::Meterpreter::Extensions::Stdapi::Railgun120].uniq121122available_modules.each do |mod|123mod.constants.each do |const|124next unless const.to_s.start_with?('TLV_TYPE_') || const.to_s.start_with?('PACKET_')125126@@cached_tlv_types[mod.const_get(const)] << const127end128end129130@@cached_tlv_types[value]131end132end133134end135end136end137138139