Meterpreter API and Extensions

Meterpreter extensions are located in metasploit-framework/lib/rex/post/meterpreter. It’s highly recommended to browse and open the files to understand the code and it’s style.

Extension ClientCore : core

Path

  • metasploit-framework/lib/rex/post/meterpreter/client_core.rb
  1. >> client.core
  2. => #<Rex::Post::Meterpreter::ClientCore:0x00000005f83388 @client=#<Session:meterpreter 192.168.0.18:55861 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">, @name="core">

use method is used to load meterpreter extensions which is used in the meterpreter console (ex. use sniffer, use mimikatz, etc )

Note: to list all loadable extensions in meterpreter console use use -l command.

From IRB console of the meterpreter, let’s try to use sniffer extension

  1. >> client.sniffer
  2. => nil

As you can see, it returns a nil because the sniffer extension hasn’t yet loaded.

Let’s try to load the extension

  1. >> client.use "sniffer"
  2. => nil

As you can see it returns a nil because the method use is available in the core extension not in the meterpreter client instance.

  • To load extension: load sniffer
  1. >> client.core.use "sniffer"
  2. => true
  3. >> client.sniffer
  4. => #<Rex::Post::Meterpreter::Extensions::Sniffer::Sniffer:0x000000142cc108 @client=#<Session:meterpreter 192.168.0.18:55861 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">, @name="sniffer">

To check all sniffer extension methods, go to metasploit-framework/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb

also, from IRB, get all methods as we know

  1. client.sniffer.methods

which returns an array of all available methods

  1. >> client.sniffer.methods
  2. => [:interfaces, :capture_start, :capture_stop, :capture_stats, :capture_release, :capture_dump, :capture_dump_read, :name, :name=, :client, :client=, :psych_to_yaml, :to_yaml, :to_yaml_properties, :blank?, :present?, :presence, :acts_like?, :to_param, :to_query, :try, :try!, :duplicable?, :deep_dup, :in?, :instance_values, :instance_variable_names, :to_json, :with_options, :html_safe?, :`, :dclone, :old_send, :as_json, :require_or_load, :require_dependency, :load_dependency, :load, :require, :unloadable, :assert_no_remainder, :decode_tlv, :decode_integer, :decode_timeticks, :decode_integer_value, :decode_uinteger_value, :build_integer, :decode_octet_string, :decode_ip_address, :decode_sequence, :decode_object_id, :decode_object_id_value, :encode_length, :encode_integer, :encode_tagged_integer, :integer_to_octets, :encode_null, :encode_exception, :encode_tlv, :encode_octet_string, :encode_sequence, :encode_object_id, :pretty_print, :pretty_print_cycle, :pretty_print_instance_variables, :pretty_print_inspect, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :select, :display, :sleep, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :gem, :class_eval, :pretty_inspect, :silence_warnings, :enable_warnings, :with_warnings, :silence_stderr, :silence_stream, :suppress, :capture, :silence, :quietly, :debugger, :breakpoint, :suppress_warnings, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
  • Getting available interfaces: sniffer_interfaces

which returns array of hashes

  1. client.sniffer.interfaces
  2. => [{"idx"=>1, "name"=>"\\Device\\NdisWanBh", "description"=>"WAN Miniport (Network Monitor)", "type"=>3, "mtu"=>1514, "wireless"=>false, "usable"=>true, "dhcp"=>false},
  3. {"idx"=>2, "name"=>"\\Device\\{DF8BF690-33F1-497F-89ED-A31C236FE8E3}", "description"=>"Intel(R) PRO/1000 MT Network Connection", "type"=>0, "mtu"=>1514, "wireless"=>false, "usable"=>true, "dhcp"=>true}]

Extension Stdapi::Fs : fs

Path

  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb
  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/fs
  1. >> client.fs
  2. => #<Rex::Post::Meterpreter::ObjectAliases:0x00000001db6ae0 @aliases={"dir"=>#<Class:0x00000001e09e70>, "file"=>#<Class:0x00000001e12890>, "filestat"=>#<Class:0x00000001db7530>, "mount"=>#<Rex::Post::Meterpreter::Extensions::Stdapi::Fs::Mount:0x00000001db6c48 @client=#<Session:meterpreter 192.168.0.18:57016 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">>}>

Dir class: dir.rb

One of the extensions available for fs is Dir located in metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb. Let’s to use some of its methods which we can know from client.fs.dir.methods or from source code.

  • Get current directory: pwd

    1. >> client.fs.dir.pwd
    2. => "C:\\Windows\\System32"
  • List all files and directories in the current directory ls

    1. client.fs.dir.entries
    2. client.fs.dir.entries_with_info
  • Change the current directory: cd

    1. >> client.fs.dir.chdir("c:\\")
    2. => 0
    3. >> client.fs.dir.pwd
    4. => "c:\\"
  • Create a new directory: mkdir

    1. >> client.fs.dir.mkdir("Rubyfu")
    2. => 0
    3. >> client.fs.dir.chdir("Rubyfu")
    4. => 0
    5. >> client.fs.dir.pwd
    6. => "c:\\Rubyfu"

File class: file.rb

Discover File class, let’s begin with a simple search. Try to download and download files.

  • Search
    1. client.fs.file.search("C:\\Users", "*.exe")

Extension Stdapi::Fs : sys

Path

  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb
  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/sys
  1. >> client.sys
  2. => #<Rex::Post::Meterpreter::ObjectAliases:0x00000001dcd600 @aliases={"config"=>#<Rex::Post::Meterpreter::Extensions::Stdapi::Sys::Config:0x00000001db69c8 @client=#<Session:meterpreter 192.168.0.18:57016 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">>, "process"=>#<Class:0x00000001db69a0>, "registry"=>#<Class:0x00000001db8ed0>, "eventlog"=>#<Class:0x00000001dc0e28>, "power"=>#<Class:0x00000001dc4398>}>

Config class: config.rb

  • Get User ID: getuid

    1. >> client.sys.config.getuid
    2. => "NT AUTHORITY\\SYSTEM"
  • Get system information

    1. >> client.sys.config.sysinfo
    2. => {"Computer"=>"WIN7-64-VICTIM", "OS"=>"Windows 7 (Build 7600).", "Architecture"=>"x64 (Current Process is WOW64)", "System Language"=>"en_US", "Domain"=>"WORKGROUP", "Logged On Users"=>2}
  • Check if current process is running as SYSTEM user

    1. >> client.sys.config.is_system?
    2. => true
  • Enables all possible privileges: getpriv

    1. >> client.sys.config.getprivs
    2. => ["SeDebugPrivilege", "SeIncreaseQuotaPrivilege", "SeSecurityPrivilege", "SeTakeOwnershipPrivilege", "SeLoadDriverPrivilege", "SeSystemProfilePrivilege", "SeSystemtimePrivilege", "SeProfileSingleProcessPrivilege", "SeIncreaseBasePriorityPrivilege", "SeCreatePagefilePrivilege", "SeBackupPrivilege", "SeRestorePrivilege", "SeShutdownPrivilege", "SeSystemEnvironmentPrivilege", "SeChangeNotifyPrivilege", "SeRemoteShutdownPrivilege", "SeUndockPrivilege", "SeManageVolumePrivilege"]

Process class: process.rb

  • Get the current Process ID: getpid

    1. >> client.sys.process.getpid
    2. => 2392
  • Get all exist processes with its details (pid, ppid, name, path, session, user, arch): ps

    1. client.sys.process.get_processes
    2. # Or
    3. client.sys.process.processes

Extension Stdapi::Fs : net

Path

  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb
  • metasploit-framework/lib/rex/post/meterpreter/extensions/stdapi/net
  1. >> client.net
  2. => #<Rex::Post::Meterpreter::ObjectAliases:0x00000001dcd3d0 @aliases={"config"=>#<Rex::Post::Meterpreter::Extensions::Stdapi::Net::Config:0x00000001dcd4e8 @client=#<Session:meterpreter 192.168.0.18:57016 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">>, "socket"=>#<Rex::Post::Meterpreter::Extensions::Stdapi::Net::Socket:0x00000001dcd4c0 @client=#<Session:meterpreter 192.168.0.18:57016 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">>, "resolve"=>#<Rex::Post::Meterpreter::Extensions::Stdapi::Net::Resolve:0x00000001dcd470 @client=#<Session:meterpreter 192.168.0.18:57016 (192.168.242.128) "win7-64-victim\Workshop @ WIN7-64-VICTIM">>}>
  • Get the current victim interfaces: ifconfig or ipconfig

    1. client.net.config.get_interfaces
    2. # Or
    3. client.net.config.interfaces
    4. # Try nicer outputs
    5. >> puts client.net.config.interfaces[0].pretty
    6. Interface 11
    7. ============
    8. Name : Intel(R) PRO/1000 MT Network Connection
    9. Hardware MAC : 00:0c:29:ff:fa:10
    10. MTU : 1500
    11. IPv4 Address : 192.168.242.128
    12. IPv4 Netmask : 255.255.255.0
    13. IPv6 Address : fe80::482c:27b5:6914:e813
    14. IPv6 Netmask : ffff:ffff:ffff:ffff::
  • Get network stat: netstat

    1. client.net.config.netstat
  • Get the ARP table: arp

    1. client.net.config.arp_table
    2. client.net.config.arp_table[0].ip_addr # IP address
    3. client.net.config.arp_table[0].mac_addr # MAC address
    4. client.net.config.arp_table[0].interface # Interface
  • Routes: route

    1. client.net.config.routes # List routes
    2. client.net.config.add_route("192.168.2.0", 24, "192.168.2.1") # Add route
  • Get Proxy settings: getproxy

    1. client.net.config.get_proxy_config

As you can see how easy to get familiar with meterpreter API. there are other extensions you can play with

  1. meterpreter > use -l
  2. espia
  3. extapi
  4. incognito
  5. kiwi
  6. lanattacks
  7. mimikatz
  8. priv
  9. python
  10. sniffer
  11. stdapi

You can add more about those too in Rubyfu!