mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-02 14:11:02 +01:00
Magic rebuild
This commit is contained in:
parent
d78730edc0
commit
728f8e65d6
@ -42,13 +42,32 @@ for (const opObj in Ops) {
|
||||
outputType: op.presentType,
|
||||
flowControl: op.flowControl,
|
||||
manualBake: op.manualBake,
|
||||
args: op.args
|
||||
args: op.args,
|
||||
};
|
||||
|
||||
if ("patterns" in op) {
|
||||
operationConfig[op.name].patterns = op.patterns;
|
||||
if ("checks" in op) {
|
||||
if ("input" in op.checks) {
|
||||
operationConfig[op.name].input = {};
|
||||
if ("regex" in op.checks.input) {
|
||||
operationConfig[op.name].input.regex = op.checks.input.regex;
|
||||
}
|
||||
if ("entropy" in op.checks.input) {
|
||||
operationConfig[op.name].input.entropy = op.checks.input.entropy;
|
||||
}
|
||||
}
|
||||
if ("output" in op.checks) {
|
||||
operationConfig[op.name].output = {};
|
||||
if ("regex" in op.checks.output) {
|
||||
operationConfig[op.name].output.regex = op.checks.output.regex;
|
||||
}
|
||||
if ("entropy" in op.checks.output) {
|
||||
operationConfig[op.name].output.entropy = op.checks.output.entropy;
|
||||
}
|
||||
if ("mime" in op.checks.output) {
|
||||
operationConfig[op.name].output.mime = op.checks.output.mime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(op.module in modules))
|
||||
modules[op.module] = {};
|
||||
modules[op.module][op.name] = opObj;
|
||||
|
@ -26,7 +26,7 @@ export function ipv4CidrRange(cidr, includeNetworkInfo, enumerateAddresses, allo
|
||||
let output = "";
|
||||
|
||||
if (cidrRange < 0 || cidrRange > 31) {
|
||||
return "IPv4 CIDR must be less than 32";
|
||||
throw new OperationError("IPv4 CIDR must be less than 32");
|
||||
}
|
||||
|
||||
const mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||
@ -64,7 +64,7 @@ export function ipv6CidrRange(cidr, includeNetworkInfo) {
|
||||
cidrRange = parseInt(cidr[cidr.length-1], 10);
|
||||
|
||||
if (cidrRange < 0 || cidrRange > 127) {
|
||||
return "IPv6 CIDR must be less than 128";
|
||||
throw new OperationError("IPv6 CIDR must be less than 128");
|
||||
}
|
||||
|
||||
const ip1 = new Array(8),
|
||||
@ -211,7 +211,7 @@ export function ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, a
|
||||
const network = strToIpv4(ipv4CidrList[i].split("/")[0]);
|
||||
const cidrRange = parseInt(ipv4CidrList[i].split("/")[1], 10);
|
||||
if (cidrRange < 0 || cidrRange > 31) {
|
||||
return "IPv4 CIDR must be less than 32";
|
||||
throw new OperationError("IPv4 CIDR must be less than 32");
|
||||
}
|
||||
const mask = ~(0xFFFFFFFF >>> cidrRange),
|
||||
cidrIp1 = network & mask,
|
||||
@ -254,7 +254,7 @@ export function ipv6ListedRange(match, includeNetworkInfo) {
|
||||
const cidrRange = parseInt(ipv6CidrList[i].split("/")[1], 10);
|
||||
|
||||
if (cidrRange < 0 || cidrRange > 127) {
|
||||
return "IPv6 CIDR must be less than 128";
|
||||
throw new OperationError("IPv6 CIDR must be less than 128");
|
||||
}
|
||||
|
||||
const cidrIp1 = new Array(8),
|
||||
|
@ -2,7 +2,7 @@ import OperationConfig from "../config/OperationConfig.json";
|
||||
import Utils, { isWorkerEnvironment } from "../Utils.mjs";
|
||||
import Recipe from "../Recipe.mjs";
|
||||
import Dish from "../Dish.mjs";
|
||||
import {detectFileType} from "./FileType.mjs";
|
||||
import {detectFileType, isType} from "./FileType.mjs";
|
||||
import chiSquared from "chi-squared";
|
||||
|
||||
/**
|
||||
@ -19,25 +19,24 @@ class Magic {
|
||||
* Magic constructor.
|
||||
*
|
||||
* @param {ArrayBuffer} buf
|
||||
* @param {Object[]} [opPatterns]
|
||||
* @param {Object} prevOp
|
||||
*/
|
||||
constructor(buf, opPatterns) {
|
||||
constructor(buf, opPatterns, prevOp) {
|
||||
this.inputBuffer = new Uint8Array(buf);
|
||||
this.inputStr = Utils.arrayBufferToStr(buf);
|
||||
this.opPatterns = opPatterns || Magic._generateOpPatterns();
|
||||
this.opPatterns = opPatterns || Magic._generateOpCriteria();
|
||||
this.prevOp = prevOp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds operations that claim to be able to decode the input based on regular
|
||||
* expression matches.
|
||||
*
|
||||
* @returns {Object[]}
|
||||
* @param opPatterns
|
||||
*/
|
||||
findMatchingOps() {
|
||||
inputRegexMatch(opPatterns) {
|
||||
const matches = [];
|
||||
|
||||
for (let i = 0; i < this.opPatterns.length; i++) {
|
||||
const pattern = this.opPatterns[i],
|
||||
for (let i = 0; i < opPatterns.length; i++) {
|
||||
const pattern = opPatterns[i],
|
||||
regex = new RegExp(pattern.match, pattern.flags);
|
||||
|
||||
if (regex.test(this.inputStr)) {
|
||||
@ -48,6 +47,34 @@ class Magic {
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
entropyInputMatch(opPatterns) {
|
||||
const matches = [];
|
||||
|
||||
const entropyOfInput = this.calcEntropy();
|
||||
|
||||
for (let i = 0; i < opPatterns.length; i++) {
|
||||
const currOp = opPatterns[i];
|
||||
if ((entropyOfInput > currOp.entropy[0]) && (entropyOfInput < currOp.entropy[1]))
|
||||
matches.push(currOp);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds operations that claim to be able to decode the input based on regular
|
||||
* expression matches.
|
||||
*
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
findMatchingInputOps() {
|
||||
let matches = this.inputRegexMatch(this.opPatterns.regex);
|
||||
matches = matches.concat(this.entropyInputMatch(this.opPatterns.entropy));
|
||||
return [...new Set(matches)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to detect the language of the input by comparing its byte frequency
|
||||
* to that of several known languages.
|
||||
@ -264,6 +291,35 @@ class Magic {
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
checkRegexes(regexes) {
|
||||
for (const elem of regexes) {
|
||||
const regex = new RegExp(elem.match, elem.flags);
|
||||
if (regex.test(this.inputStr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
checkOutputFromPrevious() {
|
||||
let score = 0;
|
||||
if ("regex" in this.prevOp.output) {
|
||||
if (this.checkRegexes(this.prevOp.output.regex)) score++;
|
||||
}
|
||||
if ("entropy" in this.prevOp.output) {
|
||||
const inputEntropy = this.calcEntropy();
|
||||
if ((inputEntropy > this.prevOp.output.entropy[0]) && (inputEntropy < this.prevOp.output.entropy[1])) score++;
|
||||
}
|
||||
if ("mime" in this.prevOp.output) {
|
||||
if (isType(this.prevOp.output.mime, this.inputBuffer)) score++;
|
||||
}
|
||||
return score > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Speculatively executes matching operations, recording metadata of each result.
|
||||
*
|
||||
@ -281,8 +337,15 @@ class Magic {
|
||||
if (depth < 0) return [];
|
||||
|
||||
// Find any operations that can be run on this data
|
||||
const matchingOps = this.findMatchingOps();
|
||||
|
||||
if (this.prevOp) {
|
||||
if ("output" in this.prevOp) {
|
||||
if (!(this.checkOutputFromPrevious())) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
const matchingOps = this.findMatchingInputOps();
|
||||
let results = [];
|
||||
|
||||
// Record the properties of the current data
|
||||
@ -305,8 +368,7 @@ class Magic {
|
||||
const opConfig = {
|
||||
op: op.op,
|
||||
args: op.args
|
||||
},
|
||||
output = await this._runRecipe([opConfig]);
|
||||
}, output = await this._runRecipe([opConfig]);
|
||||
|
||||
// If the recipe is repeating and returning the same data, do not continue
|
||||
if (prevOp && op.op === prevOp.op && _buffersEqual(output, this.inputBuffer)) {
|
||||
@ -318,7 +380,8 @@ class Magic {
|
||||
return;
|
||||
}
|
||||
|
||||
const magic = new Magic(output, this.opPatterns),
|
||||
|
||||
const magic = new Magic(output, this.opPatterns, OperationConfig[op.op]),
|
||||
speculativeResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, intensive, [...recipeConfig, opConfig], op.useful, crib);
|
||||
|
||||
@ -330,7 +393,7 @@ class Magic {
|
||||
const bfEncodings = await this.bruteForce();
|
||||
|
||||
await Promise.all(bfEncodings.map(async enc => {
|
||||
const magic = new Magic(enc.data, this.opPatterns),
|
||||
const magic = new Magic(enc.data, this.opPatterns, undefined),
|
||||
bfResults = await magic.speculativeExecution(
|
||||
depth-1, extLang, false, [...recipeConfig, enc.conf], false, crib);
|
||||
|
||||
@ -447,14 +510,17 @@ class Magic {
|
||||
* @private
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
static _generateOpPatterns() {
|
||||
const opPatterns = [];
|
||||
static _generateOpCriteria() {
|
||||
const opCriteria = {
|
||||
regex: [],
|
||||
entropy: []
|
||||
};
|
||||
|
||||
for (const op in OperationConfig) {
|
||||
if (!("patterns" in OperationConfig[op])) continue;
|
||||
|
||||
OperationConfig[op].patterns.forEach(pattern => {
|
||||
opPatterns.push({
|
||||
if ("input" in OperationConfig[op]) {
|
||||
if ("regex" in OperationConfig[op].input)
|
||||
OperationConfig[op].input.regex.forEach(pattern => {
|
||||
opCriteria.regex.push({
|
||||
op: op,
|
||||
match: pattern.match,
|
||||
flags: pattern.flags,
|
||||
@ -462,9 +528,17 @@ class Magic {
|
||||
useful: pattern.useful || false
|
||||
});
|
||||
});
|
||||
if ("entropy" in OperationConfig[op].input) {
|
||||
opCriteria.entropy.push({
|
||||
op: op,
|
||||
entropy: OperationConfig[op].input.entropy.input,
|
||||
args: OperationConfig[op].input.entropy.args
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return opPatterns;
|
||||
return opCriteria;
|
||||
}
|
||||
|
||||
/**
|
||||
|
12
src/core/lib/MagicCriteria.mjs
Normal file
12
src/core/lib/MagicCriteria.mjs
Normal file
@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Constants for the entropy of text.
|
||||
*
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
export const compressedToDecompressed = [6.5, 8];
|
||||
|
||||
export const binary = [1, 1.5];
|
||||
|
||||
export const entropyOfText = [3.5, 6];
|
@ -33,6 +33,42 @@ class A1Z26CipherDecode extends Operation {
|
||||
value: DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*([12]?[0-9] )+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["Space"]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([12]?[0-9],)+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["Comma"]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([12]?[0-9];)+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["Semi-colon"]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([12]?[0-9]:)+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["Colon"]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([12]?[0-9]\\n)+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["Line feed"]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([12]?[0-9]\\r\\n)+[12]?[0-9]\\s*$",
|
||||
flags: "",
|
||||
args: ["CRLF"]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +44,52 @@ class BaconCipherDecode extends Operation {
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*([01]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Standard (I=J and U=V)", "0/1", false]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([01]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Standard (I=J and U=V)", "0/1", true]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([AB]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Standard (I=J and U=V)", "A/B", false]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([AB]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Standard (I=J and U=V)", "A/B", true]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([01]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Complete", "0/1", false]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([01]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Complete", "0/1", true]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([AB]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Complete", "A/B", false]
|
||||
},
|
||||
{
|
||||
match: "^\\s*([AB]{5}\\s?)+$",
|
||||
flags: "",
|
||||
args: ["Complete", "A/B", true]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,13 +33,17 @@ class Bzip2Decompress extends Operation {
|
||||
value: false
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
"match": "^\\x42\\x5a\\x68",
|
||||
"flags": "",
|
||||
"args": []
|
||||
}
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,17 @@ class DechunkHTTPResponse extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*[0-9A-F]+\r\n",
|
||||
flags: "i",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,6 +30,17 @@ class DecodeNetBIOSName extends Operation {
|
||||
"value": 65
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*\\S{32}$",
|
||||
flags: "",
|
||||
args: [65]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,7 +25,27 @@ class DefangIPAddresses extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*(([0-9]{1,3}\\.){3}[0-9]{1,3}|([0-9a-f]{4}:){7}[0-9a-f]{4})\\s*$",
|
||||
flags: "i",
|
||||
args: [],
|
||||
}
|
||||
]
|
||||
},
|
||||
output: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*(([0-9]{1,3}\\[\\.\\]){3}[0-9]{1,3}|([0-9a-f]{4}\\[\\:\\]){7}[0-9a-f]{4})\\s*$",
|
||||
flags: "i",
|
||||
shouldMatch: true,
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,13 +49,17 @@ class FromBCD extends Operation {
|
||||
"value": FORMAT
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:\\d{4} ){3,}\\d{4}$",
|
||||
flags: "",
|
||||
args: ["8 4 2 1", true, false, "Nibbles"]
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,13 +36,18 @@ class FromBase32 extends Operation {
|
||||
value: true
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input:
|
||||
{
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:[A-Z2-7]{8})+(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}={1})?$",
|
||||
flags: "",
|
||||
args: ["A-Z2-7=", false]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,7 +38,10 @@ class FromBase58 extends Operation {
|
||||
"value": true
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input:
|
||||
{
|
||||
regex: [
|
||||
{
|
||||
match: "^[1-9A-HJ-NP-Za-km-z]{20,}$",
|
||||
flags: "",
|
||||
@ -49,7 +52,9 @@ class FromBase58 extends Operation {
|
||||
flags: "",
|
||||
args: ["rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", false]
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,9 @@ class FromBase64 extends Operation {
|
||||
value: true
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$",
|
||||
flags: "i",
|
||||
@ -102,7 +104,9 @@ class FromBase64 extends Operation {
|
||||
flags: "i",
|
||||
args: ["./0-9A-Za-z", true]
|
||||
},
|
||||
];
|
||||
],
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,7 +36,9 @@ class FromDecimal extends Operation {
|
||||
"value": false
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?: (?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
@ -66,8 +68,10 @@ class FromDecimal extends Operation {
|
||||
match: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\r\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$",
|
||||
flags: "",
|
||||
args: ["CRLF", false]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,13 +25,17 @@ class FromHTMLEntity extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "&(?:#\\d{2,3}|#x[\\da-f]{2}|[a-z]{2,6});",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,9 @@ class FromHex extends Operation {
|
||||
value: FROM_HEX_DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:[\\dA-F]{2})+$",
|
||||
flags: "i",
|
||||
@ -78,7 +80,9 @@ class FromHex extends Operation {
|
||||
flags: "i",
|
||||
args: ["\\x"]
|
||||
}
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,6 +26,17 @@ class FromHexContent extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*.*?\\|([0-9a-f]{2})+\\|.*$",
|
||||
flags: "i",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,13 +27,17 @@ class FromHexdump extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:(?:[\\dA-F]{4,16}h?:?)?[ \\t]*((?:[\\dA-F]{2} ){1,8}(?:[ \\t]|[\\dA-F]{2}-)(?:[\\dA-F]{2} ){1,8}|(?:[\\dA-F]{4} )*[\\dA-F]{4}|(?:[\\dA-F]{2} )*[\\dA-F]{2})[^\\n]*\\n?){2,}$",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -37,13 +37,17 @@ class FromMorseCode extends Operation {
|
||||
"value": WORD_DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "(?:^[-. \\n]{5,}$|^[_. \\n]{5,}$|^(?:dash|dot| |\\n){5,}$)",
|
||||
flags: "i",
|
||||
args: ["Space", "Line feed"]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,9 @@ class FromOctal extends Operation {
|
||||
"value": DELIM_OPTIONS
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(?:[0-7]{1,2}|[123][0-7]{2})(?: (?:[0-7]{1,2}|[123][0-7]{2}))*$",
|
||||
flags: "",
|
||||
@ -62,8 +64,10 @@ class FromOctal extends Operation {
|
||||
match: "^(?:[0-7]{1,2}|[123][0-7]{2})(?:\\r\\n(?:[0-7]{1,2}|[123][0-7]{2}))*$",
|
||||
flags: "",
|
||||
args: ["CRLF"]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,13 +28,17 @@ class FromQuotedPrintable extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "byteArray";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^[\\x21-\\x3d\\x3f-\\x7e \\t]{0,76}(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +33,9 @@ class FromUNIXTimestamp extends Operation {
|
||||
"value": UNITS
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^1?\\d{9}$",
|
||||
flags: "",
|
||||
@ -53,8 +55,10 @@ class FromUNIXTimestamp extends Operation {
|
||||
match: "^1?\\d{18}$",
|
||||
flags: "",
|
||||
args: ["Nanoseconds (ns)"]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,13 +27,17 @@ class Gunzip extends Operation {
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "ArrayBuffer";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\x1f\\x8b\\x08",
|
||||
flags: "",
|
||||
args: []
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,17 @@ class ObjectIdentifierToHex extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*([0-9]{1,3}\\.)+[0-9]{1,3}\\s*$",
|
||||
flags: "",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,6 +38,17 @@ class ParseSSHHostKey extends Operation {
|
||||
]
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*([A-F\\d]{2}[,;:]){15,}[A-F\\d]{2}\\s*$",
|
||||
flags: "i",
|
||||
args: ["Hex"]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,17 @@ class ParseUNIXFilePermissions extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*d[rxw-]{9}\\s*$",
|
||||
flags: "",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,17 @@ class ParseUserAgent extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^(User-Agent:|Mozilla\\/)[^\\n\\r]+\\s*$",
|
||||
flags: "i",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,15 +35,17 @@ class ParseX509Certificate extends Operation {
|
||||
"value": ["PEM", "DER Hex", "Base64", "Raw"]
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
"match": "^-+BEGIN CERTIFICATE-+\\r?\\n[\\da-z+/\\n\\r]+-+END CERTIFICATE-+\\r?\\n?$",
|
||||
"flags": "i",
|
||||
"args": [
|
||||
"PEM"
|
||||
"args": ["PEM"]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,7 @@ import Operation from "../Operation.mjs";
|
||||
import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs";
|
||||
import rawinflate from "zlibjs/bin/rawinflate.min.js";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import * as criteria from "../lib/MagicCriteria.mjs";
|
||||
|
||||
const Zlib = rawinflate.Zlib;
|
||||
|
||||
@ -60,6 +61,14 @@ class RawInflate extends Operation {
|
||||
value: false
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
entropy: {
|
||||
input: [7.5, 8],
|
||||
args: [0, 0, INFLATE_BUFFER_TYPE, false, false]
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,7 +163,7 @@ class RegularExpression extends Operation {
|
||||
case "List matches with capture groups":
|
||||
return Utils.escapeHtml(regexList(input, regex, displayTotal, true, true));
|
||||
default:
|
||||
return "Error: Invalid output format";
|
||||
throw new OperationError("Error: Invalid output format");
|
||||
}
|
||||
} catch (err) {
|
||||
throw new OperationError("Invalid regex. Details: " + err.message);
|
||||
|
@ -35,14 +35,21 @@ class RenderImage extends Operation {
|
||||
"value": ["Raw", "Base64", "Hex"]
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
"match": "^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)",
|
||||
"flags": "",
|
||||
"args": ["Raw"],
|
||||
"useful": true
|
||||
}
|
||||
];
|
||||
]
|
||||
},
|
||||
output: {
|
||||
mime: "image"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,6 +35,17 @@ class StripHTMLTags extends Operation {
|
||||
"value": true
|
||||
}
|
||||
];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^<html>(\\S|\\s)*</html>$",
|
||||
flags: "i",
|
||||
args: [true, true]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,17 @@ class StripHTTPHeaders extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\s*HTTP(.|\\s)+?(\\r?\\n){2}",
|
||||
flags: "",
|
||||
args: []
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,13 +24,17 @@ class URLDecode extends Operation {
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: ".*(?:%[\\da-f]{2}.*){4}",
|
||||
flags: "i",
|
||||
args: []
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,13 +27,17 @@ class Untar extends Operation {
|
||||
this.outputType = "List<File>";
|
||||
this.presentType = "html";
|
||||
this.args = [];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
"match": "^.{257}\\x75\\x73\\x74\\x61\\x72",
|
||||
"flags": "",
|
||||
"args": []
|
||||
}
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,13 +40,17 @@ class Unzip extends Operation {
|
||||
value: false
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\x50\\x4b(?:\\x03|\\x05|\\x07)(?:\\x04|\\x06|\\x08)",
|
||||
flags: "",
|
||||
args: ["", false]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,13 +59,17 @@ class ZlibInflate extends Operation {
|
||||
value: false
|
||||
}
|
||||
];
|
||||
this.patterns = [
|
||||
this.checks = {
|
||||
input: {
|
||||
regex: [
|
||||
{
|
||||
match: "^\\x78(\\x01|\\x9c|\\xda|\\x5e)",
|
||||
flags: "",
|
||||
args: [0, 0, "Adaptive", false, false]
|
||||
},
|
||||
];
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user