Skip to content

Commit f2397b8

Browse files
authored
Docs (#19)
- Major rewrite and expansion of the main README and the detectors' README: - Added clear project overview, use cases, CLI/API usage, troubleshooting, and contribution instructions. - Provided detailed, structured documentation for each supported obfuscation type and detector. - Standardized and enhanced JSDoc comments for all detector modules and shared detection methods: - Clarified function purposes, parameters, and return values. - Improved consistency and accuracy of documentation across the codebase. - Refactored and clarified code in detector modules and shared methods: - Improved variable naming and fixed typos in comments. - Made logic and intent clearer, especially in shared detection utilities.
1 parent 7c7b5dc commit f2397b8

17 files changed

+413
-364
lines changed

README.md

Lines changed: 58 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,45 +2,72 @@
22
[![Node.js CI](https://github.com/PerimeterX/obfuscation-detector/actions/workflows/node.js.yml/badge.svg?branch=main)](https://github.com/PerimeterX/obfuscation-detector/actions/workflows/node.js.yml)
33
[![Downloads](https://img.shields.io/npm/dm/obfuscation-detector.svg?maxAge=43200)](https://www.npmjs.com/package/obfuscation-detector)
44

5-
Detect different types of JS obfuscation by their AST structure.
5+
## Overview
6+
Obfuscation Detector is a tool for identifying different types of JavaScript obfuscation by analyzing the code's Abstract Syntax Tree (AST). It is designed for security researchers, reverse engineers, and developers who need to quickly determine if and how a JavaScript file has been obfuscated.
7+
8+
**Use Cases:**
9+
- Automated analysis of suspicious or third-party JavaScript
10+
- Security auditing and malware research
11+
- Integration into CI/CD pipelines to flag obfuscated code
12+
- Educational purposes for understanding obfuscation techniques
13+
14+
## How it Works
15+
Obfuscation Detector parses JavaScript code into an AST using [flAST](https://www.npmjs.com/package/flast) and applies a series of modular detectors. Each detector looks for specific patterns or structures that are characteristic of known obfuscation techniques. The tool can return all matching types or just the most likely (best) match.
616

717
## Installation
8-
`npm install obfuscation-detector`
18+
```shell
19+
npm install obfuscation-detector
20+
```
921

1022
## Usage
11-
### Module
23+
### As a Module
1224
```javascript
1325
import fs from 'node:fs';
1426
import detectObfuscation from 'obfuscation-detector';
1527

1628
const code = fs.readFileSync('obfuscated.js', 'utf-8');
17-
const most_likely_obfuscation_type = detectObfuscation(code);
18-
// const all_matching_obfuscation_types = detectObfuscation(code, false);
19-
console.log(`Obfuscation type is probably ${most_likely_obfuscation_type}`);
29+
const bestMatch = detectObfuscation(code); // returns [bestMatch] or []
30+
const allMatches = detectObfuscation(code, false); // returns all matches as an array
31+
console.log(`Obfuscation type(s): ${allMatches.join(', ')}`);
2032
```
2133

2234
### CLI
23-
```bash
24-
obfuscation-detector /path/to/obfuscated.js [stopAfterFirst]
35+
```shell
36+
obfuscation-detector /path/to/obfuscated.js [--bestMatch|-b]
37+
cat /path/to/obfuscated.js | obfuscation-detector [--bestMatch|-b]
38+
obfuscation-detector --help
2539
```
2640

27-
Getting all matching obfuscation types for a file:
28-
```bash
29-
$ obfuscation-detector /path/to/obfuscated.js
30-
[+] function_to_array_replacements, augmented_proxied_array_function_replacements
31-
```
41+
#### CLI Options
42+
- `--bestMatch`, `-b`: Return only the first (most likely) detected obfuscation type.
43+
- `--help`, `-h`: Show usage instructions.
44+
- Unknown flags will result in an error and print the usage.
3245

33-
Getting just the first match:
34-
```bash
35-
$ obfuscation-detector /path/to/obfuscated.js stop
36-
[+] function_to_array_replacements
37-
```
46+
#### Examples
47+
- **All matches:**
48+
```shell
49+
$ obfuscation-detector /path/to/obfuscated.js
50+
[+] function_to_array_replacements, augmented_proxied_array_function_replacements
51+
```
52+
- **Best match only:**
53+
```shell
54+
$ obfuscation-detector /path/to/obfuscated.js --bestMatch
55+
[+] function_to_array_replacements
56+
```
57+
- **From stdin:**
58+
```shell
59+
$ cat obfuscated.js | obfuscation-detector -b
60+
[+] function_to_array_replacements
61+
```
3862

39-
40-
The `stopAfterFirst` arguments doesn't have to be any specific string, it just needs not to be empty.
63+
## API Reference
64+
### `detectObfuscation(code: string, stopAfterFirst: boolean = true): string[]`
65+
- **code**: JavaScript source code as a string.
66+
- **stopAfterFirst**: If `true`, returns after the first positive detection (default). If `false`, returns all detected types.
67+
- **Returns**: An array of detected obfuscation type names. Returns an empty array if no known type is detected.
4168

4269
## Supported Obfuscation Types
43-
You can find descriptions of the different types in the code itself, and more info [here](src/detectors/README.md).
70+
Descriptions and technical details for each type are available in [src/detectors/README.md](src/detectors/README.md):
4471
- [Array Replacements](src/detectors/arrayReplacements.js)
4572
- [Augmented Array Replacements](src/detectors/augmentedArrayReplacements.js)
4673
- [Array Function Replacements](src/detectors/arrayFunctionReplacements.js)
@@ -49,5 +76,14 @@ You can find descriptions of the different types in the code itself, and more in
4976
- [Obfuscator.io](src/detectors/obfuscator-io.js)
5077
- [Caesar Plus](src/detectors/caesarp.js)
5178

79+
## Troubleshooting
80+
- **No obfuscation detected:** The code may not be obfuscated, or it uses an unknown technique. Consider contributing a new detector!
81+
- **Error: File not found:** Check the file path and try again.
82+
- **Unknown flag:** Run with only `--help` to see what options are available.
83+
- **Performance issues:** For very large files, detection may take longer. Consider running with only the detectors you need (advanced usage).
84+
5285
## Contribution
53-
To contribute to this project see our [contribution guide](CONTRIBUTING.md)
86+
To contribute to this project, see our [contribution guide](CONTRIBUTING.md).
87+
88+
---
89+
For technical details on each obfuscation type and how to add new detectors, see [src/detectors/README.md](src/detectors/README.md).

bin/obfuscation-detector.js

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,55 @@
11
#!/usr/bin/env node
22
import fs from 'node:fs';
3-
import {fileURLToPath} from 'node:url';
43
import {detectObfuscation} from './../src/index.js';
54

6-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
7-
try {
8-
const args = process.argv.slice(2);
9-
if (args.length) {
10-
let content = fs.readFileSync(args[0], 'utf-8');
11-
const stopAfterFirst = !!args[1];
12-
const obfuscationType = detectObfuscation(content, stopAfterFirst);
13-
if (obfuscationType.length) console.log('[+] ' + obfuscationType.join(', '));
14-
else console.log('[-] No obfuscation detected / unknown obfuscation');
15-
} else console.log('Usage: obfuscation-detector /path/to/obfuscated.js [stopAfterFirst]');
16-
} catch (e) {
17-
console.error(`[X] Critical Error: ${e.message}`);
5+
function printUsage() {
6+
console.log('Usage: obfuscation-detector /path/to/obfuscated.js [--bestMatch|-b]');
7+
console.log(' obfuscation-detector < file.js [--bestMatch|-b]');
8+
console.log(' obfuscation-detector --help|-h');
9+
}
10+
11+
const args = process.argv.slice(2);
12+
const allowedFlags = new Set(['--help', '-h', '--bestMatch', '-b']);
13+
14+
// Check for unknown flags
15+
const unknownFlags = args.filter(arg => arg.startsWith('-') && !allowedFlags.has(arg));
16+
if (unknownFlags.length) {
17+
console.error(`[-] Unknown flag(s): ${unknownFlags.join(', ')}`);
18+
printUsage();
19+
process.exit(1);
20+
}
21+
22+
if (args.includes('--help') || args.includes('-h')) {
23+
printUsage();
24+
process.exit(0);
25+
}
26+
27+
try {
28+
let content = '';
29+
// Default: show all matches unless --bestMatch or -b is present
30+
let stopAfterFirst = args.includes('--bestMatch') || args.includes('-b');
31+
32+
// Remove flags from file argument
33+
const fileArg = args.find(arg => !arg.startsWith('-'));
34+
35+
if (fileArg) {
36+
if (!fs.existsSync(fileArg)) {
37+
console.error(`[-] File not found: ${fileArg}`);
38+
printUsage();
39+
process.exit(1);
40+
}
41+
content = fs.readFileSync(fileArg, 'utf-8');
42+
} else if (!process.stdin.isTTY) {
43+
content = fs.readFileSync(0, 'utf-8');
44+
} else {
45+
printUsage();
46+
process.exit(1);
1847
}
48+
49+
const obfuscationType = detectObfuscation(content, stopAfterFirst);
50+
if (obfuscationType.length) console.log('[+] ' + obfuscationType.join(', '));
51+
else console.log('[-] No obfuscation detected / unknown obfuscation');
52+
} catch (e) {
53+
console.error(`[X] Critical Error: ${e.message}`);
54+
process.exit(1);
1955
}

eslint.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ export default [{
3838
}],
3939

4040
semi: ["error", "always"],
41-
"no-empty": ["off"],
41+
"no-empty": ["error", { "allowEmptyCatch": true }],
4242
},
4343
}];

0 commit comments

Comments
 (0)