From 748379f0b07df948cf9074d2d500b5bc5484e1da Mon Sep 17 00:00:00 2001 From: c65722 <53181351+c65722@users.noreply.github.com> Date: Sun, 15 Sep 2024 14:29:35 +0100 Subject: [PATCH] Add Strip TCP header operation --- src/core/config/Categories.json | 1 + src/core/operations/StripTCPHeader.mjs | 60 +++++++++++ tests/operations/index.mjs | 1 + tests/operations/tests/StripTCPHeader.mjs | 126 ++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 src/core/operations/StripTCPHeader.mjs create mode 100644 tests/operations/tests/StripTCPHeader.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index bebdd6a5e2..f19f0a7d0a 100644 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -235,6 +235,7 @@ "Parse IPv6 address", "Parse IPv4 header", "Parse TCP", + "Strip TCP header", "Parse UDP", "Parse SSH Host Key", "Parse URI", diff --git a/src/core/operations/StripTCPHeader.mjs b/src/core/operations/StripTCPHeader.mjs new file mode 100644 index 0000000000..747744b213 --- /dev/null +++ b/src/core/operations/StripTCPHeader.mjs @@ -0,0 +1,60 @@ +/** + * @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 TCP header operation + */ +class StripTCPHeader extends Operation { + + /** + * StripTCPHeader constructor + */ + constructor() { + super(); + + this.name = "Strip TCP header"; + this.module = "Default"; + this.description = "Strips the TCP header from a TCP segment, outputting the payload."; + this.infoURL = "https://wikipedia.org/wiki/Transmission_Control_Protocol"; + 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 DATA_OFFSET_OFFSET = 12; + const DATA_OFFSET_LEN_BITS = 4; + + const s = new Stream(new Uint8Array(input)); + if (s.length < MIN_HEADER_LEN) { + throw new OperationError("Need at least 20 bytes for a TCP Header"); + } + + s.moveTo(DATA_OFFSET_OFFSET); + const dataOffsetWords = s.readBits(DATA_OFFSET_LEN_BITS); + const dataOffsetBytes = dataOffsetWords * 4; + if (s.length < dataOffsetBytes) { + throw new OperationError("Input length is less than data offset"); + } + + s.moveTo(dataOffsetBytes); + + return s.getBytes().buffer; + } + +} + +export default StripTCPHeader; diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 40ce7a2ee6..7b7622058a 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/StripTCPHeader.mjs"; import "./tests/Subsection.mjs"; import "./tests/SwapCase.mjs"; import "./tests/SymmetricDifference.mjs"; diff --git a/tests/operations/tests/StripTCPHeader.mjs b/tests/operations/tests/StripTCPHeader.mjs new file mode 100644 index 0000000000..1d98d41163 --- /dev/null +++ b/tests/operations/tests/StripTCPHeader.mjs @@ -0,0 +1,126 @@ +/** + * Strip TCP header tests. + * + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + */ + +import TestRegister from "../../lib/TestRegister.mjs"; + +TestRegister.addTests([ + { + name: "Strip TCP header: No options, No payload", + input: "7f900050000fa4b2000cb2a45010bff100000000", + expectedOutput: "", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip TCP header: No options, Payload", + input: "7f900050000fa4b2000cb2a45010bff100000000ffffffffffffffff", + expectedOutput: "ffffffffffffffff", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip TCP header: Options, No payload", + input: "7f900050000fa4b2000cb2a47010bff100000000020405b404020000", + expectedOutput: "", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip TCP header: Options, Payload", + input: "7f900050000fa4b2000cb2a47010bff100000000020405b404020000ffffffffffffffff", + expectedOutput: "ffffffffffffffff", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip TCP header: Input length less than minimum header length", + input: "7f900050000fa4b2000cb2a45010bff1000000", + expectedOutput: "Need at least 20 bytes for a TCP Header", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + }, + { + name: "Strip TCP header: Input length less than data offset", + input: "7f900050000fa4b2000cb2a47010bff100000000", + expectedOutput: "Input length is less than data offset", + recipeConfig: [ + { + op: "From Hex", + args: ["None"] + }, + { + op: "Strip TCP header", + args: [], + }, + { + op: "To Hex", + args: ["None", 0] + } + ] + } +]);