CyberChef/src/core/operations/Strings.mjs

117 lines
3.4 KiB
JavaScript

/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation";
import XRegExp from "xregexp";
import { search } from "../lib/Extract";
/**
* Strings operation
*/
class Strings extends Operation {
/**
* Strings constructor
*/
constructor() {
super();
this.name = "Strings";
this.module = "Regex";
this.description = "Extracts all strings from the input.";
this.infoURL = "https://wikipedia.org/wiki/Strings_(Unix)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Encoding",
"type": "option",
"value": ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"]
},
{
"name": "Minimum length",
"type": "number",
"value": 4
},
{
"name": "Match",
"type": "option",
"value": [
"[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
"[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
]
},
{
"name": "Display total",
"type": "boolean",
"value": false
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [encoding, minLen, matchType, displayTotal] = args,
alphanumeric = "A-Z\\d",
punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@",
printable = "\x20-\x7e",
uniAlphanumeric = "\\pL\\pN",
uniPunctuation = "\\pP\\pZ",
uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP";
let strings = "";
switch (matchType) {
case "Alphanumeric + punctuation (A)":
strings = `[${alphanumeric + punctuation}]`;
break;
case "All printable chars (A)":
case "Null-terminated strings (A)":
strings = `[${printable}]`;
break;
case "Alphanumeric + punctuation (U)":
strings = `[${uniAlphanumeric + uniPunctuation}]`;
break;
case "All printable chars (U)":
case "Null-terminated strings (U)":
strings = `[${uniPrintable}]`;
break;
}
// UTF-16 support is hacked in by allowing null bytes on either side of the matched chars
switch (encoding) {
case "All":
strings = `(\x00?${strings}\x00?)`;
break;
case "16-bit littleendian":
strings = `(${strings}\x00)`;
break;
case "16-bit bigendian":
strings = `(\x00${strings})`;
break;
case "Single byte":
default:
break;
}
strings = `${strings}{${minLen},}`;
if (matchType.includes("Null-terminated")) {
strings += "\x00";
}
const regex = new XRegExp(strings, "ig");
return search(input, regex, null, displayTotal);
}
}
export default Strings;