class JSObfu

The primary class, used to parse and obfuscate Javascript code.

Constants

VERSION

Attributes

scope[R]

@return [JSObfu::Scope] the global scope

Public Class Methods

new(code=nil, opts={}) click to toggle source

Saves code for later obfuscation with obfuscate @param code [#to_s] the code to obfuscate @param opts [Hash] an options hash @option opts [JSObfu::Scope] a pre-existing scope. This is useful for preserving

variable rename maps between separate obfuscations of different scripts.
# File lib/jsobfu.rb, line 25
def initialize(code=nil, opts={})
  self.code = code
  @scope = opts.fetch(:scope) { Scope.new }
end

Public Instance Methods

<<(str) click to toggle source

Add str to the un-obfuscated code. Calling this method after obfuscate is undefined

# File lib/jsobfu.rb, line 32
def <<(str)
  @code << str
end
ast() click to toggle source

@return [RKelly::Nodes::SourceElementsNode] the abstract syntax tree

# File lib/jsobfu.rb, line 42
def ast
  @ast ||= parse
end
code=(code) click to toggle source

Sets the code that this obfuscator will transform @param [String] code

# File lib/jsobfu.rb, line 48
def code=(code)
  @ast = nil # invalidate any previous parses
  @code = code
end
obfuscate(opts={}) click to toggle source

Parse and obfuscate

@param opts [Hash] the options hash @option opts [Boolean] :strip_whitespace removes unnecessary whitespace from

the output code (true)

@option opts [Integer] :iterations number of times to run the

obfuscator on this code (1)

@option opts [String] :global the global object to rewrite unresolved lookups to.

Depending on the environment, it may be `window`, `global`, or `this`.

@option opts [Boolean] :memory_sensitive the execution environment is sensitive

to changes in memory usage (e.g. a heap spray). This disables string transformations
and other "noisy" obfuscation tactics. (false)

@option opts [Array<String>] :preserved_identifiers A list of identifiers to NOT obfuscate @return [self]

# File lib/jsobfu.rb, line 67
def obfuscate(opts={})
  return self if JSObfu.disabled?
  raise ArgumentError.new("code must be present") if @code.nil?

  iterations = opts.fetch(:iterations, 1).to_i
  strip_whitespace = opts.fetch(:strip_whitespace, true)

  iterations.times do |i|
    obfuscator = JSObfu::Obfuscator.new(opts.merge(scope: @scope))
    @code = obfuscator.accept(ast).to_s
    if strip_whitespace
      @code.gsub!(/(^\s+|\s+$)/, '')
      @code.delete!("\n")
      @code.delete!("\r")
    end

    if @renames
      # "patch up" the renames after each iteration
      @renames.merge! (obfuscator.renames)
    else
      # on first iteration, take the renames as-is
      @renames = obfuscator.renames.dup
    end

    unless i == iterations-1
      @scope = Scope.new
      @ast = nil # force a re-parse
    end
  end

  # Enter all of the renames into current scope
  @scope.renames.merge!(@renames || {})

  self
end
sym(sym) click to toggle source

Returns the obfuscated name for the variable or function sym

@param sym [String] the name of the variable or function @return [String] the obfuscated name

# File lib/jsobfu.rb, line 107
def sym(sym)
  return sym.to_s if @renames.nil?
  @renames[sym.to_s]
end
to_s() click to toggle source

@return [String] the (possibly obfuscated) code

# File lib/jsobfu.rb, line 37
def to_s
  @code
end

Protected Instance Methods

parse() click to toggle source

Generate an Abstract Syntax Tree (#ast) for later obfuscation @return [RKelly::Nodes::SourceElementsNode] the abstract syntax tree

# File lib/jsobfu.rb, line 116
def parse
  RKelly::Parser.new.parse(@code)
end