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:
antisnatchor
2016-03-14 16:43:59 +01:00
parent d84c8ef976
commit 85b1afb861
2 changed files with 44 additions and 31 deletions

View File

@@ -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