Protection Techniques
In this section, you can learn about protection techniques used in JSDefender.
Boolean Literal Replacement
This technique replaces the true
and false
Boolean literal values with equivalent — but less straightforward — expressions.
Console Cloaking
This technique prevents the protected code from displaying information in the console when the code invokes the methods of the console
object, such as console.log
, console.info
, etc. Important: the transform does not remove the console
-related method invocations from the code, it merely suppresses them.
Constant Argument Obfuscation
This technique replaces integer literals in function arguments with conditional expressions that use special guard conditions declared in the JSDefender Runtime. Let's assume, you have this function call:
displayNumbers(1, 10);
This protection technique will replace it with a guarded version similar to this:
displayNumbers(Ecrt.wr(123) ? 1 : 3, Ecrt.wr(14) ? 7: 10);
Date Lock
This protection technique injects code to the protected source, which tests if the current date is in a particular interval. If so, the code runs normally; otherwise, it breaks right after the date test phase.
Debugger Statement Removal
This protection technique removes the debugger
JavaScript statements from the code.
DevTools Blocking
This protection technique adds code to the JSDefender Runtime, which detects if the DevTools panel is open in the browser. If so, the protection script continuously stops the program at a breakpoint and does not allow a hacker to debug it. To carry on running the program, the attacker must close the DevTools panel. After a pre-configured number of stops, the Runtime declares the code invalid.
Expression Sequence Obfuscation
This protection technique collects adjacent expression statements in the code and joins them into an expression sequence.
Original code:
(function x() {
y = 3;
z = 4;
return y*z;
})()
Obfuscated code:
(function x() {
return y=3, z=4, y*z;
})()
Control Flow Protection
This technique analyzes control flow statements in the code (if
statements and loops), and transforms them into a finite state machine. This obfuscation makes the code's control flow more difficult to follow, especially when if
statements and loops are nested. During the transformation, the engine can inject fake condition code.
Function Reordering
This protection technique collects function declarations in the source code, and then scatters them in their declaring scope.
Global Object Hiding
Frequently used global objects and functions such as window
, navigator
, Object
, String
, setTimeout
, and many others give useful hints for reverse-engineering the code. The global object hiding protection technique uses indirect references for these objects and hides them within the protector object. Instead of the global object identifiers, an attacker will see meaningless mangled names.
Integer Literal Replacement
This method replaces integer literals with expressions that result in the very same value. As replacements use a combination of decimal, octal, and hexadecimal literals, the original value is not obvious. You can define the range of integers to apply this transformation. Also, you can define a radix (binary, decimal, hexadecimal, octal) to convert any other integer literals.
Local Declaration Name Mangling
This technique renames the identifiers of local declarations (such as variables, functions, and classes). You can choose from a number of name mangling methods. JSDefender takes care that the newly created names do not collide with existing ones. Also, global declaration names (identifiers declared outside of the protected code) remain intact.
Property Indirection
JSDefender changes direct property access expressions to indirect (indexed, or computed) property expressions. Let's see an example:
var x = {
get: function() {
return x.myProp;
}
}
After protection, this code looks like this:
var x={
["get"]: function(){
return x["myProp"];
}
}
Property Sparsing
Transforms object literal expression assignments into multiple assignment statements to make them harder to read.
Original code:
let x = {
w: 1,
z: { x: 3, y: 4},
q: "hello"
}
Code after property sparsing:
let IcwE = {};
IcWE.w = 1;
IcwE.z = {};
IcwE.z.x = 3;
IcwE.z.y = 4;
IcwE.q = "hello";
let x = IcwE
String Literal Extraction
JSDefender extracts string literals from the code, and puts their encoded forms into constant variables. Then, it replaces the original string literals with references to the corresponding variables. Let's see an example:
var greet = "hello";
var planet = "world";
After protection, this code looks similar:
const kK1K=IcZK.xb("{v\x7F\x7F|");
const E7TK=IcZK.xb("d|a\x7Fw");
var greet=kK1K;
var planet=E7TK;
Self-Defending Protection
This technique wraps function declarations, function expressions, object and class method declarations into a guarding function. That function observes if its body (thus, the original function-like construct) is tampered. Even inserting a single space or a new line character into the function body will prevent it from running normally.
Such a protection may have a high run time cost. While it is very cheap for functions and IIFEs (Immediately Invoked Function Expressions) that run only once in your code, it might be expensive for frequently invoked functions.
When you turn on this protection, JSDefender applies it only to the IIFEs that are recognized as once-executed.
Variable Grouping Protection
This technique separates variable declarations and initializations; it moves the declaration part to the end of the declaration scope. Let's see an example:
var a = 234,
b = 123;
displayNumbers(a, b);
// ... Several hundred lines of code
After applying variable grouping:
a = 234;
b = 123;
displayNumbers(a, b);
// ... Several hundred lines
var a, b;