cyberchef 9.39.1 → 9.39.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberchef",
3
- "version": "9.39.1",
3
+ "version": "9.39.4",
4
4
  "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
5
5
  "author": "n1474335 <n1474335@gmail.com>",
6
6
  "homepage": "https://gchq.github.io/CyberChef",
@@ -5044,7 +5044,7 @@
5044
5044
  },
5045
5045
  "Extract Files": {
5046
5046
  "module": "Default",
5047
- "description": "Performs file carving to attempt to extract files from the input.<br><br>This operation is currently capable of carving out the following formats:\n <ul>\n <li>\n JPG,JPEG,JPE,THM,MPO</li><li>GIF</li><li>PNG</li><li>BMP</li><li>ICO</li><li>TGA</li><li>FLV</li><li>WAV</li><li>MP3</li><li>PDF</li><li>RTF</li><li>DOCX,XLSX,PPTX</li><li>EPUB</li><li>EXE,DLL,DRV,VXD,SYS,OCX,VBX,COM,FON,SCR</li><li>ELF,BIN,AXF,O,PRX,SO</li><li>DYLIB</li><li>ZIP</li><li>TAR</li><li>GZ</li><li>BZ2</li><li>ZLIB</li><li>XZ</li><li>JAR</li><li>LZOP,LZO</li><li>DEB</li><li>SQLITE</li><li>EVT</li><li>EVTX</li><li>DMP</li><li>PF</li><li>PLIST</li><li>KEYCHAIN</li><li>LNK\n </li>\n </ul>",
5047
+ "description": "Performs file carving to attempt to extract files from the input.<br><br>This operation is currently capable of carving out the following formats:\n <ul>\n <li>\n JPG,JPEG,JPE,THM,MPO</li><li>GIF</li><li>PNG</li><li>WEBP</li><li>BMP</li><li>ICO</li><li>TGA</li><li>FLV</li><li>WAV</li><li>MP3</li><li>PDF</li><li>RTF</li><li>DOCX,XLSX,PPTX</li><li>EPUB</li><li>EXE,DLL,DRV,VXD,SYS,OCX,VBX,COM,FON,SCR</li><li>ELF,BIN,AXF,O,PRX,SO</li><li>DYLIB</li><li>ZIP</li><li>TAR</li><li>GZ</li><li>BZ2</li><li>ZLIB</li><li>XZ</li><li>JAR</li><li>LZOP,LZO</li><li>DEB</li><li>SQLITE</li><li>EVT</li><li>EVTX</li><li>DMP</li><li>PF</li><li>PLIST</li><li>KEYCHAIN</li><li>LNK\n </li>\n </ul>Minimum File Size can be used to prune small false positives.",
5048
5048
  "infoURL": "https://forensicswiki.xyz/wiki/index.php?title=File_Carving",
5049
5049
  "inputType": "ArrayBuffer",
5050
5050
  "outputType": "html",
@@ -5090,6 +5090,11 @@
5090
5090
  "name": "Ignore failed extractions",
5091
5091
  "type": "boolean",
5092
5092
  "value": true
5093
+ },
5094
+ {
5095
+ "name": "Minimum File Size",
5096
+ "type": "number",
5097
+ "value": 100
5093
5098
  }
5094
5099
  ]
5095
5100
  },
@@ -8335,13 +8340,19 @@
8335
8340
  },
8336
8341
  "Merge": {
8337
8342
  "module": "Default",
8338
- "description": "Consolidate all branches back into a single trunk. The opposite of Fork.",
8343
+ "description": "Consolidate all branches back into a single trunk. The opposite of Fork. Unticking the Merge All checkbox will only consolidate all branches up to the nearest Fork/Subsection.",
8339
8344
  "infoURL": null,
8340
8345
  "inputType": "string",
8341
8346
  "outputType": "string",
8342
8347
  "flowControl": true,
8343
8348
  "manualBake": false,
8344
- "args": []
8349
+ "args": [
8350
+ {
8351
+ "name": "Merge All",
8352
+ "type": "boolean",
8353
+ "value": true
8354
+ }
8355
+ ]
8345
8356
  },
8346
8357
  "Microsoft Script Decoder": {
8347
8358
  "module": "Default",
@@ -70,7 +70,7 @@ export const FILE_SIGNATURES = {
70
70
  10: 0x42,
71
71
  11: 0x50
72
72
  },
73
- extractor: null
73
+ extractor: extractWEBP
74
74
  },
75
75
  {
76
76
  name: "Camera Image File Format",
@@ -3032,6 +3032,30 @@ export function extractPNG(bytes, offset) {
3032
3032
  }
3033
3033
 
3034
3034
 
3035
+ /**
3036
+ * WEBP extractor.
3037
+ *
3038
+ * @param {Uint8Array} bytes
3039
+ * @param {number} offset
3040
+ * @returns {Uint8Array}
3041
+ */
3042
+ export function extractWEBP(bytes, offset) {
3043
+ const stream = new Stream(bytes.slice(offset));
3044
+
3045
+ // Move to file size offset.
3046
+ stream.moveForwardsBy(4);
3047
+
3048
+ // Read file size field.
3049
+ const fileSize = stream.readInt(4, "le");
3050
+
3051
+ // Move to end of file.
3052
+ // There is no need to minus 8 from the size as the size factors in the offset.
3053
+ stream.moveForwardsBy(fileSize);
3054
+
3055
+ return stream.carve();
3056
+ }
3057
+
3058
+
3035
3059
  /**
3036
3060
  * BMP extractor.
3037
3061
  *
@@ -38,7 +38,7 @@ class ExtractFiles extends Operation {
38
38
  <li>
39
39
  ${supportedExts.join("</li><li>")}
40
40
  </li>
41
- </ul>`;
41
+ </ul>Minimum File Size can be used to prune small false positives.`;
42
42
  this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=File_Carving";
43
43
  this.inputType = "ArrayBuffer";
44
44
  this.outputType = "List<File>";
@@ -54,6 +54,11 @@ class ExtractFiles extends Operation {
54
54
  name: "Ignore failed extractions",
55
55
  type: "boolean",
56
56
  value: true
57
+ },
58
+ {
59
+ name: "Minimum File Size",
60
+ type: "number",
61
+ value: 100
57
62
  }
58
63
  ]);
59
64
  }
@@ -66,6 +71,7 @@ class ExtractFiles extends Operation {
66
71
  run(input, args) {
67
72
  const bytes = new Uint8Array(input),
68
73
  categories = [],
74
+ minSize = args.pop(1),
69
75
  ignoreFailedExtractions = args.pop(1);
70
76
 
71
77
  args.forEach((cat, i) => {
@@ -80,7 +86,9 @@ class ExtractFiles extends Operation {
80
86
  const errors = [];
81
87
  detectedFiles.forEach(detectedFile => {
82
88
  try {
83
- files.push(extractFile(bytes, detectedFile.fileDetails, detectedFile.offset));
89
+ const file = extractFile(bytes, detectedFile.fileDetails, detectedFile.offset);
90
+ if (file.size >= minSize)
91
+ files.push(file);
84
92
  } catch (err) {
85
93
  if (!ignoreFailedExtractions && err.message.indexOf("No extraction algorithm available") < 0) {
86
94
  errors.push(
@@ -65,12 +65,21 @@ class Fork extends Operation {
65
65
  if (input)
66
66
  inputs = input.split(splitDelim);
67
67
 
68
+ // Set to 1 as if we are here, then there is one, the current one.
69
+ let numOp = 1;
68
70
  // Create subOpList for each tranche to operate on
69
- // (all remaining operations unless we encounter a Merge)
71
+ // all remaining operations unless we encounter a Merge
70
72
  for (i = state.progress + 1; i < opList.length; i++) {
71
73
  if (opList[i].name === "Merge" && !opList[i].disabled) {
72
- break;
74
+ numOp--;
75
+ if (numOp === 0 || opList[i].ingValues[0])
76
+ break;
77
+ else
78
+ // Not this Fork's Merge.
79
+ subOpList.push(opList[i]);
73
80
  } else {
81
+ if (opList[i].name === "Fork" || opList[i].name === "Subsection")
82
+ numOp++;
74
83
  subOpList.push(opList[i]);
75
84
  }
76
85
  }
@@ -20,10 +20,16 @@ class Merge extends Operation {
20
20
  this.name = "Merge";
21
21
  this.flowControl = true;
22
22
  this.module = "Default";
23
- this.description = "Consolidate all branches back into a single trunk. The opposite of Fork.";
23
+ this.description = "Consolidate all branches back into a single trunk. The opposite of Fork. Unticking the Merge All checkbox will only consolidate all branches up to the nearest Fork/Subsection.";
24
24
  this.inputType = "string";
25
25
  this.outputType = "string";
26
- this.args = [];
26
+ this.args = [
27
+ {
28
+ name: "Merge All",
29
+ type: "boolean",
30
+ value: true,
31
+ }
32
+ ];
27
33
  }
28
34
 
29
35
  /**
@@ -67,12 +67,21 @@ class Subsection extends Operation {
67
67
  subOpList = [];
68
68
 
69
69
  if (input && section !== "") {
70
+ // Set to 1 as if we are here, then there is one, the current one.
71
+ let numOp = 1;
70
72
  // Create subOpList for each tranche to operate on
71
73
  // all remaining operations unless we encounter a Merge
72
74
  for (let i = state.progress + 1; i < opList.length; i++) {
73
75
  if (opList[i].name === "Merge" && !opList[i].disabled) {
74
- break;
76
+ numOp--;
77
+ if (numOp === 0 || opList[i].ingValues[0])
78
+ break;
79
+ else
80
+ // Not this subsection's Merge.
81
+ subOpList.push(opList[i]);
75
82
  } else {
83
+ if (opList[i].name === "Fork" || opList[i].name === "Subsection")
84
+ numOp++;
76
85
  subOpList.push(opList[i]);
77
86
  }
78
87
  }
@@ -186,7 +186,7 @@ div.toggle-string {
186
186
  }
187
187
 
188
188
  .ingredients .dropdown-toggle-split {
189
- height: 41px !important;
189
+ height: 40px !important;
190
190
  }
191
191
 
192
192
  .boolean-arg {
@@ -114,6 +114,7 @@ import "./tests/HASSH.mjs";
114
114
  import "./tests/GetAllCasings.mjs";
115
115
  import "./tests/SIGABA.mjs";
116
116
  import "./tests/ELFInfo.mjs";
117
+ import "./tests/Subsection.mjs";
117
118
 
118
119
 
119
120
  // Cannot test operations that use the File type yet
@@ -31,7 +31,7 @@ TestRegister.addTests([
31
31
  },
32
32
  {
33
33
  op: "Merge",
34
- args: [],
34
+ args: [true],
35
35
  },
36
36
  ],
37
37
  },
@@ -50,7 +50,7 @@ TestRegister.addTests([
50
50
  },
51
51
  {
52
52
  op: "Merge",
53
- args: [],
53
+ args: [true],
54
54
  },
55
55
  ],
56
56
  },
@@ -66,5 +66,16 @@ TestRegister.addTests([
66
66
  {"op": "Label", "args": ["skipReturn"]},
67
67
  {"op": "To Base64", "args": ["A-Za-z0-9+/="]}
68
68
  ]
69
- }
69
+ },
70
+ {
71
+ name: "Fork, Partial Merge",
72
+ input: "Hello World",
73
+ expectedOutput: "48656c6c6f 576f726c64",
74
+ recipeConfig: [
75
+ { "op": "Fork", "args": [" ", " ", false] },
76
+ { "op": "Fork", "args": ["l", "l", false] },
77
+ { "op": "Merge", "args": [false] },
78
+ { "op": "To Hex", "args": ["None", 0] },
79
+ ]
80
+ },
70
81
  ]);
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Subsection Tests.
3
+ *
4
+ * @author n1073645 [n1073645@gmail.com]
5
+ * @copyright Crown Copyright 2022
6
+ * @license Apache-2.0
7
+ */
8
+ import TestRegister from "../../lib/TestRegister.mjs";
9
+
10
+ TestRegister.addTests([
11
+ {
12
+ name: "Subsection: nothing",
13
+ input: "",
14
+ expectedOutput: "",
15
+ recipeConfig: [
16
+ {
17
+ "op": "Subsection",
18
+ "args": ["", true, true, false],
19
+ },
20
+ ],
21
+ },
22
+ {
23
+ name: "Subsection, Full Merge: nothing",
24
+ input: "",
25
+ expectedOutput: "",
26
+ recipeConfig: [
27
+ {
28
+ "op": "Subsection",
29
+ "args": ["", true, true, false],
30
+ },
31
+ {
32
+ "op": "Merge",
33
+ "args": [true],
34
+ },
35
+ ],
36
+ },
37
+ {
38
+ name: "Subsection, Partial Merge: nothing",
39
+ input: "",
40
+ expectedOutput: "",
41
+ recipeConfig: [
42
+ {
43
+ "op": "Subsection",
44
+ "args": ["", true, true, false],
45
+ },
46
+ {
47
+ "op": "Merge",
48
+ "args": [false],
49
+ },
50
+ ],
51
+ },
52
+ {
53
+ name: "Subsection, Full Merge: Base64 with Hex",
54
+ input: "SGVsbG38675629ybGQ=",
55
+ expectedOutput: "Hello World",
56
+ recipeConfig: [
57
+ {
58
+ "op": "Subsection",
59
+ "args": ["386756", true, true, false],
60
+ },
61
+ {
62
+ "op": "From Hex",
63
+ "args": ["Auto"],
64
+ },
65
+ {
66
+ "op": "Merge",
67
+ "args": [true],
68
+ },
69
+ {
70
+ "op": "From Base64",
71
+ "args": ["A-Za-z0-9+/=", true, false],
72
+ },
73
+ ],
74
+ },
75
+ {
76
+ name: "Subsection, Partial Merge: Base64 with Hex surrounded by binary data.",
77
+ input: "000000000SGVsbG38675629ybGQ=0000000000",
78
+ expectedOutput: "000000000Hello World0000000000",
79
+ recipeConfig: [
80
+ {
81
+ "op": "Subsection",
82
+ "args": ["SGVsbG38675629ybGQ=", true, true, false],
83
+ },
84
+ {
85
+ "op": "Subsection",
86
+ "args": ["386756", true, true, false],
87
+ },
88
+ {
89
+ "op": "From Hex",
90
+ "args": ["Auto"],
91
+ },
92
+ {
93
+ "op": "Merge",
94
+ "args": [false],
95
+ },
96
+ {
97
+ "op": "From Base64",
98
+ "args": ["A-Za-z0-9+/=", true, false],
99
+ },
100
+ ],
101
+ },
102
+ ]);