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

Show errors on inaccessible payload files #18405

Merged

Conversation

sjanusz-r7
Copy link
Contributor

@sjanusz-r7 sjanusz-r7 commented Sep 27, 2023

This PR requires rapid7/metasploit-payloads#673
It allows for outputting error messages on startup if any Metasploit Payload files defined in the manifest file are missing or the user does not have read permissions for.
This PR also adds error messages when calling to_handler on a stageless payload, as well as when a payload reaches out for a stage that is not accessible.

Java Payload Sizes

The Java payload sizes are slightly different due Java compiler changes. Prior to this release we used

The changes are minimal; Small change in the try/if logic:

image

And some changes in the constant pool, verified with:

$ javap -v -c AESEncryption.class

... etc ...
Constant pool:
   #1 = Methodref          #24.#37        // java/lang/Object."<init>":()V
   #2 = Class              #38            // java/io/DataInputStream
   #3 = Methodref          #2.#39         // java/io/DataInputStream."<init>":(Ljava/io/InputStream;)V
   #4 = Methodref          #2.#40         // java/io/DataInputStream.readInt:()I
   #5 = Class              #41            // java/security/SecureRandom
   #6 = Methodref          #5.#37         // java/security/SecureRandom."<init>":()V
   #7 = Methodref          #5.#42         // java/security/SecureRandom.nextBytes:([B)V
   #8 = Methodref          #43.#44        // java/io/OutputStream.write:([B)V
   #9 = Methodref          #43.#45        // java/io/OutputStream.flush:()V
  #10 = Methodref          #2.#46         // java/io/DataInputStream.readFully:([B)V
  #11 = String             #47            // MD5
  #12 = Methodref          #48.#49        // java/security/MessageDigest.getInstance:(Ljava/lang/String;)Ljava/security/MessageDigest;
  #13 = Methodref          #50.#51        // java/lang/String.getBytes:()[B
  #14 = Methodref          #48.#52        // java/security/MessageDigest.digest:([B)[B
  #15 = String             #53            // AES/CFB8/NoPadding
  #16 = Methodref          #17.#54        // javax/crypto/Cipher.getInstance:(Ljava/lang/String;)Ljavax/crypto/Cipher;
  #17 = Class              #55            // javax/crypto/Cipher
  #18 = Class              #56            // javax/crypto/spec/SecretKeySpec
... etc ...

Diff:

  #16 = Methodref          #17.#54        // javax/crypto/Cipher.getInstance:(Ljava/lang/String;)Ljavax/crypto/Cipher;
-  #17 = Class              #55            // javax/crypto/spec/SecretKeySpec
+  #17 = Class              #55            // javax/crypto/Cipher
+  #18 = Class              #56            // javax/crypto/spec/SecretKeySpec

Verification

  • Start msfconsole
  • Ensure there are no startup error messages
  • Ensure you can get a session with payload/python/meterpreter/reverse_tcp normally
  • Exit msfconsole
  • In the local Metasploit Payloads gem, rename data/meterpreter/meterpreter.py to meterpreter.py2
  • Start msfconsole
  • Ensure you get a warning on startup that mentions missing meterpreter.py
  • Ensure use payload/python/meterpreter/reverse_tcp works
  • to_handler
  • Try to execute the payload on the target machine
  • Ensure you get an error: Meterpreter path meterpreter/meterpreter.py not found.
  • use payload/python/meterpreter_reverse_tcp (inline)
  • Ensure calling to_handler results in Meterpreter path meterpreter/meterpreter.py not found.
  • Ensure the errors are shown when calling log
  • Exit msfconsole
  • Change the meterpreter.py2 file back to meterpreter.py
  • Modify the meterpreter.py file with an additional empty line
  • Start msfconsole
  • Ensure you get a warning on startup that mentions a hash mismatch for meterpreter.py

Example Output

Staged

When the file is inaccessible, this is expected to fail when a payload reaches back to MSF Console for a stage.

msf6 payload(windows/meterpreter/reverse_tcp) > options

Module options (payload/windows/meterpreter/reverse_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique (Accepted: '', seh, thread, process, none)
   LHOST     192.168.112.1    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(windows/meterpreter/reverse_tcp) > to_handler
[*] Payload Handler Started as Job 0

[*] Started reverse TCP handler on 192.168.112.1:4444
-- Execute the payload on the target machine --
msf6 payload(windows/meterpreter/reverse_tcp) > [-] Meterpreter path meterpreter/metsrv.x86.dll not found. Ensure antivirus is not enabled, or reinstall Metasploit.

Stageless

When the file is inaccessible, this is expected to fail when calling to_handler.

msf6 payload(windows/x64/meterpreter_reverse_tcp) > options

Module options (payload/windows/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
   LHOST       192.168.207.1    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(windows/x64/meterpreter_reverse_tcp) > to_handler

[-] Exploit failed: Meterpreter path meterpreter/metsrv.x64.dll not found. Ensure antivirus is not enabled, or reinstall Metasploit.

@sjanusz-r7 sjanusz-r7 force-pushed the add-payloads-file-warnings-support branch 5 times, most recently from d601648 to 8efc6ca Compare October 2, 2023 10:37
@sjanusz-r7 sjanusz-r7 marked this pull request as draft October 2, 2023 11:49
@sjanusz-r7 sjanusz-r7 force-pushed the add-payloads-file-warnings-support branch from 8efc6ca to 618bd08 Compare October 2, 2023 11:53
@sjanusz-r7 sjanusz-r7 force-pushed the add-payloads-file-warnings-support branch from 618bd08 to e70f356 Compare October 2, 2023 13:46
@@ -58,7 +58,7 @@ def generate_jar(opts={})
jar = Rex::Zip::Jar.new
jar.add_sub("metasploit") if opts[:random]
jar.add_file("metasploit.dat", stager_config(opts))
jar.add_files(paths, MetasploitPayloads.path('java'))
jar.add_files(paths, ::MetasploitPayloads.path('java'))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For context: Without this change, the tests were failing with:

2) modules/payloads java/shell_reverse_tcp it should behave like payload cached size is consistent java/shell_reverse_tcp has a valid cached_size
     Failure/Error: generate_jar(opts).pack

     NameError:
       uninitialized constant Msf::Modules::Payload__Singles__Java__Shell_reverse_tcp::MetasploitModule::MetasploitPayloads
     Shared Example Group: "payload cached size is consistent" called from ./spec/modules/payloads_spec.rb:1555
     # ./modules/payloads/singles/java/shell_reverse_tcp.rb:39:in `block in generate_jar'
     # ./modules/payloads/singles/java/shell_reverse_tcp.rb:32:in `each'
     # ./modules/payloads/singles/java/shell_reverse_tcp.rb:32:in `generate_jar'
     # ./lib/msf/core/payload/java.rb:35:in `generate'

@sjanusz-r7 sjanusz-r7 marked this pull request as ready for review October 2, 2023 14:44
Comment on lines +366 to +371
begin
path = MetasploitPayloads.meterpreter_path(modname, suffix, debug: client.debug_build)
rescue ::StandardError => e
elog(e)
path = nil
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.

Without this change, some tests were failing with:

1.31) Failure/Error: expect(test_result).to include(acceptable_failure.value)

             expected "[-] Post failed: MetasploitPayloads::NotFoundError Meterpreter path D:/a/metasploit-framework/metasp...work/metasploit-framework/lib/msf/core/post.rb:28:in `setup'\r\n[*] Post module execution completed" to include "[-] [should raise a runtime exception if services doesnt exist] FAILED: should raise a runtime exception if services doesnt exist"
             Diff:
             @@ -1,11 +1,21 @@
             -[-] [should raise a runtime exception if services doesnt exist] FAILED: should raise a runtime exception if services doesnt exist
             +[-] Post failed: MetasploitPayloads::NotFoundError Meterpreter path D:/a/metasploit-framework/metasploit-framework/vendor/bundle/ruby/3.0.0/gems/metasploit-payloads-2.0.154/data/meterpreter/ext_server_extapi.jar not found. Ensure antivirus is not enabled, or reinstall Metasploit.
             +[-] Call stack:
             +[-]   D:/a/metasploit-framework/metasploit-framework/vendor/bundle/ruby/3.0.0/gems/metasploit-payloads-2.0.154/lib/metasploit-payloads.rb:112:in `meterpreter_path'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/rex/post/meterpreter/client_core.rb:366:in `use'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post_mixin.rb:321:in `block in meterpreter_session_incompatibility_reasons'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post_mixin.rb:316:in `each'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post_mixin.rb:316:in `meterpreter_session_incompatibility_reasons'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post_mixin.rb:226:in `session_incompatibility_reasons'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post_mixin.rb:58:in `setup'
             +[-]   D:/a/metasploit-framework/metasploit-framework/lib/msf/core/post.rb:28:in `setup'
             +[*] Post module execution completed
           # ./spec/acceptance/meterpreter_spec.rb:426:in `block (11 levels) in <top (required)>'
           # ./spec/acceptance/meterpreter_spec.rb:422:in `each'
           # ./spec/acceptance/meterpreter_spec.rb:422:in `block (10 levels) in <top (required)>'

@adfoster-r7
Copy link
Contributor

I now get warnings that I have custom meterpreter dlls:

c:\metasploit-framework>bundle exec ruby ./msfconsole -q
C:/tools/ruby30/lib/ruby/gems/3.0.0/gems/rex-core-0.1.31/lib/rex/compat.rb:381: warning: Win32API is deprecated after Ruby 1.9.1; use fiddle directly instead
WARNING: Local file c:/metasploit-framework/data/meterpreter/dump_sam.x64.debug.dll is being used
WARNING: Local files may be incompatible with the Metasploit Framework
WARNING: Local file c:/metasploit-framework/data/meterpreter/dump_sam.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/dump_sam.x86.debug.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/elevator.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_bofloader.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_espia.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_extapi.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_incognito.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_kiwi.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_lanattacks.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_peinjector.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_powershell.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_priv.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_priv.x86.debug.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_python.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_stdapi.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_unhook.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_winpmem.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/metsrv.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/screenshot.x64.dll is being used

Booting console then deleting the payload works:

msf6 payload(windows/meterpreter_reverse_tcp) > generate -f raw lhost=127.0.0.1
[-] Payload generation failed: Meterpreter path C:/tools/ruby30/lib/ruby/gems/3.0.0/gems/metasploit-payloads-2.0.154/data/meterpreter/metsrv.x86.dll not found. Ensure antivirus is not enabled, or reinstall Metasploit.

Using a stager when meterpreter dll isn't present:

msf6 payload(windows/meterpreter/reverse_tcp) > to_handler
[*] Payload Handler Started as Job 0
msf6 payload(windows/meterpreter/reverse_tcp) >
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444
[!] Failed to stage (127.0.0.1): Meterpreter path C:/tools/ruby30/lib/ruby/gems/3.0.0/gems/metasploit-payloads-2.0.154/data/meterpreter/metsrv.x86.dll not found. Ensure antivirus is not enabled, or reinstall Metasploit.

Verifying that local DLLs can still be used, even if the gem data was removed

msf6 payload(windows/x64/meterpreter/reverse_tcp) > generate -f exe -o shell.exe lhost=127.0.0.1
[*] Writing 7168 bytes to shell.exe...
msf6 payload(windows/x64/meterpreter/reverse_tcp) > to_handler
[*] Payload Handler Started as Job 0
msf6 payload(windows/x64/meterpreter/reverse_tcp) >
[!] You are binding to a loopback address by setting LHOST to 127.0.0.1. Did you want ReverseListenerBindAddress?
[*] Started reverse TCP handler on 127.0.0.1:4444
WARNING: Local file c:/metasploit-framework/data/meterpreter/metsrv.x64.dll is being used
[*] Sending stage (224326 bytes) to 127.0.0.1
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_stdapi.x64.dll is being used
WARNING: Local file c:/metasploit-framework/data/meterpreter/ext_server_priv.x64.dll is being used
[*] Meterpreter session 1 opened (127.0.0.1:4444 -> 127.0.0.1:49823) at 2023-10-03 02:45:56 -0700

@adfoster-r7 adfoster-r7 merged commit 14c42fc into rapid7:master Oct 3, 2023
55 checks passed
@adfoster-r7
Copy link
Contributor

Release Notes

Updates msfconsole to detect and warn users when Metasploit payloads may have been deleted by antivirus or similar. This functionality is currently behind a feature flag, which can be enabled with features set metasploit_payload_warnings true

@jharris-r7 jharris-r7 added rn-fix release notes fix rn-enhancement release notes enhancement rn-payload-enhancement release notes for enhanced payloads and removed rn-enhancement release notes enhancement rn-fix release notes fix labels Oct 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
rn-payload-enhancement release notes for enhanced payloads
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants