cyberchef 10.22.1 → 10.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +131 -0
  2. package/CONTRIBUTING.md +37 -0
  3. package/Dockerfile +2 -0
  4. package/Gruntfile.js +0 -12
  5. package/README.md +1 -1
  6. package/babel.config.js +0 -6
  7. package/package.json +63 -62
  8. package/src/core/Chef.mjs +8 -1
  9. package/src/core/Ingredient.mjs +5 -2
  10. package/src/core/Operation.mjs +6 -1
  11. package/src/core/Recipe.mjs +10 -5
  12. package/src/core/config/Categories.json +18 -3
  13. package/src/core/config/OperationConfig.json +496 -23
  14. package/src/core/config/modules/Ciphers.mjs +6 -0
  15. package/src/core/config/modules/Crypto.mjs +6 -0
  16. package/src/core/config/modules/Default.mjs +6 -0
  17. package/src/core/config/modules/Shellcode.mjs +2 -0
  18. package/src/core/lib/AudioBytes.mjs +103 -0
  19. package/src/core/lib/AudioMetaSchema.mjs +82 -0
  20. package/src/core/lib/AudioParsers.mjs +630 -0
  21. package/src/core/lib/BigIntUtils.mjs +73 -0
  22. package/src/core/lib/Modhex.mjs +2 -0
  23. package/src/core/lib/QRCode.mjs +30 -10
  24. package/src/core/lib/RC6.mjs +625 -0
  25. package/src/core/operations/A1Z26CipherDecode.mjs +1 -1
  26. package/src/core/operations/AddTextToImage.mjs +116 -64
  27. package/src/core/operations/BlurImage.mjs +10 -12
  28. package/src/core/operations/ContainImage.mjs +50 -40
  29. package/src/core/operations/ConvertImageFormat.mjs +33 -39
  30. package/src/core/operations/CoverImage.mjs +39 -37
  31. package/src/core/operations/CropImage.mjs +35 -21
  32. package/src/core/operations/DisassembleARM.mjs +193 -0
  33. package/src/core/operations/DitherImage.mjs +8 -8
  34. package/src/core/operations/EscapeUnicodeCharacters.mjs +0 -17
  35. package/src/core/operations/ExtractAudioMetadata.mjs +175 -0
  36. package/src/core/operations/ExtractLSB.mjs +17 -11
  37. package/src/core/operations/ExtractRGBA.mjs +12 -10
  38. package/src/core/operations/FlaskSessionDecode.mjs +80 -0
  39. package/src/core/operations/FlaskSessionSign.mjs +89 -0
  40. package/src/core/operations/FlaskSessionVerify.mjs +136 -0
  41. package/src/core/operations/FlipImage.mjs +14 -10
  42. package/src/core/operations/GenerateImage.mjs +39 -32
  43. package/src/core/operations/ImageBrightnessContrast.mjs +10 -10
  44. package/src/core/operations/ImageFilter.mjs +14 -13
  45. package/src/core/operations/ImageHueSaturationLightness.mjs +22 -20
  46. package/src/core/operations/ImageOpacity.mjs +6 -8
  47. package/src/core/operations/InvertImage.mjs +4 -6
  48. package/src/core/operations/Jq.mjs +12 -4
  49. package/src/core/operations/NormaliseImage.mjs +5 -7
  50. package/src/core/operations/OffsetChecker.mjs +1 -1
  51. package/src/core/operations/ParseEthernetFrame.mjs +112 -0
  52. package/src/core/operations/ParseIPv4Header.mjs +23 -6
  53. package/src/core/operations/ParseQRCode.mjs +13 -13
  54. package/src/core/operations/PseudoRandomIntegerGenerator.mjs +164 -0
  55. package/src/core/operations/RC6Decrypt.mjs +119 -0
  56. package/src/core/operations/RC6Encrypt.mjs +119 -0
  57. package/src/core/operations/RandomizeColourPalette.mjs +11 -11
  58. package/src/core/operations/ResizeImage.mjs +30 -23
  59. package/src/core/operations/RotateImage.mjs +8 -9
  60. package/src/core/operations/SQLBeautify.mjs +21 -3
  61. package/src/core/operations/SharpenImage.mjs +94 -62
  62. package/src/core/operations/SplitColourChannels.mjs +47 -21
  63. package/src/core/operations/TextIntegerConverter.mjs +123 -0
  64. package/src/core/operations/UnescapeUnicodeCharacters.mjs +17 -0
  65. package/src/core/operations/ViewBitPlane.mjs +16 -20
  66. package/src/core/operations/index.mjs +20 -0
  67. package/src/node/index.mjs +50 -0
  68. package/src/web/HTMLIngredient.mjs +24 -43
  69. package/src/web/Manager.mjs +1 -0
  70. package/src/web/html/index.html +6 -6
  71. package/src/web/static/fonts/bmfonts/Roboto72White.fnt +491 -485
  72. package/src/web/static/fonts/bmfonts/RobotoBlack72White.fnt +494 -488
  73. package/src/web/static/fonts/bmfonts/RobotoMono72White.fnt +110 -103
  74. package/src/web/static/fonts/bmfonts/RobotoSlab72White.fnt +498 -492
  75. package/src/web/stylesheets/layout/_banner.css +30 -0
  76. package/src/web/stylesheets/layout/_modals.css +5 -0
  77. package/src/web/stylesheets/utils/_overrides.css +7 -0
  78. package/src/web/waiters/ControlsWaiter.mjs +82 -0
  79. package/src/web/waiters/InputWaiter.mjs +12 -6
  80. package/src/web/waiters/RecipeWaiter.mjs +2 -2
  81. package/tests/browser/02_ops.js +23 -3
  82. package/tests/node/index.mjs +1 -0
  83. package/tests/node/tests/lib/BigIntUtils.mjs +150 -0
  84. package/tests/node/tests/operations.mjs +9 -7
  85. package/tests/operations/index.mjs +8 -0
  86. package/tests/operations/tests/A1Z26CipherDecode.mjs +33 -0
  87. package/tests/operations/tests/DisassembleARM.mjs +377 -0
  88. package/tests/operations/tests/ExtractAudioMetadata.mjs +287 -0
  89. package/tests/operations/tests/FlaskSession.mjs +246 -0
  90. package/tests/operations/tests/GenerateQRCode.mjs +67 -0
  91. package/tests/operations/tests/JWTSign.mjs +83 -8
  92. package/tests/operations/tests/Jq.mjs +32 -0
  93. package/tests/operations/tests/Modhex.mjs +20 -0
  94. package/tests/operations/tests/ParseEthernetFrame.mjs +45 -0
  95. package/tests/operations/tests/RC6.mjs +487 -0
  96. package/tests/operations/tests/SQLBeautify.mjs +54 -0
  97. package/tests/operations/tests/TextIntegerConverter.mjs +199 -0
  98. package/tests/samples/Audio.mjs +73 -0
  99. package/tests/samples/Images.mjs +0 -12
  100. package/webpack.config.js +10 -7
  101. package/src/core/lib/ImageManipulation.mjs +0 -251
@@ -44,6 +44,7 @@ import EncodeNetBIOSName from "../../operations/EncodeNetBIOSName.mjs";
44
44
  import EscapeString from "../../operations/EscapeString.mjs";
45
45
  import EscapeUnicodeCharacters from "../../operations/EscapeUnicodeCharacters.mjs";
46
46
  import ExpandAlphabetRange from "../../operations/ExpandAlphabetRange.mjs";
47
+ import ExtractAudioMetadata from "../../operations/ExtractAudioMetadata.mjs";
47
48
  import ExtractFiles from "../../operations/ExtractFiles.mjs";
48
49
  import ExtractID3 from "../../operations/ExtractID3.mjs";
49
50
  import FangURL from "../../operations/FangURL.mjs";
@@ -116,6 +117,7 @@ import PLISTViewer from "../../operations/PLISTViewer.mjs";
116
117
  import PadLines from "../../operations/PadLines.mjs";
117
118
  import ParseColourCode from "../../operations/ParseColourCode.mjs";
118
119
  import ParseDateTime from "../../operations/ParseDateTime.mjs";
120
+ import ParseEthernetFrame from "../../operations/ParseEthernetFrame.mjs";
119
121
  import ParseIPRange from "../../operations/ParseIPRange.mjs";
120
122
  import ParseIPv4Header from "../../operations/ParseIPv4Header.mjs";
121
123
  import ParseIPv6Address from "../../operations/ParseIPv6Address.mjs";
@@ -167,6 +169,7 @@ import SymmetricDifference from "../../operations/SymmetricDifference.mjs";
167
169
  import Tail from "../../operations/Tail.mjs";
168
170
  import TakeBytes from "../../operations/TakeBytes.mjs";
169
171
  import TakeNthBytes from "../../operations/TakeNthBytes.mjs";
172
+ import TextIntegerConverter from "../../operations/TextIntegerConverter.mjs";
170
173
  import ToBCD from "../../operations/ToBCD.mjs";
171
174
  import ToBase from "../../operations/ToBase.mjs";
172
175
  import ToBase32 from "../../operations/ToBase32.mjs";
@@ -250,6 +253,7 @@ OpModules.Default = {
250
253
  "Escape string": EscapeString,
251
254
  "Escape Unicode Characters": EscapeUnicodeCharacters,
252
255
  "Expand alphabet range": ExpandAlphabetRange,
256
+ "Extract Audio Metadata": ExtractAudioMetadata,
253
257
  "Extract Files": ExtractFiles,
254
258
  "Extract ID3": ExtractID3,
255
259
  "Fang URL": FangURL,
@@ -322,6 +326,7 @@ OpModules.Default = {
322
326
  "Pad lines": PadLines,
323
327
  "Parse colour code": ParseColourCode,
324
328
  "Parse DateTime": ParseDateTime,
329
+ "Parse Ethernet frame": ParseEthernetFrame,
325
330
  "Parse IP range": ParseIPRange,
326
331
  "Parse IPv4 header": ParseIPv4Header,
327
332
  "Parse IPv6 address": ParseIPv6Address,
@@ -373,6 +378,7 @@ OpModules.Default = {
373
378
  "Tail": Tail,
374
379
  "Take bytes": TakeBytes,
375
380
  "Take nth bytes": TakeNthBytes,
381
+ "Text-Integer Conversion": TextIntegerConverter,
376
382
  "To BCD": ToBCD,
377
383
  "To Base": ToBase,
378
384
  "To Base32": ToBase32,
@@ -5,11 +5,13 @@
5
5
  * @copyright Crown Copyright 2026
6
6
  * @license Apache-2.0
7
7
  */
8
+ import DisassembleARM from "../../operations/DisassembleARM.mjs";
8
9
  import DisassembleX86 from "../../operations/DisassembleX86.mjs";
9
10
 
10
11
  const OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
11
12
 
12
13
  OpModules.Shellcode = {
14
+ "Disassemble ARM": DisassembleARM,
13
15
  "Disassemble x86": DisassembleX86,
14
16
  };
15
17
 
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Byte-reading and text-decoding utilities for audio metadata parsing.
3
+ *
4
+ * @author d0s1nt [d0s1nt@cyberchefaudio]
5
+ * @copyright Crown Copyright 2025
6
+ * @license Apache-2.0
7
+ */
8
+
9
+ /** @returns {string} 4-byte ASCII at offset, or "" if out of bounds. */
10
+ export function ascii4(b, off) {
11
+ if (off + 4 > b.length) return "";
12
+ return String.fromCharCode(b[off], b[off + 1], b[off + 2], b[off + 3]);
13
+ }
14
+
15
+ /** @returns {number} Byte offset of ASCII needle `s`, or -1. */
16
+ export function indexOfAscii(b, s, start, end) {
17
+ const limit = Math.max(0, Math.min(end, b.length) - s.length);
18
+ for (let i = start; i <= limit; i++) {
19
+ let ok = true;
20
+ for (let j = 0; j < s.length; j++) {
21
+ if (b[i + j] !== s.charCodeAt(j)) {
22
+ ok = false;
23
+ break;
24
+ }
25
+ }
26
+ if (ok) return i;
27
+ }
28
+ return -1;
29
+ }
30
+
31
+ /** @returns {number} Unsigned 32-bit big-endian read. */
32
+ export function u32be(bytes, off) {
33
+ return ((bytes[off] << 24) >>> 0) | (bytes[off + 1] << 16) | (bytes[off + 2] << 8) | bytes[off + 3];
34
+ }
35
+
36
+ /** @returns {number} Unsigned 32-bit little-endian read. */
37
+ export function u32le(bytes, off) {
38
+ return (bytes[off] | (bytes[off + 1] << 8) | (bytes[off + 2] << 16) | (bytes[off + 3] << 24)) >>> 0;
39
+ }
40
+
41
+ /** @returns {number} Unsigned 16-bit little-endian read. */
42
+ export function u16le(bytes, off) {
43
+ return bytes[off] | (bytes[off + 1] << 8);
44
+ }
45
+
46
+ /** @returns {BigInt} Unsigned 64-bit little-endian read. */
47
+ export function u64le(bytes, off) {
48
+ return BigInt(u32le(bytes, off)) | (BigInt(u32le(bytes, off + 4)) << 32n);
49
+ }
50
+
51
+ /** @returns {number} Decoded ID3v2 synchsafe integer from four 7-bit bytes. */
52
+ export function synchsafeToInt(b0, b1, b2, b3) {
53
+ return ((b0 & 0x7f) << 21) | ((b1 & 0x7f) << 14) | ((b2 & 0x7f) << 7) | (b3 & 0x7f);
54
+ }
55
+
56
+ /** @returns {string} Decoded UTF-16LE byte range, nulls stripped. */
57
+ export function decodeUtf16LE(b, off, len) {
58
+ if (len <= 0 || off + len > b.length) return "";
59
+ try {
60
+ return new TextDecoder("utf-16le").decode(b.slice(off, off + len)).replace(/\u0000/g, "").trim();
61
+ } catch {
62
+ return "";
63
+ }
64
+ }
65
+
66
+ /** @returns {{valueBytes: Uint8Array, next: number}} Bytes until null terminator, UTF-16 aware. */
67
+ export function readNullTerminated(bytes, start, encoding) {
68
+ const isUtf16 = encoding === 1 || encoding === 2;
69
+ if (!isUtf16) {
70
+ let i = start;
71
+ while (i < bytes.length && bytes[i] !== 0x00) i++;
72
+ return { valueBytes: bytes.slice(start, i), next: i + 1 };
73
+ }
74
+ let i = start;
75
+ while (i + 1 < bytes.length && !(bytes[i] === 0x00 && bytes[i + 1] === 0x00)) i += 2;
76
+ return { valueBytes: bytes.slice(start, i), next: i + 2 };
77
+ }
78
+
79
+ const ID3_ENCODINGS = ["iso-8859-1", "utf-16", "utf-16be", "utf-8"];
80
+
81
+ /** @returns {string} Text decoded using ID3v2 encoding byte (0=latin1, 1=utf16, 2=utf16be, 3=utf8). */
82
+ export function decodeText(bytes, encoding) {
83
+ if (!bytes || bytes.length === 0) return "";
84
+ try {
85
+ return new TextDecoder(ID3_ENCODINGS[encoding] || "utf-16").decode(bytes);
86
+ } catch {
87
+ return safeUtf8(bytes);
88
+ }
89
+ }
90
+
91
+ /** @returns {string} UTF-8 decode with replacement (never throws). */
92
+ export function safeUtf8(bytes) {
93
+ try {
94
+ return new TextDecoder("utf-8", { fatal: false }).decode(bytes);
95
+ } catch {
96
+ return "";
97
+ }
98
+ }
99
+
100
+ /** @returns {string} ISO-8859-1 decode, nulls stripped, trimmed. */
101
+ export function decodeLatin1Trim(bytes) {
102
+ return decodeText(bytes, 0).replace(/\u0000/g, "").trim();
103
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Report skeleton and container detection for audio metadata extraction.
3
+ *
4
+ * @author d0s1nt [d0s1nt@cyberchefaudio]
5
+ * @copyright Crown Copyright 2025
6
+ * @license Apache-2.0
7
+ */
8
+
9
+ /* eslint-disable camelcase */
10
+
11
+ import { ascii4, indexOfAscii } from "./AudioBytes.mjs";
12
+
13
+ /** Builds the empty report skeleton ready for a format parser to populate. */
14
+ export function makeEmptyReport(filename, byteLength, container) {
15
+ return {
16
+ schema_version: "audio-meta-1.0",
17
+ artifact: {
18
+ filename,
19
+ byte_length: byteLength,
20
+ container: { type: container.type, brand: container.brand || null, mime: container.mime || null },
21
+ },
22
+ detections: { metadata_systems: [], provenance_systems: [] },
23
+ tags: {
24
+ common: {
25
+ title: null, artist: null, album: null, date: null, track: null,
26
+ genre: null, comment: null, composer: null, copyright: null, language: null,
27
+ },
28
+ raw: {},
29
+ },
30
+ embedded: [],
31
+ provenance: {
32
+ c2pa: {
33
+ present: false,
34
+ embedding: [],
35
+ manifest_store: { active_manifest_urn: null, instance_id: null, claim_generator: null },
36
+ assertions: [],
37
+ signature: {
38
+ algorithm: null, signing_time: null,
39
+ certificate: { subject_cn: null, issuer_cn: null, serial_number: null },
40
+ },
41
+ validation: { validation_state: "Unknown", reasons: [], details_raw: null },
42
+ },
43
+ },
44
+ errors: [],
45
+ };
46
+ }
47
+
48
+ /** Detects the audio container format from magic bytes. */
49
+ export function sniffContainer(b) {
50
+ if (b.length >= 3 && b[0] === 0x49 && b[1] === 0x44 && b[2] === 0x33)
51
+ return { type: "mp3", mime: "audio/mpeg" };
52
+ if (b.length >= 2 && b[0] === 0xff && (b[1] & 0xe0) === 0xe0) {
53
+ if ((b[1] & 0x06) === 0x00) return { type: "aac", mime: "audio/aac" };
54
+ return { type: "mp3", mime: "audio/mpeg" };
55
+ }
56
+ if (b.length >= 8 && b[0] === 0x0b && b[1] === 0x77)
57
+ return { type: "ac3", mime: "audio/ac3" };
58
+ if (b.length >= 16 &&
59
+ b[0] === 0x30 && b[1] === 0x26 && b[2] === 0xb2 && b[3] === 0x75 &&
60
+ b[4] === 0x8e && b[5] === 0x66 && b[6] === 0xcf && b[7] === 0x11)
61
+ return { type: "wma", mime: "audio/x-ms-wma" };
62
+ if (b.length >= 12 && ascii4(b, 0) === "RIFF" && ascii4(b, 8) === "WAVE")
63
+ return { type: "wav", mime: "audio/wav" };
64
+ if (b.length >= 12 && ascii4(b, 0) === "BW64" && ascii4(b, 8) === "WAVE")
65
+ return { type: "bw64", mime: "audio/wav" };
66
+ if (b.length >= 4 && ascii4(b, 0) === "fLaC")
67
+ return { type: "flac", mime: "audio/flac" };
68
+ if (b.length >= 4 && ascii4(b, 0) === "OggS") {
69
+ const idx = indexOfAscii(b, "OpusHead", 0, Math.min(b.length, 65536));
70
+ return idx >= 0 ? { type: "opus", mime: "audio/ogg" } : { type: "ogg", mime: "audio/ogg" };
71
+ }
72
+ if (b.length >= 12 && ascii4(b, 4) === "ftyp") {
73
+ const brand = ascii4(b, 8);
74
+ const isM4A = brand === "M4A " || brand === "M4B " || brand === "M4P ";
75
+ return { type: isM4A ? "m4a" : "mp4", mime: isM4A ? "audio/mp4" : "video/mp4", brand };
76
+ }
77
+ if (b.length >= 12 && ascii4(b, 0) === "FORM") {
78
+ const formType = ascii4(b, 8);
79
+ if (formType === "AIFF" || formType === "AIFC") return { type: "aiff", mime: "audio/aiff", brand: formType };
80
+ }
81
+ return { type: "unknown", mime: null };
82
+ }