diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index bebdd6a5e2..77cc3ca042 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -234,6 +234,7 @@ "Parse IP range", "Parse IPv6 address", "Parse IPv4 header", + "Strip IPv4 header", "Parse TCP", "Parse UDP", "Parse SSH Host Key", diff --git a/src/core/operations/StripIPv4Header.mjs b/src/core/operations/StripIPv4Header.mjs new file mode 100644 index 0000000000..4b6ef1aff2 --- /dev/null +++ b/src/core/operations/StripIPv4Header.mjs @@ -0,0 +1,57 @@ +/** + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Stream from "../lib/Stream.mjs"; + +/** + * Strip IPv4 header operation + */ +class StripIPv4Header extends Operation { + + /** + * StripIPv4Header constructor + */ + constructor() { + super(); + + this.name = "Strip IPv4 header"; + this.module = "Default"; + this.description = "Strips the IPv4 header from an IPv4 packet, outputting the payload."; + this.infoURL = "https://wikipedia.org/wiki/IPv4"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const MIN_HEADER_LEN = 20; + + const s = new Stream(new Uint8Array(input)); + if (s.length < MIN_HEADER_LEN) { + throw new OperationError("Input length is less than minimum IPv4 header length"); + } + + const ihl = s.readInt(1) & 0x0f; + const dataOffsetBytes = ihl * 4; + if (s.length < dataOffsetBytes) { + throw new OperationError("Input length is less than IHL"); + } + + s.moveTo(dataOffsetBytes); + + return s.getBytes().buffer; + } + +} + +export default StripIPv4Header; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 40ce7a2ee6..a1acb0c304 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -142,6 +142,7 @@ import "./tests/SIGABA.mjs"; import "./tests/SM4.mjs"; // import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet import "./tests/StrUtils.mjs"; +import "./tests/StripIPv4Header.mjs"; import "./tests/Subsection.mjs"; import "./tests/SwapCase.mjs"; import "./tests/SymmetricDifference.mjs"; diff --git a/tests/operations/tests/StripIPv4Header.mjs b/tests/operations/tests/StripIPv4Header.mjs new file mode 100644 index 0000000000..739bc70d75 --- /dev/null +++ b/tests/operations/tests/StripIPv4Header.mjs @@ -0,0 +1,126 @@ +/** + * Strip IPv4 header tests. + * + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Strip IPv4 header: No options, No payload", + input: "450000140005400080060000c0a80001c0a80002", + expectedOutput: "", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip IPv4 header: No options, Payload", + input: "450000140005400080060000c0a80001c0a80002ffffffffffffffff", + expectedOutput: "ffffffffffffffff", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip IPv4 header: Options, No payload", + input: "460000140005400080060000c0a80001c0a8000207000000", + expectedOutput: "", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip IPv4 header: Options, Payload", + input: "460000140005400080060000c0a80001c0a8000207000000ffffffffffffffff", + expectedOutput: "ffffffffffffffff", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip IPv4 header: Input length lesss than minimum header length", + input: "450000140005400080060000c0a80001c0a800", + expectedOutput: "Input length is less than minimum IPv4 header length", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip IPv4 header: Input length less than IHL", + input: "460000140005400080060000c0a80001c0a80000", + expectedOutput: "Input length is less than IHL", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip IPv4 header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + } +]);