cyberchef 9.37.0 → 9.37.3

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/nightwatch.json CHANGED
@@ -10,11 +10,12 @@
10
10
  "start_process": true,
11
11
  "server_path": "./node_modules/.bin/chromedriver",
12
12
  "port": 9515,
13
- "log_path": false
13
+ "log_path": "tests/browser/output"
14
14
  },
15
15
  "desiredCapabilities": {
16
16
  "browserName": "chrome"
17
- }
17
+ },
18
+ "enable_fail_fast": true
18
19
  },
19
20
 
20
21
  "dev": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cyberchef",
3
- "version": "9.37.0",
3
+ "version": "9.37.3",
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",
@@ -723,8 +723,8 @@ class Utils {
723
723
  }
724
724
 
725
725
  if (removeScriptAndStyle) {
726
- htmlStr = recursiveRemove(/<script[^>]*>.*?<\/script>/gi, htmlStr);
727
- htmlStr = recursiveRemove(/<style[^>]*>.*?<\/style>/gi, htmlStr);
726
+ htmlStr = recursiveRemove(/<script[^>]*>.*?<\/script[^>]*>/gi, htmlStr);
727
+ htmlStr = recursiveRemove(/<style[^>]*>.*?<\/style[^>]*>/gi, htmlStr);
728
728
  }
729
729
  return htmlStr.replace(/<[^>]+>/g, "");
730
730
  }
@@ -4946,7 +4946,17 @@
4946
4946
  {
4947
4947
  "name": "Display total",
4948
4948
  "type": "boolean",
4949
- "value": true
4949
+ "value": false
4950
+ },
4951
+ {
4952
+ "name": "Sort",
4953
+ "type": "boolean",
4954
+ "value": false
4955
+ },
4956
+ {
4957
+ "name": "Unique",
4958
+ "type": "boolean",
4959
+ "value": false
4950
4960
  }
4951
4961
  ]
4952
4962
  },
@@ -4973,6 +4983,16 @@
4973
4983
  "name": "Display total",
4974
4984
  "type": "boolean",
4975
4985
  "value": false
4986
+ },
4987
+ {
4988
+ "name": "Sort",
4989
+ "type": "boolean",
4990
+ "value": false
4991
+ },
4992
+ {
4993
+ "name": "Unique",
4994
+ "type": "boolean",
4995
+ "value": false
4976
4996
  }
4977
4997
  ]
4978
4998
  },
@@ -4999,6 +5019,16 @@
4999
5019
  "name": "Display total",
5000
5020
  "type": "boolean",
5001
5021
  "value": false
5022
+ },
5023
+ {
5024
+ "name": "Sort",
5025
+ "type": "boolean",
5026
+ "value": false
5027
+ },
5028
+ {
5029
+ "name": "Unique",
5030
+ "type": "boolean",
5031
+ "value": false
5002
5032
  }
5003
5033
  ]
5004
5034
  },
@@ -5091,6 +5121,16 @@
5091
5121
  "name": "Display total",
5092
5122
  "type": "boolean",
5093
5123
  "value": false
5124
+ },
5125
+ {
5126
+ "name": "Sort",
5127
+ "type": "boolean",
5128
+ "value": false
5129
+ },
5130
+ {
5131
+ "name": "Unique",
5132
+ "type": "boolean",
5133
+ "value": false
5094
5134
  }
5095
5135
  ]
5096
5136
  },
@@ -5174,6 +5214,16 @@
5174
5214
  "name": "Display total",
5175
5215
  "type": "boolean",
5176
5216
  "value": false
5217
+ },
5218
+ {
5219
+ "name": "Sort",
5220
+ "type": "boolean",
5221
+ "value": false
5222
+ },
5223
+ {
5224
+ "name": "Unique",
5225
+ "type": "boolean",
5226
+ "value": false
5177
5227
  }
5178
5228
  ]
5179
5229
  },
@@ -5228,6 +5278,16 @@
5228
5278
  "name": "Display total",
5229
5279
  "type": "boolean",
5230
5280
  "value": false
5281
+ },
5282
+ {
5283
+ "name": "Sort",
5284
+ "type": "boolean",
5285
+ "value": false
5286
+ },
5287
+ {
5288
+ "name": "Unique",
5289
+ "type": "boolean",
5290
+ "value": false
5231
5291
  }
5232
5292
  ]
5233
5293
  },
@@ -9875,9 +9935,9 @@
9875
9935
  ]
9876
9936
  },
9877
9937
  {
9878
- "name": "Number of bytes to drop",
9938
+ "name": "Number of dwords to drop",
9879
9939
  "type": "number",
9880
- "value": 768
9940
+ "value": 192
9881
9941
  }
9882
9942
  ]
9883
9943
  },
@@ -12712,6 +12772,16 @@
12712
12772
  "name": "Display total",
12713
12773
  "type": "boolean",
12714
12774
  "value": false
12775
+ },
12776
+ {
12777
+ "name": "Sort",
12778
+ "type": "boolean",
12779
+ "value": false
12780
+ },
12781
+ {
12782
+ "name": "Unique",
12783
+ "type": "boolean",
12784
+ "value": false
12715
12785
  }
12716
12786
  ]
12717
12787
  },
@@ -16039,6 +16109,11 @@
16039
16109
  "Colon",
16040
16110
  "Nothing (separate chars)"
16041
16111
  ]
16112
+ },
16113
+ {
16114
+ "name": "Display count",
16115
+ "type": "boolean",
16116
+ "value": false
16042
16117
  }
16043
16118
  ]
16044
16119
  },
@@ -12,15 +12,15 @@
12
12
  *
13
13
  * @param {string} input
14
14
  * @param {RegExp} searchRegex
15
- * @param {RegExp} removeRegex - A regular expression defining results to remove from the
15
+ * @param {RegExp} [removeRegex=null] - A regular expression defining results to remove from the
16
16
  * final list
17
- * @param {boolean} includeTotal - Whether or not to include the total number of results
17
+ * @param {Function} [sortBy=null] - The sorting comparison function to apply
18
+ * @param {boolean} [unique=false] - Whether to unique the results
18
19
  * @returns {string}
19
20
  */
20
- export function search (input, searchRegex, removeRegex, includeTotal) {
21
- let output = "",
22
- total = 0,
23
- match;
21
+ export function search(input, searchRegex, removeRegex=null, sortBy=null, unique=false) {
22
+ let results = [];
23
+ let match;
24
24
 
25
25
  while ((match = searchRegex.exec(input))) {
26
26
  // Moves pointer when an empty string is matched (prevents infinite loop)
@@ -30,14 +30,19 @@ export function search (input, searchRegex, removeRegex, includeTotal) {
30
30
 
31
31
  if (removeRegex && removeRegex.test(match[0]))
32
32
  continue;
33
- total++;
34
- output += match[0] + "\n";
33
+
34
+ results.push(match[0]);
35
+ }
36
+
37
+ if (sortBy) {
38
+ results = results.sort(sortBy);
35
39
  }
36
40
 
37
- if (includeTotal)
38
- output = "Total found: " + total + "\n\n" + output;
41
+ if (unique) {
42
+ results = results.unique();
43
+ }
39
44
 
40
- return output;
45
+ return results;
41
46
  }
42
47
 
43
48
 
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Sorting functions
3
+ *
4
+ * @author n1474335 [n1474335@gmail.com]
5
+ * @copyright Crown Copyright 2022
6
+ * @license Apache-2.0
7
+ *
8
+ */
9
+
10
+ /**
11
+ * Comparison operation for sorting of strings ignoring case.
12
+ *
13
+ * @param {string} a
14
+ * @param {string} b
15
+ * @returns {number}
16
+ */
17
+ export function caseInsensitiveSort(a, b) {
18
+ return a.toLowerCase().localeCompare(b.toLowerCase());
19
+ }
20
+
21
+
22
+ /**
23
+ * Comparison operation for sorting of IPv4 addresses.
24
+ *
25
+ * @param {string} a
26
+ * @param {string} b
27
+ * @returns {number}
28
+ */
29
+ export function ipSort(a, b) {
30
+ let a_ = a.split("."),
31
+ b_ = b.split(".");
32
+
33
+ a_ = a_[0] * 0x1000000 + a_[1] * 0x10000 + a_[2] * 0x100 + a_[3] * 1;
34
+ b_ = b_[0] * 0x1000000 + b_[1] * 0x10000 + b_[2] * 0x100 + b_[3] * 1;
35
+
36
+ if (isNaN(a_) && !isNaN(b_)) return 1;
37
+ if (!isNaN(a_) && isNaN(b_)) return -1;
38
+ if (isNaN(a_) && isNaN(b_)) return a.localeCompare(b);
39
+
40
+ return a_ - b_;
41
+ }
42
+
43
+ /**
44
+ * Comparison operation for sorting of numeric values.
45
+ *
46
+ * @author Chris van Marle
47
+ * @param {string} a
48
+ * @param {string} b
49
+ * @returns {number}
50
+ */
51
+ export function numericSort(a, b) {
52
+ const a_ = a.split(/([^\d]+)/),
53
+ b_ = b.split(/([^\d]+)/);
54
+
55
+ for (let i = 0; i < a_.length && i < b.length; ++i) {
56
+ if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
57
+ if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
58
+ if (isNaN(a_[i]) && isNaN(b_[i])) {
59
+ const ret = a_[i].localeCompare(b_[i]); // Compare strings
60
+ if (ret !== 0) return ret;
61
+ }
62
+ if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
63
+ if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
64
+ }
65
+ }
66
+
67
+ return a.localeCompare(b);
68
+ }
69
+
70
+ /**
71
+ * Comparison operation for sorting of hexadecimal values.
72
+ *
73
+ * @author Chris van Marle
74
+ * @param {string} a
75
+ * @param {string} b
76
+ * @returns {number}
77
+ */
78
+ export function hexadecimalSort(a, b) {
79
+ let a_ = a.split(/([^\da-f]+)/i),
80
+ b_ = b.split(/([^\da-f]+)/i);
81
+
82
+ a_ = a_.map(v => {
83
+ const t = parseInt(v, 16);
84
+ return isNaN(t) ? v : t;
85
+ });
86
+
87
+ b_ = b_.map(v => {
88
+ const t = parseInt(v, 16);
89
+ return isNaN(t) ? v : t;
90
+ });
91
+
92
+ for (let i = 0; i < a_.length && i < b.length; ++i) {
93
+ if (isNaN(a_[i]) && !isNaN(b_[i])) return 1; // Numbers after non-numbers
94
+ if (!isNaN(a_[i]) && isNaN(b_[i])) return -1;
95
+ if (isNaN(a_[i]) && isNaN(b_[i])) {
96
+ const ret = a_[i].localeCompare(b_[i]); // Compare strings
97
+ if (ret !== 0) return ret;
98
+ }
99
+ if (!isNaN(a_[i]) && !isNaN(b_[i])) { // Compare numbers
100
+ if (a_[i] - b_[i] !== 0) return a_[i] - b_[i];
101
+ }
102
+ }
103
+
104
+ return a.localeCompare(b);
105
+ }
@@ -44,7 +44,13 @@ class ExtractDates extends Operation {
44
44
  date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy
45
45
  regex = new RegExp(date1 + "|" + date2 + "|" + date3, "ig");
46
46
 
47
- return search(input, regex, null, displayTotal);
47
+ const results = search(input, regex);
48
+
49
+ if (displayTotal) {
50
+ return `Total found: ${results.length}\n\n${results.join("\n")}`;
51
+ } else {
52
+ return results.join("\n");
53
+ }
48
54
  }
49
55
 
50
56
  }
@@ -6,6 +6,7 @@
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
8
  import { search, DOMAIN_REGEX } from "../lib/Extract.mjs";
9
+ import { caseInsensitiveSort } from "../lib/Sort.mjs";
9
10
 
10
11
  /**
11
12
  * Extract domains operation
@@ -25,9 +26,19 @@ class ExtractDomains extends Operation {
25
26
  this.outputType = "string";
26
27
  this.args = [
27
28
  {
28
- "name": "Display total",
29
- "type": "boolean",
30
- "value": true
29
+ name: "Display total",
30
+ type: "boolean",
31
+ value: false
32
+ },
33
+ {
34
+ name: "Sort",
35
+ type: "boolean",
36
+ value: false
37
+ },
38
+ {
39
+ name: "Unique",
40
+ type: "boolean",
41
+ value: false
31
42
  }
32
43
  ];
33
44
  }
@@ -38,8 +49,21 @@ class ExtractDomains extends Operation {
38
49
  * @returns {string}
39
50
  */
40
51
  run(input, args) {
41
- const displayTotal = args[0];
42
- return search(input, DOMAIN_REGEX, null, displayTotal);
52
+ const [displayTotal, sort, unique] = args;
53
+
54
+ const results = search(
55
+ input,
56
+ DOMAIN_REGEX,
57
+ null,
58
+ sort ? caseInsensitiveSort : null,
59
+ unique
60
+ );
61
+
62
+ if (displayTotal) {
63
+ return `Total found: ${results.length}\n\n${results.join("\n")}`;
64
+ } else {
65
+ return results.join("\n");
66
+ }
43
67
  }
44
68
 
45
69
  }
@@ -6,6 +6,7 @@
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
8
  import { search } from "../lib/Extract.mjs";
9
+ import { caseInsensitiveSort } from "../lib/Sort.mjs";
9
10
 
10
11
  /**
11
12
  * Extract email addresses operation
@@ -25,9 +26,19 @@ class ExtractEmailAddresses extends Operation {
25
26
  this.outputType = "string";
26
27
  this.args = [
27
28
  {
28
- "name": "Display total",
29
- "type": "boolean",
30
- "value": false
29
+ name: "Display total",
30
+ type: "boolean",
31
+ value: false
32
+ },
33
+ {
34
+ name: "Sort",
35
+ type: "boolean",
36
+ value: false
37
+ },
38
+ {
39
+ name: "Unique",
40
+ type: "boolean",
41
+ value: false
31
42
  }
32
43
  ];
33
44
  }
@@ -38,10 +49,23 @@ class ExtractEmailAddresses extends Operation {
38
49
  * @returns {string}
39
50
  */
40
51
  run(input, args) {
41
- const displayTotal = args[0],
52
+ const [displayTotal, sort, unique] = args,
42
53
  // email regex from: https://www.regextester.com/98066
43
54
  regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}\])/ig;
44
- return search(input, regex, null, displayTotal);
55
+
56
+ const results = search(
57
+ input,
58
+ regex,
59
+ null,
60
+ sort ? caseInsensitiveSort : null,
61
+ unique
62
+ );
63
+
64
+ if (displayTotal) {
65
+ return `Total found: ${results.length}\n\n${results.join("\n")}`;
66
+ } else {
67
+ return results.join("\n");
68
+ }
45
69
  }
46
70
 
47
71
  }
@@ -6,6 +6,7 @@
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
8
  import { search } from "../lib/Extract.mjs";
9
+ import { caseInsensitiveSort } from "../lib/Sort.mjs";
9
10
 
10
11
  /**
11
12
  * Extract file paths operation
@@ -25,19 +26,29 @@ class ExtractFilePaths extends Operation {
25
26
  this.outputType = "string";
26
27
  this.args = [
27
28
  {
28
- "name": "Windows",
29
- "type": "boolean",
30
- "value": true
29
+ name: "Windows",
30
+ type: "boolean",
31
+ value: true
31
32
  },
32
33
  {
33
- "name": "UNIX",
34
- "type": "boolean",
35
- "value": true
34
+ name: "UNIX",
35
+ type: "boolean",
36
+ value: true
36
37
  },
37
38
  {
38
- "name": "Display total",
39
- "type": "boolean",
40
- "value": false
39
+ name: "Display total",
40
+ type: "boolean",
41
+ value: false
42
+ },
43
+ {
44
+ name: "Sort",
45
+ type: "boolean",
46
+ value: false
47
+ },
48
+ {
49
+ name: "Unique",
50
+ type: "boolean",
51
+ value: false
41
52
  }
42
53
  ];
43
54
  }
@@ -48,7 +59,7 @@ class ExtractFilePaths extends Operation {
48
59
  * @returns {string}
49
60
  */
50
61
  run(input, args) {
51
- const [includeWinPath, includeUnixPath, displayTotal] = args,
62
+ const [includeWinPath, includeUnixPath, displayTotal, sort, unique] = args,
52
63
  winDrive = "[A-Z]:\\\\",
53
64
  winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}",
54
65
  winExt = "[A-Z\\d]{1,6}",
@@ -65,12 +76,25 @@ class ExtractFilePaths extends Operation {
65
76
  filePaths = unixPath;
66
77
  }
67
78
 
68
- if (filePaths) {
69
- const regex = new RegExp(filePaths, "ig");
70
- return search(input, regex, null, displayTotal);
71
- } else {
79
+ if (!filePaths) {
72
80
  return "";
73
81
  }
82
+
83
+ const regex = new RegExp(filePaths, "ig");
84
+ const results = search(
85
+ input,
86
+ regex,
87
+ null,
88
+ sort ? caseInsensitiveSort : null,
89
+ unique
90
+ );
91
+
92
+ if (displayTotal) {
93
+ return `Total found: ${results.length}\n\n${results.join("\n")}`;
94
+ } else {
95
+ return results.join("\n");
96
+ }
97
+
74
98
  }
75
99
 
76
100
  }
@@ -6,6 +6,7 @@
6
6
 
7
7
  import Operation from "../Operation.mjs";
8
8
  import { search } from "../lib/Extract.mjs";
9
+ import { ipSort } from "../lib/Sort.mjs";
9
10
 
10
11
  /**
11
12
  * Extract IP addresses operation
@@ -25,24 +26,34 @@ class ExtractIPAddresses extends Operation {
25
26
  this.outputType = "string";
26
27
  this.args = [
27
28
  {
28
- "name": "IPv4",
29
- "type": "boolean",
30
- "value": true
29
+ name: "IPv4",
30
+ type: "boolean",
31
+ value: true
31
32
  },
32
33
  {
33
- "name": "IPv6",
34
- "type": "boolean",
35
- "value": false
34
+ name: "IPv6",
35
+ type: "boolean",
36
+ value: false
36
37
  },
37
38
  {
38
- "name": "Remove local IPv4 addresses",
39
- "type": "boolean",
40
- "value": false
39
+ name: "Remove local IPv4 addresses",
40
+ type: "boolean",
41
+ value: false
41
42
  },
42
43
  {
43
- "name": "Display total",
44
- "type": "boolean",
45
- "value": false
44
+ name: "Display total",
45
+ type: "boolean",
46
+ value: false
47
+ },
48
+ {
49
+ name: "Sort",
50
+ type: "boolean",
51
+ value: false
52
+ },
53
+ {
54
+ name: "Unique",
55
+ type: "boolean",
56
+ value: false
46
57
  }
47
58
  ];
48
59
  }
@@ -53,7 +64,7 @@ class ExtractIPAddresses extends Operation {
53
64
  * @returns {string}
54
65
  */
55
66
  run(input, args) {
56
- const [includeIpv4, includeIpv6, removeLocal, displayTotal] = args,
67
+ const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args,
57
68
  ipv4 = "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?",
58
69
  ipv6 = "((?=.*::)(?!.*::.+::)(::)?([\\dA-F]{1,4}:(:|\\b)|){5}|([\\dA-F]{1,4}:){6})((([\\dA-F]{1,4}((?!\\3)::|:\\b|(?![\\dA-F])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})";
59
70
  let ips = "";
@@ -66,23 +77,29 @@ class ExtractIPAddresses extends Operation {
66
77
  ips = ipv6;
67
78
  }
68
79
 
69
- if (ips) {
70
- const regex = new RegExp(ips, "ig");
80
+ if (!ips) return "";
71
81
 
72
- if (removeLocal) {
73
- const ten = "10\\..+",
74
- oneninetwo = "192\\.168\\..+",
75
- oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
76
- onetwoseven = "127\\..+",
77
- removeRegex = new RegExp("^(?:" + ten + "|" + oneninetwo +
78
- "|" + oneseventwo + "|" + onetwoseven + ")");
82
+ const regex = new RegExp(ips, "ig");
79
83
 
80
- return search(input, regex, removeRegex, displayTotal);
81
- } else {
82
- return search(input, regex, null, displayTotal);
83
- }
84
+ const ten = "10\\..+",
85
+ oneninetwo = "192\\.168\\..+",
86
+ oneseventwo = "172\\.(?:1[6-9]|2\\d|3[01])\\..+",
87
+ onetwoseven = "127\\..+",
88
+ removeRegex = new RegExp("^(?:" + ten + "|" + oneninetwo +
89
+ "|" + oneseventwo + "|" + onetwoseven + ")");
90
+
91
+ const results = search(
92
+ input,
93
+ regex,
94
+ removeLocal ? removeRegex : null,
95
+ sort ? ipSort : null,
96
+ unique
97
+ );
98
+
99
+ if (displayTotal) {
100
+ return `Total found: ${results.length}\n\n${results.join("\n")}`;
84
101
  } else {
85
- return "";
102
+ return results.join("\n");
86
103
  }
87
104
  }
88
105