Class: JSObfu::Obfuscator
- Inherits:
-
ECMANoWhitespaceVisitor
- Object
- RKelly::Visitors::ECMAVisitor
- ECMANoWhitespaceVisitor
- JSObfu::Obfuscator
- Defined in:
- lib/jsobfu/obfuscator.rb
Instance Attribute Summary collapse
-
#renames ⇒ Hash
readonly
Of original var/fn names to our new random neames.
-
#scope ⇒ JSObfu::Scope
readonly
The scope maintained while walking the ast.
Instance Method Summary collapse
-
#initialize(opts = {}) ⇒ Obfuscator
constructor
A new instance of Obfuscator.
-
#visit_DotAccessorNode(o) ⇒ Object
Called on a dot lookup, like X.Y.
- #visit_FunctionDeclNode(o) ⇒ Object
- #visit_FunctionExprNode(o) ⇒ Object
- #visit_NumberNode(o) ⇒ Object
-
#visit_ParameterNode(o) ⇒ Object
Called when a parameter is declared.
-
#visit_PropertyNode(o) ⇒ Object
A property node in an object “{}”.
-
#visit_ResolveNode(o) ⇒ Object
Called whenever a variable is referred to (not declared).
-
#visit_SourceElementsNode(o) ⇒ Object
Maintains a stack of closures that we have visited.
- #visit_StringNode(o) ⇒ Object
- #visit_TryNode(o) ⇒ Object
-
#visit_VarDeclNode(o) ⇒ Object
Called whenever a variable is declared.
Methods inherited from ECMANoWhitespaceVisitor
#function_params_and_body, #visit_ArgumentsNode, #visit_ArrayNode, #visit_AssignExprNode, #visit_BitwiseNotNode, #visit_BlockNode, #visit_BracketAccessorNode, #visit_BreakNode, #visit_CaseBlockNode, #visit_CaseClauseNode, #visit_CommaNode, #visit_ConditionalNode, #visit_ConstStatementNode, #visit_ContinueNode, #visit_DeleteNode, #visit_DoWhileNode, #visit_ElementNode, #visit_EmptyStatementNode, #visit_ExpressionStatementNode, #visit_FalseNode, #visit_ForInNode, #visit_ForNode, #visit_FunctionBodyNode, #visit_FunctionCallNode, #visit_GetterPropertyNode, #visit_IfNode, #visit_LabelNode, #visit_LessNode, #visit_LogicalNotNode, #visit_NewExprNode, #visit_NullNode, #visit_ObjectLiteralNode, #visit_OpEqualNode, #visit_ParentheticalNode, #visit_PostfixNode, #visit_PrefixNode, #visit_RegexpNode, #visit_ReturnNode, #visit_SetterPropertyNode, #visit_SwitchNode, #visit_ThisNode, #visit_ThrowNode, #visit_TrueNode, #visit_TypeOfNode, #visit_UnaryMinusNode, #visit_UnaryPlusNode, #visit_VarStatementNode, #visit_VoidNode, #visit_WhileNode, #visit_WithNode
Constructor Details
#initialize(opts = {}) ⇒ Obfuscator
Returns a new instance of Obfuscator.
17 18 19 20 21 |
# File 'lib/jsobfu/obfuscator.rb', line 17 def initialize(opts={}) @scope = opts.fetch(:scope, JSObfu::Scope.new) @renames = {} super() end |
Instance Attribute Details
#renames ⇒ Hash (readonly)
Returns of original var/fn names to our new random neames.
13 14 15 |
# File 'lib/jsobfu/obfuscator.rb', line 13 def renames @renames end |
#scope ⇒ JSObfu::Scope (readonly)
Returns the scope maintained while walking the ast.
6 7 8 |
# File 'lib/jsobfu/obfuscator.rb', line 6 def scope @scope end |
Instance Method Details
#visit_DotAccessorNode(o) ⇒ Object
Called on a dot lookup, like X.Y
96 97 98 99 |
# File 'lib/jsobfu/obfuscator.rb', line 96 def visit_DotAccessorNode(o) obf_str = JSObfu::Utils::transform_string(o.accessor, scope, :quotes => false) "#{o.value.accept(self)}[(#{obf_str})]" end |
#visit_FunctionDeclNode(o) ⇒ Object
51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/jsobfu/obfuscator.rb', line 51 def visit_FunctionDeclNode(o) o.value = if o.value and o.value.length > 0 JSObfu::Utils::random_var_encoding(scope.rename_var(o.value)) else if rand(3) != 0 JSObfu::Utils::random_var_encoding(scope.random_var_name) end end super end |
#visit_FunctionExprNode(o) ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/jsobfu/obfuscator.rb', line 63 def visit_FunctionExprNode(o) if o.value != 'function' o.value = JSObfu::Utils::random_var_encoding(rename_var(o.value)) end super end |
#visit_NumberNode(o) ⇒ Object
119 120 121 122 |
# File 'lib/jsobfu/obfuscator.rb', line 119 def visit_NumberNode(o) o.value = JSObfu::Utils::transform_number(o.value) super end |
#visit_ParameterNode(o) ⇒ Object
Called when a parameter is declared. “Shadowed” parameters in the original source are preserved - the randomized name is “shadowed” from the outer scope.
103 104 105 106 107 |
# File 'lib/jsobfu/obfuscator.rb', line 103 def visit_ParameterNode(o) o.value = JSObfu::Utils::random_var_encoding(rename_var(o.value)) super end |
#visit_PropertyNode(o) ⇒ Object
A property node in an object “{}”
110 111 112 113 114 115 116 117 |
# File 'lib/jsobfu/obfuscator.rb', line 110 def visit_PropertyNode(o) # if it is a non-alphanumeric property, obfuscate the string's bytes if o.name =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/ o.instance_variable_set :@name, '"'+JSObfu::Utils::random_string_encoding(o.name)+'"' end super end |
#visit_ResolveNode(o) ⇒ Object
Called whenever a variable is referred to (not declared).
If the variable was never added to scope, it is assumed to be a global object (like “document”), and hence will not be obfuscated.
83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/jsobfu/obfuscator.rb', line 83 def visit_ResolveNode(o) new_val = rename_var(o.value, :generate => false) if new_val o.value = JSObfu::Utils::random_var_encoding(new_val) super else # A global is used, at least obfuscate the lookup "window[#{JSObfu::Utils::transform_string(o.value, scope, :quotes => false)}]" end end |
#visit_SourceElementsNode(o) ⇒ Object
Maintains a stack of closures that we have visited. This method is called everytime we visit a nested function.
Javascript is functionally-scoped, so a function(){} creates its own unique closure. When resolving variables, Javascript looks “up” the closure stack, ending up as a property lookup in the global scope (available as ‘window` in all browsers)
This is changed in newer ES versions, where a ‘let` keyword has been introduced, which has regular C-style block scoping. We’ll ignore this feature since it is not yet widely used.
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/jsobfu/obfuscator.rb', line 34 def visit_SourceElementsNode(o) scope.push! hoister = JSObfu::Hoister.new(parent_scope: scope) o.value.each { |x| hoister.accept(x) } hoister.scope.keys.each do |key| rename_var(key) end ret = super scope.pop! ret end |
#visit_StringNode(o) ⇒ Object
124 125 126 127 |
# File 'lib/jsobfu/obfuscator.rb', line 124 def visit_StringNode(o) o.value = JSObfu::Utils::transform_string(o.value, scope) super end |
#visit_TryNode(o) ⇒ Object
129 130 131 132 133 134 |
# File 'lib/jsobfu/obfuscator.rb', line 129 def visit_TryNode(o) if o.catch_block o.instance_variable_set :@catch_var, rename_var(o.catch_var) end super end |
#visit_VarDeclNode(o) ⇒ Object
Called whenever a variable is declared.
72 73 74 75 76 |
# File 'lib/jsobfu/obfuscator.rb', line 72 def visit_VarDeclNode(o) o.name = JSObfu::Utils::random_var_encoding(rename_var(o.name)) super end |