mirror of
https://github.com/gchq/CyberChef
synced 2025-12-16 00:04:20 +00:00
Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b0ced9f9b | ||
|
|
7b245b084a | ||
|
|
b00f64518f | ||
|
|
c3434e894d | ||
|
|
dd66f728b3 | ||
|
|
e40142b8c5 | ||
|
|
1dd1b839b8 | ||
|
|
d90d845f27 | ||
|
|
8c9ad81039 | ||
|
|
cef7a7b27d | ||
|
|
3e715ef21a | ||
|
|
86b43b4ffa | ||
|
|
65d883496b | ||
|
|
69e59916e2 | ||
|
|
475282984b | ||
|
|
2f89130f41 | ||
|
|
e9dd7eceb8 | ||
|
|
037590f831 | ||
|
|
85496684d8 | ||
|
|
4200ed4eb9 | ||
|
|
6b16f11d3b | ||
|
|
683bd3e5db | ||
|
|
6a10e94bfd | ||
|
|
25086386c6 | ||
|
|
d99ee32cc4 | ||
|
|
f1d318f229 | ||
|
|
a7fc455e05 | ||
|
|
c02c4a72e4 | ||
|
|
f97ce18ff9 | ||
|
|
dfd9afc2c4 | ||
|
|
eb5663a1ed | ||
|
|
418a7962a5 | ||
|
|
2ffce23c67 | ||
|
|
b828b50ccc | ||
|
|
a6aa40db97 | ||
|
|
45ede4beaf | ||
|
|
98a95c8bbf | ||
|
|
74bb8d92dc | ||
|
|
6cccc2c786 | ||
|
|
99a0a05947 | ||
|
|
94700dab89 | ||
|
|
c9d29c89bb | ||
|
|
7d4e554571 | ||
|
|
2858a74cbf | ||
|
|
28e599a835 | ||
|
|
1fb1d9cbb7 | ||
|
|
2f097e5dfc | ||
|
|
b71e3241be | ||
|
|
4b018bf421 | ||
|
|
f751de896f | ||
|
|
65aeae9c1e | ||
|
|
80943b0c26 | ||
|
|
a9657ac5c7 | ||
|
|
6fa2e49f3a | ||
|
|
50f0f70805 | ||
|
|
fc95d82c49 | ||
|
|
bb6c1c54ff | ||
|
|
c4414bd910 | ||
|
|
42c911838d | ||
|
|
8917eabfd1 | ||
|
|
fc91469807 | ||
|
|
1735d9c091 | ||
|
|
00d754d466 | ||
|
|
906727f133 | ||
|
|
191d7f11f7 | ||
|
|
54fdc05e3a | ||
|
|
2267569c8d | ||
|
|
2f53ee3974 | ||
|
|
a3b846638f | ||
|
|
cc3033266c | ||
|
|
23b168515c | ||
|
|
049690fea2 | ||
|
|
d3de91de85 | ||
|
|
64eae37788 | ||
|
|
8c71b0b8df | ||
|
|
2bf1ac6b9c | ||
|
|
7197a434c2 | ||
|
|
5349115b94 | ||
|
|
4274e8f3a2 | ||
|
|
7610e159a3 | ||
|
|
9ec94434bb | ||
|
|
1ab444bda2 | ||
|
|
3990ba774f | ||
|
|
1fea9a25a5 | ||
|
|
e712af33b7 | ||
|
|
578a61d331 | ||
|
|
671ae6558f | ||
|
|
e8f91316ff | ||
|
|
667dfd820e | ||
|
|
3e3c526a62 | ||
|
|
f5a7db03cd | ||
|
|
ee408f7add | ||
|
|
1294d764e2 | ||
|
|
eab1be0e2c | ||
|
|
15dd9d4c93 | ||
|
|
103ecff6a7 | ||
|
|
0182cdda69 | ||
|
|
e91e993fb5 | ||
|
|
e71794d362 | ||
|
|
6fd929160d | ||
|
|
5cdd062ed9 | ||
|
|
0259ed8314 | ||
|
|
d8405e5f81 | ||
|
|
0295d0c9b4 | ||
|
|
8e1e1d56ca | ||
|
|
63bb19d48d | ||
|
|
e92ed13864 |
2
.github/workflows/master.yml
vendored
2
.github/workflows/master.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '17.x'
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
|
||||
2
.github/workflows/pull_requests.yml
vendored
2
.github/workflows/pull_requests.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '17.x'
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
|
||||
2
.github/workflows/releases.yml
vendored
2
.github/workflows/releases.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Set node version
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '17.x'
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Install
|
||||
run: |
|
||||
|
||||
45
CHANGELOG.md
45
CHANGELOG.md
@@ -13,6 +13,30 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
## Details
|
||||
|
||||
### [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]
|
||||
|
||||
### [9.43.0] - 2022-07-08
|
||||
- Added 'ROT13 Brute Force' and 'ROT47 Brute Force' operations [@mikecat] | [#1264]
|
||||
|
||||
### [9.42.0] - 2022-07-08
|
||||
- Added 'LS47 Encrypt' and 'LS47 Decrypt' operations [@n1073645] | [#951]
|
||||
|
||||
### [9.41.0] - 2022-07-08
|
||||
- Added 'Caesar Box Cipher' operation [@n1073645] | [#1066]
|
||||
|
||||
### [9.40.0] - 2022-07-08
|
||||
- Added 'P-list Viewer' operation [@n1073645] | [#906]
|
||||
|
||||
### [9.39.0] - 2022-06-09
|
||||
- Added 'ELF Info' operation [@n1073645] | [#1364]
|
||||
|
||||
### [9.38.0] - 2022-05-30
|
||||
- Added 'Parse TCP' operation [@n1474335] | [a895d1d]
|
||||
|
||||
@@ -291,6 +315,14 @@ All major and minor version changes will be documented in this file. Details of
|
||||
|
||||
|
||||
|
||||
[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
|
||||
[9.41.0]: https://github.com/gchq/CyberChef/releases/tag/v9.41.0
|
||||
[9.40.0]: https://github.com/gchq/CyberChef/releases/tag/v9.40.0
|
||||
[9.39.0]: https://github.com/gchq/CyberChef/releases/tag/v9.39.0
|
||||
[9.38.0]: https://github.com/gchq/CyberChef/releases/tag/v9.38.0
|
||||
[9.37.0]: https://github.com/gchq/CyberChef/releases/tag/v9.37.0
|
||||
[9.36.0]: https://github.com/gchq/CyberChef/releases/tag/v9.36.0
|
||||
@@ -414,6 +446,10 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[@t-8ch]: https://github.com/t-8ch
|
||||
[@hettysymes]: https://github.com/hettysymes
|
||||
[@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
|
||||
|
||||
[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7
|
||||
[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513
|
||||
@@ -487,10 +523,12 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#674]: https://github.com/gchq/CyberChef/pull/674
|
||||
[#683]: https://github.com/gchq/CyberChef/pull/683
|
||||
[#865]: https://github.com/gchq/CyberChef/pull/865
|
||||
[#906]: https://github.com/gchq/CyberChef/pull/906
|
||||
[#912]: https://github.com/gchq/CyberChef/pull/912
|
||||
[#917]: https://github.com/gchq/CyberChef/pull/917
|
||||
[#934]: https://github.com/gchq/CyberChef/pull/934
|
||||
[#948]: https://github.com/gchq/CyberChef/pull/948
|
||||
[#951]: https://github.com/gchq/CyberChef/pull/951
|
||||
[#952]: https://github.com/gchq/CyberChef/pull/952
|
||||
[#965]: https://github.com/gchq/CyberChef/pull/965
|
||||
[#966]: https://github.com/gchq/CyberChef/pull/966
|
||||
@@ -502,9 +540,16 @@ All major and minor version changes will be documented in this file. Details of
|
||||
[#1045]: https://github.com/gchq/CyberChef/pull/1045
|
||||
[#1049]: https://github.com/gchq/CyberChef/pull/1049
|
||||
[#1065]: https://github.com/gchq/CyberChef/pull/1065
|
||||
[#1066]: https://github.com/gchq/CyberChef/pull/1066
|
||||
[#1083]: https://github.com/gchq/CyberChef/pull/1083
|
||||
[#1189]: https://github.com/gchq/CyberChef/pull/1189
|
||||
[#1242]: https://github.com/gchq/CyberChef/pull/1242
|
||||
[#1244]: https://github.com/gchq/CyberChef/pull/1244
|
||||
[#1313]: https://github.com/gchq/CyberChef/pull/1313
|
||||
[#1326]: https://github.com/gchq/CyberChef/pull/1326
|
||||
[#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
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -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).
|
||||
|
||||
|
||||
3186
package-lock.json
generated
3186
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "9.38.6",
|
||||
"version": "9.46.4",
|
||||
"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",
|
||||
@@ -122,7 +121,8 @@
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.8.0",
|
||||
"jsesc": "^3.0.2",
|
||||
"jsonpath": "^1.1.1",
|
||||
"json5": "^2.2.1",
|
||||
"jsonpath-plus": "^7.2.0",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"jsqr": "^1.4.0",
|
||||
"jsrsasign": "^10.5.23",
|
||||
@@ -132,13 +132,13 @@
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.8.0",
|
||||
"loglevel-message-prefix": "^3.0.0",
|
||||
"lz-string": "^1.4.4",
|
||||
"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",
|
||||
"nwmatcher": "^1.4.4",
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
"DES Decrypt",
|
||||
"Triple DES Encrypt",
|
||||
"Triple DES Decrypt",
|
||||
"LS47 Encrypt",
|
||||
"LS47 Decrypt",
|
||||
"RC2 Encrypt",
|
||||
"RC2 Decrypt",
|
||||
"RC4",
|
||||
@@ -86,7 +88,10 @@
|
||||
"SM4 Encrypt",
|
||||
"SM4 Decrypt",
|
||||
"ROT13",
|
||||
"ROT13 Brute Force",
|
||||
"ROT47",
|
||||
"ROT47 Brute Force",
|
||||
"ROT8000",
|
||||
"XOR",
|
||||
"XOR Brute Force",
|
||||
"Vigenère Encode",
|
||||
@@ -97,6 +102,7 @@
|
||||
"Bacon Cipher Decode",
|
||||
"Bifid Cipher Encode",
|
||||
"Bifid Cipher Decode",
|
||||
"Caesar Box Cipher",
|
||||
"Affine Cipher Encode",
|
||||
"Affine Cipher Decode",
|
||||
"A1Z26 Cipher Encode",
|
||||
@@ -106,6 +112,8 @@
|
||||
"Atbash Cipher",
|
||||
"CipherSaber2 Encrypt",
|
||||
"CipherSaber2 Decrypt",
|
||||
"Cetacean Cipher Encode",
|
||||
"Cetacean Cipher Decode",
|
||||
"Substitute",
|
||||
"Derive PBKDF2 key",
|
||||
"Derive EVP key",
|
||||
@@ -176,7 +184,8 @@
|
||||
"Bit shift right",
|
||||
"Rotate left",
|
||||
"Rotate right",
|
||||
"ROT13"
|
||||
"ROT13",
|
||||
"ROT8000"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -320,7 +329,9 @@
|
||||
"Bzip2 Decompress",
|
||||
"Bzip2 Compress",
|
||||
"Tar",
|
||||
"Untar"
|
||||
"Untar",
|
||||
"LZString Compress",
|
||||
"LZString Decompress"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -413,7 +424,8 @@
|
||||
"Extract RGBA",
|
||||
"View Bit Plane",
|
||||
"Randomize Colour Palette",
|
||||
"Extract LSB"
|
||||
"Extract LSB",
|
||||
"ELF Info"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -456,6 +468,7 @@
|
||||
"Frequency distribution",
|
||||
"Index of Coincidence",
|
||||
"Chi Square",
|
||||
"P-list Viewer",
|
||||
"Disassemble x86",
|
||||
"Pseudo-Random Number Generator",
|
||||
"Generate UUID",
|
||||
|
||||
@@ -131,7 +131,7 @@ const getFeature = function() {
|
||||
|
||||
// PR IDs
|
||||
prIDs.forEach(prID => {
|
||||
changelogData = changelogData.replace(/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n/, "$1" + prID + "\n\n");
|
||||
changelogData = changelogData.replace(/(\n\[#[^\]]+\]: https:\/\/github.com\/gchq\/CyberChef\/pull\/[^\n]+\n)\n*$/, "$1" + prID + "\n\n");
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.join(process.cwd(), "CHANGELOG.md"), changelogData);
|
||||
|
||||
@@ -130,10 +130,11 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
||||
i = 0;
|
||||
|
||||
while (i < data.length) {
|
||||
enc1 = alphabet.indexOf(data.charAt(i++));
|
||||
enc2 = alphabet.indexOf(data.charAt(i++));
|
||||
enc3 = alphabet.indexOf(data.charAt(i++));
|
||||
enc4 = alphabet.indexOf(data.charAt(i++));
|
||||
// Including `|| null` forces empty strings to null so that indexOf returns -1 instead of 0
|
||||
enc1 = alphabet.indexOf(data.charAt(i++) || null);
|
||||
enc2 = alphabet.indexOf(data.charAt(i++) || null);
|
||||
enc3 = alphabet.indexOf(data.charAt(i++) || null);
|
||||
enc4 = alphabet.indexOf(data.charAt(i++) || null);
|
||||
|
||||
if (strictMode && (enc1 < 0 || enc2 < 0 || enc3 < 0 || enc4 < 0)) {
|
||||
throw new OperationError("Error: Base64 input contains non-alphabet char(s)");
|
||||
@@ -143,13 +144,13 @@ export function fromBase64(data, alphabet="A-Za-z0-9+/=", returnType="string", r
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
if (chr1 < 256) {
|
||||
if (chr1 >= 0 && chr1 < 256) {
|
||||
output.push(chr1);
|
||||
}
|
||||
if (chr2 < 256 && enc3 !== 64) {
|
||||
if (chr2 >= 0 && chr2 < 256 && enc3 !== 64) {
|
||||
output.push(chr2);
|
||||
}
|
||||
if (chr3 < 256 && enc4 !== 64) {
|
||||
if (chr3 >= 0 && chr3 < 256 && enc4 !== 64) {
|
||||
output.push(chr3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* Base85 resources.
|
||||
*
|
||||
@@ -32,13 +34,12 @@ export const ALPHABET_OPTIONS = [
|
||||
* @returns {string}
|
||||
*/
|
||||
export function alphabetName(alphabet) {
|
||||
alphabet = alphabet.replace(/'/g, "'");
|
||||
alphabet = alphabet.replace(/"/g, """);
|
||||
alphabet = alphabet.replace(/\\/g, "\");
|
||||
alphabet = escape(alphabet);
|
||||
let name;
|
||||
|
||||
ALPHABET_OPTIONS.forEach(function(a) {
|
||||
if (escape(alphabet) === escape(a.value)) name = a.name;
|
||||
const expanded = Utils.expandAlphRange(a.value).join("");
|
||||
if (alphabet === escape(expanded)) name = a.name;
|
||||
});
|
||||
|
||||
return name;
|
||||
|
||||
@@ -70,7 +70,7 @@ export const FILE_SIGNATURES = {
|
||||
10: 0x42,
|
||||
11: 0x50
|
||||
},
|
||||
extractor: null
|
||||
extractor: extractWEBP
|
||||
},
|
||||
{
|
||||
name: "Camera Image File Format",
|
||||
@@ -3032,6 +3032,30 @@ export function extractPNG(bytes, offset) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* WEBP extractor.
|
||||
*
|
||||
* @param {Uint8Array} bytes
|
||||
* @param {number} offset
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
export function extractWEBP(bytes, offset) {
|
||||
const stream = new Stream(bytes.slice(offset));
|
||||
|
||||
// Move to file size offset.
|
||||
stream.moveForwardsBy(4);
|
||||
|
||||
// Read file size field.
|
||||
const fileSize = stream.readInt(4, "le");
|
||||
|
||||
// Move to end of file.
|
||||
// There is no need to minus 8 from the size as the size factors in the offset.
|
||||
stream.moveForwardsBy(fileSize);
|
||||
|
||||
return stream.carve();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BMP extractor.
|
||||
*
|
||||
|
||||
244
src/core/lib/LS47.mjs
Normal file
244
src/core/lib/LS47.mjs
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
const letters = "_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()";
|
||||
const tiles = [];
|
||||
|
||||
/**
|
||||
* Initialises the tiles with values and positions.
|
||||
*/
|
||||
export function initTiles() {
|
||||
for (let i = 0; i < 49; i++)
|
||||
tiles.push([letters.charAt(i), [Math.floor(i/7), i % 7]]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the key "down".
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {number} col
|
||||
* @param {number} n
|
||||
* @returns {string}
|
||||
*/
|
||||
function rotateDown(key, col, n) {
|
||||
const lines = [];
|
||||
for (let i = 0; i < 7; i++)
|
||||
lines.push(key.slice(i*7, (i + 1) * 7));
|
||||
const lefts = [];
|
||||
let mids = [];
|
||||
const rights = [];
|
||||
lines.forEach((element) => {
|
||||
lefts.push(element.slice(0, col));
|
||||
mids.push(element.charAt(col));
|
||||
rights.push(element.slice(col+1));
|
||||
});
|
||||
n = (7 - n % 7) % 7;
|
||||
mids = mids.slice(n).concat(mids.slice(0, n));
|
||||
let result = "";
|
||||
for (let i = 0; i < 7; i++)
|
||||
result += lefts[i] + mids[i] + rights[i];
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates the key "right".
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {number} row
|
||||
* @param {number} n
|
||||
* @returns {string}
|
||||
*/
|
||||
function rotateRight(key, row, n) {
|
||||
const mid = key.slice(row * 7, (row + 1) * 7);
|
||||
n = (7 - n % 7) % 7;
|
||||
return key.slice(0, 7 * row) + mid.slice(n) + mid.slice(0, n) + key.slice(7 * (row + 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the position of a letter in the tiles.
|
||||
*
|
||||
* @param {string} letter
|
||||
* @returns {string}
|
||||
*/
|
||||
function findIx(letter) {
|
||||
for (let i = 0; i < tiles.length; i++)
|
||||
if (tiles[i][0] === letter)
|
||||
return tiles[i][1];
|
||||
throw new OperationError("Letter " + letter + " is not included in LS47");
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives key from the input password.
|
||||
*
|
||||
* @param {string} password
|
||||
* @returns {string}
|
||||
*/
|
||||
export function deriveKey(password) {
|
||||
let i = 0;
|
||||
let k = letters;
|
||||
for (const c of password) {
|
||||
const [row, col] = findIx(c);
|
||||
k = rotateDown(rotateRight(k, i, col), i, row);
|
||||
i = (i + 1) % 7;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the key is a valid key.
|
||||
*
|
||||
* @param {string} key
|
||||
*/
|
||||
function checkKey(key) {
|
||||
if (key.length !== letters.length)
|
||||
throw new OperationError("Wrong key size");
|
||||
const counts = new Array();
|
||||
for (let i = 0; i < letters.length; i++)
|
||||
counts[letters.charAt(i)] = 0;
|
||||
for (const elem of letters) {
|
||||
if (letters.indexOf(elem) === -1)
|
||||
throw new OperationError("Letter " + elem + " not in LS47");
|
||||
counts[elem]++;
|
||||
if (counts[elem] > 1)
|
||||
throw new OperationError("Letter duplicated in the key");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the position of a letter in they key.
|
||||
*
|
||||
* @param {letter} key
|
||||
* @param {string} letter
|
||||
* @returns {object}
|
||||
*/
|
||||
function findPos (key, letter) {
|
||||
const index = key.indexOf(letter);
|
||||
if (index >= 0 && index < 49)
|
||||
return [Math.floor(index/7), index%7];
|
||||
throw new OperationError("Letter " + letter + " is not in the key");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the character at the position on the tiles.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {object} coord
|
||||
* @returns {string}
|
||||
*/
|
||||
function findAtPos(key, coord) {
|
||||
return key.charAt(coord[1] + (coord[0] * 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new position by adding two positions.
|
||||
*
|
||||
* @param {object} a
|
||||
* @param {object} b
|
||||
* @returns {object}
|
||||
*/
|
||||
function addPos(a, b) {
|
||||
return [(a[0] + b[0]) % 7, (a[1] + b[1]) % 7];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns new position by subtracting two positions.
|
||||
* Note: We have to manually do the remainder division, since JS does not
|
||||
* operate correctly on negative numbers (e.g. -3 % 4 = -3 when it should be 1).
|
||||
*
|
||||
* @param {object} a
|
||||
* @param {object} b
|
||||
* @returns {object}
|
||||
*/
|
||||
function subPos(a, b) {
|
||||
const asub = a[0] - b[0];
|
||||
const bsub = a[1] - b[1];
|
||||
return [asub - (Math.floor(asub/7) * 7), bsub - (Math.floor(bsub/7) * 7)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the plaintext string.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} plaintext
|
||||
* @returns {string}
|
||||
*/
|
||||
function encrypt(key, plaintext) {
|
||||
checkKey(key);
|
||||
let mp = [0, 0];
|
||||
let ciphertext = "";
|
||||
for (const p of plaintext) {
|
||||
const pp = findPos(key, p);
|
||||
const mix = findIx(findAtPos(key, mp));
|
||||
let cp = addPos(pp, mix);
|
||||
const c = findAtPos(key, cp);
|
||||
ciphertext += c;
|
||||
key = rotateRight(key, pp[0], 1);
|
||||
cp = findPos(key, c);
|
||||
key = rotateDown(key, cp[1], 1);
|
||||
mp = addPos(mp, findIx(c));
|
||||
}
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the ciphertext string.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} ciphertext
|
||||
* @returns {string}
|
||||
*/
|
||||
function decrypt(key, ciphertext) {
|
||||
checkKey(key);
|
||||
let mp = [0, 0];
|
||||
let plaintext = "";
|
||||
for (const c of ciphertext) {
|
||||
let cp = findPos(key, c);
|
||||
const mix = findIx(findAtPos(key, mp));
|
||||
const pp = subPos(cp, mix);
|
||||
const p = findAtPos(key, pp);
|
||||
plaintext += p;
|
||||
key = rotateRight(key, pp[0], 1);
|
||||
cp = findPos(key, c);
|
||||
key = rotateDown(key, cp[1], 1);
|
||||
mp = addPos(mp, findIx(c));
|
||||
}
|
||||
return plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds padding to the input.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} plaintext
|
||||
* @param {string} signature
|
||||
* @param {number} paddingSize
|
||||
* @returns {string}
|
||||
*/
|
||||
export function encryptPad(key, plaintext, signature, paddingSize) {
|
||||
initTiles();
|
||||
checkKey(key);
|
||||
let padding = "";
|
||||
for (let i = 0; i < paddingSize; i++) {
|
||||
padding += letters.charAt(Math.floor(Math.random() * letters.length));
|
||||
}
|
||||
return encrypt(key, padding+plaintext+"---"+signature);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes padding from the ouput.
|
||||
*
|
||||
* @param {string} key
|
||||
* @param {string} ciphertext
|
||||
* @param {number} paddingSize
|
||||
* @returns {string}
|
||||
*/
|
||||
export function decryptPad(key, ciphertext, paddingSize) {
|
||||
initTiles();
|
||||
checkKey(key);
|
||||
return decrypt(key, ciphertext).slice(paddingSize);
|
||||
}
|
||||
21
src/core/lib/LZString.mjs
Normal file
21
src/core/lib/LZString.mjs
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* lz-string exports.
|
||||
*
|
||||
* @author crespyl [peter@crespyl.net]
|
||||
* @copyright Peter Jacobs 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import LZString from "lz-string";
|
||||
|
||||
export const COMPRESSION_OUTPUT_FORMATS = ["default", "UTF16", "Base64"];
|
||||
export const COMPRESSION_FUNCTIONS = {
|
||||
"default": LZString.compress,
|
||||
"UTF16": LZString.compressToUTF16,
|
||||
"Base64": LZString.compressToBase64,
|
||||
};
|
||||
export const DECOMPRESSION_FUNCTIONS = {
|
||||
"default": LZString.decompress,
|
||||
"UTF16": LZString.decompressFromUTF16,
|
||||
"Base64": LZString.decompressFromBase64,
|
||||
};
|
||||
@@ -184,7 +184,7 @@ class Protobuf {
|
||||
bytes: String,
|
||||
longs: Number,
|
||||
enums: String,
|
||||
defualts: true
|
||||
defaults: true
|
||||
});
|
||||
const output = {};
|
||||
|
||||
|
||||
@@ -9,35 +9,25 @@
|
||||
import { toHex, fromHex } from "./Hex.mjs";
|
||||
|
||||
/**
|
||||
* Formats Distinguished Name (DN) strings.
|
||||
* Formats Distinguished Name (DN) objects to strings.
|
||||
*
|
||||
* @param {string} dnStr
|
||||
* @param {Object} dnObj
|
||||
* @param {number} indent
|
||||
* @returns {string}
|
||||
*/
|
||||
export function formatDnStr(dnStr, indent) {
|
||||
const fields = dnStr.substr(1).replace(/([^\\])\//g, "$1$1/").split(/[^\\]\//);
|
||||
let output = "",
|
||||
maxKeyLen = 0,
|
||||
key,
|
||||
value,
|
||||
i,
|
||||
str;
|
||||
export function formatDnObj(dnObj, indent) {
|
||||
let output = "";
|
||||
|
||||
for (i = 0; i < fields.length; i++) {
|
||||
if (!fields[i].length) continue;
|
||||
const maxKeyLen = dnObj.array.reduce((max, item) => {
|
||||
return item[0].type.length > max ? item[0].type.length : max;
|
||||
}, 0);
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
for (let i = 0; i < dnObj.array.length; i++) {
|
||||
if (!dnObj.array[i].length) continue;
|
||||
|
||||
maxKeyLen = key.length > maxKeyLen ? key.length : maxKeyLen;
|
||||
}
|
||||
|
||||
for (i = 0; i < fields.length; i++) {
|
||||
if (!fields[i].length) continue;
|
||||
|
||||
key = fields[i].split("=")[0];
|
||||
value = fields[i].split("=")[1];
|
||||
str = key.padEnd(maxKeyLen, " ") + " = " + value + "\n";
|
||||
const key = dnObj.array[i][0].type;
|
||||
const value = dnObj.array[i][0].value;
|
||||
const str = `${key.padEnd(maxKeyLen, " ")} = ${value}\n`;
|
||||
|
||||
output += str.padStart(indent + str.length, " ");
|
||||
}
|
||||
|
||||
@@ -48,12 +48,14 @@ export default class Stream {
|
||||
* Interpret the following bytes as a string, stopping at the next null byte or
|
||||
* the supplied limit.
|
||||
*
|
||||
* @param {number} numBytes
|
||||
* @param {number} [numBytes=-1]
|
||||
* @returns {string}
|
||||
*/
|
||||
readString(numBytes) {
|
||||
readString(numBytes=-1) {
|
||||
if (this.position > this.length) return undefined;
|
||||
|
||||
if (numBytes === -1) numBytes = this.length - this.position;
|
||||
|
||||
let result = "";
|
||||
for (let i = this.position; i < this.position + numBytes; i++) {
|
||||
const currentByte = this.bytes[i];
|
||||
|
||||
61
src/core/operations/CaesarBoxCipher.mjs
Normal file
61
src/core/operations/CaesarBoxCipher.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* Caesar Box Cipher operation
|
||||
*/
|
||||
class CaesarBoxCipher extends Operation {
|
||||
|
||||
/**
|
||||
* CaesarBoxCipher constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Caesar Box Cipher";
|
||||
this.module = "Ciphers";
|
||||
this.description = "Caesar Box is a transposition cipher used in the Roman Empire, in which letters of the message are written in rows in a square (or a rectangle) and then, read by column.";
|
||||
this.infoURL = "https://www.dcode.fr/caesar-box-cipher";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Box Height",
|
||||
type: "number",
|
||||
value: 1
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const tableHeight = args[0];
|
||||
const tableWidth = Math.ceil(input.length / tableHeight);
|
||||
while (input.indexOf(" ") !== -1)
|
||||
input = input.replace(" ", "");
|
||||
for (let i = 0; i < (tableHeight * tableWidth) - input.length; i++) {
|
||||
input += "\x00";
|
||||
}
|
||||
let result = "";
|
||||
for (let i = 0; i < tableHeight; i++) {
|
||||
for (let j = i; j < input.length; j += tableHeight) {
|
||||
if (input.charAt(j) !== "\x00") {
|
||||
result += input.charAt(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CaesarBoxCipher;
|
||||
63
src/core/operations/CetaceanCipherDecode.mjs
Normal file
63
src/core/operations/CetaceanCipherDecode.mjs
Normal 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;
|
||||
51
src/core/operations/CetaceanCipherEncode.mjs
Normal file
51
src/core/operations/CetaceanCipherEncode.mjs
Normal 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;
|
||||
@@ -64,6 +64,7 @@ class ConditionalJump extends Operation {
|
||||
jmpIndex = getLabelIndex(label, state);
|
||||
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
state.numJumps = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -73,6 +74,8 @@ class ConditionalJump extends Operation {
|
||||
if (!invert && strMatch || invert && !strMatch) {
|
||||
state.progress = jmpIndex;
|
||||
state.numJumps++;
|
||||
} else {
|
||||
state.numJumps = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
913
src/core/operations/ELFInfo.mjs
Normal file
913
src/core/operations/ELFInfo.mjs
Normal file
@@ -0,0 +1,913 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Stream from "../lib/Stream.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
/**
|
||||
* ELF Info operation
|
||||
*/
|
||||
class ELFInfo extends Operation {
|
||||
|
||||
/**
|
||||
* ELFInfo constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "ELF Info";
|
||||
this.module = "Default";
|
||||
this.description = "Implements readelf-like functionality. This operation will extract the ELF Header, Program Headers, Section Headers and Symbol Table for an ELF file.";
|
||||
this.infoURL = "https://www.wikipedia.org/wiki/Executable_and_Linkable_Format";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
let phoff = 0;
|
||||
let phEntries = 0;
|
||||
let shoff = 0;
|
||||
let shEntries = 0;
|
||||
let shentSize = 0;
|
||||
let entry = 0;
|
||||
let format = 0;
|
||||
let endianness = "";
|
||||
let shstrtab = 0;
|
||||
|
||||
let namesOffset = 0;
|
||||
|
||||
let symtabOffset = 0;
|
||||
let symtabSize = 0;
|
||||
let symtabEntSize = 0;
|
||||
|
||||
let strtabOffset = 0;
|
||||
const align = 30;
|
||||
|
||||
/**
|
||||
* This function reads characters until it hits a null terminator.
|
||||
*
|
||||
* @param {stream} stream
|
||||
* @param {integer} namesOffset
|
||||
* @param {integer} nameOffset
|
||||
* @returns {string}
|
||||
*/
|
||||
function readString(stream, namesOffset, nameOffset) {
|
||||
const preMove = stream.position;
|
||||
stream.moveTo(namesOffset + nameOffset);
|
||||
|
||||
const nameResult = stream.readString();
|
||||
stream.moveTo(preMove);
|
||||
return nameResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses and extracts relevant information from the ELF Header.
|
||||
*
|
||||
* @param {stream} stream
|
||||
* @returns {string}
|
||||
*/
|
||||
function elfHeader(stream) {
|
||||
/**
|
||||
* The ELF Header is comprised of the following structures depending on the binary's format.
|
||||
*
|
||||
* e_ident - The Magic Number 0x7F,0x45,0x4c,0x46
|
||||
* - Byte set to 1 or 2 to signify 32-bit or 64-bit format, respectively.
|
||||
* - Byte set to 1 or 2 to signify little of big endianness, respectively.
|
||||
* - Byte set to 1 for the version of ELF.
|
||||
* - Byte identifying the target OS ABI.
|
||||
* - Byte further identifying the OS ABI Version.
|
||||
* - 7 Padding Bytes.
|
||||
* e_type - 2 bytes identifying the object file type.
|
||||
* e_machine - 2 bytes identifying the instruction set architecture.
|
||||
* e_version - Byte set to 1 for the version of ELF.
|
||||
*
|
||||
* 32-bit:
|
||||
* e_entry - 4 Bytes specifying the entry point.
|
||||
* e_phoff - 4 Bytes specifying the offset of the Program Header Table.
|
||||
* e_shoff - 4 Bytes specifying the offset of the Section Header Table.
|
||||
*
|
||||
* 64-bit:
|
||||
* e_entry - 8 Bytes specifying the entry point.
|
||||
* e_phoff - 8 Bytes specifying the offset of the Program Header Table.
|
||||
* e_shoff - 8 Bytes specifying the offset of the Section Header Table.
|
||||
*
|
||||
* e_flags - 4 Bytes specifying processor specific flags.
|
||||
* e_ehsize - 2 Bytes specifying the size of the ELF Header.
|
||||
* e_phentsize - 2 Bytes specifying the size of a Program Header Table Entry.
|
||||
* e_phnum - 2 Bytes specifying the number of entries in the Program Header Table.
|
||||
* e_shentsize - 2 Bytes specifying the size of a Section Header Table Entry.
|
||||
* e_shnum - 2 Bytes specifying the number of entries in the Section Header Table.
|
||||
* e_shstrndx - 2 Bytes specifying the index of the section containing the section names in the Section Header Table.
|
||||
*/
|
||||
const ehResult = [];
|
||||
|
||||
const magic = stream.getBytes(4);
|
||||
if (magic.join("") !== [0x7f, 0x45, 0x4c, 0x46].join(""))
|
||||
throw new OperationError("Invalid ELF");
|
||||
|
||||
ehResult.push("Magic:".padEnd(align) + `${Utils.byteArrayToChars(magic)}`);
|
||||
|
||||
format = stream.readInt(1);
|
||||
ehResult.push("Format:".padEnd(align) + `${format === 1 ? "32-bit" : "64-bit"}`);
|
||||
|
||||
endianness = stream.readInt(1) === 1 ? "le" : "be";
|
||||
ehResult.push("Endianness:".padEnd(align) + `${endianness === "le" ? "Little" : "Big"}`);
|
||||
|
||||
ehResult.push("Version:".padEnd(align) + `${stream.readInt(1).toString()}`);
|
||||
|
||||
let ABI = "";
|
||||
switch (stream.readInt(1)) {
|
||||
case 0x00:
|
||||
ABI = "System V";
|
||||
break;
|
||||
case 0x01:
|
||||
ABI = "HP-UX";
|
||||
break;
|
||||
case 0x02:
|
||||
ABI = "NetBSD";
|
||||
break;
|
||||
case 0x03:
|
||||
ABI = "Linux";
|
||||
break;
|
||||
case 0x04:
|
||||
ABI = "GNU Hurd";
|
||||
break;
|
||||
case 0x06:
|
||||
ABI = "Solaris";
|
||||
break;
|
||||
case 0x07:
|
||||
ABI = "AIX";
|
||||
break;
|
||||
case 0x08:
|
||||
ABI = "IRIX";
|
||||
break;
|
||||
case 0x09:
|
||||
ABI = "FreeBSD";
|
||||
break;
|
||||
case 0x0A:
|
||||
ABI = "Tru64";
|
||||
break;
|
||||
case 0x0B:
|
||||
ABI = "Novell Modesto";
|
||||
break;
|
||||
case 0x0C:
|
||||
ABI = "OpenBSD";
|
||||
break;
|
||||
case 0x0D:
|
||||
ABI = "OpenVMS";
|
||||
break;
|
||||
case 0x0E:
|
||||
ABI = "NonStop Kernel";
|
||||
break;
|
||||
case 0x0F:
|
||||
ABI = "AROS";
|
||||
break;
|
||||
case 0x10:
|
||||
ABI = "Fenix OS";
|
||||
break;
|
||||
case 0x11:
|
||||
ABI = "CloudABI";
|
||||
break;
|
||||
case 0x12:
|
||||
ABI = "Stratus Technologies OpenVOS";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ehResult.push("ABI:".padEnd(align) + ABI);
|
||||
|
||||
// Linux Kernel does not use ABI Version.
|
||||
const abiVersion = stream.readInt(1).toString();
|
||||
if (ABI !== "Linux")
|
||||
ehResult.push("ABI Version:".padEnd(align) + abiVersion);
|
||||
|
||||
stream.moveForwardsBy(7);
|
||||
|
||||
let eType = "";
|
||||
switch (stream.readInt(2, endianness)) {
|
||||
case 0x0000:
|
||||
eType = "Unknown";
|
||||
break;
|
||||
case 0x0001:
|
||||
eType = "Relocatable File";
|
||||
break;
|
||||
case 0x0002:
|
||||
eType = "Executable File";
|
||||
break;
|
||||
case 0x0003:
|
||||
eType = "Shared Object";
|
||||
break;
|
||||
case 0x0004:
|
||||
eType = "Core File";
|
||||
break;
|
||||
case 0xFE00:
|
||||
eType = "LOOS";
|
||||
break;
|
||||
case 0xFEFF:
|
||||
eType = "HIOS";
|
||||
break;
|
||||
case 0xFF00:
|
||||
eType = "LOPROC";
|
||||
break;
|
||||
case 0xFFFF:
|
||||
eType = "HIPROC";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ehResult.push("Type:".padEnd(align) + eType);
|
||||
|
||||
let ISA = "";
|
||||
switch (stream.readInt(2, endianness)) {
|
||||
case 0x0000:
|
||||
ISA = "No specific instruction set";
|
||||
break;
|
||||
case 0x0001:
|
||||
ISA = "AT&T WE 32100";
|
||||
break;
|
||||
case 0x0002:
|
||||
ISA = "SPARC";
|
||||
break;
|
||||
case 0x0003:
|
||||
ISA = "x86";
|
||||
break;
|
||||
case 0x0004:
|
||||
ISA = "Motorola 68000 (M68k)";
|
||||
break;
|
||||
case 0x0005:
|
||||
ISA = "Motorola 88000 (M88k)";
|
||||
break;
|
||||
case 0x0006:
|
||||
ISA = "Intel MCU";
|
||||
break;
|
||||
case 0x0007:
|
||||
ISA = "Intel 80860";
|
||||
break;
|
||||
case 0x0008:
|
||||
ISA = "MIPS";
|
||||
break;
|
||||
case 0x0009:
|
||||
ISA = "IBM System/370";
|
||||
break;
|
||||
case 0x000A:
|
||||
ISA = "MIPS RS3000 Little-endian";
|
||||
break;
|
||||
case 0x000B:
|
||||
case 0x000C:
|
||||
case 0x000D:
|
||||
case 0x000E:
|
||||
case 0x0018:
|
||||
case 0x0019:
|
||||
case 0x001A:
|
||||
case 0x001B:
|
||||
case 0x001C:
|
||||
case 0x001D:
|
||||
case 0x001E:
|
||||
case 0x001F:
|
||||
case 0x0020:
|
||||
case 0x0021:
|
||||
case 0x0022:
|
||||
case 0x0023:
|
||||
ISA = "Reserved for future use";
|
||||
break;
|
||||
case 0x000F:
|
||||
ISA = "Hewlett-Packard PA-RISC";
|
||||
break;
|
||||
case 0x0011:
|
||||
ISA = "Fujitsu VPP500";
|
||||
break;
|
||||
case 0x0012:
|
||||
ISA = "Enhanced instruction set SPARC";
|
||||
break;
|
||||
case 0x0013:
|
||||
ISA = "Intel 80960";
|
||||
break;
|
||||
case 0x0014:
|
||||
ISA = "PowerPC";
|
||||
break;
|
||||
case 0x0015:
|
||||
ISA = "PowerPC (64-bit)";
|
||||
break;
|
||||
case 0x0016:
|
||||
ISA = "S390, including S390";
|
||||
break;
|
||||
case 0x0017:
|
||||
ISA = "IBM SPU/SPC";
|
||||
break;
|
||||
case 0x0024:
|
||||
ISA = "NEC V800";
|
||||
break;
|
||||
case 0x0025:
|
||||
ISA = "Fujitsu FR20";
|
||||
break;
|
||||
case 0x0026:
|
||||
ISA = "TRW RH-32";
|
||||
break;
|
||||
case 0x0027:
|
||||
ISA = "Motorola RCE";
|
||||
break;
|
||||
case 0x0028:
|
||||
ISA = "ARM (up to ARMv7/Aarch32)";
|
||||
break;
|
||||
case 0x0029:
|
||||
ISA = "Digital Alpha";
|
||||
break;
|
||||
case 0x002A:
|
||||
ISA = "SuperH";
|
||||
break;
|
||||
case 0x002B:
|
||||
ISA = "SPARC Version 9";
|
||||
break;
|
||||
case 0x002C:
|
||||
ISA = "Siemens TriCore embedded processor";
|
||||
break;
|
||||
case 0x002D:
|
||||
ISA = "Argonaut RISC Core";
|
||||
break;
|
||||
case 0x002E:
|
||||
ISA = "Hitachi H8/300";
|
||||
break;
|
||||
case 0x002F:
|
||||
ISA = "Hitachi H8/300H";
|
||||
break;
|
||||
case 0x0030:
|
||||
ISA = "Hitachi H8S";
|
||||
break;
|
||||
case 0x0031:
|
||||
ISA = "Hitachi H8/500";
|
||||
break;
|
||||
case 0x0032:
|
||||
ISA = "IA-64";
|
||||
break;
|
||||
case 0x0033:
|
||||
ISA = "Standford MIPS-X";
|
||||
break;
|
||||
case 0x0034:
|
||||
ISA = "Motorola ColdFire";
|
||||
break;
|
||||
case 0x0035:
|
||||
ISA = "Motorola M68HC12";
|
||||
break;
|
||||
case 0x0036:
|
||||
ISA = "Fujitsu MMA Multimedia Accelerator";
|
||||
break;
|
||||
case 0x0037:
|
||||
ISA = "Siemens PCP";
|
||||
break;
|
||||
case 0x0038:
|
||||
ISA = "Sony nCPU embedded RISC processor";
|
||||
break;
|
||||
case 0x0039:
|
||||
ISA = "Denso NDR1 microprocessor";
|
||||
break;
|
||||
case 0x003A:
|
||||
ISA = "Motorola Star*Core processor";
|
||||
break;
|
||||
case 0x003B:
|
||||
ISA = "Toyota ME16 processor";
|
||||
break;
|
||||
case 0x003C:
|
||||
ISA = "STMicroelectronics ST100 processor";
|
||||
break;
|
||||
case 0x003D:
|
||||
ISA = "Advanced Logic Corp. TinyJ embedded processor family";
|
||||
break;
|
||||
case 0x003E:
|
||||
ISA = "AMD x86-64";
|
||||
break;
|
||||
case 0x003F:
|
||||
ISA = "Sony DSP Processor";
|
||||
break;
|
||||
case 0x0040:
|
||||
ISA = "Digital Equipment Corp. PDP-10";
|
||||
break;
|
||||
case 0x0041:
|
||||
ISA = "Digital Equipment Corp. PDP-11";
|
||||
break;
|
||||
case 0x0042:
|
||||
ISA = "Siemens FX66 microcontroller";
|
||||
break;
|
||||
case 0x0043:
|
||||
ISA = "STMicroelectronics ST9+ 8/16 bit microcontroller";
|
||||
break;
|
||||
case 0x0044:
|
||||
ISA = "STMicroelectronics ST7 8-bit microcontroller";
|
||||
break;
|
||||
case 0x0045:
|
||||
ISA = "Motorola MC68HC16 Microcontroller";
|
||||
break;
|
||||
case 0x0046:
|
||||
ISA = "Motorola MC68HC11 Microcontroller";
|
||||
break;
|
||||
case 0x0047:
|
||||
ISA = "Motorola MC68HC08 Microcontroller";
|
||||
break;
|
||||
case 0x0048:
|
||||
ISA = "Motorola MC68HC05 Microcontroller";
|
||||
break;
|
||||
case 0x0049:
|
||||
ISA = "Silicon Graphics SVx";
|
||||
break;
|
||||
case 0x004A:
|
||||
ISA = "STMicroelectronics ST19 8-bit microcontroller";
|
||||
break;
|
||||
case 0x004B:
|
||||
ISA = "Digital VAX";
|
||||
break;
|
||||
case 0x004C:
|
||||
ISA = "Axis Communications 32-bit embedded processor";
|
||||
break;
|
||||
case 0x004D:
|
||||
ISA = "Infineon Technologies 32-bit embedded processor";
|
||||
break;
|
||||
case 0x004E:
|
||||
ISA = "Element 14 64-bit DSP Processor";
|
||||
break;
|
||||
case 0x004F:
|
||||
ISA = "LSI Logic 16-bit DSP Processor";
|
||||
break;
|
||||
case 0x0050:
|
||||
ISA = "Donald Knuth's educational 64-bit processor";
|
||||
break;
|
||||
case 0x0051:
|
||||
ISA = "Harvard University machine-independent object files";
|
||||
break;
|
||||
case 0x0052:
|
||||
ISA = "SiTera Prism";
|
||||
break;
|
||||
case 0x0053:
|
||||
ISA = "Atmel AVR 8-bit microcontroller";
|
||||
break;
|
||||
case 0x0054:
|
||||
ISA = "Fujitsu FR30";
|
||||
break;
|
||||
case 0x0055:
|
||||
ISA = "Mitsubishi D10V";
|
||||
break;
|
||||
case 0x0056:
|
||||
ISA = "Mitsubishi D30V";
|
||||
break;
|
||||
case 0x0057:
|
||||
ISA = "NEC v850";
|
||||
break;
|
||||
case 0x0058:
|
||||
ISA = "Mitsubishi M32R";
|
||||
break;
|
||||
case 0x0059:
|
||||
ISA = "Matsushita MN10300";
|
||||
break;
|
||||
case 0x005A:
|
||||
ISA = "Matsushita MN10200";
|
||||
break;
|
||||
case 0x005B:
|
||||
ISA = "picoJava";
|
||||
break;
|
||||
case 0x005C:
|
||||
ISA = "OpenRISC 32-bit embedded processor";
|
||||
break;
|
||||
case 0x005D:
|
||||
ISA = "ARC Cores Tangent-A5";
|
||||
break;
|
||||
case 0x005E:
|
||||
ISA = "Tensilica Xtensa Architecture";
|
||||
break;
|
||||
case 0x005F:
|
||||
ISA = "Alphamosaic VideoCore processor";
|
||||
break;
|
||||
case 0x0060:
|
||||
ISA = "Thompson Multimedia General Purpose Processor";
|
||||
break;
|
||||
case 0x0061:
|
||||
ISA = "National Semiconductor 32000 series";
|
||||
break;
|
||||
case 0x0062:
|
||||
ISA = "Tenor Network TPC processor";
|
||||
break;
|
||||
case 0x0063:
|
||||
ISA = "Trebia SNP 1000 processor";
|
||||
break;
|
||||
case 0x0064:
|
||||
ISA = "STMicroelectronics (www.st.com) ST200 microcontroller";
|
||||
break;
|
||||
case 0x008C:
|
||||
ISA = "TMS320C6000 Family";
|
||||
break;
|
||||
case 0x00AF:
|
||||
ISA = "MCST Elbrus e2k";
|
||||
break;
|
||||
case 0x00B7:
|
||||
ISA = "ARM 64-bits (ARMv8/Aarch64)";
|
||||
break;
|
||||
case 0x00F3:
|
||||
ISA = "RISC-V";
|
||||
break;
|
||||
case 0x00F7:
|
||||
ISA = "Berkeley Packet Filter";
|
||||
break;
|
||||
case 0x0101:
|
||||
ISA = "WDC 65C816";
|
||||
break;
|
||||
default:
|
||||
ISA = "Unimplemented";
|
||||
break;
|
||||
}
|
||||
ehResult.push("Instruction Set Architecture:".padEnd(align) + ISA);
|
||||
|
||||
ehResult.push("ELF Version:".padEnd(align) + `${stream.readInt(4, endianness)}`);
|
||||
|
||||
const readSize = format === 1 ? 4 : 8;
|
||||
entry = stream.readInt(readSize, endianness);
|
||||
phoff = stream.readInt(readSize, endianness);
|
||||
shoff = stream.readInt(readSize, endianness);
|
||||
ehResult.push("Entry Point:".padEnd(align) + `0x${Utils.hex(entry)}`);
|
||||
ehResult.push("Entry PHOFF:".padEnd(align) + `0x${Utils.hex(phoff)}`);
|
||||
ehResult.push("Entry SHOFF:".padEnd(align) + `0x${Utils.hex(shoff)}`);
|
||||
|
||||
const flags = stream.readInt(4, endianness);
|
||||
ehResult.push("Flags:".padEnd(align) + `${Utils.bin(flags)}`);
|
||||
|
||||
ehResult.push("ELF Header Size:".padEnd(align) + `${stream.readInt(2, endianness)} bytes`);
|
||||
ehResult.push("Program Header Size:".padEnd(align) + `${stream.readInt(2, endianness)} bytes`);
|
||||
phEntries = stream.readInt(2, endianness);
|
||||
ehResult.push("Program Header Entries:".padEnd(align) + phEntries);
|
||||
shentSize = stream.readInt(2, endianness);
|
||||
ehResult.push("Section Header Size:".padEnd(align) + shentSize + " bytes");
|
||||
shEntries = stream.readInt(2, endianness);
|
||||
ehResult.push("Section Header Entries:".padEnd(align) + shEntries);
|
||||
shstrtab = stream.readInt(2, endianness);
|
||||
ehResult.push("Section Header Names:".padEnd(align) + shstrtab);
|
||||
|
||||
return ehResult.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses and extracts relevant information from a Program Header.
|
||||
*
|
||||
* @param {stream} stream
|
||||
* @returns {string}
|
||||
*/
|
||||
function programHeader(stream) {
|
||||
/**
|
||||
* A Program Header is comprised of the following structures depending on the binary's format.
|
||||
*
|
||||
* p_type - 4 Bytes identifying the type of the segment.
|
||||
*
|
||||
* 32-bit:
|
||||
* p_offset - 4 Bytes specifying the offset of the segment.
|
||||
* p_vaddr - 4 Bytes specifying the virtual address of the segment in memory.
|
||||
* p_paddr - 4 Bytes specifying the physical address of the segment in memory.
|
||||
* p_filesz - 4 Bytes specifying the size in bytes of the segment in the file image.
|
||||
* p_memsz - 4 Bytes specifying the size in bytes of the segment in memory.
|
||||
* p_flags - 4 Bytes identifying the segment dependent flags.
|
||||
* p_align - 4 Bytes set to 0 or 1 for alignment or no alignment, respectively.
|
||||
*
|
||||
* 64-bit:
|
||||
* p_flags - 4 Bytes identifying segment dependent flags.
|
||||
* p_offset - 8 Bytes specifying the offset of the segment.
|
||||
* p_vaddr - 8 Bytes specifying the virtual address of the segment in memory.
|
||||
* p_paddr - 8 Bytes specifying the physical address of the segment in memory.
|
||||
* p_filesz - 8 Bytes specifying the size in bytes of the segment in the file image.
|
||||
* p_memsz - 8 Bytes specifying the size in bytes of the segment in memory.
|
||||
* p_align - 8 Bytes set to 0 or 1 for alignment or no alignment, respectively.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This function decodes the flags bitmask for the Program Header.
|
||||
*
|
||||
* @param {integer} flags
|
||||
* @returns {string}
|
||||
*/
|
||||
function readFlags(flags) {
|
||||
const result = [];
|
||||
if (flags & 0x1)
|
||||
result.push("Execute");
|
||||
if (flags & 0x2)
|
||||
result.push("Write");
|
||||
if (flags & 0x4)
|
||||
result.push("Read");
|
||||
if (flags & 0xf0000000)
|
||||
result.push("Unspecified");
|
||||
return result.join(",");
|
||||
}
|
||||
|
||||
const phResult = [];
|
||||
|
||||
let pType = "";
|
||||
const programHeaderType = stream.readInt(4, endianness);
|
||||
switch (true) {
|
||||
case (programHeaderType === 0x00000000):
|
||||
pType = "Unused";
|
||||
break;
|
||||
case (programHeaderType === 0x00000001):
|
||||
pType = "Loadable Segment";
|
||||
break;
|
||||
case (programHeaderType === 0x00000002):
|
||||
pType = "Dynamic linking information";
|
||||
break;
|
||||
case (programHeaderType === 0x00000003):
|
||||
pType = "Interpreter Information";
|
||||
break;
|
||||
case (programHeaderType === 0x00000004):
|
||||
pType = "Auxiliary Information";
|
||||
break;
|
||||
case (programHeaderType === 0x00000005):
|
||||
pType = "Reserved";
|
||||
break;
|
||||
case (programHeaderType === 0x00000006):
|
||||
pType = "Program Header Table";
|
||||
break;
|
||||
case (programHeaderType === 0x00000007):
|
||||
pType = "Thread-Local Storage Template";
|
||||
break;
|
||||
case (programHeaderType >= 0x60000000 && programHeaderType <= 0x6FFFFFFF):
|
||||
pType = "Reserved Inclusive Range. OS Specific";
|
||||
break;
|
||||
case (programHeaderType >= 0x70000000 && programHeaderType <= 0x7FFFFFFF):
|
||||
pType = "Reserved Inclusive Range. Processor Specific";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
phResult.push("Program Header Type:".padEnd(align) + pType);
|
||||
|
||||
if (format === 2)
|
||||
phResult.push("Flags:".padEnd(align) + readFlags(stream.readInt(4, endianness)));
|
||||
|
||||
const readSize = format === 1? 4 : 8;
|
||||
phResult.push("Offset Of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
|
||||
phResult.push("Virtual Address of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
|
||||
phResult.push("Physical Address of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)}`);
|
||||
phResult.push("Size of Segment:".padEnd(align) + `${stream.readInt(readSize, endianness)} bytes`);
|
||||
phResult.push("Size of Segment in Memory:".padEnd(align) + `${stream.readInt(readSize, endianness)} bytes`);
|
||||
|
||||
if (format === 1)
|
||||
phResult.push("Flags:".padEnd(align) + readFlags(stream.readInt(4, endianness)));
|
||||
|
||||
stream.moveForwardsBy(readSize);
|
||||
|
||||
return phResult.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses and extracts relevant information from a Section Header.
|
||||
*
|
||||
* @param {stream} stream
|
||||
* @returns {string}
|
||||
*/
|
||||
function sectionHeader(stream) {
|
||||
/**
|
||||
* A Section Header is comprised of the following structures depending on the binary's format.
|
||||
*
|
||||
* sh_name - 4 Bytes identifying the offset into the .shstrtab for the name of this section.
|
||||
* sh_type - 4 Bytes identifying the type of this header.
|
||||
*
|
||||
* 32-bit:
|
||||
* sh_flags - 4 Bytes identifying section specific flags.
|
||||
* sh_addr - 4 Bytes identifying the virtual address of the section in memory.
|
||||
* sh_offset - 4 Bytes identifying the offset of the section in the file.
|
||||
* sh_size - 4 Bytes specifying the size in bytes of the section in the file image.
|
||||
* sh_link - 4 Bytes identifying the index of an associated section.
|
||||
* sh_info - 4 Bytes specifying extra information about the section.
|
||||
* sh_addralign - 4 Bytes containing the alignment for the section.
|
||||
* sh_entsize - 4 Bytes specifying the size, in bytes, of each entry in the section.
|
||||
*
|
||||
* 64-bit:
|
||||
* sh_flags - 8 Bytes identifying section specific flags.
|
||||
* sh_addr - 8 Bytes identifying the virtual address of the section in memory.
|
||||
* sh_offset - 8 Bytes identifying the offset of the section in the file.
|
||||
* sh_size - 8 Bytes specifying the size in bytes of the section in the file image.
|
||||
* sh_link - 4 Bytes identifying the index of an associated section.
|
||||
* sh_info - 4 Bytes specifying extra information about the section.
|
||||
* sh_addralign - 8 Bytes containing the alignment for the section.
|
||||
* sh_entsize - 8 Bytes specifying the size, in bytes, of each entry in the section.
|
||||
*/
|
||||
const shResult = [];
|
||||
|
||||
const nameOffset = stream.readInt(4, endianness);
|
||||
let type = "";
|
||||
const shType = stream.readInt(4, endianness);
|
||||
switch (true) {
|
||||
case (shType === 0x00000001):
|
||||
type = "Program Data";
|
||||
break;
|
||||
case (shType === 0x00000002):
|
||||
type = "Symbol Table";
|
||||
break;
|
||||
case (shType === 0x00000003):
|
||||
type = "String Table";
|
||||
break;
|
||||
case (shType === 0x00000004):
|
||||
type = "Relocation Entries with Addens";
|
||||
break;
|
||||
case (shType === 0x00000005):
|
||||
type = "Symbol Hash Table";
|
||||
break;
|
||||
case (shType === 0x00000006):
|
||||
type = "Dynamic Linking Information";
|
||||
break;
|
||||
case (shType === 0x00000007):
|
||||
type = "Notes";
|
||||
break;
|
||||
case (shType === 0x00000008):
|
||||
type = "Program Space with No Data";
|
||||
break;
|
||||
case (shType === 0x00000009):
|
||||
type = "Relocation Entries with no Addens";
|
||||
break;
|
||||
case (shType === 0x0000000A):
|
||||
type = "Reserved";
|
||||
break;
|
||||
case (shType === 0x0000000B):
|
||||
type = "Dynamic Linker Symbol Table";
|
||||
break;
|
||||
case (shType === 0x0000000E):
|
||||
type = "Array of Constructors";
|
||||
break;
|
||||
case (shType === 0x0000000F):
|
||||
type = "Array of Destructors";
|
||||
break;
|
||||
case (shType === 0x00000010):
|
||||
type = "Array of pre-constructors";
|
||||
break;
|
||||
case (shType === 0x00000011):
|
||||
type = "Section group";
|
||||
break;
|
||||
case (shType === 0x00000012):
|
||||
type = "Extended section indices";
|
||||
break;
|
||||
case (shType === 0x00000013):
|
||||
type = "Number of defined types";
|
||||
break;
|
||||
case (shType >= 0x60000000 && shType <= 0x6fffffff):
|
||||
type = "OS-specific";
|
||||
break;
|
||||
case (shType >= 0x70000000 && shType <= 0x7fffffff):
|
||||
type = "Processor-specific";
|
||||
break;
|
||||
case (shType >= 0x80000000 && shType <= 0x8fffffff):
|
||||
type = "Application-specific";
|
||||
break;
|
||||
default:
|
||||
type = "Unused";
|
||||
break;
|
||||
}
|
||||
|
||||
shResult.push("Type:".padEnd(align) + type);
|
||||
|
||||
let nameResult = "";
|
||||
if (type !== "Unused") {
|
||||
nameResult = readString(stream, namesOffset, nameOffset);
|
||||
shResult.push("Section Name: ".padEnd(align) + nameResult);
|
||||
}
|
||||
|
||||
const readSize = (format === 1) ? 4 : 8;
|
||||
|
||||
const flags = stream.readInt(readSize, endianness);
|
||||
const shFlags = [];
|
||||
const bitMasks = [
|
||||
[0x00000001, "Writable"],
|
||||
[0x00000002, "Alloc"],
|
||||
[0x00000004, "Executable"],
|
||||
[0x00000010, "Merge"],
|
||||
[0x00000020, "Strings"],
|
||||
[0x00000040, "SHT Info Link"],
|
||||
[0x00000080, "Link Order"],
|
||||
[0x00000100, "OS Specific Handling"],
|
||||
[0x00000200, "Group"],
|
||||
[0x00000400, "Thread Local Data"],
|
||||
[0x0FF00000, "OS-Specific"],
|
||||
[0xF0000000, "Processor Specific"],
|
||||
[0x04000000, "Special Ordering (Solaris)"],
|
||||
[0x08000000, "Excluded (Solaris)"]
|
||||
];
|
||||
bitMasks.forEach(elem => {
|
||||
if (flags & elem[0])
|
||||
shFlags.push(elem[1]);
|
||||
});
|
||||
shResult.push("Flags:".padEnd(align) + shFlags);
|
||||
|
||||
const vaddr = stream.readInt(readSize, endianness);
|
||||
shResult.push("Section Vaddr in memory:".padEnd(align) + vaddr);
|
||||
|
||||
const shoffset = stream.readInt(readSize, endianness);
|
||||
shResult.push("Offset of the section:".padEnd(align) + shoffset);
|
||||
|
||||
const secSize = stream.readInt(readSize, endianness);
|
||||
shResult.push("Section Size:".padEnd(align) + secSize);
|
||||
|
||||
const associatedSection = stream.readInt(4, endianness);
|
||||
shResult.push("Associated Section:".padEnd(align) + associatedSection);
|
||||
|
||||
const extraInfo = stream.readInt(4, endianness);
|
||||
shResult.push("Section Extra Information:".padEnd(align) + extraInfo);
|
||||
|
||||
// Jump over alignment field.
|
||||
stream.moveForwardsBy(readSize);
|
||||
const entSize = stream.readInt(readSize, endianness);
|
||||
switch (nameResult) {
|
||||
case ".strtab":
|
||||
strtabOffset = shoffset;
|
||||
break;
|
||||
case ".symtab":
|
||||
symtabOffset = shoffset;
|
||||
symtabSize = secSize;
|
||||
symtabEntSize = entSize;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return shResult.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the offset of the Section Header Names Section.
|
||||
*
|
||||
* @param {stream} stream
|
||||
*/
|
||||
function getNamesOffset(stream) {
|
||||
const preMove = stream.position;
|
||||
stream.moveTo(shoff + (shentSize * shstrtab));
|
||||
if (format === 1) {
|
||||
stream.moveForwardsBy(0x10);
|
||||
namesOffset = stream.readInt(4, endianness);
|
||||
} else {
|
||||
stream.moveForwardsBy(0x18);
|
||||
namesOffset = stream.readInt(8, endianness);
|
||||
}
|
||||
stream.position = preMove;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns a symbol's name from the string table.
|
||||
*
|
||||
* @param {stream} stream
|
||||
* @returns {string}
|
||||
*/
|
||||
function getSymbols(stream) {
|
||||
/**
|
||||
* The Symbol Table is comprised of Symbol Table Entries whose structure depends on the binary's format.
|
||||
*
|
||||
* 32-bit:
|
||||
* st_name - 4 Bytes specifying an index in the files symbol string table.
|
||||
* st_value - 4 Bytes identifying the value associated with the symbol.
|
||||
* st_size - 4 Bytes specifying the size associated with the symbol (this is not the size of the symbol).
|
||||
* st_info - A byte specifying the type and binding of the symbol.
|
||||
* st_other - A byte specifying the symbol's visibility.
|
||||
* st_shndx - 2 Bytes identifying the section that this symbol is related to.
|
||||
*
|
||||
* 64-bit:
|
||||
* st_name - 4 Bytes specifying an index in the files symbol string table.
|
||||
* st_info - A byte specifying the type and binding of the symbol.
|
||||
* st_other - A byte specifying the symbol's visibility.
|
||||
* st_shndx - 2 Bytes identifying the section that this symbol is related to.
|
||||
* st_value - 8 Bytes identifying the value associated with the symbol.
|
||||
* st_size - 8 Bytes specifying the size associated with the symbol (this is not the size of the symbol).
|
||||
*/
|
||||
const nameOffset = stream.readInt(4, endianness);
|
||||
stream.moveForwardsBy(format === 2 ? 20 : 12);
|
||||
return readString(stream, strtabOffset, nameOffset);
|
||||
}
|
||||
|
||||
input = new Uint8Array(input);
|
||||
const stream = new Stream(input);
|
||||
const result = ["=".repeat(align) + " ELF Header " + "=".repeat(align)];
|
||||
result.push(elfHeader(stream) + "\n");
|
||||
|
||||
getNamesOffset(stream);
|
||||
|
||||
result.push("=".repeat(align) + " Program Header " + "=".repeat(align));
|
||||
stream.moveTo(phoff);
|
||||
for (let i = 0; i < phEntries; i++)
|
||||
result.push(programHeader(stream) + "\n");
|
||||
|
||||
result.push("=".repeat(align) + " Section Header " + "=".repeat(align));
|
||||
stream.moveTo(shoff);
|
||||
for (let i = 0; i < shEntries; i++)
|
||||
result.push(sectionHeader(stream) + "\n");
|
||||
|
||||
result.push("=".repeat(align) + " Symbol Table " + "=".repeat(align));
|
||||
|
||||
stream.moveTo(symtabOffset);
|
||||
let elem = "";
|
||||
for (let i = 0; i < (symtabSize / symtabEntSize); i++)
|
||||
if ((elem = getSymbols(stream)) !== "")
|
||||
result.push("Symbol Name:".padEnd(align) + elem);
|
||||
|
||||
return result.join("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ELFInfo;
|
||||
@@ -38,7 +38,7 @@ class ExtractFiles extends Operation {
|
||||
<li>
|
||||
${supportedExts.join("</li><li>")}
|
||||
</li>
|
||||
</ul>`;
|
||||
</ul>Minimum File Size can be used to prune small false positives.`;
|
||||
this.infoURL = "https://forensicswiki.xyz/wiki/index.php?title=File_Carving";
|
||||
this.inputType = "ArrayBuffer";
|
||||
this.outputType = "List<File>";
|
||||
@@ -54,6 +54,11 @@ class ExtractFiles extends Operation {
|
||||
name: "Ignore failed extractions",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Minimum File Size",
|
||||
type: "number",
|
||||
value: 100
|
||||
}
|
||||
]);
|
||||
}
|
||||
@@ -66,6 +71,7 @@ class ExtractFiles extends Operation {
|
||||
run(input, args) {
|
||||
const bytes = new Uint8Array(input),
|
||||
categories = [],
|
||||
minSize = args.pop(1),
|
||||
ignoreFailedExtractions = args.pop(1);
|
||||
|
||||
args.forEach((cat, i) => {
|
||||
@@ -80,7 +86,9 @@ class ExtractFiles extends Operation {
|
||||
const errors = [];
|
||||
detectedFiles.forEach(detectedFile => {
|
||||
try {
|
||||
files.push(extractFile(bytes, detectedFile.fileDetails, detectedFile.offset));
|
||||
const file = extractFile(bytes, detectedFile.fileDetails, detectedFile.offset);
|
||||
if (file.size >= minSize)
|
||||
files.push(file);
|
||||
} catch (err) {
|
||||
if (!ignoreFailedExtractions && err.message.indexOf("No extraction algorithm available") < 0) {
|
||||
errors.push(
|
||||
|
||||
@@ -65,12 +65,21 @@ class Fork extends Operation {
|
||||
if (input)
|
||||
inputs = input.split(splitDelim);
|
||||
|
||||
// Set to 1 as if we are here, then there is one, the current one.
|
||||
let numOp = 1;
|
||||
// Create subOpList for each tranche to operate on
|
||||
// (all remaining operations unless we encounter a Merge)
|
||||
// all remaining operations unless we encounter a Merge
|
||||
for (i = state.progress + 1; i < opList.length; i++) {
|
||||
if (opList[i].name === "Merge" && !opList[i].disabled) {
|
||||
break;
|
||||
numOp--;
|
||||
if (numOp === 0 || opList[i].ingValues[0])
|
||||
break;
|
||||
else
|
||||
// Not this Fork's Merge.
|
||||
subOpList.push(opList[i]);
|
||||
} else {
|
||||
if (opList[i].name === "Fork" || opList[i].name === "Subsection")
|
||||
numOp++;
|
||||
subOpList.push(opList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,12 @@ class FromBase45 extends Operation {
|
||||
name: "Alphabet",
|
||||
type: "string",
|
||||
value: ALPHABET
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Remove non-alphabet chars",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
];
|
||||
|
||||
this.highlight = highlightFromBase45;
|
||||
@@ -46,10 +51,17 @@ class FromBase45 extends Operation {
|
||||
*/
|
||||
run(input, args) {
|
||||
if (!input) return [];
|
||||
const alphabet = Utils.expandAlphRange(args[0]);
|
||||
const alphabet = Utils.expandAlphRange(args[0]).join("");
|
||||
const removeNonAlphChars = args[1];
|
||||
|
||||
const res = [];
|
||||
|
||||
// Remove non-alphabet characters
|
||||
if (removeNonAlphChars) {
|
||||
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
}
|
||||
|
||||
for (const triple of Utils.chunked(input, 3)) {
|
||||
triple.reverse();
|
||||
let b = 0;
|
||||
|
||||
@@ -32,6 +32,40 @@ class FromBase85 extends Operation {
|
||||
type: "editableOption",
|
||||
value: ALPHABET_OPTIONS
|
||||
},
|
||||
{
|
||||
name: "Remove non-alphabet chars",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
];
|
||||
this.checks = [
|
||||
{
|
||||
pattern:
|
||||
"^\\s*(?:<~)?" + // Optional whitespace and starting marker
|
||||
"[\\s!-uz]*" + // Any amount of base85 characters and whitespace
|
||||
"[!-uz]{15}" + // At least 15 continoues base85 characters without whitespace
|
||||
"[\\s!-uz]*" + // Any amount of base85 characters and whitespace
|
||||
"(?:~>)?\\s*$", // Optional ending marker and whitespace
|
||||
args: ["!-u"],
|
||||
},
|
||||
{
|
||||
pattern:
|
||||
"^" +
|
||||
"[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" +
|
||||
"[0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]{15}" + // At least 15 continoues base85 characters without whitespace
|
||||
"[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" +
|
||||
"$",
|
||||
args: ["0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#"],
|
||||
},
|
||||
{
|
||||
pattern:
|
||||
"^" +
|
||||
"[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" +
|
||||
"[0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]{15}" + // At least 15 continoues base85 characters without whitespace
|
||||
"[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" +
|
||||
"$",
|
||||
args: ["0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~"],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -43,6 +77,7 @@ class FromBase85 extends Operation {
|
||||
run(input, args) {
|
||||
const alphabet = Utils.expandAlphRange(args[0]).join(""),
|
||||
encoding = alphabetName(alphabet),
|
||||
removeNonAlphChars = args[1],
|
||||
result = [];
|
||||
|
||||
if (alphabet.length !== 85 ||
|
||||
@@ -50,11 +85,18 @@ class FromBase85 extends Operation {
|
||||
throw new OperationError("Alphabet must be of length 85");
|
||||
}
|
||||
|
||||
if (input.length === 0) return [];
|
||||
|
||||
const matches = input.match(/<~(.+?)~>/);
|
||||
// Remove delimiters if present
|
||||
const matches = input.match(/^<~(.+?)~>$/);
|
||||
if (matches !== null) input = matches[1];
|
||||
|
||||
// Remove non-alphabet characters
|
||||
if (removeNonAlphChars) {
|
||||
const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g");
|
||||
input = input.replace(re, "");
|
||||
}
|
||||
|
||||
if (input.length === 0) return [];
|
||||
|
||||
let i = 0;
|
||||
let block, blockBytes;
|
||||
while (i < input.length) {
|
||||
@@ -69,7 +111,7 @@ class FromBase85 extends Operation {
|
||||
.map((chr, idx) => {
|
||||
const digit = alphabet.indexOf(chr);
|
||||
if (digit < 0 || digit > 84) {
|
||||
throw `Invalid character '${chr}' at index ${idx}`;
|
||||
throw `Invalid character '${chr}' at index ${i + idx}`;
|
||||
}
|
||||
return digit;
|
||||
});
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import vkbeautify from "vkbeautify";
|
||||
import JSON5 from "json5";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* JSON Beautify operation
|
||||
@@ -21,19 +23,25 @@ class JSONBeautify extends Operation {
|
||||
|
||||
this.name = "JSON Beautify";
|
||||
this.module = "Code";
|
||||
this.description = "Indents and prettifies JavaScript Object Notation (JSON) code.";
|
||||
this.description = "Indents and pretty prints JavaScript Object Notation (JSON) code.<br><br>Tags: json viewer, prettify, syntax highlighting";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.presentType = "html";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Indent string",
|
||||
"type": "binaryShortString",
|
||||
"value": " "
|
||||
name: "Indent string",
|
||||
type: "binaryShortString",
|
||||
value: " "
|
||||
},
|
||||
{
|
||||
"name": "Sort Object Keys",
|
||||
"type": "boolean",
|
||||
"value": false
|
||||
name: "Sort Object Keys",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Formatted",
|
||||
type: "boolean",
|
||||
value: true
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -44,35 +52,193 @@ class JSONBeautify extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [indentStr, sortBool] = args;
|
||||
|
||||
if (!input) return "";
|
||||
if (sortBool) {
|
||||
input = JSON.stringify(JSONBeautify._sort(JSON.parse(input)));
|
||||
|
||||
const [indentStr, sortBool] = args;
|
||||
let json = null;
|
||||
|
||||
try {
|
||||
json = JSON5.parse(input);
|
||||
} catch (err) {
|
||||
throw new OperationError("Unable to parse input as JSON.\n" + err);
|
||||
}
|
||||
return vkbeautify.json(input, indentStr);
|
||||
|
||||
if (sortBool) json = sortKeys(json);
|
||||
|
||||
return JSON.stringify(json, null, indentStr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sort JSON representation of an object
|
||||
* Adds various dynamic features to the JSON blob
|
||||
*
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @private
|
||||
* @param {object} o
|
||||
* @returns {object}
|
||||
* @param {string} data
|
||||
* @param {Object[]} args
|
||||
* @returns {html}
|
||||
*/
|
||||
static _sort(o) {
|
||||
if (Array.isArray(o)) {
|
||||
return o.map(JSONBeautify._sort);
|
||||
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
|
||||
return Object.keys(o).sort().reduce(function(a, k) {
|
||||
a[k] = JSONBeautify._sort(o[k]);
|
||||
return a;
|
||||
}, {});
|
||||
present(data, args) {
|
||||
const formatted = args[2];
|
||||
if (!formatted) return Utils.escapeHtml(data);
|
||||
|
||||
const json = JSON5.parse(data);
|
||||
const options = {
|
||||
withLinks: true,
|
||||
bigNumbers: true
|
||||
};
|
||||
let html = '<div class="json-document">';
|
||||
|
||||
if (isCollapsable(json)) {
|
||||
const isArr = json instanceof Array;
|
||||
html += '<details open class="json-details">' +
|
||||
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}"></summary>` +
|
||||
json2html(json, options) +
|
||||
"</details>";
|
||||
} else {
|
||||
html += json2html(json, options);
|
||||
}
|
||||
return o;
|
||||
|
||||
html += "</div>";
|
||||
return html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort keys in a JSON object
|
||||
*
|
||||
* @author Phillip Nordwall [phillip.nordwall@gmail.com]
|
||||
* @param {object} o
|
||||
* @returns {object}
|
||||
*/
|
||||
function sortKeys(o) {
|
||||
if (Array.isArray(o)) {
|
||||
return o.map(sortKeys);
|
||||
} else if ("[object Object]" === Object.prototype.toString.call(o)) {
|
||||
return Object.keys(o).sort().reduce(function(a, k) {
|
||||
a[k] = sortKeys(o[k]);
|
||||
return a;
|
||||
}, {});
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if arg is either an array with at least 1 element, or a dict with at least 1 key
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isCollapsable(arg) {
|
||||
return arg instanceof Object && Object.keys(arg).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string looks like a URL, based on protocol
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isUrl(string) {
|
||||
const protocols = ["http", "https", "ftp", "ftps"];
|
||||
for (let i = 0; i < protocols.length; i++) {
|
||||
if (string.startsWith(protocols[i] + "://")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a json object into html representation
|
||||
*
|
||||
* Adapted for CyberChef by @n1474335 from jQuery json-viewer
|
||||
* @author Alexandre Bodelot <alexandre.bodelot@gmail.com>
|
||||
* @link https://github.com/abodelot/jquery.json-viewer
|
||||
* @license MIT
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function json2html(json, options) {
|
||||
let html = "";
|
||||
if (typeof json === "string") {
|
||||
// Escape tags and quotes
|
||||
json = Utils.escapeHtml(json);
|
||||
|
||||
if (options.withLinks && isUrl(json)) {
|
||||
html += `<a href="${json}" class="json-string" target="_blank">${json}</a>`;
|
||||
} else {
|
||||
// Escape double quotes in the rendered non-URL string.
|
||||
json = json.replace(/"/g, "\\"");
|
||||
html += `<span class="json-string">"${json}"</span>`;
|
||||
}
|
||||
} else if (typeof json === "number" || typeof json === "bigint") {
|
||||
html += `<span class="json-literal">${json}</span>`;
|
||||
} else if (typeof json === "boolean") {
|
||||
html += `<span class="json-literal">${json}</span>`;
|
||||
} else if (json === null) {
|
||||
html += '<span class="json-literal">null</span>';
|
||||
} else if (json instanceof Array) {
|
||||
if (json.length > 0) {
|
||||
html += '<span class="json-bracket">[</span><ol class="json-array">';
|
||||
for (let i = 0; i < json.length; i++) {
|
||||
html += "<li>";
|
||||
|
||||
// Add toggle button if item is collapsable
|
||||
if (isCollapsable(json[i])) {
|
||||
const isArr = json[i] instanceof Array;
|
||||
html += '<details open class="json-details">' +
|
||||
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}"></summary>` +
|
||||
json2html(json[i], options) +
|
||||
"</details>";
|
||||
} else {
|
||||
html += json2html(json[i], options);
|
||||
}
|
||||
|
||||
// Add comma if item is not last
|
||||
if (i < json.length - 1) {
|
||||
html += '<span class="json-comma">,</span>';
|
||||
}
|
||||
html += "</li>";
|
||||
}
|
||||
html += '</ol><span class="json-bracket">]</span>';
|
||||
} else {
|
||||
html += '<span class="json-bracket">[]</span>';
|
||||
}
|
||||
} else if (typeof json === "object") {
|
||||
// Optional support different libraries for big numbers
|
||||
// json.isLosslessNumber: package lossless-json
|
||||
// json.toExponential(): packages bignumber.js, big.js, decimal.js, decimal.js-light, others?
|
||||
if (options.bigNumbers && (typeof json.toExponential === "function" || json.isLosslessNumber)) {
|
||||
html += `<span class="json-literal">${json.toString()}</span>`;
|
||||
} else {
|
||||
let keyCount = Object.keys(json).length;
|
||||
if (keyCount > 0) {
|
||||
html += '<span class="json-brace">{</span><ul class="json-dict">';
|
||||
for (const key in json) {
|
||||
if (Object.prototype.hasOwnProperty.call(json, key)) {
|
||||
const safeKey = Utils.escapeHtml(key);
|
||||
html += "<li>";
|
||||
|
||||
// Add toggle button if item is collapsable
|
||||
if (isCollapsable(json[key])) {
|
||||
const isArr = json[key] instanceof Array;
|
||||
html += '<details open class="json-details">' +
|
||||
`<summary class="json-summary ${isArr ? "json-arr" : "json-obj"}">${safeKey}<span class="json-colon">:</span> </summary>` +
|
||||
json2html(json[key], options) +
|
||||
"</details>";
|
||||
} else {
|
||||
html += safeKey + '<span class="json-colon">:</span> ' + json2html(json[key], options);
|
||||
}
|
||||
|
||||
// Add comma if item is not last
|
||||
if (--keyCount > 0) {
|
||||
html += '<span class="json-comma">,</span>';
|
||||
}
|
||||
html += "</li>";
|
||||
}
|
||||
}
|
||||
html += '</ul><span class="json-brace">}</span>';
|
||||
} else {
|
||||
html += '<span class="json-brace">{}</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
export default JSONBeautify;
|
||||
|
||||
@@ -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, '""');
|
||||
|
||||
@@ -52,6 +52,7 @@ class Jump extends Operation {
|
||||
const jmpIndex = getLabelIndex(label, state);
|
||||
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
state.numJumps = 0;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
57
src/core/operations/LS47Decrypt.mjs
Normal file
57
src/core/operations/LS47Decrypt.mjs
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import * as LS47 from "../lib/LS47.mjs";
|
||||
|
||||
/**
|
||||
* LS47 Decrypt operation
|
||||
*/
|
||||
class LS47Decrypt extends Operation {
|
||||
|
||||
/**
|
||||
* LS47Decrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "LS47 Decrypt";
|
||||
this.module = "Crypto";
|
||||
this.description = "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>An LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.";
|
||||
this.infoURL = "https://github.com/exaexa/ls47";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Password",
|
||||
type: "string",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Padding",
|
||||
type: "number",
|
||||
value: 10
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
this.paddingSize = parseInt(args[1], 10);
|
||||
|
||||
LS47.initTiles();
|
||||
|
||||
const key = LS47.deriveKey(args[0]);
|
||||
return LS47.decryptPad(key, input, this.paddingSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LS47Decrypt;
|
||||
62
src/core/operations/LS47Encrypt.mjs
Normal file
62
src/core/operations/LS47Encrypt.mjs
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import * as LS47 from "../lib/LS47.mjs";
|
||||
|
||||
/**
|
||||
* LS47 Encrypt operation
|
||||
*/
|
||||
class LS47Encrypt extends Operation {
|
||||
|
||||
/**
|
||||
* LS47Encrypt constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "LS47 Encrypt";
|
||||
this.module = "Crypto";
|
||||
this.description = "This is a slight improvement of the ElsieFour cipher as described by Alan Kaminsky. We use 7x7 characters instead of original (barely fitting) 6x6, to be able to encrypt some structured information. We also describe a simple key-expansion algorithm, because remembering passwords is popular. Similar security considerations as with ElsieFour hold.<br>The LS47 alphabet consists of following characters: <code>_abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()</code><br>A LS47 key is a permutation of the alphabet that is then represented in a 7x7 grid used for the encryption or decryption.";
|
||||
this.infoURL = "https://github.com/exaexa/ls47";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Password",
|
||||
type: "string",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Padding",
|
||||
type: "number",
|
||||
value: 10
|
||||
},
|
||||
{
|
||||
name: "Signature",
|
||||
type: "string",
|
||||
value: ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
this.paddingSize = parseInt(args[1], 10);
|
||||
|
||||
LS47.initTiles();
|
||||
|
||||
const key = LS47.deriveKey(args[0]);
|
||||
return LS47.encryptPad(key, input, args[2], this.paddingSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LS47Encrypt;
|
||||
55
src/core/operations/LZStringCompress.mjs
Normal file
55
src/core/operations/LZStringCompress.mjs
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @author crespyl [peter@crespyl.net]
|
||||
* @copyright Peter Jacobs 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
import {COMPRESSION_OUTPUT_FORMATS, COMPRESSION_FUNCTIONS} from "../lib/LZString.mjs";
|
||||
|
||||
/**
|
||||
* LZString Compress operation
|
||||
*/
|
||||
class LZStringCompress extends Operation {
|
||||
|
||||
/**
|
||||
* LZStringCompress constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "LZString Compress";
|
||||
this.module = "Compression";
|
||||
this.description = "Compress the input with lz-string.";
|
||||
this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Compression Format",
|
||||
type: "option",
|
||||
defaultIndex: 0,
|
||||
value: COMPRESSION_OUTPUT_FORMATS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const compress = COMPRESSION_FUNCTIONS[args[0]];
|
||||
if (compress) {
|
||||
return compress(input);
|
||||
} else {
|
||||
throw new OperationError("Unable to find compression function");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default LZStringCompress;
|
||||
56
src/core/operations/LZStringDecompress.mjs
Normal file
56
src/core/operations/LZStringDecompress.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @author crespyl [peter@crespyl.net]
|
||||
* @copyright Peter Jacobs 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
|
||||
import {COMPRESSION_OUTPUT_FORMATS, DECOMPRESSION_FUNCTIONS} from "../lib/LZString.mjs";
|
||||
|
||||
/**
|
||||
* LZString Decompress operation
|
||||
*/
|
||||
class LZStringDecompress extends Operation {
|
||||
|
||||
/**
|
||||
* LZStringDecompress constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "LZString Decompress";
|
||||
this.module = "Compression";
|
||||
this.description = "Decompresses data that was compressed with lz-string.";
|
||||
this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Compression Format",
|
||||
type: "option",
|
||||
defaultIndex: 0,
|
||||
value: COMPRESSION_OUTPUT_FORMATS
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const decompress = DECOMPRESSION_FUNCTIONS[args[0]];
|
||||
if (decompress) {
|
||||
return decompress(input);
|
||||
} else {
|
||||
throw new OperationError("Unable to find decompression function");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export default LZStringDecompress;
|
||||
@@ -20,10 +20,16 @@ class Merge extends Operation {
|
||||
this.name = "Merge";
|
||||
this.flowControl = true;
|
||||
this.module = "Default";
|
||||
this.description = "Consolidate all branches back into a single trunk. The opposite of Fork.";
|
||||
this.description = "Consolidate all branches back into a single trunk. The opposite of Fork. Unticking the Merge All checkbox will only consolidate all branches up to the nearest Fork/Subsection.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
this.args = [
|
||||
{
|
||||
name: "Merge All",
|
||||
type: "boolean",
|
||||
value: true,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ class PEMToHex extends Operation {
|
||||
this.name = "PEM to Hex";
|
||||
this.module = "Default";
|
||||
this.description = "Converts PEM (Privacy Enhanced Mail) format to a hexadecimal DER (Distinguished Encoding Rules) string.";
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail#Format";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Privacy-Enhanced_Mail#Format";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
|
||||
133
src/core/operations/PLISTViewer.mjs
Normal file
133
src/core/operations/PLISTViewer.mjs
Normal file
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* P-list Viewer operation
|
||||
*/
|
||||
class PlistViewer extends Operation {
|
||||
|
||||
/**
|
||||
* PlistViewer constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "P-list Viewer";
|
||||
this.module = "Default";
|
||||
this.description = "In the macOS, iOS, NeXTSTEP, and GNUstep programming frameworks, property list files are files that store serialized objects. Property list files use the filename extension .plist, and thus are often referred to as p-list files.<br><br>This operation displays plist files in a human readable format.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Property_list";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
|
||||
// Regexes are designed to transform the xml format into a more readable string format.
|
||||
input = input.slice(input.indexOf("<plist"))
|
||||
.replace(/<plist.+>/g, "plist => ")
|
||||
.replace(/<dict>/g, "{")
|
||||
.replace(/<\/dict>/g, "}")
|
||||
.replace(/<array>/g, "[")
|
||||
.replace(/<\/array>/g, "]")
|
||||
.replace(/<key>.+<\/key>/g, m => `${m.slice(5, m.indexOf(/<\/key>/g)-5)}\t=> `)
|
||||
.replace(/<real>.+<\/real>/g, m => `${m.slice(6, m.indexOf(/<\/real>/g)-6)}\n`)
|
||||
.replace(/<string>.+<\/string>/g, m => `"${m.slice(8, m.indexOf(/<\/string>/g)-8)}"\n`)
|
||||
.replace(/<integer>.+<\/integer>/g, m => `${m.slice(9, m.indexOf(/<\/integer>/g)-9)}\n`)
|
||||
.replace(/<false\/>/g, m => "false")
|
||||
.replace(/<true\/>/g, m => "true")
|
||||
.replace(/<\/plist>/g, "/plist")
|
||||
.replace(/<date>.+<\/date>/g, m => `${m.slice(6, m.indexOf(/<\/integer>/g)-6)}`)
|
||||
.replace(/<data>(\s|.)+?<\/data>/g, m => `${m.slice(6, m.indexOf(/<\/data>/g)-6)}`)
|
||||
.replace(/[ \t\r\f\v]/g, "");
|
||||
|
||||
/**
|
||||
* Depending on the type of brace, it will increment the depth and amount of arrays accordingly.
|
||||
*
|
||||
* @param {string} elem
|
||||
* @param {array} vals
|
||||
* @param {number} offset
|
||||
*/
|
||||
function braces(elem, vals, offset) {
|
||||
const temp = vals.indexOf(elem);
|
||||
if (temp !== -1) {
|
||||
depthCount += offset;
|
||||
if (temp === 1)
|
||||
arrCount += offset;
|
||||
}
|
||||
}
|
||||
|
||||
let result = "";
|
||||
let arrCount = 0;
|
||||
let depthCount = 0;
|
||||
|
||||
/**
|
||||
* Formats the input after the regex has replaced all of the relevant parts.
|
||||
*
|
||||
* @param {array} input
|
||||
* @param {number} index
|
||||
*/
|
||||
function printIt(input, index) {
|
||||
if (!(input.length))
|
||||
return;
|
||||
|
||||
let temp = "";
|
||||
const origArr = arrCount;
|
||||
let currElem = input[0];
|
||||
|
||||
// If the current position points at a larger dynamic structure.
|
||||
if (currElem.indexOf("=>") !== -1) {
|
||||
|
||||
// If the LHS also points at a larger structure (nested plists in a dictionary).
|
||||
if (input[1].indexOf("=>") !== -1)
|
||||
temp = currElem.slice(0, -2) + " => " + input[1].slice(0, -2) + " =>\n";
|
||||
else
|
||||
temp = currElem.slice(0, -2) + " => " + input[1] + "\n";
|
||||
|
||||
input = input.slice(1);
|
||||
} else {
|
||||
// Controls the tab depth for how many closing braces there have been.
|
||||
|
||||
braces(currElem, ["}", "]"], -1);
|
||||
|
||||
// Has to be here since the formatting breaks otherwise.
|
||||
temp = currElem + "\n";
|
||||
}
|
||||
|
||||
currElem = input[0];
|
||||
|
||||
// Tab out to the correct distance.
|
||||
result += ("\t".repeat(depthCount));
|
||||
|
||||
// If it is enclosed in an array show index.
|
||||
if (arrCount > 0 && currElem !== "]")
|
||||
result += index.toString() + " => ";
|
||||
|
||||
result += temp;
|
||||
|
||||
// Controls the tab depth for how many opening braces there have been.
|
||||
braces(currElem, ["{", "["], 1);
|
||||
|
||||
// If there has been a new array then reset index.
|
||||
if (arrCount > origArr)
|
||||
return printIt(input.slice(1), 0);
|
||||
return printIt(input.slice(1), ++index);
|
||||
}
|
||||
|
||||
input = input.split("\n").filter(e => e !== "");
|
||||
printIt(input, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export default PlistViewer;
|
||||
@@ -7,7 +7,7 @@
|
||||
import r from "jsrsasign";
|
||||
import { fromBase64 } from "../lib/Base64.mjs";
|
||||
import { toHex } from "../lib/Hex.mjs";
|
||||
import { formatByteStr, formatDnStr } from "../lib/PublicKey.mjs";
|
||||
import { formatByteStr, formatDnObj } from "../lib/PublicKey.mjs";
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
@@ -76,8 +76,8 @@ class ParseX509Certificate extends Operation {
|
||||
}
|
||||
|
||||
const sn = cert.getSerialNumberHex(),
|
||||
issuer = cert.getIssuerString(),
|
||||
subject = cert.getSubjectString(),
|
||||
issuer = cert.getIssuer(),
|
||||
subject = cert.getSubject(),
|
||||
pk = cert.getPublicKey(),
|
||||
pkFields = [],
|
||||
sig = cert.getSignatureValueHex();
|
||||
@@ -170,10 +170,10 @@ class ParseX509Certificate extends Operation {
|
||||
extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0];
|
||||
} catch (err) {}
|
||||
|
||||
const issuerStr = formatDnStr(issuer, 2),
|
||||
const issuerStr = formatDnObj(issuer, 2),
|
||||
nbDate = formatDate(cert.getNotBefore()),
|
||||
naDate = formatDate(cert.getNotAfter()),
|
||||
subjectStr = formatDnStr(subject, 2);
|
||||
subjectStr = formatDnObj(subject, 2);
|
||||
|
||||
return `Version: ${cert.version} (0x${Utils.hex(cert.version - 1)})
|
||||
Serial number: ${new r.BigInteger(sn, 16).toString()} (0x${sn})
|
||||
|
||||
102
src/core/operations/ROT13BruteForce.mjs
Normal file
102
src/core/operations/ROT13BruteForce.mjs
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @author MikeCAT
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* ROT13 Brute Force operation.
|
||||
*/
|
||||
class ROT13BruteForce extends Operation {
|
||||
|
||||
/**
|
||||
* ROT13BruteForce constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "ROT13 Brute Force";
|
||||
this.module = "Default";
|
||||
this.description = "Try all meaningful amounts for ROT13.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/ROT13";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Rotate lower case chars",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Rotate upper case chars",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Rotate numbers",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Sample length",
|
||||
type: "number",
|
||||
value: 100
|
||||
},
|
||||
{
|
||||
name: "Sample offset",
|
||||
type: "number",
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: "Print amount",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Crib (known plaintext string)",
|
||||
type: "string",
|
||||
value: ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [rotateLower, rotateUpper, rotateNum, sampleLength, sampleOffset, printAmount, crib] = args;
|
||||
const sample = input.slice(sampleOffset, sampleOffset + sampleLength);
|
||||
const cribLower = crib.toLowerCase();
|
||||
const lowerStart = "a".charCodeAt(0), upperStart = "A".charCodeAt(0), numStart = "0".charCodeAt(0);
|
||||
const result = [];
|
||||
for (let amount = 1; amount < 26; amount++) {
|
||||
const rotated = sample.slice();
|
||||
for (let i = 0; i < rotated.length; i++) {
|
||||
if (rotateLower && lowerStart <= rotated[i] && rotated[i] < lowerStart + 26) {
|
||||
rotated[i] = (rotated[i] - lowerStart + amount) % 26 + lowerStart;
|
||||
} else if (rotateUpper && upperStart <= rotated[i] && rotated[i] < upperStart + 26) {
|
||||
rotated[i] = (rotated[i] - upperStart + amount) % 26 + upperStart;
|
||||
} else if (rotateNum && numStart <= rotated[i] && rotated[i] < numStart + 10) {
|
||||
rotated[i] = (rotated[i] - numStart + amount) % 10 + numStart;
|
||||
}
|
||||
}
|
||||
const rotatedString = Utils.byteArrayToUtf8(rotated);
|
||||
if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) {
|
||||
const rotatedStringPrintable = Utils.printable(rotatedString, false);
|
||||
if (printAmount) {
|
||||
const amountStr = "Amount = " + (" " + amount).slice(-2) + ": ";
|
||||
result.push(amountStr + rotatedStringPrintable);
|
||||
} else {
|
||||
result.push(rotatedStringPrintable);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
export default ROT13BruteForce;
|
||||
82
src/core/operations/ROT47BruteForce.mjs
Normal file
82
src/core/operations/ROT47BruteForce.mjs
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @author MikeCAT
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
|
||||
/**
|
||||
* ROT47 Brute Force operation.
|
||||
*/
|
||||
class ROT47BruteForce extends Operation {
|
||||
|
||||
/**
|
||||
* ROT47BruteForce constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "ROT47 Brute Force";
|
||||
this.module = "Default";
|
||||
this.description = "Try all meaningful amounts for ROT47.<br><br>Optionally you can enter your known plaintext (crib) to filter the result.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/ROT13#Variants";
|
||||
this.inputType = "byteArray";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Sample length",
|
||||
type: "number",
|
||||
value: 100
|
||||
},
|
||||
{
|
||||
name: "Sample offset",
|
||||
type: "number",
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: "Print amount",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Crib (known plaintext string)",
|
||||
type: "string",
|
||||
value: ""
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [sampleLength, sampleOffset, printAmount, crib] = args;
|
||||
const sample = input.slice(sampleOffset, sampleOffset + sampleLength);
|
||||
const cribLower = crib.toLowerCase();
|
||||
const result = [];
|
||||
for (let amount = 1; amount < 94; amount++) {
|
||||
const rotated = sample.slice();
|
||||
for (let i = 0; i < rotated.length; i++) {
|
||||
if (33 <= rotated[i] && rotated[i] <= 126) {
|
||||
rotated[i] = (rotated[i] - 33 + amount) % 94 + 33;
|
||||
}
|
||||
}
|
||||
const rotatedString = Utils.byteArrayToUtf8(rotated);
|
||||
if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) {
|
||||
const rotatedStringPrintable = Utils.printable(rotatedString, false);
|
||||
if (printAmount) {
|
||||
const amountStr = "Amount = " + (" " + amount).slice(-2) + ": ";
|
||||
result.push(amountStr + rotatedStringPrintable);
|
||||
} else {
|
||||
result.push(rotatedStringPrintable);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
export default ROT47BruteForce;
|
||||
123
src/core/operations/ROT8000.mjs
Normal file
123
src/core/operations/ROT8000.mjs
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @author Daniel Temkin [http://danieltemkin.com]
|
||||
* @author Thomas Leplus [https://www.leplus.org]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
|
||||
/**
|
||||
* ROT8000 operation.
|
||||
*/
|
||||
class ROT8000 extends Operation {
|
||||
|
||||
/**
|
||||
* ROT8000 constructor
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "ROT8000";
|
||||
this.module = "Default";
|
||||
this.description = "The simple Caesar-cypher encryption that replaces each Unicode character with the one 0x8000 places forward or back along the alphabet.";
|
||||
this.infoURL = "https://rot8000.com/info";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {byteArray} input
|
||||
* @param {Object[]} args
|
||||
* @returns {byteArray}
|
||||
*/
|
||||
run(input, args) {
|
||||
// Inspired from https://github.com/rottytooth/rot8000/blob/main/rot8000.js
|
||||
// these come from the valid-code-point-transitions.json file generated from the c# proj
|
||||
// this is done bc: 1) don't trust JS's understanging of surrogate pairs and 2) consistency with original rot8000
|
||||
const validCodePoints = {
|
||||
"33": true,
|
||||
"127": false,
|
||||
"161": true,
|
||||
"5760": false,
|
||||
"5761": true,
|
||||
"8192": false,
|
||||
"8203": true,
|
||||
"8232": false,
|
||||
"8234": true,
|
||||
"8239": false,
|
||||
"8240": true,
|
||||
"8287": false,
|
||||
"8288": true,
|
||||
"12288": false,
|
||||
"12289": true,
|
||||
"55296": false,
|
||||
"57344": true
|
||||
};
|
||||
const bmpSize = 0x10000;
|
||||
const rotList = {}; // the mapping of char to rotated char
|
||||
const hiddenBlocks = [];
|
||||
let startBlock = 0;
|
||||
for (const key in validCodePoints) {
|
||||
if (Object.prototype.hasOwnProperty.call(validCodePoints, key)) {
|
||||
if (validCodePoints[key] === true)
|
||||
hiddenBlocks.push({ start: startBlock, end: parseInt(key, 10) - 1 });
|
||||
else
|
||||
startBlock = parseInt(key, 10);
|
||||
}
|
||||
}
|
||||
const validIntList = []; // list of all valid chars
|
||||
let currValid = false;
|
||||
for (let i = 0; i < bmpSize; i++) {
|
||||
if (validCodePoints[i] !== undefined) {
|
||||
currValid = validCodePoints[i];
|
||||
}
|
||||
if (currValid) validIntList.push(i);
|
||||
}
|
||||
const rotateNum = Object.keys(validIntList).length / 2;
|
||||
// go through every valid char and find its match
|
||||
for (let i = 0; i < validIntList.length; i++) {
|
||||
rotList[String.fromCharCode(validIntList[i])] =
|
||||
String.fromCharCode(validIntList[(i + rotateNum) % (rotateNum * 2)]);
|
||||
}
|
||||
let output = "";
|
||||
for (let count = 0; count < input.length; count++) {
|
||||
// if it is not in the mappings list, just add it directly (no rotation)
|
||||
if (rotList[input[count]] === undefined) {
|
||||
output += input[count];
|
||||
continue;
|
||||
}
|
||||
// otherwise, rotate it and add it to the string
|
||||
output += rotList[input[count]];
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight ROT8000
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlight(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight ROT8000 in reverse
|
||||
*
|
||||
* @param {Object[]} pos
|
||||
* @param {number} pos[].start
|
||||
* @param {number} pos[].end
|
||||
* @param {Object[]} args
|
||||
* @returns {Object[]} pos
|
||||
*/
|
||||
highlightReverse(pos, args) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
export default ROT8000;
|
||||
@@ -22,7 +22,7 @@ class Subsection extends Operation {
|
||||
this.name = "Subsection";
|
||||
this.flowControl = true;
|
||||
this.module = "Default";
|
||||
this.description = "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.";
|
||||
this.description = "Select a part of the input data using a regular expression (regex), and run all subsequent operations on each match separately.<br><br>You can use up to one capture group, where the recipe will only be run on the data in the capture group. If there's more than one capture group, only the first one will be operated on.<br><br>Use the Merge operation to reset the effects of subsection.";
|
||||
this.infoURL = "";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
@@ -67,12 +67,21 @@ class Subsection extends Operation {
|
||||
subOpList = [];
|
||||
|
||||
if (input && section !== "") {
|
||||
// Set to 1 as if we are here, then there is one, the current one.
|
||||
let numOp = 1;
|
||||
// Create subOpList for each tranche to operate on
|
||||
// all remaining operations unless we encounter a Merge
|
||||
for (let i = state.progress + 1; i < opList.length; i++) {
|
||||
if (opList[i].name === "Merge" && !opList[i].disabled) {
|
||||
break;
|
||||
numOp--;
|
||||
if (numOp === 0 || opList[i].ingValues[0])
|
||||
break;
|
||||
else
|
||||
// Not this subsection's Merge.
|
||||
subOpList.push(opList[i]);
|
||||
} else {
|
||||
if (opList[i].name === "Fork" || opList[i].name === "Subsection")
|
||||
numOp++;
|
||||
subOpList.push(opList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ div.toggle-string {
|
||||
}
|
||||
|
||||
.ingredients .dropdown-toggle-split {
|
||||
height: 41px !important;
|
||||
height: 40px !important;
|
||||
}
|
||||
|
||||
.boolean-arg {
|
||||
|
||||
@@ -34,3 +34,6 @@
|
||||
@import "./layout/_operations.css";
|
||||
@import "./layout/_recipe.css";
|
||||
@import "./layout/_structure.css";
|
||||
|
||||
/* Operations */
|
||||
@import "./operations/json.css";
|
||||
|
||||
@@ -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 */
|
||||
|
||||
78
src/web/stylesheets/operations/json.css
Normal file
78
src/web/stylesheets/operations/json.css
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* JSON styles
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* Adapted for CyberChef by @n1474335 from jQuery json-viewer
|
||||
* @author Alexandre Bodelot <alexandre.bodelot@gmail.com>
|
||||
* @link https://github.com/abodelot/jquery.json-viewer
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
/* Root element */
|
||||
.json-document {
|
||||
padding: .5em 1.5em;
|
||||
}
|
||||
|
||||
/* Syntax highlighting for JSON objects */
|
||||
ul.json-dict, ol.json-array {
|
||||
list-style-type: none;
|
||||
margin: 0 0 0 1px;
|
||||
border-left: 1px dotted #ccc;
|
||||
padding-left: 2em;
|
||||
}
|
||||
.json-string {
|
||||
color: green;
|
||||
}
|
||||
.json-literal {
|
||||
color: red;
|
||||
}
|
||||
.json-brace,
|
||||
.json-bracket,
|
||||
.json-colon,
|
||||
.json-comma {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
/* Collapse */
|
||||
.json-details {
|
||||
display: inline;
|
||||
}
|
||||
.json-details[open] {
|
||||
display: contents;
|
||||
}
|
||||
.json-summary {
|
||||
display: contents;
|
||||
}
|
||||
|
||||
/* Display object and array brackets when closed */
|
||||
.json-summary.json-obj::after {
|
||||
color: gray;
|
||||
content: "{ ... }"
|
||||
}
|
||||
.json-summary.json-arr::after {
|
||||
color: gray;
|
||||
content: "[ ... ]"
|
||||
}
|
||||
.json-details[open] > .json-summary.json-obj::after,
|
||||
.json-details[open] > .json-summary.json-arr::after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
/* Show arrows, even in inline mode */
|
||||
.json-summary::before {
|
||||
content: "\25BC";
|
||||
color: #c0c0c0;
|
||||
margin-left: -12px;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.json-summary:hover::before {
|
||||
color: #aaa;
|
||||
}
|
||||
.json-details[open] > .json-summary::before {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
23
src/web/stylesheets/vendors/bootstrap.scss
vendored
23
src/web/stylesheets/vendors/bootstrap.scss
vendored
@@ -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";
|
||||
@@ -249,6 +249,7 @@ module.exports = {
|
||||
// testOp(browser, "RIPEMD", "test input", "test_output");
|
||||
// testOp(browser, "ROT13", "test input", "test_output");
|
||||
// testOp(browser, "ROT47", "test input", "test_output");
|
||||
// testOp(browser, "ROT8000", "test input", "test_output");
|
||||
// testOp(browser, "Rail Fence Cipher Decode", "test input", "test_output");
|
||||
// testOp(browser, "Rail Fence Cipher Encode", "test input", "test_output");
|
||||
// testOp(browser, "Randomize Colour Palette", "test input", "test_output");
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import Chef from "../../src/core/Chef.mjs";
|
||||
import Utils from "../../src/core/Utils.mjs";
|
||||
import cliProgress from "cli-progress";
|
||||
import log from "loglevel";
|
||||
|
||||
/**
|
||||
* Object to store and run the list of tests.
|
||||
@@ -50,6 +51,9 @@ class TestRegister {
|
||||
* Runs all the tests in the register.
|
||||
*/
|
||||
async runTests () {
|
||||
// Turn off logging to avoid messy errors
|
||||
log.setLevel("silent", false);
|
||||
|
||||
const progBar = new cliProgress.SingleBar({
|
||||
format: formatter,
|
||||
stopOnComplete: true
|
||||
@@ -84,7 +88,17 @@ class TestRegister {
|
||||
|
||||
if (result.error) {
|
||||
if (test.expectedError) {
|
||||
ret.status = "passing";
|
||||
if (result.error.displayStr === test.expectedOutput) {
|
||||
ret.status = "passing";
|
||||
} else {
|
||||
ret.status = "failing";
|
||||
ret.output = [
|
||||
"Expected",
|
||||
"\t" + test.expectedOutput.replace(/\n/g, "\n\t"),
|
||||
"Received",
|
||||
"\t" + result.error.displayStr.replace(/\n/g, "\n\t"),
|
||||
].join("\n");
|
||||
}
|
||||
} else {
|
||||
ret.status = "erroring";
|
||||
ret.output = result.error.displayStr;
|
||||
@@ -118,6 +132,9 @@ class TestRegister {
|
||||
progBar.increment();
|
||||
}
|
||||
|
||||
// Turn logging back on
|
||||
log.setLevel("info", false);
|
||||
|
||||
return testResults;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,12 @@ import "./tests/Base45.mjs";
|
||||
import "./tests/Base58.mjs";
|
||||
import "./tests/Base64.mjs";
|
||||
import "./tests/Base62.mjs";
|
||||
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";
|
||||
@@ -113,6 +116,11 @@ import "./tests/JA3SFingerprint.mjs";
|
||||
import "./tests/HASSH.mjs";
|
||||
import "./tests/GetAllCasings.mjs";
|
||||
import "./tests/SIGABA.mjs";
|
||||
import "./tests/ELFInfo.mjs";
|
||||
import "./tests/Subsection.mjs";
|
||||
import "./tests/CaesarBoxCipher.mjs";
|
||||
import "./tests/LS47.mjs";
|
||||
import "./tests/LZString.mjs";
|
||||
|
||||
|
||||
// Cannot test operations that use the File type yet
|
||||
|
||||
48
tests/operations/tests/Base85.mjs
Normal file
48
tests/operations/tests/Base85.mjs
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Base85 tests
|
||||
*
|
||||
* @author john19696
|
||||
* @copyright Crown Copyright 2019
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
// Example from Wikipedia
|
||||
const wpExample = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.";
|
||||
// Escape newline, quote & backslash
|
||||
const wpOutput = "9jqo^BlbD-BleB1DJ+*+F(f,q/0JhKF<GL>Cj@.4Gp$d7F!,L7@<6@)/0JDEF<G%<+EV:2F!,O<\
|
||||
DJ+*.@<*K0@<6L(Df-\\0Ec5e;DffZ(EZee.Bl.9pF\"AGXBPCsi+DGm>@3BB/F*&OCAfu2/AKYi(\
|
||||
DIb:@FD,*)+C]U=@3BN#EcYf8ATD3s@q?d$AftVqCh[NqF<G:8+EV:.+Cf>-FD5W8ARlolDIal(\
|
||||
DId<j@<?3r@:F%a+D58'ATD4$Bl@l3De:,-DJs`8ARoFb/0JMK@qB4^F!,R<AKZ&-DfTqBG%G>u\
|
||||
D.RTpAKYo'+CT/5+Cei#DII?(E,9)oF*2M7/c";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "To Base85",
|
||||
input: wpExample,
|
||||
expectedOutput: wpOutput,
|
||||
recipeConfig: [
|
||||
{ "op": "To Base85",
|
||||
"args": ["!-u"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Base85",
|
||||
input: wpOutput + "\n",
|
||||
expectedOutput: wpExample,
|
||||
recipeConfig: [
|
||||
{ "op": "From Base85",
|
||||
"args": ["!-u", true] }
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "From Base85",
|
||||
input: wpOutput + "v",
|
||||
expectedError: true,
|
||||
expectedOutput: "From Base85 - Invalid character 'v' at index 337",
|
||||
recipeConfig: [
|
||||
{ "op": "From Base85",
|
||||
"args": ["!-u", false] }
|
||||
]
|
||||
},
|
||||
]);
|
||||
45
tests/operations/tests/CaesarBoxCipher.mjs
Normal file
45
tests/operations/tests/CaesarBoxCipher.mjs
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Caesar Box Cipher tests.
|
||||
*
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Caesar Box Cipher: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Caesar Box Cipher",
|
||||
args: ["1"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Caesar Box Cipher: Hello World!",
|
||||
input: "Hello World!",
|
||||
expectedOutput: "Hlodeor!lWl",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Caesar Box Cipher",
|
||||
args: ["3"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Caesar Box Cipher: Hello World!",
|
||||
input: "Hlodeor!lWl",
|
||||
expectedOutput: "HelloWorld!",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Caesar Box Cipher",
|
||||
args: ["4"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
22
tests/operations/tests/CetaceanCipherDecode.mjs
Normal file
22
tests/operations/tests/CetaceanCipherDecode.mjs
Normal 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: []
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
22
tests/operations/tests/CetaceanCipherEncode.mjs
Normal file
22
tests/operations/tests/CetaceanCipherEncode.mjs
Normal 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: []
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
@@ -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>',
|
||||
|
||||
86
tests/operations/tests/ELFInfo.mjs
Normal file
86
tests/operations/tests/ELFInfo.mjs
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
import {ELF32_LE, ELF32_BE, ELF64_LE, ELF64_BE} from "../../samples/Executables.mjs";
|
||||
|
||||
const ELF32_LE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 32-bit\nEndianness: Little\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: x86\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x34\nEntry SHOFF: 0x54\nFlags: 00000000\nELF Header Size: 52 bytes\nProgram Header Size: 32 bytes\nProgram Header Entries: 1\nSection Header Size: 40 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\nFlags: Execute,Read\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 204\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 230\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 245\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
|
||||
const ELF32_BE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 32-bit\nEndianness: Big\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: x86\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x34\nEntry SHOFF: 0x54\nFlags: 00000000\nELF Header Size: 52 bytes\nProgram Header Size: 32 bytes\nProgram Header Entries: 1\nSection Header Size: 40 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\nFlags: Execute,Read\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 204\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 230\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 245\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
|
||||
const ELF64_LE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 64-bit\nEndianness: Little\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: AMD x86-64\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x40\nEntry SHOFF: 0x78\nFlags: 00000000\nELF Header Size: 64 bytes\nProgram Header Size: 56 bytes\nProgram Header Entries: 1\nSection Header Size: 64 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nFlags: Execute,Read\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 312\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 336\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 361\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
|
||||
const ELF64_BE_OUTPUT = "============================== ELF Header ==============================\nMagic: \x7fELF\nFormat: 64-bit\nEndianness: Big\nVersion: 1\nABI: System V\nABI Version: 0\nType: Executable File\nInstruction Set Architecture: AMD x86-64\nELF Version: 1\nEntry Point: 0x8062150\nEntry PHOFF: 0x40\nEntry SHOFF: 0x78\nFlags: 00000000\nELF Header Size: 64 bytes\nProgram Header Size: 56 bytes\nProgram Header Entries: 1\nSection Header Size: 64 bytes\nSection Header Entries: 3\nSection Header Names: 0\n\n============================== Program Header ==============================\nProgram Header Type: Program Header Table\nFlags: Execute,Read\nOffset Of Segment: 52\nVirtual Address of Segment: 134512692\nPhysical Address of Segment: 134512692\nSize of Segment: 256 bytes\nSize of Segment in Memory: 256 bytes\n\n============================== Section Header ==============================\nType: String Table\nSection Name: .shstrab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 312\nSection Size: 28\nAssociated Section: 0\nSection Extra Information: 0\n\nType: Symbol Table\nSection Name: .symtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 336\nSection Size: 16\nAssociated Section: 0\nSection Extra Information: 0\n\nType: String Table\nSection Name: .strtab\nFlags: \nSection Vaddr in memory: 0\nOffset of the section: 361\nSection Size: 4\nAssociated Section: 0\nSection Extra Information: 0\n\n============================== Symbol Table ==============================\nSymbol Name: test";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "ELF Info invalid ELF.",
|
||||
input: "\x7f\x00\x00\x00",
|
||||
expectedOutput: "Invalid ELF",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "ELF Info",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ELF Info 32-bit ELF Little Endian.",
|
||||
input: ELF32_LE,
|
||||
expectedOutput: ELF32_LE_OUTPUT,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["None"],
|
||||
},
|
||||
{
|
||||
op: "ELF Info",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ELF Info 32-bit ELF Big Endian.",
|
||||
input: ELF32_BE,
|
||||
expectedOutput: ELF32_BE_OUTPUT,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["None"],
|
||||
},
|
||||
{
|
||||
op: "ELF Info",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ELF Info 64-bit ELF Little Endian.",
|
||||
input: ELF64_LE,
|
||||
expectedOutput: ELF64_LE_OUTPUT,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["None"],
|
||||
},
|
||||
{
|
||||
op: "ELF Info",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ELF Info 64-bit ELF Big Endian.",
|
||||
input: ELF64_BE,
|
||||
expectedOutput: ELF64_BE_OUTPUT,
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "From Hex",
|
||||
args: ["None"],
|
||||
},
|
||||
{
|
||||
op: "ELF Info",
|
||||
args: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -31,7 +31,7 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
op: "Merge",
|
||||
args: [],
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -50,7 +50,7 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
op: "Merge",
|
||||
args: [],
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -66,5 +66,16 @@ TestRegister.addTests([
|
||||
{"op": "Label", "args": ["skipReturn"]},
|
||||
{"op": "To Base64", "args": ["A-Za-z0-9+/="]}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "Fork, Partial Merge",
|
||||
input: "Hello World",
|
||||
expectedOutput: "48656c6c6f 576f726c64",
|
||||
recipeConfig: [
|
||||
{ "op": "Fork", "args": [" ", " ", false] },
|
||||
{ "op": "Fork", "args": ["l", "l", false] },
|
||||
{ "op": "Merge", "args": [false] },
|
||||
{ "op": "To Hex", "args": ["None", 0] },
|
||||
]
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -16,7 +16,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -27,7 +27,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -38,8 +38,12 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
{
|
||||
op: "HTML To Text",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -49,7 +53,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -60,7 +64,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -71,7 +75,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -82,7 +86,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
args: ["\t", false, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -93,8 +97,12 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: [" ", false],
|
||||
args: [" ", false, false],
|
||||
},
|
||||
{
|
||||
op: "HTML To Text",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -104,8 +112,12 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", false],
|
||||
args: ["\t", false, false],
|
||||
},
|
||||
{
|
||||
op: "HTML To Text",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -115,8 +127,12 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "JSON Beautify",
|
||||
args: ["\t", true],
|
||||
args: ["\t", true, false],
|
||||
},
|
||||
{
|
||||
op: "HTML To Text",
|
||||
args: []
|
||||
}
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -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}]),
|
||||
|
||||
45
tests/operations/tests/LS47.mjs
Normal file
45
tests/operations/tests/LS47.mjs
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* LS47 tests.
|
||||
*
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "LS47 Encrypt",
|
||||
input: "thequickbrownfoxjumped",
|
||||
expectedOutput: "(,t74ci78cp/8trx*yesu:alp1wqy",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "LS47 Encrypt",
|
||||
args: ["helloworld", 0, "test"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LS47 Decrypt",
|
||||
input: "(,t74ci78cp/8trx*yesu:alp1wqy",
|
||||
expectedOutput: "thequickbrownfoxjumped---test",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "LS47 Decrypt",
|
||||
args: ["helloworld", 0],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LS47 Encrypt",
|
||||
input: "thequickbrownfoxjumped",
|
||||
expectedOutput: "Letter H is not included in LS47",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "LS47 Encrypt",
|
||||
args: ["Helloworld", 0, "test"],
|
||||
},
|
||||
],
|
||||
}
|
||||
]);
|
||||
33
tests/operations/tests/LZString.mjs
Normal file
33
tests/operations/tests/LZString.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* LZString tests.
|
||||
*
|
||||
* @author crespyl [peter@crespyl.net]
|
||||
* @copyright Peter Jacobs 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "LZString Compress To Base64",
|
||||
input: "hello world",
|
||||
expectedOutput: "BYUwNmD2AEDukCcwBMg=",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "LZString Compress",
|
||||
"args": ["Base64"]
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "LZString Decompress From Base64",
|
||||
input: "BYUwNmD2AEDukCcwBMg=",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "LZString Decompress",
|
||||
"args": ["Base64"]
|
||||
}
|
||||
],
|
||||
}
|
||||
]);
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -212,4 +212,37 @@ TestRegister.addTests([
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ROT8000: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "ROT8000",
|
||||
args: []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ROT8000: normal",
|
||||
input: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
||||
expectedOutput: "籝籱籮 籚籾籲籬籴 籋类籸粀籷 籏籸粁 籓籾籶籹籮籭 籘籿籮类 籝籱籮 籕籪粃粂 籍籸籰簷",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "ROT8000",
|
||||
args: []
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "ROT8000: backward",
|
||||
input: "籝籱籮 籚籾籲籬籴 籋类籸粀籷 籏籸粁 籓籾籶籹籮籭 籘籿籮类 籝籱籮 籕籪粃粂 籍籸籰簷",
|
||||
expectedOutput: "The Quick Brown Fox Jumped Over The Lazy Dog.",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "ROT8000",
|
||||
args: []
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
102
tests/operations/tests/Subsection.mjs
Normal file
102
tests/operations/tests/Subsection.mjs
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* Subsection Tests.
|
||||
*
|
||||
* @author n1073645 [n1073645@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Subsection: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["", true, true, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Subsection, Full Merge: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["", true, true, false],
|
||||
},
|
||||
{
|
||||
"op": "Merge",
|
||||
"args": [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Subsection, Partial Merge: nothing",
|
||||
input: "",
|
||||
expectedOutput: "",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["", true, true, false],
|
||||
},
|
||||
{
|
||||
"op": "Merge",
|
||||
"args": [false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Subsection, Full Merge: Base64 with Hex",
|
||||
input: "SGVsbG38675629ybGQ=",
|
||||
expectedOutput: "Hello World",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["386756", true, true, false],
|
||||
},
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"],
|
||||
},
|
||||
{
|
||||
"op": "Merge",
|
||||
"args": [true],
|
||||
},
|
||||
{
|
||||
"op": "From Base64",
|
||||
"args": ["A-Za-z0-9+/=", true, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Subsection, Partial Merge: Base64 with Hex surrounded by binary data.",
|
||||
input: "000000000SGVsbG38675629ybGQ=0000000000",
|
||||
expectedOutput: "000000000Hello World0000000000",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["SGVsbG38675629ybGQ=", true, true, false],
|
||||
},
|
||||
{
|
||||
"op": "Subsection",
|
||||
"args": ["386756", true, true, false],
|
||||
},
|
||||
{
|
||||
"op": "From Hex",
|
||||
"args": ["Auto"],
|
||||
},
|
||||
{
|
||||
"op": "Merge",
|
||||
"args": [false],
|
||||
},
|
||||
{
|
||||
"op": "From Base64",
|
||||
"args": ["A-Za-z0-9+/=", true, false],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
375
tests/samples/Executables.mjs
Normal file
375
tests/samples/Executables.mjs
Normal file
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
* Executables in various formats for use in tests.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2022
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* ---------------ELF Header---------------
|
||||
* 7f454c46 - Magic: .ELF
|
||||
* 01 - Format: 32 bit
|
||||
* 01 - Endianness: Little
|
||||
* 01 - ELF Version: 1
|
||||
* 00 - Target ABI: System V
|
||||
* 00 - ABI Version: 0
|
||||
* 00000000000000 - Padding
|
||||
* 0200 - File Type: Executable File
|
||||
* 0300 - ISA: x86
|
||||
* 01000000 - ELF Version: 1
|
||||
* 50210608 - Entry Point: 0x8062150
|
||||
* 34000000 - PH Offset: 0x34
|
||||
* 54000000 - SH Offset: 0x54
|
||||
* 00000000 - Flags: 0
|
||||
* 3400 - ELF Header Size: 0x34
|
||||
* 2000 - PH Header Size: 0x20
|
||||
* 0100 - PH Entries: 1
|
||||
* 2800 - SH Size: 0x28
|
||||
* 0300 - SH Entries: 0x3
|
||||
* 0000 - SH Names Offset: 0x0
|
||||
*
|
||||
* -------------Program Header-------------
|
||||
* 06000000 - PH Type: Program Header Table
|
||||
* 34000000 - Segment Offset: 0x34
|
||||
* 34800408 - VAddr of segment: 134512692
|
||||
* 34800408 - PAddr of segment: 134512692
|
||||
* 00010000 - Size of segment: 256
|
||||
* 00010000 - Size of segment: 256
|
||||
* 05000000 - Flags: Execute,Read
|
||||
* 04000000 - Alignment
|
||||
*
|
||||
* --------------SH .shstrtab--------------
|
||||
* 00000000 - SH Name Offset: 0
|
||||
* 03000000 - SH Type: String Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* cc000000 - Section offset: 204
|
||||
* 1c000000 - Section size: 28
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 00000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------SH .symtab---------------
|
||||
* 09000000 - SH Name Offset: 9
|
||||
* 02000000 - SH Type: Symbol Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* e6000000 - Section offset: 230
|
||||
* 10000000 - Section size: 16
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 10000000 - Entry Size: 16
|
||||
*
|
||||
* ---------------SH .strtab---------------
|
||||
* 11000000 - SH Name Offset: 17
|
||||
* 03000000 - SH Type: String Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* f5000000 - Section offset: 245
|
||||
* 04000000 - Section size: 4
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 00000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------.shstrtab---------------
|
||||
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
|
||||
*
|
||||
* ----------------.symtab----------------
|
||||
* 00000000 - Name Offset: 0
|
||||
* 00000000 - Value: 0
|
||||
* 00000000 - Size: 0
|
||||
* 00 - Info
|
||||
* 00 - other
|
||||
* 0000 - shdx
|
||||
*
|
||||
* ----------------.strtab----------------
|
||||
* 74657374 - test
|
||||
*/
|
||||
export const ELF32_LE = "7f454c46010101000000000000000000020003000100000050210608340000005400000000000000340020000100280003000000" +
|
||||
"0600000034000000348004083480040800010000000100000500000004000000" +
|
||||
"00000000030000000000000000000000cc0000001c00000000000000000000000000000000000000" +
|
||||
"09000000020000000000000000000000e60000001000000000000000000000000000000010000000" +
|
||||
"11000000030000000000000000000000f50000000400000000000000000000000000000000000000" +
|
||||
"2e73687374726162002e73796d746162002e73747274616200" +
|
||||
"00000000000000000000000000000000" +
|
||||
"74657374";
|
||||
|
||||
/**
|
||||
* ---------------ELF Header---------------
|
||||
* 7f454c46 - Magic: .ELF
|
||||
* 01 - Format: 32 bit
|
||||
* 02 - Endianness: Big
|
||||
* 01 - ELF Version: 1
|
||||
* 00 - Target ABI: System V
|
||||
* 00 - ABI Version: 0
|
||||
* 00000000000000 - Padding
|
||||
* 0002 - File Type: Executable File
|
||||
* 0003 - ISA: x86
|
||||
* 00000001 - ELF Version: 1
|
||||
* 08062150 - Entry Point: 0x8062150
|
||||
* 00000034 - PH Offset: 0x34
|
||||
* 00000054 - SH Offset: 0x54
|
||||
* 00000000 - Flags: 0
|
||||
* 0034 - ELF Header Size: 0x34
|
||||
* 0020 - PH Header Size: 0x20
|
||||
* 0001 - PH Entries: 1
|
||||
* 0028 - SH Size: 0x28
|
||||
* 0003 - SH Entries: 0x3
|
||||
* 0000 - SH Names Offset: 0x0
|
||||
*
|
||||
* -------------Program Header-------------
|
||||
* 00000006 - PH Type: Program Header Table
|
||||
* 00000034 - Segment Offset: 0x34
|
||||
* 08048034 - VAddr of segment: 134512692
|
||||
* 08048034 - PAddr of segment: 134512692
|
||||
* 00000100 - Size of segment: 256
|
||||
* 00000100 - Size of segment: 256
|
||||
* 00000005 - Flags: Execute,Read
|
||||
* 00000004 - Alignment
|
||||
*
|
||||
* --------------SH .shstrtab--------------
|
||||
* 00000000 - SH Name Offset: 0
|
||||
* 00000003 - SH Type: String Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* 000000cc - Section offset: 204
|
||||
* 0000001c - Section size: 28
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 00000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------SH .symtab---------------
|
||||
* 00000009 - SH Name Offset: 9
|
||||
* 00000002 - SH Type: Symbol Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* 000000e6 - Section offset: 230
|
||||
* 00000010 - Section size: 16
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 00000010 - Entry Size: 16
|
||||
*
|
||||
* ---------------SH .strtab---------------
|
||||
* 00000011 - SH Name Offset: 17
|
||||
* 00000003 - SH Type: String Table
|
||||
* 00000000 - Flags:
|
||||
* 00000000 - VAddr of section: 0
|
||||
* 000000f5 - Section offset: 245
|
||||
* 00000004 - Section size: 4
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 00000000 - Alignment
|
||||
* 00000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------.shstrtab---------------
|
||||
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
|
||||
*
|
||||
* ----------------.symtab----------------
|
||||
* 00000000 - Name Offset: 0
|
||||
* 00000000 - Value: 0
|
||||
* 00000000 - Size: 0
|
||||
* 00 - Info
|
||||
* 00 - other
|
||||
* 0000 - shdx
|
||||
*
|
||||
* ----------------.strtab----------------
|
||||
* 74657374 - test
|
||||
*/
|
||||
export const ELF32_BE = "7f454c46010201000000000000000000000200030000000108062150000000340000005400000000003400200001002800030000" +
|
||||
"0000000600000034080480340804803400000100000001000000000500000004" +
|
||||
"00000000000000030000000000000000000000cc0000001c00000000000000000000000000000000" +
|
||||
"00000009000000020000000000000000000000e60000001000000000000000000000000000000010" +
|
||||
"00000011000000030000000000000000000000f50000000400000000000000000000000000000000" +
|
||||
"2e73687374726162002e73796d746162002e73747274616200" +
|
||||
"00000000000000000000000000000000" +
|
||||
"74657374";
|
||||
|
||||
/**
|
||||
* ---------------ELF Header---------------
|
||||
* 7f454c46 - Magic: .ELF
|
||||
* 02 - Format: 64 bit
|
||||
* 01 - Endianness: Little
|
||||
* 01 - ELF Version: 1
|
||||
* 00 - Target ABI: System V
|
||||
* 00 - ABI Version: 0
|
||||
* 00000000000000 - Padding
|
||||
* 0200 - File Type: Executable File
|
||||
* 3e00 - ISA: AMD x86-64
|
||||
* 01000000 - ELF Version: 1
|
||||
* 5021060800000000 - Entry Point: 0x8062150
|
||||
* 4000000000000000 - PH Offset: 0x40
|
||||
* 7800000000000000 - SH Offset: 0x78
|
||||
* 00000000 - Flags: 0
|
||||
* 4000 - ELF Header Size: 0x40
|
||||
* 3800 - PH Header Size: 0x38
|
||||
* 0100 - PH Entries: 1
|
||||
* 4000 - SH Size: 0x40
|
||||
* 0300 - SH Entries: 0x3
|
||||
* 0000 - SH Names Offset: 0x0
|
||||
*
|
||||
* -------------Program Header-------------
|
||||
* 06000000 - PH Type: Program Header Table
|
||||
* 05000000 - Flags: Execute,Read
|
||||
* 3400000000000000 - Segment Offset: 0x34
|
||||
* 3480040800000000 - VAddr of segment: 134512692
|
||||
* 3480040800000000 - PAddr of segment: 134512692
|
||||
* 0001000000000000 - Size of segment: 256
|
||||
* 0001000000000000 - Size of segment: 256
|
||||
* 0400000000000000 - Alignment
|
||||
*
|
||||
* --------------SH .shstrtab--------------
|
||||
* 00000000 - SH Name Offset: 0
|
||||
* 03000000 - SH Type: String Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 3801000000000000 - Section offset: 312
|
||||
* 1c00000000000000 - Section size: 28
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 0000000000000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------SH .symtab---------------
|
||||
* 09000000 - SH Name Offset: 9
|
||||
* 02000000 - SH Type: Symbol Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 5001000000000000 - Section offset: 336
|
||||
* 1000000000000000 - Section size: 16
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 1800000000000000 - Entry Size: 24
|
||||
*
|
||||
* ---------------SH .strtab---------------
|
||||
* 11000000 - SH Name Offset: 17
|
||||
* 03000000 - SH Type: String Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 6901000000000000 - Section offset: 361
|
||||
* 0400000000000000 - Section size: 4
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 0000000000000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------.shstrtab---------------
|
||||
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
|
||||
*
|
||||
* ----------------.symtab----------------
|
||||
* 00000000 - Name Offset: 0
|
||||
* 00 - Info
|
||||
* 00 - other
|
||||
* 0000 - shdx
|
||||
* 0000000000000000 - Value: 0
|
||||
* 0000000000000000 - Size: 0
|
||||
*
|
||||
* ----------------.strtab----------------
|
||||
* 74657374 - test
|
||||
*/
|
||||
export const ELF64_LE = "7f454c4602010100000000000000000002003e000100000050210608000000004000000000000000780000000000000000000000400038000100400003000000" +
|
||||
"0600000005000000340000000000000034800408000000003480040800000000000100000000000000010000000000000400000000000000" +
|
||||
"00000000030000000000000000000000000000000000000038010000000000001c00000000000000000000000000000000000000000000000000000000000000" +
|
||||
"09000000020000000000000000000000000000000000000050010000000000001000000000000000000000000000000000000000000000001800000000000000" +
|
||||
"11000000030000000000000000000000000000000000000069010000000000000400000000000000000000000000000000000000000000000000000000000000" +
|
||||
"2e73687374726162002e73796d746162002e73747274616200" +
|
||||
"000000000000000000000000000000000000000000000000" +
|
||||
"74657374";
|
||||
|
||||
/**
|
||||
* ---------------ELF Header---------------
|
||||
* 7f454c46 - Magic: .ELF
|
||||
* 02 - Format: 64 bit
|
||||
* 02 - Endianness: Big
|
||||
* 01 - ELF Version: 1
|
||||
* 00 - Target ABI: System V
|
||||
* 00 - ABI Version: 0
|
||||
* 00000000000000 - Padding
|
||||
* 0002 - File Type: Executable File
|
||||
* 003e - ISA: AMD x86-64
|
||||
* 00000001 - ELF Version: 1
|
||||
* 0000000008062150 - Entry Point: 0x8062150
|
||||
* 0000000000000040 - PH Offset: 0x40
|
||||
* 0000000000000078 - SH Offset: 0x78
|
||||
* 00000000 - Flags: 0
|
||||
* 0040 - ELF Header Size: 0x40
|
||||
* 0038 - PH Header Size: 0x38
|
||||
* 0001 - PH Entries: 1
|
||||
* 0040 - SH Size: 0x40
|
||||
* 0003 - SH Entries: 0x3
|
||||
* 0000 - SH Names Offset: 0x0
|
||||
*
|
||||
* -------------Program Header-------------
|
||||
* 00000006 - PH Type: Program Header Table
|
||||
* 00000005 - Flags: Execute,Read
|
||||
* 0000000000000034 - Segment Offset: 0x34
|
||||
* 0000000008048034 - VAddr of segment: 134512692
|
||||
* 0000000008048034 - PAddr of segment: 134512692
|
||||
* 0000000000000100 - Size of segment: 256
|
||||
* 0000000000000100 - Size of segment: 256
|
||||
* 0400000000000000 - Alignment
|
||||
*
|
||||
* --------------SH .shstrtab--------------
|
||||
* 00000000 - SH Name Offset: 0
|
||||
* 00000003 - SH Type: String Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 0000000000000138 - Section offset: 312
|
||||
* 000000000000001c - Section size: 28
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 0000000000000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------SH .symtab---------------
|
||||
* 00000009 - SH Name Offset: 9
|
||||
* 00000002 - SH Type: Symbol Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 0000000000000150 - Section offset: 336
|
||||
* 0000000000000010 - Section size: 16
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 0000000000000018 - Entry Size: 24
|
||||
*
|
||||
* ---------------SH .strtab---------------
|
||||
* 00000011 - SH Name Offset: 17
|
||||
* 00000003 - SH Type: String Table
|
||||
* 0000000000000000 - Flags:
|
||||
* 0000000000000000 - VAddr of section: 0
|
||||
* 0000000000000169 - Section offset: 361
|
||||
* 0000000000000004 - Section size: 4
|
||||
* 00000000 - Associated: 0
|
||||
* 00000000 - Extra Info: 0
|
||||
* 0000000000000000 - Alignment
|
||||
* 0000000000000000 - Entry Size: 0
|
||||
*
|
||||
* ---------------.shstrtab---------------
|
||||
* 2e73687374726162002e73796d746162002e73747274616200 - .shstrab\0.symtab\0.strtab\0
|
||||
*
|
||||
* ----------------.symtab----------------
|
||||
* 00000000 - Name Offset: 0
|
||||
* 00 - Info
|
||||
* 00 - other
|
||||
* 0000 - shdx
|
||||
* 0000000000000000 - Value: 0
|
||||
* 0000000000000000 - Size: 0
|
||||
*
|
||||
* ----------------.strtab----------------
|
||||
* 74657374 - test
|
||||
*/
|
||||
export const ELF64_BE = "7f454c460202010000000000000000000002003e0000000100000000080621500000000000000040000000000000007800000000004000380001004000030000" +
|
||||
"0000000600000005000000000000003400000000080480340000000008048034000000000000010000000000000001000400000000000000" +
|
||||
"0000000000000003000000000000000000000000000000000000000000000138000000000000001c000000000000000000000000000000000000000000000000" +
|
||||
"00000009000000020000000000000000000000000000000000000000000001500000000000000010000000000000000000000000000000000000000000000018" +
|
||||
"00000011000000030000000000000000000000000000000000000000000001690000000000000004000000000000000000000000000000000000000000000000" +
|
||||
"2e73687374726162002e73796d746162002e73747274616200" +
|
||||
"000000000000000000000000000000000000000000000000" +
|
||||
"74657374";
|
||||
@@ -164,19 +164,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",
|
||||
|
||||
Reference in New Issue
Block a user