Class: Rex::Exploitation::ObfuscateJS

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/exploitation/obfuscatejs.rb

Overview

Obfuscates javascript in various ways

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(js = "", opts = {}) ⇒ ObfuscateJS

Initialize an instance of the obfuscator


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/rex/exploitation/obfuscatejs.rb', line 70

def initialize(js = "", opts = {})
  @js      = js
  @dynsym  = {}
  @opts    = {
    'Symbols' => {
      'Variables'=>[],
      'Methods'=>[],
      'Namespaces'=>[],
      'Classes'=>[]
    },
    'Strings'=>false
  }
  @done = false
  update_opts(opts) if (opts.length > 0)
end

Instance Attribute Details

#optsObject (readonly)

Returns the value of attribute opts


10
11
12
# File 'lib/rex/exploitation/obfuscatejs.rb', line 10

def opts
  @opts
end

Class Method Details

.obfuscate(js, opts = {}) ⇒ Object

Obfuscates a javascript string.

Options are 'Symbols', described below, and 'Strings', a boolean which specifies whether strings within the javascript should be mucked with (defaults to false).

The 'Symbols' argument should have the following format:

{
   'Variables'  => [ 'var1', ... ],
   'Methods'    => [ 'method1', ... ],
   'Namespaces' => [ 'n', ... ],
   'Classes'    => [ { 'Namespace' => 'n', 'Class' => 'y'}, ... ]
}

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.

A simple example follows:

<code> js = ObfuscateJS.new <<ENDJS

function say_hi() {
    var foo = "Hello, world";
    document.writeln(foo);
}

ENDJS js.obfuscate(

  'Symbols' => {
     'Variables' => [ 'foo' ],
     'Methods'   => [ 'say_hi' ]
}
  'Strings' => true

) </code>

which should generate something like the following:

function oJaDYRzFOyJVQCOHk() { var cLprVG = "\x48\x65\x6c\x6c\x6f\x2c\x20\x77\x6f\x72\x6c\x64"; document.writeln(cLprVG); }

String obfuscation tries to deal with escaped quotes within strings but won't catch things like

"\\"

so be careful.


63
64
65
# File 'lib/rex/exploitation/obfuscatejs.rb', line 63

def self.obfuscate(js, opts = {})
  ObfuscateJS.new(js).obfuscate(opts)
end

Instance Method Details

#+(str) ⇒ Object


166
167
168
# File 'lib/rex/exploitation/obfuscatejs.rb', line 166

def +(str)
  @js + str
end

#<<(str) ⇒ Object


163
164
165
# File 'lib/rex/exploitation/obfuscatejs.rb', line 163

def <<(str)
  @js << str
end

#obfuscate(opts = {}) ⇒ Object

Obfuscates the javascript string passed to the constructor


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/rex/exploitation/obfuscatejs.rb', line 121

def obfuscate(opts = {})
  #return @js if (@done)
  @done = true

  update_opts(opts)

  if (@opts['Strings'])
    obfuscate_strings()

    # Full space randomization does not work for javascript -- despite
    # claims that space is irrelavent, newlines break things.  Instead,
    # use only space (0x20) and tab (0x09).

    #@js.gsub!(/[\x09\x20]+/) { |s|
    #	len = rand(50)+2
    #	set = "\x09\x20"
    #	buf = ''
    #	while (buf.length < len)
    #		buf << set[rand(set.length)].chr
    #	end
    #
    #	buf
    #}
  end

  # Remove our comments
  remove_comments

  # Globally replace symbols
  replace_symbols(@opts['Symbols']) if @opts['Symbols']

  return @js
end

#sym(name) ⇒ Object

Returns the dynamic symbol associated with the supplied symbol name

If obfuscation has not yet been performed (i.e. obfuscate() has not been called), then this method simply returns its argument


114
115
116
# File 'lib/rex/exploitation/obfuscatejs.rb', line 114

def sym(name)
  @dynsym[name] || name
end

#to_sObject Also known as: to_str

Returns the replaced javascript string


158
159
160
# File 'lib/rex/exploitation/obfuscatejs.rb', line 158

def to_s
  @js
end

#update_opts(opts) ⇒ Object


86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/rex/exploitation/obfuscatejs.rb', line 86

def update_opts(opts)
  if (opts.nil? or opts.length < 1)
    return
  end
  if (@opts['Symbols'] && opts['Symbols'])
    ['Variables', 'Methods', 'Namespaces', 'Classes'].each { |k|
      if (@opts['Symbols'][k] && opts['Symbols'][k])
        opts['Symbols'][k].each { |s|
          if (not @opts['Symbols'][k].include? s)
            @opts['Symbols'][k].push(s)
          end
        }
      elsif (opts['Symbols'][k])
        @opts['Symbols'][k] = opts['Symbols'][k]
      end
    }
  elsif opts['Symbols']
    @opts['Symbols'] = opts['Symbols']
  end
  @opts['Strings'] ||= opts['Strings']
end