Compare commits

...
11 Commits
8 changed files with 1035 additions and 35 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.7.3",
"version": "9.7.7",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.7.3",
"version": "9.7.7",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
File diff suppressed because it is too large. Load diff
+1
View File
@@ -97,6 +97,7 @@ class Magic {
if (!fileType.length) return null;
return {
name: fileType[0].name,
ext: fileType[0].extension,
mime: fileType[0].mime,
desc: fileType[0].description
+8 -5
View File
@@ -8,6 +8,13 @@ import Operation from "../Operation.mjs";
import {detectFileType} from "../lib/FileType.mjs";
import {FILE_SIGNATURES} from "../lib/FileSignatures.mjs";
// Concat all supported extensions into a single flat list
const exts = [].concat.apply([], Object.keys(FILE_SIGNATURES).map(cat =>
[].concat.apply([], FILE_SIGNATURES[cat].map(sig =>
sig.extension.split(",")
))
)).unique().sort().join(", ");
/**
* Detect File Type operation
*/
@@ -22,11 +29,7 @@ class DetectFileType extends Operation {
this.name = "Detect File Type";
this.module = "Default";
this.description = "Attempts to guess the MIME (Multipurpose Internet Mail Extensions) type of the data based on 'magic bytes'.<br><br>Currently supports the following file types: " +
Object.keys(FILE_SIGNATURES).map(cat =>
FILE_SIGNATURES[cat].map(sig =>
sig.extension.split(",")[0]
).join(", ")
).join(", ") + ".";
exts + ".";
this.infoURL = "https://wikipedia.org/wiki/List_of_file_signatures";
this.inputType = "ArrayBuffer";
this.outputType = "string";
+6 -4
View File
@@ -43,11 +43,13 @@ class NodeRecipe {
} else {
throw new TypeError("Inputted function not a Chef operation.");
}
// CASE: op with configuration
} else if (ing.op && ing.args) {
// Return op and args pair for opList item.
// CASE: op, maybe with configuration
} else if (ing.op) {
const sanitisedOp = this._validateIngredient(ing.op);
return {op: sanitisedOp, args: ing.args};
if (ing.args) {
return {op: sanitisedOp, args: ing.args};
}
return sanitisedOp;
} else {
throw new TypeError("Recipe can only contain function names or functions");
}
+20 -11
View File
@@ -1046,15 +1046,25 @@ class OutputWaiter {
* @param {Object[]} options
*/
backgroundMagicResult(options) {
if (!options.length ||
!options[0].recipe.length)
return;
if (!options.length) return;
const currentRecipeConfig = this.app.getRecipeConfig();
const newRecipeConfig = currentRecipeConfig.concat(options[0].recipe);
const opSequence = options[0].recipe.map(o => o.op).join(", ");
let msg = "",
newRecipeConfig;
this.showMagicButton(opSequence, options[0].data, newRecipeConfig);
if (options[0].recipe.length) {
const opSequence = options[0].recipe.map(o => o.op).join(", ");
newRecipeConfig = currentRecipeConfig.concat(options[0].recipe);
msg = `<i>${opSequence}</i> will produce <span class="data-text">"${Utils.escapeHtml(Utils.truncate(options[0].data), 30)}"</span>`;
} else if (options[0].fileType && options[0].fileType.name) {
const ft = options[0].fileType;
newRecipeConfig = currentRecipeConfig.concat([{op: "Detect File Type", args: []}]);
msg = `<i>${ft.name}</i> file detected`;
} else {
return;
}
this.showMagicButton(msg, newRecipeConfig);
}
/**
@@ -1072,15 +1082,14 @@ class OutputWaiter {
}
/**
* Displays the Magic button with a title and adds a link to a complete recipe.
* Displays the Magic button with a title and adds a link to a recipe.
*
* @param {string} opSequence
* @param {string} result
* @param {string} msg
* @param {Object[]} recipeConfig
*/
showMagicButton(opSequence, result, recipeConfig) {
showMagicButton(msg, recipeConfig) {
const magicButton = document.getElementById("magic");
magicButton.setAttribute("data-original-title", `<i>${opSequence}</i> will produce <span class="data-text">"${Utils.escapeHtml(Utils.truncate(result), 30)}"</span>`);
magicButton.setAttribute("data-original-title", msg);
magicButton.setAttribute("data-recipe", JSON.stringify(recipeConfig), null, "");
magicButton.classList.remove("hidden");
magicButton.classList.add("pulse");
+33
View File
@@ -259,6 +259,13 @@ TestRegister.addApiTests([
assert.strictEqual(result.toString(), "73:6f:6d:65:20:69:6e:70:75:74");
}),
it("chef.bake: should take single JSON object desribing op with optional args", () => {
const result = chef.bake("some input", {
op: chef.toHex,
});
assert.strictEqual(result.toString(), "73 6f 6d 65 20 69 6e 70 75 74");
}),
it("chef.bake: should take single JSON object describing op and args ARRAY", () => {
const result = chef.bake("some input", {
op: chef.toHex,
@@ -295,6 +302,21 @@ TestRegister.addApiTests([
assert.strictEqual(result.toString(), "67;63;72;66;146;72;66;144;72;66;65;72;62;60;72;66;71;72;66;145;72;67;60;72;67;65;72;67;64");
}),
it("chef.bake: should take multiple ops in JSON object form, some without args", () => {
const result = chef.bake("some input", [
{
op: chef.toHex,
},
{
op: "to octal",
args: {
delimiter: "Semi-colon",
}
}
]);
assert.strictEqual(result.toString(), "67;63;40;66;146;40;66;144;40;66;65;40;62;60;40;66;71;40;66;145;40;67;60;40;67;65;40;67;64");
}),
it("chef.bake: should handle op with multiple args", () => {
const result = chef.bake("some input", {
op: "to morse code",
@@ -324,6 +346,17 @@ TestRegister.addApiTests([
assert.strictEqual(result.toString(), "begin_something_anananaaaaak_da_aaak_da_aaaaananaaaaaaan_da_aaaaaaanan_da_aaak_end_something");
}),
it("chef.bake: should accept Clean JSON format from Chef website - args optional", () => {
const result = chef.bake("some input", [
{ "op": "To Morse Code" },
{ "op": "Hex to PEM",
"args": ["SOMETHING"] },
{ "op": "To Snake case",
"args": [false] }
]);
assert.strictEqual(result.toString(), "begin_something_aaaaaaaaaaaaaa_end_something");
}),
it("Excluded operations: throw a sensible error when you try and call one", () => {
try {
chef.fork();