mirror of
https://github.com/horsicq/Detect-It-Easy.git
synced 2026-06-24 01:54:08 +00:00
Updated the MiniJavaScriptHeuristic to recognize files with the 'sg' suffix, improving detection for Detect It Easy modules.
109 lines
No EOL
5.5 KiB
JavaScript
109 lines
No EOL
5.5 KiB
JavaScript
// Detect It Easy: detection rule file
|
|
|
|
// Author: DosX
|
|
// E-Mail: collab@kay-software.ru
|
|
// GitHub: https://github.com/DosX-dev
|
|
// Telegram: @DosX_dev
|
|
|
|
function detect() { main(); }
|
|
|
|
function main() {
|
|
if (Binary.isHeuristicScan()) {
|
|
switch (Binary.getFileSuffix().toLowerCase()) {
|
|
case "js": // JavaScript
|
|
case "jse": // JScript Encoded
|
|
case "jsc": // JavaScript Compiled
|
|
case "sg": // Detect It Easy module
|
|
var options = String();
|
|
|
|
if (!Binary.isPlainText()) {
|
|
options = "bytecode";
|
|
} else {
|
|
if (Binary.getSize() > 3000) {
|
|
var scriptContent = Binary.getString(0x00, Binary.getSize());
|
|
|
|
// Split the code into segments that are outside of string literals.
|
|
// Handle escaping (\", \\', \`) — escaped quotes are not treated as string delimiters.
|
|
// Also include expressions inside template literals `${...}` as code (they will be scanned).
|
|
var segments = [],
|
|
currentSegment = String(),
|
|
insideString = false,
|
|
stringDelimiter = String(),
|
|
isEscaped = false;
|
|
|
|
for (var i = 0; i < scriptContent.length; i++) {
|
|
var currChar = scriptContent[i];
|
|
|
|
if (insideString) {
|
|
if (isEscaped) {
|
|
isEscaped = false;
|
|
continue;
|
|
}
|
|
if (currChar === '\\') {
|
|
isEscaped = true;
|
|
continue;
|
|
}
|
|
|
|
// For template literals: when encountering `${` include nested expression into current segment
|
|
if (stringDelimiter === '`' && currChar === '$' && i + 1 < scriptContent.length && scriptContent[i + 1] === '{') {
|
|
// skip '{' and start accumulating the expression content
|
|
i++; // now scriptContent[i] === '{'
|
|
var braceDepth = 1;
|
|
// Inside the expression, handle escaping as well
|
|
while (i + 1 < scriptContent.length && braceDepth > 0) {
|
|
i++;
|
|
var innerChar = scriptContent[i];
|
|
if (innerChar === '\\') {
|
|
// capture escaped char and the next one
|
|
currentSegment += innerChar;
|
|
if (i + 1 < scriptContent.length) {
|
|
i++; currentSegment += scriptContent[i];
|
|
}
|
|
continue;
|
|
}
|
|
if (innerChar === '{') { braceDepth++; currentSegment += innerChar; continue; }
|
|
if (innerChar === '}') { braceDepth--; if (braceDepth === 0) break; currentSegment += innerChar; continue; }
|
|
currentSegment += innerChar;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (currChar === stringDelimiter) {
|
|
insideString = false;
|
|
stringDelimiter = String();
|
|
}
|
|
// do not copy characters that are inside strings
|
|
} else {
|
|
// not inside a string
|
|
if (currChar === '"' || currChar === "'" || currChar === '`') {
|
|
// start of string — finish current segment
|
|
if (currentSegment.length > 0) { segments.push(currentSegment); currentSegment = String(); }
|
|
insideString = true;
|
|
stringDelimiter = currChar;
|
|
} else {
|
|
currentSegment += currChar;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (currentSegment.length > 0) segments.push(currentSegment);
|
|
|
|
for (var segIndex = 0; segIndex < segments.length; segIndex++) {
|
|
var tokenToProcess = segments[segIndex];
|
|
if (!/( |\t)/.test(tokenToProcess) && (
|
|
/(((var|let|const)[\t ]|\())\b[a-zA-Z](?:,[a-zA-Z]){3,}\b/.test(tokenToProcess) ||
|
|
/[a-zA-Z][!=]?=?=![01][;,})]/.test(tokenToProcess)
|
|
)) {
|
|
options = "minified/compiled";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_setResult("~language", "JavaScript", String(), Binary.isVerbose() ? options : String());
|
|
|
|
break;
|
|
}
|
|
}
|
|
} |