Skip to content

Spike Windows version checks in exploit targets and payloads#21534

Open
sjanusz-r7 wants to merge 1 commit into
rapid7:masterfrom
sjanusz-r7:spike-improved-payload-matching
Open

Spike Windows version checks in exploit targets and payloads#21534
sjanusz-r7 wants to merge 1 commit into
rapid7:masterfrom
sjanusz-r7:spike-improved-payload-matching

Conversation

@sjanusz-r7
Copy link
Copy Markdown
Contributor

@sjanusz-r7 sjanusz-r7 commented Jun 3, 2026

This PR addresses #21320

This PR:

  • adds a minimum Windows version requirement to Windows Meterpreter payloads
  • outputs any required software versions when running the info command on a payload
  • tags the Python payloads as supporting Python 2.5+ only (no modules utilise this currently, but I added this to show that this approach is not strictly Windows Meterpreter-only)
  • tagged some targets for some ms modules with their versions => this seems cumbersome though, maybe we can spike out an improved pattern here? (potentially based on the target name? Or using actual Target objects, such as Msf::Targets::Windows_XP_SP1.new(ret: 0xFFFF) etc.)
  • adds a warning (not an outright failure) when selecting a payload or target that is incompatible with one another (not a hard error right now due to not all modules having this behaviour, so i think it is the safest to not break this workflow just yet)
  • adds unit and integration specs
  • adds the runtime version warnings when selecting a module, payload or target
    • selecting a module will now result in the first compatible payload. previously an exploit could select a default of Windows Meterpreter even when the target selected would be Windows XP SP1 etc.
    • when setting a payload with a target already selected, the warning will be output if it is not compatible
    • when setting a target with a payload specified, a warning will be shown if they are not compatible
  • maps the cryptic Windows build numbers to human-readable strings when outputting the payload version incompatibility warnings
  • adds the Windows 2000 Service Pack 4 constant to available Windows versions as it was used by some of the modified modules

Upper bounds or maximum supported versions are not implemented, e.g. MinimumVersion: Windows 7, MaximumVersion: Windows 7 SP 2

Examples

I'm using windows/smb/ms08_067_netapi for this example.

Setting payload

Warning on Meterpreter payload when targeting an old OS target, no warnings with a shell payload

msf exploit(windows/smb/ms08_067_netapi) > set target 1 (Windows 2000 Universal)
msf exploit(windows/smb/ms08_067_netapi) > set payload windows/meterpreter/reverse_tcp
[!] Payload requires Windows >= Windows XP Service Pack 2 (5.1.2600.2), but target provides Windows 2000 (5.0.2195)
payload => windows/meterpreter/reverse_tcp

msf exploit(windows/smb/ms08_067_netapi) > set payload windows/shell/reverse_tcp
payload => windows/shell/reverse_tcp

Setting target

msf exploit(windows/smb/ms08_067_netapi) > set target 7
target => 7 (windows XP SP3)
# no errors

msf exploit(windows/smb/ms08_067_netapi) > set payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
# No errors

msf exploit(windows/smb/ms08_067_netapi) > set target 1
[!] Payload requires Windows >= Windows XP Service Pack 2 (5.1.2600.2), but target provides Windows 2000 (5.0.2195)
target => 1
# Now warning when setting target after setting payload

Automatic target selection

This scenario will only output a warning if any of the module targets specify a version that is lower than the currently selected payload requirement:

msf exploit(windows/smb/ms08_067_netapi) > set target 0
[!] Payload requires Windows >= Windows XP Service Pack 2 (5.1.2600.2), but target provides Windows 2000 (5.0.2195)
target => 0
msf exploit(windows/smb/ms08_067_netapi) > set target 1
[!] Payload requires Windows >= Windows XP Service Pack 2 (5.1.2600.2), but target provides Windows 2000 (5.0.2195)
target => 1
msf exploit(windows/smb/ms08_067_netapi) > set target 39
target => 39

info command

msf payload(windows/x64/meterpreter/reverse_tcp) > info

             Name: Windows Meterpreter (Reflective Injection x64), Windows x64 Reverse TCP Stager
           Module: payload/windows/x64/meterpreter/reverse_tcp
         Platform: Windows
             Arch: x64
      Needs Admin: No
       Total size: 450
             Rank: Normal
Required Versions:
  Windows: 5.1.2600.2

Verification

  • Start msfconsole
  • use exploit/windows/smb/ms08_067_netapi
  • set target ...
  • set payload ...
  • Experiment with different Wdinows version targets and payloads (Meterpreter/shell etc.)
  • Use a payload module that has been modified, and confirm that the info command outputs the required versions
  • Run the rspec tests: bundle exec rspec spec/lib/msf/core/module/version_compatibility_spec.rb spec/integration/payload_version_compatibility/version_compatibility_integration_spec.rb

@sjanusz-r7 sjanusz-r7 force-pushed the spike-improved-payload-matching branch 5 times, most recently from e774820 to 11ad4a3 Compare June 4, 2026 15:24
@sjanusz-r7 sjanusz-r7 force-pushed the spike-improved-payload-matching branch from 11ad4a3 to 987c98f Compare June 4, 2026 17:06
@adfoster-r7 adfoster-r7 requested a review from Copilot June 5, 2026 11:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a “minimum runtime version” metadata signal (MinimumVersions on payloads, RuntimeVersions on targets) and uses it to (a) warn when a selected payload/target pair is likely incompatible and (b) prefer a compatible default payload when use-ing a module, addressing #21320.

Changes:

  • Adds a new Msf::Module::VersionCompatibility mixin that compares a payload’s MinimumVersions against the current target’s RuntimeVersions and emits warnings (including friendlier Windows version names).
  • Annotates Windows Meterpreter payloads with a minimum Windows version (XP SP2) and annotates a set of Windows exploit targets with Windows RuntimeVersions (plus a Python 2.5+ marker for Python Meterpreter as a non-Windows example).
  • Updates console flows (use, set payload, set target, show) and payload info output to surface version requirements/warnings, plus adds unit + integration specs.

Impact Analysis:

  • Blast radius: medium (core module base class mixin + console command dispatchers + default payload selection affect many interactive workflows; downstream consumers unknown).
  • Data and contract effects: adds new module metadata keys (MinimumVersions, RuntimeVersions) and changes CLI output (payload info and show descriptions may include warnings).
  • Rollback and test focus: focus on use default-payload selection, set TARGET/PAYLOAD warning behavior, and payload info output; rollback should be straightforward but CLI output differences may affect scripts.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
spec/lib/msf/core/module/version_compatibility_spec.rb Unit specs for the new version compatibility warning logic.
spec/integration/payload_version_compatibility/version_compatibility_integration_spec.rb Integration coverage using ms08_067_netapi targets and mocked payloads.
modules/payloads/stages/windows/patchupmeterpreter.rb Adds Windows minimum version metadata to staged x86 Meterpreter.
modules/payloads/singles/windows/metsvc_reverse_tcp.rb Adds Windows minimum version metadata to Meterpreter service reverse TCP single.
modules/payloads/singles/windows/metsvc_bind_tcp.rb Adds Windows minimum version metadata to Meterpreter service bind TCP single.
modules/exploits/windows/smb/smb_rras_erraticgopher.rb Adds Windows RuntimeVersions metadata to targets.
modules/exploits/windows/smb/ms17_010_eternalblue.rb Adds Windows RuntimeVersions metadata to OS-patterned targets.
modules/exploits/windows/smb/ms09_050_smb2_negotiate_func_index.rb Adds Windows RuntimeVersions metadata to the target.
modules/exploits/windows/smb/ms08_067_netapi.rb Adds Windows RuntimeVersions metadata across multiple targets.
modules/exploits/windows/smb/ms06_025_rasmans_reg.rb Adds Windows 2000 SP4 runtime version metadata to target.
modules/exploits/windows/smb/ms05_039_pnp.rb Adds Windows runtime version metadata to several language/SP-specific targets.
modules/exploits/windows/smb/ms04_031_netdde.rb Adds Windows 2000 SP4 runtime version metadata to target.
lib/msf/ui/console/command_dispatcher/modules.rb Emits version warnings during use/default payload selection and annotates show output with a warning.
lib/msf/ui/console/command_dispatcher/core.rb Emits version warnings when setting TARGET or PAYLOAD.
lib/msf/core/windows_version.rb Adds Win2000_SP4 constant and name mapping.
lib/msf/core/payload/windows/x64/meterpreter_loader_x64.rb Adds Windows minimum version metadata to x64 Meterpreter loader stage.
lib/msf/core/payload/windows/meterpreter_version.rb Introduces a single constant for the Meterpreter minimum Windows version (XP SP2).
lib/msf/core/payload/windows/meterpreter_loader.rb Adds Windows minimum version metadata to x86 Meterpreter loader stage.
lib/msf/core/payload/windows.rb Requires the new Windows Meterpreter minimum-version constant.
lib/msf/core/payload/python/meterpreter_version.rb Introduces a Python Meterpreter minimum version constant (2.5).
lib/msf/core/payload/python/meterpreter_loader.rb Wires Python MinimumVersions into Python Meterpreter loader.
lib/msf/core/payload.rb Skips preferred default payloads that warn as incompatible with the selected target.
lib/msf/core/module/version_compatibility.rb New mixin implementing runtime version comparison and warning formatting.
lib/msf/core/module.rb Includes the new version compatibility mixin into all modules.
lib/msf/base/serializer/readable_text.rb Extends payload info output to show Required Versions.

Comment on lines +503 to +508
required_versions = mod.instance_variable_get(:@module_info)['MinimumVersions']
if required_versions && required_versions.any?
output << "Required Versions:\n"
# No access to a friendly version name here
required_versions.map { |k, v| output << " #{k}: #{v}\n" }
end
Comment on lines +122 to +128
# Retrieve MinimumVersions from a payload instance.
#
# @param payload_instance [Msf::Payload] The payload to inspect.
# @return [Hash, nil] The MinimumVersions hash with OS names as the keys, or nil.
def payload_minimum_versions(payload_instance)
payload_instance.instance_variable_get(:@module_info)&.dig('MinimumVersions')
end
Comment on lines +48 to +62
# Map a runtime (Windows, Python etc.) and a version to a human-readable string.
# For example 'Windows', '5.1.2600.2' would get mapped to 'Windows XP Service Pack 2 (5.1.2600.2)'
#
# @param runtime [String] The runtime key (e.g., 'Windows', 'Python').
# @param version [Rex::Version] The version to look up.
# @return [String] A human-readable string
def human_readable_version_string(runtime, version)
case runtime
when 'Windows'
name = windows_version_name(version)
return "#{name} (#{version})" if name
end

"#{runtime} (#{version})"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

4 participants