2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-05 23:53:27 +00:00

Compare commits

..

10 Commits

Author SHA1 Message Date
a3957273
d3ee16f38b Disable flakey URL test 2025-02-11 00:49:14 +00:00
a3957273
e1d3af26da Merge pull request #1955 from max0x53/compress
Webpack compress with gzip and brotli
2025-02-11 00:43:36 +00:00
a3957273
9d014aeaa5 Merge pull request #1898 from c65722/strip_tcp_header
Add Strip TCP header operation
2025-02-11 00:38:01 +00:00
a3957273
156de53dc1 Merge branch 'master' into strip_tcp_header 2025-02-11 00:27:38 +00:00
a3957273
7ecc235b31 Merge pull request #1900 from c65722/strip_udp_header
Add Strip UDP header operation
2025-02-11 00:26:59 +00:00
a3957273
51ed3b2fc1 Merge branch 'master' into strip_tcp_header 2025-02-11 00:26:52 +00:00
a3957273
306e29da76 Merge pull request #1972 from gchq/feature/detect-chromedriver
Automatically detect chrome driver version
2025-02-11 00:23:11 +00:00
Max S
304266020d Webpack compress with gzip and brotli 2024-12-28 17:20:15 +00:00
c65722
748379f0b0 Add Strip TCP header operation 2024-09-15 18:49:17 +01:00
c65722
da74d9b22d Add Strip UDP header operation 2024-09-15 18:14:21 +01:00
10 changed files with 378 additions and 28 deletions

22
package-lock.json generated
View File

@@ -118,6 +118,7 @@
"chromedriver": "^130.0.0", "chromedriver": "^130.0.0",
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"compression-webpack-plugin": "^11.1.0",
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"core-js": "^3.37.1", "core-js": "^3.37.1",
"css-loader": "7.1.2", "css-loader": "7.1.2",
@@ -5344,6 +5345,27 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/compression-webpack-plugin": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-11.1.0.tgz",
"integrity": "sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==",
"dev": true,
"license": "MIT",
"dependencies": {
"schema-utils": "^4.2.0",
"serialize-javascript": "^6.0.2"
},
"engines": {
"node": ">= 18.12.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"webpack": "^5.1.0"
}
},
"node_modules/compression/node_modules/bytes": { "node_modules/compression/node_modules/bytes": {
"version": "3.0.0", "version": "3.0.0",
"dev": true, "dev": true,

View File

@@ -58,6 +58,7 @@
"chromedriver": "^130.0.0", "chromedriver": "^130.0.0",
"cli-progress": "^3.12.0", "cli-progress": "^3.12.0",
"colors": "^1.4.0", "colors": "^1.4.0",
"compression-webpack-plugin": "^11.1.0",
"copy-webpack-plugin": "^12.0.2", "copy-webpack-plugin": "^12.0.2",
"core-js": "^3.37.1", "core-js": "^3.37.1",
"css-loader": "7.1.2", "css-loader": "7.1.2",

View File

@@ -236,8 +236,10 @@
"Parse IPv6 address", "Parse IPv6 address",
"Parse IPv4 header", "Parse IPv4 header",
"Parse TCP", "Parse TCP",
"Strip TCP header",
"Parse TLS record", "Parse TLS record",
"Parse UDP", "Parse UDP",
"Strip UDP header",
"Parse SSH Host Key", "Parse SSH Host Key",
"Parse URI", "Parse URI",
"URL Encode", "URL Encode",

View File

@@ -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;

View File

@@ -0,0 +1,51 @@
/**
* @author c65722 []
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Stream from "../lib/Stream.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Strip UDP header operation
*/
class StripUDPHeader extends Operation {
/**
* StripUDPHeader constructor
*/
constructor() {
super();
this.name = "Strip UDP header";
this.module = "Default";
this.description = "Strips the UDP header from a UDP datagram, outputting the payload.";
this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const HEADER_LEN = 8;
const s = new Stream(new Uint8Array(input));
if (s.length < HEADER_LEN) {
throw new OperationError("Need 8 bytes for a UDP Header");
}
s.moveTo(HEADER_LEN);
return s.getBytes().buffer;
}
}
export default StripUDPHeader;

View File

@@ -675,42 +675,42 @@ module.exports = {
} }
}, },
"Loading from URL": browser => { // "Loading from URL": browser => {
utils.clear(browser); // utils.clear(browser);
/* Side panel displays correct info */ // /* Side panel displays correct info */
utils.uploadFile(browser, "files/TowelDay.jpeg"); // utils.uploadFile(browser, "files/TowelDay.jpeg");
browser // browser
.waitForElementVisible("#input-text .cm-file-details") // .waitForElementVisible("#input-text .cm-file-details")
.waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown") // .waitForElementVisible("#input-text .cm-file-details .file-details-toggle-shown")
.waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail") // .waitForElementVisible("#input-text .cm-file-details .file-details-thumbnail")
.waitForElementVisible("#input-text .cm-file-details .file-details-name") // .waitForElementVisible("#input-text .cm-file-details .file-details-name")
.waitForElementVisible("#input-text .cm-file-details .file-details-size") // .waitForElementVisible("#input-text .cm-file-details .file-details-size")
.waitForElementVisible("#input-text .cm-file-details .file-details-type") // .waitForElementVisible("#input-text .cm-file-details .file-details-type")
.waitForElementVisible("#input-text .cm-file-details .file-details-loaded"); // .waitForElementVisible("#input-text .cm-file-details .file-details-loaded");
/* Complex deep link populates the input correctly (encoding, eol, input) */ // /* Complex deep link populates the input correctly (encoding, eol, input) */
browser // browser
.urlHash("recipe=To_Base64('A-Za-z0-9%2B/%3D')&input=VGhlIHNoaXBzIGh1bmcgaW4gdGhlIHNreSBpbiBtdWNoIHRoZSBzYW1lIHdheSB0aGF0IGJyaWNrcyBkb24ndC4M&ienc=21866&oenc=1201&ieol=FF&oeol=PS") // .urlHash("recipe=To_Base64('A-Za-z0-9%2B/%3D')&input=VGhlIHNoaXBzIGh1bmcgaW4gdGhlIHNreSBpbiBtdWNoIHRoZSBzYW1lIHdheSB0aGF0IGJyaWNrcyBkb24ndC4M&ienc=21866&oenc=1201&ieol=FF&oeol=PS")
.waitForElementVisible("#rec-list li.operation"); // .waitForElementVisible("#rec-list li.operation");
browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{65}$/); // browser.expect.element(`#input-text .cm-content`).to.have.property("textContent").match(/^.{65}$/);
browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("66"); // browser.expect.element("#input-text .cm-status-bar .stats-length-value").text.to.equal("66");
browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2"); // browser.expect.element("#input-text .cm-status-bar .stats-lines-value").text.to.equal("2");
browser.expect.element("#input-text .chr-enc-value").text.that.equals("KOI8-U Ukrainian Cyrillic"); // browser.expect.element("#input-text .chr-enc-value").text.that.equals("KOI8-U Ukrainian Cyrillic");
browser.expect.element("#output-text .chr-enc-value").text.that.equals("UTF-16BE"); // browser.expect.element("#output-text .chr-enc-value").text.that.equals("UTF-16BE");
browser.expect.element("#input-text .eol-value").text.that.equals("FF"); // browser.expect.element("#input-text .eol-value").text.that.equals("FF");
browser.expect.element("#output-text .eol-value").text.that.equals("PS"); // browser.expect.element("#output-text .eol-value").text.that.equals("PS");
utils.bake(browser); // utils.bake(browser);
browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^.{44}$/); // browser.expect.element(`#output-text .cm-content`).to.have.property("textContent").match(/^.{44}$/);
browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("44"); // browser.expect.element("#output-text .cm-status-bar .stats-length-value").text.to.equal("44");
browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1"); // browser.expect.element("#output-text .cm-status-bar .stats-lines-value").text.to.equal("1");
}, // },
"Replace input with output": browser => { "Replace input with output": browser => {
/* Input is correctly populated */ /* Input is correctly populated */

View File

@@ -143,6 +143,8 @@ import "./tests/SIGABA.mjs";
import "./tests/SM4.mjs"; import "./tests/SM4.mjs";
// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet
import "./tests/StrUtils.mjs"; import "./tests/StrUtils.mjs";
import "./tests/StripTCPHeader.mjs";
import "./tests/StripUDPHeader.mjs";
import "./tests/Subsection.mjs"; import "./tests/Subsection.mjs";
import "./tests/SwapCase.mjs"; import "./tests/SwapCase.mjs";
import "./tests/SymmetricDifference.mjs"; import "./tests/SymmetricDifference.mjs";

View File

@@ -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]
}
]
}
]);

View File

@@ -0,0 +1,69 @@
/**
* Strip UDP header tests.
*
* @author c65722 []
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Strip UDP header: No payload",
input: "8111003500000000",
expectedOutput: "",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Strip UDP header",
args: [],
},
{
op: "To Hex",
args: ["None", 0]
}
]
},
{
name: "Strip UDP header: Payload",
input: "8111003500080000ffffffffffffffff",
expectedOutput: "ffffffffffffffff",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Strip UDP header",
args: [],
},
{
op: "To Hex",
args: ["None", 0]
}
]
},
{
name: "Strip UDP header: Input length less than header length",
input: "81110035000000",
expectedOutput: "Need 8 bytes for a UDP Header",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Strip UDP header",
args: [],
},
{
op: "To Hex",
args: ["None", 0]
}
]
}
]);

View File

@@ -1,8 +1,10 @@
const webpack = require("webpack"); const webpack = require("webpack");
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CompressionPlugin = require("compression-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin"); const CopyWebpackPlugin = require("copy-webpack-plugin");
const { ModifySourcePlugin, ReplaceOperation } = require("modify-source-webpack-plugin"); const { ModifySourcePlugin, ReplaceOperation } = require("modify-source-webpack-plugin");
const path = require("path"); const path = require("path");
const zlib = require("zlib");
/** /**
* Webpack configuration details for use with Grunt. * Webpack configuration details for use with Grunt.
@@ -64,6 +66,21 @@ module.exports = {
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: "assets/[name].css" filename: "assets/[name].css"
}), }),
new CompressionPlugin({
filename: "[path][base].gz",
algorithm: "gzip",
test: /\.(js|css|html)$/,
}),
new CompressionPlugin({
filename: "[path][base].br",
algorithm: "brotliCompress",
test: /\.(js|css|html)$/,
compressionOptions: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11,
},
},
}),
new CopyWebpackPlugin({ new CopyWebpackPlugin({
patterns: [ patterns: [
{ {