Support multiple suffixes on meterpreter extensions.

MS-2855/keylogger-mettle-extension
Pearce Barry 2017-10-12 11:00:24 -05:00
parent daf2acc2b1
commit 48975a4327
No known key found for this signature in database
GPG Key ID: 0916F4DEA5C5DE0A
5 changed files with 75 additions and 21 deletions

View File

@ -635,24 +635,24 @@ class Meterpreter < Rex::Post::Meterpreter::Client
# Platform-agnostic archs go first # Platform-agnostic archs go first
case self.arch case self.arch
when 'java' when 'java'
'jar' ['jar']
when 'php' when 'php'
'php' ['php']
when 'python' when 'python'
'py' ['py']
else else
# otherwise we fall back to the platform # otherwise we fall back to the platform
case self.platform case self.platform
when 'windows' when 'windows'
"#{self.arch}.dll" ["#{self.arch}.dll"]
when 'linux' , 'aix' , 'hpux' , 'irix' , 'unix' when 'linux' , 'aix' , 'hpux' , 'irix' , 'unix'
'bin' ['bin', 'elf']
when 'android', 'java' when 'android', 'java'
'jar' ['jar']
when 'php' when 'php'
'php' ['php']
when 'python' when 'python'
'py' ['py']
else else
nil nil
end end

View File

@ -249,7 +249,14 @@ class ClientCore < Extension
# path of the local and target so that it gets loaded with a random # path of the local and target so that it gets loaded with a random
# name # name
if opts['Extension'] if opts['Extension']
library_path = "ext#{rand(1000000)}.#{client.binary_suffix}" if client.binary_suffix.size > 1
m = /(.*)\.(.*)/.match(library_path)
suffix = $2
else
suffix = client.binary_suffix
end
library_path = "ext#{rand(1000000)}.#{suffix}"
target_path = library_path target_path = library_path
end end
end end
@ -296,6 +303,20 @@ class ClientCore < Extension
raise RuntimeError, "No modules were specified", caller raise RuntimeError, "No modules were specified", caller
end end
modnameprovided = mod
suffix = nil
if client.binary_suffix.size > 1
client.binary_suffix.each { |s|
if (mod =~ /(.*)\.#{s}/ )
mod = $1
suffix = s
break
end
}
else
suffix = client.binary_suffix.first
end
# Query the remote instance to see if commands for the extension are # Query the remote instance to see if commands for the extension are
# already loaded # already loaded
commands = get_loaded_extension_commands(mod.downcase) commands = get_loaded_extension_commands(mod.downcase)
@ -306,14 +327,14 @@ class ClientCore < Extension
# Get us to the installation root and then into data/meterpreter, where # Get us to the installation root and then into data/meterpreter, where
# the file is expected to be # the file is expected to be
modname = "ext_server_#{mod.downcase}" modname = "ext_server_#{mod.downcase}"
path = MetasploitPayloads.meterpreter_path(modname, client.binary_suffix) path = MetasploitPayloads.meterpreter_path(modname, suffix)
if opts['ExtensionPath'] if opts['ExtensionPath']
path = ::File.expand_path(opts['ExtensionPath']) path = ::File.expand_path(opts['ExtensionPath'])
end end
if path.nil? if path.nil?
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller raise RuntimeError, "No module of the name #{modnameprovided} found", caller
end end
# Load the extension DLL # Load the extension DLL

View File

@ -45,9 +45,19 @@ class Priv < Extension
elevator_name = Rex::Text.rand_text_alpha_lower( 6 ) elevator_name = Rex::Text.rand_text_alpha_lower( 6 )
elevator_path = MetasploitPayloads.meterpreter_path('elevator', client.binary_suffix) elevator_path = nil
client.binary_suffix.each { |s|
elevator_path = MetasploitPayloads.meterpreter_path('elevator', s)
if !elevator_path.nil?
break
end
}
if elevator_path.nil? if elevator_path.nil?
raise RuntimeError, "elevator.#{binary_suffix} not found", caller elevators = ""
client.binary_suffix.each { |s|
elevators << "elevator.#{s}, "
}
raise RuntimeError, "#{elevators.chomp(', ')} not found", caller
end end
elevator_data = "" elevator_data = ""

View File

@ -1151,8 +1151,16 @@ class Console::CommandDispatcher::Core
gem_path = MetasploitPayloads.local_meterpreter_dir gem_path = MetasploitPayloads.local_meterpreter_dir
[msf_path, gem_path].each do |path| [msf_path, gem_path].each do |path|
::Dir.entries(path).each { |f| ::Dir.entries(path).each { |f|
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) if (::File.file?(::File.join(path, f)))
exts.add($1) client.binary_suffix.each { |s|
if (f =~ /ext_server_(.*)\.#{s}/ )
if (client.binary_suffix.size > 1)
exts.add($1 + ".#{s}")
else
exts.add($1)
end
end
}
end end
} }
end end
@ -1168,7 +1176,16 @@ class Console::CommandDispatcher::Core
# Load each of the modules # Load each of the modules
args.each { |m| args.each { |m|
md = m.downcase md = m.downcase
modulenameprovided = md
if client.binary_suffix.size > 1
client.binary_suffix.each { |s|
if (md =~ /(.*)\.#{s}/ )
md = $1
break
end
}
end
if (extensions.include?(md)) if (extensions.include?(md))
print_error("The '#{md}' extension has already been loaded.") print_error("The '#{md}' extension has already been loaded.")
next next
@ -1178,7 +1195,7 @@ class Console::CommandDispatcher::Core
begin begin
# Use the remote side, then load the client-side # Use the remote side, then load the client-side
if (client.core.use(md) == true) if (client.core.use(modulenameprovided) == true)
add_extension_client(md) add_extension_client(md)
end end
rescue rescue
@ -1199,10 +1216,16 @@ class Console::CommandDispatcher::Core
gem_path = MetasploitPayloads.local_meterpreter_dir gem_path = MetasploitPayloads.local_meterpreter_dir
[msf_path, gem_path].each do |path| [msf_path, gem_path].each do |path|
::Dir.entries(path).each { |f| ::Dir.entries(path).each { |f|
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ ) if (::File.file?(::File.join(path, f)))
if (not extensions.include?($1)) client.binary_suffix.each { |s|
tabs.add($1) if (f =~ /ext_server_(.*)\.#{s}/ )
end if (client.binary_suffix.size > 1 && !extensions.include?($1 + ".#{s}"))
tabs.add($1 + ".#{s}")
elsif (!extensions.include?($1))
tabs.add($1)
end
end
}
end end
} }
end end

View File

@ -14,7 +14,7 @@ RSpec.describe Rex::Post::Meterpreter::ClientCore do
allow(@response).to receive(:result) { 0 } allow(@response).to receive(:result) { 0 }
allow(@response).to receive(:each) { [:help] } allow(@response).to receive(:each) { [:help] }
@client = double("client") @client = double("client")
allow(@client).to receive(:binary_suffix) { "x64.dll" } allow(@client).to receive(:binary_suffix) { ["x64.dll"] }
allow(@client).to receive(:capabilities) { {:ssl => false, :zlib => false } } allow(@client).to receive(:capabilities) { {:ssl => false, :zlib => false } }
allow(@client).to receive(:response_timeout) { 1 } allow(@client).to receive(:response_timeout) { 1 }
allow(@client).to receive(:send_packet_wait_response) { @response } allow(@client).to receive(:send_packet_wait_response) { @response }