Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
beefproject
GitHub Repository: beefproject/beef
Path: blob/master/tools/rest_api_examples/lib/beef_rest_api.rb
1154 views
1
class BeefRestAPI
2
3
# initialize
4
def initialize proto = 'https', host = '127.0.0.1', port = '3000', user = 'beef', pass = 'beef'
5
@user = user
6
@pass = pass
7
@url = "#{proto}://#{host}:#{port}/api/"
8
@token = nil
9
end
10
11
################################################################################
12
### BeEF core API
13
################################################################################
14
15
# authenticate and get API token
16
def auth
17
print_verbose "Retrieving authentication token"
18
begin
19
response = RestClient.post "#{@url}admin/login",
20
{ 'username' => "#{@user}",
21
'password' => "#{@pass}" }.to_json,
22
:content_type => :json,
23
:accept => :json
24
result = JSON.parse(response.body)
25
@token = result['token']
26
print_good "Retrieved RESTful API token: #{@token}"
27
rescue => e
28
print_error "Could not retrieve RESTful API token: #{e.message}"
29
end
30
end
31
32
# get BeEF version
33
def version
34
begin
35
response = RestClient.get "#{@url}server/version", {:params => {:token => @token}}
36
result = JSON.parse(response.body)
37
print_good "Retrieved BeEF version: #{result['version']}"
38
result['version']
39
rescue => e
40
print_error "Could not retrieve BeEF version: #{e.message}"
41
end
42
end
43
44
# get server mounts
45
def mounts
46
begin
47
response = RestClient.get "#{@url}server/mounts", {:params => {:token => @token}}
48
result = JSON.parse(response.body)
49
print_good "Retrieved BeEF server mounts: #{result['mounts']}"
50
result['mounts']
51
rescue => e
52
print_error "Could not retrieve BeEF version: #{e.message}"
53
end
54
end
55
56
# get online hooked browsers
57
def online_browsers
58
begin
59
print_verbose "Retrieving online browsers"
60
response = RestClient.get "#{@url}hooks", {:params => {:token => @token}}
61
result = JSON.parse(response.body)
62
browsers = result["hooked-browsers"]["online"]
63
print_good "Retrieved online browser list [#{browsers.size} online]"
64
browsers
65
rescue => e
66
print_error "Could not retrieve browser details: #{e.message}"
67
end
68
end
69
70
# get offline hooked browsers
71
def offline_browsers
72
begin
73
print_verbose "Retrieving offline browsers"
74
response = RestClient.get "#{@url}hooks", {:params => {:token => @token}}
75
result = JSON.parse(response.body)
76
browsers = result["hooked-browsers"]["offline"]
77
print_good "Retrieved offline browser list [#{browsers.size} offline]"
78
browsers
79
rescue => e
80
print_error "Could not retrieve browser details: #{e.message}"
81
end
82
end
83
84
# get hooked browser details by session
85
def browser_details session
86
begin
87
print_verbose "Retrieving browser details for hooked browser [session: #{session}]"
88
response = RestClient.get "#{@url}browserdetails/#{session}", {:params => {:token => @token}}
89
result = JSON.parse(response.body)
90
details = result['details']
91
print_good "Retrieved #{details.size} browser details"
92
details
93
rescue => e
94
print_error "Could not retrieve browser details: #{e.message}"
95
end
96
end
97
98
# delete a browser by session
99
def delete_browser session
100
begin
101
print_verbose "Removing hooked browser [session: #{session}]"
102
response = RestClient.get "#{@url}hooks/#{session}/delete", {:params => {:token => @token}}
103
print_good "Removed browser [session: #{session}]" if response.code == 200
104
response
105
rescue => e
106
print_error "Could not delete hooked browser: #{e.message}"
107
end
108
end
109
110
# get BeEF logs
111
def logs
112
begin
113
print_verbose "Retrieving logs"
114
response = RestClient.get "#{@url}logs", {:params => {:token => @token}}
115
logs = JSON.parse(response.body)
116
print_good "Retrieved #{logs['logs_count']} log entries"
117
logs
118
rescue => e
119
print_error "Could not retrieve logs: #{e.message}"
120
end
121
end
122
123
# get hooked browser logs by session
124
def browser_logs session
125
begin
126
print_verbose "Retrieving browser logs [session: #{session}]"
127
response = RestClient.get "#{@url}logs/#{session}", {:params => {:token => @token}}
128
logs = JSON.parse(response.body)
129
print_good "Retrieved #{logs['logs'].size} browser logs"
130
logs
131
rescue => e
132
print_error "Could not retrieve browser logs: #{e.message}"
133
end
134
end
135
136
################################################################################
137
### command module API
138
################################################################################
139
140
# get command module categories
141
def categories
142
begin
143
print_verbose "Retrieving module categories"
144
response = RestClient.get "#{@url}categories", {:params => {:token => @token}}
145
categories = JSON.parse(response.body)
146
print_good "Retrieved #{categories.size} module categories"
147
categories
148
rescue => e
149
print_error "Could not retrieve logs: #{e.message}"
150
end
151
end
152
153
# get command modules
154
def modules
155
begin
156
print_verbose "Retrieving modules"
157
response = RestClient.get "#{@url}modules", {:params => {:token => @token}}
158
@modules = JSON.parse(response.body)
159
print_good "Retrieved #{@modules.size} available command modules"
160
@modules
161
rescue => e
162
print_error "Could not retrieve modules: #{e.message}"
163
end
164
end
165
166
# get module id by module short name
167
def get_module_id mod_name
168
print_verbose "Retrieving id for module [name: #{mod_name}]"
169
@modules.each do |mod|
170
# normal modules
171
if mod_name.capitalize == mod[1]["class"]
172
return mod[1]["id"]
173
break
174
# metasploit modules
175
elsif mod[1]["class"] == "Msf_module" && mod_name.capitalize == mod[1]["name"]
176
return mod[1]["id"]
177
break
178
end
179
end
180
nil
181
end
182
183
# get command module details
184
def module_details id
185
begin
186
print_verbose "Retrieving details for command module [id: #{id}]"
187
response = RestClient.get "#{@url}modules/#{id}", {:params => {:token => @token}}
188
details = JSON.parse(response.body)
189
print_good "Retrieved details for module [#{details['name']}]"
190
details
191
rescue => e
192
print_error "Could not retrieve modules: #{e.message}"
193
end
194
end
195
196
# execute module
197
def execute_module session, mod_id, options
198
print_verbose "Executing module [id: #{mod_id}, #{options}]"
199
begin
200
response = RestClient.post "#{@url}modules/#{session}/#{mod_id}?token=#{@token}", options.to_json,
201
:content_type => :json,
202
:accept => :json
203
result = JSON.parse(response.body)
204
if result['success'] == 'true'
205
print_good "Executed module [id: #{mod_id}]"
206
else
207
print_error "Could not execute module [id: #{mod_id}]"
208
end
209
result
210
rescue => e
211
print_error "Could not start payload handler: #{e.message}"
212
end
213
end
214
215
216
################################################################################
217
### Metasploit API
218
################################################################################
219
220
# get metasploit version
221
def msf_version
222
begin
223
response = RestClient.get "#{@url}msf/version", {:params => {:token => @token}}
224
result = JSON.parse(response.body)
225
version = result['version']['version']
226
print_good "Retrieved Metasploit version: #{version}"
227
version
228
rescue => e
229
print_error "Could not retrieve Metasploit version: #{e.message}"
230
end
231
end
232
233
# get metasploit jobs
234
def msf_jobs
235
begin
236
response = RestClient.get "#{@url}msf/jobs", {:params => {:token => @token}}
237
result = JSON.parse(response.body)
238
jobs = result['jobs']
239
print_good "Retrieved job list [#{jobs.size} jobs]"
240
jobs
241
rescue => e
242
print_error "Could not retrieve Metasploit job list: #{e.message}"
243
end
244
end
245
246
# get metasploit job info
247
def msf_job_info id
248
begin
249
response = RestClient.get "#{@url}msf/job/#{id}/info", {:params => {:token => @token}}
250
details = JSON.parse(response.body)
251
print_good "Retrieved job information [id: #{id}]"
252
details
253
rescue => e
254
print_error "Could not retrieve job info: #{e.message}"
255
end
256
end
257
258
# start metasploit payload handler
259
def msf_handler options
260
print_verbose "Starting Metasploit payload handler [#{options}]"
261
begin
262
response = RestClient.post "#{@url}msf/handler?token=#{@token}", options.to_json,
263
:content_type => :json,
264
:accept => :json
265
result = JSON.parse(response.body)
266
job_id = result['id']
267
if job_id.nil?
268
print_error "Could not start payload handler: Job id is nil"
269
else
270
print_good "Started payload handler [id: #{job_id}]"
271
end
272
job_id
273
rescue => e
274
print_error "Could not start payload handler: #{e.message}"
275
end
276
end
277
278
# stop metasploit job
279
def msf_job_stop id
280
print_verbose "Stopping Metasploit job [id: #{id}]"
281
begin
282
response = RestClient.get "#{@url}msf/job/#{id}/stop", {:params => {:token => @token}}
283
result = JSON.parse(response.body)
284
if result['success'].nil?
285
print_error "Could not stop Metasploit job [id: #{id}]: No such job ?"
286
else
287
print_good "Stopped job [id: #{id}]"
288
end
289
result
290
rescue => e
291
print_error "Could not stop Metasploit job [id: #{id}]: #{e.message}"
292
end
293
end
294
295
296
################################################################################
297
### Network API
298
################################################################################
299
300
# get all network hosts
301
def network_hosts_all
302
begin
303
print_verbose "Retrieving all network hosts"
304
response = RestClient.get "#{@url}network/hosts", {:params => {:token => @token}}
305
details = JSON.parse(response.body)
306
print_good "Retrieved #{details['count']} network hosts"
307
details
308
rescue => e
309
print_error "Could not retrieve network hosts: #{e.message}"
310
end
311
end
312
313
# get all network services
314
def network_services_all
315
begin
316
print_verbose "Retrieving all network services"
317
response = RestClient.get "#{@url}network/services", {:params => {:token => @token}}
318
details = JSON.parse(response.body)
319
print_good "Retrieved #{details['count']} network services"
320
details
321
rescue => e
322
print_error "Could not retrieve network services: #{e.message}"
323
end
324
end
325
326
# get network hosts by session
327
def network_hosts session
328
begin
329
print_verbose "Retrieving network hosts for hooked browser [session: #{session}]"
330
response = RestClient.get "#{@url}network/hosts/#{session}", {:params => {:token => @token}}
331
details = JSON.parse(response.body)
332
print_good "Retrieved #{details['count']} network hosts"
333
details
334
rescue => e
335
print_error "Could not retrieve network hosts: #{e.message}"
336
end
337
end
338
339
# get network services by session
340
def network_services session
341
begin
342
print_verbose "Retrieving network services for hooked browser [session: #{session}]"
343
response = RestClient.get "#{@url}network/services/#{session}", {:params => {:token => @token}}
344
details = JSON.parse(response.body)
345
print_good "Retrieved #{details['count']} network services"
346
details
347
rescue => e
348
print_error "Could not retrieve network services: #{e.message}"
349
end
350
end
351
352
353
################################################################################
354
### XssRays API
355
################################################################################
356
357
# get all rays
358
def xssrays_rays_all
359
print_verbose "Retrieving all rays"
360
response = RestClient.get "#{@url}xssrays/rays", {:params => {:token => @token}}
361
details = JSON.parse(response.body)
362
print_good "Retrieved #{details['count']} rays"
363
details
364
rescue => e
365
print_error "Could not retrieve rays: #{e.message}"
366
end
367
368
# get rays by session
369
def xssrays_rays session
370
print_verbose "Retrieving rays for hooked browser [session: #{session}]"
371
response = RestClient.get "#{@url}xssrays/rays/#{session}", {:params => {:token => @token}}
372
details = JSON.parse(response.body)
373
print_good "Retrieved #{details['count']} rays"
374
details
375
rescue => e
376
print_error "Could not retrieve rays: #{e.message}"
377
end
378
379
# get all scans
380
def xssrays_scans_all
381
print_verbose "Retrieving all scans"
382
response = RestClient.get "#{@url}xssrays/scans", {:params => {:token => @token}}
383
details = JSON.parse(response.body)
384
print_good "Retrieved #{details['count']} scans"
385
details
386
rescue => e
387
print_error "Could not retrieve scans: #{e.message}"
388
end
389
390
# get scans by session
391
def xssrays_scans session
392
print_verbose "Retrieving scans for hooked browser [session: #{session}]"
393
response = RestClient.get "#{@url}xssrays/scans/#{session}", {:params => {:token => @token}}
394
details = JSON.parse(response.body)
395
print_good "Retrieved #{details['count']} scans"
396
details
397
rescue => e
398
print_error "Could not retrieve scans: #{e.message}"
399
end
400
401
402
403
################################################################################
404
### DNS API
405
################################################################################
406
407
# get ruleset
408
def dns_ruleset
409
begin
410
print_verbose "Retrieving DNS ruleset"
411
response = RestClient.get "#{@url}dns/ruleset", {:params => {:token => @token}}
412
details = JSON.parse(response.body)
413
print_good "Retrieved #{details['count']} rules"
414
details
415
rescue => e
416
print_error "Could not retrieve DNS ruleset: #{e.message}"
417
end
418
end
419
420
# add a rule
421
def dns_add_rule(dns_pattern, dns_resource, dns_response)
422
dns_response = [dns_response] if dns_response.is_a?(String)
423
print_verbose "Adding DNS rule [pattern: #{dns_pattern}, resource: #{dns_resource}, response: #{dns_response}]"
424
response = RestClient.post "#{@url}dns/rule?token=#{@token}", {
425
'pattern' => dns_pattern,
426
'resource' => dns_resource,
427
'response' => dns_response }.to_json,
428
:content_type => :json,
429
:accept => :json
430
details = JSON.parse(response.body)
431
rule_id = details['id']
432
433
if rule_id.nil?
434
print_error("Could not add DNS rule: #{details['error']}")
435
return details
436
end
437
438
print_good "Added rule [id: #{details['id']}]"
439
details
440
rescue => e
441
print_error "Could not add DNS rule: #{e.message}"
442
end
443
444
# get rule details
445
def dns_get_rule(id)
446
begin
447
print_verbose "Retrieving DNS rule details [id: #{id}]"
448
response = RestClient.get "#{@url}dns/rule/#{id}", {:params => {:token => @token}}
449
details = JSON.parse(response.body)
450
print_good "Retrieved rule [id: #{details['id']}]"
451
details
452
rescue => e
453
print_error "Could not retrieve DNS rule: #{e.message}"
454
end
455
end
456
457
# delete a rule
458
def dns_delete_rule(id)
459
response = RestClient.delete "#{@url}dns/rule/#{id}?token=#{@token}"
460
details = JSON.parse(response.body)
461
print_good "Deleted rule [id: #{id}]"
462
details
463
rescue => e
464
print_error "Could not delete DNS rule: #{e.message}"
465
end
466
467
468
################################################################################
469
### Autorun
470
################################################################################
471
472
def autorun_rules
473
print_verbose "Retrieving Autorun rules"
474
response = RestClient.get "#{@url}autorun/rules", {:params => {:token => @token}}
475
details = JSON.parse(response.body)
476
print_good("Retrieved #{details['count']} rules")
477
details
478
rescue => e
479
print_error("Could not retrieve Autorun rules: #{e.message}")
480
end
481
482
def autorun_delete_rule(id)
483
print_verbose "Deleting Autorun rule with ID: #{id}"
484
response = RestClient.delete "#{@url}autorun/rule/#{id}?token=#{@token}"
485
details = JSON.parse(response.body)
486
print_good("Deleted rule [id: #{id}]")
487
details
488
rescue => e
489
print_error("Could not delete Autorun rule: #{e.message}")
490
end
491
492
def autorun_add_rule(data)
493
print_verbose "Adding Autorun rule: #{data}"
494
response = RestClient.post "#{@url}autorun/rule/add?token=#{@token}",
495
data.to_json,
496
:content_type => :json,
497
:accept => :json
498
details = JSON.parse(response.body)
499
rule_id = details['rule_id']
500
501
if rule_id.nil?
502
print_error("Could not add Autorun rule: #{details['error']}")
503
return details
504
end
505
506
print_good("Added rule [id: #{details['id']}]")
507
details
508
rescue => e
509
print_error("Could not add Autorun rule: #{e.message}")
510
end
511
512
def autorun_run_rule_on_all_browsers(rule_id)
513
print_verbose "Running Autorun rule #{rule_id} on all browsers"
514
response = RestClient.get "#{@url}autorun/run/#{rule_id}", {:params => {:token => @token}}
515
details = JSON.parse(response.body)
516
print_debug details
517
print_good('Done')
518
details
519
rescue => e
520
print_error "Could not run Autorun rule #{rule_id}: #{e.message}"
521
end
522
523
def autorun_run_rule_on_browser(rule_id, hb_id)
524
print_verbose "Running Autorun rule #{rule_id} on browser #{hb_id}"
525
response = RestClient.get "#{@url}autorun/run/#{rule_id}/#{hb_id}", {:params => {:token => @token}}
526
details = JSON.parse(response.body)
527
print_good('Done')
528
details
529
rescue => e
530
print_error "Could not run Autorun rule #{rule_id}: #{e.message}"
531
end
532
533
534
################################################################################
535
### WebRTC
536
################################################################################
537
538
# get webrtc status for hooked browser by session
539
def webrtc_status id
540
begin
541
print_verbose "Retrieving status for hooked browser [id: #{id}]"
542
response = RestClient.get "#{@url}webrtc/status/#{id}", {:params => {:token => @token}}
543
details = JSON.parse(response.body)
544
print_good "Retrieved status for hooked browser [id: #{id}]"
545
details
546
rescue => e
547
print_error "Could not retrieve status: #{e.message}"
548
end
549
end
550
551
################################################################################
552
### Social Engineering
553
################################################################################
554
555
# bind dropper to path
556
def bind(fname, path)
557
print_verbose "Binding 'extensions/social_engineering/droppers/#{fname}' to '#{path}'"
558
begin
559
response = RestClient.post "#{@url}/server/bind?token=#{@token}",
560
{ 'mount' => "#{path}",
561
'local_file' => "#{fname}" }.to_json,
562
:content_type => :json,
563
:accept => :json
564
print_good "Bound '#{fname}' successfully" if response.code == 200
565
rescue => e
566
print_error "Could not bind file #{fname}: #{e.message}"
567
end
568
end
569
570
# clone page and bind to path
571
def clone_page(url, path, use_existing, dns_spoof)
572
print_verbose "Binding '#{url}' to '#{path}'"
573
begin
574
response = RestClient.post "#{@url}/seng/clone_page?token=#{@token}",
575
{ 'mount' => "#{path}",
576
'url' => "#{url}",
577
'use_existing' => use_existing,
578
'dns_spoof' => dns_spoof }.to_json,
579
:content_type => :json,
580
:accept => :json
581
print_good "Bound '#{url}' successfully" if response.code == 200
582
rescue => e
583
print_error "Could not bind URL #{url}: #{e.message}"
584
end
585
end
586
587
end
588
589