mirror of
https://github.com/gchq/CyberChef
synced 2026-01-10 12:33:16 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5a89efc06 | ||
|
|
1078c37043 | ||
|
|
535c7188a8 | ||
|
|
d6f9e216a6 | ||
|
|
7d6a879a67 | ||
|
|
668eac1f9e | ||
|
|
ff99436ce6 | ||
|
|
ec577fc075 | ||
|
|
cc9d51b7be | ||
|
|
cf2b54e8c0 | ||
|
|
a895d1d82a | ||
|
|
11da4188ee | ||
|
|
5b68bad185 |
@@ -13,6 +13,9 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
|
|
||||||
## Details
|
## Details
|
||||||
|
|
||||||
|
### [9.38.0] - 2022-05-30
|
||||||
|
- Added 'Parse TCP' operation [@n1474335] | [a895d1d]
|
||||||
|
|
||||||
### [9.37.0] - 2022-03-29
|
### [9.37.0] - 2022-03-29
|
||||||
- 'SM4 Encrypt' and 'SM4 Decrypt' operations added [@swesven] | [#1189]
|
- 'SM4 Encrypt' and 'SM4 Decrypt' operations added [@swesven] | [#1189]
|
||||||
- NoPadding options added for CBC and ECB modes in AES, DES and Triple DES Decrypt operations [@swesven] | [#1189]
|
- NoPadding options added for CBC and ECB modes in AES, DES and Triple DES Decrypt operations [@swesven] | [#1189]
|
||||||
@@ -135,7 +138,7 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Click to expand v8 minor versions</summary>
|
<summary>Click to expand v8 minor versions</summary>
|
||||||
|
|
||||||
### [8.38.0] - 2019-07-03
|
### [8.38.0] - 2019-07-03
|
||||||
- 'Streebog' and 'GOST hash' operations added [@MShwed] [@n1474335] | [#530]
|
- 'Streebog' and 'GOST hash' operations added [@MShwed] [@n1474335] | [#530]
|
||||||
|
|
||||||
@@ -288,6 +291,7 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[9.38.0]: https://github.com/gchq/CyberChef/releases/tag/v9.38.0
|
||||||
[9.37.0]: https://github.com/gchq/CyberChef/releases/tag/v9.37.0
|
[9.37.0]: https://github.com/gchq/CyberChef/releases/tag/v9.37.0
|
||||||
[9.36.0]: https://github.com/gchq/CyberChef/releases/tag/v9.36.0
|
[9.36.0]: https://github.com/gchq/CyberChef/releases/tag/v9.36.0
|
||||||
[9.35.0]: https://github.com/gchq/CyberChef/releases/tag/v9.35.0
|
[9.35.0]: https://github.com/gchq/CyberChef/releases/tag/v9.35.0
|
||||||
@@ -416,6 +420,7 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[289a417]: https://github.com/gchq/CyberChef/commit/289a417dfb5923de5e1694354ec42a08d9395bfe
|
[289a417]: https://github.com/gchq/CyberChef/commit/289a417dfb5923de5e1694354ec42a08d9395bfe
|
||||||
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
|
||||||
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
|
||||||
|
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
|
||||||
|
|
||||||
[#95]: https://github.com/gchq/CyberChef/pull/299
|
[#95]: https://github.com/gchq/CyberChef/pull/299
|
||||||
[#173]: https://github.com/gchq/CyberChef/pull/173
|
[#173]: https://github.com/gchq/CyberChef/pull/173
|
||||||
@@ -502,4 +507,4 @@ All major and minor version changes will be documented in this file. Details of
|
|||||||
[#1242]: https://github.com/gchq/CyberChef/pull/1242
|
[#1242]: https://github.com/gchq/CyberChef/pull/1242
|
||||||
[#1244]: https://github.com/gchq/CyberChef/pull/1244
|
[#1244]: https://github.com/gchq/CyberChef/pull/1244
|
||||||
[#1313]: https://github.com/gchq/CyberChef/pull/1313
|
[#1313]: https://github.com/gchq/CyberChef/pull/1313
|
||||||
[#1326]: https://github.com/gchq/CyberChef/pull/1326
|
[#1326]: https://github.com/gchq/CyberChef/pull/1326
|
||||||
|
|||||||
@@ -217,7 +217,8 @@ module.exports = function (grunt) {
|
|||||||
client: {
|
client: {
|
||||||
logging: "error",
|
logging: "error",
|
||||||
overlay: true
|
overlay: true
|
||||||
}
|
},
|
||||||
|
hot: "only"
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
new webpack.DefinePlugin(BUILD_CONSTANTS),
|
||||||
|
|||||||
73
package-lock.json
generated
73
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.37.3",
|
"version": "9.38.2",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.37.3",
|
"version": "9.38.2",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"autoprefixer": "^10.4.4",
|
"autoprefixer": "^10.4.4",
|
||||||
"babel-loader": "^8.2.4",
|
"babel-loader": "^8.2.4",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"chromedriver": "^99.0.0",
|
"chromedriver": "^101.0.0",
|
||||||
"cli-progress": "^3.10.0",
|
"cli-progress": "^3.10.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^10.2.4",
|
||||||
@@ -119,6 +119,7 @@
|
|||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"imports-loader": "^3.1.1",
|
"imports-loader": "^3.1.1",
|
||||||
"mini-css-extract-plugin": "2.6.0",
|
"mini-css-extract-plugin": "2.6.0",
|
||||||
|
"modify-source-webpack-plugin": "^3.0.0",
|
||||||
"nightwatch": "^2.0.10",
|
"nightwatch": "^2.0.10",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
"postcss-css-variables": "^0.18.0",
|
"postcss-css-variables": "^0.18.0",
|
||||||
@@ -4467,9 +4468,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chromedriver": {
|
"node_modules/chromedriver": {
|
||||||
"version": "99.0.0",
|
"version": "101.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-99.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-101.0.0.tgz",
|
||||||
"integrity": "sha512-pyB+5LuyZdb7EBPL3i5D5yucZUD+SlkdiUtmpjaEnLd9zAXp+SvD/hP5xF4l/ZmWvUo/1ZLxAI1YBdhazGTpgA==",
|
"integrity": "sha512-LkkWxy6KM/0YdJS8qBeg5vfkTZTRamhBfOttb4oic4echDgWvCU1E8QcBbUBOHqZpSrYMyi7WMKmKMhXFUaZ+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -10740,6 +10741,37 @@
|
|||||||
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/modify-source-webpack-plugin": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-m2g6QEittzzcde0PhgQtOwRywjqo8Q+vMLHbNoH2JDEFE/AlTBWvtNQrp17xbqDUXIueLljm4bhE5OninatHYw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"loader-utils": "^2.0.0",
|
||||||
|
"schema-utils": "^3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"webpack": "^4.37.0 || ^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/modify-source-webpack-plugin/node_modules/schema-utils": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/json-schema": "^7.0.8",
|
||||||
|
"ajv": "^6.12.5",
|
||||||
|
"ajv-keywords": "^3.5.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.13.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/webpack"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/moment": {
|
"node_modules/moment": {
|
||||||
"version": "2.29.1",
|
"version": "2.29.1",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
@@ -19171,9 +19203,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chromedriver": {
|
"chromedriver": {
|
||||||
"version": "99.0.0",
|
"version": "101.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-99.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-101.0.0.tgz",
|
||||||
"integrity": "sha512-pyB+5LuyZdb7EBPL3i5D5yucZUD+SlkdiUtmpjaEnLd9zAXp+SvD/hP5xF4l/ZmWvUo/1ZLxAI1YBdhazGTpgA==",
|
"integrity": "sha512-LkkWxy6KM/0YdJS8qBeg5vfkTZTRamhBfOttb4oic4echDgWvCU1E8QcBbUBOHqZpSrYMyi7WMKmKMhXFUaZ+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@testim/chrome-version": "^1.1.2",
|
"@testim/chrome-version": "^1.1.2",
|
||||||
@@ -24019,6 +24051,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"modify-source-webpack-plugin": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-m2g6QEittzzcde0PhgQtOwRywjqo8Q+vMLHbNoH2JDEFE/AlTBWvtNQrp17xbqDUXIueLljm4bhE5OninatHYw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"loader-utils": "^2.0.0",
|
||||||
|
"schema-utils": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"schema-utils": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/json-schema": "^7.0.8",
|
||||||
|
"ajv": "^6.12.5",
|
||||||
|
"ajv-keywords": "^3.5.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.29.1",
|
"version": "2.29.1",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cyberchef",
|
"name": "cyberchef",
|
||||||
"version": "9.37.3",
|
"version": "9.38.2",
|
||||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||||
"author": "n1474335 <n1474335@gmail.com>",
|
"author": "n1474335 <n1474335@gmail.com>",
|
||||||
"homepage": "https://gchq.github.io/CyberChef",
|
"homepage": "https://gchq.github.io/CyberChef",
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
"autoprefixer": "^10.4.4",
|
"autoprefixer": "^10.4.4",
|
||||||
"babel-loader": "^8.2.4",
|
"babel-loader": "^8.2.4",
|
||||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
"chromedriver": "^99.0.0",
|
"chromedriver": "^101.0.0",
|
||||||
"cli-progress": "^3.10.0",
|
"cli-progress": "^3.10.0",
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"copy-webpack-plugin": "^10.2.4",
|
"copy-webpack-plugin": "^10.2.4",
|
||||||
@@ -69,6 +69,7 @@
|
|||||||
"html-webpack-plugin": "^5.5.0",
|
"html-webpack-plugin": "^5.5.0",
|
||||||
"imports-loader": "^3.1.1",
|
"imports-loader": "^3.1.1",
|
||||||
"mini-css-extract-plugin": "2.6.0",
|
"mini-css-extract-plugin": "2.6.0",
|
||||||
|
"modify-source-webpack-plugin": "^3.0.0",
|
||||||
"nightwatch": "^2.0.10",
|
"nightwatch": "^2.0.10",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
"postcss-css-variables": "^0.18.0",
|
"postcss-css-variables": "^0.18.0",
|
||||||
@@ -174,6 +175,7 @@
|
|||||||
"lint": "npx grunt lint",
|
"lint": "npx grunt lint",
|
||||||
"postinstall": "npx grunt exec:fixCryptoApiImports",
|
"postinstall": "npx grunt exec:fixCryptoApiImports",
|
||||||
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
"newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs",
|
||||||
|
"minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs",
|
||||||
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
"getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'",
|
||||||
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,6 +190,7 @@
|
|||||||
"Parse IP range",
|
"Parse IP range",
|
||||||
"Parse IPv6 address",
|
"Parse IPv6 address",
|
||||||
"Parse IPv4 header",
|
"Parse IPv4 header",
|
||||||
|
"Parse TCP",
|
||||||
"Parse UDP",
|
"Parse UDP",
|
||||||
"Parse SSH Host Key",
|
"Parse SSH Host Key",
|
||||||
"Parse URI",
|
"Parse URI",
|
||||||
|
|||||||
144
src/core/config/scripts/newMinorVersion.mjs
Normal file
144
src/core/config/scripts/newMinorVersion.mjs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
* This script updates the CHANGELOG when a new minor version is created.
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint no-console: ["off"] */
|
||||||
|
|
||||||
|
import prompt from "prompt";
|
||||||
|
import colors from "colors";
|
||||||
|
import path from "path";
|
||||||
|
import fs from "fs";
|
||||||
|
import process from "process";
|
||||||
|
|
||||||
|
const dir = path.join(process.cwd() + "/src/core/config/");
|
||||||
|
if (!fs.existsSync(dir)) {
|
||||||
|
console.log("\nCWD: " + process.cwd());
|
||||||
|
console.log("Error: newMinorVersion.mjs should be run from the project root");
|
||||||
|
console.log("Example> node --experimental-modules src/core/config/scripts/newMinorVersion.mjs");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let changelogData = fs.readFileSync(path.join(process.cwd(), "CHANGELOG.md"), "utf8");
|
||||||
|
const lastVersion = changelogData.match(/## Details\s+### \[(\d+)\.(\d+)\.(\d+)\]/);
|
||||||
|
const newVersion = [
|
||||||
|
parseInt(lastVersion[1], 10),
|
||||||
|
parseInt(lastVersion[2], 10) + 1,
|
||||||
|
0
|
||||||
|
];
|
||||||
|
|
||||||
|
let knownContributors = changelogData.match(/^\[@([^\]]+)\]/gm);
|
||||||
|
knownContributors = knownContributors.map(c => c.slice(2, -1));
|
||||||
|
|
||||||
|
const date = (new Date()).toISOString().split("T")[0];
|
||||||
|
|
||||||
|
const schema = {
|
||||||
|
properties: {
|
||||||
|
message: {
|
||||||
|
description: "A short but descriptive summary of a feature in this version",
|
||||||
|
example: "Added 'Op name' operation",
|
||||||
|
prompt: "Feature description",
|
||||||
|
type: "string",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
author: {
|
||||||
|
description: "The author of the feature (only one supported, edit manually to add more)",
|
||||||
|
example: "n1474335",
|
||||||
|
prompt: "Author",
|
||||||
|
type: "string",
|
||||||
|
default: "n1474335"
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
description: "The PR number or full commit hash for this feature.",
|
||||||
|
example: "1200",
|
||||||
|
prompt: "Pull request or commit ID",
|
||||||
|
type: "string"
|
||||||
|
},
|
||||||
|
another: {
|
||||||
|
description: "y/n",
|
||||||
|
example: "y",
|
||||||
|
prompt: "Add another feature?",
|
||||||
|
type: "string",
|
||||||
|
pattern: /^[yn]$/,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build schema
|
||||||
|
for (const prop in schema.properties) {
|
||||||
|
const p = schema.properties[prop];
|
||||||
|
p.description = "\n" + colors.white(p.description) + colors.cyan("\nExample: " + p.example) + "\n" + colors.green(p.prompt);
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt.message = "";
|
||||||
|
prompt.delimiter = ":".green;
|
||||||
|
|
||||||
|
const features = [];
|
||||||
|
const authors = [];
|
||||||
|
const prIDs = [];
|
||||||
|
const commitIDs = [];
|
||||||
|
|
||||||
|
prompt.start();
|
||||||
|
|
||||||
|
const getFeature = function() {
|
||||||
|
prompt.get(schema, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
console.log("\nExiting script.");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
features.push(result);
|
||||||
|
|
||||||
|
if (result.another === "y") {
|
||||||
|
getFeature();
|
||||||
|
} else {
|
||||||
|
let message = `### [${newVersion[0]}.${newVersion[1]}.${newVersion[2]}] - ${date}\n`;
|
||||||
|
|
||||||
|
features.forEach(feature => {
|
||||||
|
const id = feature.id.length > 10 ? feature.id.slice(0, 7) : "#" + feature.id;
|
||||||
|
message += `- ${feature.message} [@${feature.author}] | [${id}]\n`;
|
||||||
|
|
||||||
|
if (!knownContributors.includes(feature.author)) {
|
||||||
|
authors.push(`[@${feature.author}]: https://github.com/${feature.author}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature.id.length > 10) {
|
||||||
|
commitIDs.push(`[${id}]: https://github.com/gchq/CyberChef/commit/${feature.id}`);
|
||||||
|
} else {
|
||||||
|
prIDs.push(`[#${feature.id}]: https://github.com/gchq/CyberChef/pull/${feature.id}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Message
|
||||||
|
changelogData = changelogData.replace(/## Details\n\n/, "## Details\n\n" + message + "\n");
|
||||||
|
|
||||||
|
// Tag
|
||||||
|
const newTag = `[${newVersion[0]}.${newVersion[1]}.${newVersion[2]}]: https://github.com/gchq/CyberChef/releases/tag/v${newVersion[0]}.${newVersion[1]}.${newVersion[2]}\n`;
|
||||||
|
changelogData = changelogData.replace(/\n\n(\[\d+\.\d+\.\d+\]: https)/, "\n\n" + newTag + "$1");
|
||||||
|
|
||||||
|
// Author
|
||||||
|
authors.forEach(author => {
|
||||||
|
changelogData = changelogData.replace(/(\n\[@[^\]]+\]: https:\/\/github\.com\/[^\n]+\n)\n/, "$1" + author + "\n\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Commit IDs
|
||||||
|
commitIDs.forEach(commitID => {
|
||||||
|
changelogData = changelogData.replace(/(\n\[[^\].]+\]: https:\/\/github.com\/gchq\/CyberChef\/commit\/[^\n]+\n)\n/, "$1" + commitID + "\n\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
// PR IDs
|
||||||
|
prIDs.forEach(prID => {
|
||||||
|
changelogData = changelogData.replace(/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n/, "$1" + prID + "\n\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||||
|
|
||||||
|
console.log("Written CHANGELOG.md");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
getFeature();
|
||||||
@@ -13,7 +13,7 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
/**
|
/**
|
||||||
* Convert a byte array into a binary string.
|
* Convert a byte array into a binary string.
|
||||||
*
|
*
|
||||||
* @param {Uint8Array|byteArray} data
|
* @param {Uint8Array|byteArray|number} data
|
||||||
* @param {string} [delim="Space"]
|
* @param {string} [delim="Space"]
|
||||||
* @param {number} [padding=8]
|
* @param {number} [padding=8]
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
@@ -26,13 +26,17 @@ import OperationError from "../errors/OperationError.mjs";
|
|||||||
* toBinary([10,20,30], ":");
|
* toBinary([10,20,30], ":");
|
||||||
*/
|
*/
|
||||||
export function toBinary(data, delim="Space", padding=8) {
|
export function toBinary(data, delim="Space", padding=8) {
|
||||||
if (!data) return "";
|
|
||||||
|
|
||||||
delim = Utils.charRep(delim);
|
delim = Utils.charRep(delim);
|
||||||
let output = "";
|
let output = "";
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i++) {
|
if (data.length) { // array
|
||||||
output += data[i].toString(2).padStart(padding, "0") + delim;
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
output += data[i].toString(2).padStart(padding, "0") + delim;
|
||||||
|
}
|
||||||
|
} else if (typeof data === "number") { // Single value
|
||||||
|
return data.toString(2).padStart(padding, "0");
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delim.length) {
|
if (delim.length) {
|
||||||
|
|||||||
@@ -3778,8 +3778,8 @@ function parseDEFLATE(stream) {
|
|||||||
|
|
||||||
while (!finalBlock) {
|
while (!finalBlock) {
|
||||||
// Read header
|
// Read header
|
||||||
finalBlock = stream.readBits(1);
|
finalBlock = stream.readBits(1, "le");
|
||||||
const blockType = stream.readBits(2);
|
const blockType = stream.readBits(2, "le");
|
||||||
|
|
||||||
if (blockType === 0) {
|
if (blockType === 0) {
|
||||||
/* No compression */
|
/* No compression */
|
||||||
@@ -3798,16 +3798,16 @@ function parseDEFLATE(stream) {
|
|||||||
/* Dynamic Huffman */
|
/* Dynamic Huffman */
|
||||||
|
|
||||||
// Read the number of liternal and length codes
|
// Read the number of liternal and length codes
|
||||||
const hlit = stream.readBits(5) + 257;
|
const hlit = stream.readBits(5, "le") + 257;
|
||||||
// Read the number of distance codes
|
// Read the number of distance codes
|
||||||
const hdist = stream.readBits(5) + 1;
|
const hdist = stream.readBits(5, "le") + 1;
|
||||||
// Read the number of code lengths
|
// Read the number of code lengths
|
||||||
const hclen = stream.readBits(4) + 4;
|
const hclen = stream.readBits(4, "le") + 4;
|
||||||
|
|
||||||
// Parse code lengths
|
// Parse code lengths
|
||||||
const codeLengths = new Uint8Array(huffmanOrder.length);
|
const codeLengths = new Uint8Array(huffmanOrder.length);
|
||||||
for (let i = 0; i < hclen; i++) {
|
for (let i = 0; i < hclen; i++) {
|
||||||
codeLengths[huffmanOrder[i]] = stream.readBits(3);
|
codeLengths[huffmanOrder[i]] = stream.readBits(3, "le");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse length table
|
// Parse length table
|
||||||
@@ -3819,16 +3819,16 @@ function parseDEFLATE(stream) {
|
|||||||
code = readHuffmanCode(stream, codeLengthsTable);
|
code = readHuffmanCode(stream, codeLengthsTable);
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 16:
|
case 16:
|
||||||
repeat = 3 + stream.readBits(2);
|
repeat = 3 + stream.readBits(2, "le");
|
||||||
while (repeat--) lengthTable[i++] = prev;
|
while (repeat--) lengthTable[i++] = prev;
|
||||||
break;
|
break;
|
||||||
case 17:
|
case 17:
|
||||||
repeat = 3 + stream.readBits(3);
|
repeat = 3 + stream.readBits(3, "le");
|
||||||
while (repeat--) lengthTable[i++] = 0;
|
while (repeat--) lengthTable[i++] = 0;
|
||||||
prev = 0;
|
prev = 0;
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
repeat = 11 + stream.readBits(7);
|
repeat = 11 + stream.readBits(7, "le");
|
||||||
while (repeat--) lengthTable[i++] = 0;
|
while (repeat--) lengthTable[i++] = 0;
|
||||||
prev = 0;
|
prev = 0;
|
||||||
break;
|
break;
|
||||||
@@ -3886,11 +3886,11 @@ function parseHuffmanBlock(stream, litTab, distTab) {
|
|||||||
if (code < 256) continue;
|
if (code < 256) continue;
|
||||||
|
|
||||||
// Length code
|
// Length code
|
||||||
stream.readBits(lengthExtraTable[code - 257]);
|
stream.readBits(lengthExtraTable[code - 257], "le");
|
||||||
|
|
||||||
// Dist code
|
// Dist code
|
||||||
code = readHuffmanCode(stream, distTab);
|
code = readHuffmanCode(stream, distTab);
|
||||||
stream.readBits(distanceExtraTable[code]);
|
stream.readBits(distanceExtraTable[code], "le");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3948,7 +3948,7 @@ function readHuffmanCode(stream, table) {
|
|||||||
const [codeTable, maxCodeLength] = table;
|
const [codeTable, maxCodeLength] = table;
|
||||||
|
|
||||||
// Read max length
|
// Read max length
|
||||||
const bitsBuf = stream.readBits(maxCodeLength);
|
const bitsBuf = stream.readBits(maxCodeLength, "le");
|
||||||
const codeWithLength = codeTable[bitsBuf & ((1 << maxCodeLength) - 1)];
|
const codeWithLength = codeTable[bitsBuf & ((1 << maxCodeLength) - 1)];
|
||||||
const codeLength = codeWithLength >>> 16;
|
const codeLength = codeWithLength >>> 16;
|
||||||
|
|
||||||
|
|||||||
47
src/core/lib/Protocol.mjs
Normal file
47
src/core/lib/Protocol.mjs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* Protocol parsing functions.
|
||||||
|
*
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import BigNumber from "bignumber.js";
|
||||||
|
import {toHexFast} from "../lib/Hex.mjs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively displays a JSON object as an HTML table
|
||||||
|
*
|
||||||
|
* @param {Object} obj
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
export function objToTable(obj, nested=false) {
|
||||||
|
let html = `<table
|
||||||
|
class='table table-sm table-nonfluid ${nested ? "mb-0 table-borderless" : "table-bordered"}'
|
||||||
|
style='table-layout: fixed; ${nested ? "margin: -1px !important;" : ""}'>`;
|
||||||
|
if (!nested)
|
||||||
|
html += `<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>`;
|
||||||
|
|
||||||
|
for (const key in obj) {
|
||||||
|
html += `<tr><td style='word-wrap: break-word'>${key}</td>`;
|
||||||
|
if (typeof obj[key] === "object")
|
||||||
|
html += `<td style='padding: 0'>${objToTable(obj[key], true)}</td>`;
|
||||||
|
else
|
||||||
|
html += `<td>${obj[key]}</td>`;
|
||||||
|
html += "</tr>";
|
||||||
|
}
|
||||||
|
html += "</table>";
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts bytes into a BigNumber string
|
||||||
|
* @param {Uint8Array} bs
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function bytesToLargeNumber(bs) {
|
||||||
|
return BigNumber(toHexFast(bs), 16).toString();
|
||||||
|
}
|
||||||
@@ -27,15 +27,17 @@ export default class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a number of bytes from the current position.
|
* Get a number of bytes from the current position, or all remaining bytes.
|
||||||
*
|
*
|
||||||
* @param {number} numBytes
|
* @param {number} [numBytes=null]
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
getBytes(numBytes) {
|
getBytes(numBytes=null) {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
const newPosition = this.position + numBytes;
|
const newPosition = numBytes !== null ?
|
||||||
|
this.position + numBytes :
|
||||||
|
this.length;
|
||||||
const bytes = this.bytes.slice(this.position, newPosition);
|
const bytes = this.bytes.slice(this.position, newPosition);
|
||||||
this.position = newPosition;
|
this.position = newPosition;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
@@ -91,34 +93,40 @@ export default class Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a number of bits from the buffer.
|
* Reads a number of bits from the buffer in big or little endian.
|
||||||
*
|
|
||||||
* @TODO Add endianness
|
|
||||||
*
|
*
|
||||||
* @param {number} numBits
|
* @param {number} numBits
|
||||||
|
* @param {string} [endianness="be"]
|
||||||
* @returns {number}
|
* @returns {number}
|
||||||
*/
|
*/
|
||||||
readBits(numBits) {
|
readBits(numBits, endianness="be") {
|
||||||
if (this.position > this.length) return undefined;
|
if (this.position > this.length) return undefined;
|
||||||
|
|
||||||
let bitBuf = 0,
|
let bitBuf = 0,
|
||||||
bitBufLen = 0;
|
bitBufLen = 0;
|
||||||
|
|
||||||
// Add remaining bits from current byte
|
// Add remaining bits from current byte
|
||||||
bitBuf = (this.bytes[this.position++] & bitMask(this.bitPos)) >>> this.bitPos;
|
bitBuf = this.bytes[this.position++] & bitMask(this.bitPos);
|
||||||
|
if (endianness !== "be") bitBuf >>>= this.bitPos;
|
||||||
bitBufLen = 8 - this.bitPos;
|
bitBufLen = 8 - this.bitPos;
|
||||||
this.bitPos = 0;
|
this.bitPos = 0;
|
||||||
|
|
||||||
// Not enough bits yet
|
// Not enough bits yet
|
||||||
while (bitBufLen < numBits) {
|
while (bitBufLen < numBits) {
|
||||||
bitBuf |= this.bytes[this.position++] << bitBufLen;
|
if (endianness === "be")
|
||||||
|
bitBuf = (bitBuf << bitBufLen) | this.bytes[this.position++];
|
||||||
|
else
|
||||||
|
bitBuf |= this.bytes[this.position++] << bitBufLen;
|
||||||
bitBufLen += 8;
|
bitBufLen += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse back to numBits
|
// Reverse back to numBits
|
||||||
if (bitBufLen > numBits) {
|
if (bitBufLen > numBits) {
|
||||||
const excess = bitBufLen - numBits;
|
const excess = bitBufLen - numBits;
|
||||||
bitBuf &= (1 << numBits) - 1;
|
if (endianness === "be")
|
||||||
|
bitBuf >>>= excess;
|
||||||
|
else
|
||||||
|
bitBuf &= (1 << numBits) - 1;
|
||||||
bitBufLen -= excess;
|
bitBufLen -= excess;
|
||||||
this.position--;
|
this.position--;
|
||||||
this.bitPos = 8 - excess;
|
this.bitPos = 8 - excess;
|
||||||
@@ -133,7 +141,9 @@ export default class Stream {
|
|||||||
* @returns {number} The bit mask
|
* @returns {number} The bit mask
|
||||||
*/
|
*/
|
||||||
function bitMask(bitPos) {
|
function bitMask(bitPos) {
|
||||||
return 256 - (1 << bitPos);
|
return endianness === "be" ?
|
||||||
|
(1 << (8 - bitPos)) - 1 :
|
||||||
|
256 - (1 << bitPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
245
src/core/operations/ParseTCP.mjs
Normal file
245
src/core/operations/ParseTCP.mjs
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
/**
|
||||||
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Operation from "../Operation.mjs";
|
||||||
|
import Stream from "../lib/Stream.mjs";
|
||||||
|
import {toHexFast, fromHex} from "../lib/Hex.mjs";
|
||||||
|
import {toBinary} from "../lib/Binary.mjs";
|
||||||
|
import {objToTable, bytesToLargeNumber} from "../lib/Protocol.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
import BigNumber from "bignumber.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse TCP operation
|
||||||
|
*/
|
||||||
|
class ParseTCP extends Operation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ParseTCP constructor
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.name = "Parse TCP";
|
||||||
|
this.module = "Default";
|
||||||
|
this.description = "Parses a TCP header and payload (if present).";
|
||||||
|
this.infoURL = "https://wikipedia.org/wiki/Transmission_Control_Protocol";
|
||||||
|
this.inputType = "string";
|
||||||
|
this.outputType = "json";
|
||||||
|
this.presentType = "html";
|
||||||
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Input format",
|
||||||
|
type: "option",
|
||||||
|
value: ["Hex", "Raw"]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
|
* @returns {html}
|
||||||
|
*/
|
||||||
|
run(input, args) {
|
||||||
|
const format = args[0];
|
||||||
|
|
||||||
|
if (format === "Hex") {
|
||||||
|
input = fromHex(input);
|
||||||
|
} else if (format === "Raw") {
|
||||||
|
input = Utils.strToArrayBuffer(input);
|
||||||
|
} else {
|
||||||
|
throw new OperationError("Unrecognised input format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const s = new Stream(new Uint8Array(input));
|
||||||
|
if (s.length < 20) {
|
||||||
|
throw new OperationError("Need at least 20 bytes for a TCP Header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse Header
|
||||||
|
const TCPPacket = {
|
||||||
|
"Source port": s.readInt(2),
|
||||||
|
"Destination port": s.readInt(2),
|
||||||
|
"Sequence number": bytesToLargeNumber(s.getBytes(4)),
|
||||||
|
"Acknowledgement number": s.readInt(4),
|
||||||
|
"Data offset": s.readBits(4),
|
||||||
|
"Flags": {
|
||||||
|
"Reserved": toBinary(s.readBits(3), "", 3),
|
||||||
|
"NS": s.readBits(1),
|
||||||
|
"CWR": s.readBits(1),
|
||||||
|
"ECE": s.readBits(1),
|
||||||
|
"URG": s.readBits(1),
|
||||||
|
"ACK": s.readBits(1),
|
||||||
|
"PSH": s.readBits(1),
|
||||||
|
"RST": s.readBits(1),
|
||||||
|
"SYN": s.readBits(1),
|
||||||
|
"FIN": s.readBits(1),
|
||||||
|
},
|
||||||
|
"Window size": s.readInt(2),
|
||||||
|
"Checksum": "0x" + toHexFast(s.getBytes(2)),
|
||||||
|
"Urgent pointer": "0x" + toHexFast(s.getBytes(2))
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parse options if present
|
||||||
|
let windowScaleShift = 0;
|
||||||
|
if (TCPPacket["Data offset"] > 5) {
|
||||||
|
let remainingLength = TCPPacket["Data offset"] * 4 - 20;
|
||||||
|
|
||||||
|
const options = {};
|
||||||
|
while (remainingLength > 0) {
|
||||||
|
const option = {
|
||||||
|
"Kind": s.readInt(1)
|
||||||
|
};
|
||||||
|
|
||||||
|
let opt = { name: "Reserved", length: true };
|
||||||
|
if (Object.prototype.hasOwnProperty.call(TCP_OPTION_KIND_LOOKUP, option.Kind)) {
|
||||||
|
opt = TCP_OPTION_KIND_LOOKUP[option.Kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add Length and Value fields
|
||||||
|
if (opt.length) {
|
||||||
|
option.Length = s.readInt(1);
|
||||||
|
|
||||||
|
if (option.Length > 2) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(opt, "parser")) {
|
||||||
|
option.Value = opt.parser(s.getBytes(option.Length - 2));
|
||||||
|
} else {
|
||||||
|
option.Value = option.Length <= 6 ?
|
||||||
|
s.readInt(option.Length - 2):
|
||||||
|
"0x" + toHexFast(s.getBytes(option.Length - 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store Window Scale shift for later
|
||||||
|
if (option.Kind === 3 && option.Value) {
|
||||||
|
windowScaleShift = option.Value["Shift count"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options[opt.name] = option;
|
||||||
|
|
||||||
|
const length = option.Length || 1;
|
||||||
|
remainingLength -= length;
|
||||||
|
}
|
||||||
|
TCPPacket.Options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s.hasMore()) {
|
||||||
|
TCPPacket.Data = "0x" + toHexFast(s.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Improve values
|
||||||
|
TCPPacket["Data offset"] = `${TCPPacket["Data offset"]} (${TCPPacket["Data offset"] * 4} bytes)`;
|
||||||
|
const trueWndSize = BigNumber(TCPPacket["Window size"]).multipliedBy(BigNumber(2).pow(BigNumber(windowScaleShift)));
|
||||||
|
TCPPacket["Window size"] = `${TCPPacket["Window size"]} (Scaled: ${trueWndSize})`;
|
||||||
|
|
||||||
|
return TCPPacket;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the TCP Packet in a tabular style
|
||||||
|
* @param {Object} data
|
||||||
|
* @returns {html}
|
||||||
|
*/
|
||||||
|
present(data) {
|
||||||
|
return objToTable(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Taken from https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml
|
||||||
|
// on 2022-05-30
|
||||||
|
const TCP_OPTION_KIND_LOOKUP = {
|
||||||
|
0: { name: "End of Option List", length: false },
|
||||||
|
1: { name: "No-Operation", length: false },
|
||||||
|
2: { name: "Maximum Segment Size", length: true },
|
||||||
|
3: { name: "Window Scale", length: true, parser: windowScaleParser },
|
||||||
|
4: { name: "SACK Permitted", length: true },
|
||||||
|
5: { name: "SACK", length: true },
|
||||||
|
6: { name: "Echo (obsoleted by option 8)", length: true },
|
||||||
|
7: { name: "Echo Reply (obsoleted by option 8)", length: true },
|
||||||
|
8: { name: "Timestamps", length: true, parser: tcpTimestampParser },
|
||||||
|
9: { name: "Partial Order Connection Permitted (obsolete)", length: true },
|
||||||
|
10: { name: "Partial Order Service Profile (obsolete)", length: true },
|
||||||
|
11: { name: "CC (obsolete)", length: true },
|
||||||
|
12: { name: "CC.NEW (obsolete)", length: true },
|
||||||
|
13: { name: "CC.ECHO (obsolete)", length: true },
|
||||||
|
14: { name: "TCP Alternate Checksum Request (obsolete)", length: true, parser: tcpAlternateChecksumParser },
|
||||||
|
15: { name: "TCP Alternate Checksum Data (obsolete)", length: true },
|
||||||
|
16: { name: "Skeeter", length: true },
|
||||||
|
17: { name: "Bubba", length: true },
|
||||||
|
18: { name: "Trailer Checksum Option", length: true },
|
||||||
|
19: { name: "MD5 Signature Option (obsoleted by option 29)", length: true },
|
||||||
|
20: { name: "SCPS Capabilities", length: true },
|
||||||
|
21: { name: "Selective Negative Acknowledgements", length: true },
|
||||||
|
22: { name: "Record Boundaries", length: true },
|
||||||
|
23: { name: "Corruption experienced", length: true },
|
||||||
|
24: { name: "SNAP", length: true },
|
||||||
|
25: { name: "Unassigned (released 2000-12-18)", length: true },
|
||||||
|
26: { name: "TCP Compression Filter", length: true },
|
||||||
|
27: { name: "Quick-Start Response", length: true },
|
||||||
|
28: { name: "User Timeout Option (also, other known unauthorized use)", length: true },
|
||||||
|
29: { name: "TCP Authentication Option (TCP-AO)", length: true },
|
||||||
|
30: { name: "Multipath TCP (MPTCP)", length: true },
|
||||||
|
69: { name: "Encryption Negotiation (TCP-ENO)", length: true },
|
||||||
|
70: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true },
|
||||||
|
76: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true },
|
||||||
|
77: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true },
|
||||||
|
78: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true },
|
||||||
|
253: { name: "RFC3692-style Experiment 1 (also improperly used for shipping products) ", length: true },
|
||||||
|
254: { name: "RFC3692-style Experiment 2 (also improperly used for shipping products) ", length: true }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the TCP Alternate Checksum Request field
|
||||||
|
* @param {Uint8Array} data
|
||||||
|
*/
|
||||||
|
function tcpAlternateChecksumParser(data) {
|
||||||
|
const lookup = {
|
||||||
|
0: "TCP Checksum",
|
||||||
|
1: "8-bit Fletchers's algorithm",
|
||||||
|
2: "16-bit Fletchers's algorithm",
|
||||||
|
3: "Redundant Checksum Avoidance"
|
||||||
|
}[data[0]];
|
||||||
|
|
||||||
|
return `${lookup} (0x${toHexFast(data)})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the TCP Timestamp field
|
||||||
|
* @param {Uint8Array} data
|
||||||
|
*/
|
||||||
|
function tcpTimestampParser(data) {
|
||||||
|
const s = new Stream(data);
|
||||||
|
|
||||||
|
if (s.length !== 8)
|
||||||
|
return `Error: Timestamp field should be 8 bytes long (received 0x${toHexFast(data)})`;
|
||||||
|
|
||||||
|
const tsval = bytesToLargeNumber(s.getBytes(4)),
|
||||||
|
tsecr = bytesToLargeNumber(s.getBytes(4));
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Current Timestamp": tsval,
|
||||||
|
"Echo Reply": tsecr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the Window Scale field
|
||||||
|
* @param {Uint8Array} data
|
||||||
|
*/
|
||||||
|
function windowScaleParser(data) {
|
||||||
|
if (data.length !== 1)
|
||||||
|
return `Error: Window Scale should be one byte long (received 0x${toHexFast(data)})`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Shift count": data[0],
|
||||||
|
"Multiplier": 1 << data[0]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ParseTCP;
|
||||||
@@ -6,7 +6,9 @@
|
|||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import Stream from "../lib/Stream.mjs";
|
import Stream from "../lib/Stream.mjs";
|
||||||
import {toHex} from "../lib/Hex.mjs";
|
import {toHexFast, fromHex} from "../lib/Hex.mjs";
|
||||||
|
import {objToTable} from "../lib/Protocol.mjs";
|
||||||
|
import Utils from "../Utils.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -24,58 +26,61 @@ class ParseUDP extends Operation {
|
|||||||
this.module = "Default";
|
this.module = "Default";
|
||||||
this.description = "Parses a UDP header and payload (if present).";
|
this.description = "Parses a UDP header and payload (if present).";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol";
|
this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "string";
|
||||||
this.outputType = "json";
|
this.outputType = "json";
|
||||||
this.presentType = "html";
|
this.presentType = "html";
|
||||||
this.args = [];
|
this.args = [
|
||||||
|
{
|
||||||
|
name: "Input format",
|
||||||
|
type: "option",
|
||||||
|
value: ["Hex", "Raw"]
|
||||||
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ArrayBuffer} input
|
* @param {string} input
|
||||||
|
* @param {Object[]} args
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
if (input.byteLength < 8) {
|
const format = args[0];
|
||||||
throw new OperationError("Need 8 bytes for a UDP Header");
|
|
||||||
|
if (format === "Hex") {
|
||||||
|
input = fromHex(input);
|
||||||
|
} else if (format === "Raw") {
|
||||||
|
input = Utils.strToArrayBuffer(input);
|
||||||
|
} else {
|
||||||
|
throw new OperationError("Unrecognised input format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const s = new Stream(new Uint8Array(input));
|
const s = new Stream(new Uint8Array(input));
|
||||||
|
if (s.length < 8) {
|
||||||
|
throw new OperationError("Need 8 bytes for a UDP Header");
|
||||||
|
}
|
||||||
|
|
||||||
// Parse Header
|
// Parse Header
|
||||||
const UDPPacket = {
|
const UDPPacket = {
|
||||||
"Source port": s.readInt(2),
|
"Source port": s.readInt(2),
|
||||||
"Destination port": s.readInt(2),
|
"Destination port": s.readInt(2),
|
||||||
"Length": s.readInt(2),
|
"Length": s.readInt(2),
|
||||||
"Checksum": toHex(s.getBytes(2), "")
|
"Checksum": "0x" + toHexFast(s.getBytes(2))
|
||||||
};
|
};
|
||||||
// Parse data if present
|
// Parse data if present
|
||||||
if (s.hasMore()) {
|
if (s.hasMore()) {
|
||||||
UDPPacket.Data = toHex(s.getBytes(UDPPacket.Length - 8), "");
|
UDPPacket.Data = "0x" + toHexFast(s.getBytes(UDPPacket.Length - 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
return UDPPacket;
|
return UDPPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the UDP Packet in a table style
|
* Displays the UDP Packet in a tabular style
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {html}
|
* @returns {html}
|
||||||
*/
|
*/
|
||||||
present(data) {
|
present(data) {
|
||||||
const html = [];
|
return objToTable(data);
|
||||||
html.push("<table class='table table-hover table-sm table-bordered table-nonfluid' style='table-layout: fixed'>");
|
|
||||||
html.push("<tr>");
|
|
||||||
html.push("<th>Field</th>");
|
|
||||||
html.push("<th>Value</th>");
|
|
||||||
html.push("</tr>");
|
|
||||||
|
|
||||||
for (const key in data) {
|
|
||||||
html.push("<tr>");
|
|
||||||
html.push("<td style=\"word-wrap:break-word\">" + key + "</td>");
|
|
||||||
html.push("<td>" + data[key] + "</td>");
|
|
||||||
html.push("</tr>");
|
|
||||||
}
|
|
||||||
html.push("</table>");
|
|
||||||
return html.join("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ class Substitute extends Operation {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
const plaintext = Utils.expandAlphRange(args[0]).join(""),
|
const plaintext = Utils.expandAlphRange([...args[0]]),
|
||||||
ciphertext = Utils.expandAlphRange(args[1]).join("");
|
ciphertext = Utils.expandAlphRange([...args[1]]);
|
||||||
let output = "",
|
let output = "",
|
||||||
index = -1;
|
index = -1;
|
||||||
|
|
||||||
@@ -53,9 +53,9 @@ class Substitute extends Operation {
|
|||||||
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (const character of input) {
|
||||||
index = plaintext.indexOf(input[i]);
|
index = plaintext.indexOf(character);
|
||||||
output += index > -1 && index < ciphertext.length ? ciphertext[index] : input[i];
|
output += index > -1 && index < ciphertext.length ? ciphertext[index] : character;
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
|
|||||||
@@ -65,6 +65,10 @@ class ToBase45 extends Operation {
|
|||||||
|
|
||||||
if (chars < 2) {
|
if (chars < 2) {
|
||||||
res.push("0");
|
res.push("0");
|
||||||
|
chars++;
|
||||||
|
}
|
||||||
|
if (pair.length > 1 && chars < 3) {
|
||||||
|
res.push("0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class ToHex extends Operation {
|
|||||||
* @returns {Object[]} pos
|
* @returns {Object[]} pos
|
||||||
*/
|
*/
|
||||||
highlight(pos, args) {
|
highlight(pos, args) {
|
||||||
let delim, commaLen;
|
let delim, commaLen = 0;
|
||||||
if (args[0] === "0x with comma") {
|
if (args[0] === "0x with comma") {
|
||||||
delim = "0x";
|
delim = "0x";
|
||||||
commaLen = 1;
|
commaLen = 1;
|
||||||
@@ -86,7 +86,7 @@ class ToHex extends Operation {
|
|||||||
pos[0].start = pos[0].start * (2 + len) + countLF(pos[0].start);
|
pos[0].start = pos[0].start * (2 + len) + countLF(pos[0].start);
|
||||||
pos[0].end = pos[0].end * (2 + len) + countLF(pos[0].end);
|
pos[0].end = pos[0].end * (2 + len) + countLF(pos[0].end);
|
||||||
|
|
||||||
// if the deliminators are not prepended, trim the trailing deliminator
|
// if the delimiters are not prepended, trim the trailing delimiter
|
||||||
if (!(delim === "0x" || delim === "\\x")) {
|
if (!(delim === "0x" || delim === "\\x")) {
|
||||||
pos[0].end -= delim.length;
|
pos[0].end -= delim.length;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class App {
|
|||||||
this.populateOperationsList();
|
this.populateOperationsList();
|
||||||
this.manager.setup();
|
this.manager.setup();
|
||||||
this.manager.output.saveBombe();
|
this.manager.output.saveBombe();
|
||||||
this.resetLayout();
|
this.adjustComponentSizes();
|
||||||
this.setCompileMessage();
|
this.setCompileMessage();
|
||||||
|
|
||||||
log.debug("App loaded");
|
log.debug("App loaded");
|
||||||
@@ -295,9 +295,7 @@ class App {
|
|||||||
gutterSize: 4,
|
gutterSize: 4,
|
||||||
expandToMin: true,
|
expandToMin: true,
|
||||||
onDrag: debounce(function() {
|
onDrag: debounce(function() {
|
||||||
this.manager.recipe.adjustWidth();
|
this.adjustComponentSizes();
|
||||||
this.manager.input.calcMaxTabs();
|
|
||||||
this.manager.output.calcMaxTabs();
|
|
||||||
}, 50, "dragSplitter", this, [])
|
}, 50, "dragSplitter", this, [])
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -307,7 +305,7 @@ class App {
|
|||||||
minSize: minimise ? [0, 0] : [100, 100]
|
minSize: minimise ? [0, 0] : [100, 100]
|
||||||
});
|
});
|
||||||
|
|
||||||
this.resetLayout();
|
this.adjustComponentSizes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -581,6 +579,13 @@ class App {
|
|||||||
resetLayout() {
|
resetLayout() {
|
||||||
this.columnSplitter.setSizes([20, 30, 50]);
|
this.columnSplitter.setSizes([20, 30, 50]);
|
||||||
this.ioSplitter.setSizes([50, 50]);
|
this.ioSplitter.setSizes([50, 50]);
|
||||||
|
this.adjustComponentSizes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjust components to fit their containers.
|
||||||
|
*/
|
||||||
|
adjustComponentSizes() {
|
||||||
this.manager.recipe.adjustWidth();
|
this.manager.recipe.adjustWidth();
|
||||||
this.manager.input.calcMaxTabs();
|
this.manager.input.calcMaxTabs();
|
||||||
this.manager.output.calcMaxTabs();
|
this.manager.output.calcMaxTabs();
|
||||||
|
|||||||
@@ -176,7 +176,7 @@
|
|||||||
<div id="recipe" class="split split-horizontal no-select">
|
<div id="recipe" class="split split-horizontal no-select">
|
||||||
<div class="title no-select">
|
<div class="title no-select">
|
||||||
Recipe
|
Recipe
|
||||||
<span class="float-right">
|
<span class="pane-controls hide-on-maximised-output">
|
||||||
<button type="button" class="btn btn-primary bmd-btn-icon" id="save" data-toggle="tooltip" title="Save recipe">
|
<button type="button" class="btn btn-primary bmd-btn-icon" id="save" data-toggle="tooltip" title="Save recipe">
|
||||||
<i class="material-icons">save</i>
|
<i class="material-icons">save</i>
|
||||||
</button>
|
</button>
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul id="rec-list" class="list-area no-select"></ul>
|
<ul id="rec-list" class="list-area no-select"></ul>
|
||||||
|
|
||||||
<div id="controls" class="no-select">
|
<div id="controls" class="no-select hide-on-maximised-output">
|
||||||
<div id="controls-content" class="d-flex align-items-center">
|
<div id="controls-content" class="d-flex align-items-center">
|
||||||
<button type="button" class="mx-2 btn btn-lg btn-secondary" id="step" data-toggle="tooltip" title="Step through the recipe">
|
<button type="button" class="mx-2 btn btn-lg btn-secondary" id="step" data-toggle="tooltip" title="Step through the recipe">
|
||||||
Step
|
Step
|
||||||
@@ -217,7 +217,10 @@
|
|||||||
<div id="input" class="split no-select">
|
<div id="input" class="split no-select">
|
||||||
<div class="title no-select">
|
<div class="title no-select">
|
||||||
<label for="input-text">Input</label>
|
<label for="input-text">Input</label>
|
||||||
<span class="float-right">
|
<span class="pane-controls">
|
||||||
|
<div class="io-info" id="input-files-info"></div>
|
||||||
|
<div class="io-info" id="input-selection-info"></div>
|
||||||
|
<div class="io-info" id="input-info"></div>
|
||||||
<button type="button" class="btn btn-primary bmd-btn-icon" id="btn-new-tab" data-toggle="tooltip" title="Add a new input tab">
|
<button type="button" class="btn btn-primary bmd-btn-icon" id="btn-new-tab" data-toggle="tooltip" title="Add a new input tab">
|
||||||
<i class="material-icons">add</i>
|
<i class="material-icons">add</i>
|
||||||
</button>
|
</button>
|
||||||
@@ -236,9 +239,7 @@
|
|||||||
<i class="material-icons">view_compact</i>
|
<i class="material-icons">view_compact</i>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<div class="io-info" id="input-files-info"></div>
|
|
||||||
<div class="io-info" id="input-info"></div>
|
|
||||||
<div class="io-info" id="input-selection-info"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="input-tabs-wrapper" style="display: none;" class="no-select">
|
<div id="input-tabs-wrapper" style="display: none;" class="no-select">
|
||||||
<span id="btn-previous-input-tab" class="input-tab-buttons">
|
<span id="btn-previous-input-tab" class="input-tab-buttons">
|
||||||
@@ -288,7 +289,10 @@
|
|||||||
<div id="output" class="split">
|
<div id="output" class="split">
|
||||||
<div class="title no-select">
|
<div class="title no-select">
|
||||||
<label for="output-text">Output</label>
|
<label for="output-text">Output</label>
|
||||||
<span class="float-right">
|
<span class="pane-controls">
|
||||||
|
<div class="io-info" id="bake-info"></div>
|
||||||
|
<div class="io-info" id="output-selection-info"></div>
|
||||||
|
<div class="io-info" id="output-info"></div>
|
||||||
<button type="button" class="btn btn-primary bmd-btn-icon" id="save-all-to-file" data-toggle="tooltip" title="Save all outputs to a zip file" style="display: none">
|
<button type="button" class="btn btn-primary bmd-btn-icon" id="save-all-to-file" data-toggle="tooltip" title="Save all outputs to a zip file" style="display: none">
|
||||||
<i class="material-icons">archive</i>
|
<i class="material-icons">archive</i>
|
||||||
</button>
|
</button>
|
||||||
@@ -308,9 +312,7 @@
|
|||||||
<i class="material-icons">fullscreen</i>
|
<i class="material-icons">fullscreen</i>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
<div class="io-info" id="bake-info"></div>
|
|
||||||
<div class="io-info" id="output-info"></div>
|
|
||||||
<div class="io-info" id="output-selection-info"></div>
|
|
||||||
<button type="button" class="btn btn-primary bmd-btn-icon hidden" id="magic" data-toggle="tooltip" title="Magic!" data-html="true">
|
<button type="button" class="btn btn-primary bmd-btn-icon hidden" id="magic" data-toggle="tooltip" title="Magic!" data-html="true">
|
||||||
<svg width="22" height="22" viewBox="0 0 24 24">
|
<svg width="22" height="22" viewBox="0 0 24 24">
|
||||||
<path d="M7.5,5.6L5,7L6.4,4.5L5,2L7.5,3.4L10,2L8.6,4.5L10,7L7.5,5.6M19.5,15.4L22,14L20.6,16.5L22,19L19.5,17.6L17,19L18.4,16.5L17,14L19.5,15.4M22,2L20.6,4.5L22,7L19.5,5.6L17,7L18.4,4.5L17,2L19.5,3.4L22,2M13.34,12.78L15.78,10.34L13.66,8.22L11.22,10.66L13.34,12.78M14.37,7.29L16.71,9.63C17.1,10 17.1,10.65 16.71,11.04L5.04,22.71C4.65,23.1 4,23.1 3.63,22.71L1.29,20.37C0.9,20 0.9,19.35 1.29,18.96L12.96,7.29C13.35,6.9 14,6.9 14.37,7.29Z" />
|
<path d="M7.5,5.6L5,7L6.4,4.5L5,2L7.5,3.4L10,2L8.6,4.5L10,7L7.5,5.6M19.5,15.4L22,14L20.6,16.5L22,19L19.5,17.6L17,19L18.4,16.5L17,14L19.5,15.4M22,2L20.6,4.5L22,7L19.5,5.6L17,7L18.4,4.5L17,2L19.5,3.4L22,2M13.34,12.78L15.78,10.34L13.66,8.22L11.22,10.66L13.34,12.78M14.37,7.29L16.71,9.63C17.1,10 17.1,10.65 16.71,11.04L5.04,22.71C4.65,23.1 4,23.1 3.63,22.71L1.29,20.37C0.9,20 0.9,19.35 1.29,18.96L12.96,7.29C13.35,6.9 14,6.9 14.37,7.29Z" />
|
||||||
|
|||||||
@@ -24,9 +24,16 @@
|
|||||||
line-height: calc(var(--title-height) - 14px);
|
line-height: calc(var(--title-height) - 14px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.title>span,
|
.pane-controls {
|
||||||
.title>.btn {
|
position: absolute;
|
||||||
margin-top: -4px;
|
right: 8px;
|
||||||
|
top: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pane-controls .btn {
|
||||||
|
margin-left: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-area {
|
.list-area {
|
||||||
@@ -107,4 +114,4 @@
|
|||||||
|
|
||||||
#files .card-header .float-right a:hover {
|
#files .card-header .float-right a:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,10 @@
|
|||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.output-maximised .hide-on-maximised-output {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
.spin {
|
.spin {
|
||||||
animation-name: spin;
|
animation-name: spin;
|
||||||
animation-duration: 3s;
|
animation-duration: 3s;
|
||||||
|
|||||||
@@ -280,9 +280,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.io-info {
|
.io-info {
|
||||||
margin-right: 20px;
|
margin-right: 18px;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
float: right;
|
|
||||||
height: 30px;
|
height: 30px;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
line-height: 12px;
|
line-height: 12px;
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ div#output {
|
|||||||
|
|
||||||
.split {
|
.split {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
/* overflow: auto;
|
/* overflow: auto; */
|
||||||
Removed to enable Background Magic button pulse to overflow.
|
/* Removed to enable Background Magic button pulse to overflow.
|
||||||
Replace this rule if it seems to be causing problems. */
|
Replace this rule if it seems to be causing problems. */
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,11 +109,15 @@ class OperationsWaiter {
|
|||||||
const matchedOps = [];
|
const matchedOps = [];
|
||||||
const matchedDescs = [];
|
const matchedDescs = [];
|
||||||
|
|
||||||
|
// Create version with no whitespace for the fuzzy match
|
||||||
|
// Helps avoid missing matches e.g. query "TCP " would not find "Parse TCP"
|
||||||
|
const inStrNWS = inStr.replace(/\s/g, "");
|
||||||
|
|
||||||
for (const opName in this.app.operations) {
|
for (const opName in this.app.operations) {
|
||||||
const op = this.app.operations[opName];
|
const op = this.app.operations[opName];
|
||||||
|
|
||||||
// Match op name using fuzzy match
|
// Match op name using fuzzy match
|
||||||
const [nameMatch, score, idxs] = fuzzyMatch(inStr, opName);
|
const [nameMatch, score, idxs] = fuzzyMatch(inStrNWS, opName);
|
||||||
|
|
||||||
// Match description based on exact match
|
// Match description based on exact match
|
||||||
const descPos = op.description.toLowerCase().indexOf(inStr.toLowerCase());
|
const descPos = op.description.toLowerCase().indexOf(inStr.toLowerCase());
|
||||||
|
|||||||
@@ -1373,6 +1373,7 @@ class OutputWaiter {
|
|||||||
const el = e.target.id === "maximise-output" ? e.target : e.target.parentNode;
|
const el = e.target.id === "maximise-output" ? e.target : e.target.parentNode;
|
||||||
|
|
||||||
if (el.getAttribute("data-original-title").indexOf("Maximise") === 0) {
|
if (el.getAttribute("data-original-title").indexOf("Maximise") === 0) {
|
||||||
|
document.body.classList.add("output-maximised");
|
||||||
this.app.initialiseSplitter(true);
|
this.app.initialiseSplitter(true);
|
||||||
this.app.columnSplitter.collapse(0);
|
this.app.columnSplitter.collapse(0);
|
||||||
this.app.columnSplitter.collapse(1);
|
this.app.columnSplitter.collapse(1);
|
||||||
@@ -1381,6 +1382,7 @@ class OutputWaiter {
|
|||||||
$(el).attr("data-original-title", "Restore output pane");
|
$(el).attr("data-original-title", "Restore output pane");
|
||||||
el.querySelector("i").innerHTML = "fullscreen_exit";
|
el.querySelector("i").innerHTML = "fullscreen_exit";
|
||||||
} else {
|
} else {
|
||||||
|
document.body.classList.remove("output-maximised");
|
||||||
$(el).attr("data-original-title", "Maximise output pane");
|
$(el).attr("data-original-title", "Maximise output pane");
|
||||||
el.querySelector("i").innerHTML = "fullscreen";
|
el.querySelector("i").innerHTML = "fullscreen";
|
||||||
this.app.initialiseSplitter(false);
|
this.app.initialiseSplitter(false);
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ class WindowWaiter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for window resize events.
|
* Handler for window resize events.
|
||||||
* Resets the layout of CyberChef's panes after 200ms (so that continuous resizing doesn't cause
|
* Resets adjustable component sizes after 200ms (so that continuous resizing doesn't cause
|
||||||
* continuous resetting).
|
* continuous resetting).
|
||||||
*/
|
*/
|
||||||
windowResize() {
|
windowResize() {
|
||||||
debounce(this.app.resetLayout, 200, "windowResize", this.app, [])();
|
debounce(this.app.adjustComponentSizes, 200, "windowResize", this.app, [])();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@ import "./tests/Protobuf.mjs";
|
|||||||
import "./tests/ParseSSHHostKey.mjs";
|
import "./tests/ParseSSHHostKey.mjs";
|
||||||
import "./tests/DefangIP.mjs";
|
import "./tests/DefangIP.mjs";
|
||||||
import "./tests/ParseUDP.mjs";
|
import "./tests/ParseUDP.mjs";
|
||||||
|
import "./tests/ParseTCP.mjs";
|
||||||
import "./tests/AvroToJSON.mjs";
|
import "./tests/AvroToJSON.mjs";
|
||||||
import "./tests/Lorenz.mjs";
|
import "./tests/Lorenz.mjs";
|
||||||
import "./tests/LuhnChecksum.mjs";
|
import "./tests/LuhnChecksum.mjs";
|
||||||
|
|||||||
44
tests/operations/tests/ParseTCP.mjs
Normal file
44
tests/operations/tests/ParseTCP.mjs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Parse TCP tests.
|
||||||
|
*
|
||||||
|
* @author n1474335
|
||||||
|
* @copyright Crown Copyright 2022
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
import TestRegister from "../../lib/TestRegister.mjs";
|
||||||
|
|
||||||
|
TestRegister.addTests([
|
||||||
|
{
|
||||||
|
name: "Parse TCP: No options",
|
||||||
|
input: "c2eb0050a138132e70dc9fb9501804025ea70000",
|
||||||
|
expectedMatch: /1026 \(Scaled: 1026\)/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Parse TCP",
|
||||||
|
args: ["Hex"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parse TCP: Options",
|
||||||
|
input: "c2eb0050a1380c1f000000008002faf080950000020405b40103030801010402",
|
||||||
|
expectedMatch: /1460/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Parse TCP",
|
||||||
|
args: ["Hex"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Parse TCP: Timestamps",
|
||||||
|
input: "9e90e11574d57b2c00000000a002ffffe5740000020405b40402080aa4e8c8f50000000001030308",
|
||||||
|
expectedMatch: /2766719221/,
|
||||||
|
recipeConfig: [
|
||||||
|
{
|
||||||
|
op: "Parse TCP",
|
||||||
|
args: ["Hex"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]);
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
* Parse UDP tests.
|
* Parse UDP tests.
|
||||||
*
|
*
|
||||||
* @author h345983745
|
* @author h345983745
|
||||||
*
|
|
||||||
* @copyright Crown Copyright 2019
|
* @copyright Crown Copyright 2019
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -12,15 +11,11 @@ TestRegister.addTests([
|
|||||||
{
|
{
|
||||||
name: "Parse UDP: No Data - JSON",
|
name: "Parse UDP: No Data - JSON",
|
||||||
input: "04 89 00 35 00 2c 01 01",
|
input: "04 89 00 35 00 2c 01 01",
|
||||||
expectedOutput: "{\"Source port\":1161,\"Destination port\":53,\"Length\":44,\"Checksum\":\"0101\"}",
|
expectedOutput: "{\"Source port\":1161,\"Destination port\":53,\"Length\":44,\"Checksum\":\"0x0101\"}",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
|
||||||
op: "From Hex",
|
|
||||||
args: ["Auto"],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
op: "Parse UDP",
|
op: "Parse UDP",
|
||||||
args: [],
|
args: ["Hex"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
op: "JSON Minify",
|
op: "JSON Minify",
|
||||||
@@ -30,15 +25,11 @@ TestRegister.addTests([
|
|||||||
}, {
|
}, {
|
||||||
name: "Parse UDP: With Data - JSON",
|
name: "Parse UDP: With Data - JSON",
|
||||||
input: "04 89 00 35 00 2c 01 01 02 02",
|
input: "04 89 00 35 00 2c 01 01 02 02",
|
||||||
expectedOutput: "{\"Source port\":1161,\"Destination port\":53,\"Length\":44,\"Checksum\":\"0101\",\"Data\":\"0202\"}",
|
expectedOutput: "{\"Source port\":1161,\"Destination port\":53,\"Length\":44,\"Checksum\":\"0x0101\",\"Data\":\"0x0202\"}",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
|
||||||
op: "From Hex",
|
|
||||||
args: ["Auto"],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
op: "Parse UDP",
|
op: "Parse UDP",
|
||||||
args: [],
|
args: ["Hex"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
op: "JSON Minify",
|
op: "JSON Minify",
|
||||||
@@ -51,13 +42,9 @@ TestRegister.addTests([
|
|||||||
input: "04 89 00",
|
input: "04 89 00",
|
||||||
expectedOutput: "Need 8 bytes for a UDP Header",
|
expectedOutput: "Need 8 bytes for a UDP Header",
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
|
||||||
op: "From Hex",
|
|
||||||
args: ["Auto"],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
op: "Parse UDP",
|
op: "Parse UDP",
|
||||||
args: [],
|
args: ["Hex"],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
op: "JSON Minify",
|
op: "JSON Minify",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
|
const { ModifySourcePlugin } = require("modify-source-webpack-plugin");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,6 +83,16 @@ module.exports = {
|
|||||||
to: "assets/forge/"
|
to: "assets/forge/"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}),
|
||||||
|
new ModifySourcePlugin({
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
// Fix toSpare(0) bug in Split.js by avoiding gutter accomodation
|
||||||
|
test: /split\.es\.js$/,
|
||||||
|
modify: (src, path) =>
|
||||||
|
src.replace("if (pixelSize < elementMinSize)", "if (false)")
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
Reference in New Issue
Block a user