diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js
index 64418cea0c..64e71394b9 100755
--- a/src/core/config/Categories.js
+++ b/src/core/config/Categories.js
@@ -285,6 +285,7 @@ const Categories = [
"Detect File Type",
"Scan for Embedded Files",
"Generate UUID",
+ "Render Image",
"Numberwang",
]
},
diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js
index 9c34b58f75..0612009b0b 100755
--- a/src/core/config/OperationConfig.js
+++ b/src/core/config/OperationConfig.js
@@ -3353,6 +3353,19 @@ const OperationConfig = {
outputType: "string",
args: [],
},
+ "Render Image": {
+ description: "Displays the input as an image. Supports the following formats:
",
+ run: Image.runRenderImage,
+ inputType: "string",
+ outputType: "html",
+ args: [
+ {
+ name: "Input format",
+ type: "option",
+ value: Image.INPUT_FORMAT
+ }
+ ]
+ },
};
export default OperationConfig;
diff --git a/src/core/operations/FileType.js b/src/core/operations/FileType.js
index 90a449ebbe..ad3e5ba747 100755
--- a/src/core/operations/FileType.js
+++ b/src/core/operations/FileType.js
@@ -20,7 +20,7 @@ const FileType = {
* @returns {string}
*/
runDetect: function(input, args) {
- const type = FileType._magicType(input);
+ const type = FileType.magicType(input);
if (!type) {
return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?";
@@ -59,7 +59,7 @@ const FileType = {
numCommonFound = 0;
for (let i = 0; i < input.length; i++) {
- type = FileType._magicType(input.slice(i));
+ type = FileType.magicType(input.slice(i));
if (type) {
if (ignoreCommon && commonExts.indexOf(type.ext) > -1) {
numCommonFound++;
@@ -96,14 +96,13 @@ const FileType = {
* Given a buffer, detects magic byte sequences at specific positions and returns the
* extension and mime type.
*
- * @private
* @param {byteArray} buf
* @returns {Object} type
* @returns {string} type.ext - File extension
* @returns {string} type.mime - Mime type
* @returns {string} [type.desc] - Description
*/
- _magicType: function (buf) {
+ magicType: function (buf) {
if (!(buf && buf.length > 1)) {
return null;
}
diff --git a/src/core/operations/Image.js b/src/core/operations/Image.js
index ef35918b05..9ebafaf0a4 100644
--- a/src/core/operations/Image.js
+++ b/src/core/operations/Image.js
@@ -1,5 +1,6 @@
import * as ExifParser from "exif-parser";
import Utils from "../Utils.js";
+import FileType from "./FileType.js";
/**
@@ -42,6 +43,57 @@ const Image = {
}
},
+
+ /**
+ * @constant
+ * @default
+ */
+ INPUT_FORMAT: ["Raw", "Base64", "Hex"],
+
+ /**
+ * Render Image operation.
+ *
+ * @author n1474335 [n1474335@gmail.com]
+ * @param {string} input
+ * @param {Object[]} args
+ * @returns {html}
+ */
+ runRenderImage(input, args) {
+ const inputFormat = args[0];
+ let dataURI = "data:";
+
+ if (!input.length) return "";
+
+ // Convert input to raw bytes
+ switch (inputFormat) {
+ case "Hex":
+ input = Utils.fromHex(input);
+ break;
+ case "Base64":
+ // Don't trust the Base64 entered by the user.
+ // Unwrap it first, then re-encode later.
+ input = Utils.fromBase64(input, null, "byteArray");
+ break;
+ case "Raw":
+ default:
+ input = Utils.strToByteArray(input);
+ break;
+ }
+
+ // Determine file type
+ const type = FileType.magicType(input);
+ if (type && type.mime.indexOf("image") === 0) {
+ dataURI += type.mime + ";";
+ } else {
+ throw "Invalid file type";
+ }
+
+ // Add image data to URI
+ dataURI += "base64," + Utils.toBase64(input);
+
+ return "";
+ },
+
};
export default Image;
diff --git a/src/web/html/index.html b/src/web/html/index.html
index bec1d51d3d..82284ea410 100755
--- a/src/web/html/index.html
+++ b/src/web/html/index.html
@@ -302,7 +302,7 @@ CyberChef - The Cyber Swiss Army Knife
Version <%= htmlWebpackPlugin.options.version %>
Compile time: <%= htmlWebpackPlugin.options.compileTime %>
- © Crown Copyright 2016.
+ © Crown Copyright 2016.
Licenced under the Apache Licence, Version 2.0.
diff --git a/src/web/stylesheets/layout/_structure.css b/src/web/stylesheets/layout/_structure.css
index b6ef0da259..77902d0924 100644
--- a/src/web/stylesheets/layout/_structure.css
+++ b/src/web/stylesheets/layout/_structure.css
@@ -6,6 +6,10 @@
* @license Apache-2.0
*/
+body {
+ overflow: hidden;
+}
+
#content-wrapper {
position: absolute;
top: 0;
diff --git a/test/index.js b/test/index.js
index 9533fd6cad..94b95e6314 100644
--- a/test/index.js
+++ b/test/index.js
@@ -75,7 +75,7 @@ function handleTestResult(testResult) {
setTimeout(function() {
console.log("Tests took longer than 10 seconds to run, returning.");
process.exit(1);
-}, 1 * 1000);
+}, 10 * 1000);
TestRegister.runTests()
diff --git a/test/tests/operations/Image.js b/test/tests/operations/Image.js
index cf6572a261..c9ec9f848e 100644
--- a/test/tests/operations/Image.js
+++ b/test/tests/operations/Image.js
@@ -2,6 +2,7 @@
* Image operation tests.
*
* @author tlwr [toby@toby.codes]
+ * @author n1474335 [n1474335@gmail.com]
*
* @copyright Crown Copyright 2017
* @license Apache-2.0
@@ -9,6 +10,39 @@
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
+ {
+ name: "Render Image: nothing",
+ input: "",
+ expectedOutput: "",
+ recipeConfig: [
+ { op: "Render Image", args: ["Raw"] }
+ ]
+ },
+ {
+ name: "Render Image: raw gif",
+ input: "4749463839610f000f00b30b00424242ffe700ffef00ffce00000000ffb500ff9c00ffff94ffff10ffffc6ffffefffffff00000000000000000000000021ff0b4e45545343415045322e30030100000021f9040532000b002c000000000f000f0000045a7049096a9d785595ce19170670081204c2600013d09de899aed411108480e229eb9a38194f553998044854725028c6623a14b3727cea7453c0404090790944cdb6abe40e40943317170ca7cff082bb0528d80b2b568662d14f220021f904050a000b002c030009000900010000040530483165040021f904050a000b002c04000a000700010000040530ac3943040021f904050a000b002c040004000700010000040550042943040021f904050a000b002c030004000900020000040a3010228298575c5949040021f904050a000b002c03000400090002000004093008492921415e11010021f9040532000b002c040004000700010000040590904565040021f9040519000b002c030004000800020000040990acb0960c52d41b010021f9040519000b002c030004000900020000040930084264a0128b49220021f904050a000b002c04000400080002000004097005b1ea24b26211010021f904050a000b002c030004000900020000040a3010228298575c5949040021f904050a000b002c03000400090002000004093008492921415e11010021f9040532000b002c040004000700010000040590904565040021f9040519000b002c040003000700030000040a90904525bd54882b42040021f9040519000b002c030003000800020000040990acb0961492da19010021f9040519000b002c030003000900020000040af0044244982408aa71040021f9040519000b002c050003000700030000040a308445c5a098128277040021f904051e000b002c0400040008000200000409902cb1961432d41b010021f904050a000b002c04000a000700010000040590ac3949040021f904050a000b002c030009000900010000040590ac491789003b",
+ expectedOutput: "",
+ recipeConfig: [
+ { op: "From Hex", args: ["Space"] },
+ { op: "Render Image", args: ["Raw"] }
+ ]
+ },
+ {
+ name: "Render Image: hex png",
+ input: "89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af400000006624b474400ff00ff00ffa0bda793000000097048597300000dd700000dd70142289b78000005184944415458c3c5575d6c145514feeeccecccacdbddb6e096a5dbcdb6d06d80d06090466d6953454ab52ad0a65589840ac1d02a313c989af062820fa66210130d9a68b0363c34610135690b188b7183c13f44506c8115ba535ab6ddd2617f667f66ae0fb41596ddee2eadf13c4de69e7bcf77cff9cecf25b83f613b3b3b975b2c96f25028c47a3c9e1f5a5a5a7e05a0016000d0c9ef9442d23448a60edeb973a769c78e1d077272721a65594620106000505996bf1a1f1f3f67369bebc2e1f0ef6bd7aedd0a409d2d00e2743a1f2929296915046199a66901007aa3d1580600131313da24000000a594124288aaaab72a2b2bed1d1d1d8f8ba2386fc3860d9f25f3c84c0088cbe56a2d2c2cdc4708d12552880770a7288a3228088215003c1ecfd68d1b377e9e488f4b66dde974aeb2dbed498da71251146d538ed1b4e4746092dddee170b4300ca3c32c251c0edfd8bc79f3d164de4e0680110461794a02119292c482202c387efcf86f3d3d3d7b13814816024a2955e62a8b4451b4abaafad8e485d5743ca005028153699c4dd30c83140a857e4c9409c900a0bbbbfbc368343a34a3754a693a1c58b76eddf2dadada5d89002705b07bf7eee13367ce3cab284aff6c482808425e6767e70bc9ea0033d3e6c6c6c65fd6ac5953a1695a3453c3a150c84d295529a59aa669914cd3705adc6eb7926eaca74455d5605555d5c3030303f59224bd525f5f7f30992e87ff40344d5328a5caa64d9bbe4ca5cbe07f1666ae522dae40a5dd8ed30941c8e5727d63341a9f8a5f181a1ac2f0f07022029e02109d2b00bae2e26207cbb2f72cf03c8f9c9c9c441c580c804dc70b330258b6c020beb87ac9abecb59f8b087377b4f4f30a68b6de482549a29224ddb5168bc51cd5d5d54ff6f5f575cfa69633edeb971c78e2d195db055e77cfb6a2eaadb816e5b59ffafb19a7d3095555e3ab64341a8d96f6f6f6fe755f247c69d542abd9c0bd3c70f90a628c30fd5f56542c5c550fc3837600406e6e2eca9e2e433837fcefc0c8b2e079fe7b9fcfe7aba9a9296613c52f55084acc864a027013b28c828a2d30e805bcbe670fac4b5740f5a9285b18c6a0db4da8c180fdc6fdb035d850c555a174a4148410b85cae7293c97442a7d395363434347775757d91b6075a2a6c45d66ce18369258685de644659d96af45ff80345f9f908c932821313c4eff7639b6d1b06838358242c82d96c86288abe582ce6e6797e052184701c9797910796e61976b10c991fff7f7b5313b6373541d5340426d36f747414e5c67294679503a1e90634e6f57adbac56ebb14020f0e9a14387decf84038c8e232b53b45888dc6dec63636389d290c9caca5a3d09a6a2a6a6a628130054d33092a2c52272bbe4515996113f16288ab2c86432bd01001cc72db5582caf651202eaf5473e7e80d7af270409d9cb320c0c66331ca5a5602c1624180d492412392bcbf2db46a3f1394992f665c481b77a2f9f78e719476b5e16ff2e00d31dae8524cb30e8f560390ee72e5e243d7d7d34168bc16030a87575752ccbb20400a2d1e8b7478e1c390ce0f0fd5442fae6d7039f343d643956345f5fcbf1fafd00b219868145afc78d4b97101a1b833a32426d361bcdcfcf87cd6663a7a6649ee70725497a6faede86e4c2c993cf171716eee5753aeb9d0b7f5ebfae5df67a99b86164e8e6cd9badcdcdcdc7d27ae5a6a3f45147c7794dd30e2e59bcf896c0f3851ccbe602c0a8df4fc783413269d8130c06f79d3e7d7a4b5b5bdbd9b45b77c60304c3f0df75752db31714acf8dbe7cbbee2f5fafd7efff9f6f6f6b357af5e8d647ade3fa1780bad734c65970000000049454e44ae426082",
+ expectedOutput: "",
+ recipeConfig: [
+ { op: "Render Image", args: ["Hex"] }
+ ]
+ },
+ {
+ name: "Render Image: base64 jpg",
+ input: "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",
+ expectedOutput: "",
+ recipeConfig: [
+ { op: "Render Image", args: ["Base64"] }
+ ]
+ },
{
name: "Extract EXIF: nothing",
input: "",