2
0
mirror of https://github.com/gchq/CyberChef synced 2025-12-05 23:53:27 +00:00

Compare commits

...

102 Commits

Author SHA1 Message Date
n1474335
17cf154bc2 9.50.5 2022-11-25 12:07:07 +00:00
n1474335
c7f6954b97 Merge branch 'view-bit-plane-use-bytelength-not-length' of https://github.com/mikecat/CyberChef 2022-11-25 12:07:01 +00:00
n1474335
9ccc1613cf 9.50.4 2022-11-25 12:05:32 +00:00
n1474335
9730ce1f6a Merge branch 'fix-windows-filetime' of https://github.com/mikecat/CyberChef 2022-11-25 12:05:22 +00:00
n1474335
55a7981547 9.50.3 2022-11-25 12:03:57 +00:00
n1474335
2d99c365dd Merge branch 'fix-reverse-character' of https://github.com/mikecat/CyberChef 2022-11-25 12:02:46 +00:00
n1474335
59d8be511a 9.50.2 2022-11-25 12:00:32 +00:00
n1474335
8349ffc001 Merge branch 'from-hex-use-delimiter-as-delimiter' of https://github.com/mikecat/CyberChef 2022-11-25 11:59:25 +00:00
n1474335
c1368c4ecb 9.50.1 2022-11-25 11:55:53 +00:00
n1474335
c6935e040d Updated newMinorVersion script 2022-11-25 11:55:48 +00:00
n1474335
f79c3ae91a Merge branch 'use-lowercase-for-asn1' of https://github.com/mikecat/CyberChef 2022-11-25 11:55:19 +00:00
n1474335
bc27cd2772 9.50.0 2022-11-25 11:51:34 +00:00
n1474335
2b02c44ca4 Updated CHANGELOG 2022-11-25 11:51:22 +00:00
n1474335
59fe8d1c4b Simplified 'Shuffle' operation to work in the same way as 'Sort' and 'Unique' 2022-11-25 11:50:27 +00:00
n1474335
9a5d62c4c3 Merge branch 'shuffle-operation' of https://github.com/mikecat/CyberChef 2022-11-25 11:24:47 +00:00
n1474335
9fa82150ee 9.49.2 2022-11-25 11:23:38 +00:00
n1474335
d7561ec208 Tidied Substitute 2022-11-25 11:23:32 +00:00
n1474335
743b834f6d Merge branch 'SamueleFacendaSubstitution' of https://github.com/SamueleFacenda/CyberChef 2022-11-25 11:21:04 +00:00
n1474335
0658836f87 9.49.1 2022-11-25 11:15:16 +00:00
n1474335
a4e20c7059 Merge branch 'large-prng' of https://github.com/mikecat/CyberChef 2022-11-25 11:13:05 +00:00
MikeCAT
c04f409d23 PseudoRandomNumberGenerator: support larger output than 65536 bytes 2022-11-17 20:24:54 +09:00
Samuele Facenda
1a9833132d Added ignoreCase feature in Substitute operation. 2022-11-13 14:41:01 +01:00
Samuele Facenda
9c3ddca269 Added ignoreCase feature in Substitute operation. 2022-11-13 14:37:19 +01:00
n1474335
72889d1c20 9.49.0 2022-11-11 16:29:13 +00:00
n1474335
6c5433b226 Updated CHANGELOG 2022-11-11 16:29:03 +00:00
n1474335
31a7f83b82 Added 'LZ4 Compress' and 'LZ4 Decompress' operations. Closes #1116 2022-11-11 16:27:14 +00:00
MikeCAT
39143fa6a1 add Shuffle operation 2022-11-11 22:26:41 +09:00
MikeCAT
1e83e0e935 convert hex string to lower before parsing as ASN.1 2022-11-03 21:43:24 +09:00
MikeCAT
c046cf5695 have "From Hex" treat the delimiter as delimiter, not what to erase 2022-11-03 00:21:20 +09:00
MikeCAT
3086c25079 improve treatment of Hex(little endian) for Windows Filetime converter 2022-11-02 23:14:48 +09:00
MikeCAT
3700780d14 improve "Reverse" operation
* Make "Character" option actually reverse characters
* Add new option "Byte" that behaves as previous "Character" option
2022-11-02 22:37:09 +09:00
MikeCAT
58b1fb8de5 ViewBitPlane.mjs: use byteLength instead of length to check validity of ArrayBuffer 2022-11-02 08:29:26 +09:00
n1474335
ed8bd34915 9.48.0 2022-10-15 00:15:49 +01:00
n1474335
5c72791279 Updated CHANGELOG 2022-10-15 00:15:39 +01:00
n1474335
142f91425c Added 'LM Hash' opertaion 2022-10-15 00:13:39 +01:00
n1474335
d6344760ec Merge branch 'master' of https://github.com/brun0ne/CyberChef 2022-10-14 18:45:47 +01:00
n1474335
64c009f266 9.47.5 2022-10-14 16:28:10 +01:00
n1474335
a73decc792 Merge branch 'master' of https://github.com/gariev/CyberChef 2022-10-14 16:26:08 +01:00
n1474335
f332ca4617 9.47.4 2022-10-14 16:24:33 +01:00
n1474335
937791d33d Merge branch 'jwt-magic' of https://github.com/whs/CyberChef 2022-10-14 16:24:19 +01:00
n1474335
a63a130723 Merge branch 'ci/actions' of https://github.com/Fdawgs/CyberChef 2022-10-14 16:21:53 +01:00
n1474335
0f1175bf15 9.47.3 2022-10-14 16:20:38 +01:00
n1474335
e4db23f857 Removed extra comment from Raw Inflate 2022-10-14 16:20:34 +01:00
n1474335
32e7dd030e Merge branch 'master' of https://github.com/XlogicX/CyberChef 2022-10-14 16:19:32 +01:00
n1474335
e33950961e 9.47.2 2022-10-14 16:10:19 +01:00
n1474335
5d65cb419f Tidied up 'Generate all hashes' operation 2022-10-14 16:10:01 +01:00
n1474335
536053d5f9 Merge branch 'hash' of https://github.com/jl2168/CyberChef 2022-10-14 14:53:00 +01:00
n1474335
04ef095b88 9.47.1 2022-10-14 14:47:30 +01:00
n1474335
66277cd71f Added more DNS request types 2022-10-14 14:47:19 +01:00
n1474335
58f01d0464 Merge branch 'PTR-option' of https://github.com/CyberGoat/CyberChef 2022-10-14 14:14:17 +01:00
n1474335
9ba9c56361 9.47.0 2022-10-14 14:07:47 +01:00
n1474335
11902e3220 Updated CHANGELOG 2022-10-14 14:07:42 +01:00
n1474335
c3f79c4b2c Merge branch 'feature/lzma' of https://github.com/mattnotmitt/CyberChef 2022-10-14 14:03:57 +01:00
n1474335
576905e8b8 9.46.7 2022-10-14 14:01:05 +01:00
n1474335
77a3b91afe Merge branch 'ssh-ed25519' of https://github.com/cplussharp/CyberChef 2022-10-14 14:00:03 +01:00
n1474335
40b58aa144 9.46.6 2022-10-14 13:57:35 +01:00
n1474335
d5bcdc8eed Dependency fixes 2022-10-14 13:57:00 +01:00
Manatsawin Hanmongkolchai
674649ca7f Added checks to JWTDecode operation 2022-10-09 14:57:02 +07:00
XlogicX
1a9a070c3b Removal of unnecessary error condition
This situation occurs because the dependancy (zlibjs/bin/rawinflate.min.js) doesn't do a sanity check on distances going back farther than the current buffer.

For example:
DEFLATE data of '123' and then a length of 9 going back a distance of 6
ASCIIHEX: 333432869300

! infgen 3.0 output
!
last			! 1
fixed			! 01
literal '1		! 10000110
literal '2		! 01000110
literal '3		! 11000110
match 9 6		! 1 00100 1110000
infgen warning: distance too far back (6/3)
end			! 0000000
			! 0

We only have 3 characters, we shouldn't be able to seek 6 characters back. But rawinflate.min.js doesn't check for this like the infgen debug tool (and others) would. So CyberChef would happily provide this as the result:
123...123...
Where the dots are just nulls of likley empty memory preceding the actual buffer

So with the example in this source
// e.g. Input data of [8b, 1d, dc, 44]

last			! 1
fixed			! 01
literal ']		! 10110001
match 158 5		! 0 00100 11011 10000011
infgen warning: distance too far back (5/1)

This means we have a literal ']' and then we are asking for 158 more characters and to find them a distance of 5 back. This explains why the ']', why it repeats every 5, and why it is a length > 158.

This code should just be removed; it isn't justified. Being that this issue is a lack of sanity checking in a dependancy, and that this routine only catches the symptom of one of the nearly unlimited edge cases like this, AND it could filter out correct inputs, such as a recipe of this as input to RAWDEFLATE
]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX
Then getting an error with the INFLATE even though the input is actually valid.
2022-10-06 14:02:27 -04:00
XlogicX
32bee35f85 Removal of unnecessary error checking routine
This situation occurs because the dependancy (zlibjs/bin/rawinflate.min.js) doesn't do a sanity check on distances going back farther than the current buffer.

For example:
DEFLATE data of '123' and then a length of 9 going back a distance of 6
ASCIIHEX: 333432869300

! infgen 3.0 output
!
last			! 1
fixed			! 01
literal '1		! 10000110
literal '2		! 01000110
literal '3		! 11000110
match 9 6		! 1 00100 1110000
infgen warning: distance too far back (6/3)
end			! 0000000
			! 0

We only have 3 characters, we shouldn't be able to seek 6 characters back. But rawinflate.min.js doesn't check for this like the infgen debug tool (and others) would. So CyberChef would happily provide this as the result:
123...123...
Where the dots are just nulls of likley empty memory preceding the actual buffer

So with the example in this source
// e.g. Input data of [8b, 1d, dc, 44]

last			! 1
fixed			! 01
literal ']		! 10110001
match 158 5		! 0 00100 11011 10000011
infgen warning: distance too far back (5/1)

This means we have a literal ']' and then we are asking for 158 more characters and to find them a distance of 5 back. This explains why the ']', why it repeats every 5, and why it is a length > 158.

This code should just be removed; it isn't justified. Being that this issue is a lack of sanity checking in a dependancy, and that this routine only catches the symptom of one of the nearly unlimited edge cases like this, AND it could filter out correct inputs, such as a recipe of this as input to RAWDEFLATE
]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX[]OMG[]HAX
Then getting an error with the INFLATE even though the input is actually valid.
2022-10-06 13:53:32 -04:00
Frazer Smith
a68ce5a5af Update GitHub Actions 2022-10-06 13:58:01 +01:00
Igor Gariev
026e9ca9c3 Added escape sequence "\a" (audible bell, 0x07) to Utils.parseEscapedChars().
The sequece is part of C and C++ standard, as well as protocol buffer encoding.

- https://en.wikipedia.org/wiki/Escape_sequences_in_C
- https://en.cppreference.com/w/cpp/language/escape
- https://developers.google.com/protocol-buffers/docs/text-format-spec#string
2022-09-28 20:32:21 -07:00
BrunonDEV
f1ce67d79b Added NTLM operation
Hashing operation - MD4 on UTF16LE-encoded input
2022-09-27 23:13:22 +02:00
john19696
312be4772c rsdix 2022-09-23 11:38:15 +01:00
john19696
be97a0062e linted 2022-09-22 16:53:29 +01:00
john19696
00f0101723 author fix 2022-09-22 16:39:51 +01:00
john19696
f450240094 Parameterise All hashes 2022-09-22 16:30:36 +01:00
Ethan Block
a7b8378736 Adding PTR to possiable values for Resolver 2022-09-21 11:37:06 -04:00
Matt C
98a70c2dd2 Add tests and handle decompress returning string or array 2022-09-19 17:33:55 +01:00
Matt C
d502dd9857 Add LZMA Decompress operation 2022-09-19 14:24:09 +01:00
Matt C
1ec7033d46 Add LZMA Compress operation 2022-09-19 14:24:09 +01:00
Matt C
28ec56a27f Update libyara package to fix bug with compile messages and add support for console module 2022-09-18 16:11:04 +01:00
CPlusSharp
bf2afcd2ef Support Ed25519 SSH host key parsing 2022-09-18 12:47:55 +02:00
Matt C
8f710461da Update yara to 4.2.3 and fix output reading 0 matches 2022-09-17 23:48:11 +01:00
n1474335
c2cf535f88 Added node builder script to package.json 2022-09-16 14:37:31 +01:00
n1474335
ced9ab68fa 9.46.5 2022-09-16 14:16:42 +01:00
n1474335
cdb197a9c3 Reverted to local copies of Tesseract trainddata in order to remain self-contained. 2022-09-16 14:15:54 +01:00
Sean Marpo
c8eacb9942 Linting fixes 2022-09-09 14:45:06 -07:00
Sean Marpo
1c8e37cb64 Update tesseract, fix API for tesseract 3.0 2022-09-09 14:33:49 -07:00
n1474335
1b0ced9f9b 9.46.4 2022-09-09 21:23:09 +01:00
n1474335
7b245b084a Updated to Node v18 and removed node-sass dependency 2022-09-09 21:22:55 +01:00
n1474335
b00f64518f Merge branch 'nodejs18' of https://github.com/john19696/CyberChef 2022-09-09 20:55:18 +01:00
n1474335
c3434e894d 9.46.3 2022-09-09 20:53:37 +01:00
n1474335
dd66f728b3 Merge branch 'fix-protobuf-order' of https://github.com/oliverrahner/CyberChef 2022-09-09 20:52:36 +01:00
n1474335
e40142b8c5 9.46.2 2022-09-09 20:39:35 +01:00
n1474335
1dd1b839b8 Switched jsonpath library to jsonpath-plus. Fixes #1318 2022-09-09 20:39:28 +01:00
n1474335
d90d845f27 9.46.1 2022-09-09 16:51:38 +01:00
n1474335
8c9ad81039 Merge branch 'feat-primitive' of https://github.com/jeiea/CyberChef 2022-09-09 16:49:12 +01:00
n1474335
cef7a7b27d Lint 2022-09-09 16:44:41 +01:00
n1474335
3e715ef21a Merge branch 'fix-select' of https://github.com/IsSafrullah/CyberChef 2022-09-09 16:43:15 +01:00
n1474335
86b43b4ffa Updated README 2022-09-09 16:39:10 +01:00
IsSafrullah
65d883496b fix select when change theme 2022-09-06 03:52:42 +07:00
jeiea
69e59916e2 feat: support boolean and null in JSON to CSV 2022-08-17 02:12:39 +09:00
Philippe Arteau
475282984b Minor typos 2022-07-29 14:32:46 -04:00
Oliver Rahner
2f89130f41 fix protobuf field order 2022-07-21 16:36:15 +02:00
john19696
e9dd7eceb8 upgrade to nodejs v18 2022-07-14 14:27:59 +01:00
n1474335
037590f831 Updated CHANGELOG 2022-07-08 17:18:20 +01:00
n1474335
85496684d8 9.46.0 2022-07-08 17:17:23 +01:00
n1474335
4200ed4eb9 Tidied Cetacean ciphers 2022-07-08 17:16:35 +01:00
n1474335
6b16f11d3b Merge branch 'master' of https://github.com/valdelaseras/CyberChef 2022-07-08 17:02:06 +01:00
n1474335
683bd3e5db Updated CHANGELOG 2022-07-08 16:34:21 +01:00
Robin Scholtes
578a61d331 add cetacean cipher encoder and decoder operations, tests. Update .gitignore to exclude idea generated files 2022-01-17 23:37:24 +13:00
58 changed files with 1861 additions and 3378 deletions

View File

@@ -22,12 +22,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2

View File

@@ -10,12 +10,12 @@ jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set node version
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: '17.x'
node-version: '18.x'
- name: Install
run: |
@@ -47,7 +47,7 @@ jobs:
- name: Deploy to GitHub Pages
if: success() && github.ref == 'refs/heads/master'
uses: crazy-max/ghaction-github-pages@v2
uses: crazy-max/ghaction-github-pages@v3
with:
target_branch: gh-pages
build_dir: ./build/prod

View File

@@ -9,12 +9,12 @@ jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set node version
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: '17.x'
node-version: '18.x'
- name: Install
run: |

View File

@@ -10,12 +10,12 @@ jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set node version
uses: actions/setup-node@v1
uses: actions/setup-node@v3
with:
node-version: '17.x'
node-version: '18.x'
- name: Install
run: |

2
.nvmrc
View File

@@ -1 +1 @@
17
18

View File

@@ -13,6 +13,24 @@ All major and minor version changes will be documented in this file. Details of
## Details
### [9.50.0] - 2022-11-25
- Added 'Shuffle' operation [@mikecat] | [#1472]
### [9.49.0] - 2022-11-11
- Added 'LZ4 Compress' and 'LZ4 Decompress' operations [@n1474335] | [31a7f83]
### [9.48.0] - 2022-10-14
- Added 'LM Hash' and 'NT Hash' operations [@n1474335] [@brun0ne] | [#1427]
### [9.47.0] - 2022-10-14
- Added 'LZMA Decompress' and 'LZMA Compress' operations [@mattnotmitt] | [#1421]
### [9.46.0] - 2022-07-08
- Added 'Cetacean Cipher Encode' and 'Cetacean Cipher Decode' operations [@valdelaseras] | [#1308]
### [9.45.0] - 2022-07-08
- Added 'ROT8000' operation [@thomasleplus] | [#1250]
### [9.44.0] - 2022-07-08
- Added 'LZString Compress' and 'LZString Decompress' operations [@crespyl] | [#1266]
@@ -309,6 +327,12 @@ All major and minor version changes will be documented in this file. Details of
[9.50.0]: https://github.com/gchq/CyberChef/releases/tag/v9.50.0
[9.49.0]: https://github.com/gchq/CyberChef/releases/tag/v9.49.0
[9.48.0]: https://github.com/gchq/CyberChef/releases/tag/v9.48.0
[9.47.0]: https://github.com/gchq/CyberChef/releases/tag/v9.47.0
[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0
[9.45.0]: https://github.com/gchq/CyberChef/releases/tag/v9.45.0
[9.44.0]: https://github.com/gchq/CyberChef/releases/tag/v9.44.0
[9.43.0]: https://github.com/gchq/CyberChef/releases/tag/v9.43.0
[9.42.0]: https://github.com/gchq/CyberChef/releases/tag/v9.42.0
@@ -440,6 +464,9 @@ All major and minor version changes will be documented in this file. Details of
[@swesven]: https://github.com/swesven
[@mikecat]: https://github.com/mikecat
[@crespyl]: https://github.com/crespyl
[@thomasleplus]: https://github.com/thomasleplus
[@valdelaseras]: https://github.com/valdelaseras
[@brun0ne]: https://github.com/brun0ne
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
@@ -447,6 +474,7 @@ All major and minor version changes will be documented in this file. Details of
[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8
[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da
[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737
[31a7f83]: https://github.com/gchq/CyberChef/commit/31a7f83b82e78927f89689f323fcb9185144d6ff
[#95]: https://github.com/gchq/CyberChef/pull/299
[#173]: https://github.com/gchq/CyberChef/pull/173
@@ -540,4 +568,9 @@ All major and minor version changes will be documented in this file. Details of
[#1364]: https://github.com/gchq/CyberChef/pull/1364
[#1264]: https://github.com/gchq/CyberChef/pull/1264
[#1266]: https://github.com/gchq/CyberChef/pull/1266
[#1250]: https://github.com/gchq/CyberChef/pull/1250
[#1308]: https://github.com/gchq/CyberChef/pull/1308
[#1421]: https://github.com/gchq/CyberChef/pull/1421
[#1427]: https://github.com/gchq/CyberChef/pull/1427
[#1472]: https://github.com/gchq/CyberChef/pull/1472

View File

@@ -54,7 +54,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Whenever you modify the input or the recipe, CyberChef will automatically "bake" for you and produce the output immediately.
- This can be turned off and operated manually if it is affecting performance (if the input is very large, for instance).
- Automated encoding detection
- CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation which can make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
- CyberChef uses [a number of techniques](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) to attempt to automatically detect which encodings your data is under. If it finds a suitable operation that make sense of your data, it displays the 'magic' icon in the Output field which you can click to decode your data.
- Breakpoints
- You can set breakpoints on any operation in your recipe to pause execution before running it.
- You can also step through the recipe one operation at a time to see what the data looks like at each stage.
@@ -66,7 +66,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Highlighting
- When you highlight text in the input or output, the offset and length values will be displayed and, if possible, the corresponding data will be highlighted in the output or input respectively (example: [highlight the word 'question' in the input to see where it appears in the output][11]).
- Save to file and load from file
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 2GB are supported (depending on your browser), however some operations may take a very long time to run over this much data.
- You can save the output to a file at any time or load a file by dragging and dropping it into the input field. Files up to around 2GB are supported (depending on your browser), however, some operations may take a very long time to run over this much data.
- CyberChef is entirely client-side
- It should be noted that none of your recipe configuration or input (either text or files) is ever sent to the CyberChef web server - all processing is carried out within your browser, on your own computer.
- Due to this feature, CyberChef can be downloaded and run locally. You can use the link in the top left corner of the app to download a full copy of CyberChef and drop it into a virtual machine, share it with other people, or host it in a closed network.
@@ -74,10 +74,10 @@ You can use as many operations as you like in simple or complex ways. Some examp
## Deep linking
By manipulation of CyberChef's URL hash, you can change the initial settings with which the page opens.
By manipulating CyberChef's URL hash, you can change the initial settings with which the page opens.
The format is `https://gchq.github.io/CyberChef/#recipe=Operation()&input=...`
Supported arguments are `recipe`, `input` (encoded in Base64), and `theme`.
Supported arguments are `recipe`, `input` (encoded in Base64), and `theme`.
## Browser support
@@ -90,12 +90,12 @@ CyberChef is built to support
## Node.js support
CyberChef is built to fully support Node.js `v10` and partially supports `v12`. Named imports using a deep import specifier does not work in `v12`. For more information, see the Node API page in the project [wiki pages](https://github.com/gchq/CyberChef/wiki)
CyberChef is built to fully support Node.js `v16`. For more information, see the Node API page in the project [wiki pages](https://github.com/gchq/CyberChef/wiki)
## Contributing
Contributing a new operation to CyberChef is super easy! There is a quickstart script which will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
Contributing a new operation to CyberChef is super easy! The quickstart script will walk you through the process. If you can write basic JavaScript, you can write a CyberChef operation.
An installation walkthrough, how-to guides for adding new operations and themes, descriptions of the repository structure, available data types and coding conventions can all be found in the project [wiki pages](https://github.com/gchq/CyberChef/wiki).

3602
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.45.0",
"version": "9.50.5",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",
@@ -49,7 +49,7 @@
"babel-loader": "^8.2.5",
"babel-plugin-dynamic-import-node": "^2.3.3",
"babel-plugin-transform-builtin-extend": "1.1.2",
"chromedriver": "^101.0.0",
"chromedriver": "^103.0.0",
"cli-progress": "^3.11.1",
"colors": "^1.4.0",
"copy-webpack-plugin": "^11.0.0",
@@ -77,7 +77,6 @@
"postcss-import": "^14.1.0",
"postcss-loader": "^7.0.0",
"prompt": "^1.3.0",
"sass-loader": "^13.0.0",
"sitemap": "^7.1.1",
"terser": "^5.14.0",
"webpack": "^5.73.0",
@@ -88,6 +87,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"@blu3r4y/lzma": "^2.3.3",
"arrive": "^2.4.1",
"avsc": "^5.7.4",
"bcryptjs": "^2.4.3",
@@ -123,26 +123,27 @@
"js-sha3": "^0.8.0",
"jsesc": "^3.0.2",
"json5": "^2.2.1",
"jsonpath": "^1.1.1",
"jsonpath-plus": "^7.2.0",
"jsonwebtoken": "^8.5.1",
"jsqr": "^1.4.0",
"jsrsasign": "^10.5.23",
"kbpgp": "2.1.15",
"libbzip2-wasm": "0.0.4",
"libyara-wasm": "^1.1.0",
"libyara-wasm": "^1.2.1",
"lodash": "^4.17.21",
"loglevel": "^1.8.0",
"loglevel-message-prefix": "^3.0.0",
"lz-string": "^1.4.4",
"lz4js": "^0.2.0",
"markdown-it": "^13.0.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"ngeohash": "^0.6.3",
"node-forge": "^1.3.1",
"node-md6": "^0.1.0",
"node-sass": "^7.0.1",
"nodom": "^2.4.0",
"notepack.io": "^3.0.1",
"ntlm": "^0.1.3",
"nwmatcher": "^1.4.4",
"otp": "0.1.3",
"path": "^0.12.7",
@@ -156,7 +157,7 @@
"split.js": "^1.6.5",
"ssdeep.js": "0.0.3",
"stream-browserify": "^3.0.0",
"tesseract.js": "2.1.5",
"tesseract.js": "3.0.2",
"ua-parser-js": "^1.0.2",
"unorm": "^1.6.0",
"utf8": "^3.0.0",
@@ -169,8 +170,9 @@
"scripts": {
"start": "npx grunt dev",
"build": "npx grunt prod",
"node": "npx grunt node",
"repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings src/node/repl.mjs",
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation tests/operations/index.mjs",
"test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider tests/operations/index.mjs",
"testnodeconsumer": "npx grunt testnodeconsumer",
"testui": "npx grunt testui",
"testuidev": "npx nightwatch --env=dev",

View File

@@ -206,7 +206,7 @@ class Utils {
* Utils.parseEscapedChars("\\n");
*/
static parseEscapedChars(str) {
return str.replace(/\\([bfnrtv'"]|[0-3][0-7]{2}|[0-7]{1,2}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]{1,6}\}|\\)/g, function(m, a) {
return str.replace(/\\([abfnrtv'"]|[0-3][0-7]{2}|[0-7]{1,2}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]{1,6}\}|\\)/g, function(m, a) {
switch (a[0]) {
case "\\":
return "\\";
@@ -219,6 +219,8 @@ class Utils {
case "6":
case "7":
return String.fromCharCode(parseInt(a, 8));
case "a":
return String.fromCharCode(7);
case "b":
return "\b";
case "t":

View File

@@ -112,6 +112,8 @@
"Atbash Cipher",
"CipherSaber2 Encrypt",
"CipherSaber2 Decrypt",
"Cetacean Cipher Encode",
"Cetacean Cipher Decode",
"Substitute",
"Derive PBKDF2 key",
"Derive EVP key",
@@ -247,6 +249,7 @@
"To Table",
"Reverse",
"Sort",
"Shuffle",
"Unique",
"Split",
"Filter",
@@ -328,8 +331,12 @@
"Bzip2 Compress",
"Tar",
"Untar",
"LZString Decompress",
"LZString Compress",
"LZString Decompress"
"LZMA Decompress",
"LZMA Compress",
"LZ4 Decompress",
"LZ4 Compress"
]
},
{
@@ -365,6 +372,8 @@
"Bcrypt compare",
"Bcrypt parse",
"Scrypt",
"NT Hash",
"LM Hash",
"Fletcher-8 Checksum",
"Fletcher-16 Checksum",
"Fletcher-32 Checksum",

View File

@@ -136,7 +136,7 @@ const getFeature = function() {
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
console.log("Written CHANGELOG.md");
console.log("Written CHANGELOG.md\nCommit changes and then run `npm version minor`.");
}
});
};

View File

@@ -105,13 +105,17 @@ export function fromHex(data, delim="Auto", byteLen=2) {
throw new OperationError("Byte length must be a positive integer");
if (delim !== "None") {
const delimRegex = delim === "Auto" ? /[^a-f\d]|(0x)/gi : Utils.regexRep(delim);
data = data.replace(delimRegex, "");
const delimRegex = delim === "Auto" ? /[^a-f\d]|0x/gi : Utils.regexRep(delim);
data = data.split(delimRegex);
} else {
data = [data];
}
const output = [];
for (let i = 0; i < data.length; i += byteLen) {
output.push(parseInt(data.substr(i, byteLen), 16));
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].length; j += byteLen) {
output.push(parseInt(data[i].substr(j, byteLen), 16));
}
}
return output;
}

View File

@@ -184,7 +184,7 @@ class Protobuf {
bytes: String,
longs: Number,
enums: String,
defualts: true
defaults: true
});
const output = {};

View File

@@ -0,0 +1,63 @@
/**
* @author dolphinOnKeys [robin@weird.io]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
/**
* Cetacean Cipher Decode operation
*/
class CetaceanCipherDecode extends Operation {
/**
* CetaceanCipherDecode constructor
*/
constructor() {
super();
this.name = "Cetacean Cipher Decode";
this.module = "Ciphers";
this.description = "Decode Cetacean Cipher input. <br/><br/>e.g. <code>EEEEEEEEEeeEeEEEEEEEEEEEEeeEeEEe</code> becomes <code>hi</code>";
this.infoURL = "https://hitchhikers.fandom.com/wiki/Dolphins";
this.inputType = "string";
this.outputType = "string";
this.checks = [
{
pattern: "^(?:[eE]{16,})(?: [eE]{16,})*$",
flags: "",
args: []
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const binaryArray = [];
for (const char of input) {
if (char === " ") {
binaryArray.push(...[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]);
} else {
binaryArray.push(char === "e" ? 1 : 0);
}
}
const byteArray = [];
for (let i = 0; i < binaryArray.length; i += 16) {
byteArray.push(binaryArray.slice(i, i + 16).join(""));
}
return byteArray.map(byte =>
String.fromCharCode(parseInt(byte, 2))
).join("");
}
}
export default CetaceanCipherDecode;

View File

@@ -0,0 +1,51 @@
/**
* @author dolphinOnKeys [robin@weird.io]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import {toBinary} from "../lib/Binary.mjs";
/**
* Cetacean Cipher Encode operation
*/
class CetaceanCipherEncode extends Operation {
/**
* CetaceanCipherEncode constructor
*/
constructor() {
super();
this.name = "Cetacean Cipher Encode";
this.module = "Ciphers";
this.description = "Converts any input into Cetacean Cipher. <br/><br/>e.g. <code>hi</code> becomes <code>EEEEEEEEEeeEeEEEEEEEEEEEEeeEeEEe</code>";
this.infoURL = "https://hitchhikers.fandom.com/wiki/Dolphins";
this.inputType = "string";
this.outputType = "string";
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const result = [];
const charArray = input.split("");
charArray.map(character => {
if (character === " ") {
result.push(character);
} else {
const binaryArray = toBinary(character.charCodeAt(0), "None", 16).split("");
result.push(binaryArray.map(str => str === "1" ? "e" : "E").join(""));
}
});
return result.join("");
}
}
export default CetaceanCipherEncode;

View File

@@ -51,10 +51,27 @@ class DNSOverHTTPS extends Operation {
value: [
"A",
"AAAA",
"TXT",
"MX",
"ANAME",
"CERT",
"CNAME",
"DNSKEY",
"NS"
"HTTPS",
"IPSECKEY",
"LOC",
"MX",
"NS",
"OPENPGPKEY",
"PTR",
"RRSIG",
"SIG",
"SOA",
"SPF",
"SRV",
"SSHFP",
"TA",
"TXT",
"URI",
"ANY"
]
},
{

View File

@@ -1,5 +1,6 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @author john19696 [john19696@protonmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
@@ -33,6 +34,9 @@ import BLAKE2b from "./BLAKE2b.mjs";
import BLAKE2s from "./BLAKE2s.mjs";
import Streebog from "./Streebog.mjs";
import GOSTHash from "./GOSTHash.mjs";
import LMHash from "./LMHash.mjs";
import NTHash from "./NTHash.mjs";
import OperationError from "../errors/OperationError.mjs";
/**
* Generate all hashes operation
@@ -51,7 +55,75 @@ class GenerateAllHashes extends Operation {
this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [];
this.args = [
{
name: "Length (bits)",
type: "option",
value: [
"All", "128", "160", "224", "256", "320", "384", "512"
]
},
{
name: "Include names",
type: "boolean",
value: true
},
];
this.hashes = [
{name: "MD2", algo: (new MD2()), inputType: "arrayBuffer", params: []},
{name: "MD4", algo: (new MD4()), inputType: "arrayBuffer", params: []},
{name: "MD5", algo: (new MD5()), inputType: "arrayBuffer", params: []},
{name: "MD6", algo: (new MD6()), inputType: "str", params: []},
{name: "SHA0", algo: (new SHA0()), inputType: "arrayBuffer", params: []},
{name: "SHA1", algo: (new SHA1()), inputType: "arrayBuffer", params: []},
{name: "SHA2 224", algo: (new SHA2()), inputType: "arrayBuffer", params: ["224"]},
{name: "SHA2 256", algo: (new SHA2()), inputType: "arrayBuffer", params: ["256"]},
{name: "SHA2 384", algo: (new SHA2()), inputType: "arrayBuffer", params: ["384"]},
{name: "SHA2 512", algo: (new SHA2()), inputType: "arrayBuffer", params: ["512"]},
{name: "SHA3 224", algo: (new SHA3()), inputType: "arrayBuffer", params: ["224"]},
{name: "SHA3 256", algo: (new SHA3()), inputType: "arrayBuffer", params: ["256"]},
{name: "SHA3 384", algo: (new SHA3()), inputType: "arrayBuffer", params: ["384"]},
{name: "SHA3 512", algo: (new SHA3()), inputType: "arrayBuffer", params: ["512"]},
{name: "Keccak 224", algo: (new Keccak()), inputType: "arrayBuffer", params: ["224"]},
{name: "Keccak 256", algo: (new Keccak()), inputType: "arrayBuffer", params: ["256"]},
{name: "Keccak 384", algo: (new Keccak()), inputType: "arrayBuffer", params: ["384"]},
{name: "Keccak 512", algo: (new Keccak()), inputType: "arrayBuffer", params: ["512"]},
{name: "Shake 128", algo: (new Shake()), inputType: "arrayBuffer", params: ["128", 256]},
{name: "Shake 256", algo: (new Shake()), inputType: "arrayBuffer", params: ["256", 512]},
{name: "RIPEMD-128", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["128"]},
{name: "RIPEMD-160", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["160"]},
{name: "RIPEMD-256", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["256"]},
{name: "RIPEMD-320", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["320"]},
{name: "HAS-160", algo: (new HAS160()), inputType: "arrayBuffer", params: []},
{name: "Whirlpool-0", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-0"]},
{name: "Whirlpool-T", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-T"]},
{name: "Whirlpool", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool"]},
{name: "BLAKE2b-128", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["128", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2b-160", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["160", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2b-256", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["256", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2b-384", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["384", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2b-512", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["512", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2s-128", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["128", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2s-160", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["160", "Hex", {string: "", option: "UTF8"}]},
{name: "BLAKE2s-256", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["256", "Hex", {string: "", option: "UTF8"}]},
{name: "Streebog-256", algo: (new Streebog), inputType: "arrayBuffer", params: ["256"]},
{name: "Streebog-512", algo: (new Streebog), inputType: "arrayBuffer", params: ["512"]},
{name: "GOST", algo: (new GOSTHash), inputType: "arrayBuffer", params: ["D-A"]},
{name: "LM Hash", algo: (new LMHash), inputType: "str", params: []},
{name: "NT Hash", algo: (new NTHash), inputType: "str", params: []},
{name: "SSDEEP", algo: (new SSDEEP()), inputType: "str"},
{name: "CTPH", algo: (new CTPH()), inputType: "str"}
];
this.checksums = [
{name: "Fletcher-8", algo: (new Fletcher8Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-16", algo: (new Fletcher16Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-32", algo: (new Fletcher32Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-64", algo: (new Fletcher64Checksum), inputType: "byteArray", params: []},
{name: "Adler-32", algo: (new Adler32Checksum), inputType: "byteArray", params: []},
{name: "CRC-8", algo: (new CRC8Checksum), inputType: "arrayBuffer", params: ["CRC-8"]},
{name: "CRC-16", algo: (new CRC16Checksum), inputType: "arrayBuffer", params: []},
{name: "CRC-32", algo: (new CRC32Checksum), inputType: "arrayBuffer", params: []}
];
}
/**
@@ -60,63 +132,74 @@ class GenerateAllHashes extends Operation {
* @returns {string}
*/
run(input, args) {
const arrayBuffer = input,
str = Utils.arrayBufferToStr(arrayBuffer, false),
byteArray = new Uint8Array(arrayBuffer),
output = "MD2: " + (new MD2()).run(arrayBuffer, []) +
"\nMD4: " + (new MD4()).run(arrayBuffer, []) +
"\nMD5: " + (new MD5()).run(arrayBuffer, []) +
"\nMD6: " + (new MD6()).run(str, []) +
"\nSHA0: " + (new SHA0()).run(arrayBuffer, []) +
"\nSHA1: " + (new SHA1()).run(arrayBuffer, []) +
"\nSHA2 224: " + (new SHA2()).run(arrayBuffer, ["224"]) +
"\nSHA2 256: " + (new SHA2()).run(arrayBuffer, ["256"]) +
"\nSHA2 384: " + (new SHA2()).run(arrayBuffer, ["384"]) +
"\nSHA2 512: " + (new SHA2()).run(arrayBuffer, ["512"]) +
"\nSHA3 224: " + (new SHA3()).run(arrayBuffer, ["224"]) +
"\nSHA3 256: " + (new SHA3()).run(arrayBuffer, ["256"]) +
"\nSHA3 384: " + (new SHA3()).run(arrayBuffer, ["384"]) +
"\nSHA3 512: " + (new SHA3()).run(arrayBuffer, ["512"]) +
"\nKeccak 224: " + (new Keccak()).run(arrayBuffer, ["224"]) +
"\nKeccak 256: " + (new Keccak()).run(arrayBuffer, ["256"]) +
"\nKeccak 384: " + (new Keccak()).run(arrayBuffer, ["384"]) +
"\nKeccak 512: " + (new Keccak()).run(arrayBuffer, ["512"]) +
"\nShake 128: " + (new Shake()).run(arrayBuffer, ["128", 256]) +
"\nShake 256: " + (new Shake()).run(arrayBuffer, ["256", 512]) +
"\nRIPEMD-128: " + (new RIPEMD()).run(arrayBuffer, ["128"]) +
"\nRIPEMD-160: " + (new RIPEMD()).run(arrayBuffer, ["160"]) +
"\nRIPEMD-256: " + (new RIPEMD()).run(arrayBuffer, ["256"]) +
"\nRIPEMD-320: " + (new RIPEMD()).run(arrayBuffer, ["320"]) +
"\nHAS-160: " + (new HAS160()).run(arrayBuffer, []) +
"\nWhirlpool-0: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool-0"]) +
"\nWhirlpool-T: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool-T"]) +
"\nWhirlpool: " + (new Whirlpool()).run(arrayBuffer, ["Whirlpool"]) +
"\nBLAKE2b-128: " + (new BLAKE2b).run(arrayBuffer, ["128", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2b-160: " + (new BLAKE2b).run(arrayBuffer, ["160", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2b-256: " + (new BLAKE2b).run(arrayBuffer, ["256", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2b-384: " + (new BLAKE2b).run(arrayBuffer, ["384", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2b-512: " + (new BLAKE2b).run(arrayBuffer, ["512", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2s-128: " + (new BLAKE2s).run(arrayBuffer, ["128", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2s-160: " + (new BLAKE2s).run(arrayBuffer, ["160", "Hex", {string: "", option: "UTF8"}]) +
"\nBLAKE2s-256: " + (new BLAKE2s).run(arrayBuffer, ["256", "Hex", {string: "", option: "UTF8"}]) +
"\nStreebog-256: " + (new Streebog).run(arrayBuffer, ["256"]) +
"\nStreebog-512: " + (new Streebog).run(arrayBuffer, ["512"]) +
"\nGOST: " + (new GOSTHash).run(arrayBuffer, ["D-A"]) +
"\nSSDEEP: " + (new SSDEEP()).run(str) +
"\nCTPH: " + (new CTPH()).run(str) +
"\n\nChecksums:" +
"\nFletcher-8: " + (new Fletcher8Checksum).run(byteArray, []) +
"\nFletcher-16: " + (new Fletcher16Checksum).run(byteArray, []) +
"\nFletcher-32: " + (new Fletcher32Checksum).run(byteArray, []) +
"\nFletcher-64: " + (new Fletcher64Checksum).run(byteArray, []) +
"\nAdler-32: " + (new Adler32Checksum).run(byteArray, []) +
"\nCRC-8: " + (new CRC8Checksum).run(arrayBuffer, ["CRC-8"]) +
"\nCRC-16: " + (new CRC16Checksum).run(arrayBuffer, []) +
"\nCRC-32: " + (new CRC32Checksum).run(arrayBuffer, []);
const [length, includeNames] = args;
this.inputArrayBuffer = input;
this.inputStr = Utils.arrayBufferToStr(input, false);
this.inputByteArray = new Uint8Array(input);
let digest, output = "";
// iterate over each of the hashes
this.hashes.forEach(hash => {
digest = this.executeAlgo(hash.algo, hash.inputType, hash.params || []);
output += this.formatDigest(digest, length, includeNames, hash.name);
});
if (length === "All") {
output += "\nChecksums:\n";
this.checksums.forEach(checksum => {
digest = this.executeAlgo(checksum.algo, checksum.inputType, checksum.params || []);
output += this.formatDigest(digest, length, includeNames, checksum.name);
});
}
return output;
}
/**
* Executes a hash or checksum algorithm
*
* @param {Function} algo - The hash or checksum algorithm
* @param {string} inputType
* @param {Object[]} [params=[]]
* @returns {string}
*/
executeAlgo(algo, inputType, params=[]) {
let digest = null;
switch (inputType) {
case "arrayBuffer":
digest = algo.run(this.inputArrayBuffer, params);
break;
case "str":
digest = algo.run(this.inputStr, params);
break;
case "byteArray":
digest = algo.run(this.inputByteArray, params);
break;
default:
throw new OperationError("Unknown hash input type: " + inputType);
}
return digest;
}
/**
* Formats the digest depending on user-specified arguments
* @param {string} digest
* @param {string} length
* @param {boolean} includeNames
* @param {string} name
* @returns {string}
*/
formatDigest(digest, length, includeNames, name) {
if (length !== "All" && (digest.length * 4) !== parseInt(length, 10))
return "";
if (!includeNames)
return digest + "\n";
return `${name}:${" ".repeat(13-name.length)}${digest}\n`;
}
}
export default GenerateAllHashes;

View File

@@ -4,7 +4,7 @@
* @license Apache-2.0
*/
import jpath from "jsonpath";
import {JSONPath} from "jsonpath-plus";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
@@ -27,14 +27,20 @@ class JPathExpression extends Operation {
this.outputType = "string";
this.args = [
{
"name": "Query",
"type": "string",
"value": ""
name: "Query",
type: "string",
value: ""
},
{
"name": "Result delimiter",
"type": "binaryShortString",
"value": "\\n"
name: "Result delimiter",
type: "binaryShortString",
value: "\\n"
},
{
name: "Prevent eval",
type: "boolean",
value: true,
description: "Evaluated expressions are disabled by default for security reasons"
}
];
}
@@ -45,18 +51,21 @@ class JPathExpression extends Operation {
* @returns {string}
*/
run(input, args) {
const [query, delimiter] = args;
let results,
obj;
const [query, delimiter, preventEval] = args;
let results, jsonObj;
try {
obj = JSON.parse(input);
jsonObj = JSON.parse(input);
} catch (err) {
throw new OperationError(`Invalid input JSON: ${err.message}`);
}
try {
results = jpath.query(obj, query);
results = JSONPath({
path: query,
json: jsonObj,
preventEval: preventEval
});
} catch (err) {
throw new OperationError(`Invalid JPath expression: ${err.message}`);
}

View File

@@ -114,8 +114,11 @@ class JSONToCSV extends Operation {
* @returns {string}
*/
escapeCellContents(data, force=false) {
if (typeof data === "number") data = data.toString();
if (force && typeof data !== "string") data = JSON.stringify(data);
if (data !== "string") {
const isPrimitive = data == null || typeof data !== "object";
if (isPrimitive) data = `${data}`;
else if (force) data = JSON.stringify(data);
}
// Double quotes should be doubled up
data = data.replace(/"/g, '""');

View File

@@ -26,6 +26,13 @@ class JWTDecode extends Operation {
this.inputType = "string";
this.outputType = "JSON";
this.args = [];
this.checks = [
{
pattern: "^ey([A-Za-z0-9_-]+)\\.ey([A-Za-z0-9_-]+)\\.([A-Za-z0-9_-]+)$",
flags: "",
args: []
},
];
}
/**

View File

@@ -0,0 +1,41 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import {smbhash} from "ntlm";
/**
* LM Hash operation
*/
class LMHash extends Operation {
/**
* LMHash constructor
*/
constructor() {
super();
this.name = "LM Hash";
this.module = "Crypto";
this.description = "An LM Hash, or LAN Manager Hash, is a deprecated way of storing passwords on old Microsoft operating systems. It is particularly weak and can be cracked in seconds on modern hardware using rainbow tables.";
this.infoURL = "https://wikipedia.org/wiki/LAN_Manager#Password_hashing_algorithm";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return smbhash.lmhash(input);
}
}
export default LMHash;

View File

@@ -0,0 +1,43 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import lz4 from "lz4js";
/**
* LZ4 Compress operation
*/
class LZ4Compress extends Operation {
/**
* LZ4Compress constructor
*/
constructor() {
super();
this.name = "LZ4 Compress";
this.module = "Compression";
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const inBuf = new Uint8Array(input);
const compressed = lz4.compress(inBuf);
return compressed.buffer;
}
}
export default LZ4Compress;

View File

@@ -0,0 +1,43 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import lz4 from "lz4js";
/**
* LZ4 Decompress operation
*/
class LZ4Decompress extends Operation {
/**
* LZ4Decompress constructor
*/
constructor() {
super();
this.name = "LZ4 Decompress";
this.module = "Compression";
this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes.";
this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const inBuf = new Uint8Array(input);
const decompressed = lz4.decompress(inBuf);
return decompressed.buffer;
}
}
export default LZ4Decompress;

View File

@@ -0,0 +1,64 @@
/**
* @author Matt C [me@mitt.dev]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { compress } from "@blu3r4y/lzma";
import {isWorkerEnvironment} from "../Utils.mjs";
/**
* LZMA Compress operation
*/
class LZMACompress extends Operation {
/**
* LZMACompress constructor
*/
constructor() {
super();
this.name = "LZMA Compress";
this.module = "Compression";
this.description = "Compresses data using the Lempel\u2013Ziv\u2013Markov chain algorithm. Compression mode determines the speed and effectiveness of the compression: 1 is fastest and less effective, 9 is slowest and most effective";
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
this.args = [
{
name: "Compression Mode",
type: "option",
value: [
"1", "2", "3", "4", "5", "6", "7", "8", "9"
],
"defaultIndex": 6
}
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
async run(input, args) {
const mode = Number(args[0]);
return new Promise((resolve, reject) => {
compress(new Uint8Array(input), mode, (result, error) => {
if (error) {
reject(new OperationError(`Failed to compress input: ${error.message}`));
}
// The compression returns as an Int8Array, but we can just get the unsigned data from the buffer
resolve(new Int8Array(result).buffer);
}, (percent) => {
if (isWorkerEnvironment()) self.sendStatusMessage(`Compressing input: ${(percent*100).toFixed(2)}%`);
});
});
}
}
export default LZMACompress;

View File

@@ -0,0 +1,57 @@
/**
* @author Matt C [me@mitt.dev]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import {decompress} from "@blu3r4y/lzma";
import Utils, {isWorkerEnvironment} from "../Utils.mjs";
/**
* LZMA Decompress operation
*/
class LZMADecompress extends Operation {
/**
* LZMADecompress constructor
*/
constructor() {
super();
this.name = "LZMA Decompress";
this.module = "Compression";
this.description = "Decompresses data using the Lempel-Ziv-Markov chain Algorithm.";
this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm";
this.inputType = "ArrayBuffer";
this.outputType = "ArrayBuffer";
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
async run(input, args) {
return new Promise((resolve, reject) => {
decompress(new Uint8Array(input), (result, error) => {
if (error) {
reject(new OperationError(`Failed to decompress input: ${error.message}`));
}
// The decompression returns either a String or an untyped unsigned int8 array, but we can just get the unsigned data from the buffer
if (typeof result == "string") {
resolve(Utils.strToArrayBuffer(result));
} else {
resolve(new Int8Array(result).buffer);
}
}, (percent) => {
if (isWorkerEnvironment()) self.sendStatusMessage(`Decompressing input: ${(percent*100).toFixed(2)}%`);
});
});
}
}
export default LZMADecompress;

View File

@@ -0,0 +1,46 @@
/**
* @author brun0ne [brunonblok@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import cptable from "codepage";
import {runHash} from "../lib/Hash.mjs";
/**
* NT Hash operation
*/
class NTHash extends Operation {
/**
* NTHash constructor
*/
constructor() {
super();
this.name = "NT Hash";
this.module = "Crypto";
this.description = "An NT Hash, sometimes referred to as an NTLM hash, is a method of storing passwords on Windows systems. It works by running MD4 on UTF-16LE encoded input. NTLM hashes are considered weak because they can be brute-forced very easily with modern hardware.";
this.infoURL = "https://wikipedia.org/wiki/NT_LAN_Manager";
this.inputType = "string";
this.outputType = "string";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const format = 1200; // UTF-16LE
const encoded = cptable.utils.encode(format, input);
const hashed = runHash("md4", encoded);
return hashed.toUpperCase();
}
}
export default NTHash;

View File

@@ -12,10 +12,8 @@ import { isImage } from "../lib/FileType.mjs";
import { toBase64 } from "../lib/Base64.mjs";
import { isWorkerEnvironment } from "../Utils.mjs";
import Tesseract from "tesseract.js";
const { createWorker } = Tesseract;
import process from "process";
import { createWorker } from "tesseract.js";
/**
* Optical Character Recognition operation
@@ -55,7 +53,7 @@ class OpticalCharacterRecognition extends Operation {
const type = isImage(input);
if (!type) {
throw new OperationError("Invalid File Type");
throw new OperationError("Unsupported file type (supported: jpg,png,pbm,bmp) or no file provided");
}
const assetDir = isWorkerEnvironment() ? `${self.docURL}/assets/` : `${process.cwd()}/src/core/vendor/`;
@@ -74,7 +72,7 @@ class OpticalCharacterRecognition extends Operation {
}
});
await worker.load();
self.sendStatusMessage("Loading English language...");
self.sendStatusMessage(`Loading English language pack...`);
await worker.loadLanguage("eng");
self.sendStatusMessage("Intialising Tesseract API...");
await worker.initialize("eng");

View File

@@ -45,7 +45,7 @@ class ParseASN1HexString extends Operation {
*/
run(input, args) {
const [index, truncateLen] = args;
return r.ASN1HEX.dump(input.replace(/\s/g, ""), {
return r.ASN1HEX.dump(input.replace(/\s/g, "").toLowerCase(), {
"ommitLongOctet": truncateLen
}, index);
}

View File

@@ -23,7 +23,7 @@ class ParseSSHHostKey extends Operation {
this.name = "Parse SSH Host Key";
this.module = "Default";
this.description = "Parses a SSH host key and extracts fields from it.<br>The key type can be:<ul><li>ssh-rsa</li><li>ssh-dss</li><li>ecdsa-sha2</li></ul>The key format can be either Hex or Base64.";
this.description = "Parses a SSH host key and extracts fields from it.<br>The key type can be:<ul><li>ssh-rsa</li><li>ssh-dss</li><li>ecdsa-sha2</li><li>ssh-ed25519</li></ul>The key format can be either Hex or Base64.";
this.infoURL = "https://wikipedia.org/wiki/Secure_Shell";
this.inputType = "string";
this.outputType = "string";
@@ -71,6 +71,8 @@ class ParseSSHHostKey extends Operation {
} else if (keyType.startsWith("ecdsa-sha2")) {
output += `\nCurve: ${Utils.byteArrayToChars(fromHex(fields[1]))}`;
output += `\nPoint: 0x${fields.slice(2)}`;
} else if (keyType === "ssh-ed25519") {
output += `\nx: 0x${fields[1]}`;
} else {
output += "\nUnsupported key type.";
output += `\nParameters: ${fields.slice(1)}`;

View File

@@ -59,7 +59,7 @@ class ParseX509Certificate extends Operation {
switch (inputFormat) {
case "DER Hex":
input = input.replace(/\s/g, "");
input = input.replace(/\s/g, "").toLowerCase();
cert.readCertHex(input);
break;
case "PEM":

View File

@@ -52,8 +52,12 @@ class PseudoRandomNumberGenerator extends Operation {
let bytes;
if (isWorkerEnvironment() && self.crypto) {
bytes = self.crypto.getRandomValues(new Uint8Array(numBytes));
bytes = Utils.arrayBufferToStr(bytes.buffer);
bytes = new ArrayBuffer(numBytes);
const CHUNK_SIZE = 65536;
for (let i = 0; i < numBytes; i += CHUNK_SIZE) {
self.crypto.getRandomValues(new Uint8Array(bytes, i, Math.min(numBytes - i, CHUNK_SIZE)));
}
bytes = Utils.arrayBufferToStr(bytes);
} else {
bytes = forge.random.getBytesSync(numBytes);
}

View File

@@ -7,7 +7,6 @@
import Operation from "../Operation.mjs";
import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs";
import rawinflate from "zlibjs/bin/rawinflate.min.js";
import OperationError from "../errors/OperationError.mjs";
const Zlib = rawinflate.Zlib;
@@ -83,25 +82,6 @@ class RawInflate extends Operation {
}),
result = new Uint8Array(inflate.decompress());
// Raw Inflate sometimes messes up and returns nonsense like this:
// ]....]....]....]....]....]....]....]....]....]....]....]....]....]...
// e.g. Input data of [8b, 1d, dc, 44]
// Look for the first two square brackets:
if (result.length > 158 && result[0] === 93 && result[5] === 93) {
// If the first two square brackets are there, check that the others
// are also there. If they are, throw an error. If not, continue.
let valid = false;
for (let i = 0; i < 155; i += 5) {
if (result[i] !== 93) {
valid = true;
}
}
if (!valid) {
throw new OperationError("Error: Unable to inflate data");
}
}
// This seems to be the easiest way...
return result.buffer;
}

View File

@@ -5,6 +5,7 @@
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
/**
* Reverse operation
@@ -26,7 +27,8 @@ class Reverse extends Operation {
{
"name": "By",
"type": "option",
"value": ["Character", "Line"]
"value": ["Byte", "Character", "Line"],
"defaultIndex": 1
}
];
}
@@ -57,6 +59,24 @@ class Reverse extends Operation {
result.push(0x0a);
}
return result.slice(0, input.length);
} else if (args[0] === "Character") {
const inputString = Utils.byteArrayToUtf8(input);
let result = "";
for (let i = inputString.length - 1; i >= 0; i--) {
const c = inputString.charCodeAt(i);
if (i > 0 && 0xdc00 <= c && c <= 0xdfff) {
const c2 = inputString.charCodeAt(i - 1);
if (0xd800 <= c2 && c2 <= 0xdbff) {
// surrogates
result += inputString.charAt(i - 1);
result += inputString.charAt(i);
i--;
continue;
}
}
result += inputString.charAt(i);
}
return Utils.strToUtf8ByteArray(result);
} else {
return input.reverse();
}

View File

@@ -0,0 +1,78 @@
/**
* @author mikecat
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs";
/**
* Shuffle operation
*/
class Shuffle extends Operation {
/**
* Shuffle constructor
*/
constructor() {
super();
this.name = "Shuffle";
this.module = "Default";
this.description = "Randomly reorders input elements.";
this.infoURL = "https://wikipedia.org/wiki/Shuffling";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
name: "Delimiter",
type: "option",
value: INPUT_DELIM_OPTIONS
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const delim = Utils.charRep(args[0]);
if (input.length === 0) return input;
// return a random number in [0, 1)
const rng = (typeof crypto) !== "undefined" && crypto.getRandomValues ? (function() {
const buf = new Uint32Array(2);
return function() {
// generate 53-bit random integer: 21 + 32 bits
crypto.getRandomValues(buf);
const value = (buf[0] >>> (32 - 21)) * ((1 << 30) * 4) + buf[1];
return value / ((1 << 23) * (1 << 30));
};
})() : Math.random;
// return a random integer in [0, max)
const randint = function(max) {
return Math.floor(rng() * max);
};
// Split input into shuffleable sections
const toShuffle = input.split(delim);
// shuffle elements
for (let i = toShuffle.length - 1; i > 0; i--) {
const idx = randint(i + 1);
const tmp = toShuffle[idx];
toShuffle[idx] = toShuffle[i];
toShuffle[i] = tmp;
}
return toShuffle.join(delim);
}
}
export default Shuffle;

View File

@@ -34,10 +34,50 @@ class Substitute extends Operation {
"name": "Ciphertext",
"type": "binaryString",
"value": "XYZABCDEFGHIJKLMNOPQRSTUVW"
},
{
"name": "Ignore case",
"type": "boolean",
"value": false
}
];
}
/**
* Convert a single character using the dictionary, if ignoreCase is true then
* check in the dictionary for both upper and lower case versions of the character.
* In output the input character case is preserved.
* @param {string} char
* @param {Object} dict
* @param {boolean} ignoreCase
* @returns {string}
*/
cipherSingleChar(char, dict, ignoreCase) {
if (!ignoreCase)
return dict[char] || char;
const isUpperCase = char === char.toUpperCase();
// convert using the dictionary keeping the case of the input character
if (dict[char] !== undefined) {
// if the character is in the dictionary return the value with the input case
return isUpperCase ? dict[char].toUpperCase() : dict[char].toLowerCase();
}
// check for the other case, if it is in the dictionary return the value with the right case
if (isUpperCase) {
if (dict[char.toLowerCase()] !== undefined)
return dict[char.toLowerCase()].toUpperCase();
} else {
if (dict[char.toUpperCase()] !== undefined)
return dict[char.toUpperCase()].toLowerCase();
}
return char;
}
/**
* @param {string} input
* @param {Object[]} args
@@ -45,17 +85,23 @@ class Substitute extends Operation {
*/
run(input, args) {
const plaintext = Utils.expandAlphRange([...args[0]]),
ciphertext = Utils.expandAlphRange([...args[1]]);
let output = "",
index = -1;
ciphertext = Utils.expandAlphRange([...args[1]]),
ignoreCase = args[2];
let output = "";
if (plaintext.length !== ciphertext.length) {
output = "Warning: Plaintext and Ciphertext lengths differ\n\n";
}
// create dictionary for conversion
const dict = {};
for (let i = 0; i < Math.min(ciphertext.length, plaintext.length); i++) {
dict[plaintext[i]] = ciphertext[i];
}
// map every letter with the conversion function
for (const character of input) {
index = plaintext.indexOf(character);
output += index > -1 && index < ciphertext.length ? ciphertext[index] : character;
output += this.cipherSingleChar(character, dict, ignoreCase);
}
return output;

View File

@@ -79,6 +79,9 @@ class UNIXTimestampToWindowsFiletime extends Operation {
flipped += result.charAt(i);
flipped += result.charAt(i + 1);
}
if (result.length % 2 !== 0) {
flipped += "0" + result.charAt(0);
}
result = flipped;
}

View File

@@ -90,7 +90,7 @@ class ViewBitPlane extends Operation {
* @returns {html}
*/
present(data) {
if (!data.length) return "";
if (!data.byteLength) return "";
const type = isImage(data);
return `<img src="data:${type};base64,${toBase64(data)}">`;

View File

@@ -52,7 +52,10 @@ class WindowsFiletimeToUNIXTimestamp extends Operation {
if (format === "Hex (little endian)") {
// Swap endianness
let result = "";
for (let i = input.length - 2; i >= 0; i -= 2) {
if (input.length % 2 !== 0) {
result += input.charAt(input.length - 1);
}
for (let i = input.length - input.length % 2 - 2; i >= 0; i -= 2) {
result += input.charAt(i);
result += input.charAt(i + 1);
}

View File

@@ -52,7 +52,17 @@ class YARARules extends Operation {
name: "Show counts",
type: "boolean",
value: true
}
},
{
name: "Show rule warnings",
type: "boolean",
value: true
},
{
name: "Show console module messages",
type: "boolean",
value: true
},
];
}
@@ -64,7 +74,7 @@ class YARARules extends Operation {
async run(input, args) {
if (isWorkerEnvironment())
self.sendStatusMessage("Instantiating YARA...");
const [rules, showStrings, showLengths, showMeta, showCounts] = args;
const [rules, showStrings, showLengths, showMeta, showCounts, showRuleWarns, showConsole] = args;
return new Promise((resolve, reject) => {
Yara().then(yara => {
if (isWorkerEnvironment()) self.sendStatusMessage("Converting data for YARA.");
@@ -83,11 +93,19 @@ class YARARules extends Operation {
const compileError = resp.compileErrors.get(i);
if (!compileError.warning) {
reject(new OperationError(`Error on line ${compileError.lineNumber}: ${compileError.message}`));
} else {
matchString += `Warning on line ${compileError.lineNumber}: ${compileError.message}`;
} else if (showRuleWarns) {
matchString += `Warning on line ${compileError.lineNumber}: ${compileError.message}\n`;
}
}
}
if (showConsole) {
const consoleLogs = resp.consoleLogs;
for (let i = 0; i < consoleLogs.size(); i++) {
matchString += consoleLogs.get(i) + "\n";
}
}
const matchedRules = resp.matchedRules;
for (let i = 0; i < matchedRules.size(); i++) {
const rule = matchedRules.get(i);
@@ -100,11 +118,11 @@ class YARARules extends Operation {
}
meta = meta.slice(0, -2) + "]";
}
const countString = showCounts ? `${matches.size()} time${matches.size() > 1 ? "s" : ""}` : "";
const countString = matches.size() === 0 ? "" : (showCounts ? ` (${matches.size()} time${matches.size() > 1 ? "s" : ""})` : "");
if (matches.size() === 0 || !(showStrings || showLengths)) {
matchString += `Input matches rule "${rule.ruleName}"${meta}${countString.length > 0 ? ` ${countString}`: ""}.\n`;
} else {
matchString += `Rule "${rule.ruleName}"${meta} matches (${countString}):\n`;
matchString += `Rule "${rule.ruleName}"${meta} matches${countString}:\n`;
for (let j = 0; j < matches.size(); j++) {
const match = matches.get(j);
if (showStrings || showLengths) {

View File

@@ -10,7 +10,7 @@
import "highlight.js/styles/vs.css";
/* Frameworks */
import "./vendors/bootstrap.scss";
import "bootstrap-material-design/dist/css/bootstrap-material-design.css";
import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css";
/* CyberChef styles */

View File

@@ -82,7 +82,17 @@ a:focus {
border-color: var(--btn-success-hover-border-colour);
}
select.form-control:not([size]):not([multiple]), select.custom-file-control:not([size]):not([multiple]) {
select.form-control,
select.form-control:focus {
background-color: var(--primary-background-colour) !important;
}
select.form-control:focus {
transition: none !important;
}
select.form-control:not([size]):not([multiple]),
select.custom-file-control:not([size]):not([multiple]) {
height: unset !important;
}
@@ -145,7 +155,8 @@ optgroup {
color: var(--primary-font-colour);
}
.table-bordered th, .table-bordered td {
.table-bordered th,
.table-bordered td {
border: 1px solid var(--table-border-colour);
}
@@ -172,7 +183,9 @@ optgroup {
color: var(--subtext-font-colour);
}
.nav-tabs>li>a.nav-link.active, .nav-tabs>li>a.nav-link.active:focus, .nav-tabs>li>a.nav-link.active:hover {
.nav-tabs>li>a.nav-link.active,
.nav-tabs>li>a.nav-link.active:focus,
.nav-tabs>li>a.nav-link.active:hover {
background-color: var(--secondary-background-colour);
border-color: var(--secondary-border-colour);
border-bottom-color: transparent;
@@ -183,7 +196,8 @@ optgroup {
border-color: var(--primary-border-colour);
}
.nav a.nav-link:focus, .nav a.nav-link:hover {
.nav a.nav-link:focus,
.nav a.nav-link:hover {
background-color: var(--secondary-border-colour);
}
@@ -199,7 +213,8 @@ optgroup {
color: var(--primary-font-colour);
}
.dropdown-menu a:focus, .dropdown-menu a:hover {
.dropdown-menu a:focus,
.dropdown-menu a:hover {
background-color: var(--secondary-background-colour);
color: var(--primary-font-colour);
}

View File

@@ -1,23 +0,0 @@
/**
* Bootstrap Material Design with overrides
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
@import "~bootstrap-material-design/scss/variables/colors";
$theme-colors: (
primary: $blue-700,
success: $green,
info: $light-blue,
warning: $deep-orange,
danger: $red,
light: $grey-100,
dark: $grey-800
);
$bmd-form-line-height: 1.25;
@import "~bootstrap-material-design/scss/core";

View File

@@ -45,10 +45,10 @@ TestRegister.addApiTests([
const result = chef.ADD("sample input", {
key: {
string: "some key",
option: "Hex"
option: "utf8"
}
});
assert.equal(result.toString(), "aO[^ZS\u000eW\\^cb");
assert.equal(result.toString(), "\xe6\xd0\xda\xd5\x8c\xd0\x85\xe2\xe1\xdf\xe2\xd9");
}),
@@ -121,10 +121,10 @@ Tiger-128`;
const result = chef.AND("Scot-free", {
key: {
string: "Raining Cats and Dogs",
option: "Hex",
option: "utf8",
}
});
assert.strictEqual(result.toString(), "\u0000\"M$(D E");
assert.strictEqual(result.toString(), "Raid)fb A");
}),
it("atBash Cipher", () => {
@@ -371,10 +371,10 @@ color: white;
},
salt: {
string: "Market",
option: "Hex",
option: "utf8",
},
});
assert.strictEqual(result.toString(), "7c21a9f5063a4d62fb1050068245c181");
assert.strictEqual(result.toString(), "4930d5d200e80f18c96b5550d13c6af8");
}),
it("Derive PBKDF2 Key", () => {

View File

@@ -28,6 +28,8 @@ import "./tests/Base85.mjs";
import "./tests/BitwiseOp.mjs";
import "./tests/ByteRepr.mjs";
import "./tests/CartesianProduct.mjs";
import "./tests/CetaceanCipherEncode.mjs";
import "./tests/CetaceanCipherDecode.mjs";
import "./tests/CharEnc.mjs";
import "./tests/ChangeIPFormat.mjs";
import "./tests/Charts.mjs";
@@ -43,6 +45,7 @@ import "./tests/DateTime.mjs";
import "./tests/ExtractEmailAddresses.mjs";
import "./tests/Fork.mjs";
import "./tests/FromDecimal.mjs";
import "./tests/GenerateAllHashes.mjs";
import "./tests/Gzip.mjs";
import "./tests/Gunzip.mjs";
import "./tests/Hash.mjs";
@@ -117,9 +120,11 @@ import "./tests/SIGABA.mjs";
import "./tests/ELFInfo.mjs";
import "./tests/Subsection.mjs";
import "./tests/CaesarBoxCipher.mjs";
import "./tests/UnescapeString.mjs";
import "./tests/LS47.mjs";
import "./tests/LZString.mjs";
import "./tests/NTLM.mjs";
import "./tests/Shuffle.mjs";
// Cannot test operations that use the File type yet
// import "./tests/SplitColourChannels.mjs";

View File

@@ -0,0 +1,22 @@
/**
* CetaceanCipher Encode tests
*
* @author dolphinOnKeys
* @copyright Crown Copyright 2022
* @licence Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Cetacean Cipher Decode",
input: "EEEEEEEEEeeEEEEe EEEEEEEEEeeEEEeE EEEEEEEEEeeEEEee EEeeEEEEEeeEEeee",
expectedOutput: "a b c で",
recipeConfig: [
{
op: "Cetacean Cipher Decode",
args: []
},
],
}
]);

View File

@@ -0,0 +1,22 @@
/**
* CetaceanCipher Encode tests
*
* @author dolphinOnKeys
* @copyright Crown Copyright 2022
* @licence Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Cetacean Cipher Encode",
input: "a b c で",
expectedOutput: "EEEEEEEEEeeEEEEe EEEEEEEEEeeEEEeE EEEEEEEEEeeEEEee EEeeEEEEEeeEEeee",
recipeConfig: [
{
op: "Cetacean Cipher Encode",
args: []
},
],
}
]);

View File

@@ -185,11 +185,11 @@ TestRegister.addTests([
{
name: "JPath Expression: Empty expression",
input: JSON.stringify(JSON_TEST_DATA),
expectedOutput: "Invalid JPath expression: we need a path",
expectedOutput: "",
recipeConfig: [
{
"op": "JPath expression",
"args": ["", "\n"]
"args": ["", "\n", true]
}
],
},
@@ -205,7 +205,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$.store.book[*].author", "\n"]
"args": ["$.store.book[*].author", "\n", true]
}
],
},
@@ -223,7 +223,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..title", "\n"]
"args": ["$..title", "\n", true]
}
],
},
@@ -238,7 +238,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$.store.*", "\n"]
"args": ["$.store.*", "\n", true]
}
],
},
@@ -249,7 +249,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[-1:]", "\n"]
"args": ["$..book[-1:]", "\n", true]
}
],
},
@@ -263,7 +263,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[:2]", "\n"]
"args": ["$..book[:2]", "\n", true]
}
],
},
@@ -277,7 +277,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.isbn)]", "\n"]
"args": ["$..book[?(@.isbn)]", "\n", false]
}
],
},
@@ -292,7 +292,7 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n"]
"args": ["$..book[?(@.price<30 && @.category==\"fiction\")]", "\n", false]
}
],
},
@@ -306,10 +306,25 @@ TestRegister.addTests([
recipeConfig: [
{
"op": "JPath expression",
"args": ["$..book[?(@.price<10)]", "\n"]
"args": ["$..book[?(@.price<10)]", "\n", false]
}
],
},
{
name: "JPath Expression: Script-based expression",
input: "[{}]",
recipeConfig: [
{
"op": "JPath expression",
"args": [
"$..[?(({__proto__:[].constructor}).constructor(\"self.postMessage({action:'bakeComplete',data:{bakeId:1,dish:{type:1,value:''},duration:1,error:false,id:undefined,inputNum:2,progress:1,result:'<iframe/onload=debugger>',type: 'html'}});\")();)]",
"\n",
true
]
}
],
expectedOutput: "Invalid JPath expression: Eval [?(expr)] prevented in JSONPath expression."
},
{
name: "CSS selector",
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',

View File

@@ -23,4 +23,86 @@ TestRegister.addTests([
}
],
},
{
name: "LZMA compress & decompress",
input: "The cat sat on the mat.",
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op": "LZMA Compress",
"args": ["6"]
},
{
"op": "LZMA Decompress",
"args": []
},
],
},
{
name: "LZMA decompress: binary",
// Generated using command `echo "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10" | xxd -r -p | lzma -z -6 | xxd -p`
input: "5d00008000ffffffffffffffff00000052500a84f99bb28021a969d627e03e8a922effffbd160000",
expectedOutput: "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "LZMA Decompress",
"args": []
},
{
"op": "To Hex",
"args": ["Space", 0]
}
],
},
{
name: "LZMA decompress: string",
// Generated using command `echo -n "The cat sat on the mat." | lzma -z -6 | xxd -p`
input: "5d00008000ffffffffffffffff002a1a08a202b1a4b814b912c94c4152e1641907d3fd8cd903ffff4fec0000",
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op": "From Hex",
"args": ["Space"]
},
{
"op": "LZMA Decompress",
"args": []
}
],
},
{
name: "LZ4 Compress",
input: "The cat sat on the mat.",
expectedOutput: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
recipeConfig: [
{
"op": "LZ4 Compress",
"args": []
},
{
"op": "To Hex",
"args": ["None", 0]
}
],
},
{
name: "LZ4 Decompress",
input: "04224d184070df170000805468652063617420736174206f6e20746865206d61742e00000000",
expectedOutput: "The cat sat on the mat.",
recipeConfig: [
{
"op": "From Hex",
"args": ["None"]
},
{
"op": "LZ4 Decompress",
"args": []
}
],
},
]);

View File

@@ -0,0 +1,115 @@
/**
* GenerateAllHashes tests.
*
* @author john19696 [john19696@protonmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Full generate all hashes",
input: "test",
expectedOutput: `MD2: dd34716876364a02d0195e2fb9ae2d1b
MD4: db346d691d7acc4dc2625db19f9e3f52
MD5: 098f6bcd4621d373cade4e832627b4f6
MD6: 93c8a7d0ff132f325138a82b2baa98c12a7c9ac982feb6c5b310a1ca713615bd
SHA0: f8d3b312442a67706057aeb45b983221afb4f035
SHA1: a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
SHA2 224: 90a3ed9e32b2aaf4c61c410eb925426119e1a9dc53d4286ade99a809
SHA2 256: 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
SHA2 384: 768412320f7b0aa5812fce428dc4706b3cae50e02a64caa16a782249bfe8efc4b7ef1ccb126255d196047dfedf17a0a9
SHA2 512: ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff
SHA3 224: 3797bf0afbbfca4a7bbba7602a2b552746876517a7f9b7ce2db0ae7b
SHA3 256: 36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
SHA3 384: e516dabb23b6e30026863543282780a3ae0dccf05551cf0295178d7ff0f1b41eecb9db3ff219007c4e097260d58621bd
SHA3 512: 9ece086e9bac491fac5c1d1046ca11d737b92a2b2ebd93f005d7b710110c0a678288166e7fbe796883a4f2e9b3ca9f484f521d0ce464345cc1aec96779149c14
Keccak 224: 3be30a9ff64f34a5861116c5198987ad780165f8366e67aff4760b5e
Keccak 256: 9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658
Keccak 384: 53d0ba137307d4c2f9b6674c83edbd58b70c0f4340133ed0adc6fba1d2478a6a03b7788229e775d2de8ae8c0759d0527
Keccak 512: 1e2e9fc2002b002d75198b7503210c05a1baac4560916a3c6d93bcce3a50d7f00fd395bf1647b9abb8d1afcc9c76c289b0c9383ba386a956da4b38934417789e
Shake 128: d3b0aa9cd8b7255622cebc631e867d4093d6f6010191a53973c45fec9b07c774
Shake 256: b54ff7255705a71ee2925e4a3e30e41aed489a579d5595e0df13e32e1e4dd202a7c7f68b31d6418d9845eb4d757adda6ab189e1bb340db818e5b3bc725d992fa
RIPEMD-128: f1abb5083c9ff8a9dbbca9cd2b11fead
RIPEMD-160: 5e52fee47e6b070565f74372468cdc699de89107
RIPEMD-256: fe0289110d07daeee9d9500e14c57787d9083f6ba10e6bcb256f86bb4fe7b981
RIPEMD-320: 3b0a2e841e589cf583634a5dd265d2b5d497c4cc44b241e34e0f62d03e98c1b9dc72970b9bc20eb5
HAS-160: cb15e491eec6e769771d1f811315139c93071084
Whirlpool-0: d50ff71342b521974bae166539871922669afcfc7181250ebbae015c317ebb797173a69e7a05afd11099a9f0918159cd5bc88434d3ca44513d7263caea9244fe
Whirlpool-T: e6b4aa087751b4428171777f1893ba585404c7e0171787720eba0d8bccd710dc2c42f874c572bfae4cedabf50f2c80bf923805d4e31c504b86ca3bc59265e7dd
Whirlpool: b913d5bbb8e461c2c5961cbe0edcdadfd29f068225ceb37da6defcf89849368f8c6c2eb6a4c4ac75775d032a0ecfdfe8550573062b653fe92fc7b8fb3b7be8d6
BLAKE2b-128: 44a8995dd50b6657a037a7839304535b
BLAKE2b-160: a34fc3b6d2cce8beb3216c2bbb5e55739e8121ed
BLAKE2b-256: 928b20366943e2afd11ebc0eae2e53a93bf177a4fcf35bcc64d503704e65e202
BLAKE2b-384: 8a84b8666c8fcfb69f2ec41f578d7c85fbdb504ea6510fb05b50fcbf7ed8153c77943bc2da73abb136834e1a0d4f22cb
BLAKE2b-512: a71079d42853dea26e453004338670a53814b78137ffbed07603a41d76a483aa9bc33b582f77d30a65e6f29a896c0411f38312e1d66e0bf16386c86a89bea572
BLAKE2s-128: e9ddd9926b9dcb382e09be39ba403d2c
BLAKE2s-160: d6197dabec2bd6f4ff303b8e519e8f15d42a453d
BLAKE2s-256: f308fc02ce9172ad02a7d75800ecfc027109bc67987ea32aba9b8dcc7b10150e
Streebog-256: 12a50838191b5504f1e5f2fd078714cf6b592b9d29af99d0b10d8d02881c3857
Streebog-512: 7200bf5dea560f0d7960d07fdc8874ad9f3b86ece2e45f5502ae2e176f2c928e0e581152281f5aee818318bed7cbe6aa69999589234723ceb33175598365b5c8
GOST: ee67303696d205ddd2b2363e8e01b4b7199a80957d94d7678eaad3fc834c5a27
LM Hash: 01FC5A6BE7BC6929AAD3B435B51404EE
NT Hash: 0CB6948805F797BF2A82807973B89537
SSDEEP: 3:Hn:Hn
CTPH: A:E:E
Checksums:
Fletcher-8: 3d
Fletcher-16: 5dc1
Fletcher-32: 045901c0
Fletcher-64: 00000459000001c0
Adler-32: 045d01c1
CRC-8: b9
CRC-16: f82e
CRC-32: d87f7e0c
`,
recipeConfig: [
{
"op": "Generate all hashes",
"args": ["All", true]
}
]
},
{
name: "Hashes with length 32",
input: "test",
expectedOutput: `MD2: dd34716876364a02d0195e2fb9ae2d1b
MD4: db346d691d7acc4dc2625db19f9e3f52
MD5: 098f6bcd4621d373cade4e832627b4f6
RIPEMD-128: f1abb5083c9ff8a9dbbca9cd2b11fead
BLAKE2b-128: 44a8995dd50b6657a037a7839304535b
BLAKE2s-128: e9ddd9926b9dcb382e09be39ba403d2c
LM Hash: 01FC5A6BE7BC6929AAD3B435B51404EE
NT Hash: 0CB6948805F797BF2A82807973B89537
`,
recipeConfig: [
{
"op": "Generate all hashes",
"args": ["128", true]
}
]
},
{
name: "Hashes without names",
input: "test",
expectedOutput: `93c8a7d0ff132f325138a82b2baa98c12a7c9ac982feb6c5b310a1ca713615bd
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
36f028580bb02cc8272a9a020f4200e346e276ae664e45ee80745574e2f5ab80
9c22ff5f21f0b81b113e63f7db6da94fedef11b2119b4088b89664fb9a3cb658
d3b0aa9cd8b7255622cebc631e867d4093d6f6010191a53973c45fec9b07c774
fe0289110d07daeee9d9500e14c57787d9083f6ba10e6bcb256f86bb4fe7b981
928b20366943e2afd11ebc0eae2e53a93bf177a4fcf35bcc64d503704e65e202
f308fc02ce9172ad02a7d75800ecfc027109bc67987ea32aba9b8dcc7b10150e
12a50838191b5504f1e5f2fd078714cf6b592b9d29af99d0b10d8d02881c3857
ee67303696d205ddd2b2363e8e01b4b7199a80957d94d7678eaad3fc834c5a27
`,
recipeConfig: [
{
"op": "Generate all hashes",
"args": ["256", false]
}
]
}
]);

View File

@@ -46,6 +46,17 @@ TestRegister.addTests([
},
],
},
{
name: "JSON to CSV: boolean and null as values",
input: JSON.stringify({a: false, b: null, c: 3}),
expectedOutput: "a,b,c\r\nfalse,null,3\r\n",
recipeConfig: [
{
op: "JSON to CSV",
args: [",", "\\r\\n"]
},
],
},
{
name: "JSON to CSV: JSON as an array",
input: JSON.stringify([{a: 1, b: "2", c: 3}]),

View File

@@ -0,0 +1,34 @@
/**
* NTLM test.
*
* @author brun0ne [brunonblok@gmail.com]
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "NT Hash",
input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/",
expectedOutput: "C5FA1C40E55734A8E528DBFE21766D23",
recipeConfig: [
{
op: "NT Hash",
args: [],
},
],
},
{
name: "LM Hash",
input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/",
expectedOutput: "6D9DF16655336CA75A3C13DD18BA8156",
recipeConfig: [
{
op: "LM Hash",
args: [],
},
],
},
]);

View File

@@ -49,6 +49,18 @@ Point: 0x046c59592006272250a15070142a6be36d1e45464313f930d985a6e6f0eba3cd39d0367
}
]
},
{
name: "SSH Host Key: Ed25519",
input: "AAAAC3NzaC1lZDI1NTE5AAAAIBOF6r99IkvqGu1kwZrHHIqjpTB5w79bpv67B/Aw3+WJ",
expectedOutput: `Key type: ssh-ed25519
x: 0x1385eabf7d224bea1aed64c19ac71c8aa3a53079c3bf5ba6febb07f030dfe589`,
recipeConfig: [
{
op: "Parse SSH Host Key",
args: ["Base64"]
}
]
},
{
name: "SSH Host Key: Extract key",
input: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiJZ/9W9Ix/Dk9b+K4E+RGCug1AtkGXaJ9vNIY0YHFHLpWsB8DAuh/cGEI9TLbL1gzR2wG+RJNQ2EAQVWe6ypkK63Jm4zw4re+vhEiszpnP889J0h5N9yzyTndesrl4d3cQtv861FcKDPxUJbRALdtl6gwOB7BCL8gsXJLLVLO4EesrbPXD454qpVt7CgJXEXByOFjcIm3XwkdOnXMPHHnMSD7EIN1SvQMD6PfIDrbDd6KQt5QXW/Rc/BsfX5cbUIV1QW5A/GbepXHHKmWRtLC2J/mH3hW2Zq/hITPEaJdG1CtIilQmJaZGXpfGIwFeb0Av9pSL926arZZ6vDi9ctF test@test",

View File

@@ -40,10 +40,10 @@ TestRegister.addTests([
"Apple": [
28
],
"Banana": "You",
"Carrot": [
"Me"
]
],
"Banana": "You"
}, null, 4),
recipeConfig: [
{
@@ -72,10 +72,10 @@ TestRegister.addTests([
"Apple": [
28
],
"Banana": "You",
"Carrot": [
"Me"
]
],
"Banana": "You"
},
"Unknown Fields": {
"4": 43,
@@ -111,10 +111,10 @@ TestRegister.addTests([
"Apple": [
28
],
"Banana": "You",
"Carrot": [
"Me"
],
"Banana": "You",
"Date": 43,
"Elderberry": {
"Fig": "abc123",
@@ -154,10 +154,10 @@ TestRegister.addTests([
input: "0d1c0000001203596f751a024d65202b2a0a0a06616263313233120031ba32a96cc10200003801",
expectedOutput: JSON.stringify({
"Test": {
"Banana (string)": "You",
"Carrot (string)": [
"Me"
],
"Banana (string)": "You",
"Date (int32)": 43,
"Imbe (Options)": "Option1"
},

View File

@@ -0,0 +1,54 @@
/**
* @author mikecat
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
"name": "Shuffle empty",
"input": "",
"expectedOutput": "",
"recipeConfig": [
{
"op": "Shuffle",
"args": ["Comma"]
}
]
},
{
"name": "Shuffle bytes",
"input": "12345678",
"expectedOutput": "31 32 33 34 35 36 37 38",
"recipeConfig": [
{
"op": "Shuffle",
"args": ["Nothing (separate chars)"]
},
{
"op": "To Hex",
"args": ["Space", 0]
},
{
"op": "Sort",
"args": ["Space", false, "Alphabetical (case sensitive)"]
}
]
},
{
"name": "Shuffle lines",
"input": "1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf\n",
"expectedOutput": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf",
"recipeConfig": [
{
"op": "Shuffle",
"args": ["Line feed"]
},
{
"op": "Sort",
"args": ["Line feed", false, "Alphabetical (case sensitive)"]
}
]
}
]);

View File

@@ -0,0 +1,55 @@
/**
* UnescapeString tests.
*
* @copyright Crown Copyright 2022
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "UnescapeString: escape sequences",
input: "\\a\\b\\f\\n\\r\\t\\v\\'\\\"",
expectedOutput: String.fromCharCode(0x07, 0x08, 0x0c, 0x0a, 0x0d, 0x09,
0x0b, 0x27, 0x22),
recipeConfig: [
{
op: "Unescape string",
args: [],
},
],
},
{
name: "UnescapeString: octals",
input: "\\0\\01\\012\\1\\12",
expectedOutput: String.fromCharCode(0, 1, 10, 1, 10),
recipeConfig: [
{
op: "Unescape string",
args: [],
},
],
},
{
name: "UnescapeString: hexadecimals",
input: "\\x00\\xAA\\xaa",
expectedOutput: String.fromCharCode(0, 170, 170),
recipeConfig: [
{
op: "Unescape string",
args: [],
},
],
},
{
name: "UnescapeString: unicode",
input: "\\u0061\\u{0062}",
expectedOutput: "ab",
recipeConfig: [
{
op: "Unescape string",
args: [],
},
],
},
]);

View File

@@ -8,6 +8,22 @@
*/
import TestRegister from "../../lib/TestRegister.mjs";
const CONSOLE_COMPILE_WARNING_RULE = `import "console"
rule a
{
strings:
$s=" "
condition:
$s and console.log("log rule a")
}
rule b
{
strings:
$s=" "
condition:
$s and console.hex("log rule b: int8(0)=", int8(0))
}`;
TestRegister.addTests([
{
name: "YARA Match: simple foobar",
@@ -20,5 +36,56 @@ TestRegister.addTests([
}
],
},
{
name: "YARA Match: hashing rules",
input: "Hello World!",
expectedOutput: "Input matches rule \"HelloWorldMD5\".\nInput matches rule \"HelloWorldSHA256\".\n",
recipeConfig: [
{
"op": "YARA Rules",
"args": [
`import "hash"
rule HelloWorldMD5 {
condition:
hash.md5(0,filesize) == "ed076287532e86365e841e92bfc50d8c"
}
rule HelloWorldSHA256 {
condition:
hash.sha256(0,filesize) == "7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"
}`,
true, true, true, true, false, false
],
}
],
},
{
name: "YARA Match: compile warnings",
input: "CyberChef Yara",
expectedOutput: "Warning on line 5: string \"$s\" may slow down scanning\n" +
"Warning on line 12: string \"$s\" may slow down scanning\n" +
"Input matches rule \"a\".\n" +
"Input matches rule \"b\".\n",
recipeConfig: [
{
"op": "YARA Rules",
"args": [CONSOLE_COMPILE_WARNING_RULE, false, false, false, false, true, false],
}
],
},
{
name: "YARA Match: console messages",
input: "CyberChef Yara",
expectedOutput: "log rule a\n" +
"log rule b: int8(0)=0x43\n" +
"Input matches rule \"a\".\n" +
"Input matches rule \"b\".\n",
recipeConfig: [
{
"op": "YARA Rules",
"args": [CONSOLE_COMPILE_WARNING_RULE, false, false, false, false, false, true],
}
],
},
]);

View File

@@ -109,7 +109,8 @@ module.exports = {
"buffer": require.resolve("buffer/"),
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"zlib": require.resolve("browserify-zlib")
"zlib": require.resolve("browserify-zlib"),
"process": false
}
},
module: {
@@ -164,19 +165,6 @@ module.exports = {
"postcss-loader",
]
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
}
},
"css-loader",
"sass-loader",
]
},
{
test: /\.(ico|eot|ttf|woff|woff2)$/,
type: "asset/resource",