Fetch Multi Part 2: The Fetchening#21384
Draft
bwatters-r7 wants to merge 4 commits into
Draft
Conversation
smcintyre-r7
reviewed
May 6, 2026
| end | ||
| end | ||
|
|
||
| def to_meterp_arch(os_arch) |
Contributor
There was a problem hiding this comment.
I think we should block this on rapid7/rex-arch#13
…in FETCH FILELESS
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a Linux multi-architecture “fetch” workflow intended to serve the correct Linux Meterpreter/Mettle binary based on the calling host’s architecture (via HTTP query strings), alongside broader refactors to fetch payload serving to support multiple served resources and new FTP delivery support.
Changes:
- Introduces a new Linux ARCH_ANY Meterpreter (stageless mettle) payload and supporting Linux multi-arch transform logic.
- Refactors fetch adapter/server plumbing to serve multiple resources per handler and adds dynamic-arch HTTP handling via
?arch=.... - Adds an in-memory anonymous FTP server plus many new FTP fetch adapter modules (Linux + Windows), and improves TFTP server resource cleanup.
Impact Analysis:
- Blast radius: high — shared fetch adapter logic (
lib/msf/core/payload/adapter/fetch.rb) and HTTP/TFTP/SMB handler mixins affect many fetch payloads and handler startup/cleanup paths; new FTP server introduces a new service type underRex::Proto. - Data and contract effects: medium — changes handler request expectations (dynamic-arch requires query string), modifies how resources are tracked/served (
@srv_resources), and introduces new options/behaviors that can change runtime payload generation and UUID/arch selection. - Rollback and test focus: rollback is code-only but touches core mixins; focus testing on (1) existing fetch payloads (HTTP/HTTPS/TFTP/SMB) still serving correctly, (2) multi-arch HTTP path with and without
archquery param, and (3) concurrent/multiple client fetches for differing architectures.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/modules/payloads_spec.rb | Adds spec coverage hooks for new cmd/linux/http/multi adapter and linux/multi payload caching behavior. |
| modules/payloads/singles/linux/multi/meterpreter_reverse_tcp.rb | New ARCH_ANY Linux stageless Meterpreter/Mettle payload using the new multi-arch logic. |
| modules/payloads/adapters/cmd/windows/ftp/x86.rb | New Windows x86 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/windows/ftp/x64.rb | New Windows x64 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/http/multi.rb | New Linux HTTP “multi” fetch adapter (ARCH_ANY) intended for dynamic arch selection. |
| modules/payloads/adapters/cmd/linux/ftp/x86.rb | New Linux x86 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/x64.rb | New Linux x64 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/riscv64le.rb | New Linux RISC-V 64-bit LE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/riscv32le.rb | New Linux RISC-V 32-bit LE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/ppc64.rb | New Linux PPC64 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/ppc.rb | New Linux PPC FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/mipsle.rb | New Linux MIPSLE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/mipsbe.rb | New Linux MIPSBE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/mips64.rb | New Linux MIPS64 FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/armle.rb | New Linux ARMLE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/armbe.rb | New Linux ARMBE FTP fetch adapter wrapper. |
| modules/payloads/adapters/cmd/linux/ftp/aarch64.rb | New Linux AARCH64 FTP fetch adapter wrapper. |
| lib/rex/proto/tftp/server.rb | Adds aliasing helpers and file deregistration support for TFTP service cleanup. |
| lib/rex/proto/ftp/server.rb | Adds a new lightweight in-memory anonymous FTP server implementation. |
| lib/msf/core/payload/linux/multi_arch.rb | Adds Linux multi-arch mapping helpers and REQUESTED_ARCH option for payload generation/UUID arch selection. |
| lib/msf/core/payload/adapter/fetch/tftp.rb | Refactors TFTP fetch handler setup to support multiple resources. |
| lib/msf/core/payload/adapter/fetch/smb.rb | Updates SMB fetch handler setup to pull served data from the new resource list. |
| lib/msf/core/payload/adapter/fetch/server/tftp.rb | Refactors TFTP server startup via Rex::ServiceManager and supports multiple resources + cleanup. |
| lib/msf/core/payload/adapter/fetch/server/http.rb | Adds dynamic-arch request handling (?arch=) and refactors HTTP serving to use resource entries. |
| lib/msf/core/payload/adapter/fetch/server/ftp.rb | New FTP fetch server mixin using the new in-memory FTP server. |
| lib/msf/core/payload/adapter/fetch/pipe.rb | New shared helper for pipe-enabled fetch payload command generation. |
| lib/msf/core/payload/adapter/fetch/multi.rb | New shared helper for multi-arch fetch behaviors (including OS-arch to meterpreter-arch mapping). |
| lib/msf/core/payload/adapter/fetch/https.rb | Refactors HTTPS fetch handler setup to serve from the new resource list. |
| lib/msf/core/payload/adapter/fetch/http.rb | Refactors HTTP fetch handler setup to serve from the new resource list. |
| lib/msf/core/payload/adapter/fetch/ftp.rb | New FTP fetch transport mixin wiring handler lifecycle to the FTP server mixin. |
| lib/msf/core/payload/adapter/fetch.rb | Core refactor: resource list (@srv_resources), dynamic-arch placeholder serving, and updated command generation plumbing. |
| lib/msf/base/sessions/meterpreter_multi_linux.rb | Adds a Linux platform-specific, arch-agnostic Meterpreter session class. |
| lib/msf_autoload.rb | Updates Zeitwerk inflections/camelization to support rex/proto/ftp module naming. |
Comment on lines
+38
to
+45
| when ARCH_PPCE500V2, 'ARCH_PPCE500V3' | ||
| return 'powerpc-e500v2-linux-musl' | ||
| when ARCH_PPC64LE, 'ARCH_PPC64LE' | ||
| return 'powerpc64le-linux-musl' | ||
| when ARCH_X64, 'ARCH_X86' | ||
| return 'x86_64-linux-musl' | ||
| when ARCH_X86, 'ARCH_X86' | ||
| return 'i486-linux-musl' |
Comment on lines
+80
to
+83
| vprint_status request.uri_parts['QueryString']['arch'].to_s | ||
| arch = to_meterp_arch(request.uri_parts['QueryString']['arch']) | ||
| if arch.nil? | ||
| print_error("Failed to identify the architecture in Query String #{request.uri_parts['QueryString']['arch'].to_s}") |
Comment on lines
+86
to
+91
| vprint_status("Building payload for #{arch.to_s} arch") | ||
| opts[:arch] = arch | ||
| @multi_arch = arch | ||
| vprint_status("2") | ||
| # Call generate with arch and dynamic_arch populated properly to build the right binary | ||
| payload_exe = generate(opts) |
Comment on lines
+142
to
+155
| def generate_fetch_commands(uri = srvuri, dynamic_arch = false) | ||
| case datastore['FETCH_COMMAND'].upcase | ||
| when 'FTP' | ||
| return _generate_ftp_command | ||
| return _generate_ftp_command(uri) | ||
| when 'TNFTP' | ||
| return _generate_tnftp_command | ||
| return _generate_tnftp_command(uri) | ||
| when 'WGET' | ||
| return _generate_wget_command | ||
| when 'GET' | ||
| return _generate_get_command | ||
| return _generate_wget_command(uri, dynamic_arch) | ||
| when 'CURL' | ||
| return _generate_curl_command | ||
| return _generate_curl_command(uri, dynamic_arch) | ||
| when 'TFTP' | ||
| return _generate_tftp_command | ||
| return _generate_tftp_command(uri) | ||
| when 'CERTUTIL' | ||
| return _generate_certutil_command | ||
| return _generate_certutil_command(uri) |
Comment on lines
166
to
181
| @@ -204,6 +176,7 @@ def generate_stage(opts = {}) | |||
| # @return [PayloadUUID] The generated payload UUID. | |||
| def generate_payload_uuid(conf = {}) | |||
| conf[:arch] ||= module_info['AdaptedArch'] | |||
| conf[:arch] = @multi_arch unless @multi_arch.nil? | |||
| conf[:platform] ||= module_info['AdaptedPlatform'] | |||
| super | |||
Comment on lines
+6
to
+22
| module MetasploitModule | ||
| include Msf::Payload::Adapter::Fetch::HTTP | ||
| include Msf::Payload::Adapter::Fetch::LinuxOptions | ||
|
|
||
| def initialize(info = {}) | ||
| super( | ||
| update_info( | ||
| info, | ||
| 'Name' => 'HTTP Fetch', | ||
| 'Description' => 'Fetch and execute a script to determine the host arch and execute a payload from an HTTP server.', | ||
| 'Author' => ['Brendan Watters', 'Spencer McIntyre'], | ||
| 'Platform' => 'linux', | ||
| 'Arch' => ARCH_CMD, | ||
| 'License' => MSF_LICENSE, | ||
| 'AdaptedArch' => ARCH_ANY, | ||
| 'AdaptedPlatform' => 'linux' | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is another shot at the fetch multi payloads that will automagically serve the proper arch of Linux payload regardless of what architecture calls back. Per request, it uses query strings, so it is only available on http-based fetch commands. It also only works with Linux right now, but as we do not have an AARCH64 Windows Meterpreter, that's probably fine for now.
Currently, this works, but probably a lot of the other fetch payloads are broken, so this is in draft. I also likely need to do a bit of cleanup for artifacts left over from other attempts.
Closes #21389
Example