From ce6d38860dcc1b76fc85ecbecde04dbceeb57416 Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 19:39:01 +0100 Subject: [PATCH 001/165] Add operation Added 'Take nth bytes' operation. --- src/core/config/Categories.json | 3 +- src/core/operations/TakeNthBytes.mjs | 78 ++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/core/operations/TakeNthBytes.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index db2ab3a63..9fb63d360 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -238,7 +238,8 @@ "Escape string", "Unescape string", "Pseudo-Random Number Generator", - "Sleep" + "Sleep", + "Take nth bytes" ] }, { diff --git a/src/core/operations/TakeNthBytes.mjs b/src/core/operations/TakeNthBytes.mjs new file mode 100644 index 000000000..7dcf9c6ee --- /dev/null +++ b/src/core/operations/TakeNthBytes.mjs @@ -0,0 +1,78 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Take nth bytes operation + */ +class TakeNthBytes extends Operation { + + /** + * TakeNthBytes constructor + */ + constructor() { + super(); + + this.name = "Take nth bytes"; + this.module = "Default"; + this.description = "Takes every nth byte starting with a given byte."; + this.infoURL = ""; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Take every", + type: "number", + value: 4 + }, + { + name: "Starting at", + type: "number", + value: 0 + }, + { + name: "Apply to each line", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + let n = args[0]; + let start = args[1]; + let eachLine = args[2]; + + if (parseInt(n) !== n || n <= 0) { + throw new OperationError("'Take every' must be a positive integer.") + } + if (parseInt(start) !== start || start < 0) { + throw new OperationError("'Starting at' must be a positive or zero integer.") + } + + let offset = 0; + let output = []; + for (let i = 0; i < input.length; i++) { + if (eachLine && input[i] == 0x0a) { + offset = i + 1; + } else if (i - offset >= start && (i - (start + offset)) % n == 0) { + output.push(input[i]); + } + } + + return output; + } + +} + +export default TakeNthBytes; From 7c7d1823ca4e31139a804c3ca067806c200c530c Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 19:53:57 +0100 Subject: [PATCH 002/165] Fix formatting issue Fixed issue where new lines were truncated. --- src/core/operations/TakeNthBytes.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/operations/TakeNthBytes.mjs b/src/core/operations/TakeNthBytes.mjs index 7dcf9c6ee..ffc42ff9e 100644 --- a/src/core/operations/TakeNthBytes.mjs +++ b/src/core/operations/TakeNthBytes.mjs @@ -64,6 +64,7 @@ class TakeNthBytes extends Operation { let output = []; for (let i = 0; i < input.length; i++) { if (eachLine && input[i] == 0x0a) { + output.push(0x0a); offset = i + 1; } else if (i - offset >= start && (i - (start + offset)) % n == 0) { output.push(input[i]); From 502f126986cc10c2eb4df2aca46bcbe98cadeb3a Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:15:45 +0100 Subject: [PATCH 003/165] Fix linting Fixed linting. --- src/core/operations/TakeNthBytes.mjs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/core/operations/TakeNthBytes.mjs b/src/core/operations/TakeNthBytes.mjs index ffc42ff9e..05de88697 100644 --- a/src/core/operations/TakeNthBytes.mjs +++ b/src/core/operations/TakeNthBytes.mjs @@ -49,24 +49,24 @@ class TakeNthBytes extends Operation { * @returns {byteArray} */ run(input, args) { - let n = args[0]; - let start = args[1]; - let eachLine = args[2]; + const n = args[0]; + const start = args[1]; + const eachLine = args[2]; - if (parseInt(n) !== n || n <= 0) { - throw new OperationError("'Take every' must be a positive integer.") + if (parseInt(n, 10) !== n || n <= 0) { + throw new OperationError("'Take every' must be a positive integer."); } - if (parseInt(start) !== start || start < 0) { - throw new OperationError("'Starting at' must be a positive or zero integer.") + if (parseInt(start, 10) !== start || start < 0) { + throw new OperationError("'Starting at' must be a positive or zero integer."); } - + let offset = 0; - let output = []; + const output = []; for (let i = 0; i < input.length; i++) { - if (eachLine && input[i] == 0x0a) { + if (eachLine && input[i] === 0x0a) { output.push(0x0a); offset = i + 1; - } else if (i - offset >= start && (i - (start + offset)) % n == 0) { + } else if (i - offset >= start && (i - (start + offset)) % n === 0) { output.push(input[i]); } } From 02f65379736b3a9739342f335fa84476600ea39e Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:16:14 +0100 Subject: [PATCH 004/165] Add tests Added tests for the 'Take nth byte' operation. --- tests/operations/tests/TakeNthBytes.mjs | 123 ++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 tests/operations/tests/TakeNthBytes.mjs diff --git a/tests/operations/tests/TakeNthBytes.mjs b/tests/operations/tests/TakeNthBytes.mjs new file mode 100644 index 000000000..22181c3d2 --- /dev/null +++ b/tests/operations/tests/TakeNthBytes.mjs @@ -0,0 +1,123 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +/** + * Take nth bytes tests + */ +TestRegister.addTests([ + { + name: "Take nth bytes: Nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Take nth bytes: Nothing (apply to each line)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Take nth bytes: Basic single line", + input: "0123456789", + expectedOutput: "048", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Take nth bytes: Basic single line (apply to each line)", + input: "0123456789", + expectedOutput: "048", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Take nth bytes: Complex single line", + input: "0123456789", + expectedOutput: "59", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Take nth bytes: Complex single line (apply to each line)", + input: "0123456789", + expectedOutput: "59", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 5, true], + }, + ], + }, + { + name: "Take nth bytes: Basic multi line", + input: "01234\n56789", + expectedOutput: "047", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Take nth bytes: Basic multi line (apply to each line)", + input: "01234\n56789", + expectedOutput: "04\n59", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Take nth bytes: Complex multi line", + input: "01234\n56789", + expectedOutput: "\n8", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Take nth bytes: Complex multi line (apply to each line)", + input: "012345\n6789ab", + expectedOutput: "5\nb", + recipeConfig: [ + { + op: "Take nth bytes", + args: [4, 5, true], + }, + ], + } +]); From 30349dbcb90156b98365462dcd93b6dabb540b9d Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:44:57 +0100 Subject: [PATCH 005/165] Add operation Added 'Drop nth bytes' operation. --- src/core/config/Categories.json | 3 +- src/core/operations/DropNthBytes.mjs | 79 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/core/operations/DropNthBytes.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index db2ab3a63..9cfeb7fe0 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -238,7 +238,8 @@ "Escape string", "Unescape string", "Pseudo-Random Number Generator", - "Sleep" + "Sleep", + "Drop nth bytes" ] }, { diff --git a/src/core/operations/DropNthBytes.mjs b/src/core/operations/DropNthBytes.mjs new file mode 100644 index 000000000..e6bac1cd2 --- /dev/null +++ b/src/core/operations/DropNthBytes.mjs @@ -0,0 +1,79 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Drop nth bytes operation + */ +class DropNthBytes extends Operation { + + /** + * DropNthBytes constructor + */ + constructor() { + super(); + + this.name = "Drop nth bytes"; + this.module = "Default"; + this.description = "Drops every nth byte starting with a given byte."; + this.infoURL = ""; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Drop every", + type: "number", + value: 4 + }, + { + name: "Starting at", + type: "number", + value: 0 + }, + { + name: "Apply to each line", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const n = args[0]; + const start = args[1]; + const eachLine = args[2]; + + if (parseInt(n, 10) !== n || n <= 0) { + throw new OperationError("'Drop every' must be a positive integer."); + } + if (parseInt(start, 10) !== start || start < 0) { + throw new OperationError("'Starting at' must be a positive or zero integer."); + } + + let offset = 0; + const output = []; + for (let i = 0; i < input.length; i++) { + if (eachLine && input[i] === 0x0a) { + output.push(0x0a); + offset = i + 1; + } else if (i - offset < start || (i - (start + offset)) % n !== 0) { + output.push(input[i]); + } + } + + return output; + } + +} + +export default DropNthBytes; From b125f82784274b3d68eb0a1e2777c63bbf68f205 Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 20:59:04 +0100 Subject: [PATCH 006/165] Add tests Added tests for 'Drop nth bytes' operation. --- tests/operations/index.mjs | 1 + tests/operations/tests/DropNthBytes.mjs | 123 ++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 tests/operations/tests/DropNthBytes.mjs diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index d64a77377..046a0b79d 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -91,6 +91,7 @@ import "./tests/Protobuf.mjs"; import "./tests/ParseSSHHostKey.mjs"; import "./tests/DefangIP.mjs"; import "./tests/ParseUDP.mjs"; +import "./tests/DropNthBytes.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; diff --git a/tests/operations/tests/DropNthBytes.mjs b/tests/operations/tests/DropNthBytes.mjs new file mode 100644 index 000000000..00d4e0ab7 --- /dev/null +++ b/tests/operations/tests/DropNthBytes.mjs @@ -0,0 +1,123 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +/** + * Drop nth bytes tests + */ +TestRegister.addTests([ + { + name: "Drop nth bytes: Nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Nothing (apply to each line)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Basic single line", + input: "0123456789", + expectedOutput: "1235679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Basic single line (apply to each line)", + input: "0123456789", + expectedOutput: "1235679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Complex single line", + input: "0123456789", + expectedOutput: "01234678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Drop nth bytes: Complex single line (apply to each line)", + input: "0123456789", + expectedOutput: "01234678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, true], + }, + ], + }, + { + name: "Drop nth bytes: Basic multi line", + input: "01234\n56789", + expectedOutput: "123\n5689", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, false], + }, + ], + }, + { + name: "Drop nth bytes: Basic multi line (apply to each line)", + input: "01234\n56789", + expectedOutput: "123\n678", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 0, true], + }, + ], + }, + { + name: "Drop nth bytes: Complex multi line", + input: "01234\n56789", + expectedOutput: "012345679", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, false], + }, + ], + }, + { + name: "Drop nth bytes: Complex multi line (apply to each line)", + input: "012345\n6789ab", + expectedOutput: "01234\n6789a", + recipeConfig: [ + { + op: "Drop nth bytes", + args: [4, 5, true], + }, + ], + } +]); From 518b33643198ed6ee474b9296fa6f7ffdd6f9dfb Mon Sep 17 00:00:00 2001 From: Oshawk Date: Mon, 21 Oct 2019 21:01:33 +0100 Subject: [PATCH 007/165] Add tests to index Added tests to index. --- tests/operations/index.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index d64a77377..348e84605 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -91,6 +91,7 @@ import "./tests/Protobuf.mjs"; import "./tests/ParseSSHHostKey.mjs"; import "./tests/DefangIP.mjs"; import "./tests/ParseUDP.mjs"; +import "./tests/TakeNthBytes.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; From 23763363bab5c24338c89f7131ebed7921dc5951 Mon Sep 17 00:00:00 2001 From: Philipp Arnold Date: Fri, 10 Dec 2021 23:22:57 +0100 Subject: [PATCH 008/165] Added a JSON to YAML and a YALM to JSON operation --- src/core/config/Categories.json | 4 ++- src/core/operations/JSONToYAML.mjs | 46 ++++++++++++++++++++++++++++++ src/core/operations/YAMLToJSON.mjs | 45 +++++++++++++++++++++++++++++ tests/operations/index.mjs | 1 + tests/operations/tests/YAML.mjs | 42 +++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 src/core/operations/JSONToYAML.mjs create mode 100644 src/core/operations/YAMLToJSON.mjs create mode 100644 tests/operations/tests/YAML.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 09ee8d15b..e35bc8519 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -63,7 +63,9 @@ "JSON to CSV", "Avro to JSON", "CBOR Encode", - "CBOR Decode" + "CBOR Decode", + "YAML to JSON", + "JSON to YAML" ] }, { diff --git a/src/core/operations/JSONToYAML.mjs b/src/core/operations/JSONToYAML.mjs new file mode 100644 index 000000000..2c8102e06 --- /dev/null +++ b/src/core/operations/JSONToYAML.mjs @@ -0,0 +1,46 @@ +/** + * @author ccarpo [ccarpo@gmx.net] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import YAML from "yaml"; + +/** + * JSON to YAML operation + */ +class JSONToYAML extends Operation { + + /** + * JSONToYAML constructor + */ + constructor() { + super(); + + this.name = "JSON to YAML"; + this.module = "Default"; + this.description = "Converts a JSON into a YAML"; + this.infoURL = "https://en.wikipedia.org/wiki/YAML"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + try { + return YAML.stringify(input); + } catch (err) { + throw new OperationError("Test"); + } + } + +} + +export default JSONToYAML; diff --git a/src/core/operations/YAMLToJSON.mjs b/src/core/operations/YAMLToJSON.mjs new file mode 100644 index 000000000..4f77f4fde --- /dev/null +++ b/src/core/operations/YAMLToJSON.mjs @@ -0,0 +1,45 @@ +/** + * @author ccarpo [ccarpo@gmx.net] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import jsYaml from "js-yaml"; +/** + * YAML to JSON operation + */ +class YAMLToJSON extends Operation { + + /** + * YAMLToJSON constructor + */ + constructor() { + super(); + + this.name = "YAML to JSON"; + this.module = "Default"; + this.description = "Converts a YAML to JSON"; + this.infoURL = "https://en.wikipedia.org/wiki/YAML"; + this.inputType = "string"; + this.outputType = "JSON"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {JSON} + */ + run(input, args) { + try { + return jsYaml.load(input); + } catch (err) { + throw new OperationError("Unable to parse YAML: " + err); + } + } + +} + +export default YAMLToJSON; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 9add20b9b..3f7a7457f 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -107,6 +107,7 @@ import "./tests/CBORDecode.mjs"; import "./tests/JA3Fingerprint.mjs"; import "./tests/JA3SFingerprint.mjs"; import "./tests/HASSH.mjs"; +import "./tests/YAML.mjs"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/YAML.mjs b/tests/operations/tests/YAML.mjs new file mode 100644 index 000000000..ba72ed436 --- /dev/null +++ b/tests/operations/tests/YAML.mjs @@ -0,0 +1,42 @@ + +/** + * YAML tests. + * + * @author ccarpo [ccarpo@gmx.net] + * + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +const EXAMPLE_YAML = `number: 3\nplain: string\nblock: |\n two\n lines`; +const EXAMPLE_JSON = `{ "number": 3, "plain": "string" }`; + +TestRegister.addTests([ + { + name: "YAML to JSON", + input: EXAMPLE_YAML, + expectedOutput: JSON.stringify({ + "number": 3, + "plain": "string", + "block": "two\nlines\n" + }, null, 4), + recipeConfig: [ + { + op: "YAML to JSON", + args: [], + } + ], + }, + { + name: "JSON to YAML", + input: EXAMPLE_JSON, + expectedOutput: `number: 3\nplain: string\n`, + recipeConfig: [ + { + op: "JSON to YAML", + args: [], + } + ], + }, +]); From 3e8c5d945cd65e920930ddd6dfb012123cd6a0a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Mon, 27 Feb 2023 06:09:30 +0000 Subject: [PATCH 009/165] Add "XOR Checksum" operation --- src/core/config/Categories.json | 3 +- src/core/operations/XORChecksum.mjs | 59 +++++++++++++++++++ tests/operations/tests/Checksum.mjs | 90 ++++++++++++++++++++++++++++- 3 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 src/core/operations/XORChecksum.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 075e8d666..97b20bd76 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -390,7 +390,8 @@ "CRC-8 Checksum", "CRC-16 Checksum", "CRC-32 Checksum", - "TCP/IP Checksum" + "TCP/IP Checksum", + "XOR Checksum" ] }, { diff --git a/src/core/operations/XORChecksum.mjs b/src/core/operations/XORChecksum.mjs new file mode 100644 index 000000000..1603a2651 --- /dev/null +++ b/src/core/operations/XORChecksum.mjs @@ -0,0 +1,59 @@ +/** + * @author Thomas Weißschuh [thomas@t-8ch.de] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { toHex } from "../lib/Hex.mjs"; + +/** + * XOR Checksum operation + */ +class XORChecksum extends Operation { + + /** + * XORChecksum constructor + */ + constructor() { + super(); + + this.name = "XOR Checksum"; + this.module = "Crypto"; + this.description = "XOR Checksum splits the input into blocks of a configurable size and performs the XOR operation on these blocks."; + this.infoURL = "https://wikipedia.org/wiki/XOR"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "Blocksize", + type: "number", + value: 4 + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const blocksize = args[0]; + input = new Uint8Array(input); + + const res = Array(blocksize); + res.fill(0); + + for (const chunk of Utils.chunked(input, blocksize)) { + for (let i = 0; i < blocksize; i++) { + res[i] ^= chunk[i]; + } + } + + return toHex(res, ""); + } +} + +export default XORChecksum; diff --git a/tests/operations/tests/Checksum.mjs b/tests/operations/tests/Checksum.mjs index 142ee2678..5266ab992 100644 --- a/tests/operations/tests/Checksum.mjs +++ b/tests/operations/tests/Checksum.mjs @@ -237,5 +237,93 @@ TestRegister.addTests([ "args": [] } ] - } + }, + { + name: "XOR Checksum (1): nothing", + input: "", + expectedOutput: "00", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [1] + } + ] + }, + { + name: "XOR Checksum (1): basic string", + input: BASIC_STRING, + expectedOutput: "08", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [1] + } + ] + }, + { + name: "XOR Checksum (1): UTF-8", + input: UTF8_STR, + expectedOutput: "df", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [1] + } + ] + }, + { + name: "XOR Checksum (1): all bytes", + input: ALL_BYTES, + expectedOutput: "00", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [1] + } + ] + }, + { + name: "XOR Checksum (4): nothing", + input: "", + expectedOutput: "00000000", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [4] + } + ] + }, + { + name: "XOR Checksum (4): basic string", + input: BASIC_STRING, + expectedOutput: "4918421b", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [4] + } + ] + }, + { + name: "XOR Checksum (4): UTF-8", + input: UTF8_STR, + expectedOutput: "83a424dc", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [4] + } + ] + }, + { + name: "XOR Checksum (4): all bytes", + input: ALL_BYTES, + expectedOutput: "00000000", + recipeConfig: [ + { + "op": "XOR Checksum", + "args": [4] + } + ] + }, ]); From 73a39fa3ceba9f04bda0d7c96d6993732700add3 Mon Sep 17 00:00:00 2001 From: starplanet Date: Wed, 5 Apr 2023 18:25:37 +0800 Subject: [PATCH 010/165] fix: fix ToDecimal signed logic --- src/core/operations/ToDecimal.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/operations/ToDecimal.mjs b/src/core/operations/ToDecimal.mjs index 65798a7cb..50db41f68 100644 --- a/src/core/operations/ToDecimal.mjs +++ b/src/core/operations/ToDecimal.mjs @@ -45,11 +45,12 @@ class ToDecimal extends Operation { * @returns {string} */ run(input, args) { - input = new Uint8Array(input); const delim = Utils.charRep(args[0]), signed = args[1]; if (signed) { - input = input.map(v => v > 0x7F ? v - 0xFF - 1 : v); + input = new Int8Array(input); + } else { + input = new Uint8Array(input); } return input.join(delim); } From bf1e708a4cd465b35df6bede05a75f4b81fe1394 Mon Sep 17 00:00:00 2001 From: Brunon Blok <43315279+brun0ne@users.noreply.github.com> Date: Thu, 6 Apr 2023 20:32:50 +0000 Subject: [PATCH 011/165] added PHP Serialize operation --- src/core/operations/PHPSerialize.mjs | 144 ++++++++++++++++++++++++ tests/operations/tests/PHPSerialize.mjs | 112 ++++++++++++++++++ 2 files changed, 256 insertions(+) create mode 100644 src/core/operations/PHPSerialize.mjs create mode 100644 tests/operations/tests/PHPSerialize.mjs diff --git a/src/core/operations/PHPSerialize.mjs b/src/core/operations/PHPSerialize.mjs new file mode 100644 index 000000000..94f42cbb4 --- /dev/null +++ b/src/core/operations/PHPSerialize.mjs @@ -0,0 +1,144 @@ +/** + * @author brun0ne [brunonblok@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PHP Serialize operation + */ +class PHPSerialize extends Operation { + + /** + * PHPSerialize constructor + */ + constructor() { + super(); + + this.name = "PHP Serialize"; + this.module = "Default"; + this.description = "Performs PHP serialization on JSON data.

This function does not support object tags.

Since PHP doesn't distinguish dicts and arrays, this operation is not always symmetric to PHP Deserialize.

Example:
[5,"abc",true]
becomes
a:3:{i:0;i:5;i:1;s:3:"abc";i:2;b:1;}"; + this.infoURL = "https://www.phpinternalsbook.com/php5/classes_objects/serialization.html"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + /** + * Determines if a number is an integer + * @param {number} value + * @returns {boolean} + */ + function isInteger(value) { + return typeof value === "number" && parseInt(value.toString(), 10) === value; + } + + /** + * Serialize basic types + * @param {string | number | boolean} content + * @returns {string} + */ + function serializeBasicTypes(content) { + const basicTypes = { + "string": "s", + "integer": "i", + "float": "d", + "boolean": "b" + }; + + /** + * Booleans + * cast to 0 or 1 + */ + if (typeof content === "boolean"){ + return `${basicTypes["boolean"]}:${content ? 1 : 0}`; + } + + /** + * Numbers + */ + if (typeof content === "number"){ + if (isInteger(content)){ + return `${basicTypes["integer"]}:${content.toString()}` + } + else { + return `${basicTypes["float"]}:${content.toString()}` + } + } + + /** + * Strings + */ + if (typeof content === "string") + return `${basicTypes["string"]}:${content.length}:"${content}"`; + + /** This should be unreachable */ + throw new OperationError(`Encountered a non-implemented type: ${typeof content}`); + } + + /** + * Recursively serialize + * @param {*} object + * @returns {string} + */ + function serialize(object) { + /** + * Null + */ + if (object == null) { + return `N;` + } + + /** + * Basic types + */ + if (typeof object !== "object"){ + return `${serializeBasicTypes(object)};`; + } + + /** + * Arrays + */ + else if (object instanceof Array) { + const serializedElements = []; + + for (let i = 0; i < object.length; i++) { + serializedElements.push(`${serialize(i)}${serialize(object[i])}`); + } + + return `a:${object.length}:{${serializedElements.join("")}}` + } + + /** + * Objects + * Note: the output cannot be guaranteed to be in the same order as the input + */ + else if (object instanceof Object) { + const serializedElements = []; + const keys = Object.keys(object); + + for (const key of keys) { + serializedElements.push(`${serialize(key)}${serialize(object[key])}`); + } + + return `a:${keys.length}:{${serializedElements.join("")}}` + } + + /** This should be unreachable */ + throw new OperationError(`Encountered a non-implemented type: ${typeof object}`); + } + + return serialize(input); + } +} + +export default PHPSerialize; diff --git a/tests/operations/tests/PHPSerialize.mjs b/tests/operations/tests/PHPSerialize.mjs new file mode 100644 index 000000000..fa6e87c53 --- /dev/null +++ b/tests/operations/tests/PHPSerialize.mjs @@ -0,0 +1,112 @@ +/** + * PHP Serialization tests. + * + * @author brun0ne [brunonblok@gmail.com] + * + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "PHP Serialize empty array", + input: "[]", + expectedOutput: "a:0:{}", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize empty object", + input: "{}", + expectedOutput: "a:0:{}", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize null", + input: "null", + expectedOutput: "N;", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize integer", + input: "10", + expectedOutput: "i:10;", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize float", + input: "14.523", + expectedOutput: "d:14.523;", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize boolean", + input: "[true, false]", + expectedOutput: "a:2:{i:0;b:1;i:1;b:0;}", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize string", + input: "\"Test string to serialize\"", + expectedOutput: "s:24:\"Test string to serialize\";", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize object", + input: "{\"a\": 10,\"0\": {\"ab\": true}}", + expectedOutput: "a:2:{s:1:\"0\";a:1:{s:2:\"ab\";b:1;}s:1:\"a\";i:10;}", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + }, + { + name: "PHP Serialize array", + input: "[1,\"abc\",true,{\"x\":1,\"y\":2}]", + expectedOutput: "a:4:{i:0;i:1;i:1;s:3:\"abc\";i:2;b:1;i:3;a:2:{s:1:\"x\";i:1;s:1:\"y\";i:2;}}", + recipeConfig: [ + { + op: "PHP Serialize", + args: [] + } + ] + } +]); From 15b426ebb6e18414259f000640f5287c431b5a25 Mon Sep 17 00:00:00 2001 From: Brunon Blok <43315279+brun0ne@users.noreply.github.com> Date: Thu, 6 Apr 2023 21:03:46 +0000 Subject: [PATCH 012/165] clean up code formatting and fix missing entries --- src/core/config/Categories.json | 1 + src/core/operations/PHPSerialize.mjs | 74 +++++++++++++--------------- tests/operations/index.mjs | 1 + 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index ce2f01f5e..c95637eff 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -418,6 +418,7 @@ "JPath expression", "CSS selector", "PHP Deserialize", + "PHP Serialize", "Microsoft Script Decoder", "Strip HTML tags", "Diff", diff --git a/src/core/operations/PHPSerialize.mjs b/src/core/operations/PHPSerialize.mjs index 94f42cbb4..221af3274 100644 --- a/src/core/operations/PHPSerialize.mjs +++ b/src/core/operations/PHPSerialize.mjs @@ -35,7 +35,7 @@ class PHPSerialize extends Operation { run(input, args) { /** * Determines if a number is an integer - * @param {number} value + * @param {number} value * @returns {boolean} */ function isInteger(value) { @@ -44,7 +44,7 @@ class PHPSerialize extends Operation { /** * Serialize basic types - * @param {string | number | boolean} content + * @param {string | number | boolean} content * @returns {string} */ function serializeBasicTypes(content) { @@ -54,40 +54,36 @@ class PHPSerialize extends Operation { "float": "d", "boolean": "b" }; - /** * Booleans * cast to 0 or 1 */ - if (typeof content === "boolean"){ - return `${basicTypes["boolean"]}:${content ? 1 : 0}`; + if (typeof content === "boolean") { + return `${basicTypes.boolean}:${content ? 1 : 0}`; } - /** * Numbers */ - if (typeof content === "number"){ - if (isInteger(content)){ - return `${basicTypes["integer"]}:${content.toString()}` - } - else { - return `${basicTypes["float"]}:${content.toString()}` + if (typeof content === "number") { + if (isInteger(content)) { + return `${basicTypes.integer}:${content.toString()}`; + } else { + return `${basicTypes.float}:${content.toString()}`; } } - /** * Strings */ if (typeof content === "string") - return `${basicTypes["string"]}:${content.length}:"${content}"`; - + return `${basicTypes.string}:${content.length}:"${content}"`; + /** This should be unreachable */ throw new OperationError(`Encountered a non-implemented type: ${typeof content}`); } /** * Recursively serialize - * @param {*} object + * @param {*} object * @returns {string} */ function serialize(object) { @@ -95,42 +91,38 @@ class PHPSerialize extends Operation { * Null */ if (object == null) { - return `N;` + return `N;`; } - - /** - * Basic types - */ - if (typeof object !== "object"){ + + if (typeof object !== "object") { + /** + * Basic types + */ return `${serializeBasicTypes(object)};`; - } - - /** - * Arrays - */ - else if (object instanceof Array) { + } else if (object instanceof Array) { + /** + * Arrays + */ const serializedElements = []; - + for (let i = 0; i < object.length; i++) { serializedElements.push(`${serialize(i)}${serialize(object[i])}`); } - - return `a:${object.length}:{${serializedElements.join("")}}` - } - - /** - * Objects - * Note: the output cannot be guaranteed to be in the same order as the input - */ - else if (object instanceof Object) { + + return `a:${object.length}:{${serializedElements.join("")}}`; + } else if (object instanceof Object) { + /** + * Objects + * Note: the output cannot be guaranteed to be in the same order as the input + */ const serializedElements = []; const keys = Object.keys(object); - + for (const key of keys) { serializedElements.push(`${serialize(key)}${serialize(object[key])}`); } - - return `a:${keys.length}:{${serializedElements.join("")}}` + + return `a:${keys.length}:{${serializedElements.join("")}}`; } /** This should be unreachable */ diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 56f432e09..0bf8fd3bf 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -70,6 +70,7 @@ import "./tests/NormaliseUnicode.mjs"; import "./tests/OTP.mjs"; import "./tests/PGP.mjs"; import "./tests/PHP.mjs"; +import "./tests/PHPSerialize.mjs"; import "./tests/ParseIPRange.mjs"; import "./tests/ParseQRCode.mjs"; import "./tests/PEMtoHex.mjs"; From c0e84dcd501d12d0b322b2595f2c2424d6489b0e Mon Sep 17 00:00:00 2001 From: Brunon Blok <43315279+brun0ne@users.noreply.github.com> Date: Sun, 9 Apr 2023 19:06:59 +0000 Subject: [PATCH 013/165] change comments --- src/core/operations/PHPSerialize.mjs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/core/operations/PHPSerialize.mjs b/src/core/operations/PHPSerialize.mjs index 221af3274..00fb1380b 100644 --- a/src/core/operations/PHPSerialize.mjs +++ b/src/core/operations/PHPSerialize.mjs @@ -61,9 +61,7 @@ class PHPSerialize extends Operation { if (typeof content === "boolean") { return `${basicTypes.boolean}:${content ? 1 : 0}`; } - /** - * Numbers - */ + /* Numbers */ if (typeof content === "number") { if (isInteger(content)) { return `${basicTypes.integer}:${content.toString()}`; @@ -71,9 +69,7 @@ class PHPSerialize extends Operation { return `${basicTypes.float}:${content.toString()}`; } } - /** - * Strings - */ + /* Strings */ if (typeof content === "string") return `${basicTypes.string}:${content.length}:"${content}"`; @@ -87,22 +83,16 @@ class PHPSerialize extends Operation { * @returns {string} */ function serialize(object) { - /** - * Null - */ + /* Null */ if (object == null) { return `N;`; } if (typeof object !== "object") { - /** - * Basic types - */ + /* Basic types */ return `${serializeBasicTypes(object)};`; } else if (object instanceof Array) { - /** - * Arrays - */ + /* Arrays */ const serializedElements = []; for (let i = 0; i < object.length; i++) { From d2da11c79a59412b3ae480a5c2e05ff4421bd113 Mon Sep 17 00:00:00 2001 From: zhzy0077 Date: Tue, 25 Jul 2023 14:42:43 +0800 Subject: [PATCH 014/165] Support jq. --- package-lock.json | 11 +++++++ package.json | 1 + src/core/config/Categories.json | 1 + src/core/operations/Jq.mjs | 57 +++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 src/core/operations/Jq.mjs diff --git a/package-lock.json b/package-lock.json index 3cccfa6ca..a53ba37ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ "geodesy": "1.1.3", "highlight.js": "^11.7.0", "jimp": "^0.16.13", + "jq-web": "^0.5.1", "jquery": "3.6.4", "js-crc": "^0.2.0", "js-sha3": "^0.8.0", @@ -8662,6 +8663,11 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, + "node_modules/jq-web": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jq-web/-/jq-web-0.5.1.tgz", + "integrity": "sha512-3Fa3E6g3U1O1j46ljy0EM10yRr4txzILga8J7bqOG8F89gZ6Lilz82WG9z6TItWpYEO0YGa4W8yFGj+NMM1xqQ==" + }, "node_modules/jquery": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.4.tgz", @@ -19681,6 +19687,11 @@ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" }, + "jq-web": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jq-web/-/jq-web-0.5.1.tgz", + "integrity": "sha512-3Fa3E6g3U1O1j46ljy0EM10yRr4txzILga8J7bqOG8F89gZ6Lilz82WG9z6TItWpYEO0YGa4W8yFGj+NMM1xqQ==" + }, "jquery": { "version": "3.6.4", "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.4.tgz", diff --git a/package.json b/package.json index 45328dd19..7bb14e9b4 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "geodesy": "1.1.3", "highlight.js": "^11.7.0", "jimp": "^0.16.13", + "jq-web": "^0.5.1", "jquery": "3.6.4", "js-crc": "^0.2.0", "js-sha3": "^0.8.0", diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index cf4d91be0..3cf600fdf 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -422,6 +422,7 @@ "CSS Minify", "XPath expression", "JPath expression", + "Jq", "CSS selector", "PHP Deserialize", "Microsoft Script Decoder", diff --git a/src/core/operations/Jq.mjs b/src/core/operations/Jq.mjs new file mode 100644 index 000000000..38aa5abb0 --- /dev/null +++ b/src/core/operations/Jq.mjs @@ -0,0 +1,57 @@ +/** + * @author zhzy0077 [zhzy0077@hotmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import jq from "jq-web"; + +/** + * jq operation + */ +class Jq extends Operation { + + /** + * Jq constructor + */ + constructor() { + super(); + + this.name = "jq"; + this.module = "Code"; + this.description = "jq is a lightweight and flexible command-line JSON processor."; + this.infoURL = "https://github.com/jqlang/jq"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = [ + { + name: "Query", + type: "string", + value: "" + } + ]; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [query] = args; + let result; + + try { + result = jq.json(input, query); + } catch (err) { + throw new OperationError(`Invalid jq expression: ${err.message}`); + } + + return JSON.stringify(result); + } + +} + +export default Jq; From 721061d0548a4b9cc9e1d48aa9043ce5c38e8ef2 Mon Sep 17 00:00:00 2001 From: zhzy0077 Date: Tue, 25 Jul 2023 14:48:03 +0800 Subject: [PATCH 015/165] fix typo. --- src/core/config/Categories.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 3cf600fdf..9283fe65d 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -422,7 +422,7 @@ "CSS Minify", "XPath expression", "JPath expression", - "Jq", + "jq", "CSS selector", "PHP Deserialize", "Microsoft Script Decoder", From 7353315baaedb2113cda178d03a88cafc7f02a4e Mon Sep 17 00:00:00 2001 From: ccarpo Date: Tue, 21 Nov 2023 08:56:20 +0100 Subject: [PATCH 016/165] Renamed JSON to Yaml to Beautify JSON --- src/core/config/Categories.json | 2 +- .../operations/{JSONToYAML.mjs => BeautifyYAML.mjs} | 12 ++++++------ src/core/operations/YAMLToJSON.mjs | 2 +- tests/operations/index.mjs | 2 +- .../operations/tests/{YAML.mjs => BeautifyYAML.mjs} | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/core/operations/{JSONToYAML.mjs => BeautifyYAML.mjs} (76%) rename tests/operations/tests/{YAML.mjs => BeautifyYAML.mjs} (89%) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index e35bc8519..ce1a639be 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -65,7 +65,7 @@ "CBOR Encode", "CBOR Decode", "YAML to JSON", - "JSON to YAML" + "Beatufiy YAML" ] }, { diff --git a/src/core/operations/JSONToYAML.mjs b/src/core/operations/BeautifyYAML.mjs similarity index 76% rename from src/core/operations/JSONToYAML.mjs rename to src/core/operations/BeautifyYAML.mjs index 2c8102e06..b87573d8f 100644 --- a/src/core/operations/JSONToYAML.mjs +++ b/src/core/operations/BeautifyYAML.mjs @@ -9,19 +9,19 @@ import OperationError from "../errors/OperationError.mjs"; import YAML from "yaml"; /** - * JSON to YAML operation + * Beautify YAML operation */ -class JSONToYAML extends Operation { +class BeautifyYAML extends Operation { /** - * JSONToYAML constructor + * BeautifyYAML constructor */ constructor() { super(); - this.name = "JSON to YAML"; + this.name = "Beautify YAML"; this.module = "Default"; - this.description = "Converts a JSON into a YAML"; + this.description = "Format a JSON object into YAML"; this.infoURL = "https://en.wikipedia.org/wiki/YAML"; this.inputType = "JSON"; this.outputType = "string"; @@ -43,4 +43,4 @@ class JSONToYAML extends Operation { } -export default JSONToYAML; +export default BeautifyYAML; diff --git a/src/core/operations/YAMLToJSON.mjs b/src/core/operations/YAMLToJSON.mjs index 4f77f4fde..5b9865752 100644 --- a/src/core/operations/YAMLToJSON.mjs +++ b/src/core/operations/YAMLToJSON.mjs @@ -20,7 +20,7 @@ class YAMLToJSON extends Operation { this.name = "YAML to JSON"; this.module = "Default"; - this.description = "Converts a YAML to JSON"; + this.description = "Convert YAML to JSON"; this.infoURL = "https://en.wikipedia.org/wiki/YAML"; this.inputType = "string"; this.outputType = "JSON"; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 3f7a7457f..475d6d310 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -107,7 +107,7 @@ import "./tests/CBORDecode.mjs"; import "./tests/JA3Fingerprint.mjs"; import "./tests/JA3SFingerprint.mjs"; import "./tests/HASSH.mjs"; -import "./tests/YAML.mjs"; +import "./tests/BeautifyYAML.mjs"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/YAML.mjs b/tests/operations/tests/BeautifyYAML.mjs similarity index 89% rename from tests/operations/tests/YAML.mjs rename to tests/operations/tests/BeautifyYAML.mjs index ba72ed436..f2cc58fbe 100644 --- a/tests/operations/tests/YAML.mjs +++ b/tests/operations/tests/BeautifyYAML.mjs @@ -4,7 +4,7 @@ * * @author ccarpo [ccarpo@gmx.net] * - * @copyright Crown Copyright 2018 + * @copyright Crown Copyright 2021 * @license Apache-2.0 */ import TestRegister from "../../lib/TestRegister.mjs"; @@ -29,12 +29,12 @@ TestRegister.addTests([ ], }, { - name: "JSON to YAML", + name: "Beautify YAML", input: EXAMPLE_JSON, expectedOutput: `number: 3\nplain: string\n`, recipeConfig: [ { - op: "JSON to YAML", + op: "Beautify YAML", args: [], } ], From 4255d8d543226969381adc1c6a06f421e76ac6d8 Mon Sep 17 00:00:00 2001 From: ccarpo Date: Tue, 21 Nov 2023 09:19:58 +0100 Subject: [PATCH 017/165] Renamed JSON to Yaml to Beautify JSON --- src/core/config/Categories.json | 2 +- .../operations/{JSONToYAML.mjs => BeautifyYAML.mjs} | 12 ++++++------ src/core/operations/YAMLToJSON.mjs | 2 +- tests/operations/index.mjs | 2 +- .../operations/tests/{YAML.mjs => BeautifyYAML.mjs} | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) rename src/core/operations/{JSONToYAML.mjs => BeautifyYAML.mjs} (76%) rename tests/operations/tests/{YAML.mjs => BeautifyYAML.mjs} (89%) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index e35bc8519..6e5e7f040 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -65,7 +65,7 @@ "CBOR Encode", "CBOR Decode", "YAML to JSON", - "JSON to YAML" + "Beautify YAML" ] }, { diff --git a/src/core/operations/JSONToYAML.mjs b/src/core/operations/BeautifyYAML.mjs similarity index 76% rename from src/core/operations/JSONToYAML.mjs rename to src/core/operations/BeautifyYAML.mjs index 2c8102e06..b87573d8f 100644 --- a/src/core/operations/JSONToYAML.mjs +++ b/src/core/operations/BeautifyYAML.mjs @@ -9,19 +9,19 @@ import OperationError from "../errors/OperationError.mjs"; import YAML from "yaml"; /** - * JSON to YAML operation + * Beautify YAML operation */ -class JSONToYAML extends Operation { +class BeautifyYAML extends Operation { /** - * JSONToYAML constructor + * BeautifyYAML constructor */ constructor() { super(); - this.name = "JSON to YAML"; + this.name = "Beautify YAML"; this.module = "Default"; - this.description = "Converts a JSON into a YAML"; + this.description = "Format a JSON object into YAML"; this.infoURL = "https://en.wikipedia.org/wiki/YAML"; this.inputType = "JSON"; this.outputType = "string"; @@ -43,4 +43,4 @@ class JSONToYAML extends Operation { } -export default JSONToYAML; +export default BeautifyYAML; diff --git a/src/core/operations/YAMLToJSON.mjs b/src/core/operations/YAMLToJSON.mjs index 4f77f4fde..5b9865752 100644 --- a/src/core/operations/YAMLToJSON.mjs +++ b/src/core/operations/YAMLToJSON.mjs @@ -20,7 +20,7 @@ class YAMLToJSON extends Operation { this.name = "YAML to JSON"; this.module = "Default"; - this.description = "Converts a YAML to JSON"; + this.description = "Convert YAML to JSON"; this.infoURL = "https://en.wikipedia.org/wiki/YAML"; this.inputType = "string"; this.outputType = "JSON"; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 3f7a7457f..475d6d310 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -107,7 +107,7 @@ import "./tests/CBORDecode.mjs"; import "./tests/JA3Fingerprint.mjs"; import "./tests/JA3SFingerprint.mjs"; import "./tests/HASSH.mjs"; -import "./tests/YAML.mjs"; +import "./tests/BeautifyYAML.mjs"; // Cannot test operations that use the File type yet diff --git a/tests/operations/tests/YAML.mjs b/tests/operations/tests/BeautifyYAML.mjs similarity index 89% rename from tests/operations/tests/YAML.mjs rename to tests/operations/tests/BeautifyYAML.mjs index ba72ed436..f2cc58fbe 100644 --- a/tests/operations/tests/YAML.mjs +++ b/tests/operations/tests/BeautifyYAML.mjs @@ -4,7 +4,7 @@ * * @author ccarpo [ccarpo@gmx.net] * - * @copyright Crown Copyright 2018 + * @copyright Crown Copyright 2021 * @license Apache-2.0 */ import TestRegister from "../../lib/TestRegister.mjs"; @@ -29,12 +29,12 @@ TestRegister.addTests([ ], }, { - name: "JSON to YAML", + name: "Beautify YAML", input: EXAMPLE_JSON, expectedOutput: `number: 3\nplain: string\n`, recipeConfig: [ { - op: "JSON to YAML", + op: "Beautify YAML", args: [], } ], From cc21fe18ca450e05a8e71c1d1c0b58c460127d94 Mon Sep 17 00:00:00 2001 From: ccarpo Date: Tue, 21 Nov 2023 09:24:54 +0100 Subject: [PATCH 018/165] fixed typo. --- src/core/config/Categories.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index ce1a639be..6e5e7f040 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -65,7 +65,7 @@ "CBOR Encode", "CBOR Decode", "YAML to JSON", - "Beatufiy YAML" + "Beautify YAML" ] }, { From 3ca4c2fd453f9698b93f762b98b2117c141297b9 Mon Sep 17 00:00:00 2001 From: jb30795 Date: Thu, 4 Apr 2024 15:54:43 +0100 Subject: [PATCH 019/165] Initial commit for new IPv6 Transition operation --- src/core/config/Categories.json | 1 + .../operations/IPv6TransitionAddresses.mjs | 147 ++++++++++++++++++ tests/operations/tests/IPv6Transition.mjs | 43 +++++ 3 files changed, 191 insertions(+) create mode 100644 src/core/operations/IPv6TransitionAddresses.mjs create mode 100644 tests/operations/tests/IPv6Transition.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index e483c747f..0c7442d1a 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -224,6 +224,7 @@ "Parse User Agent", "Parse IP range", "Parse IPv6 address", + "IPv6 Transition Addresses", "Parse IPv4 header", "Parse TCP", "Parse UDP", diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs new file mode 100644 index 000000000..becafa71e --- /dev/null +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -0,0 +1,147 @@ +/** + * @author jb30795 [jb30795@proton.me] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * IPv6 Transition Addresses operation + */ +class IPv6TransitionAddresses extends Operation { + + /** + * IPv6TransitionAddresses constructor + */ + constructor() { + super(); + + this.name = "IPv6 Transition Addresses"; + this.module = "Default"; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist."; + this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; + + /** + * Function to convert to hex + */ + function hexify(octet) { + return Number(octet).toString(16).padStart(2, "0"); + } + + /** + * Function to convert Hex to Int + */ + function intify(hex) { + return parseInt(hex, 16); + } + + /** + * Function converts IPv4 to IPv6 Transtion address + */ + function ipTransition(input) { + let output = ""; + const HEXIP = input.split("."); + + /** + * 6to4 + */ + output += "6to4: " + "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + + /** + * Mapped + */ + output += "IPv4 Mapped: " + "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + /** + * Translated + */ + output += "IPv4 Translated: " + "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + /** + * Nat64 + */ + output += "Nat 64: " + "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + + + return output; + } + + /** + * Convert MAC to EUI-64 + */ + function macTransition(input) { + let output = ""; + const MACPARTS = input.split(":"); + output += "EUI-64 Interface ID: "; + const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2).toUpperCase()].toLowerCase() + MAC.slice(2); + + return output; + } + + + /** + * Convert IPv6 address to its original IPv4 or MAC address + */ + function unTransition(input) { + let output = ""; + let hextets = ""; + + /** + * 6to4 + */ + if (input.startsWith("2002:")) { + output += "IPv4: " + String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))); + } else if (input.startsWith("::ffff:") || input.startsWith("0000:0000:0000:0000:0000:ffff:") || input.startsWith("::ffff:0000:") || input.startsWith("0000:0000:0000:0000:ffff:0000:") || input.startsWith("64:ff9b::") || input.startsWith("0064:ff9b:0000:0000:0000:0000:")) { + /** + * Mapped/Translated/Nat64 + */ + hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); + output += "IPv4: " + intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)); + } else if (input.slice(-12, -7).toUpperCase() === "FF:FE") { + /** + * EUI-64 + */ + output += "Mac Address: "; + const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); + } + + return output; + } + + + /** + * Main + */ + let output = ""; + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(input)) { + output = ipTransition(input); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(input.toUpperCase())) { + output = macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(input)) { + output = unTransition(input); + } else { + output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } + + + return output; + } + +} + +export default IPv6TransitionAddresses; diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs new file mode 100644 index 000000000..4e5c0e639 --- /dev/null +++ b/tests/operations/tests/IPv6Transition.mjs @@ -0,0 +1,43 @@ +/** + * IPv6Transition tests. + * + * @author jb30795 + * + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "IPv6 Transition: IPv4 to IPv6", + input: "198.51.100.7", + expectedOutput: "6to4: 2002:c633:6407::/48\nIPv4 Mapped: ::ffff:c633:6407\nIPv4 Translated: ::ffff:0:c633:6407\nNat 64: 64:ff9b::c633:6407", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, { + name: "IPv6 Transition: IPv6 to IPv4", + input: "64:ff9b::c633:6407", + expectedOutput: "IPv4: 198.51.100.7", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, { + name: "IPv6 Transition: MAC to EUI-64", + input: "a1:b2:c3:d4:e5:f6", + expectedOutput: "EUI-64 Interface ID: a3b2:c3ff:fed4:e5f6", + recipeConfig: [ + { + op: "IPv6 Transition Addresses", + args: [], + }, + ], + }, +]); From 036f80d7349f024c7aaffcda235afe39e2be9de2 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Thu, 4 Apr 2024 17:00:14 +0100 Subject: [PATCH 020/165] indentation --- src/core/config/Categories.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 0c7442d1a..45622ded0 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -224,7 +224,7 @@ "Parse User Agent", "Parse IP range", "Parse IPv6 address", - "IPv6 Transition Addresses", + "IPv6 Transition Addresses", "Parse IPv4 header", "Parse TCP", "Parse UDP", From edd22372d80663bf91f70b42ea95421b45328104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lteri=C5=9F=20Ya=C4=9F=C4=B1ztegin=20Ero=C4=9Flu?= Date: Mon, 17 Jun 2024 23:55:59 +0000 Subject: [PATCH 021/165] feat(Modhex): Introduce basic Modhex conversion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: İlteriş Yağıztegin Eroğlu --- src/core/config/Categories.json | 4 +- src/core/lib/Modhex.mjs | 165 +++++++++++++++++++++++++++++ src/core/operations/FromModhex.mjs | 84 +++++++++++++++ src/core/operations/ToModhex.mjs | 55 ++++++++++ tests/operations/index.mjs | 1 + tests/operations/tests/Modhex.mjs | 150 ++++++++++++++++++++++++++ 6 files changed, 458 insertions(+), 1 deletion(-) create mode 100644 src/core/lib/Modhex.mjs create mode 100644 src/core/operations/FromModhex.mjs create mode 100644 src/core/operations/ToModhex.mjs create mode 100644 tests/operations/tests/Modhex.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index bebdd6a5e..34d3bfc8f 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -74,7 +74,9 @@ "CBOR Decode", "Caret/M-decode", "Rison Encode", - "Rison Decode" + "Rison Decode", + "To Modhex", + "From Modhex" ] }, { diff --git a/src/core/lib/Modhex.mjs b/src/core/lib/Modhex.mjs new file mode 100644 index 000000000..4f28e9a11 --- /dev/null +++ b/src/core/lib/Modhex.mjs @@ -0,0 +1,165 @@ +/** + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { fromHex, toHex } from "./Hex.mjs"; + +/** + * Modhex alphabet. + */ +const MODHEX_ALPHABET = "cbdefghijklnrtuv"; + + +/** + * Modhex alphabet map. + */ +const MODHEX_ALPHABET_MAP = MODHEX_ALPHABET.split(""); + + +/** + * Hex alphabet to substitute Modhex. + */ +const HEX_ALPHABET = "0123456789abcdef"; + + +/** + * Hex alphabet map to substitute Modhex. + */ +const HEX_ALPHABET_MAP = HEX_ALPHABET.split(""); + + +/** + * Convert a byte array into a modhex string. + * + * @param {byteArray|Uint8Array|ArrayBuffer} data + * @param {string} [delim=" "] + * @param {number} [padding=2] + * @returns {string} + * + * @example + * // returns "cl bf bu" + * toModhex([10,20,30]); + * + * // returns "cl:bf:bu" + * toModhex([10,20,30], ":"); + */ +export function toModhex(data, delim=" ", padding=2, extraDelim="", lineSize=0) { + if (!data) return ""; + if (data instanceof ArrayBuffer) data = new Uint8Array(data); + + const regularHexString = toHex(data, "", padding, "", 0); + + let modhexString = ""; + for (const letter of regularHexString.split("")) { + modhexString += MODHEX_ALPHABET_MAP[HEX_ALPHABET_MAP.indexOf(letter)]; + } + + let output = ""; + const groupingRegexp = new RegExp(`.{1,${padding}}`, "g"); + const groupedModhex = modhexString.match(groupingRegexp); + + for (let i = 0; i < groupedModhex.length; i++) { + const group = groupedModhex[i]; + output += group + delim; + + if (extraDelim) { + output += extraDelim; + } + // Add LF after each lineSize amount of bytes but not at the end + if ((i !== groupedModhex.length - 1) && ((i + 1) % lineSize === 0)) { + output += "\n"; + } + } + + // Remove the extraDelim at the end (if there is one) + // and remove the delim at the end, but if it's prepended there's nothing to remove + const rTruncLen = extraDelim.length + delim.length; + if (rTruncLen) { + // If rTruncLen === 0 then output.slice(0,0) will be returned, which is nothing + return output.slice(0, -rTruncLen); + } else { + return output; + } +} + + +/** + * Convert a byte array into a modhex string as efficiently as possible with no options. + * + * @param {byteArray|Uint8Array|ArrayBuffer} data + * @returns {string} + * + * @example + * // returns "clbfbu" + * toModhexFast([10,20,30]); + */ +export function toModhexFast(data) { + if (!data) return ""; + if (data instanceof ArrayBuffer) data = new Uint8Array(data); + + const output = []; + + for (let i = 0; i < data.length; i++) { + output.push(MODHEX_ALPHABET_MAP[(data[i] >> 4) & 0xf]); + output.push(MODHEX_ALPHABET_MAP[data[i] & 0xf]); + } + return output.join(""); +} + + +/** + * Convert a modhex string into a byte array. + * + * @param {string} data + * @param {string} [delim] + * @param {number} [byteLen=2] + * @returns {byteArray} + * + * @example + * // returns [10,20,30] + * fromModhex("cl bf bu"); + * + * // returns [10,20,30] + * fromModhex("cl:bf:bu", "Colon"); + */ +export function fromModhex(data, delim="Auto", byteLen=2) { + if (byteLen < 1 || Math.round(byteLen) !== byteLen) + throw new OperationError("Byte length must be a positive integer"); + + // The `.replace(/\s/g, "")` an interesting workaround: Hex "multiline" tests aren't actually + // multiline. Tests for Modhex fixes that, thus exposing the issue. + data = data.toLowerCase().replace(/\s/g, ""); + + if (delim !== "None") { + const delimRegex = delim === "Auto" ? /[^cbdefghijklnrtuv]/gi : Utils.regexRep(delim); + data = data.split(delimRegex); + } else { + data = [data]; + } + + let regularHexString = ""; + for (let i = 0; i < data.length; i++) { + for (const letter of data[i].split("")) { + regularHexString += HEX_ALPHABET_MAP[MODHEX_ALPHABET_MAP.indexOf(letter)]; + } + } + + const output = fromHex(regularHexString, "None", byteLen); + return output; +} + + +/** + * To Modhex delimiters. + */ +export const TO_MODHEX_DELIM_OPTIONS = ["Space", "Percent", "Comma", "Semi-colon", "Colon", "Line feed", "CRLF", "None"]; + + +/** + * From Modhex delimiters. + */ +export const FROM_MODHEX_DELIM_OPTIONS = ["Auto"].concat(TO_MODHEX_DELIM_OPTIONS); diff --git a/src/core/operations/FromModhex.mjs b/src/core/operations/FromModhex.mjs new file mode 100644 index 000000000..029d95d8e --- /dev/null +++ b/src/core/operations/FromModhex.mjs @@ -0,0 +1,84 @@ +/** + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import { FROM_MODHEX_DELIM_OPTIONS, fromModhex } from "../lib/Modhex.mjs"; + +/** + * From Modhex operation + */ +class FromModhex extends Operation { + + /** + * FromModhex constructor + */ + constructor() { + super(); + + this.name = "From Modhex"; + this.module = "Default"; + this.description = "Converts a modhex byte string back into its raw value."; + this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Delimiter", + type: "option", + value: FROM_MODHEX_DELIM_OPTIONS + } + ]; + this.checks = [ + { + pattern: "^(?:[cbdefghijklnrtuv]{2})+$", + flags: "i", + args: ["None"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?: [cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["Space"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:,[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["Comma"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:;[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["Semi-colon"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?::[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["Colon"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:\\n[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["Line feed"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:\\r\\n[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["CRLF"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = args[0] || "Auto"; + return fromModhex(input, delim, 2); + } +} + +export default FromModhex; diff --git a/src/core/operations/ToModhex.mjs b/src/core/operations/ToModhex.mjs new file mode 100644 index 000000000..6d91fb5dd --- /dev/null +++ b/src/core/operations/ToModhex.mjs @@ -0,0 +1,55 @@ +/** + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import { TO_MODHEX_DELIM_OPTIONS, toModhex } from "../lib/Modhex.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To Modhex operation + */ +class ToModhex extends Operation { + + /** + * ToModhex constructor + */ + constructor() { + super(); + + this.name = "To Modhex"; + this.module = "Default"; + this.description = "Converts the input string to modhex bytes separated by the specified delimiter."; + this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "Delimiter", + type: "option", + value: TO_MODHEX_DELIM_OPTIONS + }, + { + name: "Bytes per line", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]); + const lineSize = args[1]; + + return toModhex(new Uint8Array(input), delim, 2, "", lineSize); + } +} + +export default ToModhex; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 40ce7a2ee..11e65e666 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -102,6 +102,7 @@ import "./tests/LZNT1Decompress.mjs"; import "./tests/LZString.mjs"; import "./tests/Magic.mjs"; import "./tests/Media.mjs"; +import "./tests/Modhex.mjs"; import "./tests/MorseCode.mjs"; import "./tests/MS.mjs"; import "./tests/MultipleBombe.mjs"; diff --git a/tests/operations/tests/Modhex.mjs b/tests/operations/tests/Modhex.mjs new file mode 100644 index 000000000..1e0f27912 --- /dev/null +++ b/tests/operations/tests/Modhex.mjs @@ -0,0 +1,150 @@ +/** + * Modhex operation tests. + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "ASCII to Modhex stream", + input: "aberystwyth", + expectedOutput: "hbhdhgidikieifiiikifhj", + recipeConfig: [ + { + "op": "To Modhex", + "args": [ + "None", + 0 + ] + }, + ] + }, + { + name: "ASCII to Modhex with colon deliminator", + input: "aberystwyth", + expectedOutput: "hb:hd:hg:id:ik:ie:if:ii:ik:if:hj", + recipeConfig: [ + { + "op": "To Modhex", + "args": [ + "Colon", + 0 + ] + } + ] + }, + { + name: "Modhex stream to UTF-8", + input: "uhkgkbuhkgkbugltlkugltkc", + expectedOutput: "救救孩子", + recipeConfig: [ + { + "op": "From Modhex", + "args": [ + "Auto" + ] + } + ] + + }, + { + name: "Mixed case Modhex stream to UTF-8", + input: "uhKGkbUHkgkBUGltlkugltkc", + expectedOutput: "救救孩子", + recipeConfig: [ + { + "op": "From Modhex", + "args": [ + "Auto" + ] + } + ] + + }, + { + name: "Mutiline Modhex with comma to ASCII (Auto Mode)", + input: "fk,dc,ie,hb,ii,dc,ht,ik,ie,hg,hr,hh,dc,ie,hk,\n\ +if,if,hk,hu,hi,dc,hk,hu,dc,if,hj,hg,dc,he,id,\n\ +hv,if,he,hj,dc,hv,hh,dc,if,hj,hg,dc,if,hj,hk,\n\ +ie,dc,hh,hk,hi,dc,if,id,hg,hg,dr,dc,ie,if,hb,\n\ +id,ih,hk,hu,hi,dc,if,hv,dc,hf,hg,hb,if,hj,dr,\n\ +dc,hl,ig,ie,if,dc,hd,hg,he,hb,ig,ie,hg,dc,fk,\n\ +dc,he,hv,ig,hr,hf,hu,di,if,dc,ht,hb,hn,hg,dc,\n\ +ig,ic,dc,ht,ik,dc,ht,hk,hu,hf,dc,ii,hj,hk,he,\n\ +hj,dc,hv,hh,dc,if,hj,hg,dc,hh,hk,hi,ie,dc,fk,\n\ +dc,ii,hv,ig,hr,hf,dc,he,hj,hv,hv,ie,hg,du", + expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.", + recipeConfig: [ + { + "op": "From Modhex", + "args": [ + "Auto" + ] + } + ] + + }, + { + name: "Mutiline Modhex with percent to ASCII (Percent Mode)", + input: "fk%dc%ie%hb%ii%dc%ht%ik%ie%hg%hr%hh%dc%ie%hk%\n\ +if%if%hk%hu%hi%dc%hk%hu%dc%if%hj%hg%dc%he%id%\n\ +hv%if%he%hj%dc%hv%hh%dc%if%hj%hg%dc%if%hj%hk%\n\ +ie%dc%hh%hk%hi%dc%if%id%hg%hg%dr%dc%ie%if%hb%\n\ +id%ih%hk%hu%hi%dc%if%hv%dc%hf%hg%hb%if%hj%dr%\n\ +dc%hl%ig%ie%if%dc%hd%hg%he%hb%ig%ie%hg%dc%fk%\n\ +dc%he%hv%ig%hr%hf%hu%di%if%dc%ht%hb%hn%hg%dc%\n\ +ig%ic%dc%ht%ik%dc%ht%hk%hu%hf%dc%ii%hj%hk%he%\n\ +hj%dc%hv%hh%dc%if%hj%hg%dc%hh%hk%hi%ie%dc%fk%\n\ +dc%ii%hv%ig%hr%hf%dc%he%hj%hv%hv%ie%hg%du", + expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.", + recipeConfig: [ + { + "op": "From Modhex", + "args": [ + "Percent" + ] + } + ] + + }, + { + name: "Mutiline Modhex with semicolon to ASCII (Semi-colon Mode)", + input: "fk;dc;ie;hb;ii;dc;ht;ik;ie;hg;hr;hh;dc;ie;hk;\n\ +if;if;hk;hu;hi;dc;hk;hu;dc;if;hj;hg;dc;he;id;\n\ +hv;if;he;hj;dc;hv;hh;dc;if;hj;hg;dc;if;hj;hk;\n\ +ie;dc;hh;hk;hi;dc;if;id;hg;hg;dr;dc;ie;if;hb;\n\ +id;ih;hk;hu;hi;dc;if;hv;dc;hf;hg;hb;if;hj;dr;\n\ +dc;hl;ig;ie;if;dc;hd;hg;he;hb;ig;ie;hg;dc;fk;\n\ +dc;he;hv;ig;hr;hf;hu;di;if;dc;ht;hb;hn;hg;dc;\n\ +ig;ic;dc;ht;ik;dc;ht;hk;hu;hf;dc;ii;hj;hk;he;\n\ +hj;dc;hv;hh;dc;if;hj;hg;dc;hh;hk;hi;ie;dc;fk;\n\ +dc;ii;hv;ig;hr;hf;dc;he;hj;hv;hv;ie;hg;du", + expectedOutput: "I saw myself sitting in the crotch of the this fig tree, starving to death, just because I couldn't make up my mind which of the figs I would choose.", + recipeConfig: [ + { + "op": "From Modhex", + "args": [ + "Semi-colon" + ] + } + ] + + }, + { + name: "ASCII to Modhex with comma and line breaks", + input: "aberystwyth", + expectedOutput: "hb,hd,hg,id,\nik,ie,if,ii,\nik,if,hj", + recipeConfig: [ + { + "op": "To Modhex", + "args": [ + "Comma", + 4 + ] + } + ] + }, +]); From fb3c36af85a528ee2728a051b931c3bcba6d1ecb Mon Sep 17 00:00:00 2001 From: JSCU-CNI <121175071+JSCU-CNI@users.noreply.github.com> Date: Wed, 24 Jul 2024 14:23:40 +0200 Subject: [PATCH 022/165] Add fingerprints to 'Parse X.509 certificate' operation --- src/core/operations/ParseX509Certificate.mjs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/operations/ParseX509Certificate.mjs b/src/core/operations/ParseX509Certificate.mjs index 11e63424d..cdd1e9c7c 100644 --- a/src/core/operations/ParseX509Certificate.mjs +++ b/src/core/operations/ParseX509Certificate.mjs @@ -6,7 +6,8 @@ import r from "jsrsasign"; import { fromBase64 } from "../lib/Base64.mjs"; -import { toHex } from "../lib/Hex.mjs"; +import { runHash } from "../lib/Hash.mjs"; +import { fromHex, toHex } from "../lib/Hex.mjs"; import { formatByteStr, formatDnObj } from "../lib/PublicKey.mjs"; import Operation from "../Operation.mjs"; import Utils from "../Utils.mjs"; @@ -81,7 +82,8 @@ class ParseX509Certificate extends Operation { } if (undefinedInputFormat) throw "Undefined input format"; - const sn = cert.getSerialNumberHex(), + const hex = Utils.strToArrayBuffer(Utils.byteArrayToChars(fromHex(cert.hex))), + sn = cert.getSerialNumberHex(), issuer = cert.getIssuer(), subject = cert.getSubject(), pk = cert.getPublicKey(), @@ -191,6 +193,10 @@ Issuer ${issuerStr} Subject ${subjectStr} +Fingerprints + MD5: ${runHash("md5", hex)} + SHA1: ${runHash("sha1", hex)} + SHA256: ${runHash("sha256", hex)} Public Key ${pkStr.slice(0, -1)} Certificate Signature From b090ce0428f55ef4db0abf6c354acf1261daf1a9 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 17:06:15 +0100 Subject: [PATCH 023/165] Update to accept multiple inputs --- .../operations/IPv6TransitionAddresses.mjs | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index becafa71e..a574b8cdd 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -23,10 +23,16 @@ class IPv6TransitionAddresses extends Operation { this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; - this.args = []; + this.args = [ + { + "name": "Ignore ranges", + "type": "boolean", + "value": true + } + ]; } - /** + /** * @param {string} input * @param {Object[]} args * @returns {string} @@ -128,17 +134,19 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(input)) { - output = ipTransition(input); - } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(input.toUpperCase())) { - output = macTransition(input.toLowerCase()); - } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(input)) { - output = unTransition(input); - } else { - output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + const inputs = input.split("\n"); + for (let input = 0; input < inputs.length; input++){ + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { + output += ipTransition(inputs[input]); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { + output += macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { + output += unTransition(inputs[input]); + } else { + output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } } - return output; } From 5e763b86dc42e26cf3a7baedacf2abc036be8ccf Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 18:17:00 +0100 Subject: [PATCH 024/165] Option to remove headers and ignore blank input rows --- .../operations/IPv6TransitionAddresses.mjs | 52 +++++++++++++++---- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index a574b8cdd..c52907358 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -28,7 +28,12 @@ class IPv6TransitionAddresses extends Operation { "name": "Ignore ranges", "type": "boolean", "value": true - } + }, + { + "name": "Remove headers", + "type": "boolean", + "value": false + } ]; } @@ -39,6 +44,7 @@ class IPv6TransitionAddresses extends Operation { */ run(input, args) { const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; + const [ignoreRanges, removeHeaders] = args; /** * Function to convert to hex @@ -64,22 +70,34 @@ class IPv6TransitionAddresses extends Operation { /** * 6to4 */ - output += "6to4: " + "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + if (!args[1]){ + output += "6to4: "; + } + output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; /** * Mapped */ - output += "IPv4 Mapped: " + "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "IPv4 Mapped: "; + } + output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; /** * Translated */ - output += "IPv4 Translated: " + "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "IPv4 Translated: "; + } + output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; /** * Nat64 */ - output += "Nat 64: " + "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + if (!args[1]){ + output += "Nat 64: "; + } + output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; return output; @@ -91,7 +109,9 @@ class IPv6TransitionAddresses extends Operation { function macTransition(input) { let output = ""; const MACPARTS = input.split(":"); - output += "EUI-64 Interface ID: "; + if (!args[1]){ + output += "EUI-64 Interface ID: "; + } const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2).toUpperCase()].toLowerCase() + MAC.slice(2); @@ -110,20 +130,28 @@ class IPv6TransitionAddresses extends Operation { * 6to4 */ if (input.startsWith("2002:")) { - output += "IPv4: " + String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))); + if (!args[1]){ + output += "IPv4: "; + } + output += String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))) + "\n"; } else if (input.startsWith("::ffff:") || input.startsWith("0000:0000:0000:0000:0000:ffff:") || input.startsWith("::ffff:0000:") || input.startsWith("0000:0000:0000:0000:ffff:0000:") || input.startsWith("64:ff9b::") || input.startsWith("0064:ff9b:0000:0000:0000:0000:")) { /** * Mapped/Translated/Nat64 */ hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); - output += "IPv4: " + intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)); + if (!args[1]){ + output += "IPv4: "; + } + output += intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)) + "\n"; } else if (input.slice(-12, -7).toUpperCase() === "FF:FE") { /** * EUI-64 */ - output += "Mac Address: "; + if (!args[1]){ + output += "Mac Address: "; + } const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); - output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2) + "\n"; } return output; @@ -134,7 +162,9 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - const inputs = input.split("\n"); + let inputs = input.split("\n"); + //Remove blank rows + inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++){ if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input]); From 51a07a27dba4fe724015124fa4d86a3ee75020a2 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 18:49:58 +0100 Subject: [PATCH 025/165] Formatting updates --- .../operations/IPv6TransitionAddresses.mjs | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index c52907358..d6eb903d7 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -31,20 +31,19 @@ class IPv6TransitionAddresses extends Operation { }, { "name": "Remove headers", - "type": "boolean", - "value": false + "type": "boolean", + "value": false } - ]; + ]; } - /** + /** * @param {string} input * @param {Object[]} args * @returns {string} */ run(input, args) { const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "A", "9": "B", "A": "8", "B": "9", "C": "E", "D": "F", "E": "C", "F": "D"}; - const [ignoreRanges, removeHeaders] = args; /** * Function to convert to hex @@ -70,7 +69,7 @@ class IPv6TransitionAddresses extends Operation { /** * 6to4 */ - if (!args[1]){ + if (!args[1]) { output += "6to4: "; } output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; @@ -78,7 +77,7 @@ class IPv6TransitionAddresses extends Operation { /** * Mapped */ - if (!args[1]){ + if (!args[1]) { output += "IPv4 Mapped: "; } output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -86,7 +85,7 @@ class IPv6TransitionAddresses extends Operation { /** * Translated */ - if (!args[1]){ + if (!args[1]) { output += "IPv4 Translated: "; } output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -94,7 +93,7 @@ class IPv6TransitionAddresses extends Operation { /** * Nat64 */ - if (!args[1]){ + if (!args[1]) { output += "Nat 64: "; } output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; @@ -109,7 +108,7 @@ class IPv6TransitionAddresses extends Operation { function macTransition(input) { let output = ""; const MACPARTS = input.split(":"); - if (!args[1]){ + if (!args[1]) { output += "EUI-64 Interface ID: "; } const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; @@ -130,7 +129,7 @@ class IPv6TransitionAddresses extends Operation { * 6to4 */ if (input.startsWith("2002:")) { - if (!args[1]){ + if (!args[1]) { output += "IPv4: "; } output += String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))) + "\n"; @@ -139,7 +138,7 @@ class IPv6TransitionAddresses extends Operation { * Mapped/Translated/Nat64 */ hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); - if (!args[1]){ + if (!args[1]) { output += "IPv4: "; } output += intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)) + "\n"; @@ -147,7 +146,7 @@ class IPv6TransitionAddresses extends Operation { /** * EUI-64 */ - if (!args[1]){ + if (!args[1]) { output += "Mac Address: "; } const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); @@ -162,10 +161,10 @@ class IPv6TransitionAddresses extends Operation { * Main */ let output = ""; - let inputs = input.split("\n"); - //Remove blank rows + let inputs = input.split("\n"); + // Remove blank rows inputs = inputs.filter(Boolean); - for (let input = 0; input < inputs.length; input++){ + for (let input = 0; input < inputs.length; input++) { if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input]); } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { From 9169254fff375b7393210e9ce5eb104a38dcbd0e Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 19:13:44 +0100 Subject: [PATCH 026/165] minor wording update --- src/core/operations/IPv6TransitionAddresses.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index d6eb903d7..bb06e5a77 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -172,7 +172,7 @@ class IPv6TransitionAddresses extends Operation { } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { output += unTransition(inputs[input]); } else { - output = "Enter a compressed or expanded IPv6 address, IPv4 address or MAC Address."; + output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; } } From 660069865aa0798fd1ddcbefb818433a0a992789 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 21:02:00 +0100 Subject: [PATCH 027/165] Updating description --- src/core/operations/IPv6TransitionAddresses.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index bb06e5a77..cfc810715 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -19,7 +19,7 @@ class IPv6TransitionAddresses extends Operation { this.name = "IPv6 Transition Addresses"; this.module = "Default"; - this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist."; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Remove headers to easily copy out results."; this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; From 752ce789c21ffa07c8e40c40749e590739f11969 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Wed, 7 Aug 2024 21:19:13 +0100 Subject: [PATCH 028/165] Updating tests --- tests/operations/tests/IPv6Transition.mjs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/operations/tests/IPv6Transition.mjs b/tests/operations/tests/IPv6Transition.mjs index 4e5c0e639..c658f0fb7 100644 --- a/tests/operations/tests/IPv6Transition.mjs +++ b/tests/operations/tests/IPv6Transition.mjs @@ -16,7 +16,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, { @@ -26,7 +26,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, { @@ -36,7 +36,7 @@ TestRegister.addTests([ recipeConfig: [ { op: "IPv6 Transition Addresses", - args: [], + args: [true, false], }, ], }, From a616e46b507607716c7e2bd2f934d81a43427da7 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 9 Aug 2024 14:28:50 +0100 Subject: [PATCH 029/165] Handling of /24 ranges --- .../operations/IPv6TransitionAddresses.mjs | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index cfc810715..813224bdb 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -19,7 +19,7 @@ class IPv6TransitionAddresses extends Operation { this.name = "IPv6 Transition Addresses"; this.module = "Default"; - this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Remove headers to easily copy out results."; + this.description = "Converts IPv4 addresses to their IPv6 Transition addresses. IPv6 Transition addresses can also be converted back into their original IPv4 address. MAC addresses can also be converted into the EUI-64 format, this can them be appended to your IPv6 /64 range to obtain a full /128 address.

Transition technologies enable translation between IPv4 and IPv6 addresses or tunneling to allow traffic to pass through the incompatible network, allowing the two standards to coexist.

Only /24 ranges and currently handled. Remove headers to easily copy out results."; this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; this.inputType = "string"; this.outputType = "string"; @@ -62,7 +62,7 @@ class IPv6TransitionAddresses extends Operation { /** * Function converts IPv4 to IPv6 Transtion address */ - function ipTransition(input) { + function ipTransition(input, range) { let output = ""; const HEXIP = input.split("."); @@ -72,7 +72,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "6to4: "; } - output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "::/48\n"; + output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00::/40\n"; + } else { + output += hexify(HEXIP[3]) + "::/48\n"; + } /** * Mapped @@ -80,7 +85,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "IPv4 Mapped: "; } - output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } /** * Translated @@ -88,7 +98,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "IPv4 Translated: "; } - output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; + output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } /** * Nat64 @@ -96,8 +111,12 @@ class IPv6TransitionAddresses extends Operation { if (!args[1]) { output += "Nat 64: "; } - output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]) + hexify(HEXIP[3]) + "\n"; - + output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } return output; } @@ -165,14 +184,19 @@ class IPv6TransitionAddresses extends Operation { // Remove blank rows inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++) { - if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { - output += ipTransition(inputs[input]); - } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { - output += macTransition(input.toLowerCase()); - } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { - output += unTransition(inputs[input]); - } else { - output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; + // if ignore ranges is checked and input is a range, skip + if ((args[0] && !inputs[input].includes("\/")) || (!args[0])) { + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { + output += ipTransition(inputs[input], false); + } else if (/\/24$/.test(inputs[input])) { + output += ipTransition(inputs[input], true); + } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { + output += macTransition(input.toLowerCase()); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[input])) { + output += unTransition(inputs[input]); + } else { + output = "Enter compressed or expanded IPv6 address, IPv4 address or MAC Address."; + } } } From a80b1568acbbf8d722c667b77381e1810429a387 Mon Sep 17 00:00:00 2001 From: jb30795 <> Date: Fri, 9 Aug 2024 14:32:31 +0100 Subject: [PATCH 030/165] Lint errors --- src/core/operations/IPv6TransitionAddresses.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/operations/IPv6TransitionAddresses.mjs b/src/core/operations/IPv6TransitionAddresses.mjs index 813224bdb..7f2f05c59 100644 --- a/src/core/operations/IPv6TransitionAddresses.mjs +++ b/src/core/operations/IPv6TransitionAddresses.mjs @@ -185,10 +185,10 @@ class IPv6TransitionAddresses extends Operation { inputs = inputs.filter(Boolean); for (let input = 0; input < inputs.length; input++) { // if ignore ranges is checked and input is a range, skip - if ((args[0] && !inputs[input].includes("\/")) || (!args[0])) { + if ((args[0] && !inputs[input].includes("/")) || (!args[0])) { if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[input])) { output += ipTransition(inputs[input], false); - } else if (/\/24$/.test(inputs[input])) { + } else if (/\/24$/.test(inputs[input])) { output += ipTransition(inputs[input], true); } else if (/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/.test(inputs[input].toUpperCase())) { output += macTransition(input.toLowerCase()); From 77c2b7923dfa7d4acd2323ea752f4686a5f6d69c Mon Sep 17 00:00:00 2001 From: remingtr Date: Fri, 9 Aug 2024 16:20:38 -0700 Subject: [PATCH 031/165] Add more clear build instructions Added more clear build instructions to the README. --- README.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5549bda2a..7add97261 100755 --- a/README.md +++ b/README.md @@ -20,21 +20,36 @@ Cryptographic operations in CyberChef should not be relied upon to provide secur [A live demo can be found here][1] - have fun! -## Containers +## Running Locally with Docker -If you would like to try out CyberChef locally you can either build it yourself: +**Prerequisites:** +- [Docker](hhttps://www.docker.com/products/docker-desktop/) + - Docker Desktop must be open and running on your machine + + +#### Option 1: Build the Docker Image Yourself + +1. Build the docker image ```bash docker build --tag cyberchef --ulimit nofile=10000 . +``` +2. Run the docker container +```bash docker run -it -p 8080:80 cyberchef ``` +3. Navigate to `http://localhost:8080` in your browser -Or you can use our image directly: +#### Option 2: Use the pre-built Docker Image + +If you prefer to skip the build process, you can use the pre-built image ```bash docker run -it -p 8080:80 ghcr.io/gchq/cyberchef:latest ``` +Just like before, navigate to `http://localhost:8080` in your browser. + This image is built and published through our [GitHub Workflows](.github/workflows/releases.yml) ## How it works From d58e162bfafc6cb5b9dc1bbfb57ab29dd6162e4e Mon Sep 17 00:00:00 2001 From: Niall Date: Fri, 23 Aug 2024 19:37:00 +0000 Subject: [PATCH 032/165] Fixes an issue with ShowOnMap where previous tileUrl would result in 403 errors when pulling images, also bumped to leaflet 1.9.4 as the latest stable version Changed tileUrl provider to openstreetmap directly and updated tileAttribution, as well as infoURL --- src/core/operations/ShowOnMap.mjs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/operations/ShowOnMap.mjs b/src/core/operations/ShowOnMap.mjs index c2ac1c6e3..d75c2aa6a 100644 --- a/src/core/operations/ShowOnMap.mjs +++ b/src/core/operations/ShowOnMap.mjs @@ -1,6 +1,7 @@ /** * @author j433866 [j433866@gmail.com] - * @copyright Crown Copyright 2019 + * @author 0xff1ce [github.com/0xff1ce] + * @copyright Crown Copyright 2024 * @license Apache-2.0 */ @@ -22,7 +23,7 @@ class ShowOnMap extends Operation { this.name = "Show on map"; this.module = "Hashing"; this.description = "Displays co-ordinates on a slippy map.

Co-ordinates will be converted to decimal degrees before being shown on the map.

Supported formats:
  • Degrees Minutes Seconds (DMS)
  • Degrees Decimal Minutes (DDM)
  • Decimal Degrees (DD)
  • Geohash
  • Military Grid Reference System (MGRS)
  • Ordnance Survey National Grid (OSNG)
  • Universal Transverse Mercator (UTM)

This operation will not work offline."; - this.infoURL = "https://foundation.wikimedia.org/wiki/Maps_Terms_of_Use"; + this.infoURL = "https://osmfoundation.org/wiki/Terms_of_Use"; this.inputType = "string"; this.outputType = "string"; this.presentType = "html"; @@ -85,10 +86,10 @@ class ShowOnMap extends Operation { data = "0, 0"; } const zoomLevel = args[0]; - const tileUrl = "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png", - tileAttribution = "Wikimedia maps | © OpenStreetMap contributors", - leafletUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.js", - leafletCssUrl = "https://unpkg.com/leaflet@1.5.0/dist/leaflet.css"; + const tileUrl = "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + tileAttribution = "© OpenStreetMap contributors", + leafletUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js", + leafletCssUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"; return `