class JSObfu::Scope
A single Javascript scope, used as a key-value store to maintain uniqueness of members in generated closures. For speed this class is implemented as a subclass of Hash.
Constants
- BUILTIN_VARS
these vars should not be shadowed as they in the exploit code, and generating them would cause problems.
- RESERVED_KEYWORDS
these keywords should never be used as a random var name source: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words
Attributes
@return [JSObfu::Scope] parent that spawned this scope
@return [Hash] mapping old var names to random ones
Public Class Methods
@param [Hash] opts the options hash @option opts [Rex::Exploitation::JSObfu::Scope] :parent an optional parent scope,
sometimes necessary to prevent needless var shadowing
@option opts [Integer] :min_len minimum length of the var names
# File lib/jsobfu/scope.rb, line 38 def initialize(opts={}) @parent = opts[:parent] @first_char_set = opts[:first_char_set] || [*'A'..'Z']+[*'a'..'z']+['_', '$'] @char_set = opts[:first_char_set] || @first_char_set + [*'0'..'9'] @min_len = opts[:min_len] || 1 @renames = {} end
Public Instance Methods
@return [Boolean] scope has members
# File lib/jsobfu/scope.rb, line 98 def empty? self.keys.empty? and (parent.nil? or parent.empty?) end
Check if we've used this var before. This will also check any attached parent scopes (and their parents, recursively)
@return [Boolean] whether var is in scope
# File lib/jsobfu/scope.rb, line 117 def has_key?(key) super or (parent and parent.has_key?(key)) end
“Consumes” the parent and replaces self with it
# File lib/jsobfu/scope.rb, line 134 def pop! clear if @parent merge! @parent @renames = @parent.renames @parent = @parent.parent end end
replaces this Scope in the “parent” chain with a copy, empties current scope, and returns. Essentially an in-place push operation
# File lib/jsobfu/scope.rb, line 124 def push! replacement = dup replacement.parent = @parent replacement.renames = @renames @renames = {} @parent = replacement clear end
@return [String] a random string that can be used as a var
# File lib/jsobfu/scope.rb, line 144 def random_string(len) @first_char_set.sample + (len-1).times.map { @char_set.sample }.join end
Generates a unique, “safe” random variable @return [String] a unique random var name that is not a reserved keyword
# File lib/jsobfu/scope.rb, line 48 def random_var_name len = @min_len loop do text = random_string(len) unless has_key?(text) or RESERVED_KEYWORDS.include?(text) or BUILTIN_VARS.include?(text) self[text] = nil return text end len += 1 end end
Re-maps your var_name
to a unique, random names in the current
scope
@param var_name [String] the name you want to replace. This
name will be remembered in the #renames hash
@param opts [Hash] the options hash @option opts [Boolean] :generate if the variable was not
explicitly renamed before, in this scope or any parent scope, generate a new random name
@return [String] the randomly generated replacement name @return nil if
generate=false and var_name
was not already replaced
# File lib/jsobfu/scope.rb, line 76 def rename_var(var_name, opts={}) return var_name if BUILTIN_VARS.include?(var_name) generate = opts.fetch(:generate, true) unresolved = opts.fetch(:unresolved, []) renamed = @renames[var_name] if renamed.nil? and parent renamed = parent.rename_var(var_name, :generate => false) end if renamed.nil? and generate @renames[var_name] = random_var_name renamed = @renames[var_name] end #puts "Mapped #{var_name} => #{renamed}" if renamed renamed end
# File lib/jsobfu/scope.rb, line 107 def top p = self p = p.parent until p.parent.nil? p end
@return [Boolean] scope has no parent
# File lib/jsobfu/scope.rb, line 103 def top? parent.nil? end