2
0
mirror of https://github.com/gchq/CyberChef synced 2026-01-02 00:23:55 +00:00

Compare commits

..

86 Commits

Author SHA1 Message Date
n1474335
8dd223f1cb 7.7.8 2018-03-04 17:51:39 +00:00
n1474335
d15662dea4 Merge branch 'bug-hashes' 2018-03-04 17:49:36 +00:00
n1474335
f47a408755 Fix for UTF-8/binary handling in hashing operations. Added tests to prevent future breakages. Closes #249. 2018-03-04 17:39:53 +00:00
n1474335
8360c9e9f9 Fixed noindex meta tag for standalone version 2018-03-02 11:15:37 +00:00
n1474335
328142dac7 Added 's' to the standalone version string 2018-03-01 20:32:09 +00:00
n1474335
372b2378a8 7.7.7 2018-03-01 19:45:47 +00:00
n1474335
574207c626 Updated many dependencies including Webpack (v4) and crypto-api (v0.8) 2018-03-01 19:45:34 +00:00
n1474335
ead64dcb47 7.7.6 2018-02-28 16:40:22 +00:00
n1474335
da473de9f0 Switched from uas_parser.js to ua-parser-js library to improve library management and remove ReDos vulnerabilities. Also improved performance of two native regexes. Thanks to James Davis for raising awareness. 2018-02-28 16:40:15 +00:00
n1474335
a177e2ab7e 7.7.5 2018-02-21 11:24:46 +00:00
n1474335
8cef6db482 Added IPv6 interface IDs to the 'Format MAC address' operation 2018-02-21 11:24:38 +00:00
n1474335
79a3128491 Changed fragment to query in sitemap 2018-02-20 17:39:46 +00:00
n1474335
cb1fe80214 Added robots meta tag to inline version to prevent indexing. 2018-02-20 17:34:19 +00:00
n1474335
19f2e6dae0 Fixed robots.txt copy 2018-02-20 17:15:06 +00:00
n1474335
74394a773d Fixed URL in sitemap 2018-02-20 17:09:02 +00:00
n1474335
d491e95d1c 7.7.4 2018-02-20 17:04:47 +00:00
n1474335
881523ce54 Merge branch 'sitemap' 2018-02-20 17:04:34 +00:00
n1474335
502a9fbb92 Added dynamically generated sitemap and robots.txt file to prevent crawling of inline version 2018-02-20 16:52:27 +00:00
n1474335
cc44fe6557 7.7.3 2018-02-16 13:33:41 +00:00
n1474335
5b1ac3de18 Reduced byte length in 'Unescape Unicode Characters' 2018-02-16 13:33:33 +00:00
n1474335
5a2a649d8e 7.7.2 2018-02-15 13:41:17 +00:00
n1474335
1aef193b40 Fixed file loading error message 2018-02-15 13:41:13 +00:00
n1474335
750fa45c04 7.7.1 2018-02-14 10:34:14 +00:00
n1474335
50f2819699 OR now calls the correct function instead of duplicating XOR. Closes #243. 2018-02-14 10:34:08 +00:00
n1474335
ab55b91da1 7.7.0 2018-02-13 15:51:45 +00:00
n1474335
59f7774964 Merge branch 'feature-xkcd-rand' 2018-02-13 15:51:02 +00:00
n1474335
b5eb44af9f When highlighting operation descriptions in search results, HTML tags are now ignored. 2018-02-13 15:43:55 +00:00
n1474335
8518fa67f2 Added 'XKCD Random Number' operation 2018-02-13 15:05:55 +00:00
n1474335
f6b68f9880 Increased file overlay slice to 4096 for larger screen support 2018-02-12 13:57:01 +00:00
n1474335
f6b2783f8b File overlays now show a blurred representation of the file in the background. 2018-02-09 16:26:39 +00:00
n1474335
078849041f 7.6.3 2018-01-26 19:14:15 +00:00
n1474335
1c711f5e03 Updated dependencies 2018-01-26 19:14:05 +00:00
n1474335
614af0602a 7.6.2 2018-01-25 18:41:53 +00:00
n1474335
e55cfe0bc1 Fixed 'Syntax highlighter' operation. Using highlight.js instead of google-code-prettify. 2018-01-25 18:41:47 +00:00
n1474335
2b703b2b9b HTML outputs are now unescaped correctly when converted to a string 2018-01-25 16:25:19 +00:00
n1474335
170feaaff2 7.6.1 2018-01-25 14:03:19 +00:00
n1474335
870c2b6d8b Fixed deep copy bug with Fork/Register ingredient values. 2018-01-25 14:03:13 +00:00
n1474335
eee8b7db56 Fixed dispatchEvent call in recipe loading chain. 2018-01-25 13:46:06 +00:00
n1474335
3c669a075e 7.6.0 2018-01-25 13:45:05 +00:00
n1474335
f528930ad2 Added 'Sleep' operation. 2018-01-25 13:44:39 +00:00
n1474335
231322eddf 7.5.6 2018-01-24 16:54:42 +00:00
n1474335
8e6763c165 'Register' and 'Fork' now play well together. 2018-01-24 16:54:37 +00:00
n1474335
f091918575 7.5.5 2018-01-24 15:50:10 +00:00
n1474335
bb077c87b3 'Extract file paths' operation now handles 8.3 windows file paths correctly. 2018-01-24 15:50:05 +00:00
n1474335
fe8f8bc712 Setting a text value in the input now closes any open files. 2018-01-22 19:58:21 +00:00
n1474335
abe87830cd Operation tooltips now disappear if you hover over them while dragging an opertion. 2018-01-22 17:51:04 +00:00
n1474335
7490651a06 7.5.4 2018-01-22 17:10:02 +00:00
n1474335
6220128a74 Fixed delimiter options in StrUtils. Closes #238. 2018-01-22 17:09:58 +00:00
n1474335
ec205f4f7d 7.5.3 2018-01-18 19:53:01 +00:00
n1474335
512487328d Fixed bugs in pretty recipe format generation 2018-01-18 18:35:17 +00:00
n1474335
6fbb2f26d1 7.5.2 2018-01-18 15:27:26 +00:00
n1474335
c91bfeaa81 Merge branch 'qistoph-SplitAndJoin' 2018-01-18 15:26:34 +00:00
n1474335
aa2b3b2843 Changed order of split delimiters, placing comma first. 2018-01-18 15:26:09 +00:00
Chris van Marle
90d8be48d4 Make Split more flexible so it can be used to join 2018-01-17 15:52:25 +01:00
n1474335
aa6890432c 7.5.1 2018-01-12 23:59:03 +00:00
n1474335
192d0ed8a6 Merge branch 'feature-unicode-strings' 2018-01-12 23:57:20 +00:00
n1474335
fff188eb30 Merged master into feature-unicode-strings 2018-01-12 23:57:02 +00:00
n1474335
71067939e3 Added Regex tests and updated description 2018-01-12 23:51:51 +00:00
n1474335
b07c014b48 Added more modifiers to the Regex operation 2018-01-12 23:42:48 +00:00
n1474335
f2c073798b 'Strings' now supports various different match types in ASCII and Unicode 2018-01-12 23:09:27 +00:00
n1474335
4cc38db895 Added documentation. 2018-01-12 22:14:06 +00:00
n1474335
2762319dbb 7.5.0 2018-01-12 18:29:10 +00:00
n1474335
8e5d43dfa8 Merge branch 'feature-hamming' 2018-01-12 18:28:55 +00:00
n1474335
82ad8cc444 BigNumber Dish types are now converted to fixed notation instead of exponential when translated between types 2018-01-12 18:28:40 +00:00
n1474335
1d6bf39548 Added 'Hamming Distance' operation. 2018-01-12 18:17:28 +00:00
n1474335
ec02b7deda Regexes are now checked for 0-length matches and incremented manually to avoid infinite loops 2018-01-10 19:44:25 +00:00
n1474335
fa938f832f Fixed IE 11 detection so that support message is correctly shown. 2018-01-10 18:38:17 +00:00
n1474335
6f59d9217c Changed 'Number' option to 'Integer' in PRNG op 2018-01-06 17:01:01 +00:00
n1474335
7176e5ca6e 7.4.0 2018-01-06 16:34:06 +00:00
n1474335
429829471f Merge branch 'feature-paste-performance' 2018-01-06 16:33:12 +00:00
n1474335
4760e539b7 PRNG operation now supports BigNumbers as output 2018-01-06 16:30:17 +00:00
n1474335
f53e7ad617 Chef now defaults to treat as UTF8 if option is not set 2018-01-06 16:21:42 +00:00
n1474335
28c83fa921 Dish translation now obeys UTF8 rules 2018-01-06 16:02:50 +00:00
n1474335
4588cd151c Data pasted into the input is treat as a file if it's over the IO threshold 2018-01-06 15:29:58 +00:00
n1474335
2d9f87abef Added more loading messages 2018-01-05 20:26:51 +00:00
n1474335
491e6f5f5f 7.3.0 2018-01-05 18:50:48 +00:00
n1474335
ab7c05284d Merge branch 'artemisbot-features/big-number' 2018-01-05 18:50:13 +00:00
n1474335
0586fa0e01 Fixed failing Fork test that required an error. 2018-01-05 18:49:51 +00:00
n1474335
53eba2337c BCD operations now support BigNumbers 2018-01-05 18:38:23 +00:00
n1474335
283d3e1e7b Blank BigNumber dishes are now treat as NaN instead of erroring 2018-01-05 18:20:06 +00:00
n1474335
7992a540ae Conversion operations now support BigNumbers 2018-01-05 18:14:03 +00:00
n1474335
3f3e7a78eb Arithmetic operations now support BigNumbers 2018-01-05 18:04:55 +00:00
n1474335
8d3d39acd3 Merge branch 'features/big-number' of https://github.com/artemisbot/CyberChef into artemisbot-features/big-number 2018-01-05 17:31:27 +00:00
n1474335
7b20aba2ff Improved descriptions for 'Unescape string' and 'Escape string' operations 2018-01-04 18:32:03 +00:00
n1474335
56551712d6 Began implementing UTF-16 support in the 'Strings' operation. 2018-01-03 16:51:10 +00:00
Matt C
c241d2f90b Adds basic BigNumber type support
Fixes `To Base` & `From Base` issues as reported on twitter
2018-01-03 11:26:31 +00:00
55 changed files with 5504 additions and 27920 deletions

View File

@@ -51,6 +51,7 @@
"mode": "minimum" "mode": "minimum"
}], }],
"indent": ["error", 4, { "indent": ["error", 4, {
"ignoreComments": true,
"ArrayExpression": "first", "ArrayExpression": "first",
"SwitchCase": 1 "SwitchCase": 1
}], }],

View File

@@ -11,6 +11,7 @@ script:
- grunt node - grunt node
- grunt prod --msg="$COMPILE_MSG" - grunt prod --msg="$COMPILE_MSG"
before_deploy: before_deploy:
- grunt exec:sitemap
- grunt copy:ghPages - grunt copy:ghPages
deploy: deploy:
- provider: pages - provider: pages

View File

@@ -185,8 +185,12 @@ module.exports = function (grunt) {
webpack: { webpack: {
options: webpackConfig, options: webpackConfig,
metaConf: { metaConf: {
mode: "production",
target: "node", target: "node",
entry: "./src/core/config/OperationConfig.js", entry: [
"babel-polyfill",
"./src/core/config/OperationConfig.js"
],
output: { output: {
filename: "MetaConfig.js", filename: "MetaConfig.js",
path: __dirname + "/src/core/config/", path: __dirname + "/src/core/config/",
@@ -197,8 +201,12 @@ module.exports = function (grunt) {
externals: [NodeExternals()], externals: [NodeExternals()],
}, },
metaConfDev: { metaConfDev: {
mode: "development",
target: "node", target: "node",
entry: "./src/core/config/OperationConfig.js", entry: [
"babel-polyfill",
"./src/core/config/OperationConfig.js"
],
output: { output: {
filename: "MetaConfig.js", filename: "MetaConfig.js",
path: __dirname + "/src/core/config/", path: __dirname + "/src/core/config/",
@@ -210,9 +218,11 @@ module.exports = function (grunt) {
watch: true watch: true
}, },
web: { web: {
mode: "production",
target: "web", target: "web",
entry: Object.assign({ entry: Object.assign({
main: "./src/web/index.js" main: "./src/web/index.js",
sitemap: "./src/web/static/sitemap.js"
}, moduleEntryPoints), }, moduleEntryPoints),
output: { output: {
path: __dirname + "/build/prod" path: __dirname + "/build/prod"
@@ -224,15 +234,6 @@ module.exports = function (grunt) {
}, },
plugins: [ plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS), new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.UglifyJsPlugin({
compress: {
"screw_ie8": true,
"dead_code": true,
"unused": true,
"warnings": false
},
comments: false,
}),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
filename: "index.html", filename: "index.html",
template: "./src/web/html/index.html", template: "./src/web/html/index.html",
@@ -249,6 +250,7 @@ module.exports = function (grunt) {
] ]
}, },
webInline: { webInline: {
mode: "production",
target: "web", target: "web",
entry: "./src/web/index.js", entry: "./src/web/index.js",
output: { output: {
@@ -256,21 +258,14 @@ module.exports = function (grunt) {
path: __dirname + "/build/prod" path: __dirname + "/build/prod"
}, },
plugins: [ plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS), new webpack.DefinePlugin(Object.assign({}, BUILD_CONSTANTS, {
new webpack.optimize.UglifyJsPlugin({ INLINE: "true"
compress: { })),
"screw_ie8": true,
"dead_code": true,
"unused": true,
"warnings": false
},
comments: false,
}),
new HtmlWebpackPlugin({ new HtmlWebpackPlugin({
filename: "cyberchef.htm", filename: "cyberchef.htm",
template: "./src/web/html/index.html", template: "./src/web/html/index.html",
compileTime: compileTime, compileTime: compileTime,
version: pkg.version, version: pkg.version + "s",
inline: true, inline: true,
minify: { minify: {
removeComments: true, removeComments: true,
@@ -282,6 +277,7 @@ module.exports = function (grunt) {
] ]
}, },
tests: { tests: {
mode: "development",
target: "node", target: "node",
entry: "./test/index.js", entry: "./test/index.js",
externals: [NodeExternals()], externals: [NodeExternals()],
@@ -294,6 +290,7 @@ module.exports = function (grunt) {
] ]
}, },
node: { node: {
mode: "production",
target: "node", target: "node",
entry: "./src/node/index.js", entry: "./src/node/index.js",
externals: [NodeExternals()], externals: [NodeExternals()],
@@ -320,11 +317,13 @@ module.exports = function (grunt) {
children: false, children: false,
chunks: false, chunks: false,
modules: false, modules: false,
entrypoints: false,
warningsFilter: /source-map/, warningsFilter: /source-map/,
} }
}, },
start: { start: {
webpack: { webpack: {
mode: "development",
target: "web", target: "web",
entry: Object.assign({ entry: Object.assign({
main: "./src/web/index.js" main: "./src/web/index.js"
@@ -371,7 +370,7 @@ module.exports = function (grunt) {
expand: true, expand: true,
src: "docs/**", src: "docs/**",
dest: "build/prod/" dest: "build/prod/"
} },
] ]
} }
}, },
@@ -400,6 +399,9 @@ module.exports = function (grunt) {
cleanGit: { cleanGit: {
command: "git gc --prune=now --aggressive" command: "git gc --prune=now --aggressive"
}, },
sitemap: {
command: "node build/prod/sitemap.js > build/prod/sitemap.xml"
}
}, },
execute: { execute: {
test: "build/test/index.js" test: "build/test/index.js"

View File

@@ -103,4 +103,4 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
[8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA [8]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
[9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ [9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ
[10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg [10]: https://gchq.github.io/CyberChef/#recipe=Register('(.%7B32%7D)',true,false)Drop_bytes(0,32,false)AES_Decrypt(%7B'option':'Hex','string':'1748e7179bd56570d51fa4ba287cc3e5'%7D,%7B'option':'Hex','string':'$R0'%7D,'CTR','Hex','Raw',%7B'option':'Hex','string':''%7D)&input=NTFlMjAxZDQ2MzY5OGVmNWY3MTdmNzFmNWI0NzEyYWYyMGJlNjc0YjNiZmY1M2QzODU0NjM5NmVlNjFkYWFjNDkwOGUzMTljYTNmY2Y3MDg5YmZiNmIzOGVhOTllNzgxZDI2ZTU3N2JhOWRkNmYzMTFhMzk0MjBiODk3OGU5MzAxNGIwNDJkNDQ3MjZjYWVkZjU0MzZlYWY2NTI0MjljMGRmOTRiNTIxNjc2YzdjMmNlODEyMDk3YzI3NzI3M2M3YzcyY2Q4OWFlYzhkOWZiNGEyNzU4NmNjZjZhYTBhZWUyMjRjMzRiYTNiZmRmN2FlYjFkZGQ0Nzc2MjJiOTFlNzJjOWU3MDlhYjYwZjhkYWY3MzFlYzBjYzg1Y2UwZjc0NmZmMTU1NGE1YTNlYzI5MWNhNDBmOWU2MjlhODcyNTkyZDk4OGZkZDgzNDUzNGFiYTc5YzFhZDE2NzY3NjlhN2MwMTBiZjA0NzM5ZWNkYjY1ZDk1MzAyMzcxZDYyOWQ5ZTM3ZTdiNGEzNjFkYTQ2OGYxZWQ1MzU4OTIyZDJlYTc1MmRkMTFjMzY2ZjMwMTdiMTRhYTAxMWQyYWYwM2M0NGY5NTU3OTA5OGExNWUzY2Y5YjQ0ODZmOGZmZTljMjM5ZjM0ZGU3MTUxZjZjYTY1MDBmZTRiODUwYzNmMWMwMmU4MDFjYWYzYTI0NDY0NjE0ZTQyODAxNjE1YjhmZmFhMDdhYzgyNTE0OTNmZmRhN2RlNWRkZjMzNjg4ODBjMmI5NWIwMzBmNDFmOGYxNTA2NmFkZDA3MWE2NmNmNjBlNWY0NmYzYTIzMGQzOTdiNjUyOTYzYTIxYTUzZg
[11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4 [11]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'Standard',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4

5375
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "cyberchef", "name": "cyberchef",
"version": "7.2.3", "version": "7.7.8",
"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",
@@ -31,14 +31,15 @@
"bugs": "https://github.com/gchq/CyberChef/issues", "bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": { "devDependencies": {
"babel-core": "^6.26.0", "babel-core": "^6.26.0",
"babel-loader": "^7.1.2", "babel-loader": "^7.1.3",
"babel-preset-env": "^1.6.1", "babel-preset-env": "^1.6.1",
"css-loader": "^0.28.7", "css-loader": "^0.28.10",
"exports-loader": "^0.6.4", "eslint": "^4.18.1",
"extract-text-webpack-plugin": "^3.0.2", "exports-loader": "^0.7.0",
"file-loader": "^1.1.6", "extract-text-webpack-plugin": "^4.0.0-alpha0",
"grunt": ">=1.0.1", "file-loader": "^1.1.10",
"grunt-accessibility": "~5.0.0", "grunt": ">=1.0.2",
"grunt-accessibility": "~6.0.0",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-concurrent": "^2.3.1", "grunt-concurrent": "^2.3.1",
"grunt-contrib-clean": "~1.1.0", "grunt-contrib-clean": "~1.1.0",
@@ -46,62 +47,66 @@
"grunt-eslint": "^20.1.0", "grunt-eslint": "^20.1.0",
"grunt-exec": "~3.0.0", "grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2", "grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.2.0", "grunt-jsdoc": "^2.2.1",
"grunt-webpack": "^3.0.2", "grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.30.1", "html-webpack-plugin": "^3.0.4",
"imports-loader": "^0.7.1", "imports-loader": "^0.8.0",
"ink-docstrap": "^1.3.2", "ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.3.0", "jsdoc-babel": "^0.3.0",
"less": "^2.7.3", "less": "^3.0.1",
"less-loader": "^4.0.5", "less-loader": "^4.0.6",
"postcss-css-variables": "^0.8.0", "postcss-css-variables": "^0.8.0",
"postcss-import": "^11.0.0", "postcss-import": "^11.1.0",
"postcss-loader": "^2.0.9", "postcss-loader": "^2.1.1",
"style-loader": "^0.19.1", "sitemap": "^1.13.0",
"style-loader": "^0.20.2",
"url-loader": "^0.6.2", "url-loader": "^0.6.2",
"val-loader": "^1.1.0", "val-loader": "^1.1.0",
"web-resource-inliner": "^4.2.0", "web-resource-inliner": "^4.2.1",
"webpack": "^3.10.0", "webpack": "^4.0.1",
"webpack-dev-server": "^2.9.7", "webpack-dev-server": "^3.1.0",
"webpack-node-externals": "^1.6.0", "webpack-node-externals": "^1.6.0",
"worker-loader": "^1.1.0" "worker-loader": "^1.1.1"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.26.0", "babel-polyfill": "^6.26.0",
"bignumber.js": "^6.0.0",
"bootstrap": "^3.3.7", "bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.2", "bootstrap-colorpicker": "^2.5.2",
"bootstrap-switch": "^3.3.4", "bootstrap-switch": "^3.3.4",
"crypto-api": "^0.7.5", "crypto-api": "^0.8.0",
"crypto-js": "^3.1.9-1", "crypto-js": "^3.1.9-1",
"diff": "^3.4.0", "diff": "^3.4.0",
"escodegen": "^1.9.0", "escodegen": "^1.9.1",
"esmangle": "^1.0.1", "esmangle": "^1.0.1",
"esprima": "^4.0.0", "esprima": "^4.0.0",
"exif-parser": "^0.1.12", "exif-parser": "^0.1.12",
"file-saver": "^1.3.3", "file-saver": "^1.3.3",
"google-code-prettify": "^1.0.5", "highlight.js": "^9.12.0",
"jquery": "^3.2.1", "jquery": "^3.3.1",
"js-crc": "^0.2.0", "js-crc": "^0.2.0",
"js-sha3": "^0.7.0", "js-sha3": "^0.7.0",
"jsbn": "^1.1.0", "jsbn": "^1.1.0",
"jsonpath": "^1.0.0", "jsonpath": "^1.0.0",
"jsrsasign": "8.0.4", "jsrsasign": "8.0.6",
"lodash": "^4.17.4", "lodash": "^4.17.5",
"loglevel": "^1.6.0", "loglevel": "^1.6.1",
"loglevel-message-prefix": "^3.0.0", "loglevel-message-prefix": "^3.0.0",
"moment": "^2.20.1", "moment": "^2.20.1",
"moment-timezone": "^0.5.14", "moment-timezone": "^0.5.14",
"node-forge": "^0.7.1", "node-forge": "^0.7.2",
"node-md6": "^0.1.0", "node-md6": "^0.1.0",
"nwmatcher": "^1.4.3", "nwmatcher": "^1.4.3",
"otp": "^0.1.3", "otp": "^0.1.3",
"sladex-blowfish": "^0.8.1", "sladex-blowfish": "^0.8.1",
"sortablejs": "^1.7.0", "sortablejs": "^1.7.0",
"split.js": "^1.3.5", "split.js": "^1.3.5",
"ua-parser-js": "^0.7.17",
"utf8": "^3.0.0", "utf8": "^3.0.0",
"vkbeautify": "^0.99.3", "vkbeautify": "^0.99.3",
"xmldom": "^0.1.27", "xmldom": "^0.1.27",
"xpath": "0.0.27", "xpath": "0.0.27",
"xregexp": "^4.1.1",
"zlibjs": "^0.3.1" "zlibjs": "^0.3.1"
}, },
"scripts": { "scripts": {

View File

@@ -35,10 +35,11 @@ const Chef = function() {
*/ */
Chef.prototype.bake = async function(input, recipeConfig, options, progress, step) { Chef.prototype.bake = async function(input, recipeConfig, options, progress, step) {
log.debug("Chef baking"); log.debug("Chef baking");
let startTime = new Date().getTime(), const startTime = new Date().getTime(),
recipe = new Recipe(recipeConfig), recipe = new Recipe(recipeConfig),
containsFc = recipe.containsFlowControl(), containsFc = recipe.containsFlowControl(),
error = false; notUTF8 = options && options.hasOwnProperty("treatAsUtf8") && !options.treatAsUtf8;
let error = false;
if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false); if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
@@ -80,13 +81,13 @@ Chef.prototype.bake = async function(input, recipeConfig, options, progress, ste
// Depending on the size of the output, we may send it back as a string or an ArrayBuffer. // Depending on the size of the output, we may send it back as a string or an ArrayBuffer.
// This can prevent unnecessary casting as an ArrayBuffer can be easily downloaded as a file. // This can prevent unnecessary casting as an ArrayBuffer can be easily downloaded as a file.
// The threshold is specified in KiB. // The threshold is specified in KiB.
const threshold = (options.outputFileThreshold || 1024) * 1024; const threshold = (options.ioDisplayThreshold || 1024) * 1024;
const returnType = this.dish.size() > threshold ? Dish.ARRAY_BUFFER : Dish.STRING; const returnType = this.dish.size() > threshold ? Dish.ARRAY_BUFFER : Dish.STRING;
return { return {
result: this.dish.type === Dish.HTML ? result: this.dish.type === Dish.HTML ?
this.dish.get(Dish.HTML) : this.dish.get(Dish.HTML, notUTF8) :
this.dish.get(returnType), this.dish.get(returnType, notUTF8),
type: Dish.enumLookup(this.dish.type), type: Dish.enumLookup(this.dish.type),
progress: progress, progress: progress,
duration: new Date().getTime() - startTime, duration: new Date().getTime() - startTime,

View File

@@ -138,6 +138,7 @@ function loadRequiredModules(recipeConfig) {
log.info("Loading module " + module); log.info("Loading module " + module);
self.sendStatusMessage("Loading module " + module); self.sendStatusMessage("Loading module " + module);
self.importScripts(self.docURL + "/" + module + ".js"); self.importScripts(self.docURL + "/" + module + ".js");
self.sendStatusMessage("");
} }
}); });
} }

View File

@@ -1,14 +1,16 @@
import Utils from "./Utils.js"; import Utils from "./Utils.js";
import BigNumber from "bignumber.js";
/** /**
* The data being operated on by each operation. * The data being operated on by each operation.
* *
* @author n1474335 [n1474335@gmail.com] * @author n1474335 [n1474335@gmail.com]
* @author Matt C [matt@artemisbot.uk]
* @copyright Crown Copyright 2016 * @copyright Crown Copyright 2016
* @license Apache-2.0 * @license Apache-2.0
* *
* @class * @class
* @param {byteArray|string|number|ArrayBuffer} value - The value of the input data. * @param {byteArray|string|number|ArrayBuffer|BigNumber} value - The value of the input data.
* @param {number} type - The data type of value, see Dish enums. * @param {number} type - The data type of value, see Dish enums.
*/ */
const Dish = function(value, type) { const Dish = function(value, type) {
@@ -47,6 +49,12 @@ Dish.HTML = 3;
* @enum * @enum
*/ */
Dish.ARRAY_BUFFER = 4; Dish.ARRAY_BUFFER = 4;
/**
* Dish data type enum for BigNumbers.
* @readonly
* @enum
*/
Dish.BIG_NUMBER = 5;
/** /**
@@ -57,22 +65,22 @@ Dish.ARRAY_BUFFER = 4;
* @returns {number} The data type enum value. * @returns {number} The data type enum value.
*/ */
Dish.typeEnum = function(typeStr) { Dish.typeEnum = function(typeStr) {
switch (typeStr) { switch (typeStr.toLowerCase()) {
case "byteArray": case "bytearray":
case "Byte array": case "byte array":
return Dish.BYTE_ARRAY; return Dish.BYTE_ARRAY;
case "string": case "string":
case "String":
return Dish.STRING; return Dish.STRING;
case "number": case "number":
case "Number":
return Dish.NUMBER; return Dish.NUMBER;
case "html": case "html":
case "HTML":
return Dish.HTML; return Dish.HTML;
case "arrayBuffer": case "arraybuffer":
case "ArrayBuffer": case "array buffer":
return Dish.ARRAY_BUFFER; return Dish.ARRAY_BUFFER;
case "bignumber":
case "big number":
return Dish.BIG_NUMBER;
default: default:
throw "Invalid data type string. No matching enum."; throw "Invalid data type string. No matching enum.";
} }
@@ -83,8 +91,8 @@ Dish.typeEnum = function(typeStr) {
* Returns the data type string for the given type enum. * Returns the data type string for the given type enum.
* *
* @static * @static
* @param {string} typeEnum - The enum value of the data type. * @param {number} typeEnum - The enum value of the data type.
* @returns {number} The data type as a string. * @returns {string} The data type as a string.
*/ */
Dish.enumLookup = function(typeEnum) { Dish.enumLookup = function(typeEnum) {
switch (typeEnum) { switch (typeEnum) {
@@ -98,6 +106,8 @@ Dish.enumLookup = function(typeEnum) {
return "html"; return "html";
case Dish.ARRAY_BUFFER: case Dish.ARRAY_BUFFER:
return "ArrayBuffer"; return "ArrayBuffer";
case Dish.BIG_NUMBER:
return "BigNumber";
default: default:
throw "Invalid data type enum. No matching type."; throw "Invalid data type enum. No matching type.";
} }
@@ -107,7 +117,7 @@ Dish.enumLookup = function(typeEnum) {
/** /**
* Sets the data value and type and then validates them. * Sets the data value and type and then validates them.
* *
* @param {byteArray|string|number|ArrayBuffer} value - The value of the input data. * @param {byteArray|string|number|ArrayBuffer|BigNumber} value - The value of the input data.
* @param {number} type - The data type of value, see Dish enums. * @param {number} type - The data type of value, see Dish enums.
*/ */
Dish.prototype.set = function(value, type) { Dish.prototype.set = function(value, type) {
@@ -126,11 +136,12 @@ Dish.prototype.set = function(value, type) {
* Returns the value of the data in the type format specified. * Returns the value of the data in the type format specified.
* *
* @param {number} type - The data type of value, see Dish enums. * @param {number} type - The data type of value, see Dish enums.
* @returns {byteArray|string|number|ArrayBuffer} The value of the output data. * @param {boolean} [notUTF8] - Do not treat strings as UTF8.
* @returns {byteArray|string|number|ArrayBuffer|BigNumber} The value of the output data.
*/ */
Dish.prototype.get = function(type) { Dish.prototype.get = function(type, notUTF8) {
if (this.type !== type) { if (this.type !== type) {
this.translate(type); this.translate(type, notUTF8);
} }
return this.value; return this.value;
}; };
@@ -140,9 +151,11 @@ Dish.prototype.get = function(type) {
* Translates the data to the given type format. * Translates the data to the given type format.
* *
* @param {number} toType - The data type of value, see Dish enums. * @param {number} toType - The data type of value, see Dish enums.
* @param {boolean} [notUTF8] - Do not treat strings as UTF8.
*/ */
Dish.prototype.translate = function(toType) { Dish.prototype.translate = function(toType, notUTF8) {
log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`); log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`);
const byteArrayToStr = notUTF8 ? Utils.byteArrayToChars : Utils.byteArrayToUtf8;
// Convert data to intermediate byteArray type // Convert data to intermediate byteArray type
switch (this.type) { switch (this.type) {
@@ -159,6 +172,9 @@ Dish.prototype.translate = function(toType) {
// Array.from() would be nicer here, but it's slightly slower // Array.from() would be nicer here, but it's slightly slower
this.value = Array.prototype.slice.call(new Uint8Array(this.value)); this.value = Array.prototype.slice.call(new Uint8Array(this.value));
break; break;
case Dish.BIG_NUMBER:
this.value = this.value instanceof BigNumber ? Utils.strToByteArray(this.value.toFixed()) : [];
break;
default: default:
break; break;
} }
@@ -169,17 +185,25 @@ Dish.prototype.translate = function(toType) {
switch (toType) { switch (toType) {
case Dish.STRING: case Dish.STRING:
case Dish.HTML: case Dish.HTML:
this.value = this.value ? Utils.byteArrayToUtf8(this.value) : ""; this.value = this.value ? byteArrayToStr(this.value) : "";
this.type = Dish.STRING; this.type = Dish.STRING;
break; break;
case Dish.NUMBER: case Dish.NUMBER:
this.value = this.value ? parseFloat(Utils.byteArrayToUtf8(this.value)) : 0; this.value = this.value ? parseFloat(byteArrayToStr(this.value)) : 0;
this.type = Dish.NUMBER; this.type = Dish.NUMBER;
break; break;
case Dish.ARRAY_BUFFER: case Dish.ARRAY_BUFFER:
this.value = new Uint8Array(this.value).buffer; this.value = new Uint8Array(this.value).buffer;
this.type = Dish.ARRAY_BUFFER; this.type = Dish.ARRAY_BUFFER;
break; break;
case Dish.BIG_NUMBER:
try {
this.value = new BigNumber(byteArrayToStr(this.value));
} catch (err) {
this.value = new BigNumber(NaN);
}
this.type = Dish.BIG_NUMBER;
break;
default: default:
break; break;
} }
@@ -215,6 +239,8 @@ Dish.prototype.valid = function() {
return typeof this.value === "number"; return typeof this.value === "number";
case Dish.ARRAY_BUFFER: case Dish.ARRAY_BUFFER:
return this.value instanceof ArrayBuffer; return this.value instanceof ArrayBuffer;
case Dish.BIG_NUMBER:
return this.value instanceof BigNumber;
default: default:
return false; return false;
} }
@@ -235,6 +261,7 @@ Dish.prototype.size = function() {
case Dish.HTML: case Dish.HTML:
return this.value.length; return this.value.length;
case Dish.NUMBER: case Dish.NUMBER:
case Dish.BIG_NUMBER:
return this.value.toString().length; return this.value.toString().length;
case Dish.ARRAY_BUFFER: case Dish.ARRAY_BUFFER:
return this.value.byteLength; return this.value.byteLength;

View File

@@ -52,14 +52,25 @@ const FlowControl = {
output = "", output = "",
progress = 0; progress = 0;
state.forkOffset += state.progress + 1;
recipe.addOperations(subOpList); recipe.addOperations(subOpList);
// Take a deep(ish) copy of the ingredient values
const ingValues = subOpList.map(op => JSON.parse(JSON.stringify(op.getIngValues())));
// Run recipe over each tranche // Run recipe over each tranche
for (i = 0; i < inputs.length; i++) { for (i = 0; i < inputs.length; i++) {
log.debug(`Entering tranche ${i + 1} of ${inputs.length}`); log.debug(`Entering tranche ${i + 1} of ${inputs.length}`);
// Baseline ing values for each tranche so that registers are reset
subOpList.forEach((op, i) => {
op.setIngValues(JSON.parse(JSON.stringify(ingValues[i])));
});
const dish = new Dish(inputs[i], inputType); const dish = new Dish(inputs[i], inputType);
try { try {
progress = await recipe.execute(dish, 0); progress = await recipe.execute(dish, 0, state);
} catch (err) { } catch (err) {
if (!ignoreErrors) { if (!ignoreErrors) {
throw err; throw err;
@@ -117,7 +128,7 @@ const FlowControl = {
if (!registers) return state; if (!registers) return state;
if (ENVIRONMENT_IS_WORKER()) { if (ENVIRONMENT_IS_WORKER()) {
self.setRegisters(state.progress, state.numRegisters, registers.slice(1)); self.setRegisters(state.forkOffset + state.progress, state.numRegisters, registers.slice(1));
} }
/** /**

View File

@@ -141,11 +141,14 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
* *
* @param {Dish} dish * @param {Dish} dish
* @param {number} [startFrom=0] - The index of the Operation to start executing from * @param {number} [startFrom=0] - The index of the Operation to start executing from
* @param {number} [forkState={}] - If this is a forked recipe, the state of the recipe up to this point
* @returns {number} - The final progress through the recipe * @returns {number} - The final progress through the recipe
*/ */
Recipe.prototype.execute = async function(dish, startFrom) { Recipe.prototype.execute = async function(dish, startFrom = 0, forkState = {}) {
startFrom = startFrom || 0; let op, input, output,
let op, input, output, numJumps = 0, numRegisters = 0; numJumps = 0,
numRegisters = forkState.numRegisters || 0;
log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`); log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`);
for (let i = startFrom; i < this.opList.length; i++) { for (let i = startFrom; i < this.opList.length; i++) {
@@ -171,7 +174,8 @@ Recipe.prototype.execute = async function(dish, startFrom) {
"dish": dish, "dish": dish,
"opList": this.opList, "opList": this.opList,
"numJumps": numJumps, "numJumps": numJumps,
"numRegisters": numRegisters "numRegisters": numRegisters,
"forkOffset": forkState.forkOffset || 0
}; };
state = await op.run(state); state = await op.run(state);
@@ -256,4 +260,5 @@ Recipe.prototype.generateHighlightList = function() {
return highlights; return highlights;
}; };
export default Recipe; export default Recipe;

View File

@@ -495,15 +495,16 @@ const Utils = {
* Converts an ArrayBuffer to a string. * Converts an ArrayBuffer to a string.
* *
* @param {ArrayBuffer} arrayBuffer * @param {ArrayBuffer} arrayBuffer
* @param {boolean} [utf8=true] - Whether to attempt to decode the buffer as UTF-8
* @returns {string} * @returns {string}
* *
* @example * @example
* // returns "hello" * // returns "hello"
* Utils.arrayBufferToStr(Uint8Array.from([104,101,108,108,111]).buffer); * Utils.arrayBufferToStr(Uint8Array.from([104,101,108,108,111]).buffer);
*/ */
arrayBufferToStr: function(arrayBuffer) { arrayBufferToStr: function(arrayBuffer, utf8=true) {
const byteArray = Array.prototype.slice.call(new Uint8Array(arrayBuffer)); const byteArray = Array.prototype.slice.call(new Uint8Array(arrayBuffer));
return Utils.byteArrayToUtf8(byteArray); return utf8 ? Utils.byteArrayToUtf8(byteArray) : Utils.byteArrayToChars(byteArray);
}, },
@@ -903,9 +904,9 @@ const Utils = {
* "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?) * "Pretty" CyberChef recipe formats are designed to be included in the fragment (#) or query (?)
* parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order * parts of the URL. They can also be loaded into CyberChef through the 'Load' interface. In order
* to make this format as readable as possible, various special characters are used unescaped. This * to make this format as readable as possible, various special characters are used unescaped. This
* reduces the amount of percent-encoding included in the URL which is typically difficult to read, * reduces the amount of percent-encoding included in the URL which is typically difficult to read
* as well as substantially increasing the overall length. These characteristics can be quite * and substantially increases the overall length. These characteristics can be quite off-putting
* offputting for users. * for users.
* *
* @param {Object[]} recipeConfig * @param {Object[]} recipeConfig
* @param {boolean} newline - whether to add a newline after each operation * @param {boolean} newline - whether to add a newline after each operation
@@ -922,12 +923,11 @@ const Utils = {
name = op.op.replace(/ /g, "_"); name = op.op.replace(/ /g, "_");
args = JSON.stringify(op.args) args = JSON.stringify(op.args)
.slice(1, -1) // Remove [ and ] as they are implied .slice(1, -1) // Remove [ and ] as they are implied
// We now need to switch double-quoted (") strings to single-quotes (') as these do not // We now need to switch double-quoted (") strings to single quotes (') as single quotes
// need to be percent-encoded. // do not need to be percent-encoded.
.replace(/'/g, "\\'") // Escape single quotes .replace(/'/g, "\\'") // Escape single quotes
.replace(/\\"/g, '"') // Unescape double quotes .replace(/"((?:[^"\\]|\\.)*)"/g, "'$1'") // Replace opening and closing " with '
.replace(/(^|,|{|:)"/g, "$1'") // Replace opening " with ' .replace(/\\"/g, '"'); // Unescape double quotes
.replace(/"(,|:|}|$)/g, "'$1"); // Replace closing " with '
disabled = op.disabled ? "/disabled": ""; disabled = op.disabled ? "/disabled": "";
bp = op.breakpoint ? "/breakpoint" : ""; bp = op.breakpoint ? "/breakpoint" : "";
@@ -953,7 +953,7 @@ const Utils = {
// Parse bespoke recipe format // Parse bespoke recipe format
recipe = recipe.replace(/\n/g, ""); recipe = recipe.replace(/\n/g, "");
let m, let m,
recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/])*)(\/[^)]+)?\)/g, recipeRegex = /([^(]+)\(((?:'[^'\\]*(?:\\.[^'\\]*)*'|[^)/'])*)(\/[^)]+)?\)/g,
recipeConfig = [], recipeConfig = [],
args; args;

View File

@@ -189,6 +189,7 @@ const Categories = [
"Find / Replace", "Find / Replace",
"Regular expression", "Regular expression",
"Offset checker", "Offset checker",
"Hamming Distance",
"Convert distance", "Convert distance",
"Convert area", "Convert area",
"Convert mass", "Convert mass",
@@ -200,6 +201,7 @@ const Categories = [
"Escape string", "Escape string",
"Unescape string", "Unescape string",
"Pseudo-Random Number Generator", "Pseudo-Random Number Generator",
"Sleep",
] ]
}, },
{ {
@@ -212,6 +214,7 @@ const Categories = [
"Windows Filetime to UNIX Timestamp", "Windows Filetime to UNIX Timestamp",
"UNIX Timestamp to Windows Filetime", "UNIX Timestamp to Windows Filetime",
"Extract dates", "Extract dates",
"Sleep",
] ]
}, },
{ {
@@ -323,6 +326,7 @@ const Categories = [
"Remove EXIF", "Remove EXIF",
"Extract EXIF", "Extract EXIF",
"Numberwang", "Numberwang",
"XKCD Random Number",
] ]
}, },
{ {

View File

@@ -30,6 +30,7 @@ import NetBIOS from "../operations/NetBIOS.js";
import PHP from "../operations/PHP.js"; import PHP from "../operations/PHP.js";
import PublicKey from "../operations/PublicKey.js"; import PublicKey from "../operations/PublicKey.js";
import Punycode from "../operations/Punycode.js"; import Punycode from "../operations/Punycode.js";
import Regex from "../operations/Regex.js";
import Rotate from "../operations/Rotate.js"; import Rotate from "../operations/Rotate.js";
import SeqUtils from "../operations/SeqUtils.js"; import SeqUtils from "../operations/SeqUtils.js";
import Shellcode from "../operations/Shellcode.js"; import Shellcode from "../operations/Shellcode.js";
@@ -524,7 +525,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Adds together a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>18.5</code>", description: "Adds together a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>18.5</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -537,7 +538,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Subtracts a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>1.5</code>", description: "Subtracts a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>1.5</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -550,7 +551,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Multiplies a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>40</code>", description: "Multiplies a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>40</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -563,7 +564,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Divides a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>2.5</code>", description: "Divides a list of numbers. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>2.5</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -576,7 +577,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Computes the mean (average) of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5 .5</code> becomes <code>4.75</code>", description: "Computes the mean (average) of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5 .5</code> becomes <code>4.75</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -589,7 +590,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Computes the median of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 1 .5</code> becomes <code>4.5</code>", description: "Computes the median of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 1 .5</code> becomes <code>4.5</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -602,7 +603,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Computes the standard deviation of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>4.089281382128433</code>", description: "Computes the standard deviation of a number list. If an item in the string is not a number it is excluded from the list.<br><br>e.g. <code>0x0a 8 .5</code> becomes <code>4.089281382128433</code>",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Delimiter", name: "Delimiter",
@@ -806,7 +807,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Converts a number to decimal from a given numerical base.", description: "Converts a number to decimal from a given numerical base.",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Radix", name: "Radix",
@@ -818,7 +819,7 @@ const OperationConfig = {
"To Base": { "To Base": {
module: "Default", module: "Default",
description: "Converts a decimal number to a given numerical base.", description: "Converts a decimal number to a given numerical base.",
inputType: "number", inputType: "BigNumber",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -1824,6 +1825,11 @@ const OperationConfig = {
name: "Cisco style", name: "Cisco style",
type: "boolean", type: "boolean",
value: MAC.CISCO_STYLE value: MAC.CISCO_STYLE
},
{
name: "IPv6 interface ID",
type: "boolean",
value: MAC.IPV6_INTERFACE_ID
} }
] ]
}, },
@@ -2058,9 +2064,8 @@ const OperationConfig = {
args: [] args: []
}, },
"Find / Replace": { "Find / Replace": {
module: "Default", module: "Regex",
description: "Replaces all occurrences of the first string with the second.<br><br> Includes support for regular expressions (regex), simple strings and extended strings (which support \\n, \\r, \\t, \\b, \\f and escaped hex bytes using \\x notation, e.g. \\x00 for a null byte).", description: "Replaces all occurrences of the first string with the second.<br><br> Includes support for regular expressions (regex), simple strings and extended strings (which support \\n, \\r, \\t, \\b, \\f and escaped hex bytes using \\x notation, e.g. \\x00 for a null byte).",
manualBake: true,
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
@@ -2068,7 +2073,7 @@ const OperationConfig = {
name: "Find", name: "Find",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: StrUtils.SEARCH_TYPE toggleValues: Regex.SEARCH_TYPE
}, },
{ {
name: "Replace", name: "Replace",
@@ -2078,17 +2083,17 @@ const OperationConfig = {
{ {
name: "Global match", name: "Global match",
type: "boolean", type: "boolean",
value: StrUtils.FIND_REPLACE_GLOBAL, value: Regex.FIND_REPLACE_GLOBAL,
}, },
{ {
name: "Case insensitive", name: "Case insensitive",
type: "boolean", type: "boolean",
value: StrUtils.FIND_REPLACE_CASE, value: Regex.FIND_REPLACE_CASE,
}, },
{ {
name: "Multiline matching", name: "Multiline matching",
type: "boolean", type: "boolean",
value: StrUtils.FIND_REPLACE_MULTILINE, value: Regex.FIND_REPLACE_MULTILINE,
}, },
] ]
@@ -2125,20 +2130,19 @@ const OperationConfig = {
args: [ args: [
{ {
name: "Split delimiter", name: "Split delimiter",
type: "binaryShortString", type: "editableOption",
value: StrUtils.SPLIT_DELIM value: StrUtils.SPLIT_DELIM_OPTIONS
}, },
{ {
name: "Join delimiter", name: "Join delimiter",
type: "option", type: "editableOption",
value: StrUtils.DELIMITER_OPTIONS value: StrUtils.JOIN_DELIM_OPTIONS
} }
] ]
}, },
"Filter": { "Filter": {
module: "Default", module: "Default",
description: "Splits up the input using the specified delimiter and then filters each branch based on a regular expression.", description: "Splits up the input using the specified delimiter and then filters each branch based on a regular expression.",
manualBake: true,
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
@@ -2155,21 +2159,31 @@ const OperationConfig = {
{ {
name: "Invert condition", name: "Invert condition",
type: "boolean", type: "boolean",
value: SeqUtils.SORT_REVERSE value: false
}, },
] ]
}, },
"Strings": { "Strings": {
module: "Default", module: "Regex",
description: "Extracts all strings from the input.", description: "Extracts all strings from the input.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{
name: "Encoding",
type: "option",
value: Extract.ENCODING_LIST
},
{ {
name: "Minimum length", name: "Minimum length",
type: "number", type: "number",
value: Extract.MIN_STRING_LEN value: Extract.MIN_STRING_LEN
}, },
{
name: "Match",
type: "option",
value: Extract.STRING_MATCH_TYPE
},
{ {
name: "Display total", name: "Display total",
type: "boolean", type: "boolean",
@@ -2178,7 +2192,7 @@ const OperationConfig = {
] ]
}, },
"Extract IP addresses": { "Extract IP addresses": {
module: "Default", module: "Regex",
description: "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!", description: "Extracts all IPv4 and IPv6 addresses.<br><br>Warning: Given a string <code>710.65.0.456</code>, this will match <code>10.65.0.45</code> so always check the original input!",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2206,7 +2220,7 @@ const OperationConfig = {
] ]
}, },
"Extract email addresses": { "Extract email addresses": {
module: "Default", module: "Regex",
description: "Extracts all email addresses from the input.", description: "Extracts all email addresses from the input.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2219,7 +2233,7 @@ const OperationConfig = {
] ]
}, },
"Extract MAC addresses": { "Extract MAC addresses": {
module: "Default", module: "Regex",
description: "Extracts all Media Access Control (MAC) addresses from the input.", description: "Extracts all Media Access Control (MAC) addresses from the input.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2232,7 +2246,7 @@ const OperationConfig = {
] ]
}, },
"Extract URLs": { "Extract URLs": {
module: "Default", module: "Regex",
description: "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.", description: "Extracts Uniform Resource Locators (URLs) from the input. The protocol (http, ftp etc.) is required otherwise there will be far too many false positives.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2245,7 +2259,7 @@ const OperationConfig = {
] ]
}, },
"Extract domains": { "Extract domains": {
module: "Default", module: "Regex",
description: "Extracts domain names.<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.", description: "Extracts domain names.<br>Note that this will not include paths. Use <strong>Extract URLs</strong> to find entire URLs.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2258,7 +2272,7 @@ const OperationConfig = {
] ]
}, },
"Extract file paths": { "Extract file paths": {
module: "Default", module: "Regex",
description: "Extracts anything that looks like a Windows or UNIX file path.<br><br>Note that if UNIX is selected, there will likely be a lot of false positives.", description: "Extracts anything that looks like a Windows or UNIX file path.<br><br>Note that if UNIX is selected, there will likely be a lot of false positives.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2281,7 +2295,7 @@ const OperationConfig = {
] ]
}, },
"Extract dates": { "Extract dates": {
module: "Default", module: "Regex",
description: "Extracts dates in the following formats<ul><li><code>yyyy-mm-dd</code></li><li><code>dd/mm/yyyy</code></li><li><code>mm/dd/yyyy</code></li></ul>Dividers can be any of /, -, . or space", description: "Extracts dates in the following formats<ul><li><code>yyyy-mm-dd</code></li><li><code>dd/mm/yyyy</code></li><li><code>mm/dd/yyyy</code></li></ul>Dividers can be any of /, -, . or space",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2294,16 +2308,15 @@ const OperationConfig = {
] ]
}, },
"Regular expression": { "Regular expression": {
module: "Default", module: "Regex",
description: "Define your own regular expression (regex) to search the input data with, optionally choosing from a list of pre-defined patterns.", description: "Define your own regular expression (regex) to search the input data with, optionally choosing from a list of pre-defined patterns.<br><br>Supports extended regex syntax including the 'dot matches all' flag, named capture groups, full unicode coverage (including <code>\\p{}</code> categories and scripts as well as astral codes) and recursive matching.",
manualBake: true,
inputType: "string", inputType: "string",
outputType: "html", outputType: "html",
args: [ args: [
{ {
name: "Built in regexes", name: "Built in regexes",
type: "populateOption", type: "populateOption",
value: StrUtils.REGEX_PRE_POPULATE, value: Regex.REGEX_PRE_POPULATE,
target: 1, target: 1,
}, },
{ {
@@ -2314,22 +2327,37 @@ const OperationConfig = {
{ {
name: "Case insensitive", name: "Case insensitive",
type: "boolean", type: "boolean",
value: StrUtils.REGEX_CASE_INSENSITIVE value: true
}, },
{ {
name: "Multiline matching", name: "^ and $ match at newlines",
type: "boolean", type: "boolean",
value: StrUtils.REGEX_MULTILINE_MATCHING value: true
},
{
name: "Dot matches all",
type: "boolean",
value: false
},
{
name: "Unicode support",
type: "boolean",
value: false
},
{
name: "Astral support",
type: "boolean",
value: false
}, },
{ {
name: "Display total", name: "Display total",
type: "boolean", type: "boolean",
value: StrUtils.DISPLAY_TOTAL value: Regex.DISPLAY_TOTAL
}, },
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
value: StrUtils.OUTPUT_FORMAT value: Regex.OUTPUT_FORMAT
}, },
] ]
}, },
@@ -2418,8 +2446,21 @@ const OperationConfig = {
} }
] ]
}, },
"Sleep": {
module: "Default",
description: "Sleep causes the recipe to wait for a specified number of milliseconds before continuing execution.",
inputType: "ArrayBuffer",
outputType: "ArrayBuffer",
args: [
{
name: "Time (ms)",
type: "number",
value: 1000
}
]
},
"Windows Filetime to UNIX Timestamp": { "Windows Filetime to UNIX Timestamp": {
module: "JSBN", module: "Default",
description: "Converts a Windows Filetime value to a UNIX timestamp.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.", description: "Converts a Windows Filetime value to a UNIX timestamp.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2437,7 +2478,7 @@ const OperationConfig = {
] ]
}, },
"UNIX Timestamp to Windows Filetime": { "UNIX Timestamp to Windows Filetime": {
module: "JSBN", module: "Default",
description: "Converts a UNIX timestamp to a Windows Filetime value.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.", description: "Converts a UNIX timestamp to a Windows Filetime value.<br><br>A Windows Filetime is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 UTC.<br><br>A UNIX timestamp is a 32-bit value representing the number of seconds since January 1, 1970 UTC (the UNIX epoch).<br><br>This operation also supports UNIX timestamps in milliseconds, microseconds and nanoseconds.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
@@ -2515,8 +2556,8 @@ const OperationConfig = {
"Convert distance": { "Convert distance": {
module: "Default", module: "Default",
description: "Converts a unit of distance to another format.", description: "Converts a unit of distance to another format.",
inputType: "number", inputType: "BigNumber",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Input units", name: "Input units",
@@ -2533,8 +2574,8 @@ const OperationConfig = {
"Convert area": { "Convert area": {
module: "Default", module: "Default",
description: "Converts a unit of area to another format.", description: "Converts a unit of area to another format.",
inputType: "number", inputType: "BigNumber",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Input units", name: "Input units",
@@ -2551,8 +2592,8 @@ const OperationConfig = {
"Convert mass": { "Convert mass": {
module: "Default", module: "Default",
description: "Converts a unit of mass to another format.", description: "Converts a unit of mass to another format.",
inputType: "number", inputType: "BigNumber",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Input units", name: "Input units",
@@ -2569,8 +2610,8 @@ const OperationConfig = {
"Convert speed": { "Convert speed": {
module: "Default", module: "Default",
description: "Converts a unit of speed to another format.", description: "Converts a unit of speed to another format.",
inputType: "number", inputType: "BigNumber",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Input units", name: "Input units",
@@ -2587,8 +2628,8 @@ const OperationConfig = {
"Convert data units": { "Convert data units": {
module: "Default", module: "Default",
description: "Converts a unit of data to another format.", description: "Converts a unit of data to another format.",
inputType: "number", inputType: "BigNumber",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Input units", name: "Input units",
@@ -2969,21 +3010,21 @@ const OperationConfig = {
"MD2": { "MD2": {
module: "Hashing", module: "Hashing",
description: "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.", description: "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.<br><br>Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"MD4": { "MD4": {
module: "Hashing", module: "Hashing",
description: "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.<br><br>The security of MD4 has been severely compromised.", description: "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.<br><br>The security of MD4 has been severely compromised.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"MD5": { "MD5": {
module: "Hashing", module: "Hashing",
description: "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.<br><br>However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.", description: "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.<br><br>However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
@@ -3013,21 +3054,21 @@ const OperationConfig = {
"SHA0": { "SHA0": {
module: "Hashing", module: "Hashing",
description: "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.", description: "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"SHA1": { "SHA1": {
module: "Hashing", module: "Hashing",
description: "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.", description: "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.<br><br>However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"SHA2": { "SHA2": {
module: "Hashing", module: "Hashing",
description: "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>", description: "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3040,7 +3081,7 @@ const OperationConfig = {
"SHA3": { "SHA3": {
module: "Hashing", module: "Hashing",
description: "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.<br><br>SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún.", description: "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.<br><br>SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3053,7 +3094,7 @@ const OperationConfig = {
"Keccak": { "Keccak": {
module: "Hashing", module: "Hashing",
description: "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún. It was selected as the winner of the SHA-3 design competition.<br><br>This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.", description: "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún. It was selected as the winner of the SHA-3 design competition.<br><br>This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3066,7 +3107,7 @@ const OperationConfig = {
"Shake": { "Shake": {
module: "Hashing", module: "Hashing",
description: "Shake is an Extendable Output Function (XOF) of the SHA-3 hash algorithm, part of the Keccak family, allowing for variable output length/size.", description: "Shake is an Extendable Output Function (XOF) of the SHA-3 hash algorithm, part of the Keccak family, allowing for variable output length/size.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3085,7 +3126,7 @@ const OperationConfig = {
"RIPEMD": { "RIPEMD": {
module: "Hashing", module: "Hashing",
description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>", description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3098,14 +3139,14 @@ const OperationConfig = {
"HAS-160": { "HAS-160": {
module: "Hashing", module: "Hashing",
description: "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.", description: "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"Whirlpool": { "Whirlpool": {
module: "Hashing", module: "Hashing",
description: "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Wirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>", description: "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Wirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3118,7 +3159,7 @@ const OperationConfig = {
"Snefru": { "Snefru": {
module: "Hashing", module: "Hashing",
description: "Snefru is a cryptographic hash function invented by Ralph Merkle in 1990 while working at Xerox PARC. The function supports 128-bit and 256-bit output. It was named after the Egyptian Pharaoh Sneferu, continuing the tradition of the Khufu and Khafre block ciphers.<br><br>The original design of Snefru was shown to be insecure by Eli Biham and Adi Shamir who were able to use differential cryptanalysis to find hash collisions. The design was then modified by increasing the number of iterations of the main pass of the algorithm from two to eight.", description: "Snefru is a cryptographic hash function invented by Ralph Merkle in 1990 while working at Xerox PARC. The function supports 128-bit and 256-bit output. It was named after the Egyptian Pharaoh Sneferu, continuing the tradition of the Khufu and Khafre block ciphers.<br><br>The original design of Snefru was shown to be insecure by Eli Biham and Adi Shamir who were able to use differential cryptanalysis to find hash collisions. The design was then modified by increasing the number of iterations of the main pass of the algorithm from two to eight.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3136,11 +3177,11 @@ const OperationConfig = {
"HMAC": { "HMAC": {
module: "Hashing", module: "Hashing",
description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.", description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Password", name: "Key",
type: "binaryString", type: "binaryString",
value: "" value: ""
}, },
@@ -3203,7 +3244,7 @@ const OperationConfig = {
"Generate all hashes": { "Generate all hashes": {
module: "Hashing", module: "Hashing",
description: "Generates all available hashes and checksums for the input.", description: "Generates all available hashes and checksums for the input.",
inputType: "string", inputType: "ArrayBuffer",
outputType: "string", outputType: "string",
args: [] args: []
}, },
@@ -3426,15 +3467,10 @@ const OperationConfig = {
outputType: "html", outputType: "html",
args: [ args: [
{ {
name: "Language/File extension", name: "Language",
type: "option", type: "option",
value: Code.LANGUAGES value: Code.LANGUAGES
}, },
{
name: "Display line numbers",
type: "boolean",
value: Code.LINE_NUMS
}
] ]
}, },
"TCP/IP Checksum": { "TCP/IP Checksum": {
@@ -3478,14 +3514,14 @@ const OperationConfig = {
}, },
"Escape string": { "Escape string": {
module: "Default", module: "Default",
description: "Escapes special characters in a string so that they do not cause conflicts. For example, <code>Don't stop me now</code> becomes <code>Don\\'t stop me now</code>.", description: "Escapes special characters in a string so that they do not cause conflicts. For example, <code>Don't stop me now</code> becomes <code>Don\\'t stop me now</code>.<br><br>Supports the following escape sequences:<ul><li><code>\\n</code> (Line feed/newline)</li><li><code>\\r</code> (Carriage return)</li><li><code>\\t</code> (Horizontal tab)</li><li><code>\\b</code> (Backspace)</li><li><code>\\f</code> (Form feed)</li><li><code>\\xnn</code> (Hex, where n is 0-f)</li><li><code>\\\\</code> (Backslash)</li><li><code>\\'</code> (Single quote)</li><li><code>\\&quot;</code> (Double quote)</li></ul>",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [] args: []
}, },
"Unescape string": { "Unescape string": {
module: "Default", module: "Default",
description: "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.", description: "Unescapes characters in a string that have been escaped. For example, <code>Don\\'t stop me now</code> becomes <code>Don't stop me now</code>.<br><br>Supports the following escape sequences:<ul><li><code>\\n</code> (Line feed/newline)</li><li><code>\\r</code> (Carriage return)</li><li><code>\\t</code> (Horizontal tab)</li><li><code>\\b</code> (Backspace)</li><li><code>\\f</code> (Form feed)</li><li><code>\\xnn</code> (Hex, where n is 0-f)</li><li><code>\\\\</code> (Backslash)</li><li><code>\\'</code> (Single quote)</li><li><code>\\&quot;</code> (Double quote)</li></ul>",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [] args: []
@@ -3750,7 +3786,7 @@ const OperationConfig = {
module: "Default", module: "Default",
description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign.", description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign.",
inputType: "string", inputType: "string",
outputType: "number", outputType: "BigNumber",
args: [ args: [
{ {
name: "Scheme", name: "Scheme",
@@ -3778,7 +3814,7 @@ const OperationConfig = {
"To BCD": { "To BCD": {
module: "Default", module: "Default",
description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign", description: "Binary-Coded Decimal (BCD) is a class of binary encodings of decimal numbers where each decimal digit is represented by a fixed number of bits, usually four or eight. Special bit patterns are sometimes used for a sign",
inputType: "number", inputType: "BigNumber",
outputType: "string", outputType: "string",
args: [ args: [
{ {
@@ -3913,6 +3949,36 @@ const OperationConfig = {
} }
] ]
}, },
"Hamming Distance": {
module: "Default",
description: "In information theory, the Hamming distance between two strings of equal length is the number of positions at which the corresponding symbols are different. In other words, it measures the minimum number of substitutions required to change one string into the other, or the minimum number of errors that could have transformed one string into the other. In a more general context, the Hamming distance is one of several string metrics for measuring the edit distance between two sequences.",
inputType: "string",
outputType: "string",
args: [
{
name: "Delimiter",
type: "binaryShortString",
value: StrUtils.HAMMING_DELIM
},
{
name: "Unit",
type: "option",
value: StrUtils.HAMMING_UNIT
},
{
name: "Input type",
type: "option",
value: StrUtils.HAMMING_INPUT_TYPE
}
]
},
"XKCD Random Number": {
module: "Default",
description: "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number.<br><br><a href='https://xkcd.com/221/'>XKCD #221</a>",
inputType: "string",
outputType: "number",
args: []
}
}; };

View File

@@ -11,7 +11,7 @@ import Code from "../../operations/Code.js";
* - xmldom * - xmldom
* - xpath * - xpath
* - jpath * - jpath
* - googlecodeprettify * - highlight.js
* *
* @author n1474335 [n1474335@gmail.com] * @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017 * @copyright Crown Copyright 2017

View File

@@ -10,7 +10,7 @@ import Convert from "../../operations/Convert.js";
import DateTime from "../../operations/DateTime.js"; import DateTime from "../../operations/DateTime.js";
import Endian from "../../operations/Endian.js"; import Endian from "../../operations/Endian.js";
import Entropy from "../../operations/Entropy.js"; import Entropy from "../../operations/Entropy.js";
import Extract from "../../operations/Extract.js"; import Filetime from "../../operations/Filetime.js";
import FileType from "../../operations/FileType.js"; import FileType from "../../operations/FileType.js";
import Hexdump from "../../operations/Hexdump.js"; import Hexdump from "../../operations/Hexdump.js";
import HTML from "../../operations/HTML.js"; import HTML from "../../operations/HTML.js";
@@ -29,6 +29,8 @@ import StrUtils from "../../operations/StrUtils.js";
import Tidy from "../../operations/Tidy.js"; import Tidy from "../../operations/Tidy.js";
import Unicode from "../../operations/Unicode.js"; import Unicode from "../../operations/Unicode.js";
import UUID from "../../operations/UUID.js"; import UUID from "../../operations/UUID.js";
import XKCD from "../../operations/XKCD.js";
/** /**
* Default module. * Default module.
@@ -40,6 +42,7 @@ import UUID from "../../operations/UUID.js";
* - Utils.js * - Utils.js
* - otp * - otp
* - crypto * - crypto
* - bignumber.js
* *
* @author n1474335 [n1474335@gmail.com] * @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017 * @copyright Crown Copyright 2017
@@ -89,7 +92,7 @@ OpModules.Default = {
"Bit shift right": BitwiseOp.runBitShiftRight, "Bit shift right": BitwiseOp.runBitShiftRight,
"XOR": BitwiseOp.runXor, "XOR": BitwiseOp.runXor,
"XOR Brute Force": BitwiseOp.runXorBrute, "XOR Brute Force": BitwiseOp.runXorBrute,
"OR": BitwiseOp.runXor, "OR": BitwiseOp.runOr,
"NOT": BitwiseOp.runNot, "NOT": BitwiseOp.runNot,
"AND": BitwiseOp.runAnd, "AND": BitwiseOp.runAnd,
"ADD": BitwiseOp.runAdd, "ADD": BitwiseOp.runAdd,
@@ -99,17 +102,16 @@ OpModules.Default = {
"Format MAC addresses": MAC.runFormat, "Format MAC addresses": MAC.runFormat,
"Encode NetBIOS Name": NetBIOS.runEncodeName, "Encode NetBIOS Name": NetBIOS.runEncodeName,
"Decode NetBIOS Name": NetBIOS.runDecodeName, "Decode NetBIOS Name": NetBIOS.runDecodeName,
"Regular expression": StrUtils.runRegex,
"Offset checker": StrUtils.runOffsetChecker, "Offset checker": StrUtils.runOffsetChecker,
"To Upper case": StrUtils.runUpper, "To Upper case": StrUtils.runUpper,
"To Lower case": StrUtils.runLower, "To Lower case": StrUtils.runLower,
"Find / Replace": StrUtils.runFindReplace,
"Split": StrUtils.runSplit, "Split": StrUtils.runSplit,
"Filter": StrUtils.runFilter, "Filter": StrUtils.runFilter,
"Escape string": StrUtils.runEscape, "Escape string": StrUtils.runEscape,
"Unescape string": StrUtils.runUnescape, "Unescape string": StrUtils.runUnescape,
"Head": StrUtils.runHead, "Head": StrUtils.runHead,
"Tail": StrUtils.runTail, "Tail": StrUtils.runTail,
"Hamming Distance": StrUtils.runHamming,
"Remove whitespace": Tidy.runRemoveWhitespace, "Remove whitespace": Tidy.runRemoveWhitespace,
"Remove null bytes": Tidy.runRemoveNulls, "Remove null bytes": Tidy.runRemoveNulls,
"Drop bytes": Tidy.runDropBytes, "Drop bytes": Tidy.runDropBytes,
@@ -132,14 +134,7 @@ OpModules.Default = {
"Translate DateTime Format": DateTime.runTranslateFormat, "Translate DateTime Format": DateTime.runTranslateFormat,
"From UNIX Timestamp": DateTime.runFromUnixTimestamp, "From UNIX Timestamp": DateTime.runFromUnixTimestamp,
"To UNIX Timestamp": DateTime.runToUnixTimestamp, "To UNIX Timestamp": DateTime.runToUnixTimestamp,
"Strings": Extract.runStrings, "Sleep": DateTime.runSleep,
"Extract IP addresses": Extract.runIp,
"Extract email addresses": Extract.runEmail,
"Extract MAC addresses": Extract.runMac,
"Extract URLs": Extract.runUrls,
"Extract domains": Extract.runDomains,
"Extract file paths": Extract.runFilePaths,
"Extract dates": Extract.runDates,
"Microsoft Script Decoder": MS.runDecodeScript, "Microsoft Script Decoder": MS.runDecodeScript,
"Entropy": Entropy.runEntropy, "Entropy": Entropy.runEntropy,
"Frequency distribution": Entropy.runFreqDistrib, "Frequency distribution": Entropy.runFreqDistrib,
@@ -166,6 +161,9 @@ OpModules.Default = {
"Mean": Arithmetic.runMean, "Mean": Arithmetic.runMean,
"Median": Arithmetic.runMedian, "Median": Arithmetic.runMedian,
"Standard Deviation": Arithmetic.runStdDev, "Standard Deviation": Arithmetic.runStdDev,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
"XKCD Random Number": XKCD.runRandomNumber,
/* /*

View File

@@ -1,5 +1,4 @@
import IP from "../../operations/IP.js"; import IP from "../../operations/IP.js";
import Filetime from "../../operations/Filetime.js";
/** /**
@@ -21,8 +20,6 @@ OpModules.JSBN = {
"Parse IPv4 header": IP.runParseIPv4Header, "Parse IPv4 header": IP.runParseIPv4Header,
"Change IP format": IP.runChangeIpFormat, "Change IP format": IP.runChangeIpFormat,
"Group IP addresses": IP.runGroupIps, "Group IP addresses": IP.runGroupIps,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
}; };
export default OpModules; export default OpModules;

View File

@@ -18,6 +18,7 @@ import HTTPModule from "./HTTP.js";
import ImageModule from "./Image.js"; import ImageModule from "./Image.js";
import JSBNModule from "./JSBN.js"; import JSBNModule from "./JSBN.js";
import PublicKeyModule from "./PublicKey.js"; import PublicKeyModule from "./PublicKey.js";
import RegexModule from "./Regex.js";
import ShellcodeModule from "./Shellcode.js"; import ShellcodeModule from "./Shellcode.js";
import URLModule from "./URL.js"; import URLModule from "./URL.js";
@@ -34,6 +35,7 @@ Object.assign(
ImageModule, ImageModule,
JSBNModule, JSBNModule,
PublicKeyModule, PublicKeyModule,
RegexModule,
ShellcodeModule, ShellcodeModule,
URLModule URLModule
); );

View File

@@ -0,0 +1,30 @@
import Extract from "../../operations/Extract.js";
import Regex from "../../operations/Regex.js";
/**
* Regex module.
*
* Libraries:
* - XRegExp
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Regex = {
"Regular expression": Regex.runRegex,
"Find / Replace": Regex.runFindReplace,
"Strings": Extract.runStrings,
"Extract IP addresses": Extract.runIp,
"Extract email addresses": Extract.runEmail,
"Extract MAC addresses": Extract.runMac,
"Extract URLs": Extract.runUrls,
"Extract domains": Extract.runDomains,
"Extract file paths": Extract.runFilePaths,
"Extract dates": Extract.runDates,
};
export default OpModules;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import BigNumber from "bignumber.js";
/** /**
@@ -24,11 +25,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runSum: function(input, args) { runSum: function(input, args) {
const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0])); const val = Arithmetic._sum(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -37,11 +38,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runSub: function(input, args) { runSub: function(input, args) {
let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._sub(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -50,11 +51,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runMulti: function(input, args) { runMulti: function(input, args) {
let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._multi(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -63,11 +64,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runDiv: function(input, args) { runDiv: function(input, args) {
let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._div(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -76,11 +77,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runMean: function(input, args) { runMean: function(input, args) {
let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._mean(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -89,11 +90,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runMedian: function(input, args) { runMedian: function(input, args) {
let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._median(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -102,11 +103,11 @@ const Arithmetic = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runStdDev: function(input, args) { runStdDev: function(input, args) {
let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0])); let val = Arithmetic._stdDev(Arithmetic._createNumArray(input, args[0]));
return typeof(val) === "number" ? val : NaN; return val instanceof BigNumber ? val : new BigNumber(NaN);
}, },
@@ -116,7 +117,7 @@ const Arithmetic = {
* @private * @private
* @param {string[]} input * @param {string[]} input
* @param {string} delim * @param {string} delim
* @returns {number[]} * @returns {BigNumber[]}
*/ */
_createNumArray: function(input, delim) { _createNumArray: function(input, delim) {
delim = Utils.charRep[delim || "Space"]; delim = Utils.charRep[delim || "Space"];
@@ -125,13 +126,13 @@ const Arithmetic = {
num; num;
for (let i = 0; i < splitNumbers.length; i++) { for (let i = 0; i < splitNumbers.length; i++) {
if (splitNumbers[i].indexOf(".") >= 0) { try {
num = parseFloat(splitNumbers[i].trim()); num = BigNumber(splitNumbers[i].trim());
} else { if (!num.isNaN()) {
num = parseInt(splitNumbers[i].trim(), 0); numbers.push(num);
} }
if (!isNaN(num)) { } catch (err) {
numbers.push(num); // This line is not a valid number
} }
} }
return numbers; return numbers;
@@ -142,12 +143,12 @@ const Arithmetic = {
* Adds an array of numbers and returns the value. * Adds an array of numbers and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_sum: function(data) { _sum: function(data) {
if (data.length > 0) { if (data.length > 0) {
return data.reduce((acc, curr) => acc + curr); return data.reduce((acc, curr) => acc.plus(curr));
} }
}, },
@@ -156,12 +157,12 @@ const Arithmetic = {
* Subtracts an array of numbers and returns the value. * Subtracts an array of numbers and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_sub: function(data) { _sub: function(data) {
if (data.length > 0) { if (data.length > 0) {
return data.reduce((acc, curr) => acc - curr); return data.reduce((acc, curr) => acc.minus(curr));
} }
}, },
@@ -170,12 +171,12 @@ const Arithmetic = {
* Multiplies an array of numbers and returns the value. * Multiplies an array of numbers and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_multi: function(data) { _multi: function(data) {
if (data.length > 0) { if (data.length > 0) {
return data.reduce((acc, curr) => acc * curr); return data.reduce((acc, curr) => acc.times(curr));
} }
}, },
@@ -184,12 +185,12 @@ const Arithmetic = {
* Divides an array of numbers and returns the value. * Divides an array of numbers and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_div: function(data) { _div: function(data) {
if (data.length > 0) { if (data.length > 0) {
return data.reduce((acc, curr) => acc / curr); return data.reduce((acc, curr) => acc.div(curr));
} }
}, },
@@ -198,12 +199,12 @@ const Arithmetic = {
* Computes mean of a number array and returns the value. * Computes mean of a number array and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_mean: function(data) { _mean: function(data) {
if (data.length > 0) { if (data.length > 0) {
return Arithmetic._sum(data) / data.length; return Arithmetic._sum(data).div(data.length);
} }
}, },
@@ -212,14 +213,14 @@ const Arithmetic = {
* Computes median of a number array and returns the value. * Computes median of a number array and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_median: function (data) { _median: function (data) {
if ((data.length % 2) === 0) { if ((data.length % 2) === 0 && data.length > 0) {
let first, second; let first, second;
data.sort(function(a, b){ data.sort(function(a, b){
return a - b; return a.minus(b);
}); });
first = data[Math.floor(data.length / 2)]; first = data[Math.floor(data.length / 2)];
second = data[Math.floor(data.length / 2) - 1]; second = data[Math.floor(data.length / 2) - 1];
@@ -234,17 +235,17 @@ const Arithmetic = {
* Computes standard deviation of a number array and returns the value. * Computes standard deviation of a number array and returns the value.
* *
* @private * @private
* @param {number[]} data * @param {BigNumber[]} data
* @returns {number} * @returns {BigNumber}
*/ */
_stdDev: function (data) { _stdDev: function (data) {
if (data.length > 0) { if (data.length > 0) {
let avg = Arithmetic._mean(data); let avg = Arithmetic._mean(data);
let devSum = 0; let devSum = new BigNumber(0);
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
devSum += (data[i] - avg) ** 2; devSum = devSum.plus(data[i].minus(avg).pow(2));
} }
return Math.sqrt(devSum / data.length); return devSum.div(data.length).sqrt();
} }
}, },
}; };

View File

@@ -1,4 +1,5 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import BigNumber from "bignumber.js";
/** /**
@@ -61,14 +62,14 @@ const BCD = {
/** /**
* To BCD operation. * To BCD operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
runToBCD: function(input, args) { runToBCD: function(input, args) {
if (isNaN(input)) if (input.isNaN())
return "Invalid input"; return "Invalid input";
if (Math.floor(input) !== input) if (!input.integerValue(BigNumber.ROUND_DOWN).isEqualTo(input))
return "Fractional values are not supported by BCD"; return "Fractional values are not supported by BCD";
const encoding = BCD.ENCODING_LOOKUP[args[0]], const encoding = BCD.ENCODING_LOOKUP[args[0]],
@@ -77,7 +78,7 @@ const BCD = {
outputFormat = args[3]; outputFormat = args[3];
// Split input number up into separate digits // Split input number up into separate digits
const digits = input.toString().split(""); const digits = input.toFixed().split("");
if (digits[0] === "-" || digits[0] === "+") { if (digits[0] === "-" || digits[0] === "+") {
digits.shift(); digits.shift();
@@ -152,7 +153,7 @@ const BCD = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runFromBCD: function(input, args) { runFromBCD: function(input, args) {
const encoding = BCD.ENCODING_LOOKUP[args[0]], const encoding = BCD.ENCODING_LOOKUP[args[0]],
@@ -206,7 +207,7 @@ const BCD = {
output += val.toString(); output += val.toString();
}); });
return parseInt(output, 10); return new BigNumber(output);
}, },
}; };

View File

@@ -1,3 +1,5 @@
import BigNumber from "bignumber.js";
/** /**
* Numerical base operations. * Numerical base operations.
* *
@@ -18,7 +20,7 @@ const Base = {
/** /**
* To Base operation. * To Base operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -39,7 +41,7 @@ const Base = {
* *
* @param {string} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runFrom: function(input, args) { runFrom: function(input, args) {
const radix = args[0] || Base.DEFAULT_RADIX; const radix = args[0] || Base.DEFAULT_RADIX;
@@ -48,14 +50,14 @@ const Base = {
} }
let number = input.replace(/\s/g, "").split("."), let number = input.replace(/\s/g, "").split("."),
result = parseInt(number[0], radix) || 0; result = new BigNumber(number[0], radix) || 0;
if (number.length === 1) return result; if (number.length === 1) return result;
// Fractional part // Fractional part
for (let i = 0; i < number[1].length; i++) { for (let i = 0; i < number[1].length; i++) {
const digit = parseInt(number[1][i], radix); const digit = new BigNumber(number[1][i], radix);
result += digit / Math.pow(radix, i+1); result += digit.div(Math.pow(radix, i+1));
} }
return result; return result;

View File

@@ -2,6 +2,7 @@ import Utils from "../Utils.js";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import forge from "imports-loader?jQuery=>null!node-forge/dist/forge.min.js"; import forge from "imports-loader?jQuery=>null!node-forge/dist/forge.min.js";
import {blowfish as Blowfish} from "sladex-blowfish"; import {blowfish as Blowfish} from "sladex-blowfish";
import BigNumber from "bignumber.js";
/** /**
@@ -520,7 +521,11 @@ DES uses a key length of 8 bytes (64 bits).`;
* @default * @default
*/ */
PRNG_BYTES: 32, PRNG_BYTES: 32,
PRNG_OUTPUT: ["Hex", "Number", "Byte array", "Raw"], /**
* @constant
* @default
*/
PRNG_OUTPUT: ["Hex", "Integer", "Byte array", "Raw"],
/** /**
* Pseudo-Random Number Generator operation. * Pseudo-Random Number Generator operation.
@@ -542,17 +547,17 @@ DES uses a key length of 8 bytes (64 bits).`;
bytes = forge.random.getBytesSync(numBytes); bytes = forge.random.getBytesSync(numBytes);
} }
let value = 0, let value = new BigNumber(0),
i; i;
switch (outputAs) { switch (outputAs) {
case "Hex": case "Hex":
return forge.util.bytesToHex(bytes); return forge.util.bytesToHex(bytes);
case "Number": case "Integer":
for (i = bytes.length - 1; i >= 0; i--) { for (i = bytes.length - 1; i >= 0; i--) {
value = (value * 256) + bytes.charCodeAt(i); value = value.times(256).plus(bytes.charCodeAt(i));
} }
return value.toString(); return value.toFixed();
case "Byte array": case "Byte array":
return JSON.stringify(Utils.strToCharcode(bytes)); return JSON.stringify(Utils.strToCharcode(bytes));
case "Raw": case "Raw":

View File

@@ -1,12 +1,10 @@
import {camelCase, kebabCase, snakeCase} from "lodash"; import {camelCase, kebabCase, snakeCase} from "lodash";
import Utils from "../Utils.js";
import vkbeautify from "vkbeautify"; import vkbeautify from "vkbeautify";
import {DOMParser} from "xmldom"; import {DOMParser} from "xmldom";
import xpath from "xpath"; import xpath from "xpath";
import jpath from "jsonpath"; import jpath from "jsonpath";
import nwmatcher from "nwmatcher"; import nwmatcher from "nwmatcher";
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js"; import hljs from "highlight.js";
/** /**
@@ -24,12 +22,7 @@ const Code = {
* @constant * @constant
* @default * @default
*/ */
LANGUAGES: ["default-code", "default-markup", "bash", "bsh", "c", "cc", "coffee", "cpp", "cs", "csh", "cv", "cxx", "cyc", "htm", "html", "in.tag", "java", "javascript", "js", "json", "m", "mxml", "perl", "pl", "pm", "py", "python", "rb", "rc", "rs", "ruby", "rust", "sh", "uq.val", "xhtml", "xml", "xsl"], LANGUAGES: ["auto detect"].concat(hljs.listLanguages()),
/**
* @constant
* @default
*/
LINE_NUMS: false,
/** /**
* Syntax highlighter operation. * Syntax highlighter operation.
@@ -39,9 +32,13 @@ const Code = {
* @returns {html} * @returns {html}
*/ */
runSyntaxHighlight: function(input, args) { runSyntaxHighlight: function(input, args) {
let language = args[0], const language = args[0];
lineNums = args[1];
return "<code class='prettyprint'>" + prettyPrintOne(Utils.escapeHtml(input), language, lineNums) + "</code>"; if (language === "auto detect") {
return hljs.highlightAuto(input).value;
}
return hljs.highlight(language, input, true).value;
}, },

View File

@@ -60,17 +60,16 @@ const Convert = {
/** /**
* Convert distance operation. * Convert distance operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runDistance: function (input, args) { runDistance: function (input, args) {
let inputUnits = args[0], let inputUnits = args[0],
outputUnits = args[1]; outputUnits = args[1];
input = input * Convert.DISTANCE_FACTOR[inputUnits]; input = input.times(Convert.DISTANCE_FACTOR[inputUnits]);
return input / Convert.DISTANCE_FACTOR[outputUnits]; return input.div(Convert.DISTANCE_FACTOR[outputUnits]);
// TODO Remove rounding errors (e.g. 1.000000000001)
}, },
@@ -141,16 +140,16 @@ const Convert = {
/** /**
* Convert data units operation. * Convert data units operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runDataSize: function (input, args) { runDataSize: function (input, args) {
let inputUnits = args[0], let inputUnits = args[0],
outputUnits = args[1]; outputUnits = args[1];
input = input * Convert.DATA_FACTOR[inputUnits]; input = input.times(Convert.DATA_FACTOR[inputUnits]);
return input / Convert.DATA_FACTOR[outputUnits]; return input.div(Convert.DATA_FACTOR[outputUnits]);
}, },
@@ -221,16 +220,16 @@ const Convert = {
/** /**
* Convert area operation. * Convert area operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runArea: function (input, args) { runArea: function (input, args) {
let inputUnits = args[0], let inputUnits = args[0],
outputUnits = args[1]; outputUnits = args[1];
input = input * Convert.AREA_FACTOR[inputUnits]; input = input.times(Convert.AREA_FACTOR[inputUnits]);
return input / Convert.AREA_FACTOR[outputUnits]; return input.div(Convert.AREA_FACTOR[outputUnits]);
}, },
@@ -332,16 +331,16 @@ const Convert = {
/** /**
* Convert mass operation. * Convert mass operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runMass: function (input, args) { runMass: function (input, args) {
let inputUnits = args[0], let inputUnits = args[0],
outputUnits = args[1]; outputUnits = args[1];
input = input * Convert.MASS_FACTOR[inputUnits]; input = input.times(Convert.MASS_FACTOR[inputUnits]);
return input / Convert.MASS_FACTOR[outputUnits]; return input.div(Convert.MASS_FACTOR[outputUnits]);
}, },
@@ -397,16 +396,16 @@ const Convert = {
/** /**
* Convert speed operation. * Convert speed operation.
* *
* @param {number} input * @param {BigNumber} input
* @param {Object[]} args * @param {Object[]} args
* @returns {number} * @returns {BigNumber}
*/ */
runSpeed: function (input, args) { runSpeed: function (input, args) {
let inputUnits = args[0], let inputUnits = args[0],
outputUnits = args[1]; outputUnits = args[1];
input = input * Convert.SPEED_FACTOR[inputUnits]; input = input.times(Convert.SPEED_FACTOR[inputUnits]);
return input / Convert.SPEED_FACTOR[outputUnits]; return input.div(Convert.SPEED_FACTOR[outputUnits]);
}, },
}; };

View File

@@ -189,6 +189,20 @@ const DateTime = {
}, },
/**
* Sleep operation.
*
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
runSleep: async function(input, args) {
const ms = args[0];
await new Promise(r => setTimeout(r, ms));
return input;
},
/** /**
* @constant * @constant
*/ */

View File

@@ -1,3 +1,6 @@
import XRegExp from "xregexp";
/** /**
* Identifier extraction operations. * Identifier extraction operations.
* *
@@ -26,6 +29,11 @@ const Extract = {
match; match;
while ((match = searchRegex.exec(input))) { while ((match = searchRegex.exec(input))) {
// Moves pointer when an empty string is matched (prevents infinite loop)
if (match.index === searchRegex.lastIndex) {
searchRegex.lastIndex++;
}
if (removeRegex && removeRegex.test(match[0])) if (removeRegex && removeRegex.test(match[0]))
continue; continue;
total++; total++;
@@ -43,7 +51,20 @@ const Extract = {
* @constant * @constant
* @default * @default
*/ */
MIN_STRING_LEN: 3, MIN_STRING_LEN: 4,
/**
* @constant
* @default
*/
STRING_MATCH_TYPE: [
"[ASCII]", "Alphanumeric + punctuation (A)", "All printable chars (A)", "Null-terminated strings (A)",
"[Unicode]", "Alphanumeric + punctuation (U)", "All printable chars (U)", "Null-terminated strings (U)"
],
/**
* @constant
* @default
*/
ENCODING_LIST: ["Single byte", "16-bit littleendian", "16-bit bigendian", "All"],
/** /**
* @constant * @constant
* @default * @default
@@ -58,10 +79,59 @@ const Extract = {
* @returns {string} * @returns {string}
*/ */
runStrings: function(input, args) { runStrings: function(input, args) {
let minLen = args[0] || Extract.MIN_STRING_LEN, const encoding = args[0],
displayTotal = args[1], minLen = args[1],
strings = "[A-Z\\d/\\-:.,_$%'\"()<>= !\\[\\]{}@]", matchType = args[2],
regex = new RegExp(strings + "{" + minLen + ",}", "ig"); displayTotal = args[3],
alphanumeric = "A-Z\\d",
punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@",
printable = "\x20-\x7e",
uniAlphanumeric = "\\pL\\pN",
uniPunctuation = "\\pP\\pZ",
uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP";
let strings = "";
switch (matchType) {
case "Alphanumeric + punctuation (A)":
strings = `[${alphanumeric + punctuation}]`;
break;
case "All printable chars (A)":
case "Null-terminated strings (A)":
strings = `[${printable}]`;
break;
case "Alphanumeric + punctuation (U)":
strings = `[${uniAlphanumeric + uniPunctuation}]`;
break;
case "All printable chars (U)":
case "Null-terminated strings (U)":
strings = `[${uniPrintable}]`;
break;
}
// UTF-16 support is hacked in by allowing null bytes on either side of the matched chars
switch (encoding) {
case "All":
strings = `(\x00?${strings}\x00?)`;
break;
case "16-bit littleendian":
strings = `(${strings}\x00)`;
break;
case "16-bit bigendian":
strings = `(\x00${strings})`;
break;
case "Single byte":
default:
break;
}
strings = `${strings}{${minLen},}`;
if (matchType.includes("Null-terminated")) {
strings += "\x00";
}
const regex = new XRegExp(strings, "ig");
return Extract._search(input, regex, null, displayTotal); return Extract._search(input, regex, null, displayTotal);
}, },
@@ -137,7 +207,7 @@ const Extract = {
*/ */
runEmail: function(input, args) { runEmail: function(input, args) {
let displayTotal = args[0], let displayTotal = args[0],
regex = /\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}/ig; regex = /\b\w[-.\w]*@[-\w]+(?:\.[-\w]+)*\.[A-Z]{2,4}\b/ig;
return Extract._search(input, regex, null, displayTotal); return Extract._search(input, regex, null, displayTotal);
}, },
@@ -217,7 +287,7 @@ const Extract = {
includeUnixPath = args[1], includeUnixPath = args[1],
displayTotal = args[2], displayTotal = args[2],
winDrive = "[A-Z]:\\\\", winDrive = "[A-Z]:\\\\",
winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)]{0,61}", winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}",
winExt = "[A-Z\\d]{1,6}", winExt = "[A-Z\\d]{1,6}",
winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName + winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName +
"(?:\\." + winExt + ")?", "(?:\\." + winExt + ")?",

View File

@@ -1,4 +1,4 @@
import {BigInteger} from "jsbn"; import BigNumber from "bignumber.js";
/** /**
* Windows Filetime operations. * Windows Filetime operations.
@@ -35,27 +35,29 @@ const Filetime = {
let units = args[0], let units = args[0],
format = args[1]; format = args[1];
if (!input) return "";
if (format === "Hex") { if (format === "Hex") {
input = new BigInteger(input, 16); input = new BigNumber(input, 16);
} else { } else {
input = new BigInteger(input); input = new BigNumber(input);
} }
input = input.subtract(new BigInteger("116444736000000000")); input = input.minus(new BigNumber("116444736000000000"));
if (units === "Seconds (s)"){ if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000")); input = input.dividedBy(new BigNumber("10000000"));
} else if (units === "Milliseconds (ms)") { } else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000")); input = input.dividedBy(new BigNumber("10000"));
} else if (units === "Microseconds (μs)") { } else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10")); input = input.dividedBy(new BigNumber("10"));
} else if (units === "Nanoseconds (ns)") { } else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100")); input = input.multipliedBy(new BigNumber("100"));
} else { } else {
throw "Unrecognised unit"; throw "Unrecognised unit";
} }
return input.toString(); return input.toFixed();
}, },
@@ -71,26 +73,28 @@ const Filetime = {
let units = args[0], let units = args[0],
format = args[1]; format = args[1];
input = new BigInteger(input); if (!input) return "";
input = new BigNumber(input);
if (units === "Seconds (s)"){ if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000")); input = input.multipliedBy(new BigNumber("10000000"));
} else if (units === "Milliseconds (ms)") { } else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000")); input = input.multipliedBy(new BigNumber("10000"));
} else if (units === "Microseconds (μs)") { } else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10")); input = input.multiplyiedBy(new BigNumber("10"));
} else if (units === "Nanoseconds (ns)") { } else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100")); input = input.dividedBy(new BigNumber("100"));
} else { } else {
throw "Unrecognised unit"; throw "Unrecognised unit";
} }
input = input.add(new BigInteger("116444736000000000")); input = input.plus(new BigNumber("116444736000000000"));
if (format === "Hex"){ if (format === "Hex"){
return input.toString(16); return input.toString(16);
} else { } else {
return input.toString(); return input.toFixed();
} }
}, },

View File

@@ -1,4 +1,4 @@
import {UAS_parser as UAParser} from "../lib/uas_parser.js"; import UAParser from "ua-parser-js";
/** /**
@@ -46,20 +46,22 @@ const HTTP = {
* @returns {string} * @returns {string}
*/ */
runParseUserAgent: function(input, args) { runParseUserAgent: function(input, args) {
const ua = UAParser.parse(input); const ua = UAParser(input);
return `Browser
return "Type: " + ua.type + "\n" + Name: ${ua.browser.name || "unknown"}
"Family: " + ua.uaFamily + "\n" + Version: ${ua.browser.version || "unknown"}
"Name: " + ua.uaName + "\n" + Device
"URL: " + ua.uaUrl + "\n" + Model: ${ua.device.model || "unknown"}
"Company: " + ua.uaCompany + "\n" + Type: ${ua.device.type || "unknown"}
"Company URL: " + ua.uaCompanyUrl + "\n\n" + Vendor: ${ua.device.vendor || "unknown"}
"OS Family: " + ua.osFamily + "\n" + Engine
"OS Name: " + ua.osName + "\n" + Name: ${ua.engine.name || "unknown"}
"OS URL: " + ua.osUrl + "\n" + Version: ${ua.engine.version || "unknown"}
"OS Company: " + ua.osCompany + "\n" + OS
"OS Company URL: " + ua.osCompanyUrl + "\n" + Name: ${ua.os.name || "unknown"}
"Device Type: " + ua.deviceType + "\n"; Version: ${ua.os.version || "unknown"}
CPU
Architecture: ${ua.cpu.architecture || "unknown"}`;
}, },

View File

@@ -1,5 +1,5 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import CryptoApi from "crypto-api"; import CryptoApi from "babel-loader!crypto-api";
import MD6 from "node-md6"; import MD6 from "node-md6";
import * as SHA3 from "js-sha3"; import * as SHA3 from "js-sha3";
import Checksum from "./Checksum.js"; import Checksum from "./Checksum.js";
@@ -20,22 +20,22 @@ const Hash = {
* Generic hash function. * Generic hash function.
* *
* @param {string} name * @param {string} name
* @param {string} input * @param {ArrayBuffer} input
* @param {Object} [options={}]
* @returns {string} * @returns {string}
*/ */
runHash: function(name, input) { runHash: function(name, input, options={}) {
const hasher = CryptoApi.hasher(name); const msg = Utils.arrayBufferToStr(input, false),
hasher.state.message = input; hasher = CryptoApi.getHasher(name, options);
hasher.state.length += input.length; hasher.update(msg);
hasher.process(); return CryptoApi.encoder.toHex(hasher.finalize());
return hasher.finalize().stringify("hex");
}, },
/** /**
* MD2 operation. * MD2 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -47,7 +47,7 @@ const Hash = {
/** /**
* MD4 operation. * MD4 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -59,7 +59,7 @@ const Hash = {
/** /**
* MD5 operation. * MD5 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -103,7 +103,7 @@ const Hash = {
/** /**
* SHA0 operation. * SHA0 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -115,7 +115,7 @@ const Hash = {
/** /**
* SHA1 operation. * SHA1 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -133,7 +133,7 @@ const Hash = {
/** /**
* SHA2 operation. * SHA2 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -152,7 +152,7 @@ const Hash = {
/** /**
* SHA3 operation. * SHA3 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -190,7 +190,7 @@ const Hash = {
/** /**
* Keccak operation. * Keccak operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -233,7 +233,7 @@ const Hash = {
/** /**
* Shake operation. * Shake operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -269,7 +269,7 @@ const Hash = {
/** /**
* RIPEMD operation. * RIPEMD operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -282,7 +282,7 @@ const Hash = {
/** /**
* HAS-160 operation. * HAS-160 operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -300,7 +300,7 @@ const Hash = {
/** /**
* Whirlpool operation. * Whirlpool operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
@@ -324,14 +324,15 @@ const Hash = {
/** /**
* Snefru operation. * Snefru operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
runSnefru: function (input, args) { runSnefru: function (input, args) {
const rounds = args[0], return Hash.runHash("snefru", input, {
size = args[1]; rounds: args[0],
return Hash.runHash(`snefru-${rounds}-${size}`, input); length: args[1]
});
}, },
@@ -358,71 +359,83 @@ const Hash = {
"HAS160", "HAS160",
"Whirlpool", "Whirlpool",
"Whirlpool-0", "Whirlpool-0",
"Whirlpool-T" "Whirlpool-T",
"Snefru"
], ],
/** /**
* HMAC operation. * HMAC operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
runHMAC: function (input, args) { runHMAC: function (input, args) {
const password = args[0], const key = args[0],
hashFunc = args[1].toLowerCase(), hashFunc = args[1].toLowerCase(),
hmac = CryptoApi.mac("hmac", password, hashFunc, {}); msg = Utils.arrayBufferToStr(input, false),
hasher = CryptoApi.getHasher(hashFunc);
hmac.update(input); // Horrible shim to fix constructor bug. Reported in nf404/crypto-api#8
return hmac.finalize().stringify("hex"); hasher.reset = () => {
hasher.state = {};
const tmp = new hasher.constructor();
hasher.state = tmp.state;
};
const mac = CryptoApi.getHmac(CryptoApi.encoder.fromUtf(key), hasher);
mac.update(msg);
return CryptoApi.encoder.toHex(mac.finalize());
}, },
/** /**
* Generate all hashes operation. * Generate all hashes operation.
* *
* @param {string} input * @param {ArrayBuffer} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
runAll: function (input, args) { runAll: function (input, args) {
let byteArray = Utils.strToByteArray(input), const arrayBuffer = input,
output = "MD2: " + Hash.runMD2(input, []) + str = Utils.arrayBufferToStr(arrayBuffer, false),
"\nMD4: " + Hash.runMD4(input, []) + byteArray = new Uint8Array(arrayBuffer),
"\nMD5: " + Hash.runMD5(input, []) + output = "MD2: " + Hash.runMD2(arrayBuffer, []) +
"\nMD6: " + Hash.runMD6(input, []) + "\nMD4: " + Hash.runMD4(arrayBuffer, []) +
"\nSHA0: " + Hash.runSHA0(input, []) + "\nMD5: " + Hash.runMD5(arrayBuffer, []) +
"\nSHA1: " + Hash.runSHA1(input, []) + "\nMD6: " + Hash.runMD6(str, []) +
"\nSHA2 224: " + Hash.runSHA2(input, ["224"]) + "\nSHA0: " + Hash.runSHA0(arrayBuffer, []) +
"\nSHA2 256: " + Hash.runSHA2(input, ["256"]) + "\nSHA1: " + Hash.runSHA1(arrayBuffer, []) +
"\nSHA2 384: " + Hash.runSHA2(input, ["384"]) + "\nSHA2 224: " + Hash.runSHA2(arrayBuffer, ["224"]) +
"\nSHA2 512: " + Hash.runSHA2(input, ["512"]) + "\nSHA2 256: " + Hash.runSHA2(arrayBuffer, ["256"]) +
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) + "\nSHA2 384: " + Hash.runSHA2(arrayBuffer, ["384"]) +
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) + "\nSHA2 512: " + Hash.runSHA2(arrayBuffer, ["512"]) +
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) + "\nSHA3 224: " + Hash.runSHA3(arrayBuffer, ["224"]) +
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) + "\nSHA3 256: " + Hash.runSHA3(arrayBuffer, ["256"]) +
"\nKeccak 224: " + Hash.runKeccak(input, ["224"]) + "\nSHA3 384: " + Hash.runSHA3(arrayBuffer, ["384"]) +
"\nKeccak 256: " + Hash.runKeccak(input, ["256"]) + "\nSHA3 512: " + Hash.runSHA3(arrayBuffer, ["512"]) +
"\nKeccak 384: " + Hash.runKeccak(input, ["384"]) + "\nKeccak 224: " + Hash.runKeccak(arrayBuffer, ["224"]) +
"\nKeccak 512: " + Hash.runKeccak(input, ["512"]) + "\nKeccak 256: " + Hash.runKeccak(arrayBuffer, ["256"]) +
"\nShake 128: " + Hash.runShake(input, ["128", 256]) + "\nKeccak 384: " + Hash.runKeccak(arrayBuffer, ["384"]) +
"\nShake 256: " + Hash.runShake(input, ["256", 512]) + "\nKeccak 512: " + Hash.runKeccak(arrayBuffer, ["512"]) +
"\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) + "\nShake 128: " + Hash.runShake(arrayBuffer, ["128", 256]) +
"\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) + "\nShake 256: " + Hash.runShake(arrayBuffer, ["256", 512]) +
"\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) + "\nRIPEMD-128: " + Hash.runRIPEMD(arrayBuffer, ["128"]) +
"\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) + "\nRIPEMD-160: " + Hash.runRIPEMD(arrayBuffer, ["160"]) +
"\nHAS-160: " + Hash.runHAS(input, []) + "\nRIPEMD-256: " + Hash.runRIPEMD(arrayBuffer, ["256"]) +
"\nWhirlpool-0: " + Hash.runWhirlpool(input, ["Whirlpool-0"]) + "\nRIPEMD-320: " + Hash.runRIPEMD(arrayBuffer, ["320"]) +
"\nWhirlpool-T: " + Hash.runWhirlpool(input, ["Whirlpool-T"]) + "\nHAS-160: " + Hash.runHAS(arrayBuffer, []) +
"\nWhirlpool: " + Hash.runWhirlpool(input, ["Whirlpool"]) + "\nWhirlpool-0: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-0"]) +
"\nWhirlpool-T: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-T"]) +
"\nWhirlpool: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool"]) +
"\n\nChecksums:" + "\n\nChecksums:" +
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) + "\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) + "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) + "\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) + "\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) + "\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
"\nCRC-16: " + Checksum.runCRC16(input, []) + "\nCRC-16: " + Checksum.runCRC16(str, []) +
"\nCRC-32: " + Checksum.runCRC32(input, []); "\nCRC-32: " + Checksum.runCRC32(str, []);
return output; return output;
}, },

View File

@@ -34,6 +34,11 @@ const MAC = {
* @default * @default
*/ */
CISCO_STYLE: false, CISCO_STYLE: false,
/**
* @constant
* @default
*/
IPV6_INTERFACE_ID: false,
/** /**
* Format MAC addresses operation. * Format MAC addresses operation.
@@ -50,6 +55,7 @@ const MAC = {
dashDelim = args[2], dashDelim = args[2],
colonDelim = args[3], colonDelim = args[3],
ciscoStyle = args[4], ciscoStyle = args[4],
ipv6IntID = args[5],
outputList = [], outputList = [],
macs = input.toLowerCase().split(/[,\s\r\n]+/); macs = input.toLowerCase().split(/[,\s\r\n]+/);
@@ -57,23 +63,32 @@ const MAC = {
let cleanMac = mac.replace(/[:.-]+/g, ""), let cleanMac = mac.replace(/[:.-]+/g, ""),
macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"), macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"),
macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"), macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"),
macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."); macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."),
macIPv6 = cleanMac.slice(0, 6) + "fffe" + cleanMac.slice(6);
macIPv6 = macIPv6.replace(/(.{4}(?=.))/g, "$1:");
let bite = parseInt(macIPv6.slice(0, 2), 16) ^ 2;
bite = bite.toString(16).padStart(2, "0");
macIPv6 = bite + macIPv6.slice(2);
if (outputCase === "Lower only") { if (outputCase === "Lower only") {
if (noDelim) outputList.push(cleanMac); if (noDelim) outputList.push(cleanMac);
if (dashDelim) outputList.push(macHyphen); if (dashDelim) outputList.push(macHyphen);
if (colonDelim) outputList.push(macColon); if (colonDelim) outputList.push(macColon);
if (ciscoStyle) outputList.push(macCisco); if (ciscoStyle) outputList.push(macCisco);
if (ipv6IntID) outputList.push(macIPv6);
} else if (outputCase === "Upper only") { } else if (outputCase === "Upper only") {
if (noDelim) outputList.push(cleanMac.toUpperCase()); if (noDelim) outputList.push(cleanMac.toUpperCase());
if (dashDelim) outputList.push(macHyphen.toUpperCase()); if (dashDelim) outputList.push(macHyphen.toUpperCase());
if (colonDelim) outputList.push(macColon.toUpperCase()); if (colonDelim) outputList.push(macColon.toUpperCase());
if (ciscoStyle) outputList.push(macCisco.toUpperCase()); if (ciscoStyle) outputList.push(macCisco.toUpperCase());
if (ipv6IntID) outputList.push(macIPv6.toUpperCase());
} else { } else {
if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase()); if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase());
if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase()); if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase());
if (colonDelim) outputList.push(macColon, macColon.toUpperCase()); if (colonDelim) outputList.push(macColon, macColon.toUpperCase());
if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase()); if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase());
if (ipv6IntID) outputList.push(macIPv6, macIPv6.toUpperCase());
} }
outputList.push( outputList.push(

View File

@@ -0,0 +1,278 @@
import XRegExp from "xregexp";
import Utils from "../Utils.js";
/**
* Regex operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*
* @namespace
*/
const Regex = {
/**
* @constant
* @default
*/
REGEX_PRE_POPULATE: [
{
name: "User defined",
value: ""
},
{
name: "IPv4 address",
value: "(?:(?:\\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})?"
},
{
name: "IPv6 address",
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
},
{
name: "Email address",
value: "\\b(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})\\b"
},
{
name: "URL",
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
},
{
name: "Domain",
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
},
{
name: "Windows file path",
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)~]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
},
{
name: "UNIX file path",
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
},
{
name: "MAC address",
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
},
{
name: "Date (yyyy-mm-dd)",
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
},
{
name: "Date (dd/mm/yyyy)",
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
},
{
name: "Date (mm/dd/yyyy)",
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
},
{
name: "Strings",
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
},
],
/**
* @constant
* @default
*/
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
/**
* @constant
* @default
*/
DISPLAY_TOTAL: false,
/**
* Regular expression operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runRegex: function(input, args) {
const userRegex = args[1],
i = args[2],
m = args[3],
s = args[4],
u = args[5],
a = args[6],
displayTotal = args[7],
outputFormat = args[8];
let modifiers = "g";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (s) modifiers += "s";
if (u) modifiers += "u";
if (a) modifiers += "A";
if (userRegex && userRegex !== "^" && userRegex !== "$") {
try {
const regex = new XRegExp(userRegex, modifiers);
switch (outputFormat) {
case "Highlight matches":
return Regex._regexHighlight(input, regex, displayTotal);
case "List matches":
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, false));
case "List capture groups":
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, false, true));
case "List matches with capture groups":
return Utils.escapeHtml(Regex._regexList(input, regex, displayTotal, true, true));
default:
return "Error: Invalid output format";
}
} catch (err) {
return "Invalid regex. Details: " + err.message;
}
} else {
return Utils.escapeHtml(input);
}
},
/**
* @constant
* @default
*/
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"],
/**
* @constant
* @default
*/
FIND_REPLACE_GLOBAL: true,
/**
* @constant
* @default
*/
FIND_REPLACE_CASE: false,
/**
* @constant
* @default
*/
FIND_REPLACE_MULTILINE: true,
/**
* Find / Replace operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFindReplace: function(input, args) {
let find = args[0].string,
type = args[0].option,
replace = args[1],
g = args[2],
i = args[3],
m = args[4],
modifiers = "";
if (g) modifiers += "g";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (type === "Regex") {
find = new RegExp(find, modifiers);
return input.replace(find, replace);
}
if (type.indexOf("Extended") === 0) {
find = Utils.parseEscapedChars(find);
}
find = new RegExp(Utils.escapeRegex(find), modifiers);
return input.replace(find, replace);
},
/**
* Adds HTML highlights to matches within a string.
*
* @private
* @param {string} input
* @param {RegExp} regex
* @param {boolean} displayTotal
* @returns {string}
*/
_regexHighlight: function(input, regex, displayTotal) {
let output = "",
m,
hl = 1,
i = 0,
total = 0;
while ((m = regex.exec(input))) {
// Moves pointer when an empty string is matched (prevents infinite loop)
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// Add up to match
output += Utils.escapeHtml(input.slice(i, m.index));
// Add match with highlighting
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
// Switch highlight
hl = hl === 1 ? 2 : 1;
i = regex.lastIndex;
total++;
}
// Add all after final match
output += Utils.escapeHtml(input.slice(i, input.length));
if (displayTotal)
output = "Total found: " + total + "\n\n" + output;
return output;
},
/**
* Creates a string listing the matches within a string.
*
* @private
* @param {string} input
* @param {RegExp} regex
* @param {boolean} displayTotal
* @param {boolean} matches - Display full match
* @param {boolean} captureGroups - Display each of the capture groups separately
* @returns {string}
*/
_regexList: function(input, regex, displayTotal, matches, captureGroups) {
let output = "",
total = 0,
match;
while ((match = regex.exec(input))) {
// Moves pointer when an empty string is matched (prevents infinite loop)
if (match.index === regex.lastIndex) {
regex.lastIndex++;
}
total++;
if (matches) {
output += match[0] + "\n";
}
if (captureGroups) {
for (let i = 1; i < match.length; i++) {
if (matches) {
output += " Group " + i + ": ";
}
output += match[i] + "\n";
}
}
}
if (displayTotal)
output = "Total found: " + total + "\n\n" + output;
return output.slice(0, -1);
},
};
export default Regex;

View File

@@ -12,128 +12,6 @@ import Utils from "../Utils.js";
*/ */
const StrUtils = { const StrUtils = {
/**
* @constant
* @default
*/
REGEX_PRE_POPULATE: [
{
name: "User defined",
value: ""
},
{
name: "IPv4 address",
value: "(?:(?:\\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})?"
},
{
name: "IPv6 address",
value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})"
},
{
name: "Email address",
value: "(\\w[-.\\w]*)@([-\\w]+(?:\\.[-\\w]+)*)\\.([A-Za-z]{2,4})"
},
{
name: "URL",
value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?"
},
{
name: "Domain",
value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
},
{
name: "Windows file path",
value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?"
},
{
name: "UNIX file path",
value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+"
},
{
name: "MAC address",
value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}"
},
{
name: "Date (yyyy-mm-dd)",
value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])"
},
{
name: "Date (dd/mm/yyyy)",
value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)"
},
{
name: "Date (mm/dd/yyyy)",
value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)"
},
{
name: "Strings",
value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}"
},
],
/**
* @constant
* @default
*/
REGEX_CASE_INSENSITIVE: true,
/**
* @constant
* @default
*/
REGEX_MULTILINE_MATCHING: true,
/**
* @constant
* @default
*/
OUTPUT_FORMAT: ["Highlight matches", "List matches", "List capture groups", "List matches with capture groups"],
/**
* @constant
* @default
*/
DISPLAY_TOTAL: false,
/**
* Regular expression operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runRegex: function(input, args) {
let userRegex = args[1],
i = args[2],
m = args[3],
displayTotal = args[4],
outputFormat = args[5],
modifiers = "g";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (userRegex && userRegex !== "^" && userRegex !== "$") {
try {
const regex = new RegExp(userRegex, modifiers);
switch (outputFormat) {
case "Highlight matches":
return StrUtils._regexHighlight(input, regex, displayTotal);
case "List matches":
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, false));
case "List capture groups":
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, false, true));
case "List matches with capture groups":
return Utils.escapeHtml(StrUtils._regexList(input, regex, displayTotal, true, true));
default:
return "Error: Invalid output format";
}
} catch (err) {
return "Invalid regex. Details: " + err.message;
}
} else {
return Utils.escapeHtml(input);
}
},
/** /**
* @constant * @constant
* @default * @default
@@ -187,68 +65,28 @@ const StrUtils = {
* @constant * @constant
* @default * @default
*/ */
SEARCH_TYPE: ["Regex", "Extended (\\n, \\t, \\x...)", "Simple string"], SPLIT_DELIM_OPTIONS: [
{name: "Comma", value: ","},
{name: "Space", value: " "},
{name: "Line feed", value: "\\n"},
{name: "CRLF", value: "\\r\\n"},
{name: "Semi-colon", value: ";"},
{name: "Colon", value: ":"},
{name: "Nothing (separate chars)", value: ""}
],
/** /**
* @constant * @constant
* @default * @default
*/ */
FIND_REPLACE_GLOBAL: true, JOIN_DELIM_OPTIONS: [
/** {name: "Line feed", value: "\\n"},
* @constant {name: "CRLF", value: "\\r\\n"},
* @default {name: "Space", value: " "},
*/ {name: "Comma", value: ","},
FIND_REPLACE_CASE: false, {name: "Semi-colon", value: ";"},
/** {name: "Colon", value: ":"},
* @constant {name: "Nothing (join chars)", value: ""}
* @default ],
*/
FIND_REPLACE_MULTILINE: true,
/**
* Find / Replace operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFindReplace: function(input, args) {
let find = args[0].string,
type = args[0].option,
replace = args[1],
g = args[2],
i = args[3],
m = args[4],
modifiers = "";
if (g) modifiers += "g";
if (i) modifiers += "i";
if (m) modifiers += "m";
if (type === "Regex") {
find = new RegExp(find, modifiers);
return input.replace(find, replace);
}
if (type.indexOf("Extended") === 0) {
find = Utils.parseEscapedChars(find);
}
find = new RegExp(Utils.escapeRegex(find), modifiers);
return input.replace(find, replace);
},
/**
* @constant
* @default
*/
SPLIT_DELIM: ",",
/**
* @constant
* @default
*/
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
/** /**
* Split operation. * Split operation.
@@ -258,14 +96,20 @@ const StrUtils = {
* @returns {string} * @returns {string}
*/ */
runSplit: function(input, args) { runSplit: function(input, args) {
let splitDelim = args[0] || StrUtils.SPLIT_DELIM, let splitDelim = args[0],
joinDelim = Utils.charRep[args[1]], joinDelim = args[1],
sections = input.split(splitDelim); sections = input.split(splitDelim);
return sections.join(joinDelim); return sections.join(joinDelim);
}, },
/**
* @constant
* @default
*/
DELIMITER_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon", "Nothing (separate chars)"],
/** /**
* Filter operation. * Filter operation.
* *
@@ -510,80 +354,71 @@ const StrUtils = {
/** /**
* Adds HTML highlights to matches within a string. * @constant
* * @default
* @private
* @param {string} input
* @param {RegExp} regex
* @param {boolean} displayTotal
* @returns {string}
*/ */
_regexHighlight: function(input, regex, displayTotal) { HAMMING_DELIM: "\\n\\n",
let output = "", /**
m, * @constant
hl = 1, * @default
i = 0, */
total = 0; HAMMING_INPUT_TYPE: ["Raw string", "Hex"],
/**
while ((m = regex.exec(input))) { * @constant
// Add up to match * @default
output += Utils.escapeHtml(input.slice(i, m.index)); */
HAMMING_UNIT: ["Byte", "Bit"],
// Add match with highlighting
output += "<span class='hl"+hl+"'>" + Utils.escapeHtml(m[0]) + "</span>";
// Switch highlight
hl = hl === 1 ? 2 : 1;
i = regex.lastIndex;
total++;
}
// Add all after final match
output += Utils.escapeHtml(input.slice(i, input.length));
if (displayTotal)
output = "Total found: " + total + "\n\n" + output;
return output;
},
/** /**
* Creates a string listing the matches within a string. * Hamming Distance operation.
*
* @author GCHQ Contributor [2]
* *
* @private
* @param {string} input * @param {string} input
* @param {RegExp} regex * @param {Object[]} args
* @param {boolean} displayTotal
* @param {boolean} matches - Display full match
* @param {boolean} captureGroups - Display each of the capture groups separately
* @returns {string} * @returns {string}
*/ */
_regexList: function(input, regex, displayTotal, matches, captureGroups) { runHamming: function(input, args) {
let output = "", const delim = args[0],
total = 0, byByte = args[1] === "Byte",
match; inputType = args[2],
samples = input.split(delim);
while ((match = regex.exec(input))) { if (samples.length !== 2) {
total++; return "Error: You can only calculae the edit distance between 2 strings. Please ensure exactly two inputs are provided, separated by the specified delimiter.";
if (matches) { }
output += match[0] + "\n";
} if (samples[0].length !== samples[1].length) {
if (captureGroups) { return "Error: Both inputs must be of the same length.";
for (let i = 1; i < match.length; i++) { }
if (matches) {
output += " Group " + i + ": "; if (inputType === "Hex") {
} samples[0] = Utils.fromHex(samples[0]);
output += match[i] + "\n"; samples[1] = Utils.fromHex(samples[1]);
} else {
samples[0] = Utils.strToByteArray(samples[0]);
samples[1] = Utils.strToByteArray(samples[1]);
}
let dist = 0;
for (let i = 0; i < samples[0].length; i++) {
const lhs = samples[0][i],
rhs = samples[1][i];
if (byByte && lhs !== rhs) {
dist++;
} else if (!byByte) {
let xord = lhs ^ rhs;
while (xord) {
dist++;
xord &= xord - 1;
} }
} }
} }
if (displayTotal) return dist.toString();
output = "Total found: " + total + "\n\n" + output;
return output;
}, },
}; };

View File

@@ -27,7 +27,7 @@ const Unicode = {
*/ */
runUnescape: function(input, args) { runUnescape: function(input, args) {
let prefix = Unicode._prefixToRegex[args[0]], let prefix = Unicode._prefixToRegex[args[0]],
regex = new RegExp(prefix+"([a-f\\d]{4,6})", "ig"), regex = new RegExp(prefix+"([a-f\\d]{4})", "ig"),
output = "", output = "",
m, m,
i = 0; i = 0;

26
src/core/operations/XKCD.js Executable file
View File

@@ -0,0 +1,26 @@
/**
* XKCD operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*
* @namespace
*/
const XKCD = {
/**
* XKCD Random Number operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {number}
*/
runRandomNumber: function(input, args) {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
},
};
export default XKCD;

View File

@@ -377,6 +377,7 @@ App.prototype.loadURIParams = function() {
window.location.href.split("#")[1] || window.location.href.split("#")[1] ||
window.location.hash; window.location.hash;
this.uriParams = Utils.parseURIParams(params); this.uriParams = Utils.parseURIParams(params);
this.autoBakePause = true;
// Read in recipe from URI params // Read in recipe from URI params
if (this.uriParams.recipe) { if (this.uriParams.recipe) {
@@ -387,35 +388,29 @@ App.prototype.loadURIParams = function() {
} else if (this.uriParams.op) { } else if (this.uriParams.op) {
// If there's no recipe, look for single operations // If there's no recipe, look for single operations
this.manager.recipe.clearRecipe(); this.manager.recipe.clearRecipe();
try {
this.manager.recipe.addOperation(this.uriParams.op);
} catch (err) {
// If no exact match, search for nearest match and add that
const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
if (matchedOps.length) {
this.manager.recipe.addOperation(matchedOps[0].name);
}
// Populate search with the string // Search for nearest match and add it
const search = document.getElementById("search"); const matchedOps = this.manager.ops.filterOperations(this.uriParams.op, false);
if (matchedOps.length) {
search.value = this.uriParams.op; this.manager.recipe.addOperation(matchedOps[0].name);
search.dispatchEvent(new Event("search"));
} }
// Populate search with the string
const search = document.getElementById("search");
search.value = this.uriParams.op;
search.dispatchEvent(new Event("search"));
} }
// Read in input data from URI params // Read in input data from URI params
if (this.uriParams.input) { if (this.uriParams.input) {
this.autoBakePause = true;
try { try {
const inputData = Utils.fromBase64(this.uriParams.input); const inputData = Utils.fromBase64(this.uriParams.input);
this.setInput(inputData); this.setInput(inputData);
} catch (err) { } catch (err) {}
} finally {
this.autoBakePause = false;
}
} }
this.autoBakePause = false;
this.autoBake(); this.autoBake();
}; };
@@ -443,6 +438,7 @@ App.prototype.getRecipeConfig = function() {
/** /**
* Given a recipe configuration, sets the recipe to that configuration. * Given a recipe configuration, sets the recipe to that configuration.
* *
* @fires Manager#statechange
* @param {Object[]} recipeConfig - The recipe configuration * @param {Object[]} recipeConfig - The recipe configuration
*/ */
App.prototype.setRecipeConfig = function(recipeConfig) { App.prototype.setRecipeConfig = function(recipeConfig) {

View File

@@ -382,10 +382,13 @@ ControlsWaiter.prototype.supportButtonClick = function(e) {
const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/"); const saveLink = this.generateStateUrl(true, true, null, "https://gchq.github.io/CyberChef/");
if (reportBugInfo) { if (reportBugInfo) {
reportBugInfo.innerHTML = "* Version: " + PKG_VERSION + "\n" + reportBugInfo.innerHTML = `* Version: ${PKG_VERSION + (typeof INLINE === "undefined" ? "" : "s")}
"* Compile time: " + COMPILE_TIME + "\n" + * Compile time: ${COMPILE_TIME}
"* User-Agent: \n" + navigator.userAgent + "\n" + * User-Agent:
"* [Link to reproduce](" + saveLink + ")\n\n"; ${navigator.userAgent}
* [Link to reproduce](${saveLink})
`;
} }
}; };

View File

@@ -110,6 +110,15 @@ HTMLOperation.prototype.highlightSearchString = function(searchStr, namePos, des
} }
if (this.description && descPos >= 0) { if (this.description && descPos >= 0) {
// Find HTML tag offsets
const re = /<[^>]+>/g;
let match;
while ((match = re.exec(this.description))) {
// If the search string occurs within an HTML tag, return without highlighting it.
if (descPos >= match.index && descPos <= (match.index + match[0].length))
return;
}
this.description = this.description.slice(0, descPos) + "<b><u>" + this.description = this.description.slice(0, descPos) + "<b><u>" +
this.description.slice(descPos, descPos + searchStr.length) + "</u></b>" + this.description.slice(descPos, descPos + searchStr.length) + "</u></b>" +
this.description.slice(descPos + searchStr.length); this.description.slice(descPos + searchStr.length);

View File

@@ -1,4 +1,5 @@
import LoaderWorker from "worker-loader?inline&fallback=false!./LoaderWorker.js"; import LoaderWorker from "worker-loader?inline&fallback=false!./LoaderWorker.js";
import Utils from "../core/Utils.js";
/** /**
@@ -61,9 +62,14 @@ InputWaiter.prototype.set = function(input) {
if (input instanceof File) { if (input instanceof File) {
this.setFile(input); this.setFile(input);
inputText.value = ""; inputText.value = "";
this.setInputInfo(input.size, null);
} else { } else {
inputText.value = input; inputText.value = input;
this.closeFile();
window.dispatchEvent(this.manager.statechange); window.dispatchEvent(this.manager.statechange);
const lines = input.length < (this.app.options.ioDisplayThreshold * 1024) ?
input.count("\n") + 1 : null;
this.setInputInfo(input.length, lines);
} }
}; };
@@ -81,6 +87,7 @@ InputWaiter.prototype.setFile = function(file) {
fileType = document.getElementById("input-file-type"), fileType = document.getElementById("input-file-type"),
fileLoaded = document.getElementById("input-file-loaded"); fileLoaded = document.getElementById("input-file-loaded");
this.fileBuffer = new ArrayBuffer();
fileOverlay.style.display = "block"; fileOverlay.style.display = "block";
fileName.textContent = file.name; fileName.textContent = file.name;
fileSize.textContent = file.size.toLocaleString() + " bytes"; fileSize.textContent = file.size.toLocaleString() + " bytes";
@@ -100,21 +107,28 @@ InputWaiter.prototype.setInputInfo = function(length, lines) {
width = width < 2 ? 2 : width; width = width < 2 ? 2 : width;
const lengthStr = length.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); const lengthStr = length.toString().padStart(width, " ").replace(/ /g, "&nbsp;");
const linesStr = lines.toString().padStart(width, " ").replace(/ /g, "&nbsp;"); let msg = "length: " + lengthStr;
document.getElementById("input-info").innerHTML = "length: " + lengthStr + "<br>lines: " + linesStr; if (typeof lines === "number") {
const linesStr = lines.toString().padStart(width, " ").replace(/ /g, "&nbsp;");
msg += "<br>lines: " + linesStr;
}
document.getElementById("input-info").innerHTML = msg;
}; };
/** /**
* Handler for input scroll events. * Handler for input change events.
* Scrolls the highlighter pane to match the input textarea position and updates history state.
* *
* @param {event} e * @param {event} e
* *
* @fires Manager#statechange * @fires Manager#statechange
*/ */
InputWaiter.prototype.inputChange = function(e) { InputWaiter.prototype.inputChange = function(e) {
// Ignore this function if the input is a File
if (this.fileBuffer) return;
// Remove highlighting from input and output panes as the offsets might be different now // Remove highlighting from input and output panes as the offsets might be different now
this.manager.highlighter.removeHighlights(); this.manager.highlighter.removeHighlights();
@@ -123,18 +137,47 @@ InputWaiter.prototype.inputChange = function(e) {
// Update the input metadata info // Update the input metadata info
const inputText = this.get(); const inputText = this.get();
const lines = inputText.count("\n") + 1; const lines = inputText.length < (this.app.options.ioDisplayThreshold * 1024) ?
inputText.count("\n") + 1 : null;
this.setInputInfo(inputText.length, lines); this.setInputInfo(inputText.length, lines);
if (e && this.badKeys.indexOf(e.keyCode) < 0) {
if (this.badKeys.indexOf(e.keyCode) < 0) {
// Fire the statechange event as the input has been modified // Fire the statechange event as the input has been modified
window.dispatchEvent(this.manager.statechange); window.dispatchEvent(this.manager.statechange);
} }
}; };
/**
* Handler for input paste events.
* Checks that the size of the input is below the display limit, otherwise treats it as a file/blob.
*
* @param {event} e
*/
InputWaiter.prototype.inputPaste = function(e) {
const pastedData = e.clipboardData.getData("Text");
if (pastedData.length < (this.app.options.ioDisplayThreshold * 1024)) {
this.inputChange(e);
} else {
e.preventDefault();
e.stopPropagation();
const file = new File([pastedData], "PastedData", {
type: "text/plain",
lastModified: Date.now()
});
this.loaderWorker = new LoaderWorker();
this.loaderWorker.addEventListener("message", this.handleLoaderMessage.bind(this));
this.loaderWorker.postMessage({"file": file});
this.set(file);
return false;
}
};
/** /**
* Handler for input dragover events. * Handler for input dragover events.
* Gives the user a visual cue to show that items can be dropped here. * Gives the user a visual cue to show that items can be dropped here.
@@ -221,11 +264,28 @@ InputWaiter.prototype.handleLoaderMessage = function(e) {
if (r.hasOwnProperty("fileBuffer")) { if (r.hasOwnProperty("fileBuffer")) {
log.debug("Input file loaded"); log.debug("Input file loaded");
this.fileBuffer = r.fileBuffer; this.fileBuffer = r.fileBuffer;
this.displayFilePreview();
window.dispatchEvent(this.manager.statechange); window.dispatchEvent(this.manager.statechange);
} }
}; };
/**
* Shows a chunk of the file in the input behind the file overlay.
*/
InputWaiter.prototype.displayFilePreview = function() {
const inputText = document.getElementById("input-text"),
fileSlice = this.fileBuffer.slice(0, 4096);
inputText.style.overflow = "hidden";
inputText.classList.add("blur");
inputText.value = Utils.printable(Utils.arrayBufferToStr(fileSlice));
if (this.fileBuffer.byteLength > 4096) {
inputText.value += "[truncated]...";
}
};
/** /**
* Handler for file close events. * Handler for file close events.
*/ */
@@ -233,6 +293,9 @@ InputWaiter.prototype.closeFile = function() {
if (this.loaderWorker) this.loaderWorker.terminate(); if (this.loaderWorker) this.loaderWorker.terminate();
this.fileBuffer = null; this.fileBuffer = null;
document.getElementById("input-file").style.display = "none"; document.getElementById("input-file").style.display = "none";
const inputText = document.getElementById("input-text");
inputText.style.overflow = "auto";
inputText.classList.remove("blur");
}; };

View File

@@ -47,7 +47,7 @@ self.loadFile = function(file) {
}; };
reader.onerror = function(e) { reader.onerror = function(e) {
self.postMessage({"error": file.error.message}); self.postMessage({"error": reader.error.message});
}; };
seek(); seek();

View File

@@ -132,7 +132,8 @@ Manager.prototype.initialiseEventListeners = function() {
this.addDynamicListener("#rec-list", "operationremove", this.recipe.opRemove.bind(this.recipe)); this.addDynamicListener("#rec-list", "operationremove", this.recipe.opRemove.bind(this.recipe));
// Input // Input
this.addMultiEventListener("#input-text", "keyup paste", this.input.inputChange, this.input); this.addMultiEventListener("#input-text", "keyup", this.input.inputChange, this.input);
this.addMultiEventListener("#input-text", "paste", this.input.inputPaste, this.input);
document.getElementById("reset-layout").addEventListener("click", this.app.resetLayout.bind(this.app)); document.getElementById("reset-layout").addEventListener("click", this.app.resetLayout.bind(this.app));
document.getElementById("clr-io").addEventListener("click", this.input.clearIoClick.bind(this.input)); document.getElementById("clr-io").addEventListener("click", this.input.clearIoClick.bind(this.input));
this.addListeners("#input-text,#input-file", "dragover", this.input.inputDragover, this.input); this.addListeners("#input-text,#input-file", "dragover", this.input.inputDragover, this.input);

View File

@@ -167,7 +167,8 @@ OperationsWaiter.prototype.opListCreate = function(e) {
OperationsWaiter.prototype.enableOpsListPopovers = function(el) { OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
$(el).find("[data-toggle=popover]").addBack("[data-toggle=popover]") $(el).find("[data-toggle=popover]").addBack("[data-toggle=popover]")
.popover({trigger: "manual"}) .popover({trigger: "manual"})
.on("mouseenter", function() { .on("mouseenter", function(e) {
if (e.buttons > 0) return; // Mouse button held down - likely dragging an opertion
const _this = this; const _this = this;
$(this).popover("show"); $(this).popover("show");
$(".popover").on("mouseleave", function () { $(".popover").on("mouseleave", function () {
@@ -178,7 +179,7 @@ OperationsWaiter.prototype.enableOpsListPopovers = function(el) {
setTimeout(function() { setTimeout(function() {
// Determine if the popover associated with this element is being hovered over // Determine if the popover associated with this element is being hovered over
if ($(_this).data("bs.popover") && if ($(_this).data("bs.popover") &&
!$(_this).data("bs.popover").$tip.is(":hover")) { ($(_this).data("bs.popover").$tip && !$(_this).data("bs.popover").$tip.is(":hover"))) {
$(_this).popover("hide"); $(_this).popover("hide");
} }
}, 50); }, 50);

View File

@@ -64,7 +64,7 @@ OutputWaiter.prototype.set = function(data, type, duration, preserveBuffer) {
outputText.value = ""; outputText.value = "";
outputHtml.innerHTML = data; outputHtml.innerHTML = data;
this.dishStr = Utils.stripHtmlTags(data, true); this.dishStr = Utils.unescapeHtml(Utils.stripHtmlTags(data, true));
length = data.length; length = data.length;
lines = this.dishStr.count("\n") + 1; lines = this.dishStr.count("\n") + 1;
@@ -128,6 +128,13 @@ OutputWaiter.prototype.setFile = function(buf) {
fileOverlay.style.display = "block"; fileOverlay.style.display = "block";
fileSize.textContent = file.size.toLocaleString() + " bytes"; fileSize.textContent = file.size.toLocaleString() + " bytes";
// Display preview slice in the background
const outputText = document.getElementById("output-text"),
fileSlice = this.dishBuffer.slice(0, 4096);
outputText.classList.add("blur");
outputText.value = Utils.printable(Utils.arrayBufferToStr(fileSlice));
}; };
@@ -137,6 +144,7 @@ OutputWaiter.prototype.setFile = function(buf) {
OutputWaiter.prototype.closeFile = function() { OutputWaiter.prototype.closeFile = function() {
this.dishBuffer = null; this.dishBuffer = null;
document.getElementById("output-file").style.display = "none"; document.getElementById("output-file").style.display = "none";
document.getElementById("output-text").classList.remove("blur");
}; };
@@ -163,6 +171,7 @@ OutputWaiter.prototype.displayFileSlice = function() {
sliceTo = parseInt(sliceToEl.value, 10), sliceTo = parseInt(sliceToEl.value, 10),
str = Utils.arrayBufferToStr(this.dishBuffer.slice(sliceFrom, sliceTo)); str = Utils.arrayBufferToStr(this.dishBuffer.slice(sliceFrom, sliceTo));
document.getElementById("output-text").classList.remove("blur");
showFileOverlay.style.display = "block"; showFileOverlay.style.display = "block";
this.set(str, "string", new Date().getTime() - startTime, true); this.set(str, "string", new Date().getTime() - startTime, true);
}; };
@@ -177,6 +186,7 @@ OutputWaiter.prototype.showFileOverlayClick = function(e) {
const outputFile = document.getElementById("output-file"), const outputFile = document.getElementById("output-file"),
showFileOverlay = e.target; showFileOverlay = e.target;
document.getElementById("output-text").classList.add("blur");
outputFile.style.display = "block"; outputFile.style.display = "block";
showFileOverlay.style.display = "none"; showFileOverlay.style.display = "none";
this.setOutputInfo(this.dishBuffer.byteLength, null, 0); this.setOutputInfo(this.dishBuffer.byteLength, null, 0);

View File

@@ -59,6 +59,9 @@
"for i in range(additional): Pylon()", "for i in range(additional): Pylon()",
"(creating unresolved tension...", "(creating unresolved tension...",
"Symlinking emacs and vim to ed...", "Symlinking emacs and vim to ed...",
"Training branch predictor...",
"Timing cache hits...",
"Speculatively executing recipes..."
]; ];
// Shuffle array using Durstenfeld algorithm // Shuffle array using Durstenfeld algorithm
@@ -84,7 +87,9 @@
changeLoadingMsg(); changeLoadingMsg();
window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500); window.loadingMsgsInt = setInterval(changeLoadingMsg, (Math.random() * 2000) + 1500);
</script> </script>
<% if (!htmlWebpackPlugin.options.inline) { %> <% if (htmlWebpackPlugin.options.inline) { %>
<meta name="robots" content="noindex" />
<% } else { %>
<script type="application/ld+json"> <script type="application/ld+json">
<% print(JSON.stringify(require("../static/structuredData.json"))); %> <% print(JSON.stringify(require("../static/structuredData.json"))); %>
</script> </script>
@@ -115,7 +120,7 @@
<span id="notice"> <span id="notice">
<script type="text/javascript"> <script type="text/javascript">
// Must be text/javascript rather than application/javascript otherwise IE won't recognise it... // Must be text/javascript rather than application/javascript otherwise IE won't recognise it...
if (navigator.userAgent && navigator.userAgent.match(/MSIE \d\d?\./)) { if (navigator.userAgent && navigator.userAgent.match(/Trident/)) {
document.write("Internet Explorer is not supported, please use Firefox or Chrome instead"); document.write("Internet Explorer is not supported, please use Firefox or Chrome instead");
alert("Internet Explorer is not supported, please use Firefox or Chrome instead"); alert("Internet Explorer is not supported, please use Firefox or Chrome instead");
} }
@@ -180,8 +185,9 @@
</div> </div>
<div class="textarea-wrapper no-select"> <div class="textarea-wrapper no-select">
<div id="input-highlighter" class="no-select"></div> <div id="input-highlighter" class="no-select"></div>
<textarea id="input-text"></textarea> <textarea id="input-text" spellcheck="false"></textarea>
<div id="input-file"> <div id="input-file">
<div class="file-overlay"></div>
<div style="position: relative; height: 100%;"> <div style="position: relative; height: 100%;">
<div class="card"> <div class="card">
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/> <img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
@@ -215,9 +221,10 @@
<div class="textarea-wrapper"> <div class="textarea-wrapper">
<div id="output-highlighter" class="no-select"></div> <div id="output-highlighter" class="no-select"></div>
<div id="output-html"></div> <div id="output-html"></div>
<textarea id="output-text" readonly="readonly"></textarea> <textarea id="output-text" readonly="readonly" spellcheck="false"></textarea>
<img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png') %>" alt="Show file overlay" title="Show file overlay"/> <img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png') %>" alt="Show file overlay" title="Show file overlay"/>
<div id="output-file"> <div id="output-file">
<div class="file-overlay"></div>
<div style="position: relative; height: 100%;"> <div style="position: relative; height: 100%;">
<div class="card"> <div class="card">
<img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/> <img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
@@ -230,7 +237,7 @@
</span> </span>
<input type="number" class="form-control" id="output-file-slice-from" placeholder="From" value="0" step="1024" min="0"> <input type="number" class="form-control" id="output-file-slice-from" placeholder="From" value="0" step="1024" min="0">
<div class="input-group-addon">to</div> <div class="input-group-addon">to</div>
<input type="number" class="form-control" id="output-file-slice-to" placeholder="To" value="1024" step="1024" min="0"> <input type="number" class="form-control" id="output-file-slice-to" placeholder="To" value="2048" step="1024" min="0">
</div> </div>
</div> </div>
</div> </div>
@@ -369,8 +376,8 @@
<label for="errorTimeout"> Operation error timeout in ms (0 for never)</label> <label for="errorTimeout"> Operation error timeout in ms (0 for never)</label>
</div> </div>
<div class="option-item"> <div class="option-item">
<input type="number" option="outputFileThreshold" id="outputFileThreshold" /> <input type="number" option="ioDisplayThreshold" id="ioDisplayThreshold" />
<label for="outputFileThreshold"> Size threshold for treating the output as a file (KiB)</label> <label for="ioDisplayThreshold"> Size threshold for treating the input and output as a file (KiB)</label>
</div> </div>
<div class="option-item"> <div class="option-item">
<select option="logLevel" id="logLevel"> <select option="logLevel" id="logLevel">

View File

@@ -47,7 +47,7 @@ function main() {
attemptHighlight: true, attemptHighlight: true,
theme: "classic", theme: "classic",
useMetaKey: false, useMetaKey: false,
outputFileThreshold: 1024, ioDisplayThreshold: 512,
logLevel: "info" logLevel: "info"
}; };

33
src/web/static/sitemap.js Normal file
View File

@@ -0,0 +1,33 @@
import sm from "sitemap";
import OperationConfig from "../../core/config/MetaConfig.js";
/**
* Generates an XML sitemap for all CyberChef operations and a number of recipes.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
const sitemap = sm.createSitemap({
hostname: "https://gchq.github.io/CyberChef",
});
sitemap.add({
url: "/",
changefreq: "weekly",
priority: 1.0
});
for (let op in OperationConfig) {
sitemap.add({
url: `/?op=${encodeURIComponent(op)}`,
changeFreq: "yearly",
priority: 0.5
});
}
const xml = sitemap.toString();
console.log(xml); // eslint-disable-line no-console

View File

@@ -7,7 +7,7 @@
*/ */
/* Libraries */ /* Libraries */
import "google-code-prettify/src/prettify.css"; import "highlight.js/styles/vs.css";
/* Frameworks */ /* Frameworks */
import "./vendors/bootstrap.less"; import "./vendors/bootstrap.less";

View File

@@ -84,10 +84,17 @@
top: 0; top: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: var(--title-background-colour);
display: none; display: none;
} }
.file-overlay {
position: absolute;
opacity: 0.8;
background-color: var(--title-background-colour);
width: 100%;
height: 100%;
}
#show-file-overlay { #show-file-overlay {
position: absolute; position: absolute;
right: 15px; right: 15px;

View File

@@ -30,6 +30,7 @@ import "./tests/operations/MS.js";
import "./tests/operations/PHP.js"; import "./tests/operations/PHP.js";
import "./tests/operations/NetBIOS.js"; import "./tests/operations/NetBIOS.js";
import "./tests/operations/OTP.js"; import "./tests/operations/OTP.js";
import "./tests/operations/Regex.js";
import "./tests/operations/StrUtils.js"; import "./tests/operations/StrUtils.js";
import "./tests/operations/SeqUtils.js"; import "./tests/operations/SeqUtils.js";

View File

@@ -37,7 +37,7 @@ TestRegister.addTests([
}, },
{ {
name: "Fork, (expect) Error, Merge", name: "Fork, (expect) Error, Merge",
input: "1\n2\na\n4", input: "1.1\n2.5\na\n3.4",
expectedError: true, expectedError: true,
recipeConfig: [ recipeConfig: [
{ {
@@ -45,8 +45,8 @@ TestRegister.addTests([
args: ["\n", "\n", false], args: ["\n", "\n", false],
}, },
{ {
op: "To Base", op: "Object Identifier to Hex",
args: [16], args: [],
}, },
{ {
op: "Merge", op: "Merge",

View File

@@ -415,4 +415,264 @@ TestRegister.addTests([
} }
] ]
}, },
{
name: "MD5: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "4f4f02e2646545aa8fc42f613c9aa068",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "MD5",
"args": []
}
]
},
{
name: "SHA1: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "2c5400aaee7e8ad4cad29bfbdf8d566924e5442c",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA1",
"args": []
}
]
},
{
name: "SHA2 224: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "66c166eba2529ecc44a7b7b218a64a8e3892f873c8d231e8e3c1ef3d",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA2",
"args": ["224"]
}
]
},
{
name: "SHA2 256: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "186ffd22c3af83995afa4a0316023f81a7f8834fd16bd2ed358c7b1b8182ba41",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA2",
"args": ["256"]
}
]
},
{
name: "SHA2 384: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "2a6369ffec550ea0bfb810b3b8246b7d6b7f060edfae88441f0f242b98b91549aa4ff407de38c6d03b5f377434ad2f36",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA2",
"args": ["384"]
}
]
},
{
name: "SHA2 512: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "544ae686522c05b70d12b460b5b39ea0a758eb4027333edbded7e2b3f467aa605804f71f54db61a7bbe50e6e7898510635efd6721fd418a9ea4d05b286d12806",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA2",
"args": ["512"]
}
]
},
{
name: "SHA3 224: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "e2c07562ee8c2d73e3dd309efea257159abd0948ebc14619bab9ffb3",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA3",
"args": ["224"]
}
]
},
{
name: "SHA3 256: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "55a55275387586afd1ed64757c9ee7ad1d96ca81a5b7b742c40127856ee78a2d",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA3",
"args": ["256"]
}
]
},
{
name: "SHA3 384: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "39f8796dd697dc39e5a943817833793f2c29dc0d1adc7037854c0fb51e135c6bd26b113240c4fb1e3fcc16ff8690c91a",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA3",
"args": ["384"]
}
]
},
{
name: "SHA3 512: Complex bytes",
input: "10dc10e32010de10d010dc10d810d910d010e12e",
expectedOutput: "ee9061bed83b1ad1e2fc4a4bac72a5a65a23a0fa55193b808af0a3e2013b718a5a3e40474765b4f93d1b2747401058a5b58099cc890a159db92b2ea816287add",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "SHA3",
"args": ["512"]
}
]
},
{
name: "MD5: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "2e93ee2b5b2a337ccb678c7db12eff1b",
recipeConfig: [
{
"op": "MD5",
"args": []
}
]
},
{
name: "SHA1: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "87f483b1515dce672be044bf183ae8103e3b2d4b",
recipeConfig: [
{
"op": "SHA1",
"args": []
}
]
},
{
name: "SHA2 224: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "563ca57b500157717961a5fa87ce42c6db76a488c98ea9c28d620770",
recipeConfig: [
{
"op": "SHA2",
"args": ["224"]
}
]
},
{
name: "SHA2 256: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "36abbb4622ffff06aa3e3cea266765601b21457bb3755a0a2cf0a206422863c1",
recipeConfig: [
{
"op": "SHA2",
"args": ["256"]
}
]
},
{
name: "SHA2 384: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "140b929391a66c9a943bcd60e6964f0d19526d3bc9ba020fbb29aae51cddb8e63a78784d8770f1d36335bf4efff8c131",
recipeConfig: [
{
"op": "SHA2",
"args": ["384"]
}
]
},
{
name: "SHA2 512: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "04a7887c400bf647b7c67b9a0f1ada70d176348b5afdfebea184f7e62748849828669c7b5160be99455fdbf625589bd1689c003bc06ef60c39607d825a2f8838",
recipeConfig: [
{
"op": "SHA2",
"args": ["512"]
}
]
},
{
name: "SHA3 224: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "b3ffc9620949f879cb561fb240452494e2566cb4e4f701a85715e14f",
recipeConfig: [
{
"op": "SHA3",
"args": ["224"]
}
]
},
{
name: "SHA3 256: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "b5f247d725b46546c832502cd07bccb5d4de0c41a6665d3944ed2cc55cd9d156",
recipeConfig: [
{
"op": "SHA3",
"args": ["256"]
}
]
},
{
name: "SHA3 384: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "93e87b9aa8c9c47eba146adac357c525b418b71677f6db01d1c760d87b058682e639c8d43a8bfe91529cecd9800700e3",
recipeConfig: [
{
"op": "SHA3",
"args": ["384"]
}
]
},
{
name: "SHA3 512: UTF-8",
input: "ნუ პანიკას",
expectedOutput: "1fbc484b5184982561795162757717474eebc846ca9f10029a75a54cdd897a7b48d1db42f2478fa1d5d213a0dd7de71c809cb19c60581ba57e7289d29408fb36",
recipeConfig: [
{
"op": "SHA3",
"args": ["512"]
}
]
},
]); ]);

View File

@@ -0,0 +1,59 @@
/**
* StrUtils tests.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import TestRegister from "../../TestRegister.js";
TestRegister.addTests([
{
name: "Regex: non-HTML op",
input: "/<>",
expectedOutput: "/<>",
recipeConfig: [
{
"op": "Regular expression",
"args": ["User defined", "", true, true, false, false, false, false, "Highlight matches"]
},
{
"op": "Remove whitespace",
"args": [true, true, true, true, true, false]
}
],
},
{
name: "Regex: Dot matches all",
input: "Hello\nWorld",
expectedOutput: "Hello\nWorld",
recipeConfig: [
{
"op": "Regular expression",
"args": ["User defined", ".+", true, true, true, false, false, false, "List matches"]
}
],
},
{
name: "Regex: Astral off",
input: "𝌆😆",
expectedOutput: "",
recipeConfig: [
{
"op": "Regular expression",
"args": ["User defined", "\\pS", true, true, false, false, false, false, "List matches"]
}
],
},
{
name: "Regex: Astral on",
input: "𝌆😆",
expectedOutput: "𝌆\n😆",
recipeConfig: [
{
"op": "Regular expression",
"args": ["User defined", "\\pS", true, true, false, false, true, false, "List matches"]
}
],
}
]);

View File

@@ -8,21 +8,6 @@
import TestRegister from "../../TestRegister.js"; import TestRegister from "../../TestRegister.js";
TestRegister.addTests([ TestRegister.addTests([
{
name: "Regex, non-HTML op",
input: "/<>",
expectedOutput: "/<>",
recipeConfig: [
{
"op": "Regular expression",
"args": ["User defined", "", true, true, false, "Highlight matches"]
},
{
"op": "Remove whitespace",
"args": [true, true, true, true, true, false]
}
],
},
{ {
name: "Diff, basic usage", name: "Diff, basic usage",
input: "testing23\n\ntesting123", input: "testing23\n\ntesting123",

View File

@@ -109,9 +109,13 @@ module.exports = {
children: false, children: false,
chunks: false, chunks: false,
modules: false, modules: false,
entrypoints: false,
warningsFilter: /source-map/, warningsFilter: /source-map/,
}, },
node: { node: {
fs: "empty" fs: "empty"
},
performance: {
hints: false
} }
}; };