Path: blob/master/extensions/admin_ui/media/javascript/ui/panel/common.js
1154 views
//1// Copyright (c) 2006-2025 Wade Alcorn - [email protected]2// Browser Exploitation Framework (BeEF) - https://beefproject.com3// See the file 'doc/COPYING' for copying permission4//56var zombie_execute_button_text = 'Execute'7var zombie_reexecute_button_text = 'Re-execute'8var re_execute_command_title = 'Re-execute command'910/**11* Generates fields for the form used to send command modules.12*13* @param: {Object} the form to generate the field in.14* @param: {String/Object} the field name or it's definition as an object.15* @param: {String} the value that field should have.16* @param: {Boolean} set to true if you want the field to be disabled.17* @param: {Object} the targeted Zombie.18*/19function generate_form_input_field(form, input, value, disabled, zombie) {20var input_field = null;21var input_def = null;2223if (!input['ui_label']) input['ui_label'] = input['name'];24if (!input['type']) input['type'] = 'textfield';25if (!input['value']) input['value'] = '';2627input_def = {28id: 'form-zombie-'+zombie.session+'-field-'+input['name'],29name: 'txt_'+input['name'],30fieldLabel: input['ui_label'],31anchor:'70%',32allowBlank: false,33value: input['value']34};3536// create the input field object based upon the type supplied37switch(input['type'].toLowerCase()) {38case 'textfield':39input_field = new Ext.form.TextField(input_def);40break;41case 'textarea':42input_field = new Ext.form.TextArea(input_def);43break;44case 'hidden':45input_field = new Ext.form.Hidden(input_def);46break;47case 'label':48input_def['fieldLabel'] = ''49input_def['html'] = input['html'];50input_field = new Ext.form.Label(input_def);51break;52case 'checkbox':53input_def['name'] = 'chk_' + input['name'];54input_field = new Ext.form.Checkbox(input_def);55break;56case 'checkboxgroup':57input_def['name'] = 'chkg_' + input['name'];58input_def['items'] = input['items'];59input_field = new Ext.form.CheckboxGroup(input_def);60break;61case 'combobox':62input_def['name'] = 'com_' + input['name'];63input_def['triggerAction'] = 'all';6465if(input.reloadOnChange || input.defaultPayload != null) { // defined in msfcommand.rb66Ext.getCmp("payload-panel").show(); // initially the panel will be empty so it may appear still hidden67input_def['listeners'] = {68// update the payload options when one of them is selected69'select': function(combo, value) {70get_dynamic_payload_details(combo.getValue(), zombie);71},72// set the default payload value as defined in defaultPayload73'afterrender': function(combo){74combo.setValue(input.defaultPayload);75get_dynamic_payload_details(combo.getValue(),zombie);76}77};78}798081// create store to contain options for the combo box82input_def['store'] = new Ext.data.ArrayStore( {83fields: input['store_fields'],84data: input['store_data']85});8687input_field = new Ext.form.ComboBox(input_def);8889break;90default:91input_field = new Ext.form.TextField(input_def);92break;93}9495// add the properties for the input element, for example: widths, default values and the html lables96for(definition in input) {97if( (typeof input[definition] == 'string') && (definition != 'type') && (definition != 'name')) {98input_field[definition] = input[definition];99}100}101102if(value) input_field.setValue(value);103if(disabled) input_field.setDisabled(true);104105form.add(input_field);106return input_field;107};108109function get_dynamic_payload_details(payload, zombie) {110modid = Ext.getCmp('form-zombie-' + zombie.session + '-field-mod_id').value;111Ext.Ajax.request({112loadMask: true,113url: '<%= @base_path %>/modules/select/commandmodule.json',114method: 'POST',115params: 'command_module_id=' + modid + '&' + 'payload_name=' + payload,116success: function(resp) {117var module = Ext.decode(resp.responseText);118module = module.command_modules[1][0];119Ext.getCmp("payload-panel").removeAll(); // clear the panel contents120Ext.each(module.data , function(input){121// generate each of the payload input options122generate_form_input_field(Ext.getCmp("payload-panel"), input, null, false, zombie);123});124125Ext.getCmp("payload-panel").doLayout();126}127})128}129130/**131* Generate a panel for an command module that already has been executed.132*133* @param: {Object} the Panel in the UI to generate the form into.134* @param: {Integer} the command id to generate the panel for.135* @param: {Object} the targeted Zombie.136* @param: {Object} the status bar.137*/138function genExistingExploitPanel(panel, command_id, zombie, sb) {139if(typeof panel != 'object') {140Ext.beef.msg('Bad!', 'Incorrect panel chosen.');141return;142}143144sb.showBusy(); // status bar update145panel.removeAll();146147Ext.Ajax.request({148url: '<%= @base_path %>/modules/select/command.json',149method: 'POST',150params: 'command_id=' + command_id,151loadMask: true,152success: function(resp) {153var xhr = Ext.decode(resp.responseText);154155if(!xhr || !xhr.definition) {156Ext.beef.msg('Error!', 'We could not retrieve the definition of that command module...');157return;158}159160var form = new Ext.form.FormPanel({161url: '<%= @base_path %>/modules/commandmodule/reexecute',162id: 'form-command-module-zombie-'+zombie.session,163border: false,164labelWidth: 75,165defaultType: 'textfield',166title: re_execute_command_title,167bodyStyle: 'padding: 5px;',168169items: [new Ext.form.Hidden({name: 'command_id', value: command_id})],170171buttons:[{172text: zombie_reexecute_button_text,173handler: function() {174var form = Ext.getCmp('form-command-module-zombie-'+zombie.session);175if(!form || !form.getForm().isValid()) return;176177sb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update178179var command_module_form = form.getForm(); // form to be submitted when execute button is pressed on an command module tab180command_module_form.submit({181params: { // insert the nonce with the form182nonce: Ext.get ("nonce").dom.value183},184success: function() {185sb.update_sent("Commands sent to zombie " + zombie.ip); // status bar update186},187failure: function() {188sb.update_fail("Error!"); // status bar update189}190});191}192}]193});194195Ext.each(xhr.definition.Data, function(input) {196var value = null;197198if(typeof input == 'string') {199value = xhr.data[input];200}201202if(typeof input == 'object' && typeof input[0] == 'object') {203value = xhr.data[input[0]['name']]204}205206generate_form_input_field(form, input, value, false, zombie);207});208209var grid_store = new Ext.data.JsonStore({210url: '<%= @base_path %>/modules/select/command_results.json?command_id='+command_id,211storeId: 'command-results-store-zombie-'+zombie.session,212root: 'results',213remoteSort: false,214autoDestroy: true,215fields: [216{name: 'date', type: 'date', dateFormat: 'timestamp'},217{name: 'data'}218]219});220221Ext.TaskMgr.start({222run: function(task) {223var grid = Ext.getCmp('command-results-grid-zombie-'+zombie.session);224//here we have to check for the existance of the grid before reloading225//because we do not want to reload the store if the tab has been closed.226if(grid_store && grid) {227grid_store.reload();228}229},230interval: 4000231});232233var grid = new Ext.grid.GridPanel({234id: 'command-results-grid-zombie-'+zombie.session,235store: grid_store,236border: false,237hideHeaders: true,238title: 'Command results',239240viewConfig: {241forceFit:true242},243244// render command responses245columns:[new Ext.grid.RowNumberer({width: 20}), {246dataIndex: 'date',247sortable: false,248renderer: function(value, p, record) {249html = String.format("<div style='color:#385F95;text-align:right;'>{0}</div>", value);250html += '<p>';251for(index in record.data.data) {252result = record.data.data[index];253index = index.toString().replace('_', ' ');254255// Check for a base64 encoded image256var header = "image=data:image/(jpg|png);base64,";257var re = new RegExp(header, "");258if (result.match(re)) {259260// Render the image261try {262var img = result.replace(/[\r\n]/g, '');263base64_data = window.atob(img.replace(re, ''));264html += String.format('<img src="{0}" /><br>', img.replace(/^image=/, ''));265} catch(e) {266console.log("Received invalid base64 encoded image string: "+e.toString());267html += String.format('<b>{0}</b>: {1}<br>', index, result);268}269270// output escape everything else, but allow the <br> tag for better rendering.271} else {272html += String.format('<b>{0}</b>: {1}<br>', index, $jEncoder.encoder.encodeForHTML(result).replace(/<br>/g,'<br>'));273}274}275276html += '</p>';277return html;278}279}]280});281282grid.store.load();283284var accordion = new Ext.Panel({285id: 'command-results-accordion-zombie-'+zombie.session,286layout:'accordion',287border: false,288items: [grid, form]289});290291panel.add(accordion);292panel.doLayout();293294sb.update_ready(); // status bar update295}296});297};298299/**300* Generate a panel for an command module.301*302* @param: {Object} the Panel in the UI to generate the form into.303* @param: {String} the path to the command module file in the framework.304* @param: {String} the name of the command module.305* @param: {Object} the targeted Zombie.306* @param: {Object} the status bar.307*/308function genNewExploitPanel(panel, command_module_id, command_module_name, zombie, sb) {309if(typeof panel != 'object') {310Ext.beef.msg('Bad!', 'Incorrect panel chosen.');311return;312}313314var xgrid = Ext.getCmp('command-module-grid-zombie-'+zombie.session);315var sb = Ext.getCmp('commands-bbar-zombie-'+zombie.session);316panel.removeAll();317if(command_module_name == 'some special command module') {318//HERE we will develop specific panels for the command modules that require it.319} else {320Ext.Ajax.request({321loadMask: true,322url: '<%= @base_path %>/modules/select/commandmodule.json',323method: 'POST',324params: 'command_module_id=' + command_module_id,325success: function(resp) {326var module = Ext.decode(resp.responseText);327328if(!module) {329Ext.beef.msg('Error!', 'We could not retrieve the definition of that command_module...');330return;331}332333var submiturl = '<%= @base_path %>/modules/commandmodule/new';334if(module.dynamic){335submiturl = '<%= @base_path %>/modules/commandmodule/dynamicnew';336}337338module = module.command_modules[1];339340var form = new Ext.form.FormPanel({341url: submiturl,342343id: 'form-command-module-zombie-'+zombie.session,344border: false,345labelWidth: 75,346defaultType: 'textfield',347title: module.Name,348autoScroll: true,349bodyStyle: 'padding: 5px;',350351items: [352new Ext.form.Hidden({name: 'zombie_session', value: zombie.session}),353new Ext.form.Hidden({name: 'command_module_id', value: command_module_id}),354new Ext.form.DisplayField({355name: 'command_module_description',356fieldLabel: 'Description',357fieldClass: 'command-module-panel-description',358value: module.Description359}),360new Ext.form.DisplayField({361name: 'command_module_id_visible',362fieldLabel: 'Id',363fieldClass: 'command-module-panel-description',364value: command_module_id365})366],367368buttons:[{369text: zombie_execute_button_text,370handler: function() {371var form = Ext.getCmp('form-command-module-zombie-'+zombie.session), command_module_params = new Array();372373if(!form || !form.getForm().isValid()) {374sb.update_fail("Please complete all input fields!"); // status bar update375return;376}377378sb.update_sending('Sending commands to ' + zombie.ip + '...'); // status bar update379380var command_module_form = form.getForm(); // form to be submitted when execute button is pressed on an command module tab381382command_module_form.submit({383params: { // insert the nonce with the form384nonce: Ext.get ("nonce").dom.value385},386success: function() {387xgrid.i = 0;388xgrid.store.reload({ //reload the command module grid389params: { // insert the nonce with the request to reload the grid390nonce: Ext.get ("nonce").dom.value391}392});393sb.update_sent("Commands sent to zombie " + zombie.ip); // status bar update394},395failure: function() {396sb.update_fail("Error!"); // status bar update397}398});399}400}]401});402403// create the panel and hide it404var payload_panel = new Ext.Panel({405id: 'payload-panel', // used with Ext.GetCmp('payload-panel')406bodyStyle: 'padding:10px;', // we can assign styles to the main div407layout : 'form',408bodyBorder: false,409height: 200,410hidden: true,411border: false //we can remove the border of the panel412});413414Ext.each(module.Data, function(input){415generate_form_input_field(form, input, null, false, zombie)}416);417418form.add(payload_panel);419panel.add(form);420panel.doLayout();421// hide the load mask after rendering of the config panel is done422panel.configLoadMask.hide();423}424});425}426};427428