Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
9164e15
First pass of TLV-based configuration and MC2
OJ Jul 7, 2025
1675458
"Working" C2 sessions with diff GET/POST uris
OJ Jul 10, 2025
ab29296
Payload wrapping support and more
OJ Jul 15, 2025
78b0fd8
Add C2 packet support to the stageless transition
OJ Jul 16, 2025
39cc6ca
Tidy and refactor of some C2 code
OJ Jul 16, 2025
50f2b52
Wire in support for C2 profiles in the x64 payload
OJ Jul 16, 2025
2829533
Small code tidy
OJ Jul 17, 2025
d538f2d
Small fix for non-c2 profile payloads
OJ Jul 17, 2025
0008175
C2 profile persistence and better UUID handling
OJ Jul 23, 2025
b760e0a
Remove query string from POST request body
OJ Jul 24, 2025
97ebb56
Change support for connection IDs in the HTTP server
OJ Jul 24, 2025
1b2442c
Fix a failing test
smcintyre-r7 Jul 1, 2026
c6d2c1f
Push CID finding into reverse_http
OJ Jul 24, 2025
8da1c69
Fix C2 config timeout generation
OJ Jul 28, 2025
d63b076
Fix transport comment TLV generation/handling
OJ Jul 28, 2025
07f2939
Re-add the overridden body property in the HTTP packet
OJ Jul 28, 2025
931a485
Prepends should not be reversed
OJ Jul 28, 2025
f449af2
Fixes as per discussion
OJ Jul 29, 2025
82380eb
Add C2 custom header support in responses
OJ Jul 29, 2025
6c73a46
Revert previous change to cid extraction
OJ Jul 30, 2025
5b0d87d
Support encoding/decoding of data from C2 profile
OJ Jul 30, 2025
1a2c0bd
Support escaped double-quote
OJ Jul 30, 2025
f9990a2
Fix old payloads
zeroSteiner Sep 23, 2025
e54e9b7
Handle IPv6 addresses in the URL
zeroSteiner Sep 26, 2025
e2cd130
Switch PROXY_HOST to PROXY_URL which is more accurate
zeroSteiner Sep 26, 2025
a63cc50
Ensure slashes are where they need to be
zeroSteiner Oct 1, 2025
90038c3
Add C2 profile support to win https
OJ Mar 21, 2026
1b7d86d
Fix bug unwrapping bytes in post
OJ Mar 21, 2026
851b779
Fix hex escape parasing in C2 profile string handling
OJ Mar 21, 2026
b248314
Simplify prefix/suffix checks
OJ Mar 21, 2026
b44172b
Short-circuit on first match of directives
OJ Mar 21, 2026
e3c6c0a
Fix base_uri mutation
OJ Mar 21, 2026
e1f231f
Extract GET/POST TLV builders
OJ Mar 22, 2026
b4d6074
Fix stale C2 profile configuration
OJ Mar 22, 2026
08930ac
Change MALLEABLEC2 option type to OptPath
dledda-r7 Mar 27, 2026
94b5e78
Change MALLEABLEC2 option type to OptPath
dledda-r7 Mar 27, 2026
278900d
Fix a staging-related URI problem
smcintyre-r7 Jul 1, 2026
9ba0e11
Support MC2 in python
OJ Mar 21, 2026
f7aafe6
Refactor config gen
OJ Mar 24, 2026
5ec1fc2
Add support for HTTP/S PHP and TLV config
OJ Mar 24, 2026
4a5fe56
Remove emails from source
OJ Mar 24, 2026
bf781a9
Config block support for mettle
OJ Mar 26, 2026
1f0bf60
Restore android stageless via TLV
OJ May 13, 2026
1472c4d
Fix custom_headers emission, add C2 UUID for placement
OJ May 13, 2026
aa220bb
Support mc2 in transport_* commands
OJ May 13, 2026
428f34f
Add stagless payloads for Java
OJ May 13, 2026
f0dc4a7
Add debug output for incoming MC2 payloads
OJ May 19, 2026
492c030
Fix MC2 payload gen
OJ May 19, 2026
a01c8d4
Fix mettle config generation
OJ May 19, 2026
2b7e6d4
Wire MC2 into PHP payloads
OJ May 19, 2026
b60e645
Remove debug log and fix uuid loading in C2
OJ May 19, 2026
b130aa9
Add IN/OUTBOUND encoding to correctly handle encoding
OJ May 20, 2026
6c88462
Wire MC2 into mettle
OJ May 20, 2026
44b3b63
Correctly handle UUID encoding/decoding
OJ May 20, 2026
3da3c71
Move to STRING instead of RAW for UUID prefix/suffix
OJ May 20, 2026
068e9c4
Support stageless java payloads
OJ May 20, 2026
509c38e
Add support for stageless extension wiring
OJ May 20, 2026
7627ef1
Add stageless extension support to mettle
OJ May 20, 2026
45f33dc
Fallback to global UA if not present in profile
OJ Jun 8, 2026
8c1a36c
Fix connd_id to session map and C2 comment handling
OJ Jun 9, 2026
932962b
Tolerate unsupported C2 blocks and split multi-URI directives
OJ Jun 16, 2026
69a5e60
Add fetch-payload fix as per Diego's comments
OJ Jun 16, 2026
1b2f8f7
Merge remote-tracking branch 'upstream/6.5' into 6.5.0-prerelease-build
adfoster-r7 Jul 3, 2026
8c0d35f
Merge remote-tracking branch 'upstream/pr/21483' into 6.5.0-prereleas…
adfoster-r7 Jul 3, 2026
df91190
Add https://patch-diff.githubusercontent.com/raw/OJ/metasploit-framew…
adfoster-r7 Jul 3, 2026
6beb47c
Use pre1
adfoster-r7 Jul 3, 2026
4d91576
Remove non-ascii chars
adfoster-r7 Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ PATH
metasploit-concern
metasploit-credential (>= 6.0.21)
metasploit-model
metasploit-payloads (= 2.0.245)
metasploit-payloads (= 2.0.246.pre.3)
metasploit_data_models (>= 6.0.15)
metasploit_payloads-mettle (= 1.0.46)
metasploit_payloads-mettle (= 1.0.48.pre.2)
mqtt
msgpack (~> 1.6.0)
mutex_m
Expand Down Expand Up @@ -369,7 +369,7 @@ GEM
drb
mutex_m
railties (>= 7.0, < 8.1)
metasploit-payloads (2.0.245)
metasploit-payloads (2.0.246.pre.3)
metasploit_data_models (6.0.18)
activerecord (>= 7.0, < 8.1)
activesupport (>= 7.0, < 8.1)
Expand All @@ -383,7 +383,7 @@ GEM
railties (>= 7.0, < 8.1)
recog
webrick
metasploit_payloads-mettle (1.0.46)
metasploit_payloads-mettle (1.0.48.pre.2)
method_source (1.1.0)
mime-types (3.7.0)
logger
Expand Down
10 changes: 5 additions & 5 deletions db/modules_metadata_base.json
Original file line number Diff line number Diff line change
Expand Up @@ -66658,7 +66658,7 @@
"disclosure_date": null,
"type": "encoder",
"author": [
"OJ Reeves <oj@buffered.io>"
"OJ Reeves"
],
"description": "Encodes a payload using a series of SUB instructions and writing the\n encoded value to ESP. This concept is based on the known SUB encoding\n approach that is widely used to manually encode payloads with very\n restricted allowed character sets. It will not reset EAX to zero unless\n absolutely necessary, which helps reduce the payload by 10 bytes for\n every 4-byte chunk. ADD support hasn't been included as the SUB\n instruction is more likely to avoid bad characters anyway.\n\n The payload requires a base register to work off which gives the start\n location of the encoder payload in memory. If not specified, it defaults\n to ESP. If the given register doesn't point exactly to the start of the\n payload then an offset value is also required.\n\n Note: Due to the fact that many payloads use the FSTENV approach to\n get the current location in memory there is an option to protect the\n start of the payload by setting the 'OverwriteProtect' flag to true.\n This adds 3-bytes to the start of the payload to bump ESP by 32 bytes\n so that it's clear of the top of the payload.",
"references": [],
Expand Down Expand Up @@ -86684,7 +86684,7 @@
"disclosure_date": "2015-03-01",
"type": "exploit",
"author": [
"OJ Reeves <oj@beyondbinary.io>"
"OJ Reeves"
],
"description": "Some Seagate Business NAS devices are vulnerable to command execution via a local\n file include vulnerability hidden in the language parameter of the CodeIgniter\n session cookie. The vulnerability manifests in the way the language files are\n included in the code on the login page, and hence is open to attack from users\n without the need for authentication. The cookie can be easily decrypted using a\n known static encryption key and re-encrypted once the PHP object string has been\n modified.\n\n This module has been tested on the STBN300 device.",
"references": [
Expand Down Expand Up @@ -189649,7 +189649,7 @@
"author": [
"superkojiman",
"PsychoSpy <neinwechter@gmail.com>",
"OJ Reeves <oj@buffered.io>"
"OJ Reeves"
],
"description": "This module exploits a stack based buffer overflow in Ultra Mini HTTPD 1.21,\n allowing remote attackers to execute arbitrary code via a long resource name in an HTTP\n request. This exploit has to deal with the fact that the application's request handler\n thread is terminated after 60 seconds by a \"monitor\" thread. To do this, it allocates\n some RWX memory, copies the payload to it and creates another thread. When done, it\n terminates the current thread so that it doesn't crash and hence doesn't bring down\n the process with it.",
"references": [
Expand Down Expand Up @@ -207276,7 +207276,7 @@
"author": [
"Sean Dillon <sean.dillon@risksense.com>",
"Ryan Hanson",
"OJ Reeves <oj@beyondbinary.io>",
"OJ Reeves",
"Brent Cook <bcook@rapid7.com>"
],
"description": "The RDP termdd.sys driver improperly handles binds to internal-only channel MS_T120,\n allowing a malformed Disconnect Provider Indication message to cause use-after-free.\n With a controllable data/size remote nonpaged pool spray, an indirect call gadget of\n the freed channel is used to achieve arbitrary code execution.\n\n Windows 7 SP1 and Windows Server 2008 R2 are the only currently supported targets.\n\n Windows 7 SP1 should be exploitable in its default configuration, assuming your target\n selection is correctly matched to the system's memory layout.\n\n HKLM\\SYSTEM\\CurrentControlSet\\Control\\TerminalServer\\Winstations\\RDP-Tcp\\fDisableCam\n *needs* to be set to 0 for exploitation to succeed against Windows Server 2008 R2.\n This is a non-standard configuration for normal servers, and the target will crash if\n the aforementioned Registry key is not set!\n\n If the target is crashing regardless, you will likely need to determine the non-paged\n pool base in kernel memory and set it as the GROOMBASE option.",
Expand Down Expand Up @@ -311249,4 +311249,4 @@
"needs_cleanup": null,
"actions": []
}
}
}
66 changes: 56 additions & 10 deletions lib/msf/base/sessions/mettle_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,61 @@ def generate_config(opts = {})

opts[:uuid] ||= generate_payload_uuid

case opts[:scheme]
when 'http'
opts[:uri] = generate_http_uri(transport_config_reverse_http(opts))
when 'https'
opts[:uri] = generate_http_uri(transport_config_reverse_https(opts))
when 'tcp'
opts[:uri] = generate_tcp_uri(transport_config_reverse_tcp(opts))
else
raise ArgumentError, "Unknown scheme: #{opts[:scheme]}"
unless opts[:transport_config]
if opts[:stageless] == true
case opts[:scheme]
when 'http'
opts[:transport_config] = [transport_config_reverse_http(opts)]
when 'https'
opts[:transport_config] = [transport_config_reverse_https(opts)]
when 'tcp'
opts[:transport_config] = [transport_config_reverse_tcp(opts)]
else
raise ArgumentError, "Unknown scheme: #{opts[:scheme]}"
end
else
# Staged payloads inherit the stager's socket (fd transport);
# the stage must not synthesise its own C2 transport. Use an
# explicit empty array ([] is truthy, so the build is skipped).
opts[:transport_config] = []
end
end

# Generate the TLV config block
config_opts = {
ascii_str: true,
null_session_guid: opts[:stageless] == true,
expiration: (ds[:expiration] || ds['SessionExpirationTimeout']).to_i,
uuid: opts[:uuid],
transports: opts[:transport_config],
extensions: opts[:extensions] || [],
ext_format: 'bin',
mettle_platform: opts[:mettle_platform],
stageless: opts[:stageless] == true,
}.merge(meterpreter_logging_config(opts))

config = Rex::Payloads::Meterpreter::Config.new(config_opts)
opts[:config_block] = config.to_b

# Mettle reserves a fixed 8 KB slot in the binary for the config
# block. Catch the overflow here with a useful message instead of
# letting the gem's `to_binary` raise a generic "config block too
# large" -- baked-in EXTENSIONS= is the usual culprit.
if opts[:config_block].length > MetasploitPayloads::Mettle::CONFIG_BLOCK_MAX
raise ArgumentError, "Mettle config block (#{opts[:config_block].length} bytes) exceeds the #{MetasploitPayloads::Mettle::CONFIG_BLOCK_MAX}-byte embedded slot. " \
"Drop EXTENSIONS= and `load <ext>` once the session is up."
end

# Keep the legacy CLI config for backward compatibility during
# transition. Skipped for staged payloads, which have no transport.
transport = opts[:transport_config].first
if transport
case opts[:scheme]
when 'http', 'https'
opts[:uri] = generate_http_uri(transport)
when 'tcp'
opts[:uri] = generate_tcp_uri(transport)
end
end

opts[:uuid] = Base64.encode64(opts[:uuid].to_raw).strip
Expand All @@ -114,7 +160,7 @@ def generate_config(opts = {})
end
opts[:session_guid] = Base64.encode64(guid).strip

opts.slice(:uuid, :session_guid, :uri, :debug, :log_file, :name, :background)
opts.slice(:uuid, :session_guid, :uri, :debug, :log_file, :name, :background, :config_block)
end

# Stage encoding is not safe for Mettle (doesn't apply to stageless)
Expand Down
Loading
Loading