metasploit-framework/lib/rex/exploitation/obfuscatejs.rb

106 lines
2.1 KiB
Ruby

module Rex
module Exploitation
#
# Obfuscates javascript in various ways
#
class ObfuscateJS
#
# Obfuscates symbols found within a javascript string. The symbols
# argument should have the following format:
#
# {
# 'Variables' => [ 'var1', ... ],
# 'Methods' => [ 'method1', ... ],
# 'Classes' => [ { 'Namespace' => 'n', 'Class' => 'y'}, ... ],
# 'Namespaces' => [ 'n', ... ]
# }
#
# Make sure you order your methods, classes, and namespaces by most
# specific to least specific to prevent partial substitution. For
# instance, if you have two methods (joe and joeBob), you should place
# joeBob before joe because it is more specific and will be globally
# replaced before joe is replaced.
#
def self.obfuscate(js, opts = {})
ObfuscateJS.new(js).obfuscate(opts)
end
#
# Initialize an instance of the obfuscator
#
def initialize(js)
@js = js
@dynsym = {}
end
#
# Returns the dynamic symbol associated with the supplied symbol name
#
def sym(name)
@dynsym[name] || name
end
#
# Obfuscates the javascript string passed to the constructor
#
def obfuscate(opts = {})
# Remove our comments
remove_comments
# Globally replace symbols
replace_symbols(opts['Symbols']) if opts['Symbols']
@js
end
#
# Returns the replaced javascript string
#
def to_s
@js
end
protected
# Get rid of comments
def remove_comments
@js.gsub!(/(\/\/.+?\n)/m, '')
end
# Replace method, class, and namespace symbols found in the javascript
# string
def replace_symbols(symbols)
taken = { }
# Generate random symbol names
[ 'Variables', 'Methods', 'Classes', 'Namespaces' ].each { |symtype|
next if symbols[symtype].nil?
symbols[symtype].each { |sym|
dyn = Rex::Text.rand_text_alpha(rand(32)+1) until dyn and not taken.key?(dyn)
taken[dyn] = true
if symtype == 'Classes'
full_sym = sym['Namespace'] + "." + sym['Class']
@dynsym[full_sym] = dyn
@js.gsub!(/#{full_sym}/) { |m|
sym['Namespace'] + "." + dyn
}
else
@dynsym[sym] = dyn
@js.gsub!(/#{sym}/, dyn)
end
}
}
end
end
end
end