/** * Malware Detection Module for JavaScript/TypeScript * Detects various types of malicious code patterns * * Inspired by YARA rules and malware analysis techniques */ import { Severity, ThreatType, FindingCategory, SecurityStandard } from '../../types'; import { getStandardsForThreat } from '../../rules/standards'; import { calculateEntropy, isBase64Like, isHexEncoded } from '../../utils'; /** * Malware detection result */ export interface MalwareMatch { /** Type of malware detected */ type: MalwareType; /** Name of the detection */ name: string; /** Description of the threat */ description: string; /** Severity level */ severity: Severity; /** Line number */ line: number; /** Matched code snippet */ code: string; /** Detection confidence 0-100 */ confidence: number; /** Indicators of compromise */ indicators: string[]; /** MITRE ATT&CK references */ mitreAttack?: string[]; /** Remediation advice */ remediation: string; } /** * Types of malware */ export enum MalwareType { // Data Theft STEALER = 'stealer', KEYLOGGER = 'keylogger', CREDENTIAL_HARVESTER = 'credential_harvester', // Cryptocurrency CRYPTOMINER = 'cryptominer', CRYPTO_WALLET_STEALER = 'crypto_wallet_stealer', // Remote Access BACKDOOR = 'backdoor', REVERSE_SHELL = 'reverse_shell', C2_COMMUNICATION = 'c2_communication', // Loaders DROPPER = 'dropper', LOADER = 'loader', // Obfuscation OBFUSCATED_PAYLOAD = 'obfuscated_payload', ENCODED_PAYLOAD = 'encoded_payload', // Supply Chain TYPOSQUAT = 'typosquat', DEPENDENCY_CONFUSION = 'dependency_confusion', POSTINSTALL_MALWARE = 'postinstall_malware', // Evasion ANTI_DEBUGGING = 'anti_debugging', VM_DETECTION = 'vm_detection', SANDBOX_EVASION = 'sandbox_evasion', // Persistence PERSISTENCE = 'persistence', // Generic SUSPICIOUS_BEHAVIOR = 'suspicious_behavior' } /** * Malware detection pattern */ interface MalwarePattern { /** Pattern name */ name: string; /** Pattern type */ type: MalwareType; /** Regex pattern */ pattern: RegExp; /** Description */ description: string; /** Severity */ severity: Severity; /** Confidence base */ confidence: number; /** Indicators to extract */ indicators?: (match: RegExpMatchArray) => string[]; /** MITRE ATT&CK references */ mitre?: string[]; /** Remediation */ remediation: string; } /** * Malware detection patterns organized by category */ const MALWARE_PATTERNS: MalwarePattern[] = [ // ============ DATA STEALERS ============ { name: 'Cookie Stealer', type: MalwareType.STEALER, pattern: /document\.cookie[\s\S]{0,100}(?:fetch|XMLHttpRequest|sendBeacon|axios|http)/gi, description: 'Code that reads cookies and sends them to a remote server', severity: Severity.CRITICAL, confidence: 85, mitre: ['T1539', 'T1041'], remediation: 'Remove the malicious code. Investigate how it was introduced.' }, { name: 'LocalStorage Exfiltration', type: MalwareType.STEALER, pattern: /localStorage(?:\.getItem|\[)[\s\S]{0,200}(?:fetch|XMLHttpRequest|sendBeacon|axios)/gi, description: 'Reads localStorage data and sends it externally', severity: Severity.HIGH, confidence: 80, mitre: ['T1005', 'T1041'], remediation: 'Remove the exfiltration code and audit stored data.' }, { name: 'Credentials Harvester', type: MalwareType.CREDENTIAL_HARVESTER, pattern: /(?:password|passwd|pwd|credentials?|auth|token|secret|api[_-]?key)[\s\S]{0,50}(?:\.value|\.val\(\)|\.text)[\s\S]{0,100}(?:fetch|XMLHttp|send|post)/gi, description: 'Harvests credential input fields and sends them', severity: Severity.CRITICAL, confidence: 75, mitre: ['T1056', 'T1041'], remediation: 'Remove harvesting code and rotate all affected credentials.' }, { name: 'Environment Variable Stealer', type: MalwareType.STEALER, pattern: /process\.env[\s\S]{0,200}(?:fetch|http\.request|axios|child_process)/gi, description: 'Reads environment variables and exfiltrates them', severity: Severity.CRITICAL, confidence: 80, mitre: ['T1552.001', 'T1041'], remediation: 'Remove the code and rotate all environment secrets.' }, { name: 'SSH Key Stealer', type: MalwareType.STEALER, pattern: /(?:\.ssh|id_rsa|id_ed25519|known_hosts|authorized_keys)[\s\S]{0,100}(?:readFile|fs\.|createReadStream)/gi, description: 'Attempts to read SSH keys', severity: Severity.CRITICAL, confidence: 85, mitre: ['T1552.004'], remediation: 'Remove code and regenerate SSH keys.' }, // ============ CRYPTOMINERS ============ { name: 'Cryptominer - WebAssembly', type: MalwareType.CRYPTOMINER, pattern: /WebAssembly\.(?:instantiate|compile)[\s\S]{0,300}(?:hash|mine|worker|crypto)/gi, description: 'WebAssembly-based cryptocurrency miner', severity: Severity.HIGH, confidence: 75, mitre: ['T1496'], remediation: 'Remove the cryptomining code entirely.' }, { name: 'Cryptominer - CoinHive Style', type: MalwareType.CRYPTOMINER, pattern: /(?:coinhive|coin-hive|cryptonight|monero|xmr|hashrate|CryptoNight)/gi, description: 'Browser-based cryptocurrency miner reference', severity: Severity.HIGH, confidence: 90, mitre: ['T1496'], remediation: 'Remove all cryptomining references.' }, { name: 'Cryptominer - Worker Pool', type: MalwareType.CRYPTOMINER, pattern: /(?:stratum|mining[_-]?pool|worker\.postMessage[\s\S]{0,50}hash)/gi, description: 'Mining pool communication pattern', severity: Severity.HIGH, confidence: 80, mitre: ['T1496'], remediation: 'Remove the mining worker code.' }, { name: 'Crypto Wallet Stealer', type: MalwareType.CRYPTO_WALLET_STEALER, pattern: /(?:wallet|ethereum|bitcoin|metamask|web3|privateKey)[\s\S]{0,100}(?:localStorage|send|post|fetch)/gi, description: 'Attempts to steal cryptocurrency wallet data', severity: Severity.CRITICAL, confidence: 75, mitre: ['T1005', 'T1041'], remediation: 'Remove code, notify affected users, rotate wallet keys.' }, // ============ BACKDOORS & REMOTE ACCESS ============ { name: 'Reverse Shell', type: MalwareType.REVERSE_SHELL, pattern: /(?:net\.Socket|dgram)[\s\S]{0,200}(?:spawn|exec)[\s\S]{0,100}(?:\/bin\/(?:sh|bash)|cmd\.exe|powershell)/gi, description: 'Network socket connected to shell execution', severity: Severity.CRITICAL, confidence: 95, mitre: ['T1059', 'T1095'], remediation: 'Remove immediately and audit all system access.' }, { name: 'Backdoor - Remote Code Execution', type: MalwareType.BACKDOOR, pattern: /(?:fetch|axios|http\.get)[\s\S]{0,100}(?:eval|Function|exec|spawn)[\s\S]{0,50}(?:body|response|data)/gi, description: 'Fetches code from remote server and executes it', severity: Severity.CRITICAL, confidence: 90, mitre: ['T1105', 'T1059'], remediation: 'Remove the backdoor and investigate compromise.' }, { name: 'C2 Beacon', type: MalwareType.C2_COMMUNICATION, pattern: /setInterval[\s\S]{0,100}(?:fetch|axios|XMLHttpRequest)[\s\S]{0,100}(?:exec|eval|Function)/gi, description: 'Periodic command and control communication', severity: Severity.CRITICAL, confidence: 80, mitre: ['T1071', 'T1059'], remediation: 'Remove C2 code and investigate network traffic.' }, { name: 'DNS Exfiltration', type: MalwareType.C2_COMMUNICATION, pattern: /(?:dns|resolve)[\s\S]{0,50}(?:encode|base64|hex)[\s\S]{0,50}(?:lookup|resolve4)/gi, description: 'Data exfiltration via DNS queries', severity: Severity.HIGH, confidence: 75, mitre: ['T1048.003'], remediation: 'Remove the DNS exfiltration code.' }, // ============ DROPPERS & LOADERS ============ { name: 'Remote Script Loader', type: MalwareType.LOADER, pattern: /(?:document\.createElement\s*\(\s*['"`]script['"`]\s*\))[\s\S]{0,200}(?:src\s*=|appendChild)/gi, description: 'Dynamically loads remote scripts', severity: Severity.HIGH, confidence: 70, mitre: ['T1105'], remediation: 'Verify script sources or remove dynamic loading.' }, { name: 'Payload Dropper', type: MalwareType.DROPPER, pattern: /(?:fs\.writeFile|writeFileSync)[\s\S]{0,100}(?:atob|Buffer\.from|base64|0x[0-9a-f]+)/gi, description: 'Writes decoded payload to filesystem', severity: Severity.CRITICAL, confidence: 85, mitre: ['T1105', 'T1204'], remediation: 'Remove dropper and scan for dropped files.' }, { name: 'curl/wget Pipe Execution', type: MalwareType.DROPPER, pattern: /(?:curl|wget)\s+[^\s]+\s*\|\s*(?:sh|bash|node|python)/gi, description: 'Downloads and executes remote script', severity: Severity.CRITICAL, confidence: 95, mitre: ['T1059', 'T1105'], remediation: 'Remove the dangerous command execution.' }, // ============ OBFUSCATED & ENCODED PAYLOADS ============ { name: 'Base64 Decode + Eval', type: MalwareType.OBFUSCATED_PAYLOAD, pattern: /(?:atob|Buffer\.from\s*\([^)]+,\s*['"`]base64['"`]\))[\s\S]{0,50}(?:eval|Function|exec)/gi, description: 'Decodes Base64 and executes the result', severity: Severity.CRITICAL, confidence: 90, mitre: ['T1140', 'T1059'], remediation: 'Decode and analyze the payload, then remove.' }, { name: 'Hex Decode + Eval', type: MalwareType.OBFUSCATED_PAYLOAD, pattern: /Buffer\.from\s*\([^)]+,\s*['"`]hex['"`]\)[\s\S]{0,50}(?:eval|Function|exec|toString)/gi, description: 'Decodes hex-encoded payload and executes', severity: Severity.CRITICAL, confidence: 85, mitre: ['T1140', 'T1059'], remediation: 'Decode and analyze, then remove the code.' }, { name: 'String.fromCharCode Obfuscation', type: MalwareType.OBFUSCATED_PAYLOAD, pattern: /String\.fromCharCode\s*\(\s*(?:\d+\s*,?\s*){10,}\)/gi, description: 'Uses character codes to hide strings', severity: Severity.HIGH, confidence: 75, mitre: ['T1140'], remediation: 'Decode the character codes to analyze.' }, { name: 'Unicode Escape Obfuscation', type: MalwareType.OBFUSCATED_PAYLOAD, pattern: /(?:\\u[0-9a-f]{4}){10,}/gi, description: 'Heavy use of unicode escapes for obfuscation', severity: Severity.MEDIUM, confidence: 65, mitre: ['T1140'], remediation: 'Decode and review the actual content.' }, { name: 'Hex Escape Obfuscation', type: MalwareType.OBFUSCATED_PAYLOAD, pattern: /(?:\\x[0-9a-f]{2}){15,}/gi, description: 'Heavy use of hex escapes for obfuscation', severity: Severity.HIGH, confidence: 70, mitre: ['T1140'], remediation: 'Decode and analyze the hidden content.' }, // ============ ANTI-DEBUGGING / EVASION ============ { name: 'DevTools Detection', type: MalwareType.ANTI_DEBUGGING, pattern: /(?:devtools|firebug)[\s\S]{0,50}(?:open|detect|isOpen)/gi, description: 'Detects if browser DevTools is open', severity: Severity.MEDIUM, confidence: 80, mitre: ['T1622'], remediation: 'Remove anti-debugging checks.' }, { name: 'Console Timing Detection', type: MalwareType.ANTI_DEBUGGING, pattern: /console\.(?:log|table|dir)[\s\S]{0,100}(?:Date\.now|performance\.now)[\s\S]{0,50}(?:>\s*\d+|threshold)/gi, description: 'Uses console timing to detect debuggers', severity: Severity.MEDIUM, confidence: 70, mitre: ['T1622'], remediation: 'Remove timing-based detection.' }, { name: 'Debugger Trap', type: MalwareType.ANTI_DEBUGGING, pattern: /(?:setInterval|setTimeout)[\s\S]{0,50}(?:function\s*\(\)\s*{\s*debugger|['"`]debugger['"`])/gi, description: 'Repeatedly triggers debugger statement', severity: Severity.MEDIUM, confidence: 85, mitre: ['T1622'], remediation: 'Remove the debugger trap code.' }, { name: 'VM/Sandbox Detection', type: MalwareType.SANDBOX_EVASION, pattern: /(?:navigator\.(?:webdriver|hardwareConcurrency|deviceMemory)|screen\.(?:width|height)[\s\S]{0,50}(?:800|1024))[\s\S]{0,100}(?:if|===|!==)/gi, description: 'Checks for VM/sandbox environment', severity: Severity.MEDIUM, confidence: 70, mitre: ['T1497'], remediation: 'Remove environment detection code.' }, // ============ PERSISTENCE ============ { name: 'Cron Job Creation', type: MalwareType.PERSISTENCE, pattern: /(?:cron|crontab|\/etc\/cron)[\s\S]{0,100}(?:write|exec|spawn|append)/gi, description: 'Attempts to create scheduled tasks', severity: Severity.HIGH, confidence: 80, mitre: ['T1053'], remediation: 'Remove persistence mechanism and check crontab.' }, { name: 'Startup Script Modification', type: MalwareType.PERSISTENCE, pattern: /(?:\.bashrc|\.profile|\.bash_profile|init\.d|systemd)[\s\S]{0,100}(?:writeFile|appendFile|exec)/gi, description: 'Modifies startup scripts for persistence', severity: Severity.CRITICAL, confidence: 85, mitre: ['T1546'], remediation: 'Remove persistence and check startup files.' }, // ============ SUPPLY CHAIN SPECIFIC ============ { name: 'Package Install Hook Abuse', type: MalwareType.POSTINSTALL_MALWARE, pattern: /["'](?:preinstall|postinstall|preuninstall)["']\s*:\s*["'](?:[^"']*(?:curl|wget|node\s+-e|eval|exec)[^"']*)/gi, description: 'Suspicious npm lifecycle script', severity: Severity.CRITICAL, confidence: 90, mitre: ['T1195.002'], remediation: 'Remove malicious lifecycle scripts.' }, { name: 'Suspicious Package Name Pattern', type: MalwareType.TYPOSQUAT, pattern: /require\s*\(\s*['"`](?:l[o0]dash|und[e3]rscore|ex[p9]ress|m[o0]ment|ax[i1]os|react-d[o0]m|vue-r[o0]uter)['"`]\s*\)/gi, description: 'Potential typosquatting package import', severity: Severity.HIGH, confidence: 70, mitre: ['T1195.002'], remediation: 'Verify package names are spelled correctly.' }, // ============ SUSPICIOUS NETWORK BEHAVIOR ============ { name: 'Suspicious Webhook', type: MalwareType.SUSPICIOUS_BEHAVIOR, pattern: /(?:discord\.com\/api\/webhooks|hooks\.slack\.com|api\.telegram\.org\/bot)/gi, description: 'Sends data to messaging webhook', severity: Severity.HIGH, confidence: 75, mitre: ['T1567'], remediation: 'Verify webhook usage is legitimate.' }, { name: 'Data Upload to Pastebin', type: MalwareType.SUSPICIOUS_BEHAVIOR, pattern: /(?:pastebin\.com|ghostbin|hastebin|paste\.ee)[\s\S]{0,100}(?:post|send|upload)/gi, description: 'Uploads data to paste service', severity: Severity.MEDIUM, confidence: 70, mitre: ['T1567.002'], remediation: 'Verify the data being uploaded.' }, { name: 'IP Logger', type: MalwareType.SUSPICIOUS_BEHAVIOR, pattern: /(?:iplogger|grabify|ipify|ip-api|whatismyip)[\s\S]{0,50}(?:fetch|get|request)/gi, description: 'Resolves and potentially logs IP address', severity: Severity.MEDIUM, confidence: 65, mitre: ['T1016'], remediation: 'Verify IP lookup is necessary and legitimate.' } ]; /** * Long encoded string patterns to detect */ const ENCODED_STRING_THRESHOLD = 200; /** * Malware Detector Class */ export class MalwareDetector { private matches: MalwareMatch[] = []; private lines: string[] = []; /** * Scan code for malware patterns */ scan(content: string, filePath: string): MalwareMatch[] { this.matches = []; this.lines = content.split('\n'); // Run pattern matching this.runPatternMatching(content); // Check for suspicious encoded strings this.checkEncodedStrings(content); // Check for high entropy sections (possible encrypted/encoded payloads) this.checkHighEntropyContent(content); // Check for suspicious network URLs this.checkSuspiciousUrls(content); // Deduplicate matches return this.deduplicateMatches(); } /** * Run all malware pattern checks */ private runPatternMatching(content: string): void { for (const pattern of MALWARE_PATTERNS) { // Reset regex state pattern.pattern.lastIndex = 0; let match; while ((match = pattern.pattern.exec(content)) !== null) { const lineNumber = this.getLineNumber(content, match.index); this.matches.push({ type: pattern.type, name: pattern.name, description: pattern.description, severity: pattern.severity, line: lineNumber, code: this.getCodeSnippet(lineNumber), confidence: pattern.confidence, indicators: pattern.indicators ? pattern.indicators(match) : [match[0].substring(0, 100)], mitreAttack: pattern.mitre, remediation: pattern.remediation }); } } } /** * Check for suspicious encoded strings */ private checkEncodedStrings(content: string): void { // Find long base64-like strings const base64Pattern = /['"`]([A-Za-z0-9+/=]{100,})['"`]/g; let match; while ((match = base64Pattern.exec(content)) !== null) { const encoded = match[1]; if (isBase64Like(encoded)) { const lineNumber = this.getLineNumber(content, match.index); // Try to decode and check for suspicious content let decodedContent = ''; try { decodedContent = Buffer.from(encoded, 'base64').toString('utf8'); } catch { // Not valid base64 } const isSuspicious = decodedContent.includes('eval') || decodedContent.includes('exec') || decodedContent.includes('Function') || decodedContent.includes('http') || decodedContent.includes('require'); if (isSuspicious) { this.matches.push({ type: MalwareType.ENCODED_PAYLOAD, name: 'Suspicious Base64 Encoded Content', description: 'Long Base64 string that decodes to potentially malicious content', severity: Severity.HIGH, line: lineNumber, code: this.getCodeSnippet(lineNumber), confidence: 80, indicators: [`Base64 length: ${encoded.length}`, `Contains suspicious keywords when decoded`], mitreAttack: ['T1140'], remediation: 'Decode and analyze the Base64 content.' }); } } } // Find long hex strings const hexPattern = /['"`]((?:0x)?[0-9a-fA-F]{100,})['"`]/g; while ((match = hexPattern.exec(content)) !== null) { const hex = match[1]; if (isHexEncoded(hex.replace(/^0x/, ''))) { const lineNumber = this.getLineNumber(content, match.index); this.matches.push({ type: MalwareType.ENCODED_PAYLOAD, name: 'Suspicious Hex Encoded Content', description: 'Long hex-encoded string detected', severity: Severity.MEDIUM, line: lineNumber, code: this.getCodeSnippet(lineNumber), confidence: 65, indicators: [`Hex string length: ${hex.length}`], mitreAttack: ['T1140'], remediation: 'Decode and analyze the hex content.' }); } } } /** * Check for high entropy content (encrypted/compressed data) */ private checkHighEntropyContent(content: string): void { // Split into chunks and check entropy const chunkSize = 500; for (let i = 0; i < this.lines.length; i++) { const line = this.lines[i]; if (line.length > 200) { const entropy = calculateEntropy(line); if (entropy > 5.8) { this.matches.push({ type: MalwareType.OBFUSCATED_PAYLOAD, name: 'High Entropy Code Line', description: `Line with unusually high entropy (${entropy.toFixed(2)}) suggesting obfuscated or encrypted content`, severity: Severity.MEDIUM, line: i + 1, code: line.substring(0, 100) + '...', confidence: 60, indicators: [`Entropy: ${entropy.toFixed(2)}`], mitreAttack: ['T1027'], remediation: 'Analyze the obfuscated content.' }); } } } } /** * Check for suspicious URLs */ private checkSuspiciousUrls(content: string): void { const suspiciousPatterns = [ // Dynamic DNS providers (often used by malware) { pattern: /(?:no-ip\.com|duckdns\.org|dynu\.com|freedns\.afraid\.org)/gi, name: 'Dynamic DNS Service' }, // URL shorteners (can hide malicious destinations) { pattern: /(?:bit\.ly|tinyurl\.com|t\.co|goo\.gl|is\.gd|v\.gd)\/\w+/gi, name: 'URL Shortener' }, // Raw IP addresses in URLs { pattern: /https?:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/gi, name: 'Raw IP URL' }, // File sharing services { pattern: /(?:mega\.nz|mediafire\.com|zippyshare\.com|uploadfiles)/gi, name: 'File Sharing Service' } ]; for (const { pattern, name } of suspiciousPatterns) { pattern.lastIndex = 0; let match; while ((match = pattern.exec(content)) !== null) { const lineNumber = this.getLineNumber(content, match.index); this.matches.push({ type: MalwareType.SUSPICIOUS_BEHAVIOR, name: `Suspicious URL: ${name}`, description: `Code references ${name} which may be used to hide malicious activity`, severity: Severity.MEDIUM, line: lineNumber, code: this.getCodeSnippet(lineNumber), confidence: 55, indicators: [match[0]], mitreAttack: ['T1102'], remediation: 'Verify the URL is legitimate and necessary.' }); } } } /** * Get line number from string index */ private getLineNumber(content: string, index: number): number { const beforeMatch = content.substring(0, index); return beforeMatch.split('\n').length; } /** * Get code snippet for a line */ private getCodeSnippet(lineNumber: number): string { const lineIndex = lineNumber - 1; if (lineIndex >= 0 && lineIndex < this.lines.length) { return this.lines[lineIndex].trim().substring(0, 150); } return ''; } /** * Remove duplicate matches */ private deduplicateMatches(): MalwareMatch[] { const seen = new Set(); return this.matches.filter(match => { const key = `${match.type}:${match.line}:${match.name}`; if (seen.has(key)) return false; seen.add(key); return true; }); } /** * Get threat type for malware type */ static getThreatType(type: MalwareType): ThreatType { const mapping: Record = { [MalwareType.STEALER]: ThreatType.DATA_EXFILTRATION, [MalwareType.KEYLOGGER]: ThreatType.KEYLOGGER, [MalwareType.CREDENTIAL_HARVESTER]: ThreatType.DATA_EXFILTRATION, [MalwareType.CRYPTOMINER]: ThreatType.CRYPTOMINER, [MalwareType.CRYPTO_WALLET_STEALER]: ThreatType.DATA_EXFILTRATION, [MalwareType.BACKDOOR]: ThreatType.BACKDOOR, [MalwareType.REVERSE_SHELL]: ThreatType.REVERSE_SHELL, [MalwareType.C2_COMMUNICATION]: ThreatType.SUSPICIOUS_NETWORK, [MalwareType.DROPPER]: ThreatType.MALICIOUS_LOADER, [MalwareType.LOADER]: ThreatType.MALICIOUS_LOADER, [MalwareType.OBFUSCATED_PAYLOAD]: ThreatType.OBFUSCATED_CODE, [MalwareType.ENCODED_PAYLOAD]: ThreatType.EMBEDDED_PAYLOAD, [MalwareType.TYPOSQUAT]: ThreatType.MALICIOUS_LOADER, [MalwareType.DEPENDENCY_CONFUSION]: ThreatType.MALICIOUS_LOADER, [MalwareType.POSTINSTALL_MALWARE]: ThreatType.MALICIOUS_LOADER, [MalwareType.ANTI_DEBUGGING]: ThreatType.OBFUSCATED_CODE, [MalwareType.VM_DETECTION]: ThreatType.OBFUSCATED_CODE, [MalwareType.SANDBOX_EVASION]: ThreatType.OBFUSCATED_CODE, [MalwareType.PERSISTENCE]: ThreatType.BACKDOOR, [MalwareType.SUSPICIOUS_BEHAVIOR]: ThreatType.SUSPICIOUS_NETWORK }; return mapping[type] || ThreatType.MALICIOUS_LOADER; } } export default MalwareDetector;