- 26 Dec 2024
- 5 Minutes à lire
- SombreLumière
- PDF
Features
- Mis à jour le 26 Dec 2024
- 5 Minutes à lire
- SombreLumière
- PDF
The JavaScript protection is achieved by layering several transformations of the code to remove structure and meaning from the code. Each transformation uses randomness to introduce diversity so that thousands of variations are possible from the same input.
The --seed option is used to control the randomness of the output, the default value of 0 tells the tool to use system entropy to seed the RNG so that a unique output will be generated. If a fixed seed is used then the output will be consistent for the same input. This is useful when repeatable builds are needed across test phases.
Random seed configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--seed=<seed> | "seed": 0 | Specifies the see to use for the random generator |
The different transformation passes are described below.
Property Hiding
Property hiding hides the property access of objects by changing it to a computed form using a string literal to locate the property. This string is later hidden by the String Hiding pass. Property hiding is also the foundation for the Externals Hiding pass so disabling this will also disable Externals Hiding. Here’s an example of the transformation
console.log("Hello World");
Can become:
console["log"]("Hello World");
Property hiding configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-property-hiding | "propertyHiding": { "enabled": false } | Disables property hiding |
Externals Hiding
Since external symbols cannot be renamed without breaking the code, they are accessed indirectly via strings and assigned to a local variable. These locals are then used instead of the original symbols. The strings will be hidden by String Hiding and the local variables will be hidden through the later Renaming pass.
Externals hiding configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-externals-hiding | "externalsHiding": { "enabled": false } | Disables externals hiding |
| "externalsHiding": { "globals": true } | Enables hiding of externals at global scope (normally disabled). |
String Hiding
String literals are collected from the source code and hidden using a variety of strategies. Mostly they are encoded as integers and replaced with unique function calls to reconstruct and cache them. Floating point literals are also turned into strings and hidden the same way. A small number of strings are also hidden by using an alternative encoding scheme. The resultant integers are later hidden through the Integer Hiding pass.
The maximum size of strings collected can be controlled using the --string-hiding-max-len=<len> argument. This can be useful when source files contain large bodies of text which might be costly to decode at runtime.
String hiding configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-string-hiding | "stringHiding": { "enabled": false } | Disables string hiding |
-string-hiding-max-len=<len> | "stringHiding": { "maxLength": 1024 } | Excludes strings greater than this length |
Integer Hiding
After the String Hiding pass, there will be a large number of integer literals in the code. These and the original integer literals will be hidden by replacing them with variables which have been computed via arithmetic expressions to the same value from other hidden integers. In some cases, it may not have been possible to easily compute the exact value so these will be left as an assignment. The computations will use a variety of arithmetic operations which will be later hidden using the Operator Removal pass.
Integer hiding configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-integer-hiding | "integerHiding": { "enabled": false } | Disables integer hiding |
Operator Removal
Arithmetic, logical and conditional operators are replaced by functions which perform the same operations. These function calls are then inserted in place of the original operator. This helps to remove a lot of meaning as it then becomes hard to spot computations which might give away the purpose of a particular section of code.
Operator removal configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-operator-removal | "operatorRemoval": { "enabled": false } | Disables operator removal |
Anti-debug
To frustrate debugging efforts, the tool inserts many debugger statements into the code. Controlled by randomness, these can be direct, indirect via eval or indirect via generated functions. Anybody using a debugger will find that the code stops repeatedly in unhelpful places.
Anti-debug configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-anti-debug | "antiDebug": { "enabled": false } | Disables anti-debug |
Integrity Checking
Any attempt to modify the source file, from simple reformatting to insertion or removal of code will be detected by the Integrity Checking protection. Checks are sprinkled at random intervals throughout the code and any one will detect changes up to that point in the code. By default, detection will lead to a random crash usually exhibiting as an out of memory error further frustrating debugging efforts. Alternatively you can configure a custom callback function to do something specific such as delete data or call an API to log the event. You can also combine a crash after the callback.
Integrity checking configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-integrity-checking | "integrityChecking": { "enabled": false } | Disables integrity checking |
--tamper-callback=<callback> | "integrityChecking": { "callback": "myfunc" } | Specifies the name of a function to call when tampering is detected. Example: function myfunc() { alert("Stop!"); } The default crash gadget will still occur after the callback function has completed. |
--tamper-fail-silent | "integrityChecking": { "failSilent": true } | Suppresses the default crash gadget so the code continues as normal after detecting tampering. |
--tamper-check-frequency=<chance> | "integrityChecking": { "checkFrequency": 1 } | Controls the insertion density of integrity checking statements. The number represents a percentage chance of insertion per statement of code e.g. 50 (50%) will be an average of one check statement every 2 statements of code. The default is 1% i.e. an average of one check statement every 100 code statements. Note this is random and so actually distribution is unlikely to be uniform. |
Function Shuffling
As many of the previous passes generate many functions, these are randomly shuffled along with the original functions to make it hard to separate the original functions from the protected code. Statements which are not dependent on predecessors can also be shuffled.
Function shuffling configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-function-shuffling | "functionShuffling": { "enabled": false } | Disables function shuffling |
Renaming
The original program symbols (variables, functions, arguments, etc.) and the many inserted symbols are extensively renamed to symbol names deliberately chosen to be similar to each other. The lifetime of symbols is considered so that variables can be deliberately shadowed as much as possible to confuse the attacker.
To avoid breaking linkages via exports to other code modules, by default, renaming is not applied to symbols at global scope. However it is safe to do this if you are sure that no symbols are exported by the script. This behavior can be controlled with the --rename-globals option.
Renaming only renames symbols declared within the source code, external symbols imported will be unaffected and will be hidden via Externals Hiding instead.
Even if renaming is disabled, it will still rename symbols inserted by the other protection passes.
Renaming configuration options | ||
Command line option | JSON configuration | Purpose |
---|---|---|
--disable-renaming | "renaming": { "enabled": false } | Disables renaming |
--rename-globals | "renaming": { "globals": true } | Renames symbols declared at the global scope. For backwards compatibility, the command line flag also enables globals in external hiding. The JSON attribute does not, it only controls renaming and externals has it’s own control. |
--renaming-utf | "renaming": { "utf":true } | Uses an alternative UTF-8 character set for random symbol names. These characters include letters which look like common language symbols and therefore leads to impressive looking obfuscation. These characters are however multi-byte which results in significantly larger output files. For that reason, the default is to use a simple ASCII character set. |