Fixed #1203 Now wrapping function names are appended with 8 bytes of random hexchars, to prevent name collisions. The rule_token "seed" is also stored in the ARE Execution table.
This commit is contained in:
@@ -44,6 +44,10 @@ module BeEF
|
||||
mods_codes = Array.new
|
||||
mods_conditions = Array.new
|
||||
|
||||
# this ensures that if both rule A and rule B call the same module in sequential mode,
|
||||
# execution will be correct preventing wrapper functions to be called with equal names.
|
||||
rule_token = SecureRandom.hex(5)
|
||||
|
||||
modules.each do |cmd_mod|
|
||||
mod = BeEF::Core::Models::CommandModule.first(:name => cmd_mod['name'])
|
||||
options = []
|
||||
@@ -53,7 +57,9 @@ module BeEF
|
||||
replace_input = true if v == '<<mod_input>>'
|
||||
end
|
||||
|
||||
command_body = prepare_command(mod, options, hb_id, replace_input)
|
||||
command_body = prepare_command(mod, options, hb_id, replace_input, rule_token)
|
||||
|
||||
|
||||
mods_bodies.push(command_body)
|
||||
mods_codes.push(cmd_mod['code'])
|
||||
mods_conditions.push(cmd_mod['condition'])
|
||||
@@ -62,11 +68,12 @@ module BeEF
|
||||
# Depending on the chosen chain mode (sequential or nested/forward), prepare the appropriate wrapper
|
||||
case chain_mode
|
||||
when 'nested-forward'
|
||||
wrapper = prepare_nested_forward_wrapper(mods_bodies, mods_codes, mods_conditions, execution_order)
|
||||
wrapper = prepare_nested_forward_wrapper(mods_bodies, mods_codes, mods_conditions, execution_order, rule_token)
|
||||
when 'sequential'
|
||||
wrapper = prepare_sequential_wrapper(mods_bodies, execution_order, execution_delay)
|
||||
wrapper = prepare_sequential_wrapper(mods_bodies, execution_order, execution_delay, rule_token)
|
||||
else
|
||||
wrapper = nil
|
||||
print_error "Chain mode looks wrong!"
|
||||
# TODO catch error, which should never happen as values are checked way before ;-)
|
||||
end
|
||||
|
||||
@@ -74,6 +81,7 @@ module BeEF
|
||||
:session => hb_session,
|
||||
:mod_count => modules.length,
|
||||
:mod_successful => 0,
|
||||
:rule_token => rule_token,
|
||||
:mod_body => wrapper,
|
||||
:is_sent => false,
|
||||
:rule_id => rule_id
|
||||
@@ -93,14 +101,14 @@ module BeEF
|
||||
# setTimeout(module_three(), 3000);
|
||||
# Note: no result status is checked here!! Useful if you just want to launch a bunch of modules without caring
|
||||
# what their status will be (for instance, a bunch of XSRFs on a set of targets)
|
||||
def prepare_sequential_wrapper(mods, order, delay)
|
||||
def prepare_sequential_wrapper(mods, order, delay, rule_token)
|
||||
wrapper = ''
|
||||
delayed_exec = ''
|
||||
c = 0
|
||||
|
||||
while c < mods.length
|
||||
delayed_exec += %Q| setTimeout("#{mods[order[c]][:mod_name]}();", #{delay[c]}); |
|
||||
wrapped_mod = "#{mods[order[c]][:mod_body]}\n"
|
||||
delayed_exec += %Q| setTimeout("#{mods[order[c]][:mod_name]}_#{rule_token}();", #{delay[c]}); |
|
||||
mod_body = mods[order[c]][:mod_body].to_s.gsub("#{mods[order[c]][:mod_name]}_mod_output", "#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output")
|
||||
wrapped_mod = "#{mod_body}\n"
|
||||
wrapper += wrapped_mod
|
||||
c += 1
|
||||
end
|
||||
@@ -124,7 +132,7 @@ module BeEF
|
||||
# Note: Useful in situations where you want to launch 2 modules, where the second one will execute only
|
||||
# if the first once return with success. Also, the second module has the possibility of mangling first
|
||||
# module output and use it as input for some of its module inputs.
|
||||
def prepare_nested_forward_wrapper(mods, code, conditions, order)
|
||||
def prepare_nested_forward_wrapper(mods, code, conditions, order, rule_token)
|
||||
wrapper, delayed_exec = '',''
|
||||
delayed_exec_footers = Array.new
|
||||
c = 0
|
||||
@@ -148,8 +156,8 @@ module BeEF
|
||||
if c == 0
|
||||
# this is the first wrapper to prepare
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
#{mods[order[c]][:mod_name]}();
|
||||
function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}();
|
||||
|
||||
// TODO add timeout to prevent infinite loops
|
||||
function isResReady(mod_result, start){
|
||||
@@ -165,8 +173,8 @@ module BeEF
|
||||
}
|
||||
var status = mod_result[0];
|
||||
if(#{conditions[i]}){
|
||||
#{mods[order[i]][:mod_name]}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_mod_output = mod_result[1];
|
||||
#{mods[order[i]][:mod_name]}_#{rule_token}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output = mod_result[1];
|
||||
|
|
||||
|
||||
delayed_exec_footer = %Q|
|
||||
@@ -174,20 +182,22 @@ module BeEF
|
||||
}
|
||||
}
|
||||
var start = (new Date()).getTime();
|
||||
var resultReady = setInterval(function(){var start = (new Date()).getTime(); isResReady(#{mods[order[c]][:mod_name]}_mod_output, start);},#{@result_poll_interval});
|
||||
var resultReady = setInterval(function(){var start = (new Date()).getTime(); isResReady(#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output, start);},#{@result_poll_interval});
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}_f();
|
||||
|
|
||||
|
||||
delayed_exec_footers.push(delayed_exec_footer)
|
||||
|
||||
elsif c < mods.length - 1
|
||||
code_snippet = code_snippet.to_s.gsub(mods[order[c-1]][:mod_name], "#{mods[order[c-1]][:mod_name]}_#{rule_token}")
|
||||
|
||||
# this is one of the wrappers in the middle of the chain
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_can_exec){
|
||||
function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_#{rule_token}_can_exec){
|
||||
#{code_snippet}
|
||||
#{mods[order[c]][:mod_name]}(#{mod_input});
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}(#{mod_input});
|
||||
function isResReady(mod_result, start){
|
||||
if (mod_result === null && parseInt(((new Date().getTime()) - start)) < #{@result_poll_timeout}){
|
||||
// loop
|
||||
@@ -201,8 +211,8 @@ module BeEF
|
||||
}
|
||||
var status = mod_result[0];
|
||||
if(#{conditions[i]}){
|
||||
#{mods[order[i]][:mod_name]}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_mod_output = mod_result[1];
|
||||
#{mods[order[i]][:mod_name]}_#{rule_token}_can_exec = true;
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output = mod_result[1];
|
||||
|
|
||||
|
||||
delayed_exec_footer = %Q|
|
||||
@@ -210,26 +220,28 @@ module BeEF
|
||||
}
|
||||
}
|
||||
var start = (new Date()).getTime();
|
||||
var resultReady = setInterval(function(){ isResReady(#{mods[order[c]][:mod_name]}_mod_output, start);},#{@result_poll_interval});
|
||||
var resultReady = setInterval(function(){ isResReady(#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output, start);},#{@result_poll_interval});
|
||||
}
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}_f();
|
||||
|
|
||||
|
||||
delayed_exec_footers.push(delayed_exec_footer)
|
||||
else
|
||||
code_snippet = code_snippet.to_s.gsub(mods[order[c-1]][:mod_name], "#{mods[order[c-1]][:mod_name]}_#{rule_token}")
|
||||
# this is the last wrapper to prepare
|
||||
delayed_exec += %Q|
|
||||
function #{mods[order[c]][:mod_name]}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_can_exec){
|
||||
function #{mods[order[c]][:mod_name]}_#{rule_token}_f(){
|
||||
if(#{mods[order[c]][:mod_name]}_#{rule_token}_can_exec){
|
||||
#{code_snippet}
|
||||
#{mods[order[c]][:mod_name]}(#{mod_input});
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}(#{mod_input});
|
||||
}
|
||||
}
|
||||
#{mods[order[c]][:mod_name]}_f();
|
||||
#{mods[order[c]][:mod_name]}_#{rule_token}_f();
|
||||
|
|
||||
end
|
||||
wrapped_mod = "#{mods[order[c]][:mod_body]}\n"
|
||||
mod_body = mods[order[c]][:mod_body].to_s.gsub("#{mods[order[c]][:mod_name]}_mod_output", "#{mods[order[c]][:mod_name]}_#{rule_token}_mod_output")
|
||||
wrapped_mod = "#{mod_body}\n"
|
||||
wrapper += wrapped_mod
|
||||
c += 1
|
||||
end
|
||||
@@ -242,7 +254,7 @@ module BeEF
|
||||
# prepare the command module (compiling the Erubis templating stuff), eventually obfuscate it,
|
||||
# and store it in the database.
|
||||
# Returns the raw module body after template substitution.
|
||||
def prepare_command(mod, options, hb_id, replace_input)
|
||||
def prepare_command(mod, options, hb_id, replace_input, rule_token)
|
||||
config = BeEF::Core::Configuration.instance
|
||||
begin
|
||||
command = BeEF::Core::Models::Command.new(
|
||||
@@ -285,11 +297,11 @@ module BeEF
|
||||
|
||||
replace_input ? mod_input = 'mod_input' : mod_input = ''
|
||||
result = %Q|
|
||||
var #{mod.name} = function(#{mod_input}){
|
||||
var #{mod.name}_#{rule_token} = function(#{mod_input}){
|
||||
#{clean_command_body(command_body, replace_input)}
|
||||
};
|
||||
var #{mod.name}_can_exec = false;
|
||||
var #{mod.name}_mod_output = null;
|
||||
var #{mod.name}_#{rule_token}_can_exec = false;
|
||||
var #{mod.name}_#{rule_token}_mod_output = null;
|
||||
|
|
||||
|
||||
return {:mod_name => mod.name, :mod_body => result}
|
||||
@@ -349,7 +361,7 @@ module BeEF
|
||||
return cleaned_cmd_body
|
||||
end
|
||||
rescue => e
|
||||
print_error "[ARE] There is likely a problem with the module's command.js parsing. Check Engine.clean_command_body.dd"
|
||||
print_error "[ARE] There is likely a problem with the module's command.js parsing. Check Engine.clean_command_body"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user