Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
beefproject
GitHub Repository: beefproject/beef
Path: blob/master/core/api.rb
1146 views
1
#
2
# Copyright (c) 2006-2025 Wade Alcorn - [email protected]
3
# Browser Exploitation Framework (BeEF) - https://beefproject.com
4
# See the file 'doc/COPYING' for copying permission
5
#
6
7
module BeEF
8
module API
9
#
10
# Registrar class to handle all registered timed API calls
11
#
12
class Registrar
13
include Singleton
14
15
#
16
# Create registrar
17
#
18
def initialize
19
@registry = []
20
@count = 1
21
end
22
23
# Register timed API calls to an owner
24
#
25
# @param [Class] owner the owner of the API hook
26
# @param [Class] clss the API class the owner would like to hook into
27
# @param [String] method the method of the class the owner would like to execute
28
# @param [Array] params an array of parameters that need to be matched before the owner will be called
29
#
30
def register(owner, clss, method, params = [])
31
unless verify_api_path(clss, method)
32
print_error "API Registrar: Attempted to register non-existant API method #{clss} :#{method}"
33
return
34
end
35
36
if registered?(owner, clss, method, params)
37
print_debug "API Registrar: Attempting to re-register API call #{clss} :#{method}"
38
return
39
end
40
41
id = @count
42
@registry << {
43
'id' => id,
44
'owner' => owner,
45
'class' => clss,
46
'method' => method,
47
'params' => params
48
}
49
@count += 1
50
51
id
52
end
53
54
#
55
# Tests whether the owner is registered for an API hook
56
#
57
# @param [Class] owner the owner of the API hook
58
# @param [Class] clss the API class
59
# @param [String] method the method of the class
60
# @param [Array] params an array of parameters that need to be matched
61
#
62
# @return [Boolean] whether or not the owner is registered
63
#
64
def registered?(owner, clss, method, params = [])
65
@registry.each do |r|
66
next unless r['owner'] == owner
67
next unless r['class'] == clss
68
next unless r['method'] == method
69
next unless is_matched_params? r, params
70
71
return true
72
end
73
false
74
end
75
76
#
77
# Match a timed API call to determine if an API.fire() is required
78
#
79
# @param [Class] clss the target API class
80
# @param [String] method the method of the target API class
81
# @param [Array] params an array of parameters that need to be matched
82
#
83
# @return [Boolean] whether or not the arguments match an entry in the API registry
84
#
85
def matched?(clss, method, params = [])
86
@registry.each do |r|
87
next unless r['class'] == clss
88
next unless r['method'] == method
89
next unless is_matched_params? r, params
90
91
return true
92
end
93
false
94
end
95
96
#
97
# Un-registers an API hook
98
#
99
# @param [Integer] id the ID of the API hook
100
#
101
def unregister(id)
102
@registry.delete_if { |r| r['id'] == id }
103
end
104
105
#
106
# Retrieves all the owners and ID's of an API hook
107
# @param [Class] clss the target API class
108
# @param [String] method the method of the target API class
109
# @param [Array] params an array of parameters that need to be matched
110
#
111
# @return [Array] an array of hashes consisting of two keys :owner and :id
112
#
113
def get_owners(clss, method, params = [])
114
owners = []
115
@registry.each do |r|
116
next unless r['class'] == clss
117
next unless r['method'] == method
118
next unless is_matched_params? r, params
119
120
owners << { owner: r['owner'], id: r['id'] }
121
end
122
owners
123
end
124
125
#
126
# Verifies that the api_path has been regitered
127
# Verifies the API path has been registered.
128
#
129
# @note This is a security precaution
130
#
131
# @param [Class] clss the target API class to verify
132
# @param [String] mthd the target method to verify
133
#
134
def verify_api_path(clss, mthd)
135
(clss.const_defined?('API_PATHS') && clss.const_get('API_PATHS').key?(mthd))
136
end
137
138
#
139
# Retrieves the registered symbol reference for an API hook
140
#
141
# @param [Class] clss the target API class to verify
142
# @param [String] mthd the target method to verify
143
#
144
# @return [Symbol] the API path
145
#
146
def get_api_path(clss, mthd)
147
verify_api_path(clss, mthd) ? clss.const_get('API_PATHS')[mthd] : nil
148
end
149
150
#
151
# Matches stored API params to params
152
#
153
# @note If a stored API parameter has a NilClass the parameter matching is skipped for that parameter
154
# @note By default this method returns true, this is either because the API.fire() did not include any parameters or there were no parameters defined for this registry entry
155
#
156
# @param [Hash] reg hash of registry element, must contain 'params' key
157
# @param [Array] params array of parameters to be compared to the stored parameters
158
#
159
# @return [Boolean] whether params matches the stored API parameters
160
#
161
def is_matched_params?(reg, params)
162
stored = reg['params']
163
return true unless stored.length == params.length
164
165
stored.each_index do |i|
166
next if stored[i].nil?
167
return false unless stored[i] == params[i]
168
end
169
170
true
171
end
172
173
#
174
# Fires all owners registered to this API hook
175
#
176
# @param [Class] clss the target API class
177
# @param [String] mthd the target API method
178
# @param [Array] *args parameters passed for the API call
179
#
180
# @return [Hash, NilClass] returns either a Hash of :api_id and :data
181
# if the owners return data, otherwise NilClass
182
#
183
def fire(clss, mthd, *args)
184
mods = get_owners(clss, mthd, args)
185
return nil unless mods.length.positive?
186
187
unless verify_api_path(clss, mthd) && clss.ancestors.first.to_s.start_with?('BeEF::API')
188
print_error "API Path not defined for Class: #{clss} method: #{mthd}"
189
return []
190
end
191
192
data = []
193
method = get_api_path(clss, mthd)
194
mods.each do |mod|
195
# Only used for API Development (very verbose)
196
# print_info "API: #{mod} fired #{method}"
197
198
result = mod[:owner].method(method).call(*args)
199
data << { api_id: mod[:id], data: result } unless result.nil?
200
rescue StandardError => e
201
print_error "API Fire Error: #{e.message} in #{mod}.#{method}()"
202
end
203
204
data
205
end
206
end
207
end
208
end
209
210
require 'core/api/module'
211
require 'core/api/modules'
212
require 'core/api/extension'
213
require 'core/api/extensions'
214
require 'core/api/main/migration'
215
require 'core/api/main/network_stack/assethandler'
216
require 'core/api/main/server'
217
require 'core/api/main/server/hook'
218
require 'core/api/main/configuration'
219
220