Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
beefproject
GitHub Repository: beefproject/beef
Path: blob/master/extensions/admin_ui/media/javascript/ui/panel/common.js
1154 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
var zombie_execute_button_text = 'Execute'
8
var zombie_reexecute_button_text = 'Re-execute'
9
var re_execute_command_title = 'Re-execute command'
10
11
/**
12
* Generates fields for the form used to send command modules.
13
*
14
* @param: {Object} the form to generate the field in.
15
* @param: {String/Object} the field name or it's definition as an object.
16
* @param: {String} the value that field should have.
17
* @param: {Boolean} set to true if you want the field to be disabled.
18
* @param: {Object} the targeted Zombie.
19
*/
20
function generate_form_input_field(form, input, value, disabled, zombie) {
21
var input_field = null;
22
var input_def = null;
23
24
if (!input['ui_label']) input['ui_label'] = input['name'];
25
if (!input['type']) input['type'] = 'textfield';
26
if (!input['value']) input['value'] = '';
27
28
input_def = {
29
id: 'form-zombie-'+zombie.session+'-field-'+input['name'],
30
name: 'txt_'+input['name'],
31
fieldLabel: input['ui_label'],
32
anchor:'70%',
33
allowBlank: false,
34
value: input['value']
35
};
36
37
// create the input field object based upon the type supplied
38
switch(input['type'].toLowerCase()) {
39
case 'textfield':
40
input_field = new Ext.form.TextField(input_def);
41
break;
42
case 'textarea':
43
input_field = new Ext.form.TextArea(input_def);
44
break;
45
case 'hidden':
46
input_field = new Ext.form.Hidden(input_def);
47
break;
48
case 'label':
49
input_def['fieldLabel'] = ''
50
input_def['html'] = input['html'];
51
input_field = new Ext.form.Label(input_def);
52
break;
53
case 'checkbox':
54
input_def['name'] = 'chk_' + input['name'];
55
input_field = new Ext.form.Checkbox(input_def);
56
break;
57
case 'checkboxgroup':
58
input_def['name'] = 'chkg_' + input['name'];
59
input_def['items'] = input['items'];
60
input_field = new Ext.form.CheckboxGroup(input_def);
61
break;
62
case 'combobox':
63
input_def['name'] = 'com_' + input['name'];
64
input_def['triggerAction'] = 'all';
65
66
if(input.reloadOnChange || input.defaultPayload != null) { // defined in msfcommand.rb
67
Ext.getCmp("payload-panel").show(); // initially the panel will be empty so it may appear still hidden
68
input_def['listeners'] = {
69
// update the payload options when one of them is selected
70
'select': function(combo, value) {
71
get_dynamic_payload_details(combo.getValue(), zombie);
72
},
73
// set the default payload value as defined in defaultPayload
74
'afterrender': function(combo){
75
combo.setValue(input.defaultPayload);
76
get_dynamic_payload_details(combo.getValue(),zombie);
77
}
78
};
79
}
80
81
82
// create store to contain options for the combo box
83
input_def['store'] = new Ext.data.ArrayStore( {
84
fields: input['store_fields'],
85
data: input['store_data']
86
});
87
88
input_field = new Ext.form.ComboBox(input_def);
89
90
break;
91
default:
92
input_field = new Ext.form.TextField(input_def);
93
break;
94
}
95
96
// add the properties for the input element, for example: widths, default values and the html lables
97
for(definition in input) {
98
if( (typeof input[definition] == 'string') && (definition != 'type') && (definition != 'name')) {
99
input_field[definition] = input[definition];
100
}
101
}
102
103
if(value) input_field.setValue(value);
104
if(disabled) input_field.setDisabled(true);
105
106
form.add(input_field);
107
return input_field;
108
};
109
110
function get_dynamic_payload_details(payload, zombie) {
111
modid = Ext.getCmp('form-zombie-' + zombie.session + '-field-mod_id').value;
112
Ext.Ajax.request({
113
loadMask: true,
114
url: '<%= @base_path %>/modules/select/commandmodule.json',
115
method: 'POST',
116
params: 'command_module_id=' + modid + '&' + 'payload_name=' + payload,
117
success: function(resp) {
118
var module = Ext.decode(resp.responseText);
119
module = module.command_modules[1][0];
120
Ext.getCmp("payload-panel").removeAll(); // clear the panel contents
121
Ext.each(module.data , function(input){
122
// generate each of the payload input options
123
generate_form_input_field(Ext.getCmp("payload-panel"), input, null, false, zombie);
124
});
125
126
Ext.getCmp("payload-panel").doLayout();
127
}
128
})
129
}
130
131
/**
132
* Generate a panel for an command module that already has been executed.
133
*
134
* @param: {Object} the Panel in the UI to generate the form into.
135
* @param: {Integer} the command id to generate the panel for.
136
* @param: {Object} the targeted Zombie.
137
* @param: {Object} the status bar.
138
*/
139
function genExistingExploitPanel(panel, command_id, zombie, sb) {
140
if(typeof panel != 'object') {
141
Ext.beef.msg('Bad!', 'Incorrect panel chosen.');
142
return;
143
}
144
145
sb.showBusy(); // status bar update
146
panel.removeAll();
147
148
Ext.Ajax.request({
149
url: '<%= @base_path %>/modules/select/command.json',
150
method: 'POST',
151
params: 'command_id=' + command_id,
152
loadMask: true,
153
success: function(resp) {
154
var xhr = Ext.decode(resp.responseText);
155
156
if(!xhr || !xhr.definition) {
157
Ext.beef.msg('Error!', 'We could not retrieve the definition of that command module...');
158
return;
159
}
160
161
var form = new Ext.form.FormPanel({
162
url: '<%= @base_path %>/modules/commandmodule/reexecute',
163
id: 'form-command-module-zombie-'+zombie.session,
164
border: false,
165
labelWidth: 75,
166
defaultType: 'textfield',
167
title: re_execute_command_title,
168
bodyStyle: 'padding: 5px;',
169
170
items: [new Ext.form.Hidden({name: 'command_id', value: command_id})],
171
172
buttons:[{
173
text: zombie_reexecute_button_text,
174
handler: function() {
175
var form = Ext.getCmp('form-command-module-zombie-'+zombie.session);
176
if(!form || !form.getForm().isValid()) return;
177
178
sb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update
179
180
var command_module_form = form.getForm(); // form to be submitted when execute button is pressed on an command module tab
181
command_module_form.submit({
182
params: { // insert the nonce with the form
183
nonce: Ext.get ("nonce").dom.value
184
},
185
success: function() {
186
sb.update_sent("Commands sent to zombie " + zombie.ip); // status bar update
187
},
188
failure: function() {
189
sb.update_fail("Error!"); // status bar update
190
}
191
});
192
}
193
}]
194
});
195
196
Ext.each(xhr.definition.Data, function(input) {
197
var value = null;
198
199
if(typeof input == 'string') {
200
value = xhr.data[input];
201
}
202
203
if(typeof input == 'object' && typeof input[0] == 'object') {
204
value = xhr.data[input[0]['name']]
205
}
206
207
generate_form_input_field(form, input, value, false, zombie);
208
});
209
210
var grid_store = new Ext.data.JsonStore({
211
url: '<%= @base_path %>/modules/select/command_results.json?command_id='+command_id,
212
storeId: 'command-results-store-zombie-'+zombie.session,
213
root: 'results',
214
remoteSort: false,
215
autoDestroy: true,
216
fields: [
217
{name: 'date', type: 'date', dateFormat: 'timestamp'},
218
{name: 'data'}
219
]
220
});
221
222
Ext.TaskMgr.start({
223
run: function(task) {
224
var grid = Ext.getCmp('command-results-grid-zombie-'+zombie.session);
225
//here we have to check for the existance of the grid before reloading
226
//because we do not want to reload the store if the tab has been closed.
227
if(grid_store && grid) {
228
grid_store.reload();
229
}
230
},
231
interval: 4000
232
});
233
234
var grid = new Ext.grid.GridPanel({
235
id: 'command-results-grid-zombie-'+zombie.session,
236
store: grid_store,
237
border: false,
238
hideHeaders: true,
239
title: 'Command results',
240
241
viewConfig: {
242
forceFit:true
243
},
244
245
// render command responses
246
columns:[new Ext.grid.RowNumberer({width: 20}), {
247
dataIndex: 'date',
248
sortable: false,
249
renderer: function(value, p, record) {
250
html = String.format("<div style='color:#385F95;text-align:right;'>{0}</div>", value);
251
html += '<p>';
252
for(index in record.data.data) {
253
result = record.data.data[index];
254
index = index.toString().replace('_', ' ');
255
256
// Check for a base64 encoded image
257
var header = "image=data:image/(jpg|png);base64,";
258
var re = new RegExp(header, "");
259
if (result.match(re)) {
260
261
// Render the image
262
try {
263
var img = result.replace(/[\r\n]/g, '');
264
base64_data = window.atob(img.replace(re, ''));
265
html += String.format('<img src="{0}" /><br>', img.replace(/^image=/, ''));
266
} catch(e) {
267
console.log("Received invalid base64 encoded image string: "+e.toString());
268
html += String.format('<b>{0}</b>: {1}<br>', index, result);
269
}
270
271
// output escape everything else, but allow the <br> tag for better rendering.
272
} else {
273
html += String.format('<b>{0}</b>: {1}<br>', index, $jEncoder.encoder.encodeForHTML(result).replace(/&lt;br&gt;/g,'<br>'));
274
}
275
}
276
277
html += '</p>';
278
return html;
279
}
280
}]
281
});
282
283
grid.store.load();
284
285
var accordion = new Ext.Panel({
286
id: 'command-results-accordion-zombie-'+zombie.session,
287
layout:'accordion',
288
border: false,
289
items: [grid, form]
290
});
291
292
panel.add(accordion);
293
panel.doLayout();
294
295
sb.update_ready(); // status bar update
296
}
297
});
298
};
299
300
/**
301
* Generate a panel for an command module.
302
*
303
* @param: {Object} the Panel in the UI to generate the form into.
304
* @param: {String} the path to the command module file in the framework.
305
* @param: {String} the name of the command module.
306
* @param: {Object} the targeted Zombie.
307
* @param: {Object} the status bar.
308
*/
309
function genNewExploitPanel(panel, command_module_id, command_module_name, zombie, sb) {
310
if(typeof panel != 'object') {
311
Ext.beef.msg('Bad!', 'Incorrect panel chosen.');
312
return;
313
}
314
315
var xgrid = Ext.getCmp('command-module-grid-zombie-'+zombie.session);
316
var sb = Ext.getCmp('commands-bbar-zombie-'+zombie.session);
317
panel.removeAll();
318
if(command_module_name == 'some special command module') {
319
//HERE we will develop specific panels for the command modules that require it.
320
} else {
321
Ext.Ajax.request({
322
loadMask: true,
323
url: '<%= @base_path %>/modules/select/commandmodule.json',
324
method: 'POST',
325
params: 'command_module_id=' + command_module_id,
326
success: function(resp) {
327
var module = Ext.decode(resp.responseText);
328
329
if(!module) {
330
Ext.beef.msg('Error!', 'We could not retrieve the definition of that command_module...');
331
return;
332
}
333
334
var submiturl = '<%= @base_path %>/modules/commandmodule/new';
335
if(module.dynamic){
336
submiturl = '<%= @base_path %>/modules/commandmodule/dynamicnew';
337
}
338
339
module = module.command_modules[1];
340
341
var form = new Ext.form.FormPanel({
342
url: submiturl,
343
344
id: 'form-command-module-zombie-'+zombie.session,
345
border: false,
346
labelWidth: 75,
347
defaultType: 'textfield',
348
title: module.Name,
349
autoScroll: true,
350
bodyStyle: 'padding: 5px;',
351
352
items: [
353
new Ext.form.Hidden({name: 'zombie_session', value: zombie.session}),
354
new Ext.form.Hidden({name: 'command_module_id', value: command_module_id}),
355
new Ext.form.DisplayField({
356
name: 'command_module_description',
357
fieldLabel: 'Description',
358
fieldClass: 'command-module-panel-description',
359
value: module.Description
360
}),
361
new Ext.form.DisplayField({
362
name: 'command_module_id_visible',
363
fieldLabel: 'Id',
364
fieldClass: 'command-module-panel-description',
365
value: command_module_id
366
})
367
],
368
369
buttons:[{
370
text: zombie_execute_button_text,
371
handler: function() {
372
var form = Ext.getCmp('form-command-module-zombie-'+zombie.session), command_module_params = new Array();
373
374
if(!form || !form.getForm().isValid()) {
375
sb.update_fail("Please complete all input fields!"); // status bar update
376
return;
377
}
378
379
sb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update
380
381
var command_module_form = form.getForm(); // form to be submitted when execute button is pressed on an command module tab
382
383
command_module_form.submit({
384
params: { // insert the nonce with the form
385
nonce: Ext.get ("nonce").dom.value
386
},
387
success: function() {
388
xgrid.i = 0;
389
xgrid.store.reload({ //reload the command module grid
390
params: { // insert the nonce with the request to reload the grid
391
nonce: Ext.get ("nonce").dom.value
392
}
393
});
394
sb.update_sent("Commands sent to zombie " + zombie.ip); // status bar update
395
},
396
failure: function() {
397
sb.update_fail("Error!"); // status bar update
398
}
399
});
400
}
401
}]
402
});
403
404
// create the panel and hide it
405
var payload_panel = new Ext.Panel({
406
id: 'payload-panel', // used with Ext.GetCmp('payload-panel')
407
bodyStyle: 'padding:10px;', // we can assign styles to the main div
408
layout : 'form',
409
bodyBorder: false,
410
height: 200,
411
hidden: true,
412
border: false //we can remove the border of the panel
413
});
414
415
Ext.each(module.Data, function(input){
416
generate_form_input_field(form, input, null, false, zombie)}
417
);
418
419
form.add(payload_panel);
420
panel.add(form);
421
panel.doLayout();
422
// hide the load mask after rendering of the config panel is done
423
panel.configLoadMask.hide();
424
}
425
});
426
}
427
};
428