mirror of
https://github.com/gchq/CyberChef
synced 2025-12-05 23:53:27 +00:00
Compare commits
117 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe4c5f5899 | ||
|
|
d47b7b9242 | ||
|
|
09b6661e35 | ||
|
|
57b1667b69 | ||
|
|
5e9380b550 | ||
|
|
fc8a0480fb | ||
|
|
317327d097 | ||
|
|
ecd0ac2521 | ||
|
|
f9eaf67db2 | ||
|
|
99e0c8d5e3 | ||
|
|
7a951d86d8 | ||
|
|
d9dfaec84c | ||
|
|
80719ae368 | ||
|
|
9407809356 | ||
|
|
f7e958e7a1 | ||
|
|
5d75f8636a | ||
|
|
22aaeb3ff5 | ||
|
|
8c29ce95e2 | ||
|
|
049fc66785 | ||
|
|
029c55fd53 | ||
|
|
7b433b9bd6 | ||
|
|
5ec210990b | ||
|
|
a7a0cacddb | ||
|
|
e61ced93d6 | ||
|
|
df122da1d2 | ||
|
|
31d90939fe | ||
|
|
67b0fdf73e | ||
|
|
12fc8c22dd | ||
|
|
4ca2a30249 | ||
|
|
08a31523b2 | ||
|
|
4b29a61065 | ||
|
|
06c83cb44c | ||
|
|
75a5fc0ddc | ||
|
|
946d165aa0 | ||
|
|
224d79be05 | ||
|
|
435ed587a5 | ||
|
|
caae0ec5ca | ||
|
|
9bc6c46dc3 | ||
|
|
b48e940f2d | ||
|
|
e500cfae75 | ||
|
|
f01c0adee2 | ||
|
|
021cae1a95 | ||
|
|
f66cd8f983 | ||
|
|
fe8049199a | ||
|
|
cfb6dd9471 | ||
|
|
7abda44fd6 | ||
|
|
47ce240e70 | ||
|
|
c23d7fd79c | ||
|
|
555fed2d51 | ||
|
|
7a2f68e14a | ||
|
|
8fd08cb2bf | ||
|
|
7a2b75c861 | ||
|
|
00074f914f | ||
|
|
ea352e05f0 | ||
|
|
305956cbe3 | ||
|
|
5399d27875 | ||
|
|
29047c2481 | ||
|
|
50a32e90d9 | ||
|
|
f596fe8404 | ||
|
|
4be7f89fd8 | ||
|
|
8b30fdf7f1 | ||
|
|
2cd4256ece | ||
|
|
c6a65c4686 | ||
|
|
1553b5f54b | ||
|
|
2ddd2e0a60 | ||
|
|
d924ede9cf | ||
|
|
638e03856b | ||
|
|
8afd77b32d | ||
|
|
599fefb39b | ||
|
|
ec7294d734 | ||
|
|
c0d03db9e8 | ||
|
|
0365f96678 | ||
|
|
40d8b42478 | ||
|
|
e5a32ac57d | ||
|
|
390d5927a4 | ||
|
|
b61a1b4edb | ||
|
|
1d78578fc2 | ||
|
|
0e3751407b | ||
|
|
7feafbf0e7 | ||
|
|
cfd9b16f8b | ||
|
|
1bbc73ec50 | ||
|
|
dc9ba583d5 | ||
|
|
6b5ff83927 | ||
|
|
a5ffa406a8 | ||
|
|
6234afc119 | ||
|
|
ef2ead262b | ||
|
|
cd5265fad4 | ||
|
|
0c4ef1cc94 | ||
|
|
4fee6cd5d8 | ||
|
|
da63420d67 | ||
|
|
72c79c684b | ||
|
|
a997ec0695 | ||
|
|
e3be2a9531 | ||
|
|
bd1790b692 | ||
|
|
90763dee6a | ||
|
|
16879a9190 | ||
|
|
2afd23fcf7 | ||
|
|
39fd0f9b34 | ||
|
|
ee57a92daa | ||
|
|
ab7cc878c3 | ||
|
|
877ab57f0a | ||
|
|
e2ac297102 | ||
|
|
b86dceb3c6 | ||
|
|
35c9dca955 | ||
|
|
d54d7011d9 | ||
|
|
392652ed8e | ||
|
|
7557e1e9e5 | ||
|
|
d924da2f25 | ||
|
|
be4d1eabaa | ||
|
|
db98e56e72 | ||
|
|
e2a35ea844 | ||
|
|
7966b2bde6 | ||
|
|
9391b947c6 | ||
|
|
e61e3bcf9b | ||
|
|
89ca2cc631 | ||
|
|
e2cae035f2 | ||
|
|
d79a0e737a |
@@ -28,11 +28,7 @@
|
||||
// modify rules from base configurations
|
||||
"no-unused-vars": ["error", {
|
||||
"args": "none",
|
||||
"vars": "local",
|
||||
// Allow vars that start with a capital letter to be unused.
|
||||
// This is mainly for exported module names which are useful to indicate
|
||||
// the name of the module and may be used to refer to itself in future.
|
||||
"varsIgnorePattern": "^[A-Z]"
|
||||
"vars": "all"
|
||||
}],
|
||||
"no-empty": ["error", {
|
||||
"allowEmptyCatch": true
|
||||
|
||||
13
.github/ISSUE_TEMPLATE.md
vendored
13
.github/ISSUE_TEMPLATE.md
vendored
@@ -5,21 +5,10 @@
|
||||
<!-- Misc: -->
|
||||
|
||||
### Summary
|
||||
<!-- If you're describing a bug, tell us what's wrong -->
|
||||
<!-- If you're suggesting a change/improvement, tell us what it is and how it should work -->
|
||||
|
||||
|
||||
### Example
|
||||
<!-- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!-- Include a link that triggers the bug if possible -->
|
||||
<!-- If you are requesting a new operation, include example input and output -->
|
||||
|
||||
### Possible solutions
|
||||
<!-- Not obligatory, but suggest a fix/reason for the bug, or ideas for how to -->
|
||||
<!-- implement the addition or change, including links to relevant resources -->
|
||||
|
||||
### Environment
|
||||
<!-- Include any relevant details about the environment you experienced the bug in -->
|
||||
<!-- This information is displayed in the About/Support pane -->
|
||||
* CyberChef compile time:
|
||||
* User-Agent:
|
||||
* [Link to reproduce]()
|
||||
|
||||
@@ -39,4 +39,10 @@ deploy:
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/83c143a6822e218d5b34
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: never
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
"use strict";
|
||||
|
||||
const webpack = require("webpack");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const NodeExternals = require("webpack-node-externals");
|
||||
@@ -309,7 +311,10 @@ module.exports = function (grunt) {
|
||||
"webpack-dev-server": {
|
||||
options: {
|
||||
webpack: webpackConfig,
|
||||
host: "0.0.0.0",
|
||||
disableHostCheck: true,
|
||||
overlay: true,
|
||||
inline: false,
|
||||
clientLogLevel: "error",
|
||||
stats: {
|
||||
children: false,
|
||||
|
||||
24
README.md
24
README.md
@@ -1,8 +1,12 @@
|
||||
# CyberChef
|
||||
|
||||
[](https://travis-ci.org/gchq/CyberChef)
|
||||
[](https://www.npmjs.com/package/cyberchef)
|
||||

|
||||
[](https://david-dm.org/gchq/CyberChef)
|
||||
[](https://www.npmjs.com/package/cyberchef)
|
||||

|
||||
[](https://github.com/gchq/CyberChef/blob/master/LICENSE)
|
||||
[](https://gitter.im/gchq/CyberChef?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
|
||||
|
||||
#### *The Cyber Swiss Army Knife*
|
||||
|
||||
@@ -34,8 +38,10 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||
- [Convert a date and time to a different time zone][3]
|
||||
- [Parse a Teredo IPv6 address][4]
|
||||
- [Convert data from a hexdump, then decompress][5]
|
||||
- [Display multiple timestamps as full dates][6]
|
||||
- [Carry out different operations on data of different types][7]
|
||||
- [Decrypt and disassemble shellcode][6]
|
||||
- [Display multiple timestamps as full dates][7]
|
||||
- [Carry out different operations on data of different types][8]
|
||||
- [Use parts of the input as arguments to operations][9]
|
||||
|
||||
|
||||
## Features
|
||||
@@ -56,7 +62,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
|
||||
- Search
|
||||
- If you know the name of the operation you want or a word associated with it, start typing it into the search field and any matching operations will immediately be shown.
|
||||
- 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][8]).
|
||||
- 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][10]).
|
||||
- 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 (note that files larger than about 500kb may cause your browser to hang or even crash due to the way that browsers handle large amounts of textual data).
|
||||
- CyberChef is entirely client-side
|
||||
@@ -92,6 +98,8 @@ CyberChef is released under the [Apache 2.0 Licence](https://www.apache.org/lice
|
||||
[3]: https://gchq.github.io/CyberChef/#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA
|
||||
[4]: https://gchq.github.io/CyberChef/#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy
|
||||
[5]: https://gchq.github.io/CyberChef/#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw
|
||||
[6]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
||||
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||
[8]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
[6]: https://gchq.github.io/CyberChef/#recipe=RC4(%7B'option':'UTF8','string':'secret'%7D,'Hex','Hex')Disassemble_x86('64','Full%20x86%20architecture',16,0,true,true)&input=MjFkZGQyNTQwMTYwZWU2NWZlMDc3NzEwM2YyYTM5ZmJlNWJjYjZhYTBhYWJkNDE0ZjkwYzZjYWY1MzEyNzU0YWY3NzRiNzZiM2JiY2QxOTNjYjNkZGZkYmM1YTI2NTMzYTY4NmI1OWI4ZmVkNGQzODBkNDc0NDIwMWFlYzIwNDA1MDcxMzhlMmZlMmIzOTUwNDQ2ZGIzMWQyYmM2MjliZTRkM2YyZWIwMDQzYzI5M2Q3YTVkMjk2MmMwMGZlNmRhMzAwNzJkOGM1YTZiNGZlN2Q4NTlhMDQwZWVhZjI5OTczMzYzMDJmNWEwZWMxOQ
|
||||
[7]: https://gchq.github.io/CyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA
|
||||
[8]: https://gchq.github.ioeCyberChef/#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA
|
||||
[9]: https://gchq.github.io/CyberChef/#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ
|
||||
[10]: https://gchq.github.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4
|
||||
|
||||
3329
package-lock.json
generated
3329
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
53
package.json
53
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cyberchef",
|
||||
"version": "6.0.1",
|
||||
"version": "6.7.2",
|
||||
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
|
||||
"author": "n1474335 <n1474335@gmail.com>",
|
||||
"homepage": "https://gchq.github.io/CyberChef",
|
||||
@@ -32,11 +32,11 @@
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"css-loader": "^0.28.7",
|
||||
"exports-loader": "^0.6.4",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^0.11.2",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^1.1.6",
|
||||
"grunt": ">=1.0.1",
|
||||
"grunt-accessibility": "~5.0.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
@@ -46,34 +46,34 @@
|
||||
"grunt-eslint": "^20.1.0",
|
||||
"grunt-exec": "~3.0.0",
|
||||
"grunt-execute": "^0.2.2",
|
||||
"grunt-jsdoc": "^2.1.1",
|
||||
"grunt-jsdoc": "^2.2.0",
|
||||
"grunt-webpack": "^3.0.2",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"ink-docstrap": "^1.3.0",
|
||||
"ink-docstrap": "^1.3.2",
|
||||
"jsdoc-babel": "^0.3.0",
|
||||
"less": "^2.7.2",
|
||||
"less": "^2.7.3",
|
||||
"less-loader": "^4.0.5",
|
||||
"postcss-css-variables": "^0.8.0",
|
||||
"postcss-import": "^10.0.0",
|
||||
"postcss-loader": "^2.0.6",
|
||||
"style-loader": "^0.18.2",
|
||||
"url-loader": "^0.5.9",
|
||||
"val-loader": "^1.0.2",
|
||||
"web-resource-inliner": "^4.1.1",
|
||||
"webpack": "^3.5.6",
|
||||
"webpack-dev-server": "^2.5.0",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.9",
|
||||
"style-loader": "^0.19.1",
|
||||
"url-loader": "^0.6.2",
|
||||
"val-loader": "^1.1.0",
|
||||
"web-resource-inliner": "^4.2.0",
|
||||
"webpack": "^3.10.0",
|
||||
"webpack-dev-server": "^2.9.7",
|
||||
"webpack-node-externals": "^1.6.0",
|
||||
"worker-loader": "^0.8.0"
|
||||
"worker-loader": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"bootstrap": "^3.3.7",
|
||||
"bootstrap-colorpicker": "^2.5.1",
|
||||
"bootstrap-colorpicker": "^2.5.2",
|
||||
"bootstrap-switch": "^3.3.4",
|
||||
"crypto-api": "^0.7.3",
|
||||
"crypto-api": "^0.7.5",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"diff": "^3.3.1",
|
||||
"diff": "^3.4.0",
|
||||
"escodegen": "^1.9.0",
|
||||
"esmangle": "^1.0.1",
|
||||
"esprima": "^4.0.0",
|
||||
@@ -81,21 +81,22 @@
|
||||
"google-code-prettify": "^1.0.5",
|
||||
"jquery": "^3.2.1",
|
||||
"js-crc": "^0.2.0",
|
||||
"js-sha3": "^0.6.1",
|
||||
"js-sha3": "^0.7.0",
|
||||
"jsbn": "^1.1.0",
|
||||
"jsonpath": "^0.2.12",
|
||||
"jsrsasign": "8.0.3",
|
||||
"jsonpath": "^1.0.0",
|
||||
"jsrsasign": "8.0.4",
|
||||
"lodash": "^4.17.4",
|
||||
"moment": "^2.18.1",
|
||||
"moment-timezone": "^0.5.13",
|
||||
"moment": "^2.20.1",
|
||||
"moment-timezone": "^0.5.14",
|
||||
"node-md6": "^0.1.0",
|
||||
"nwmatcher": "^1.4.3",
|
||||
"otp": "^0.1.3",
|
||||
"sladex-blowfish": "^0.8.1",
|
||||
"sortablejs": "^1.6.1",
|
||||
"sortablejs": "^1.7.0",
|
||||
"split.js": "^1.3.5",
|
||||
"vkbeautify": "^0.99.3",
|
||||
"xmldom": "^0.1.27",
|
||||
"xpath": "0.0.24",
|
||||
"xpath": "0.0.27",
|
||||
"zlibjs": "^0.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -68,9 +68,10 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
|
||||
try {
|
||||
progress = await recipe.execute(this.dish, progress);
|
||||
} catch (err) {
|
||||
// Return the error in the result so that everything else gets correctly updated
|
||||
// rather than throwing it here and losing state info.
|
||||
error = err;
|
||||
console.log(err);
|
||||
error = {
|
||||
displayStr: err.displayStr,
|
||||
};
|
||||
progress = err.progress;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ async function bake(data) {
|
||||
} catch (err) {
|
||||
self.postMessage({
|
||||
action: "bakeError",
|
||||
data: err.message
|
||||
data: err
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -176,3 +176,22 @@ self.setOption = function(option, value) {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Send register values back to the app.
|
||||
*
|
||||
* @param {number} opIndex
|
||||
* @param {number} numPrevRegisters
|
||||
* @param {string[]} registers
|
||||
*/
|
||||
self.setRegisters = function(opIndex, numPrevRegisters, registers) {
|
||||
self.postMessage({
|
||||
action: "setRegisters",
|
||||
data: {
|
||||
opIndex: opIndex,
|
||||
numPrevRegisters: numPrevRegisters,
|
||||
registers: registers
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -90,6 +90,74 @@ const FlowControl = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Register operation.
|
||||
*
|
||||
* @param {Object} state - The current state of the recipe.
|
||||
* @param {number} state.progress - The current position in the recipe.
|
||||
* @param {Dish} state.dish - The Dish being operated on.
|
||||
* @param {Operation[]} state.opList - The list of operations in the recipe.
|
||||
* @returns {Object} The updated state of the recipe.
|
||||
*/
|
||||
runRegister: function(state) {
|
||||
const ings = state.opList[state.progress].getIngValues(),
|
||||
extractorStr = ings[0],
|
||||
i = ings[1],
|
||||
m = ings[2];
|
||||
|
||||
let modifiers = "";
|
||||
if (i) modifiers += "i";
|
||||
if (m) modifiers += "m";
|
||||
|
||||
const extractor = new RegExp(extractorStr, modifiers),
|
||||
input = state.dish.get(Dish.STRING),
|
||||
registers = input.match(extractor);
|
||||
|
||||
if (!registers) return state;
|
||||
|
||||
if (ENVIRONMENT_IS_WORKER()) {
|
||||
self.setRegisters(state.progress, state.numRegisters, registers.slice(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces references to registers (e.g. $R0) with the contents of those registers.
|
||||
*
|
||||
* @param {string} str
|
||||
* @returns {string}
|
||||
*/
|
||||
function replaceRegister(str) {
|
||||
// Replace references to registers ($Rn) with contents of registers
|
||||
return str.replace(/(\\*)\$R(\d{1,2})/g, (match, slashes, regNum) => {
|
||||
const index = parseInt(regNum, 10) + 1;
|
||||
if (index <= state.numRegisters || index >= state.numRegisters + registers.length)
|
||||
return match;
|
||||
if (slashes.length % 2 !== 0) return match.slice(1); // Remove escape
|
||||
return slashes + registers[index - state.numRegisters];
|
||||
});
|
||||
}
|
||||
|
||||
// Step through all subsequent ops and replace registers in args with extracted content
|
||||
for (let i = state.progress + 1; i < state.opList.length; i++) {
|
||||
if (state.opList[i].isDisabled()) continue;
|
||||
|
||||
let args = state.opList[i].getIngValues();
|
||||
args = args.map(arg => {
|
||||
if (typeof arg !== "string" && typeof arg !== "object") return arg;
|
||||
|
||||
if (typeof arg === "object" && arg.hasOwnProperty("string")) {
|
||||
arg.string = replaceRegister(arg.string);
|
||||
return arg;
|
||||
}
|
||||
return replaceRegister(arg);
|
||||
});
|
||||
state.opList[i].setIngValues(args);
|
||||
}
|
||||
|
||||
state.numRegisters += registers.length - 1;
|
||||
return state;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Jump operation.
|
||||
*
|
||||
@@ -102,18 +170,14 @@ const FlowControl = {
|
||||
*/
|
||||
runJump: function(state) {
|
||||
let ings = state.opList[state.progress].getIngValues(),
|
||||
jumpNum = ings[0],
|
||||
jmpIndex = FlowControl._getLabelIndex(ings[0], state),
|
||||
maxJumps = ings[1];
|
||||
|
||||
if (jumpNum < 0) {
|
||||
jumpNum--;
|
||||
}
|
||||
|
||||
if (state.numJumps >= maxJumps) {
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
return state;
|
||||
}
|
||||
|
||||
state.progress += jumpNum;
|
||||
state.progress = jmpIndex;
|
||||
state.numJumps++;
|
||||
return state;
|
||||
},
|
||||
@@ -133,20 +197,20 @@ const FlowControl = {
|
||||
let ings = state.opList[state.progress].getIngValues(),
|
||||
dish = state.dish,
|
||||
regexStr = ings[0],
|
||||
jumpNum = ings[1],
|
||||
maxJumps = ings[2];
|
||||
invert = ings[1],
|
||||
jmpIndex = FlowControl._getLabelIndex(ings[2], state),
|
||||
maxJumps = ings[3];
|
||||
|
||||
if (jumpNum < 0) {
|
||||
jumpNum--;
|
||||
}
|
||||
|
||||
if (state.numJumps >= maxJumps) {
|
||||
if (state.numJumps >= maxJumps || jmpIndex === -1) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (regexStr !== "" && dish.get(Dish.STRING).search(regexStr) > -1) {
|
||||
state.progress += jumpNum;
|
||||
state.numJumps++;
|
||||
if (regexStr !== "") {
|
||||
let strMatch = dish.get(Dish.STRING).search(regexStr) > -1;
|
||||
if (!invert && strMatch || invert && !strMatch) {
|
||||
state.progress = jmpIndex;
|
||||
state.numJumps++;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -181,6 +245,26 @@ const FlowControl = {
|
||||
return state;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index of a label.
|
||||
*
|
||||
* @param {Object} state
|
||||
* @param {string} name
|
||||
* @returns {number}
|
||||
*/
|
||||
_getLabelIndex: function(name, state) {
|
||||
for (let o = 0; o < state.opList.length; o++) {
|
||||
let operation = state.opList[o];
|
||||
if (operation.name === "Label"){
|
||||
let ings = operation.getIngValues();
|
||||
if (name === ings[0]) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
};
|
||||
|
||||
export default FlowControl;
|
||||
|
||||
@@ -145,7 +145,7 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
|
||||
*/
|
||||
Recipe.prototype.execute = async function(dish, startFrom) {
|
||||
startFrom = startFrom || 0;
|
||||
let op, input, output, numJumps = 0;
|
||||
let op, input, output, numJumps = 0, numRegisters = 0;
|
||||
|
||||
for (let i = startFrom; i < this.opList.length; i++) {
|
||||
op = this.opList[i];
|
||||
@@ -162,15 +162,17 @@ Recipe.prototype.execute = async function(dish, startFrom) {
|
||||
if (op.isFlowControl()) {
|
||||
// Package up the current state
|
||||
let state = {
|
||||
"progress": i,
|
||||
"dish": dish,
|
||||
"opList": this.opList,
|
||||
"numJumps": numJumps
|
||||
"progress": i,
|
||||
"dish": dish,
|
||||
"opList": this.opList,
|
||||
"numJumps": numJumps,
|
||||
"numRegisters": numRegisters
|
||||
};
|
||||
|
||||
state = await op.run(state);
|
||||
i = state.progress;
|
||||
numJumps = state.numJumps;
|
||||
numRegisters = state.numRegisters;
|
||||
} else {
|
||||
output = await op.run(input, op.getIngValues());
|
||||
dish.set(output, op.outputType);
|
||||
|
||||
@@ -409,7 +409,7 @@ const Utils = {
|
||||
* Utils.strToCharcode("你好");
|
||||
*/
|
||||
strToCharcode: function(str) {
|
||||
const charcode = new Array();
|
||||
const charcode = [];
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let ord = str.charCodeAt(i);
|
||||
@@ -859,7 +859,7 @@ const Utils = {
|
||||
*
|
||||
* fragment = *( pchar / "/" / "?" )
|
||||
* query = *( pchar / "/" / "?" )
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
|
||||
@@ -255,6 +255,9 @@ const Categories = [
|
||||
"Keccak",
|
||||
"Shake",
|
||||
"RIPEMD",
|
||||
"HAS-160",
|
||||
"Whirlpool",
|
||||
"Snefru",
|
||||
"HMAC",
|
||||
"Fletcher-8 Checksum",
|
||||
"Fletcher-16 Checksum",
|
||||
@@ -285,6 +288,7 @@ const Categories = [
|
||||
"XPath expression",
|
||||
"JPath expression",
|
||||
"CSS selector",
|
||||
"PHP Deserialize",
|
||||
"Microsoft Script Decoder",
|
||||
"Strip HTML tags",
|
||||
"Diff",
|
||||
@@ -298,8 +302,10 @@ const Categories = [
|
||||
ops: [
|
||||
"Entropy",
|
||||
"Frequency distribution",
|
||||
"Chi Square",
|
||||
"Detect File Type",
|
||||
"Scan for Embedded Files",
|
||||
"Disassemble x86",
|
||||
"Generate UUID",
|
||||
"Generate TOTP",
|
||||
"Generate HOTP",
|
||||
@@ -314,6 +320,8 @@ const Categories = [
|
||||
ops: [
|
||||
"Fork",
|
||||
"Merge",
|
||||
"Register",
|
||||
"Label",
|
||||
"Jump",
|
||||
"Conditional Jump",
|
||||
"Return",
|
||||
|
||||
@@ -5,7 +5,6 @@ import BCD from "../operations/BCD.js";
|
||||
import BitwiseOp from "../operations/BitwiseOp.js";
|
||||
import ByteRepr from "../operations/ByteRepr.js";
|
||||
import CharEnc from "../operations/CharEnc.js";
|
||||
import Checksum from "../operations/Checksum.js";
|
||||
import Cipher from "../operations/Cipher.js";
|
||||
import Code from "../operations/Code.js";
|
||||
import Compress from "../operations/Compress.js";
|
||||
@@ -26,21 +25,17 @@ import IP from "../operations/IP.js";
|
||||
import JS from "../operations/JS.js";
|
||||
import MAC from "../operations/MAC.js";
|
||||
import MorseCode from "../operations/MorseCode.js";
|
||||
import MS from "../operations/MS.js";
|
||||
import NetBIOS from "../operations/NetBIOS.js";
|
||||
import Numberwang from "../operations/Numberwang.js";
|
||||
import OS from "../operations/OS.js";
|
||||
import OTP from "../operations/OTP.js";
|
||||
import PHP from "../operations/PHP.js";
|
||||
import PublicKey from "../operations/PublicKey.js";
|
||||
import Punycode from "../operations/Punycode.js";
|
||||
import QuotedPrintable from "../operations/QuotedPrintable.js";
|
||||
import Rotate from "../operations/Rotate.js";
|
||||
import SeqUtils from "../operations/SeqUtils.js";
|
||||
import Shellcode from "../operations/Shellcode.js";
|
||||
import StrUtils from "../operations/StrUtils.js";
|
||||
import Tidy from "../operations/Tidy.js";
|
||||
import Unicode from "../operations/Unicode.js";
|
||||
import URL_ from "../operations/URL.js";
|
||||
import UUID from "../operations/UUID.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -116,17 +111,41 @@ const OperationConfig = {
|
||||
flowControl: true,
|
||||
args: []
|
||||
},
|
||||
"Jump": {
|
||||
"Register": {
|
||||
module: "Default",
|
||||
description: "Jump forwards or backwards over the specified number of operations.",
|
||||
description: "Extract data from the input and store it in registers which can then be passed into subsequent operations as arguments. Regular expression capture groups are used to select the data to extract.<br><br>To use registers in arguments, refer to them using the notation <code>$Rn</code> where n is the register number, starting at 0.<br><br>For example:<br>Input: <code>Test</code><br>Extractor: <code>(.*)</code><br>Argument: <code>$R0</code> becomes <code>Test</code><br><br>Registers can be escaped in arguments using a backslash. e.g. <code>\\$R0</code> would become <code>$R0</code> rather than <code>Test</code>.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
flowControl: true,
|
||||
args: [
|
||||
{
|
||||
name: "Number of operations to jump over",
|
||||
type: "number",
|
||||
value: 0
|
||||
name: "Extractor",
|
||||
type: "binaryString",
|
||||
value: "([\\s\\S]*)"
|
||||
},
|
||||
{
|
||||
name: "Case insensitive",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Multiline matching",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
]
|
||||
},
|
||||
"Jump": {
|
||||
module: "Default",
|
||||
description: "Jump forwards or backwards to the specified Label",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
flowControl: true,
|
||||
args: [
|
||||
{
|
||||
name: "Label name",
|
||||
type: "string",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Maximum jumps (if jumping backwards)",
|
||||
@@ -137,7 +156,7 @@ const OperationConfig = {
|
||||
},
|
||||
"Conditional Jump": {
|
||||
module: "Default",
|
||||
description: "Conditionally jump forwards or backwards over the specified number of operations based on whether the data matches the specified regular expression.",
|
||||
description: "Conditionally jump forwards or backwards to the specified Label based on whether the data matches the specified regular expression.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
flowControl: true,
|
||||
@@ -148,9 +167,14 @@ const OperationConfig = {
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Number of operations to jump over if match found",
|
||||
type: "number",
|
||||
value: 0
|
||||
name: "Invert match",
|
||||
type: "boolean",
|
||||
value: false
|
||||
},
|
||||
{
|
||||
name: "Label name",
|
||||
type: "shortString",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Maximum jumps (if jumping backwards)",
|
||||
@@ -159,6 +183,20 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"Label": {
|
||||
module: "Default",
|
||||
description: "Provides a location for conditional and fixed jumps to redirect execution to.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
flowControl: true,
|
||||
args: [
|
||||
{
|
||||
name: "Name",
|
||||
type: "shortString",
|
||||
value: ""
|
||||
}
|
||||
]
|
||||
},
|
||||
"Return": {
|
||||
module: "Default",
|
||||
description: "End execution of operations at this point in the recipe.",
|
||||
@@ -296,6 +334,44 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"Disassemble x86": {
|
||||
module: "Shellcode",
|
||||
description: "Disassembly is the process of translating machine language into assembly language.<br><br>This operation supports 64-bit, 32-bit and 16-bit code written for Intel or AMD x86 processors. It is particularly useful for reverse engineering shellcode.<br><br>Input should be in hexadecimal.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Bit mode",
|
||||
type: "option",
|
||||
value: Shellcode.MODE
|
||||
},
|
||||
{
|
||||
name: "Compatibility",
|
||||
type: "option",
|
||||
value: Shellcode.COMPATIBILITY
|
||||
},
|
||||
{
|
||||
name: "Code Segment (CS)",
|
||||
type: "number",
|
||||
value: 16
|
||||
},
|
||||
{
|
||||
name: "Offset (IP)",
|
||||
type: "number",
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
name: "Show instruction hex",
|
||||
type: "boolean",
|
||||
value: true
|
||||
},
|
||||
{
|
||||
name: "Show instruction position",
|
||||
type: "boolean",
|
||||
value: true
|
||||
}
|
||||
]
|
||||
},
|
||||
"XOR": {
|
||||
module: "Default",
|
||||
description: "XOR the input with the given key.<br>e.g. <code>fe023da5</code><br><br><strong>Options</strong><br><u>Null preserving:</u> If the current byte is 0x00 or the same as the key, skip it.<br><br><u>Scheme:</u><ul><li>Standard - key is unchanged after each round</li><li>Input differential - key is set to the value of the previous unprocessed byte</li><li>Output differential - key is set to the value of the previous processed byte</li></ul>",
|
||||
@@ -704,14 +780,14 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"URL Decode": {
|
||||
module: "Default",
|
||||
module: "URL",
|
||||
description: "Converts URI/URL percent-encoded characters back to their raw values.<br><br>e.g. <code>%3d</code> becomes <code>=</code>",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"URL Encode": {
|
||||
module: "Default",
|
||||
module: "URL",
|
||||
description: "Encodes problematic characters into percent-encoding, a format supported by URIs/URLs.<br><br>e.g. <code>=</code> becomes <code>%3d</code>",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -724,7 +800,7 @@ const OperationConfig = {
|
||||
]
|
||||
},
|
||||
"Parse URI": {
|
||||
module: "Default",
|
||||
module: "URL",
|
||||
description: "Pretty prints complicated Uniform Resource Identifier (URI) strings for ease of reading. Particularly useful for Uniform Resource Locators (URLs) with a lot of arguments.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
@@ -2991,6 +3067,44 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"HAS-160": {
|
||||
module: "Hashing",
|
||||
description: "HAS-160 is a cryptographic hash function designed for use with the Korean KCDSA digital signature algorithm. It is derived from SHA-1, with assorted changes intended to increase its security. It produces a 160-bit output.<br><br>HAS-160 is used in the same way as SHA-1. First it divides input in blocks of 512 bits each and pads the final block. A digest function updates the intermediate hash value by processing the input blocks in turn.<br><br>The message digest algorithm consists of 80 rounds.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: []
|
||||
},
|
||||
"Whirlpool": {
|
||||
module: "Hashing",
|
||||
description: "Whirlpool is a cryptographic hash function designed by Vincent Rijmen (co-creator of AES) and Paulo S. L. M. Barreto, who first described it in 2000.<br><br>Several variants exist:<ul><li>Whirlpool-0 is the original version released in 2000.</li><li>Whirlpool-T is the first revision, released in 2001, improving the generation of the s-box.</li><li>Wirlpool is the latest revision, released in 2003, fixing a flaw in the difusion matrix.</li></ul>",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Variant",
|
||||
type: "option",
|
||||
value: Hash.WHIRLPOOL_VARIANT
|
||||
}
|
||||
]
|
||||
},
|
||||
"Snefru": {
|
||||
module: "Hashing",
|
||||
description: "Snefru is a cryptographic hash function invented by Ralph Merkle in 1990 while working at Xerox PARC. The function supports 128-bit and 256-bit output. It was named after the Egyptian Pharaoh Sneferu, continuing the tradition of the Khufu and Khafre block ciphers.<br><br>The original design of Snefru was shown to be insecure by Eli Biham and Adi Shamir who were able to use differential cryptanalysis to find hash collisions. The design was then modified by increasing the number of iterations of the main pass of the algorithm from two to eight.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Rounds",
|
||||
type: "option",
|
||||
value: Hash.SNEFRU_ROUNDS
|
||||
},
|
||||
{
|
||||
name: "Size",
|
||||
type: "option",
|
||||
value: Hash.SNEFRU_SIZE
|
||||
}
|
||||
]
|
||||
},
|
||||
"HMAC": {
|
||||
module: "Hashing",
|
||||
description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.",
|
||||
@@ -3091,6 +3205,13 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"Chi Square": {
|
||||
module: "Default",
|
||||
description: "Calculates the Chi Square distribution of values.",
|
||||
inputType: "byteArray",
|
||||
outputType: "number",
|
||||
args: []
|
||||
},
|
||||
"Numberwang": {
|
||||
module: "Default",
|
||||
description: "Based on the popular gameshow by Mitchell and Webb.",
|
||||
@@ -3726,7 +3847,7 @@ const OperationConfig = {
|
||||
"Generate HOTP": {
|
||||
module: "Default",
|
||||
description: "The HMAC-based One-Time Password algorithm (HOTP) is an algorithm that computes a one-time password from a shared secret key and an incrementing counter. It has been adopted as Internet Engineering Task Force standard RFC 4226, is the cornerstone of Initiative For Open Authentication (OATH), and is used in a number of two-factor authentication systems.<br><br>Enter the secret as the input or leave it blank for a random secret to be generated.",
|
||||
inputType: "string",
|
||||
inputType: "byteArray",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
@@ -3751,6 +3872,19 @@ const OperationConfig = {
|
||||
}
|
||||
]
|
||||
},
|
||||
"PHP Deserialize": {
|
||||
module: "Default",
|
||||
description: "Deserializes PHP serialized data, outputting keyed arrays as JSON.<br><br>This function does not support <code>object</code> tags.<br><br>Example:<br><code>a:2:{s:1:"a";i:10;i:0;a:1:{s:2:"ab";b:1;}}</code><br>becomes<br><code>{"a": 10,0: {"ab": true}}</code><br><br><u>Output valid JSON:</u> JSON doesn't support integers as keys, whereas PHP serialization does. Enabling this will cast these integers to strings. This will also escape backslashes.",
|
||||
inputType: "string",
|
||||
outputType: "string",
|
||||
args: [
|
||||
{
|
||||
name: "Output valid JSON",
|
||||
type: "boolean",
|
||||
value: PHP.OUTPUT_VALID_JSON
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -3769,3 +3903,5 @@ function valExport() {
|
||||
}
|
||||
|
||||
export default valExport;
|
||||
|
||||
export { OperationConfig };
|
||||
|
||||
@@ -20,16 +20,15 @@ import NetBIOS from "../../operations/NetBIOS.js";
|
||||
import Numberwang from "../../operations/Numberwang.js";
|
||||
import OS from "../../operations/OS.js";
|
||||
import OTP from "../../operations/OTP.js";
|
||||
import PHP from "../../operations/PHP.js";
|
||||
import QuotedPrintable from "../../operations/QuotedPrintable.js";
|
||||
import Rotate from "../../operations/Rotate.js";
|
||||
import SeqUtils from "../../operations/SeqUtils.js";
|
||||
import StrUtils from "../../operations/StrUtils.js";
|
||||
import Tidy from "../../operations/Tidy.js";
|
||||
import Unicode from "../../operations/Unicode.js";
|
||||
import URL_ from "../../operations/URL.js";
|
||||
import UUID from "../../operations/UUID.js";
|
||||
|
||||
|
||||
/**
|
||||
* Default module.
|
||||
*
|
||||
@@ -40,6 +39,7 @@ import UUID from "../../operations/UUID.js";
|
||||
* - Utils.js
|
||||
* - CryptoJS
|
||||
* - otp
|
||||
* - crypto
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
@@ -77,9 +77,6 @@ OpModules.Default = {
|
||||
"From HTML Entity": HTML.runFromEntity,
|
||||
"Strip HTML tags": HTML.runStripTags,
|
||||
"Parse colour code": HTML.runParseColourCode,
|
||||
"URL Encode": URL_.runTo,
|
||||
"URL Decode": URL_.runFrom,
|
||||
"Parse URI": URL_.runParse,
|
||||
"Unescape Unicode Characters": Unicode.runUnescape,
|
||||
"To Quoted Printable": QuotedPrintable.runTo,
|
||||
"From Quoted Printable": QuotedPrintable.runFrom,
|
||||
@@ -146,6 +143,7 @@ OpModules.Default = {
|
||||
"Microsoft Script Decoder": MS.runDecodeScript,
|
||||
"Entropy": Entropy.runEntropy,
|
||||
"Frequency distribution": Entropy.runFreqDistrib,
|
||||
"Chi Square": Entropy.runChiSq,
|
||||
"Detect File Type": FileType.runDetect,
|
||||
"Scan for Embedded Files": FileType.runScanForEmbeddedFiles,
|
||||
"Generate UUID": UUID.runGenerateV4,
|
||||
@@ -154,10 +152,13 @@ OpModules.Default = {
|
||||
"Generate HOTP": OTP.runHOTP,
|
||||
"Fork": FlowControl.runFork,
|
||||
"Merge": FlowControl.runMerge,
|
||||
"Register": FlowControl.runRegister,
|
||||
"Label": FlowControl.runComment,
|
||||
"Jump": FlowControl.runJump,
|
||||
"Conditional Jump": FlowControl.runCondJump,
|
||||
"Return": FlowControl.runReturn,
|
||||
"Comment": FlowControl.runComment,
|
||||
"PHP Deserialize": PHP.runDeserialize,
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -31,6 +31,9 @@ OpModules.Hashing = {
|
||||
"Keccak": Hash.runKeccak,
|
||||
"Shake": Hash.runShake,
|
||||
"RIPEMD": Hash.runRIPEMD,
|
||||
"HAS-160": Hash.runHAS,
|
||||
"Whirlpool": Hash.runWhirlpool,
|
||||
"Snefru": Hash.runSnefru,
|
||||
"HMAC": Hash.runHMAC,
|
||||
"Fletcher-8 Checksum": Checksum.runFletcher8,
|
||||
"Fletcher-16 Checksum": Checksum.runFletcher16,
|
||||
|
||||
@@ -18,6 +18,8 @@ import HTTPModule from "./HTTP.js";
|
||||
import ImageModule from "./Image.js";
|
||||
import JSBNModule from "./JSBN.js";
|
||||
import PublicKeyModule from "./PublicKey.js";
|
||||
import ShellcodeModule from "./Shellcode.js";
|
||||
import URLModule from "./URL.js";
|
||||
|
||||
Object.assign(
|
||||
OpModules,
|
||||
@@ -31,7 +33,9 @@ Object.assign(
|
||||
HTTPModule,
|
||||
ImageModule,
|
||||
JSBNModule,
|
||||
PublicKeyModule
|
||||
PublicKeyModule,
|
||||
ShellcodeModule,
|
||||
URLModule
|
||||
);
|
||||
|
||||
export default OpModules;
|
||||
|
||||
20
src/core/config/modules/Shellcode.js
Normal file
20
src/core/config/modules/Shellcode.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import Shellcode from "../../operations/Shellcode.js";
|
||||
|
||||
|
||||
/**
|
||||
* Shellcode module.
|
||||
*
|
||||
* Libraries:
|
||||
* - DisassembleX86-64.js
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.Shellcode = {
|
||||
"Disassemble x86": Shellcode.runDisassemble,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
23
src/core/config/modules/URL.js
Normal file
23
src/core/config/modules/URL.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import URL_ from "../../operations/URL.js";
|
||||
|
||||
|
||||
/**
|
||||
* URL module.
|
||||
*
|
||||
* Libraries:
|
||||
* - Utils.js
|
||||
* - url
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
|
||||
|
||||
OpModules.URL = {
|
||||
"URL Encode": URL_.runTo,
|
||||
"URL Decode": URL_.runFrom,
|
||||
"Parse URI": URL_.runParse,
|
||||
};
|
||||
|
||||
export default OpModules;
|
||||
5722
src/core/lib/DisassembleX86-64.js
Normal file
5722
src/core/lib/DisassembleX86-64.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
||||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import cptable from "../lib/js-codepage/cptable.js";
|
||||
import Utils from "../Utils.js";
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,9 +2,10 @@ import {camelCase, kebabCase, snakeCase} from "lodash";
|
||||
|
||||
import Utils from "../Utils.js";
|
||||
import vkbeautify from "vkbeautify";
|
||||
import {DOMParser as dom} from "xmldom";
|
||||
import {DOMParser} from "xmldom";
|
||||
import xpath from "xpath";
|
||||
import jpath from "jsonpath";
|
||||
import nwmatcher from "nwmatcher";
|
||||
import prettyPrintOne from "imports-loader?window=>global!exports-loader?prettyPrintOne!google-code-prettify/bin/prettify.min.js";
|
||||
|
||||
|
||||
@@ -336,7 +337,7 @@ const Code = {
|
||||
|
||||
let doc;
|
||||
try {
|
||||
doc = new dom().parseFromString(input);
|
||||
doc = new DOMParser().parseFromString(input, "application/xml");
|
||||
} catch (err) {
|
||||
return "Invalid input XML.";
|
||||
}
|
||||
@@ -423,7 +424,7 @@ const Code = {
|
||||
let query = args[0],
|
||||
delimiter = args[1],
|
||||
parser = new DOMParser(),
|
||||
html,
|
||||
dom,
|
||||
result;
|
||||
|
||||
if (!query.length || !input.length) {
|
||||
@@ -431,32 +432,32 @@ const Code = {
|
||||
}
|
||||
|
||||
try {
|
||||
html = parser.parseFromString(input, "text/html");
|
||||
dom = parser.parseFromString(input);
|
||||
} catch (err) {
|
||||
return "Invalid input HTML.";
|
||||
}
|
||||
|
||||
try {
|
||||
result = html.querySelectorAll(query);
|
||||
const matcher = nwmatcher({document: dom});
|
||||
result = matcher.select(query, dom);
|
||||
} catch (err) {
|
||||
return "Invalid CSS Selector. Details:\n" + err.message;
|
||||
}
|
||||
|
||||
const nodeToString = function(node) {
|
||||
return node.toString();
|
||||
/* xmldom does not return the outerHTML value.
|
||||
switch (node.nodeType) {
|
||||
case Node.ELEMENT_NODE: return node.outerHTML;
|
||||
case Node.ATTRIBUTE_NODE: return node.value;
|
||||
case Node.COMMENT_NODE: return node.data;
|
||||
case Node.TEXT_NODE: return node.wholeText;
|
||||
case Node.DOCUMENT_NODE: return node.outerHTML;
|
||||
case node.ELEMENT_NODE: return node.outerHTML;
|
||||
case node.ATTRIBUTE_NODE: return node.value;
|
||||
case node.TEXT_NODE: return node.wholeText;
|
||||
case node.COMMENT_NODE: return node.data;
|
||||
case node.DOCUMENT_NODE: return node.outerHTML;
|
||||
default: throw new Error("Unknown Node Type: " + node.nodeType);
|
||||
}
|
||||
}*/
|
||||
};
|
||||
|
||||
return Array.apply(null, Array(result.length))
|
||||
.map(function(_, i) {
|
||||
return result[i];
|
||||
})
|
||||
return result
|
||||
.map(nodeToString)
|
||||
.join(delimiter);
|
||||
},
|
||||
|
||||
@@ -192,268 +192,270 @@ const DateTime = {
|
||||
/**
|
||||
* @constant
|
||||
*/
|
||||
FORMAT_EXAMPLES: "Format string tokens:\n\n\
|
||||
<table class='table table-striped table-hover table-condensed table-bordered' style='font-family: sans-serif'>\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<th>Category</th>\
|
||||
<th>Token</th>\
|
||||
<th>Output</th>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr>\
|
||||
<td><b>Month</b></td>\
|
||||
<td>M</td>\
|
||||
<td>1 2 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Mo</td>\
|
||||
<td>1st 2nd ... 11th 12th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MM</td>\
|
||||
<td>01 02 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MMM</td>\
|
||||
<td>Jan Feb ... Nov Dec</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>MMMM</td>\
|
||||
<td>January February ... November December</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Quarter</b></td>\
|
||||
<td>Q</td>\
|
||||
<td>1 2 3 4</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Month</b></td>\
|
||||
<td>D</td>\
|
||||
<td>1 2 ... 30 31</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Do</td>\
|
||||
<td>1st 2nd ... 30th 31st</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DD</td>\
|
||||
<td>01 02 ... 30 31</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Year</b></td>\
|
||||
<td>DDD</td>\
|
||||
<td>1 2 ... 364 365</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DDDo</td>\
|
||||
<td>1st 2nd ... 364th 365th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>DDDD</td>\
|
||||
<td>001 002 ... 364 365</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week</b></td>\
|
||||
<td>d</td>\
|
||||
<td>0 1 ... 5 6</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>do</td>\
|
||||
<td>0th 1st ... 5th 6th</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>dd</td>\
|
||||
<td>Su Mo ... Fr Sa</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ddd</td>\
|
||||
<td>Sun Mon ... Fri Sat</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>dddd</td>\
|
||||
<td>Sunday Monday ... Friday Saturday</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week (Locale)</b></td>\
|
||||
<td>e</td>\
|
||||
<td>0 1 ... 5 6</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Day of Week (ISO)</b></td>\
|
||||
<td>E</td>\
|
||||
<td>1 2 ... 6 7</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week of Year</b></td>\
|
||||
<td>w</td>\
|
||||
<td>1 2 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>wo</td>\
|
||||
<td>1st 2nd ... 52nd 53rd</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ww</td>\
|
||||
<td>01 02 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week of Year (ISO)</b></td>\
|
||||
<td>W</td>\
|
||||
<td>1 2 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Wo</td>\
|
||||
<td>1st 2nd ... 52nd 53rd</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>WW</td>\
|
||||
<td>01 02 ... 52 53</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Year</b></td>\
|
||||
<td>YY</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>YYYY</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week Year</b></td>\
|
||||
<td>gg</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>gggg</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Week Year (ISO)</b></td>\
|
||||
<td>GG</td>\
|
||||
<td>70 71 ... 29 30</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>GGGG</td>\
|
||||
<td>1970 1971 ... 2029 2030</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>AM/PM</b></td>\
|
||||
<td>A</td>\
|
||||
<td>AM PM</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>a</td>\
|
||||
<td>am pm</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Hour</b></td>\
|
||||
<td>H</td>\
|
||||
<td>0 1 ... 22 23</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>HH</td>\
|
||||
<td>00 01 ... 22 23</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>h</td>\
|
||||
<td>1 2 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>hh</td>\
|
||||
<td>01 02 ... 11 12</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Minute</b></td>\
|
||||
<td>m</td>\
|
||||
<td>0 1 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>mm</td>\
|
||||
<td>00 01 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Second</b></td>\
|
||||
<td>s</td>\
|
||||
<td>0 1 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ss</td>\
|
||||
<td>00 01 ... 58 59</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Fractional Second</b></td>\
|
||||
<td>S</td>\
|
||||
<td>0 1 ... 8 9</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SS</td>\
|
||||
<td>00 01 ... 98 99</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SSS</td>\
|
||||
<td>000 001 ... 998 999</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>SSSS ... SSSSSSSSS</td>\
|
||||
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Timezone</b></td>\
|
||||
<td>z or zz</td>\
|
||||
<td>EST CST ... MST PST</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>Z</td>\
|
||||
<td>-07:00 -06:00 ... +06:00 +07:00</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td></td>\
|
||||
<td>ZZ</td>\
|
||||
<td>-0700 -0600 ... +0600 +0700</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Unix Timestamp</b></td>\
|
||||
<td>X</td>\
|
||||
<td>1360013296</td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td><b>Unix Millisecond Timestamp</b></td>\
|
||||
<td>x</td>\
|
||||
<td>1360013296123</td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
</table>",
|
||||
FORMAT_EXAMPLES: `Format string tokens:
|
||||
|
||||
|
||||
<table class="table table-striped table-hover table-condensed table-bordered" style="font-family: sans-serif">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<th>Token</th>
|
||||
<th>Output</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>Month</b></td>
|
||||
<td>M</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Mo</td>
|
||||
<td>1st 2nd ... 11th 12th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MM</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMM</td>
|
||||
<td>Jan Feb ... Nov Dec</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMMM</td>
|
||||
<td>January February ... November December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Quarter</b></td>
|
||||
<td>Q</td>
|
||||
<td>1 2 3 4</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Month</b></td>
|
||||
<td>D</td>
|
||||
<td>1 2 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Do</td>
|
||||
<td>1st 2nd ... 30th 31st</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DD</td>
|
||||
<td>01 02 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Year</b></td>
|
||||
<td>DDD</td>
|
||||
<td>1 2 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDo</td>
|
||||
<td>1st 2nd ... 364th 365th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DDDD</td>
|
||||
<td>001 002 ... 364 365</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week</b></td>
|
||||
<td>d</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>do</td>
|
||||
<td>0th 1st ... 5th 6th</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dd</td>
|
||||
<td>Su Mo ... Fr Sa</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ddd</td>
|
||||
<td>Sun Mon ... Fri Sat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dddd</td>
|
||||
<td>Sunday Monday ... Friday Saturday</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (Locale)</b></td>
|
||||
<td>e</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week (ISO)</b></td>
|
||||
<td>E</td>
|
||||
<td>1 2 ... 6 7</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year</b></td>
|
||||
<td>w</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ww</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week of Year (ISO)</b></td>
|
||||
<td>W</td>
|
||||
<td>1 2 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Wo</td>
|
||||
<td>1st 2nd ... 52nd 53rd</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>WW</td>
|
||||
<td>01 02 ... 52 53</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Year</b></td>
|
||||
<td>YY</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>YYYY</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year</b></td>
|
||||
<td>gg</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>gggg</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Week Year (ISO)</b></td>
|
||||
<td>GG</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>GGGG</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>AM/PM</b></td>
|
||||
<td>A</td>
|
||||
<td>AM PM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>a</td>
|
||||
<td>am pm</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hour</b></td>
|
||||
<td>H</td>
|
||||
<td>0 1 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>HH</td>
|
||||
<td>00 01 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>h</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>hh</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Minute</b></td>
|
||||
<td>m</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>mm</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Second</b></td>
|
||||
<td>s</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ss</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Fractional Second</b></td>
|
||||
<td>S</td>
|
||||
<td>0 1 ... 8 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SS</td>
|
||||
<td>00 01 ... 98 99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSS</td>
|
||||
<td>000 001 ... 998 999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSSS ... SSSSSSSSS</td>
|
||||
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Timezone</b></td>
|
||||
<td>z or zz</td>
|
||||
<td>EST CST ... MST PST</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Z</td>
|
||||
<td>-07:00 -06:00 ... +06:00 +07:00</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ZZ</td>
|
||||
<td>-0700 -0600 ... +0600 +0700</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Timestamp</b></td>
|
||||
<td>X</td>
|
||||
<td>1360013296</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Unix Millisecond Timestamp</b></td>
|
||||
<td>x</td>
|
||||
<td>1360013296123</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -135,6 +135,31 @@ const Entropy = {
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Chi Square operation.
|
||||
*
|
||||
* @param {byteArray} data
|
||||
* @param {Object[]} args
|
||||
* @returns {number}
|
||||
*/
|
||||
runChiSq: function(input, args) {
|
||||
let distArray = new Array(256).fill(0),
|
||||
total = 0;
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
distArray[input[i]]++;
|
||||
}
|
||||
|
||||
for (let i = 0; i < distArray.length; i++) {
|
||||
if (distArray[i] > 0) {
|
||||
total += Math.pow(distArray[i] - input.length / 256, 2) / (input.length / 256);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Calculates the Shannon entropy for a given chunk of data.
|
||||
*
|
||||
|
||||
@@ -225,26 +225,26 @@ const HTML = {
|
||||
cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")";
|
||||
|
||||
// Generate output
|
||||
return "<div id='colorpicker' style='display: inline-block'></div>" +
|
||||
"Hex: " + hex + "\n" +
|
||||
"RGB: " + rgb + "\n" +
|
||||
"RGBA: " + rgba + "\n" +
|
||||
"HSL: " + hsl + "\n" +
|
||||
"HSLA: " + hsla + "\n" +
|
||||
"CMYK: " + cmyk +
|
||||
"<script>\
|
||||
$('#colorpicker').colorpicker({\
|
||||
format: 'rgba',\
|
||||
color: '" + rgba + "',\
|
||||
container: true,\
|
||||
inline: true,\
|
||||
}).on('changeColor', function(e) {\
|
||||
var color = e.color.toRGB();\
|
||||
document.getElementById('input-text').value = 'rgba(' +\
|
||||
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';\
|
||||
window.app.autoBake();\
|
||||
});\
|
||||
</script>";
|
||||
return `<div id="colorpicker" style="display: inline-block"></div>
|
||||
Hex: ${hex}
|
||||
RGB: ${rgb}
|
||||
RGBA: ${rgba}
|
||||
HSL: ${hsl}
|
||||
HSLA: ${hsla}
|
||||
CMYK: ${cmyk}
|
||||
<script>
|
||||
$('#colorpicker').colorpicker({
|
||||
format: 'rgba',
|
||||
color: '${rgba}',
|
||||
container: true,
|
||||
inline: true,
|
||||
}).on('changeColor', function(e) {
|
||||
var color = e.color.toRGB();
|
||||
document.getElementById('input-text').value = 'rgba(' +
|
||||
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';
|
||||
window.app.autoBake();
|
||||
});
|
||||
</script>`;
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,22 @@ import Checksum from "./Checksum.js";
|
||||
*/
|
||||
const Hash = {
|
||||
|
||||
/**
|
||||
* Generic hash function.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {string} input
|
||||
* @returns {string}
|
||||
*/
|
||||
runHash: function(name, input) {
|
||||
const hasher = CryptoApi.hasher(name);
|
||||
hasher.state.message = input;
|
||||
hasher.state.length += input.length;
|
||||
hasher.process();
|
||||
return hasher.finalize().stringify("hex");
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* MD2 operation.
|
||||
*
|
||||
@@ -24,7 +40,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD2: function (input, args) {
|
||||
return CryptoApi.hash("md2", input, {}).stringify("hex");
|
||||
return Hash.runHash("md2", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -36,7 +52,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD4: function (input, args) {
|
||||
return CryptoApi.hash("md4", input, {}).stringify("hex");
|
||||
return Hash.runHash("md4", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -48,7 +64,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runMD5: function (input, args) {
|
||||
return CryptoApi.hash("md5", input, {}).stringify("hex");
|
||||
return Hash.runHash("md5", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -92,7 +108,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA0: function (input, args) {
|
||||
return CryptoApi.hash("sha0", input, {}).stringify("hex");
|
||||
return Hash.runHash("sha0", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -104,7 +120,7 @@ const Hash = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runSHA1: function (input, args) {
|
||||
return CryptoApi.hash("sha1", input, {}).stringify("hex");
|
||||
return Hash.runHash("sha1", input);
|
||||
},
|
||||
|
||||
|
||||
@@ -123,7 +139,7 @@ const Hash = {
|
||||
*/
|
||||
runSHA2: function (input, args) {
|
||||
const size = args[0];
|
||||
return CryptoApi.hash("sha" + size, input, {}).stringify("hex");
|
||||
return Hash.runHash("sha" + size, input);
|
||||
},
|
||||
|
||||
|
||||
@@ -259,7 +275,63 @@ const Hash = {
|
||||
*/
|
||||
runRIPEMD: function (input, args) {
|
||||
const size = args[0];
|
||||
return CryptoApi.hash("ripemd" + size, input, {}).stringify("hex");
|
||||
return Hash.runHash("ripemd" + size, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* HAS-160 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runHAS: function (input, args) {
|
||||
return Hash.runHash("has160", input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
WHIRLPOOL_VARIANT: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"],
|
||||
|
||||
/**
|
||||
* Whirlpool operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runWhirlpool: function (input, args) {
|
||||
const variant = args[0].toLowerCase();
|
||||
return Hash.runHash(variant, input);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_ROUNDS: ["8", "4", "2"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
SNEFRU_SIZE: ["256", "128"],
|
||||
|
||||
/**
|
||||
* Snefru operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runSnefru: function (input, args) {
|
||||
const rounds = args[0],
|
||||
size = args[1];
|
||||
return Hash.runHash(`snefru-${rounds}-${size}`, input);
|
||||
},
|
||||
|
||||
|
||||
@@ -283,6 +355,10 @@ const Hash = {
|
||||
"RIPEMD160",
|
||||
"RIPEMD256",
|
||||
"RIPEMD320",
|
||||
"HAS160",
|
||||
"Whirlpool",
|
||||
"Whirlpool-0",
|
||||
"Whirlpool-T"
|
||||
],
|
||||
|
||||
/**
|
||||
@@ -335,6 +411,10 @@ const Hash = {
|
||||
"\nRIPEMD-160: " + Hash.runRIPEMD(input, ["160"]) +
|
||||
"\nRIPEMD-256: " + Hash.runRIPEMD(input, ["256"]) +
|
||||
"\nRIPEMD-320: " + Hash.runRIPEMD(input, ["320"]) +
|
||||
"\nHAS-160: " + Hash.runHAS(input, []) +
|
||||
"\nWhirlpool-0: " + Hash.runWhirlpool(input, ["Whirlpool-0"]) +
|
||||
"\nWhirlpool-T: " + Hash.runWhirlpool(input, ["Whirlpool-T"]) +
|
||||
"\nWhirlpool: " + Hash.runWhirlpool(input, ["Whirlpool"]) +
|
||||
"\n\nChecksums:" +
|
||||
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
|
||||
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* globals app */
|
||||
import Utils from "../Utils.js";
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Microsoft operations.
|
||||
* Microsoft operations.
|
||||
*
|
||||
* @author bmwhitn [brian.m.whitney@outlook.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
|
||||
@@ -26,9 +26,14 @@ const NetBIOS = {
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output.push((input[i] >> 4) + offset);
|
||||
output.push((input[i] & 0xf) + offset);
|
||||
if (input.length <= 16) {
|
||||
let len = input.length;
|
||||
input.length = 16;
|
||||
input.fill(32, len, 16);
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
output.push((input[i] >> 4) + offset);
|
||||
output.push((input[i] & 0xf) + offset);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
@@ -46,9 +51,15 @@ const NetBIOS = {
|
||||
let output = [],
|
||||
offset = args[0];
|
||||
|
||||
for (let i = 0; i < input.length; i += 2) {
|
||||
output.push(((input[i] - offset) << 4) |
|
||||
((input[i + 1] - offset) & 0xf));
|
||||
if (input.length <= 32 && (input.length % 2) === 0) {
|
||||
for (let i = 0; i < input.length; i += 2) {
|
||||
output.push((((input[i] & 0xff) - offset) << 4) |
|
||||
(((input[i + 1] & 0xff) - offset) & 0xf));
|
||||
}
|
||||
for (let i = output.length - 1; i > 0; i--) {
|
||||
if (output[i] === 32) output.splice(i, i);
|
||||
else break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
||||
@@ -14,16 +14,72 @@ const Numberwang = {
|
||||
* @returns {string}
|
||||
*/
|
||||
run: function(input, args) {
|
||||
if (!input) return "Let's play Wangernumb!";
|
||||
const match = input.match(/\d+/);
|
||||
if (match) {
|
||||
return match[0] + "! That's Numberwang!";
|
||||
let output;
|
||||
if (!input) {
|
||||
output = "Let's play Wangernumb!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
return "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
const match = input.match(/(f0rty-s1x|shinty-six|filth-hundred and neeb|-?√?\d+(\.\d+)?i?([a-z]?)%?)/i);
|
||||
if (match) {
|
||||
if (match[3]) output = match[0] + "! That's AlphaNumericWang!";
|
||||
else output = match[0] + "! That's Numberwang!";
|
||||
} else {
|
||||
// That's a bad miss!
|
||||
output = "Sorry, that's not Numberwang. Let's rotate the board!";
|
||||
}
|
||||
}
|
||||
|
||||
const rand = Math.floor(Math.random() * Numberwang._didYouKnow.length);
|
||||
return output + "\n\nDid you know: " + Numberwang._didYouKnow[rand];
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Taken from http://numberwang.wikia.com/wiki/Numberwang_Wikia
|
||||
*
|
||||
* @private
|
||||
* @constant
|
||||
*/
|
||||
_didYouKnow: [
|
||||
"Numberwang, contrary to popular belief, is a fruit and not a vegetable.",
|
||||
"Robert Webb once got WordWang while presenting an episode of Numberwang.",
|
||||
"The 6705th digit of pi is Numberwang.",
|
||||
"Numberwang was invented on a Sevenday.",
|
||||
"Contrary to popular belief, Albert Einstein always got good grades in Numberwang at school. He once scored ^4$ on a test.",
|
||||
"680 asteroids have been named after Numberwang.",
|
||||
"Archimedes is most famous for proclaiming \"That's Numberwang!\" during an epiphany about water displacement he had while taking a bath.",
|
||||
"Numberwang Day is celebrated in Japan on every day of the year apart from June 6.",
|
||||
"Biologists recently discovered Numberwang within a strand of human DNA.",
|
||||
"Numbernot is a special type of non-Numberwang number. It is divisible by 3 and the letter \"y\".",
|
||||
"Julie once got 612.04 Numberwangs in a single episode of Emmerdale.",
|
||||
"In India, it is traditional to shout out \"Numberwang!\" instead of checkmate during games of chess.",
|
||||
"There is a rule on Countdown which states that if you get Numberwang in the numbers round, you automatically win. It has only ever been invoked twice.",
|
||||
"\"Numberwang\" was the third-most common baby name for a brief period in 1722.",
|
||||
"\"The Lion King\" was loosely based on Numberwang.",
|
||||
"\"A Numberwang a day keeps the doctor away\" is how Donny Cosy, the oldest man in the world, explained how he was in such good health at the age of 136.",
|
||||
"The \"number lock\" button on a keyboard is based on the popular round of the same name in \"Numberwang\".",
|
||||
"Cambridge became the first university to offer a course in Numberwang in 1567.",
|
||||
"Schrödinger's Numberwang is a number that has been confusing dentists for centuries.",
|
||||
"\"Harry Potter and the Numberwang of Numberwang\" was rejected by publishers -41 times before it became a bestseller.",
|
||||
"\"Numberwang\" is the longest-running British game show in history; it has aired 226 seasons, each containing 19 episodes, which makes a grand total of 132 episodes.",
|
||||
"The triple Numberwang bonus was discovered by archaeologist Thomas Jefferson in Somerset.",
|
||||
"Numberwang is illegal in parts of Czechoslovakia.",
|
||||
"Numberwang was discovered in India in the 12th century.",
|
||||
"Numberwang has the chemical formula Zn4SO2(HgEs)3.",
|
||||
"The first pack of cards ever created featured two \"Numberwang\" cards instead of jokers.",
|
||||
"Julius Caesar was killed by an overdose of Numberwang.",
|
||||
"The most Numberwang musical note is G#.",
|
||||
"In 1934, the forty-third Google Doodle promoted the upcoming television show \"Numberwang on Ice\".",
|
||||
"A recent psychology study found that toddlers were 17% faster at identifying numbers which were Numberwang.",
|
||||
"There are 700 ways to commit a foul in the television show \"Numberwang\". All 700 of these fouls were committed by Julie in one single episode in 1473.",
|
||||
"Astronomers suspect God is Numberwang.",
|
||||
"Numberwang is the official beverage of Canada.",
|
||||
"In the pilot episode of \"The Price is Right\", if a contestant got the value of an item exactly right they were told \"That's Numberwang!\" and immediately won ₹5.7032.",
|
||||
"The first person to get three Numberwangs in a row was Madonna.",
|
||||
"\"Numberwang\" has the code U+46402 in Unicode.",
|
||||
"The musical note \"Numberwang\" is between D# and E♮.",
|
||||
"Numberwang was first played on the moon in 1834.",
|
||||
],
|
||||
|
||||
};
|
||||
|
||||
export default Numberwang;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import otp from "otp";
|
||||
import Base64 from "./Base64.js";
|
||||
|
||||
|
||||
/**
|
||||
* One-Time Password operations.
|
||||
*
|
||||
|
||||
160
src/core/operations/PHP.js
Normal file
160
src/core/operations/PHP.js
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* PHP operations.
|
||||
*
|
||||
* @author Jarmo van Lenthe [github.com/jarmovanlenthe]
|
||||
* @copyright Jarmo van Lenthe
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const PHP = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
OUTPUT_VALID_JSON: true,
|
||||
|
||||
/**
|
||||
* PHP Deserialize operation.
|
||||
*
|
||||
* This Javascript implementation is based on the Python implementation by
|
||||
* Armin Ronacher (2016), who released it under the 3-Clause BSD license.
|
||||
* See: https://github.com/mitsuhiko/phpserialize/
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDeserialize: function (input, args) {
|
||||
/**
|
||||
* Recursive method for deserializing.
|
||||
* @returns {*}
|
||||
*/
|
||||
function handleInput() {
|
||||
/**
|
||||
* Read `length` characters from the input, shifting them out the input.
|
||||
* @param length
|
||||
* @returns {string}
|
||||
*/
|
||||
function read(length) {
|
||||
let result = "";
|
||||
for (let idx = 0; idx < length; idx++) {
|
||||
let char = inputPart.shift();
|
||||
if (char === undefined) {
|
||||
throw "End of input reached before end of script";
|
||||
}
|
||||
result += char;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input until `until` is found.
|
||||
* @param until
|
||||
* @returns {string}
|
||||
*/
|
||||
function readUntil(until) {
|
||||
let result = "";
|
||||
for (;;) {
|
||||
let char = read(1);
|
||||
if (char === until) {
|
||||
break;
|
||||
} else {
|
||||
result += char;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read characters from the input that must be equal to `expect`
|
||||
* @param expect
|
||||
* @returns {string}
|
||||
*/
|
||||
function expect(expect) {
|
||||
let result = read(expect.length);
|
||||
if (result !== expect) {
|
||||
throw "Unexpected input found";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to handle deserialized arrays.
|
||||
* @returns {Array}
|
||||
*/
|
||||
function handleArray() {
|
||||
let items = parseInt(readUntil(":"), 10) * 2;
|
||||
expect("{");
|
||||
let result = [];
|
||||
let isKey = true;
|
||||
let lastItem = null;
|
||||
for (let idx = 0; idx < items; idx++) {
|
||||
let item = handleInput();
|
||||
if (isKey) {
|
||||
lastItem = item;
|
||||
isKey = false;
|
||||
} else {
|
||||
let numberCheck = lastItem.match(/[0-9]+/);
|
||||
if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) {
|
||||
result.push("\"" + lastItem + "\": " + item);
|
||||
} else {
|
||||
result.push(lastItem + ": " + item);
|
||||
}
|
||||
isKey = true;
|
||||
}
|
||||
}
|
||||
expect("}");
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
let kind = read(1).toLowerCase();
|
||||
|
||||
switch (kind) {
|
||||
case "n":
|
||||
expect(";");
|
||||
return "";
|
||||
|
||||
case "i":
|
||||
case "d":
|
||||
case "b": {
|
||||
expect(":");
|
||||
let data = readUntil(";");
|
||||
if (kind === "b") {
|
||||
return (parseInt(data, 10) !== 0);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
case "a":
|
||||
expect(":");
|
||||
return "{" + handleArray() + "}";
|
||||
|
||||
case "s": {
|
||||
expect(":");
|
||||
let length = readUntil(":");
|
||||
expect("\"");
|
||||
let value = read(length);
|
||||
expect("\";");
|
||||
if (args[0]) {
|
||||
return "\"" + value.replace(/"/g, "\\\"") + "\"";
|
||||
} else {
|
||||
return "\"" + value + "\"";
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
throw "Unknown type: " + kind;
|
||||
}
|
||||
}
|
||||
|
||||
let inputPart = input.split("");
|
||||
return handleInput();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
export default PHP;
|
||||
@@ -249,7 +249,7 @@ const SeqUtils = {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return a.localeCompare(b);
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
96
src/core/operations/Shellcode.js
Normal file
96
src/core/operations/Shellcode.js
Normal file
@@ -0,0 +1,96 @@
|
||||
import disassemble from "../lib/DisassembleX86-64.js";
|
||||
|
||||
|
||||
/**
|
||||
* Shellcode operations.
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
const Shellcode = {
|
||||
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
MODE: ["64", "32", "16"],
|
||||
/**
|
||||
* @constant
|
||||
* @default
|
||||
*/
|
||||
COMPATIBILITY: [
|
||||
"Full x86 architecture",
|
||||
"Knights Corner",
|
||||
"Larrabee",
|
||||
"Cyrix",
|
||||
"Geode",
|
||||
"Centaur",
|
||||
"X86/486"
|
||||
],
|
||||
|
||||
/**
|
||||
* Disassemble x86 operation.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
runDisassemble: function(input, args) {
|
||||
const mode = args[0],
|
||||
compatibility = args[1],
|
||||
codeSegment = args[2],
|
||||
offset = args[3],
|
||||
showInstructionHex = args[4],
|
||||
showInstructionPos = args[5];
|
||||
|
||||
switch (mode) {
|
||||
case "64":
|
||||
disassemble.setBitMode(2);
|
||||
break;
|
||||
case "32":
|
||||
disassemble.setBitMode(1);
|
||||
break;
|
||||
case "16":
|
||||
disassemble.setBitMode(0);
|
||||
break;
|
||||
default:
|
||||
throw "Invalid mode value";
|
||||
}
|
||||
|
||||
switch (compatibility) {
|
||||
case "Full x86 architecture":
|
||||
disassemble.CompatibilityMode(0);
|
||||
break;
|
||||
case "Knights Corner":
|
||||
disassemble.CompatibilityMode(1);
|
||||
break;
|
||||
case "Larrabee":
|
||||
disassemble.CompatibilityMode(2);
|
||||
break;
|
||||
case "Cyrix":
|
||||
disassemble.CompatibilityMode(3);
|
||||
break;
|
||||
case "Geode":
|
||||
disassemble.CompatibilityMode(4);
|
||||
break;
|
||||
case "Centaur":
|
||||
disassemble.CompatibilityMode(5);
|
||||
break;
|
||||
case "X86/486":
|
||||
disassemble.CompatibilityMode(6);
|
||||
break;
|
||||
}
|
||||
|
||||
disassemble.SetBasePosition(codeSegment + ":" + offset);
|
||||
disassemble.setShowInstructionHex(showInstructionHex);
|
||||
disassemble.setShowInstructionPos(showInstructionPos);
|
||||
disassemble.LoadBinCode(input.replace(/\s/g, ""));
|
||||
return disassemble.LDisassemble();
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
export default Shellcode;
|
||||
@@ -1,5 +1,6 @@
|
||||
/* globals unescape */
|
||||
import Utils from "../Utils.js";
|
||||
import url from "url";
|
||||
|
||||
|
||||
/**
|
||||
@@ -58,56 +59,36 @@ const URL_ = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runParse: function(input, args) {
|
||||
if (!document) {
|
||||
throw "This operation only works in a browser.";
|
||||
}
|
||||
const uri = url.parse(input, true);
|
||||
|
||||
const a = document.createElement("a");
|
||||
let output = "";
|
||||
|
||||
// Overwrite base href which will be the current CyberChef URL to reduce confusion.
|
||||
a.href = "http://example.com/";
|
||||
a.href = input;
|
||||
if (uri.protocol) output += "Protocol:\t" + uri.protocol + "\n";
|
||||
if (uri.auth) output += "Auth:\t\t" + uri.auth + "\n";
|
||||
if (uri.hostname) output += "Hostname:\t" + uri.hostname + "\n";
|
||||
if (uri.port) output += "Port:\t\t" + uri.port + "\n";
|
||||
if (uri.pathname) output += "Path name:\t" + uri.pathname + "\n";
|
||||
if (uri.query) {
|
||||
let keys = Object.keys(uri.query),
|
||||
padding = 0;
|
||||
|
||||
if (a.protocol) {
|
||||
let output = "";
|
||||
if (a.hostname !== window.location.hostname) {
|
||||
output = "Protocol:\t" + a.protocol + "\n";
|
||||
if (a.hostname) output += "Hostname:\t" + a.hostname + "\n";
|
||||
if (a.port) output += "Port:\t\t" + a.port + "\n";
|
||||
}
|
||||
keys.forEach(k => {
|
||||
padding = (k.length > padding) ? k.length : padding;
|
||||
});
|
||||
|
||||
if (a.pathname && a.pathname !== window.location.pathname) {
|
||||
let pathname = a.pathname;
|
||||
if (pathname.indexOf(window.location.pathname) === 0)
|
||||
pathname = pathname.replace(window.location.pathname, "");
|
||||
if (pathname)
|
||||
output += "Path name:\t" + pathname + "\n";
|
||||
}
|
||||
|
||||
if (a.hash && a.hash !== window.location.hash) {
|
||||
output += "Hash:\t\t" + a.hash + "\n";
|
||||
}
|
||||
|
||||
if (a.search && a.search !== window.location.search) {
|
||||
output += "Arguments:\n";
|
||||
const args_ = (a.search.slice(1, a.search.length)).split("&");
|
||||
let splitArgs = [], padding = 0, i;
|
||||
for (i = 0; i < args_.length; i++) {
|
||||
splitArgs.push(args_[i].split("="));
|
||||
padding = (splitArgs[i][0].length > padding) ? splitArgs[i][0].length : padding;
|
||||
}
|
||||
for (i = 0; i < splitArgs.length; i++) {
|
||||
output += "\t" + Utils.padRight(splitArgs[i][0], padding);
|
||||
if (splitArgs[i].length > 1 && splitArgs[i][1].length)
|
||||
output += " = " + splitArgs[i][1] + "\n";
|
||||
else output += "\n";
|
||||
output += "Arguments:\n";
|
||||
for (let key in uri.query) {
|
||||
output += "\t" + Utils.padRight(key, padding);
|
||||
if (uri.query[key].length) {
|
||||
output += " = " + uri.query[key] + "\n";
|
||||
} else {
|
||||
output += "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
if (uri.hash) output += "Hash:\t\t" + uri.hash + "\n";
|
||||
|
||||
return "Invalid URI";
|
||||
return output;
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import crypto from "crypto";
|
||||
|
||||
|
||||
/**
|
||||
* UUID operations.
|
||||
*
|
||||
@@ -17,25 +20,17 @@ const UUID = {
|
||||
* @returns {string}
|
||||
*/
|
||||
runGenerateV4: function(input, args) {
|
||||
if (window && typeof(window.crypto) !== "undefined" && typeof(window.crypto.getRandomValues) !== "undefined") {
|
||||
let buf = new Uint32Array(4),
|
||||
i = 0;
|
||||
window.crypto.getRandomValues(buf);
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
let r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
} else {
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
let r = Math.random() * 16 | 0,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
const buf = new Uint32Array(4).map(() => {
|
||||
return crypto.randomBytes(4).readUInt32BE(0, true);
|
||||
});
|
||||
let i = 0;
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
|
||||
let r = (buf[i >> 3] >> ((i % 8) * 4)) & 0xf,
|
||||
v = c === "x" ? r : (r & 0x3 | 0x8);
|
||||
i++;
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default UUID;
|
||||
|
||||
@@ -9,7 +9,7 @@ require("babel-polyfill");
|
||||
|
||||
const Chef = require("../core/Chef.js").default;
|
||||
|
||||
const CyberChef = module.exports = {
|
||||
const CyberChef = {
|
||||
|
||||
bake: function(input, recipeConfig) {
|
||||
this.chef = new Chef();
|
||||
@@ -23,3 +23,5 @@ const CyberChef = module.exports = {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
module.exports = CyberChef;
|
||||
|
||||
@@ -88,9 +88,10 @@ App.prototype.loaded = function() {
|
||||
* An error handler for displaying the error to the user.
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {boolean} [logToConsole=false]
|
||||
*/
|
||||
App.prototype.handleError = function(err) {
|
||||
console.error(err);
|
||||
App.prototype.handleError = function(err, logToConsole) {
|
||||
if (logToConsole) console.error(err);
|
||||
const msg = err.displayStr || err.toString();
|
||||
this.alert(msg, "danger", this.options.errorTimeout, !this.options.showErrors);
|
||||
};
|
||||
@@ -122,7 +123,12 @@ App.prototype.bake = function(step) {
|
||||
* Runs Auto Bake if it is set.
|
||||
*/
|
||||
App.prototype.autoBake = function() {
|
||||
if (this.autoBake_ && !this.autoBakePause && !this.baking) {
|
||||
// If autoBakePause is set, we are loading a full recipe (and potentially input), so there is no
|
||||
// need to set the staleness indicator. Just exit and wait until auto bake is called after loading
|
||||
// has completed.
|
||||
if (this.autoBakePause) return false;
|
||||
|
||||
if (this.autoBake_ && !this.baking) {
|
||||
this.bake();
|
||||
} else {
|
||||
this.manager.controls.showStaleIndicator();
|
||||
@@ -240,7 +246,7 @@ App.prototype.initialiseSplitter = function() {
|
||||
App.prototype.loadLocalStorage = function() {
|
||||
// Load options
|
||||
let lOptions;
|
||||
if (localStorage.options !== undefined) {
|
||||
if (this.isLocalStorageAvailable() && localStorage.options !== undefined) {
|
||||
lOptions = JSON.parse(localStorage.options);
|
||||
}
|
||||
this.manager.options.load(lOptions);
|
||||
@@ -256,13 +262,17 @@ App.prototype.loadLocalStorage = function() {
|
||||
* If the user currently has no saved favourites, the defaults from the view constructor are used.
|
||||
*/
|
||||
App.prototype.loadFavourites = function() {
|
||||
let favourites = localStorage.favourites &&
|
||||
localStorage.favourites.length > 2 ?
|
||||
JSON.parse(localStorage.favourites) :
|
||||
this.dfavourites;
|
||||
let favourites;
|
||||
|
||||
favourites = this.validFavourites(favourites);
|
||||
this.saveFavourites(favourites);
|
||||
if (this.isLocalStorageAvailable()) {
|
||||
favourites = localStorage.favourites && localStorage.favourites.length > 2 ?
|
||||
JSON.parse(localStorage.favourites) :
|
||||
this.dfavourites;
|
||||
favourites = this.validFavourites(favourites);
|
||||
this.saveFavourites(favourites);
|
||||
} else {
|
||||
favourites = this.dfavourites;
|
||||
}
|
||||
|
||||
const favCat = this.categories.filter(function(c) {
|
||||
return c.name === "Favourites";
|
||||
@@ -306,6 +316,15 @@ App.prototype.validFavourites = function(favourites) {
|
||||
* @param {string[]} favourites - A list of the user's favourite operations
|
||||
*/
|
||||
App.prototype.saveFavourites = function(favourites) {
|
||||
if (!this.isLocalStorageAvailable()) {
|
||||
this.alert(
|
||||
"Your security settings do not allow access to local storage so your favourites cannot be saved.",
|
||||
"danger",
|
||||
5000
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
localStorage.setItem("favourites", JSON.stringify(this.validFavourites(favourites)));
|
||||
};
|
||||
|
||||
@@ -356,10 +375,6 @@ App.prototype.loadURIParams = function() {
|
||||
window.location.hash;
|
||||
this.uriParams = Utils.parseURIParams(params);
|
||||
|
||||
// Pause auto-bake while loading but don't modify `this.autoBake_`
|
||||
// otherwise `manualBake` cannot trigger.
|
||||
this.autoBakePause = true;
|
||||
|
||||
// Read in recipe from URI params
|
||||
if (this.uriParams.recipe) {
|
||||
try {
|
||||
@@ -388,14 +403,16 @@ App.prototype.loadURIParams = function() {
|
||||
|
||||
// Read in input data from URI params
|
||||
if (this.uriParams.input) {
|
||||
this.autoBakePause = true;
|
||||
try {
|
||||
const inputData = Utils.fromBase64(this.uriParams.input);
|
||||
this.setInput(inputData);
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
} finally {
|
||||
this.autoBakePause = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Unpause auto-bake
|
||||
this.autoBakePause = false;
|
||||
this.autoBake();
|
||||
};
|
||||
|
||||
@@ -428,6 +445,10 @@ App.prototype.getRecipeConfig = function() {
|
||||
App.prototype.setRecipeConfig = function(recipeConfig) {
|
||||
document.getElementById("rec-list").innerHTML = null;
|
||||
|
||||
// Pause auto-bake while loading but don't modify `this.autoBake_`
|
||||
// otherwise `manualBake` cannot trigger.
|
||||
this.autoBakePause = true;
|
||||
|
||||
for (let i = 0; i < recipeConfig.length; i++) {
|
||||
const item = this.manager.recipe.addOperation(recipeConfig[i].op);
|
||||
|
||||
@@ -460,6 +481,9 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
|
||||
|
||||
this.progress = 0;
|
||||
}
|
||||
|
||||
// Unpause auto bake
|
||||
this.autoBakePause = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -503,6 +527,22 @@ App.prototype.setCompileMessage = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether the browser supports Local Storage and if it is accessible.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
App.prototype.isLocalStorageAvailable = function() {
|
||||
try {
|
||||
if (!localStorage) return false;
|
||||
return true;
|
||||
} catch (err) {
|
||||
// Access to LocalStorage is denied
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Pops up a message to the user and writes it to the console log.
|
||||
*
|
||||
|
||||
217
src/web/BindingsWaiter.js
Normal file
217
src/web/BindingsWaiter.js
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* Waiter to handle keybindings to CyberChef functions (i.e. Bake, Step, Save, Load etc.)
|
||||
*
|
||||
* @author Matt C [matt@artemisbot.uk]
|
||||
* @copyright Crown Copyright 2016
|
||||
* @license Apache-2.0
|
||||
*
|
||||
* @constructor
|
||||
* @param {App} app - The main view object for CyberChef.
|
||||
* @param {Manager} manager - The CyberChef event manager.
|
||||
*/
|
||||
const BindingsWaiter = function (app, manager) {
|
||||
this.app = app;
|
||||
this.manager = manager;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for all keydown events
|
||||
* Checks whether valid keyboard shortcut has been instated
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
* @param {event} e
|
||||
*/
|
||||
BindingsWaiter.prototype.parseInput = function(e) {
|
||||
const modKey = this.app.options.useMetaKey ? e.metaKey : e.altKey;
|
||||
|
||||
if (e.ctrlKey && modKey) {
|
||||
let elem;
|
||||
switch (e.code) {
|
||||
case "KeyF": // Focus search
|
||||
e.preventDefault();
|
||||
document.getElementById("search").focus();
|
||||
break;
|
||||
case "KeyI": // Focus input
|
||||
e.preventDefault();
|
||||
document.getElementById("input-text").focus();
|
||||
break;
|
||||
case "KeyO": // Focus output
|
||||
e.preventDefault();
|
||||
document.getElementById("output-text").focus();
|
||||
break;
|
||||
case "Period": // Focus next operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation") || document.querySelector("#rec-list .operation");
|
||||
if (elem.parentNode.lastChild === elem) {
|
||||
// If operation is last in recipe, loop around to the top operation's first argument
|
||||
elem.parentNode.firstChild.querySelectorAll(".arg")[0].focus();
|
||||
} else {
|
||||
// Focus first argument of next operation
|
||||
elem.nextSibling.querySelectorAll(".arg")[0].focus();
|
||||
}
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "KeyB": // Set breakpoint
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation").querySelectorAll(".breakpoint")[0];
|
||||
if (elem.getAttribute("break") === "false") {
|
||||
elem.setAttribute("break", "true"); // add break point if not already enabled
|
||||
elem.classList.add("breakpoint-selected");
|
||||
} else {
|
||||
elem.setAttribute("break", "false"); // remove break point if already enabled
|
||||
elem.classList.remove("breakpoint-selected");
|
||||
}
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "KeyD": // Disable operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
elem = document.activeElement.closest(".operation").querySelectorAll(".disable-icon")[0];
|
||||
if (elem.getAttribute("disabled") === "false") {
|
||||
elem.setAttribute("disabled", "true"); // disable operation if enabled
|
||||
elem.classList.add("disable-elem-selected");
|
||||
elem.parentNode.parentNode.classList.add("disabled");
|
||||
} else {
|
||||
elem.setAttribute("disabled", "false"); // enable operation if disabled
|
||||
elem.classList.remove("disable-elem-selected");
|
||||
elem.parentNode.parentNode.classList.remove("disabled");
|
||||
}
|
||||
this.app.progress = 0;
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
break;
|
||||
case "Space": // Bake
|
||||
e.preventDefault();
|
||||
this.app.bake();
|
||||
break;
|
||||
case "Quote": // Step through
|
||||
e.preventDefault();
|
||||
this.app.bake(true);
|
||||
break;
|
||||
case "KeyC": // Clear recipe
|
||||
e.preventDefault();
|
||||
this.manager.recipe.clearRecipe();
|
||||
break;
|
||||
case "KeyS": // Save output to file
|
||||
e.preventDefault();
|
||||
this.manager.output.saveClick();
|
||||
break;
|
||||
case "KeyL": // Load recipe
|
||||
e.preventDefault();
|
||||
this.manager.controls.loadClick();
|
||||
break;
|
||||
case "KeyM": // Switch input and output
|
||||
e.preventDefault();
|
||||
this.manager.output.switchClick();
|
||||
break;
|
||||
default:
|
||||
if (e.code.match(/Digit[0-9]/g)) { // Select nth operation
|
||||
e.preventDefault();
|
||||
try {
|
||||
// Select the first argument of the operation corresponding to the number pressed
|
||||
document.querySelector(`li:nth-child(${e.code.substr(-1)}) .arg`).focus();
|
||||
} catch (e) {
|
||||
// do nothing, just don't throw an error
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Updates keybinding list when metaKey option is toggled
|
||||
*
|
||||
*/
|
||||
BindingsWaiter.prototype.updateKeybList = function() {
|
||||
let modWinLin = "Alt";
|
||||
let modMac = "Opt";
|
||||
if (this.app.options.useMetaKey) {
|
||||
modWinLin = "Win";
|
||||
modMac = "Cmd";
|
||||
}
|
||||
document.getElementById("keybList").innerHTML = `
|
||||
<tr>
|
||||
<td><b>Command</b></td>
|
||||
<td><b>Shortcut (Win/Linux)</b></td>
|
||||
<td><b>Shortcut (Mac)</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in search field</td>
|
||||
<td>Ctrl+${modWinLin}+f</td>
|
||||
<td>Ctrl+${modMac}+f</td>
|
||||
<tr>
|
||||
<td>Place cursor in input box</td>
|
||||
<td>Ctrl+${modWinLin}+i</td>
|
||||
<td>Ctrl+${modMac}+i</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in output box</td>
|
||||
<td>Ctrl+${modWinLin}+o</td>
|
||||
<td>Ctrl+${modMac}+o</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in first argument field of the next operation in the recipe</td>
|
||||
<td>Ctrl+${modWinLin}+.</td>
|
||||
<td>Ctrl+${modMac}+.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Place cursor in first argument field of the nth operation in the recipe</td>
|
||||
<td>Ctrl+${modWinLin}+[1-9]</td>
|
||||
<td>Ctrl+${modMac}+[1-9]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Disable current operation</td>
|
||||
<td>Ctrl+${modWinLin}+d</td>
|
||||
<td>Ctrl+${modMac}+d</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Set/clear breakpoint</td>
|
||||
<td>Ctrl+${modWinLin}+b</td>
|
||||
<td>Ctrl+${modMac}+b</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bake</td>
|
||||
<td>Ctrl+${modWinLin}+Space</td>
|
||||
<td>Ctrl+${modMac}+Space</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Step</td>
|
||||
<td>Ctrl+${modWinLin}+'</td>
|
||||
<td>Ctrl+${modMac}+'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Clear recipe</td>
|
||||
<td>Ctrl+${modWinLin}+c</td>
|
||||
<td>Ctrl+${modMac}+c</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Save to file</td>
|
||||
<td>Ctrl+${modWinLin}+s</td>
|
||||
<td>Ctrl+${modMac}+s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Load recipe</td>
|
||||
<td>Ctrl+${modWinLin}+l</td>
|
||||
<td>Ctrl+${modMac}+l</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Move output to input</td>
|
||||
<td>Ctrl+${modWinLin}+m</td>
|
||||
<td>Ctrl+${modMac}+m</td>
|
||||
</tr>
|
||||
`;
|
||||
};
|
||||
|
||||
export default BindingsWaiter;
|
||||
@@ -254,6 +254,15 @@ ControlsWaiter.prototype.loadClick = function() {
|
||||
* Saves the recipe specified in the save textarea to local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.saveButtonClick = function() {
|
||||
if (!this.app.isLocalStorageAvailable()) {
|
||||
this.app.alert(
|
||||
"Your security settings do not allow access to local storage so your recipe cannot be saved.",
|
||||
"danger",
|
||||
5000
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
|
||||
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
|
||||
|
||||
@@ -283,6 +292,8 @@ ControlsWaiter.prototype.saveButtonClick = function() {
|
||||
* Populates the list of saved recipes in the load dialog box from local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.populateLoadRecipesList = function() {
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
const loadNameEl = document.getElementById("load-name");
|
||||
|
||||
// Remove current recipes from select
|
||||
@@ -313,6 +324,8 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
|
||||
* Removes the currently selected recipe from local storage.
|
||||
*/
|
||||
ControlsWaiter.prototype.loadDeleteClick = function() {
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
const id = parseInt(document.getElementById("load-name").value, 10);
|
||||
const rawSavedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
@@ -328,6 +341,8 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
|
||||
* Displays the selected recipe in the load text box.
|
||||
*/
|
||||
ControlsWaiter.prototype.loadNameChange = function(e) {
|
||||
if (!this.app.isLocalStorageAvailable()) return false;
|
||||
|
||||
const el = e.target;
|
||||
const savedRecipes = localStorage.savedRecipes ?
|
||||
JSON.parse(localStorage.savedRecipes) : [];
|
||||
@@ -346,6 +361,7 @@ ControlsWaiter.prototype.loadButtonClick = function() {
|
||||
try {
|
||||
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
|
||||
this.app.setRecipeConfig(recipeConfig);
|
||||
this.app.autoBake();
|
||||
|
||||
$("#rec-list [data-toggle=popover]").popover();
|
||||
} catch (e) {
|
||||
|
||||
@@ -158,13 +158,11 @@ InputWaiter.prototype.inputDrop = function(e) {
|
||||
const CHUNK_SIZE = 20480; // 20KB
|
||||
|
||||
const setInput = function() {
|
||||
this.app.autoBakePause = true;
|
||||
const recipeConfig = this.app.getRecipeConfig();
|
||||
if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") {
|
||||
recipeConfig.unshift({op: "From Hex", args: ["Space"]});
|
||||
this.app.setRecipeConfig(recipeConfig);
|
||||
}
|
||||
this.app.autoBakePause = false;
|
||||
|
||||
this.set(inputCharcode);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import OutputWaiter from "./OutputWaiter.js";
|
||||
import OptionsWaiter from "./OptionsWaiter.js";
|
||||
import HighlighterWaiter from "./HighlighterWaiter.js";
|
||||
import SeasonalWaiter from "./SeasonalWaiter.js";
|
||||
import BindingsWaiter from "./BindingsWaiter.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -60,6 +61,7 @@ const Manager = function(app) {
|
||||
this.options = new OptionsWaiter(this.app);
|
||||
this.highlighter = new HighlighterWaiter(this.app, this);
|
||||
this.seasonal = new SeasonalWaiter(this.app, this);
|
||||
this.bindings = new BindingsWaiter(this.app, this);
|
||||
|
||||
// Object to store dynamic handlers to fire on elements that may not exist yet
|
||||
this.dynamicHandlers = {};
|
||||
@@ -75,6 +77,7 @@ Manager.prototype.setup = function() {
|
||||
this.worker.registerChefWorker();
|
||||
this.recipe.initialiseOperationDragNDrop();
|
||||
this.controls.autoBakeChange();
|
||||
this.bindings.updateKeybList();
|
||||
this.seasonal.load();
|
||||
};
|
||||
|
||||
@@ -119,9 +122,8 @@ Manager.prototype.initialiseEventListeners = function() {
|
||||
this.addDynamicListener("li.operation", "operationadd", this.recipe.opAdd.bind(this.recipe));
|
||||
|
||||
// Recipe
|
||||
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg", "change", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg", "input", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg:not(select)", "input", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".arg[type=checkbox], .arg[type=radio], select.arg", "change", this.recipe.ingChange, this.recipe);
|
||||
this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe);
|
||||
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
|
||||
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);
|
||||
@@ -143,6 +145,7 @@ Manager.prototype.initialiseEventListeners = function() {
|
||||
|
||||
// Output
|
||||
document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
|
||||
document.getElementById("copy-output").addEventListener("click", this.output.copyClick.bind(this.output));
|
||||
document.getElementById("switch").addEventListener("click", this.output.switchClick.bind(this.output));
|
||||
document.getElementById("undo-switch").addEventListener("click", this.output.undoSwitchClick.bind(this.output));
|
||||
document.getElementById("maximise-output").addEventListener("click", this.output.maximiseOutputClick.bind(this.output));
|
||||
@@ -160,12 +163,14 @@ Manager.prototype.initialiseEventListeners = function() {
|
||||
document.getElementById("reset-options").addEventListener("click", this.options.resetOptionsClick.bind(this.options));
|
||||
$(document).on("switchChange.bootstrapSwitch", ".option-item input:checkbox", this.options.switchChange.bind(this.options));
|
||||
$(document).on("switchChange.bootstrapSwitch", ".option-item input:checkbox", this.options.setWordWrap.bind(this.options));
|
||||
$(document).on("switchChange.bootstrapSwitch", ".option-item input:checkbox#useMetaKey", this.bindings.updateKeybList.bind(this.bindings));
|
||||
this.addDynamicListener(".option-item input[type=number]", "keyup", this.options.numberChange, this.options);
|
||||
this.addDynamicListener(".option-item input[type=number]", "change", this.options.numberChange, this.options);
|
||||
this.addDynamicListener(".option-item select", "change", this.options.selectChange, this.options);
|
||||
document.getElementById("theme").addEventListener("change", this.options.themeChange.bind(this.options));
|
||||
|
||||
// Misc
|
||||
window.addEventListener("keydown", this.bindings.parseInput.bind(this.bindings));
|
||||
document.getElementById("alert-close").addEventListener("click", this.app.alertCloseClick.bind(this.app));
|
||||
};
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ OperationsWaiter.prototype.editFavouritesClick = function(e) {
|
||||
filter: ".remove-icon",
|
||||
onFilter: function (evt) {
|
||||
const el = editableList.closest(evt.item);
|
||||
if (el) {
|
||||
if (el && el.parentNode) {
|
||||
$(el).popover("destroy");
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
|
||||
@@ -87,7 +87,9 @@ OptionsWaiter.prototype.switchChange = function(e, state) {
|
||||
const option = el.getAttribute("option");
|
||||
|
||||
this.app.options[option] = state;
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
|
||||
if (this.app.isLocalStorageAvailable())
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
};
|
||||
|
||||
|
||||
@@ -102,7 +104,9 @@ OptionsWaiter.prototype.numberChange = function(e) {
|
||||
const option = el.getAttribute("option");
|
||||
|
||||
this.app.options[option] = parseInt(el.value, 10);
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
|
||||
if (this.app.isLocalStorageAvailable())
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
};
|
||||
|
||||
|
||||
@@ -117,7 +121,9 @@ OptionsWaiter.prototype.selectChange = function(e) {
|
||||
const option = el.getAttribute("option");
|
||||
|
||||
this.app.options[option] = el.value;
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
|
||||
if (this.app.isLocalStorageAvailable())
|
||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -105,17 +105,20 @@ OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) {
|
||||
OutputWaiter.prototype.adjustWidth = function() {
|
||||
const output = document.getElementById("output");
|
||||
const saveToFile = document.getElementById("save-to-file");
|
||||
const copyOutput = document.getElementById("copy-output");
|
||||
const switchIO = document.getElementById("switch");
|
||||
const undoSwitch = document.getElementById("undo-switch");
|
||||
const maximiseOutput = document.getElementById("maximise-output");
|
||||
|
||||
if (output.clientWidth < 680) {
|
||||
saveToFile.childNodes[1].nodeValue = "";
|
||||
copyOutput.childNodes[1].nodeValue = "";
|
||||
switchIO.childNodes[1].nodeValue = "";
|
||||
undoSwitch.childNodes[1].nodeValue = "";
|
||||
maximiseOutput.childNodes[1].nodeValue = "";
|
||||
} else {
|
||||
saveToFile.childNodes[1].nodeValue = " Save to file";
|
||||
copyOutput.childNodes[1].nodeValue = " Copy output";
|
||||
switchIO.childNodes[1].nodeValue = " Move output to input";
|
||||
undoSwitch.childNodes[1].nodeValue = " Undo";
|
||||
maximiseOutput.childNodes[1].nodeValue =
|
||||
@@ -147,6 +150,44 @@ OutputWaiter.prototype.saveClick = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for copy click events.
|
||||
* Copies the output to the clipboard.
|
||||
*/
|
||||
OutputWaiter.prototype.copyClick = function() {
|
||||
// Create invisible textarea to populate with the raw dishStr (not the printable version that
|
||||
// contains dots instead of the actual bytes)
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.style.position = "fixed";
|
||||
textarea.style.top = 0;
|
||||
textarea.style.left = 0;
|
||||
textarea.style.width = 0;
|
||||
textarea.style.height = 0;
|
||||
textarea.style.border = "none";
|
||||
|
||||
textarea.value = this.app.dishStr;
|
||||
document.body.appendChild(textarea);
|
||||
|
||||
// Select and copy the contents of this textarea
|
||||
let success = false;
|
||||
try {
|
||||
textarea.select();
|
||||
success = document.execCommand("copy");
|
||||
} catch (err) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
this.app.alert("Copied raw output successfully.", "success", 2000);
|
||||
} else {
|
||||
this.app.alert("Sorry, the output could not be copied.", "danger", 2000);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
document.body.removeChild(textarea);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handler for switch click events.
|
||||
* Moves the current output into the input textarea.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import HTMLOperation from "./HTMLOperation.js";
|
||||
import Sortable from "sortablejs";
|
||||
import Utils from "../core/Utils.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -191,7 +192,7 @@ RecipeWaiter.prototype.favDrop = function(e) {
|
||||
*
|
||||
* @fires Manager#statechange
|
||||
*/
|
||||
RecipeWaiter.prototype.ingChange = function() {
|
||||
RecipeWaiter.prototype.ingChange = function(e) {
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
};
|
||||
|
||||
@@ -435,4 +436,30 @@ RecipeWaiter.prototype.opRemove = function(e) {
|
||||
window.dispatchEvent(this.manager.statechange);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets register values.
|
||||
*
|
||||
* @param {number} opIndex
|
||||
* @param {number} numPrevRegisters
|
||||
* @param {string[]} registers
|
||||
*/
|
||||
RecipeWaiter.prototype.setRegisters = function(opIndex, numPrevRegisters, registers) {
|
||||
const op = document.querySelector(`#rec-list .operation:nth-child(${opIndex + 1})`),
|
||||
prevRegList = op.querySelector(".register-list");
|
||||
|
||||
// Remove previous div
|
||||
if (prevRegList) prevRegList.remove();
|
||||
|
||||
let registerList = [];
|
||||
for (let i = 0; i < registers.length; i++) {
|
||||
registerList.push(`$R${numPrevRegisters + i} = ${Utils.escapeHtml(Utils.truncate(Utils.printable(registers[i]), 100))}`);
|
||||
}
|
||||
const registerListEl = `<div class="register-list">
|
||||
${registerList.join("<br>")}
|
||||
</div>`;
|
||||
|
||||
op.insertAdjacentHTML("beforeend", registerListEl);
|
||||
};
|
||||
|
||||
export default RecipeWaiter;
|
||||
|
||||
@@ -61,6 +61,9 @@ WorkerWaiter.prototype.handleChefMessage = function(e) {
|
||||
case "optionUpdate":
|
||||
this.app.options[r.data.option] = r.data.value;
|
||||
break;
|
||||
case "setRegisters":
|
||||
this.manager.recipe.setRegisters(r.data.opIndex, r.data.numPrevRegisters, r.data.registers);
|
||||
break;
|
||||
case "highlightsCalculated":
|
||||
this.manager.highlighter.displayHighlights(r.data.pos, r.data.direction);
|
||||
break;
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<!-- htmlmin:ignore --><!--
|
||||
CyberChef - The Cyber Swiss Army Knife
|
||||
|
||||
|
||||
@copyright Crown Copyright 2016
|
||||
@license Apache-2.0
|
||||
|
||||
|
||||
Copyright 2016 Crown Copyright
|
||||
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -24,7 +24,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>CyberChef</title>
|
||||
|
||||
|
||||
<meta name="copyright" content="Crown Copyright 2016" />
|
||||
<meta name="description" content="The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis" />
|
||||
<meta name="keywords" content="base64, hex, decode, encode, encrypt, decrypt, compress, decompress, regex, regular expressions, hash, crypt, hexadecimal, user agent, url, certificate, x.509, parser, JSON, gzip, md5, sha1, aes, des, blowfish, xor" />
|
||||
@@ -35,7 +35,11 @@
|
||||
"use strict";
|
||||
|
||||
// Load theme before the preloader is shown
|
||||
document.querySelector(":root").className = (JSON.parse(localStorage.getItem("options")) || {}).theme;
|
||||
try {
|
||||
document.querySelector(":root").className = (JSON.parse(localStorage.getItem("options")) || {}).theme;
|
||||
} catch (err) {
|
||||
// LocalStorage access is denied by security settings
|
||||
}
|
||||
|
||||
// Define loading messages
|
||||
const loadingMsgs = [
|
||||
@@ -131,11 +135,11 @@
|
||||
<ul id="search-results" class="op-list"></ul>
|
||||
<div id="categories" class="panel-group no-select"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="recipe" class="split split-horizontal no-select">
|
||||
<div class="title no-select">Recipe</div>
|
||||
<ul id="rec-list" class="list-area no-select"></ul>
|
||||
|
||||
|
||||
<div id="controls" class="no-select">
|
||||
<div id="operational-controls">
|
||||
<div id="bake-group">
|
||||
@@ -148,13 +152,13 @@
|
||||
<div>Auto Bake</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-group" style="padding-top: 10px;">
|
||||
<button type="button" class="btn btn-default" id="step"><img aria-hidden="true" src="<%- require('../static/images/step-16x16.png') %>" alt="Footstep Icon"/> Step through</button>
|
||||
<button type="button" class="btn btn-default" id="clr-breaks"><img aria-hidden="true" src="<%- require('../static/images/erase-16x16.png') %>" alt="Eraser Icon"/> Clear breakpoints</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="btn-group-vertical" id="extra-controls">
|
||||
<button type="button" class="btn btn-default" id="save"><img aria-hidden="true" src="<%- require('../static/images/save-16x16.png') %>" alt="Save Icon"/> Save recipe</button>
|
||||
<button type="button" class="btn btn-default" id="load"><img aria-hidden="true" src="<%- require('../static/images/open_yellow-16x16.png') %>" alt="Open Icon"/> Load recipe</button>
|
||||
@@ -162,7 +166,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="split split-horizontal" id="IO">
|
||||
<div id="input" class="split no-select">
|
||||
<div class="title no-select">
|
||||
@@ -179,12 +183,13 @@
|
||||
<textarea id="input-text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="output" class="split">
|
||||
<div class="title no-select">
|
||||
<label for="output-text">Output</label>
|
||||
<div class="btn-group io-btn-group">
|
||||
<button type="button" class="btn btn-default btn-sm" id="save-to-file" title="Save to file"><img aria-hidden="true" src="<%- require('../static/images/save_as-16x16.png') %>" alt="Save Icon"/> Save to file</button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="copy-output" title="Copy output"><img aria-hidden="true" src="<%- require('../static/images/copy-16x16.png') %>" alt="Copy Icon"/> Copy raw output</button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="switch" title="Move output to input"><img aria-hidden="true" src="<%- require('../static/images/switch-16x16.png') %>" alt="Switch Icon"/> Move output to input</button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="undo-switch" title="Undo move" disabled="disabled"><img aria-hidden="true" src="<%- require('../static/images/undo-16x16.png') %>" alt="Undo Icon"/> Undo</button>
|
||||
<button type="button" class="btn btn-default btn-sm" id="maximise-output" title="Maximise"><img aria-hidden="true" src="<%- require('../static/images/maximise-16x16.png') %>" alt="Maximise Icon"/> Max</button>
|
||||
@@ -206,7 +211,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="save-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -257,7 +262,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="load-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -283,7 +288,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="options-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -321,6 +326,10 @@
|
||||
<input type="checkbox" option="showErrors" id="showErrors" checked />
|
||||
<label for="showErrors"> Operation error reporting (recommended) </label>
|
||||
</div>
|
||||
<div class="option-item">
|
||||
<input type="checkbox" option="useMetaKey" id="useMetaKey" />
|
||||
<label for="useMetaKey"> Use meta key for keybindings (Windows ⊞/Command ⌘) </label>
|
||||
</div>
|
||||
<div class="option-item">
|
||||
<input type="number" option="errorTimeout" id="errorTimeout" />
|
||||
<label for="errorTimeout"> Operation error timeout in ms (0 for never) </label>
|
||||
@@ -333,7 +342,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="favourites-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -360,7 +369,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="support-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -376,6 +385,11 @@
|
||||
</p>
|
||||
<p>© Crown Copyright 2016.</p>
|
||||
<p>Released under the Apache Licence, Version 2.0.</p>
|
||||
<p>
|
||||
<a href="https://gitter.im/gchq/CyberChef">
|
||||
<img src="<%- require('../static/images/gitter-badge.svg') %>">
|
||||
</a>
|
||||
</p>
|
||||
<br>
|
||||
<br>
|
||||
<div>
|
||||
@@ -392,6 +406,10 @@
|
||||
<img aria-hidden="true" src="<%- require('../static/images/speech-16x16.png') %>" alt="Speech Balloon Icon"/>
|
||||
About
|
||||
</a></li>
|
||||
<li role="presentation"><a href="#keybindings" aria-controls="messages" role="tab" data-toggle="tab">
|
||||
<img aria-hidden="true" src="<%- require('../static/images/code-16x16.png') %>" alt="List Icon"/>
|
||||
Keybindings
|
||||
</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="faqs">
|
||||
@@ -408,8 +426,10 @@
|
||||
<li><a href="#recipe=Translate_DateTime_Format('Standard%20date%20and%20time','DD/MM/YYYY%20HH:mm:ss','UTC','dddd%20Do%20MMMM%20YYYY%20HH:mm:ss%20Z%20z','Australia/Queensland')&input=MTUvMDYvMjAxNSAyMDo0NTowMA">Convert a date and time to a different time zone</a></li>
|
||||
<li><a href="#recipe=Parse_IPv6_address()&input=MjAwMTowMDAwOjQxMzY6ZTM3ODo4MDAwOjYzYmY6M2ZmZjpmZGQy">Parse a Teredo IPv6 address</a></li>
|
||||
<li><a href="#recipe=From_Hexdump()Gunzip()&input=MDAwMDAwMDAgIDFmIDhiIDA4IDAwIDEyIGJjIGYzIDU3IDAwIGZmIDBkIGM3IGMxIDA5IDAwIDIwICB8Li4uLi6881cu/y7HwS4uIHwKMDAwMDAwMTAgIDA4IDA1IGQwIDU1IGZlIDA0IDJkIGQzIDA0IDFmIGNhIDhjIDQ0IDIxIDViIGZmICB8Li7QVf4uLdMuLsouRCFb/3wKMDAwMDAwMjAgIDYwIGM3IGQ3IDAzIDE2IGJlIDQwIDFmIDc4IDRhIDNmIDA5IDg5IDBiIDlhIDdkICB8YMfXLi6%2BQC54Sj8uLi4ufXwKMDAwMDAwMzAgIDRlIGM4IDRlIDZkIDA1IDFlIDAxIDhiIDRjIDI0IDAwIDAwIDAwICAgICAgICAgICB8TshObS4uLi5MJC4uLnw">Convert data from a hexdump, then decompress</a></li>
|
||||
<li><a href="#recipe=RC4(%7B'option':'UTF8','string':'secret'%7D,'Hex','Hex')Disassemble_x86('64','Full%20x86%20architecture',16,0,true,true)&input=MjFkZGQyNTQwMTYwZWU2NWZlMDc3NzEwM2YyYTM5ZmJlNWJjYjZhYTBhYWJkNDE0ZjkwYzZjYWY1MzEyNzU0YWY3NzRiNzZiM2JiY2QxOTNjYjNkZGZkYmM1YTI2NTMzYTY4NmI1OWI4ZmVkNGQzODBkNDc0NDIwMWFlYzIwNDA1MDcxMzhlMmZlMmIzOTUwNDQ2ZGIzMWQyYmM2MjliZTRkM2YyZWIwMDQzYzI5M2Q3YTVkMjk2MmMwMGZlNmRhMzAwNzJkOGM1YTZiNGZlN2Q4NTlhMDQwZWVhZjI5OTczMzYzMDJmNWEwZWMxOQ">Decrypt and disassemble shellcode</a></li>
|
||||
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)From_UNIX_Timestamp('Seconds%20(s)')&input=OTc4MzQ2ODAwCjEwMTI2NTEyMDAKMTA0NjY5NjQwMAoxMDgxMDg3MjAwCjExMTUzMDUyMDAKMTE0OTYwOTYwMA">Display multiple timestamps as full dates</a></li>
|
||||
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
||||
<li><a href="#recipe=Fork('%5C%5Cn','%5C%5Cn',false)Conditional_Jump('1',false,'base64',10)To_Hex('Space')Return()Label('base64')To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA">Carry out different operations on data of different types</a></li>
|
||||
<li><a href="#recipe=Register('key%3D(%5B%5C%5Cda-f%5D*)',true,false)Find_/_Replace(%7B'option':'Regex','string':'.*data%3D(.*)'%7D,'$1',true,false,true)RC4(%7B'option':'Hex','string':'$R0'%7D,'Hex','Latin1')&input=aHR0cDovL21hbHdhcmV6LmJpei9iZWFjb24ucGhwP2tleT0wZTkzMmE1YyZkYXRhPThkYjdkNWViZTM4NjYzYTU0ZWNiYjMzNGUzZGIxMQ">Use parts of the input as arguments to operations</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<blockquote>
|
||||
@@ -443,20 +463,20 @@
|
||||
<div role="tabpanel" class="tab-pane" id="about" style="padding: 20px;">
|
||||
<h5><strong>What</strong></h5>
|
||||
<p>A simple, intuitive web app for analysing and decoding data without having to deal with complex tools or programming languages. CyberChef encourages both technical and non-technical people to explore data formats, encryption and compression.</p><br>
|
||||
|
||||
|
||||
<h5><strong>Why</strong></h5>
|
||||
<p>Digital data comes in all shapes, sizes and formats in the modern world – CyberChef helps to make sense of this data all on one easy-to-use platform.</p><br>
|
||||
|
||||
|
||||
|
||||
<h5><strong>How</strong></h5>
|
||||
<p>The interface is designed with simplicity at its heart. Complex techniques are now as trivial as drag-and-drop. Simple functions can be combined to build up a "recipe", potentially resulting in complex analysis, which can be shared with other users and used with their input.</p>
|
||||
<p>For those comfortable writing code, CyberChef is a quick and efficient way to prototype solutions to a problem which can then be scripted once proven to work.</p><br>
|
||||
|
||||
|
||||
|
||||
<h5><strong>Who</strong></h5>
|
||||
<p>It is expected that CyberChef will be useful for cybersecurity and antivirus companies. It should also appeal to the academic world and any individuals or companies involved in the analysis of digital data, be that software developers, analysts, mathematicians or casual puzzle solvers.</p><br>
|
||||
|
||||
|
||||
|
||||
<h5><strong>Aim</strong></h5>
|
||||
<p>It is hoped that by releasing CyberChef through <a href="https://github.com/gchq/CyberChef">GitHub</a>, contributions can be added which can be rolled out into future versions of the tool.</p><br>
|
||||
|
||||
@@ -465,6 +485,9 @@
|
||||
<p>There are around 150 useful operations in CyberChef for anyone working on anything vaguely Internet-related, whether you just want to convert a timestamp to a different format, decompress gzipped data, create a SHA3 hash, or parse an X.509 certificate to find out who issued it.</p>
|
||||
<p>It’s the Cyber Swiss Army Knife.</p>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="keybindings" style="padding: 20px;">
|
||||
<table class="table table-condensed table-bordered table-hover" id="keybList"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -477,7 +500,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal" id="confirm-modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
@@ -498,6 +521,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -46,6 +46,7 @@ function main() {
|
||||
errorTimeout: 4000,
|
||||
attemptHighlight: true,
|
||||
theme: "classic",
|
||||
useMetaKey: false
|
||||
};
|
||||
|
||||
document.removeEventListener("DOMContentLoaded", main, false);
|
||||
|
||||
BIN
src/web/static/images/copy-16x16.png
Executable file
BIN
src/web/static/images/copy-16x16.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 432 B |
0
src/web/static/images/fork_me.png
Normal file → Executable file
0
src/web/static/images/fork_me.png
Normal file → Executable file
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
1
src/web/static/images/gitter-badge.svg
Executable file
1
src/web/static/images/gitter-badge.svg
Executable file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><mask id="a"><rect width="92" height="20" rx="3" fill="#fff"/></mask><g mask="url(#a)"><path fill="#555" d="M0 0h34v20H0z"/><path fill="#46BC99" d="M34 0h58v20H34z"/><path fill="url(#b)" d="M0 0h92v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="17" y="15" fill="#010101" fill-opacity=".3">chat</text><text x="17" y="14">chat</text><text x="62" y="15" fill="#010101" fill-opacity=".3">on gitter</text><text x="62" y="14">on gitter</text></g></svg>
|
||||
|
After Width: | Height: | Size: 733 B |
@@ -124,6 +124,12 @@ button.dropdown-toggle {
|
||||
background-color: var(--secondary-background-colour);
|
||||
}
|
||||
|
||||
.register-list {
|
||||
background-color: var(--fc-operation-border-colour);
|
||||
font-family: var(--fixed-width-font-family);
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.op-icon {
|
||||
float: right;
|
||||
margin-left: 10px;
|
||||
@@ -195,3 +201,13 @@ button.dropdown-toggle {
|
||||
background-color: var(--disabled-bg-colour) !important;
|
||||
border-color: var(--disabled-border-colour) !important;
|
||||
}
|
||||
|
||||
.break .register-list {
|
||||
color: var(--fc-breakpoint-operation-font-colour) !important;
|
||||
background-color: var(--fc-breakpoint-operation-border-colour) !important;
|
||||
}
|
||||
|
||||
.disabled .register-list {
|
||||
color: var(--disabled-font-colour) !important;
|
||||
background-color: var(--disabled-border-colour) !important;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ import "./tests/operations/Hash.js";
|
||||
import "./tests/operations/Image.js";
|
||||
import "./tests/operations/MorseCode.js";
|
||||
import "./tests/operations/MS.js";
|
||||
import "./tests/operations/PHP.js";
|
||||
import "./tests/operations/NetBIOS.js";
|
||||
import "./tests/operations/OTP.js";
|
||||
import "./tests/operations/StrUtils.js";
|
||||
import "./tests/operations/SeqUtils.js";
|
||||
|
||||
|
||||
@@ -310,4 +310,26 @@ TestRegister.addTests([
|
||||
}
|
||||
],
|
||||
},
|
||||
{
|
||||
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>',
|
||||
expectedOutput: '<p class="a">hello</p>\n<p class="a">again</p>',
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "CSS selector",
|
||||
"args": ["#test p.a", "\\n"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "XPath expression",
|
||||
input: '<div id="test">\n<p class="a">hello</p>\n<p>world</p>\n<p class="a">again</p>\n</div>',
|
||||
expectedOutput: '<p class="a">hello</p>\n<p class="a">again</p>',
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "XPath expression",
|
||||
"args": ["/div/p[@class=\"a\"]", "\\n"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -60,14 +60,15 @@ TestRegister.addTests([
|
||||
expectedOutput: "U29tZSBkYXRhIHdpdGggYSAxIGluIGl0\n53 6f 6d 65 20 64 61 74 61 20 77 69 74 68 20 61 20 32 20 69 6e 20 69 74\n",
|
||||
recipeConfig: [
|
||||
{"op": "Fork", "args": ["\\n", "\\n", false]},
|
||||
{"op": "Conditional Jump", "args": ["1", "2", "10"]},
|
||||
{"op": "Conditional Jump", "args": ["1", false, "skipReturn", "10"]},
|
||||
{"op": "To Hex", "args": ["Space"]},
|
||||
{"op": "Return", "args": []},
|
||||
{"op": "Label", "args": ["skipReturn"]},
|
||||
{"op": "To Base64", "args": ["A-Za-z0-9+/="]}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Jump: skips 0",
|
||||
name: "Jump: Empty Label",
|
||||
input: [
|
||||
"should be changed",
|
||||
].join("\n"),
|
||||
@@ -77,7 +78,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Jump",
|
||||
args: [0, 10],
|
||||
args: ["", 10],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
@@ -105,7 +106,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Jump",
|
||||
args: [1, 10],
|
||||
args: ["skipReplace", 10],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
@@ -120,6 +121,10 @@ TestRegister.addTests([
|
||||
true,
|
||||
],
|
||||
},
|
||||
{
|
||||
op: "Label",
|
||||
args: ["skipReplace"]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -137,7 +142,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Conditional Jump",
|
||||
args: ["match", 0, 0],
|
||||
args: ["match", false, "", 0],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
@@ -212,7 +217,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Conditional Jump",
|
||||
args: ["match", 1, 10],
|
||||
args: ["match", false, "skip match", 10],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
@@ -227,6 +232,9 @@ TestRegister.addTests([
|
||||
true,
|
||||
],
|
||||
},
|
||||
{
|
||||
op: "Label", args: ["skip match"],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
args: [
|
||||
@@ -251,9 +259,13 @@ TestRegister.addTests([
|
||||
"replaced",
|
||||
].join("\n"),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Label",
|
||||
args: ["back to the beginning"],
|
||||
},
|
||||
{
|
||||
op: "Jump",
|
||||
args: [1],
|
||||
args: ["skip replace"],
|
||||
},
|
||||
{
|
||||
op: "Find / Replace",
|
||||
@@ -268,9 +280,13 @@ TestRegister.addTests([
|
||||
true,
|
||||
],
|
||||
},
|
||||
{
|
||||
op: "Label",
|
||||
args: ["skip replace"],
|
||||
},
|
||||
{
|
||||
op: "Conditional Jump",
|
||||
args: ["match", -2, 10],
|
||||
args: ["match", false, "back to the beginning", 10],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -294,6 +294,116 @@ TestRegister.addTests([
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HAS-160",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "8f6dd8d7c8a04b1cb3831adc358b1e4ac2ed5984",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "HAS-160",
|
||||
"args": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Whirlpool-0",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "1c327026f565a0105a827efbfb3d3635cdb042c0aabb8416e96deb128e6c5c8684b13541cf31c26c1488949df050311c6999a12eb0e7002ad716350f5c7700ca",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Whirlpool",
|
||||
"args": ["Whirlpool-0"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Whirlpool-T",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "16c581089b6a6f356ae56e16a63a4c613eecd82a2a894b293f5ee45c37a31d09d7a8b60bfa7e414bd4a7166662cea882b5cf8c96b7d583fc610ad202591bcdb1",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Whirlpool",
|
||||
"args": ["Whirlpool-T"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Whirlpool",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "3d837c9ef7bb291bd1dcfc05d3004af2eeb8c631dd6a6c4ba35159b8889de4b1ec44076ce7a8f7bfa497e4d9dcb7c29337173f78d06791f3c3d9e00cc6017f0b",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Whirlpool",
|
||||
"args": ["Whirlpool"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 2 128",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "a4ad2b8848580511d0884fb4233a7e7a",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["2", "128"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 4 128",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "d154eae2c9ffbcd2e1bdaf0b84736126",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["4", "128"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 8 128",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "6f3d55b69557abb0a3c4e9de9d29ba5d",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["8", "128"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 2 256",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "65736daba648de28ef4c4a316b4684584ecf9f22ddb5c457729e6bf0f40113c4",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["2", "256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 4 256",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "71b0ea4b3e33f2e58bcc67c8a8de060b99ec0107355bbfdc18d8f65f0194ffcc",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["4", "256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Snefru 8 256",
|
||||
input: "Hello, World!",
|
||||
expectedOutput: "255cd401414c79588cf689e8d5ff0536a2cfab83fcae36e654f202b09bc4b8a7",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Snefru",
|
||||
"args": ["8", "256"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "HMAC SHA256",
|
||||
input: "Hello, World!",
|
||||
|
||||
34
test/tests/operations/NetBIOS.js
Normal file
34
test/tests/operations/NetBIOS.js
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* NetBIOS tests.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Encode NetBIOS name",
|
||||
input: "The NetBIOS name",
|
||||
expectedOutput: "FEGIGFCAEOGFHEECEJEPFDCAGOGBGNGF",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Encode NetBIOS Name",
|
||||
args: [65],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Decode NetBIOS Name",
|
||||
input: "FEGIGFCAEOGFHEECEJEPFDCAGOGBGNGF",
|
||||
expectedOutput: "The NetBIOS name",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Decode NetBIOS Name",
|
||||
args: [65],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
23
test/tests/operations/OTP.js
Normal file
23
test/tests/operations/OTP.js
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* OTP HOTP tests.
|
||||
*
|
||||
* @author bwhitn [brian.m.whitney@outlook.com]
|
||||
*
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Generate HOTP",
|
||||
input: "12345678901234567890",
|
||||
expectedOutput: "URI: otpauth://hotp/OTPAuthentication?secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ\n\nPassword: 755224",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Generate HOTP",
|
||||
args: ["", 32, 6, 0],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
68
test/tests/operations/PHP.js
Normal file
68
test/tests/operations/PHP.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* PHP tests.
|
||||
*
|
||||
* @author Jarmo van Lenthe
|
||||
*
|
||||
* @copyright Crown Copyright 2017
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import TestRegister from "../../TestRegister.js";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "PHP Deserialize empty array",
|
||||
input: "a:0:{}",
|
||||
expectedOutput: "{}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "PHP Deserialize",
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "PHP Deserialize integer",
|
||||
input: "i:10;",
|
||||
expectedOutput: "10",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "PHP Deserialize",
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "PHP Deserialize string",
|
||||
input: "s:17:\"PHP Serialization\";",
|
||||
expectedOutput: "\"PHP Serialization\"",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "PHP Deserialize",
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "PHP Deserialize array (JSON)",
|
||||
input: "a:2:{s:1:\"a\";i:10;i:0;a:1:{s:2:\"ab\";b:1;}}",
|
||||
expectedOutput: "{\"a\": 10,\"0\": {\"ab\": true}}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "PHP Deserialize",
|
||||
args: [true],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "PHP Deserialize array (non-JSON)",
|
||||
input: "a:2:{s:1:\"a\";i:10;i:0;a:1:{s:2:\"ab\";b:1;}}",
|
||||
expectedOutput: "{\"a\": 10,0: {\"ab\": true}}",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "PHP Deserialize",
|
||||
args: [false],
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
@@ -10,8 +10,8 @@ import TestRegister from "../../TestRegister.js";
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "SeqUtils - Numeric sort photos",
|
||||
input: "Photo-1.jpg\nPhoto-4.jpg\nPhoto-2.jpg\nPhoto-3.jpg\n",
|
||||
expectedOutput: "Photo-1.jpg\nPhoto-2.jpg\nPhoto-3.jpg\nPhoto-4.jpg\n",
|
||||
input: "Photo-1.jpg\nPhoto-4.jpg\nPhoto-2.jpg\nPhoto-3.jpg",
|
||||
expectedOutput: "Photo-1.jpg\nPhoto-2.jpg\nPhoto-3.jpg\nPhoto-4.jpg",
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "Sort",
|
||||
|
||||
Reference in New Issue
Block a user