CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/post/hwbridge/client.rb
Views: 11783
1
# -*- coding: binary -*-
2
3
require 'rex/post/hwbridge/extension'
4
require 'rex/post/hwbridge/object_aliases'
5
6
module Rex
7
module Post
8
module HWBridge
9
10
# Used for merging constants from extensions
11
module Extensions
12
end
13
14
class Client
15
@@ext_hash = {}
16
17
#
18
# Checks the extension hash to see if a class has already been associated
19
# with the supplied extension name.
20
#
21
def self.check_ext_hash(name)
22
@@ext_hash[name]
23
end
24
25
#
26
# Stores the name to class association for the supplied extension name.
27
#
28
def self.set_ext_hash(name, klass)
29
@@ext_hash[name] = klass
30
end
31
32
#
33
# Initializes the client context
34
#
35
def initialize(sock,opts={})
36
init_hwbridge(sock,opts)
37
end
38
39
#
40
# Initialize the hwbridge instance
41
#
42
def init_hwbridge(sock,opts={})
43
self.sock = sock
44
self.ext = ObjectAliases.new
45
self.ext_aliases = ObjectAliases.new
46
end
47
48
#
49
# sends request through 'exploit' which is the hwbridge/connect
50
#
51
def send_request(uri)
52
if not exploit
53
$stdout.puts("Exploit module not connected")
54
return {}
55
end
56
exploit.fetch_json(uri)
57
end
58
59
#
60
# Gets/refreshes HW status & capabilities
61
#
62
def get_status
63
send_request("/status")
64
end
65
66
#
67
# Gets the devices statistics
68
#
69
def get_statistics
70
send_request("/statistics")
71
end
72
73
#
74
# Fetches custom methods from HW, if any
75
#
76
def get_custom_methods
77
send_request("/custom_methods")
78
end
79
80
#
81
# Sends a reset signal to the device to perform a software bounce or a full
82
# factory reset. Depends on how the device decided to handle it.
83
#
84
def reset
85
send_request("/control/factory_reset")
86
end
87
88
#
89
# Sends a reboot signal to reboot the device.
90
#
91
def reboot
92
send_request("/control/reboot")
93
end
94
95
##
96
#
97
# Alias processor
98
#
99
##
100
101
#
102
# Translates unhandled methods into registered extension aliases
103
# if a matching extension alias exists for the supplied symbol.
104
#
105
def method_missing(symbol, *args)
106
self.ext_aliases.aliases[symbol.to_s]
107
end
108
109
##
110
#
111
# Extension registration
112
#
113
##
114
115
#
116
# Loads the client half of the supplied extension and initializes it as a
117
# registered extension that can be reached through client.ext.[extension].
118
#
119
def add_extension(name, commands=[])
120
self.commands |= commands
121
122
# Check to see if this extension has already been loaded.
123
if ((klass = self.class.check_ext_hash(name.downcase)) == nil)
124
old = Rex::Post::HWBridge::Extensions.constants
125
require("rex/post/hwbridge/extensions/#{name.downcase}/#{name.downcase}")
126
new = Rex::Post::HWBridge::Extensions.constants
127
128
# No new constants added?
129
if ((diff = new - old).empty?)
130
diff = [ name.capitalize ]
131
end
132
133
klass = Rex::Post::HWBridge::Extensions.const_get(diff[0]).const_get(diff[0])
134
135
# Save the module name to class association now that the code is
136
# loaded.
137
self.class.set_ext_hash(name.downcase, klass)
138
end
139
140
# Create a new instance of the extension
141
inst = klass.new(self)
142
143
self.ext.aliases[inst.name] = inst
144
145
return true
146
end
147
148
#
149
# Deregisters an extension alias of the supplied name.
150
#
151
def deregister_extension(name)
152
self.ext.aliases.delete(name)
153
end
154
155
#
156
# Enumerates all of the loaded extensions.
157
#
158
def each_extension(&block)
159
self.ext.aliases.each(block)
160
end
161
162
#
163
# Registers an aliased extension that can be referenced through
164
# client.name.
165
#
166
def register_extension_alias(name, ext)
167
self.ext_aliases.aliases[name] = ext
168
# Whee! Syntactic sugar, where art thou?
169
#
170
# Create an instance method on this object called +name+ that returns
171
# +ext+. We have to do it this way instead of simply
172
# self.class.class_eval so that other meterpreter sessions don't get
173
# extension methods when this one does
174
(class << self; self; end).class_eval do
175
define_method(name.to_sym) do
176
ext
177
end
178
end
179
ext
180
end
181
182
#
183
# Registers zero or more aliases that are provided in an array.
184
#
185
def register_extension_aliases(aliases)
186
aliases.each { |a|
187
register_extension_alias(a['name'], a['ext'])
188
}
189
end
190
191
#
192
# Deregisters a previously registered extension alias.
193
#
194
def deregister_extension_alias(name)
195
self.ext_aliases.aliases.delete(name)
196
end
197
198
#
199
# Dumps the extension tree.
200
#
201
def dump_extension_tree()
202
items = []
203
items.concat(self.ext.dump_alias_tree('client.ext'))
204
items.concat(self.ext_aliases.dump_alias_tree('client'))
205
206
return items.sort
207
end
208
209
#
210
# Encodes (or not) a UTF-8 string
211
#
212
def unicode_filter_encode(str)
213
self.encode_unicode ? Rex::Text.unicode_filter_encode(str) : str
214
end
215
216
#
217
# Decodes (or not) a UTF-8 string
218
#
219
def unicode_filter_decode(str)
220
self.encode_unicode ? Rex::Text.unicode_filter_decode(str) : str
221
end
222
223
# A list of the commands
224
#
225
attr_reader :commands
226
attr_reader :ext, :sock
227
protected
228
attr_writer :commands # :nodoc:
229
attr_accessor :ext_aliases # :nodoc:
230
attr_writer :ext, :sock # :nodoc:
231
232
end
233
234
###
235
#
236
# Exception thrown when a request fails.
237
#
238
###
239
class RequestError < ArgumentError
240
def initialize(method, einfo, ecode=nil)
241
@method = method
242
@result = einfo
243
@code = ecode || einfo
244
end
245
246
def to_s
247
"#{@method}: Operation failed: #{@result}"
248
end
249
250
# The method that failed.
251
attr_reader :method
252
253
# The error result that occurred, typically a windows error message.
254
attr_reader :result
255
256
# The error result that occurred, typically a windows error code.
257
attr_reader :code
258
end
259
260
end
261
end
262
end
263
264