Autorun UI elements now match command module elements.
This commit is contained in:
@@ -25,21 +25,20 @@ module BeEF
|
||||
get '/' do
|
||||
mods = BeEF::Core::Models::CommandModule.all
|
||||
|
||||
mods_hash = {}
|
||||
i = 0
|
||||
mods_array = []
|
||||
|
||||
mods.each do |mod|
|
||||
modk = BeEF::Module.get_key_by_database_id(mod.id)
|
||||
next unless BeEF::Module.is_enabled(modk)
|
||||
|
||||
mods_hash[i] = {
|
||||
mods_array << {
|
||||
'id' => mod.id,
|
||||
'class' => config.get("beef.module.#{modk}.class"),
|
||||
'name' => config.get("beef.module.#{modk}.name"),
|
||||
'category' => config.get("beef.module.#{modk}.category")
|
||||
}
|
||||
i += 1
|
||||
end
|
||||
mods_hash.to_json
|
||||
mods_array.to_json
|
||||
end
|
||||
|
||||
get '/search/:mod_name' do
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
|
||||
loadModuleInfo = async function(token, moduleName) {
|
||||
let moduleId = null;
|
||||
try {
|
||||
const searchResponse = await fetch(`/api/modules/search/${moduleName}?token=${token}`);
|
||||
if (!searchResponse.ok) {
|
||||
throw new Error(`Getting auto run rules failed with status ${searchResponse.status}`);
|
||||
}
|
||||
const searchData = await searchResponse.json();
|
||||
console.log("Search data:");
|
||||
console.log(searchData);
|
||||
if (typeof searchData.id === 'number') {
|
||||
moduleId = searchData.id;
|
||||
} else {
|
||||
throw new Error("Searching module name failed.");
|
||||
}
|
||||
|
||||
// DEBUG log
|
||||
console.log(`Successfully retrieved module id for ${moduleName} = ${moduleId}`);
|
||||
|
||||
const infoResponse = await fetch(`/api/modules/${moduleId}?token=${token}`);
|
||||
const infoData = await infoResponse.json();
|
||||
if (!infoData) {
|
||||
throw new Error(`Module with name ${moduleName} and ID ${moduleId} couldn't be retrived.`);
|
||||
}
|
||||
return infoData;
|
||||
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
console.error("Failed to get module information.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Form that displays fields for a module.
|
||||
*
|
||||
@@ -9,22 +44,37 @@
|
||||
AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, index) {
|
||||
const moduleTextAreaId = `rule-${ruleId}-module-textarea-${index}`;
|
||||
const chainModeComboId = `rule-${ruleId}-module-combo-${index}`;
|
||||
const token = BeefWUI.get_rest_token();
|
||||
|
||||
// TODO: Load in modules from ruby.
|
||||
/*
|
||||
const moduleSelect = new Ext.form.ComboBox({
|
||||
fieldLabel: 'Command Module',
|
||||
store: [{name: 'hi', id: 1}],
|
||||
queryMode: 'local', // Set the queryMode to 'remote'
|
||||
displayField: 'name',
|
||||
valueField: 'id',
|
||||
editable: false, // Disable manual editing of the field
|
||||
forceSelection: true, // Force selection from the list
|
||||
//listeners: {
|
||||
// render: function (combo) {
|
||||
// combo.setValue(moduleData.name);
|
||||
// },
|
||||
// select: function(combo, newValue, oldValue) {
|
||||
// if (newValue) {
|
||||
// console.log("Combo value selected.");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
});
|
||||
*/
|
||||
|
||||
const moduleOptionsContainer = new Ext.Panel({
|
||||
padding: '5 5 5 5',
|
||||
border: false,
|
||||
title: `${moduleData.name}`,
|
||||
padding: '10 10 10 10',
|
||||
layout: 'form',
|
||||
items: [/*{
|
||||
xtype: 'combo',
|
||||
id: chainModeComboId,
|
||||
fieldLabel: 'Chain Mode',
|
||||
store: ['moduleA', 'moduleB'], // TODO: Update this to the array of commands.
|
||||
queryMode: 'local', // Use local data.
|
||||
triggerAction: 'all', // Show both options instead of just the default.
|
||||
editable: false, // Disable manual text input.
|
||||
forceSelection: true,
|
||||
value: moduleData.name,
|
||||
},*/
|
||||
border: false,
|
||||
items: [
|
||||
{
|
||||
xtype: 'displayfield',
|
||||
fieldLabel: 'Module Name',
|
||||
@@ -35,23 +85,42 @@ AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, ind
|
||||
fieldLabel: 'Module Author',
|
||||
value: moduleData.author ? moduleData.author : 'anonymous',
|
||||
}
|
||||
]
|
||||
],
|
||||
listeners: {
|
||||
afterrender: loadModule
|
||||
}
|
||||
});
|
||||
|
||||
function loadModule() {
|
||||
|
||||
async function loadModule() {
|
||||
// TODO: Need to query module option types so that not everything is given a textfield.
|
||||
const moduleInfo = await loadModuleInfo(token, moduleData.name);
|
||||
if (!moduleInfo) {
|
||||
moduleOptionsContainer.update("<p>Failed to load module information.</p>");
|
||||
return;
|
||||
}
|
||||
console.log("Module data:");
|
||||
console.log(moduleData);
|
||||
for (key in moduleData.options) {
|
||||
const value = moduleData.options[key];
|
||||
const inputField = new Ext.form.TextField({
|
||||
fieldLabel: key,
|
||||
value: value ? value : '',
|
||||
});
|
||||
moduleOptionsContainer.add(inputField);
|
||||
console.log("Module info:");
|
||||
console.log(JSON.stringify(moduleInfo, null, 2));
|
||||
console.log("Module options, should be an array:");
|
||||
console.log(moduleInfo.options);
|
||||
|
||||
//genNewAutoRunModulePanel(moduleOptionsContainer, moduleInfo, ruleId);
|
||||
|
||||
for (let i = 0; i < moduleInfo.options.length; i++) {
|
||||
console.log(JSON.stringify(moduleInfo.options[i], null, 2));
|
||||
// TODO add real autorun module value by default.
|
||||
generate_form_input_field(
|
||||
moduleOptionsContainer,
|
||||
moduleInfo.options[i],
|
||||
null,
|
||||
false,
|
||||
{session: `${moduleInfo.name}-module-${index}-field-${i}`}
|
||||
);
|
||||
};
|
||||
moduleOptionsContainer.doLayout();
|
||||
}
|
||||
loadModule();
|
||||
|
||||
const buttonContainer = new Ext.Container({
|
||||
layout: {
|
||||
@@ -79,12 +148,12 @@ AutoRunModuleForm = function(moduleData, deleteFn, moveUp, moveDown, ruleId, ind
|
||||
|
||||
|
||||
AutoRunModuleForm.superclass.constructor.call(this, {
|
||||
padding: '10 10 10 10',
|
||||
closable: false,
|
||||
items: [
|
||||
//moduleSelect,
|
||||
moduleOptionsContainer,
|
||||
buttonContainer
|
||||
]});
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
Ext.extend(AutoRunModuleForm, Ext.Panel, {});
|
||||
Ext.extend(AutoRunModuleForm, Ext.Container, {});
|
||||
@@ -18,10 +18,11 @@ const areNotificationUpdateTest = {
|
||||
* Form for the user to read, update and delete a specific Auto Run rule.
|
||||
*
|
||||
* rule: The object definition of this rule from the Auto Run Engine.
|
||||
* modules: The list of all commands/modules that the user can choose from.
|
||||
* deleteFn: callback function to delete this rule.
|
||||
* updateFn: callback function to update this rule.
|
||||
*/
|
||||
AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
||||
AutoRunRuleForm = function(rule, modules, deleteFn, updateFn) {
|
||||
const self = this;
|
||||
const ruleTextFieldId = `rule-name-${rule.id}`;
|
||||
const chainModeComboId = `rule-chain-mode-${rule.id}`;
|
||||
@@ -31,6 +32,9 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
||||
const moduleContainer = new Ext.Container({
|
||||
style: {
|
||||
padding: '10 10 10 10',
|
||||
},
|
||||
listeners: {
|
||||
afterrender: setupModuleForms
|
||||
}
|
||||
});
|
||||
|
||||
@@ -72,7 +76,7 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
||||
moduleContainer.removeAll(true);
|
||||
|
||||
// I think execution order should always be sequential.
|
||||
// The actual order comed from the modules array.
|
||||
// The actual order comes from the modules array.
|
||||
for (let i = 0; i < newRule.modules.length; ++i) {
|
||||
const isFirstModule = i === 0;
|
||||
const isLastModule = i >= newRule.modules.length - 1;
|
||||
@@ -86,7 +90,6 @@ AutoRunRuleForm = function(rule, deleteFn, updateFn) {
|
||||
));
|
||||
}
|
||||
}
|
||||
setupModuleForms();
|
||||
|
||||
function handleUpdateRule() {
|
||||
// TODO: Check if inputs are valid.
|
||||
|
||||
@@ -30,8 +30,6 @@ getCurrentRules = async function(token) {
|
||||
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
||||
}
|
||||
const data = await res.json();
|
||||
console.log("Successfully retrieved active rules.");
|
||||
console.log(data);
|
||||
const rules = JSON.parse(data.rules);
|
||||
|
||||
if (data.success === true && Array.isArray(rules)) {
|
||||
@@ -49,6 +47,27 @@ getCurrentRules = async function(token) {
|
||||
}
|
||||
}
|
||||
|
||||
getModules = async function(token) {
|
||||
try {
|
||||
var res = await fetch(`/api/modules?token=${token}`);
|
||||
if (!res.ok) {
|
||||
throw new Error(`Getting auto run rules failed with status ${res.status}`);
|
||||
}
|
||||
const modules = await res.json();
|
||||
|
||||
// DEBUG log
|
||||
console.log("Successfully retrieved active modules:");
|
||||
console.log(modules);
|
||||
|
||||
return modules;
|
||||
|
||||
} catch(error) {
|
||||
console.error(error);
|
||||
console.error("Failed to get auto run rules.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
AutoRunTab = function() {
|
||||
// RESTful API token.
|
||||
var token = BeefWUI.get_rest_token();
|
||||
@@ -128,7 +147,18 @@ AutoRunTab = function() {
|
||||
}
|
||||
|
||||
async function loadRules() {
|
||||
const rules = await getCurrentRules(token);
|
||||
let modules = [];
|
||||
let rules = [];
|
||||
try {
|
||||
modules = await getModules(token);
|
||||
rules = await getCurrentRules(token);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
console.error("Failed to load command modules and/or rules for Auto Run.");
|
||||
ruleLoadingState.update("<p>Failed to load Auto Run rules.</p>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (rules !== null) {
|
||||
ruleLoadingState.update(`<p>Loaded ${rules.length} Auto Run rules.</p>`);
|
||||
ruleContainer.removeAll();
|
||||
@@ -136,6 +166,7 @@ AutoRunTab = function() {
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
ruleForm = new AutoRunRuleForm(
|
||||
rules[i],
|
||||
modules,
|
||||
function() {deleteRule(rules[i].id)},
|
||||
function(newRuleData) {updateRule(rules[i].id, newRuleData)}
|
||||
);
|
||||
|
||||
@@ -20,6 +20,8 @@ var re_execute_command_title = 'Re-execute command'
|
||||
function generate_form_input_field(form, input, value, disabled, zombie) {
|
||||
var input_field = null;
|
||||
var input_def = null;
|
||||
console.log("Input type: ");
|
||||
console.log(JSON.stringify(input, null, 2));
|
||||
|
||||
if (!input['ui_label']) input['ui_label'] = input['name'];
|
||||
if (!input['type']) input['type'] = 'textfield';
|
||||
@@ -33,6 +35,8 @@ function generate_form_input_field(form, input, value, disabled, zombie) {
|
||||
allowBlank: false,
|
||||
value: input['value']
|
||||
};
|
||||
console.log("Input Def:");
|
||||
console.log(JSON.stringify(input_def, null, 2));
|
||||
|
||||
// create the input field object based upon the type supplied
|
||||
switch(input['type'].toLowerCase()) {
|
||||
@@ -100,9 +104,11 @@ function generate_form_input_field(form, input, value, disabled, zombie) {
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Before setting values input field.");
|
||||
if(value) input_field.setValue(value);
|
||||
if(disabled) input_field.setDisabled(true);
|
||||
|
||||
console.log("Before adding input field to form values input field.");
|
||||
form.add(input_field);
|
||||
|
||||
};
|
||||
@@ -425,63 +431,3 @@ function genNewExploitPanel(panel, command_module_id, command_module_name, zombi
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function genNewAutoRunModulePanel(panel, module, ruleId) {
|
||||
if(typeof panel != 'object') {
|
||||
Ext.beef.msg('Bad!', 'Incorrect panel chosen.');
|
||||
return;
|
||||
}
|
||||
|
||||
panel.removeAll();
|
||||
if(module.name == 'some special command module') {
|
||||
//HERE we will develop specific panels for the command modules that require it.
|
||||
} else {
|
||||
var form = new Ext.form.FormPanel({
|
||||
id: `form-are-module-${ruleId}`,
|
||||
border: false,
|
||||
labelWidth: 75,
|
||||
defaultType: 'textfield',
|
||||
title: module.name,
|
||||
bodyStyle: 'padding: 5px;',
|
||||
|
||||
items: [
|
||||
new Ext.form.DisplayField({
|
||||
name: 'command_module_description',
|
||||
fieldLabel: 'Description',
|
||||
fieldClass: 'command-module-panel-description',
|
||||
value: module.description
|
||||
}),
|
||||
],
|
||||
|
||||
buttons:[{
|
||||
text: "Save Module",
|
||||
handler: function() {console.log("Saved module...")}
|
||||
}]
|
||||
});
|
||||
|
||||
// create the panel and hide it
|
||||
/*
|
||||
var payload_panel = new Ext.Panel({
|
||||
id: 'payload-panel', // used with Ext.GetCmp('payload-panel')
|
||||
bodyStyle: 'padding:10px;', // we can assign styles to the main div
|
||||
layout : 'form',
|
||||
bodyBorder: false,
|
||||
height: 200,
|
||||
hidden: true,
|
||||
border: false //we can remove the border of the panel
|
||||
});
|
||||
*/
|
||||
|
||||
Ext.each(module.Data, function(input){
|
||||
// Fake a zombie "session" property for the sake of getting it working.
|
||||
generate_form_input_field(form, input, null, false, {session: module.name})}
|
||||
);
|
||||
|
||||
//form.add(payload_panel);
|
||||
panel.add(form);
|
||||
panel.doLayout();
|
||||
// hide the load mask after rendering of the config panel is done
|
||||
//panel.configLoadMask.hide();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user