Merge pull request #1 from gchq/master

updating
This commit is contained in:
bwhitn 2017-11-24 07:50:13 -05:00 committed by GitHub
commit 47ce240e70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
121 changed files with 12980 additions and 3494 deletions

View File

@ -1 +1,2 @@
src/core/lib/** src/core/lib/**
src/core/config/MetaConfig.js

View File

@ -28,11 +28,7 @@
// modify rules from base configurations // modify rules from base configurations
"no-unused-vars": ["error", { "no-unused-vars": ["error", {
"args": "none", "args": "none",
"vars": "local", "vars": "all"
// 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]"
}], }],
"no-empty": ["error", { "no-empty": ["error", {
"allowEmptyCatch": true "allowEmptyCatch": true
@ -97,6 +93,9 @@
"COMPILE_TIME": false, "COMPILE_TIME": false,
"COMPILE_MSG": false, "COMPILE_MSG": false,
"PKG_VERSION": false "PKG_VERSION": false,
"ENVIRONMENT_IS_WORKER": false,
"ENVIRONMENT_IS_NODE": false,
"ENVIRONMENT_IS_WEB": false
} }
} }

View File

@ -5,21 +5,10 @@
<!-- Misc: --> <!-- Misc: -->
### Summary ### 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 ### Example
<!-- If describing a bug, tell us what happens instead of the expected behavior --> <!-- If describing a bug, tell us what happens instead of the expected behavior -->
<!-- Include a link that triggers the bug if possible --> <!-- Include a link that triggers the bug if possible -->
<!-- If you are requesting a new operation, include example input and output --> <!-- 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]()

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ docs/*
!docs/*.conf.json !docs/*.conf.json
!docs/*.ico !docs/*.ico
.vscode .vscode
src/core/config/MetaConfig.js

View File

@ -1,6 +1,6 @@
language: node_js language: node_js
node_js: node_js:
- node - "8.4"
install: npm install install: npm install
before_script: before_script:
- npm install -g grunt - npm install -g grunt
@ -22,7 +22,7 @@ deploy:
repo: gchq/CyberChef repo: gchq/CyberChef
branch: master branch: master
- provider: releases - provider: releases
skip_cleaup: true skip_cleanup: true
api_key: api_key:
secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA=" secure: "HV1WSKv4l/0Y2bKKs1iBJocBcmLj08PCRUeEM/jTwA4jqJ8EiLHWiXtER/D5sEg2iibRVKd2OQjfrmS6bo4AiwdeVgAKmv0FtS2Jw+391N8Nd5AkEANHa5Om/IpHLTL2YRAjpJTsDpY72bMUTJIwjQA3TFJkgrpOw6KYfohOcgbxLpZ4XuNJRU3VL4Hsxdv5V9aOVmfFOmMOVPQlakXy7NgtW5POp1f2WJwgcZxylkR1CjwaqMyXmSoVl46pyH3tr5+dptsQoKSGdi6sIHGA60oDotFPcm+0ifa47wZw+vapuuDi4tdNxhrHGaDMG8xiE0WFDHwQUDlk2/+W7j9SEX0H3Em7us371JXRp56EDwEcDa34VpVkC6i8HGcHK55hnxVbMZXGf3qhOFD8wY7qMbjMRvIpucrMHBi86OfkDfv0vDj2LyvIl5APj/AX50BrE0tfH1MZbH26Jkx4NdlkcxQ14GumarmUqfmVvbX/fsoA6oUuAAE9ZgRRi3KHO4wci6KUcRfdm+XOeUkaBFsL86G3EEYIvrtBTuaypdz+Cx7nd1iPZyWMx5Y1gXnVzha4nBdV4+7l9JIsFggD8QVpw2uHXQiS1KXFjOeqA3DBD8tjMB7q26Fl2fD3jkOo4BTbQ2NrRIZUu/iL+fOmMPsyMt2qulB0yaSBCfkbEq8xrUA="
file: file:
@ -39,4 +39,10 @@ deploy:
on: on:
tags: true tags: true
branch: master branch: master
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/83c143a6822e218d5b34
on_success: change
on_failure: always
on_start: never

View File

@ -1,8 +1,18 @@
"use strict";
const webpack = require("webpack"); const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin");
const NodeExternals = require("webpack-node-externals"); const NodeExternals = require("webpack-node-externals");
const Inliner = require("web-resource-inliner"); const Inliner = require("web-resource-inliner");
const fs = require("fs");
/**
* Grunt configuration for building the app in various formats.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
module.exports = function (grunt) { module.exports = function (grunt) {
grunt.file.defaultEncoding = "utf8"; grunt.file.defaultEncoding = "utf8";
@ -11,15 +21,15 @@ module.exports = function (grunt) {
// Tasks // Tasks
grunt.registerTask("dev", grunt.registerTask("dev",
"A persistent task which creates a development build whenever source files are modified.", "A persistent task which creates a development build whenever source files are modified.",
["clean:dev", "webpack:webDev"]); ["clean:dev", "concurrent:dev"]);
grunt.registerTask("node", grunt.registerTask("node",
"Compiles CyberChef into a single NodeJS module.", "Compiles CyberChef into a single NodeJS module.",
["clean:node", "webpack:node", "chmod:build"]); ["clean:node", "webpack:metaConf", "webpack:node", "chmod:build"]);
grunt.registerTask("test", grunt.registerTask("test",
"A task which runs all the tests in test/tests.", "A task which runs all the tests in test/tests.",
["clean:test", "webpack:tests", "execute:test"]); ["clean:test", "webpack:metaConf", "webpack:tests", "execute:test"]);
grunt.registerTask("docs", grunt.registerTask("docs",
"Compiles documentation in the /docs directory.", "Compiles documentation in the /docs directory.",
@ -27,7 +37,7 @@ module.exports = function (grunt) {
grunt.registerTask("prod", grunt.registerTask("prod",
"Creates a production-ready build. Use the --msg flag to add a compile message.", "Creates a production-ready build. Use the --msg flag to add a compile message.",
["eslint", "clean:prod", "webpack:webProd", "inline", "chmod"]); ["eslint", "clean:prod", "webpack:metaConf", "webpack:web", "inline", "chmod"]);
grunt.registerTask("default", grunt.registerTask("default",
"Lints the code base", "Lints the code base",
@ -35,8 +45,10 @@ module.exports = function (grunt) {
grunt.registerTask("inline", grunt.registerTask("inline",
"Compiles a production build of CyberChef into a single, portable web page.", "Compiles a production build of CyberChef into a single, portable web page.",
runInliner); ["webpack:webInline", "runInliner", "clean:inlineScripts"]);
grunt.registerTask("runInliner", runInliner);
grunt.registerTask("doc", "docs"); grunt.registerTask("doc", "docs");
grunt.registerTask("tests", "test"); grunt.registerTask("tests", "test");
grunt.registerTask("lint", "eslint"); grunt.registerTask("lint", "eslint");
@ -52,31 +64,28 @@ module.exports = function (grunt) {
grunt.loadNpmTasks("grunt-exec"); grunt.loadNpmTasks("grunt-exec");
grunt.loadNpmTasks("grunt-execute"); grunt.loadNpmTasks("grunt-execute");
grunt.loadNpmTasks("grunt-accessibility"); grunt.loadNpmTasks("grunt-accessibility");
grunt.loadNpmTasks("grunt-concurrent");
// Project configuration // Project configuration
const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC", const compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC",
banner = "/**\n" + pkg = grunt.file.readJSON("package.json"),
"* CyberChef - The Cyber Swiss Army Knife\n" + webpackConfig = require("./webpack.config.js"),
"*\n" + BUILD_CONSTANTS = {
"* @copyright Crown Copyright 2016\n" + COMPILE_TIME: JSON.stringify(compileTime),
"* @license Apache-2.0\n" + COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
"*\n" + PKG_VERSION: JSON.stringify(pkg.version),
"* Copyright 2016 Crown Copyright\n" + ENVIRONMENT_IS_WORKER: function() {
"*\n" + return typeof importScripts === "function";
'* Licensed under the Apache License, Version 2.0 (the "License");\n' + },
"* you may not use this file except in compliance with the License.\n" + ENVIRONMENT_IS_NODE: function() {
"* You may obtain a copy of the License at\n" + return typeof process === "object" && typeof require === "function";
"*\n" + },
"* http://www.apache.org/licenses/LICENSE-2.0\n" + ENVIRONMENT_IS_WEB: function() {
"*\n" + return typeof window === "object";
"* Unless required by applicable law or agreed to in writing, software\n" + }
'* distributed under the License is distributed on an "AS IS" BASIS,\n' + },
"* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" + moduleEntryPoints = listEntryModules();
"* See the License for the specific language governing permissions and\n" +
"* limitations under the License.\n" +
"*/\n",
pkg = grunt.file.readJSON("package.json");
/** /**
* Compiles a production build of CyberChef into a single, portable web page. * Compiles a production build of CyberChef into a single, portable web page.
@ -105,20 +114,36 @@ module.exports = function (grunt) {
}); });
} }
/**
* Generates an entry list for all the modules.
*/
function listEntryModules() {
const path = "./src/core/config/modules/";
let entryModules = {};
fs.readdirSync(path).forEach(file => {
if (file !== "Default.js" && file !== "OpModules.js")
entryModules[file.split(".js")[0]] = path + file;
});
return entryModules;
}
grunt.initConfig({ grunt.initConfig({
clean: { clean: {
dev: ["build/dev/*"], dev: ["build/dev/*", "src/core/config/MetaConfig.js"],
prod: ["build/prod/*"], prod: ["build/prod/*", "src/core/config/MetaConfig.js"],
test: ["build/test/*"], test: ["build/test/*", "src/core/config/MetaConfig.js"],
node: ["build/node/*"], node: ["build/node/*", "src/core/config/MetaConfig.js"],
docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico"], docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"],
inlineScripts: ["build/prod/scripts.js"],
}, },
eslint: { eslint: {
options: { options: {
configFile: "./.eslintrc.json" configFile: "./.eslintrc.json"
}, },
configs: ["Gruntfile.js"], configs: ["Gruntfile.js"],
core: ["src/core/**/*.js", "!src/core/lib/**/*"], core: ["src/core/**/*.js", "!src/core/lib/**/*", "!src/core/config/MetaConfig.js"],
web: ["src/web/**/*.js"], web: ["src/web/**/*.js"],
node: ["src/node/**/*.js"], node: ["src/node/**/*.js"],
tests: ["test/**/*.js"], tests: ["test/**/*.js"],
@ -135,9 +160,16 @@ module.exports = function (grunt) {
src: [ src: [
"src/**/*.js", "src/**/*.js",
"!src/core/lib/**/*", "!src/core/lib/**/*",
"!src/core/config/MetaConfig.js"
], ],
} }
}, },
concurrent: {
options: {
logConcurrentOutput: true
},
dev: ["webpack:metaConfDev", "webpack-dev-server:start"]
},
accessibility: { accessibility: {
options: { options: {
accessibilityLevel: "WCAG2A", accessibilityLevel: "WCAG2A",
@ -151,114 +183,47 @@ module.exports = function (grunt) {
} }
}, },
webpack: { webpack: {
options: { options: webpackConfig,
plugins: [ metaConf: {
new webpack.ProvidePlugin({ target: "node",
$: "jquery", entry: "./src/core/config/OperationConfig.js",
jQuery: "jquery",
moment: "moment-timezone"
}),
new webpack.BannerPlugin({
banner: banner,
raw: true,
entryOnly: true
}),
new webpack.DefinePlugin({
COMPILE_TIME: JSON.stringify(compileTime),
COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""),
PKG_VERSION: JSON.stringify(pkg.version)
}),
new ExtractTextPlugin("styles.css"),
],
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader?compact=false"
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
]
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
use: [
{ loader: "css-loader?minimize" },
{ loader: "postcss-loader" },
{ loader: "less-loader" }
]
})
},
{
test: /\.(ico|eot|ttf|woff|woff2)$/,
loader: "url-loader",
options: {
limit: 10000
}
},
{ // First party images are saved as files to be cached
test: /\.(png|jpg|gif|svg)$/,
exclude: /node_modules/,
loader: "file-loader",
options: {
name: "images/[name].[ext]"
}
},
{ // Third party images are inlined
test: /\.(png|jpg|gif|svg)$/,
exclude: /web\/static/,
loader: "url-loader",
options: {
limit: 10000
}
},
]
},
stats: {
children: false,
warningsFilter: /source-map/
},
node: {
fs: "empty"
}
},
webDev: {
target: "web",
entry: "./src/web/index.js",
output: { output: {
filename: "scripts.js", filename: "MetaConfig.js",
path: __dirname + "/build/dev" path: __dirname + "/src/core/config/",
library: "MetaConfig",
libraryTarget: "commonjs2",
libraryExport: "default"
}, },
plugins: [ externals: [NodeExternals()],
new HtmlWebpackPlugin({ },
filename: "index.html", metaConfDev: {
template: "./src/web/html/index.html", target: "node",
compileTime: compileTime, entry: "./src/core/config/OperationConfig.js",
version: pkg.version, output: {
}) filename: "MetaConfig.js",
], path: __dirname + "/src/core/config/",
library: "MetaConfig",
libraryTarget: "commonjs2",
libraryExport: "default"
},
externals: [NodeExternals()],
watch: true watch: true
}, },
webProd: { web: {
target: "web", target: "web",
entry: "./src/web/index.js", entry: Object.assign({
main: "./src/web/index.js"
}, moduleEntryPoints),
output: { output: {
filename: "scripts.js",
path: __dirname + "/build/prod" path: __dirname + "/build/prod"
}, },
resolve: {
alias: {
"./config/modules/OpModules.js": "./config/modules/Default.js"
}
},
plugins: [ plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.UglifyJsPlugin({ new webpack.optimize.UglifyJsPlugin({
compress: { compress: {
"screw_ie8": true, "screw_ie8": true,
@ -268,9 +233,10 @@ module.exports = function (grunt) {
}, },
comments: false, comments: false,
}), }),
new HtmlWebpackPlugin({ // Main version new HtmlWebpackPlugin({
filename: "index.html", filename: "index.html",
template: "./src/web/html/index.html", template: "./src/web/html/index.html",
chunks: ["main"],
compileTime: compileTime, compileTime: compileTime,
version: pkg.version, version: pkg.version,
minify: { minify: {
@ -280,7 +246,27 @@ module.exports = function (grunt) {
minifyCSS: true minifyCSS: true
} }
}), }),
new HtmlWebpackPlugin({ // Inline version ]
},
webInline: {
target: "web",
entry: "./src/web/index.js",
output: {
filename: "scripts.js",
path: __dirname + "/build/prod"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new webpack.optimize.UglifyJsPlugin({
compress: {
"screw_ie8": true,
"dead_code": true,
"unused": true,
"warnings": false
},
comments: false,
}),
new HtmlWebpackPlugin({
filename: "cyberchef.htm", filename: "cyberchef.htm",
template: "./src/web/html/index.html", template: "./src/web/html/index.html",
compileTime: compileTime, compileTime: compileTime,
@ -302,7 +288,10 @@ module.exports = function (grunt) {
output: { output: {
filename: "index.js", filename: "index.js",
path: __dirname + "/build/test" path: __dirname + "/build/test"
} },
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
}, },
node: { node: {
target: "node", target: "node",
@ -313,21 +302,77 @@ module.exports = function (grunt) {
path: __dirname + "/build/node", path: __dirname + "/build/node",
library: "CyberChef", library: "CyberChef",
libraryTarget: "commonjs2" libraryTarget: "commonjs2"
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS)
]
}
},
"webpack-dev-server": {
options: {
webpack: webpackConfig,
host: "0.0.0.0",
disableHostCheck: true,
overlay: true,
inline: false,
clientLogLevel: "error",
stats: {
children: false,
chunks: false,
modules: false,
warningsFilter: /source-map/,
}
},
start: {
webpack: {
target: "web",
entry: Object.assign({
main: "./src/web/index.js"
}, moduleEntryPoints),
resolve: {
alias: {
"./config/modules/OpModules.js": "./config/modules/Default.js"
}
},
plugins: [
new webpack.DefinePlugin(BUILD_CONSTANTS),
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/web/html/index.html",
chunks: ["main"],
compileTime: compileTime,
version: pkg.version,
})
]
} }
} }
}, },
copy: { copy: {
ghPages: { ghPages: {
options: { options: {
process: function (content) { process: function (content, srcpath) {
// Add Google Analytics code to index.html // Add Google Analytics code to index.html
content = content.replace("</body></html>", if (srcpath.indexOf("index.html") >= 0) {
grunt.file.read("src/web/static/ga.html") + "</body></html>"); content = content.replace("</body></html>",
return grunt.template.process(content); grunt.file.read("src/web/static/ga.html") + "</body></html>");
} return grunt.template.process(content, srcpath);
} else {
return content;
}
},
noProcess: ["**", "!**/*.html"]
}, },
src: "build/prod/index.html", files: [
dest: "build/prod/index.html" {
src: "build/prod/index.html",
dest: "build/prod/index.html"
},
{
expand: true,
src: "docs/**",
dest: "build/prod/"
}
]
} }
}, },
chmod: { chmod: {

View File

@ -1,8 +1,12 @@
# CyberChef # CyberChef
[![Build Status](https://travis-ci.org/gchq/CyberChef.svg?branch=master)](https://travis-ci.org/gchq/CyberChef) [![Build Status](https://travis-ci.org/gchq/CyberChef.svg?branch=master)](https://travis-ci.org/gchq/CyberChef)
[![npm](https://badge.fury.io/js/cyberchef.svg)](https://www.npmjs.com/package/cyberchef) [![dependencies Status](https://david-dm.org/gchq/CyberChef/status.svg)](https://david-dm.org/gchq/CyberChef)
![](https://reposs.herokuapp.com/?path=gchq/CyberChef&color=brightgreen) [![npm](http://img.shields.io/npm/v/cyberchef.svg)](https://www.npmjs.com/package/cyberchef)
![](https://reposs.herokuapp.com/?path=gchq/CyberChef&color=blue)
[![](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/gchq/CyberChef/blob/master/LICENSE)
[![Gitter](https://badges.gitter.im/gchq/CyberChef.svg)](https://gitter.im/gchq/CyberChef?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
#### *The Cyber Swiss Army Knife* #### *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] - [Convert a date and time to a different time zone][3]
- [Parse a Teredo IPv6 address][4] - [Parse a Teredo IPv6 address][4]
- [Convert data from a hexdump, then decompress][5] - [Convert data from a hexdump, then decompress][5]
- [Display multiple timestamps as full dates][6] - [Decrypt and disassemble shellcode][6]
- [Carry out different operations on data of different types][7] - [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 ## Features
@ -56,7 +62,7 @@ You can use as many operations as you like in simple or complex ways. Some examp
- Search - 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. - 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 - 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 - 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). - 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 - 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 [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 [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 [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 [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)Conditional_Jump('1',2,10)To_Hex('Space')Return()To_Base64('A-Za-z0-9%2B/%3D')&input=U29tZSBkYXRhIHdpdGggYSAxIGluIGl0ClNvbWUgZGF0YSB3aXRoIGEgMiBpbiBpdA [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.io/CyberChef/#recipe=XOR(%7B'option':'Hex','string':'3a'%7D,'',false)To_Hexdump(16,false,false)&input=VGhlIGFuc3dlciB0byB0aGUgdWx0aW1hdGUgcXVlc3Rpb24gb2YgbGlmZSwgdGhlIFVuaXZlcnNlLCBhbmQgZXZlcnl0aGluZyBpcyA0Mi4 [8]: 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
[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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -19,7 +19,7 @@
"outputSourcePath": true, "outputSourcePath": true,
"dateFormat": "ddd MMM Do YYYY", "dateFormat": "ddd MMM Do YYYY",
"sort": false, "sort": false,
"logoFile": "../build/prod/images/cyberchef-32x32.png", "logoFile": "cyberchef-32x32.png",
"cleverLinks": false, "cleverLinks": false,
"monospaceLinks": false, "monospaceLinks": false,
"protocol": "html://", "protocol": "html://",

4044
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "cyberchef", "name": "cyberchef",
"version": "5.16.3", "version": "6.4.6",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.", "description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>", "author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef", "homepage": "https://gchq.github.io/CyberChef",
@ -30,67 +30,76 @@
"main": "build/node/CyberChef.js", "main": "build/node/CyberChef.js",
"bugs": "https://github.com/gchq/CyberChef/issues", "bugs": "https://github.com/gchq/CyberChef/issues",
"devDependencies": { "devDependencies": {
"babel-core": "^6.24.0", "babel-core": "^6.26.0",
"babel-loader": "^7.1.1", "babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0", "babel-preset-env": "^1.6.1",
"css-loader": "^0.28.4", "css-loader": "^0.28.7",
"exports-loader": "^0.6.4", "exports-loader": "^0.6.4",
"extract-text-webpack-plugin": "^3.0.0", "extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^0.11.2", "file-loader": "^1.1.5",
"grunt": ">=0.4.5", "grunt": ">=1.0.1",
"grunt-accessibility": "~5.0.0", "grunt-accessibility": "~5.0.0",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-concurrent": "^2.3.1",
"grunt-contrib-clean": "~1.1.0", "grunt-contrib-clean": "~1.1.0",
"grunt-contrib-copy": "~1.0.0", "grunt-contrib-copy": "~1.0.0",
"grunt-eslint": "^20.0.0", "grunt-eslint": "^20.1.0",
"grunt-exec": "~3.0.0", "grunt-exec": "~3.0.0",
"grunt-execute": "^0.2.2", "grunt-execute": "^0.2.2",
"grunt-jsdoc": "^2.1.0", "grunt-jsdoc": "^2.2.0",
"grunt-webpack": "^3.0.2", "grunt-webpack": "^3.0.2",
"html-webpack-plugin": "^2.30.1", "html-webpack-plugin": "^2.30.1",
"imports-loader": "^0.7.1", "imports-loader": "^0.7.1",
"ink-docstrap": "^1.1.4", "ink-docstrap": "^1.3.2",
"jsdoc-babel": "^0.3.0", "jsdoc-babel": "^0.3.0",
"less": "^2.7.2", "less": "^2.7.3",
"less-loader": "^4.0.5", "less-loader": "^4.0.5",
"postcss-css-variables": "^0.7.0", "postcss-css-variables": "^0.8.0",
"postcss-import": "^10.0.0", "postcss-import": "^11.0.0",
"postcss-loader": "^2.0.5", "postcss-loader": "^2.0.8",
"style-loader": "^0.18.2", "style-loader": "^0.19.0",
"url-loader": "^0.5.8", "url-loader": "^0.6.2",
"web-resource-inliner": "^4.1.0", "val-loader": "^1.1.0",
"webpack": "^3.4.1", "web-resource-inliner": "^4.2.0",
"webpack-node-externals": "^1.6.0" "webpack": "^3.8.1",
"webpack-dev-server": "^2.9.4",
"webpack-node-externals": "^1.6.0",
"worker-loader": "^1.1.0"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.23.0", "babel-polyfill": "^6.26.0",
"bootstrap": "^3.3.7", "bootstrap": "^3.3.7",
"bootstrap-colorpicker": "^2.5.1", "bootstrap-colorpicker": "^2.5.2",
"bootstrap-switch": "^3.3.4", "bootstrap-switch": "^3.3.4",
"crypto-api": "^0.6.2", "crypto-api": "^0.7.5",
"crypto-js": "^3.1.9-1", "crypto-js": "^3.1.9-1",
"diff": "^3.3.0", "diff": "^3.4.0",
"escodegen": "^1.8.1", "escodegen": "^1.9.0",
"esmangle": "^1.0.1", "esmangle": "^1.0.1",
"esprima": "^4.0.0", "esprima": "^4.0.0",
"exif-parser": "^0.1.12", "exif-parser": "^0.1.12",
"google-code-prettify": "^1.0.5", "google-code-prettify": "^1.0.5",
"jquery": "^3.1.1", "jquery": "^3.2.1",
"js-crc": "^0.2.0",
"js-sha3": "^0.6.1",
"jsbn": "^1.1.0", "jsbn": "^1.1.0",
"jsonpath": "^0.2.12", "jsonpath": "^1.0.0",
"jsrsasign": "8.0.3", "jsrsasign": "8.0.4",
"lodash": "^4.17.4", "lodash": "^4.17.4",
"moment": "^2.17.1", "moment": "^2.19.2",
"moment-timezone": "^0.5.11", "moment-timezone": "^0.5.14",
"node-md6": "^0.1.0",
"otp": "^0.1.3",
"sladex-blowfish": "^0.8.1", "sladex-blowfish": "^0.8.1",
"sortablejs": "^1.5.1", "sortablejs": "^1.7.0",
"split.js": "^1.2.0", "split.js": "^1.3.5",
"vkbeautify": "^0.99.3", "vkbeautify": "^0.99.3",
"xmldom": "^0.1.27", "xmldom": "^0.1.27",
"xpath": "0.0.24", "xpath": "0.0.24",
"zlibjs": "^0.3.1" "zlibjs": "^0.3.1"
}, },
"scripts": { "scripts": {
"start": "grunt dev",
"build": "grunt prod", "build": "grunt prod",
"test": "grunt test", "test": "grunt test",
"docs": "grunt docs" "docs": "grunt docs"

View File

@ -30,7 +30,6 @@ const Chef = function() {
* @returns {string} response.result - The output of the recipe * @returns {string} response.result - The output of the recipe
* @returns {string} response.type - The data type of the result * @returns {string} response.type - The data type of the result
* @returns {number} response.progress - The position that we have got to in the recipe * @returns {number} response.progress - The position that we have got to in the recipe
* @returns {number} response.options - The app options object (which may have been changed)
* @returns {number} response.duration - The number of ms it took to execute the recipe * @returns {number} response.duration - The number of ms it took to execute the recipe
* @returns {number} response.error - The error object thrown by a failed operation (false if no error) * @returns {number} response.error - The error object thrown by a failed operation (false if no error)
*/ */
@ -40,12 +39,7 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
containsFc = recipe.containsFlowControl(), containsFc = recipe.containsFlowControl(),
error = false; error = false;
// Reset attemptHighlight flag if (containsFc && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
if (options.hasOwnProperty("attemptHighlight")) {
options.attemptHighlight = true;
}
if (containsFc) options.attemptHighlight = false;
// Clean up progress // Clean up progress
if (progress >= recipeConfig.length) { if (progress >= recipeConfig.length) {
@ -74,9 +68,10 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
try { try {
progress = await recipe.execute(this.dish, progress); progress = await recipe.execute(this.dish, progress);
} catch (err) { } catch (err) {
// Return the error in the result so that everything else gets correctly updated console.log(err);
// rather than throwing it here and losing state info. error = {
error = err; displayStr: err.displayStr,
};
progress = err.progress; progress = err.progress;
} }
@ -86,7 +81,6 @@ Chef.prototype.bake = async function(inputText, recipeConfig, options, progress,
this.dish.get(Dish.STRING), this.dish.get(Dish.STRING),
type: Dish.enumLookup(this.dish.type), type: Dish.enumLookup(this.dish.type),
progress: progress, progress: progress,
options: options,
duration: new Date().getTime() - startTime, duration: new Date().getTime() - startTime,
error: error error: error
}; };
@ -123,4 +117,38 @@ Chef.prototype.silentBake = function(recipeConfig) {
return new Date().getTime() - startTime; return new Date().getTime() - startTime;
}; };
/**
* Calculates highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
* @returns {Object}
*/
Chef.prototype.calculateHighlights = function(recipeConfig, direction, pos) {
const recipe = new Recipe(recipeConfig);
const highlights = recipe.generateHighlightList();
if (!highlights) return false;
for (let i = 0; i < highlights.length; i++) {
// Remove multiple highlights before processing again
pos = [pos[0]];
const func = direction === "forward" ? highlights[i].f : highlights[i].b;
if (typeof func == "function") {
pos = func(pos, highlights[i].args);
}
}
return {
pos: pos,
direction: direction
};
};
export default Chef; export default Chef;

197
src/core/ChefWorker.js Normal file
View File

@ -0,0 +1,197 @@
/**
* Web Worker to handle communications between the front-end and the core.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import "babel-polyfill";
import Chef from "./Chef.js";
import OperationConfig from "./config/MetaConfig.js";
import OpModules from "./config/modules/Default.js";
// Set up Chef instance
self.chef = new Chef();
self.OpModules = OpModules;
self.OperationConfig = OperationConfig;
// Tell the app that the worker has loaded and is ready to operate
self.postMessage({
action: "workerLoaded",
data: {}
});
/**
* Respond to message from parent thread.
*
* Messages should have the following format:
* {
* action: "bake" | "silentBake",
* data: {
* input: {string},
* recipeConfig: {[Object]},
* options: {Object},
* progress: {number},
* step: {boolean}
* } | undefined
* }
*/
self.addEventListener("message", function(e) {
// Handle message
const r = e.data;
switch (r.action) {
case "bake":
bake(r.data);
break;
case "silentBake":
silentBake(r.data);
break;
case "docURL":
// Used to set the URL of the current document so that scripts can be
// imported into an inline worker.
self.docURL = r.data;
break;
case "highlight":
calculateHighlights(
r.data.recipeConfig,
r.data.direction,
r.data.pos
);
break;
default:
break;
}
});
/**
* Baking handler
*
* @param {Object} data
*/
async function bake(data) {
// Ensure the relevant modules are loaded
loadRequiredModules(data.recipeConfig);
try {
const response = await self.chef.bake(
data.input, // The user's input
data.recipeConfig, // The configuration of the recipe
data.options, // Options set by the user
data.progress, // The current position in the recipe
data.step // Whether or not to take one step or execute the whole recipe
);
self.postMessage({
action: "bakeSuccess",
data: response
});
} catch (err) {
self.postMessage({
action: "bakeError",
data: err
});
}
}
/**
* Silent baking handler
*/
function silentBake(data) {
const duration = self.chef.silentBake(data.recipeConfig);
self.postMessage({
action: "silentBakeComplete",
data: duration
});
}
/**
* Checks that all required modules are loaded and loads them if not.
*
* @param {Object} recipeConfig
*/
function loadRequiredModules(recipeConfig) {
recipeConfig.forEach(op => {
let module = self.OperationConfig[op.op].module;
if (!OpModules.hasOwnProperty(module)) {
console.log("Loading module " + module);
self.sendStatusMessage("Loading module " + module);
self.importScripts(self.docURL + "/" + module + ".js");
}
});
}
/**
* Calculates highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
*/
function calculateHighlights(recipeConfig, direction, pos) {
pos = self.chef.calculateHighlights(recipeConfig, direction, pos);
self.postMessage({
action: "highlightsCalculated",
data: pos
});
}
/**
* Send status update to the app.
*
* @param {string} msg
*/
self.sendStatusMessage = function(msg) {
self.postMessage({
action: "statusMessage",
data: msg
});
};
/**
* Send an option value update to the app.
*
* @param {string} option
* @param {*} value
*/
self.setOption = function(option, value) {
self.postMessage({
action: "optionUpdate",
data: {
option: option,
value: 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
}
});
};

View File

@ -13,22 +13,6 @@ import Dish from "./Dish.js";
*/ */
const FlowControl = { const FlowControl = {
/**
* @constant
* @default
*/
FORK_DELIM: "\\n",
/**
* @constant
* @default
*/
MERGE_DELIM: "\\n",
/**
* @constant
* @default
*/
FORK_IGNORE_ERRORS: false,
/** /**
* Fork operation. * Fork operation.
* *
@ -107,15 +91,72 @@ const FlowControl = {
/** /**
* @constant * Register operation.
* @default *
* @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.
*/ */
JUMP_NUM: 0, runRegister: function(state) {
/** const ings = state.opList[state.progress].getIngValues(),
* @constant extractorStr = ings[0],
* @default i = ings[1],
*/ m = ings[2];
MAX_JUMPS: 10,
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. * Jump operation.

View File

@ -1,5 +1,7 @@
import Dish from "./Dish.js"; import Dish from "./Dish.js";
import Ingredient from "./Ingredient.js"; import Ingredient from "./Ingredient.js";
import OperationConfig from "./config/MetaConfig.js";
import OpModules from "./config/modules/OpModules.js";
/** /**
@ -11,10 +13,10 @@ import Ingredient from "./Ingredient.js";
* *
* @class * @class
* @param {string} operationName * @param {string} operationName
* @param {Object} operationConfig
*/ */
const Operation = function(operationName, operationConfig) { const Operation = function(operationName) {
this.name = operationName; this.name = operationName;
this.module = "";
this.description = ""; this.description = "";
this.inputType = -1; this.inputType = -1;
this.outputType = -1; this.outputType = -1;
@ -25,8 +27,8 @@ const Operation = function(operationName, operationConfig) {
this.disabled = false; this.disabled = false;
this.ingList = []; this.ingList = [];
if (operationConfig) { if (OperationConfig.hasOwnProperty(this.name)) {
this._parseConfig(operationConfig); this._parseConfig(OperationConfig[this.name]);
} }
}; };
@ -38,19 +40,28 @@ const Operation = function(operationName, operationConfig) {
* @param {Object} operationConfig * @param {Object} operationConfig
*/ */
Operation.prototype._parseConfig = function(operationConfig) { Operation.prototype._parseConfig = function(operationConfig) {
this.module = operationConfig.module;
this.description = operationConfig.description; this.description = operationConfig.description;
this.inputType = Dish.typeEnum(operationConfig.inputType); this.inputType = Dish.typeEnum(operationConfig.inputType);
this.outputType = Dish.typeEnum(operationConfig.outputType); this.outputType = Dish.typeEnum(operationConfig.outputType);
this.run = operationConfig.run;
this.highlight = operationConfig.highlight; this.highlight = operationConfig.highlight;
this.highlightReverse = operationConfig.highlightReverse; this.highlightReverse = operationConfig.highlightReverse;
this.flowControl = operationConfig.flowControl; this.flowControl = operationConfig.flowControl;
this.run = OpModules[this.module][this.name];
for (let a = 0; a < operationConfig.args.length; a++) { for (let a = 0; a < operationConfig.args.length; a++) {
const ingredientConfig = operationConfig.args[a]; const ingredientConfig = operationConfig.args[a];
const ingredient = new Ingredient(ingredientConfig); const ingredient = new Ingredient(ingredientConfig);
this.addIngredient(ingredient); this.addIngredient(ingredient);
} }
if (this.highlight === "func") {
this.highlight = OpModules[this.module][`${this.name}-highlight`];
}
if (this.highlightReverse === "func") {
this.highlightReverse = OpModules[this.module][`${this.name}-highlightReverse`];
}
}; };

View File

@ -1,5 +1,4 @@
import Operation from "./Operation.js"; import Operation from "./Operation.js";
import OperationConfig from "./config/OperationConfig.js";
/** /**
@ -30,8 +29,7 @@ const Recipe = function(recipeConfig) {
Recipe.prototype._parseConfig = function(recipeConfig) { Recipe.prototype._parseConfig = function(recipeConfig) {
for (let c = 0; c < recipeConfig.length; c++) { for (let c = 0; c < recipeConfig.length; c++) {
const operationName = recipeConfig[c].op; const operationName = recipeConfig[c].op;
const operationConfig = OperationConfig[operationName]; const operation = new Operation(operationName);
const operation = new Operation(operationName, operationConfig);
operation.setIngValues(recipeConfig[c].args); operation.setIngValues(recipeConfig[c].args);
operation.setBreakpoint(recipeConfig[c].breakpoint); operation.setBreakpoint(recipeConfig[c].breakpoint);
operation.setDisabled(recipeConfig[c].disabled); operation.setDisabled(recipeConfig[c].disabled);
@ -147,7 +145,7 @@ Recipe.prototype.lastOpIndex = function(startIndex) {
*/ */
Recipe.prototype.execute = async function(dish, startFrom) { Recipe.prototype.execute = async function(dish, startFrom) {
startFrom = startFrom || 0; 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++) { for (let i = startFrom; i < this.opList.length; i++) {
op = this.opList[i]; op = this.opList[i];
@ -164,15 +162,17 @@ Recipe.prototype.execute = async function(dish, startFrom) {
if (op.isFlowControl()) { if (op.isFlowControl()) {
// Package up the current state // Package up the current state
let state = { let state = {
"progress": i, "progress": i,
"dish": dish, "dish": dish,
"opList": this.opList, "opList": this.opList,
"numJumps": numJumps "numJumps": numJumps,
"numRegisters": numRegisters
}; };
state = await op.run(state); state = await op.run(state);
i = state.progress; i = state.progress;
numJumps = state.numJumps; numJumps = state.numJumps;
numRegisters = state.numRegisters;
} else { } else {
output = await op.run(input, op.getIngValues()); output = await op.run(input, op.getIngValues());
dish.set(output, op.outputType); dish.set(output, op.outputType);
@ -217,4 +217,37 @@ Recipe.prototype.fromString = function(recipeStr) {
this._parseConfig(recipeConfig); this._parseConfig(recipeConfig);
}; };
/**
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
* entire recipe supports highlighting.
*
* @returns {Object[]} highlights
* @returns {function} highlights[].f
* @returns {function} highlights[].b
* @returns {Object[]} highlights[].args
*/
Recipe.prototype.generateHighlightList = function() {
const highlights = [];
for (let i = 0; i < this.opList.length; i++) {
let op = this.opList[i];
if (op.isDisabled()) continue;
// If any breakpoints are set, do not attempt to highlight
if (op.isBreakpoint()) return false;
// If any of the operations do not support highlighting, fail immediately.
if (op.highlight === false || op.highlight === undefined) return false;
highlights.push({
f: op.highlight,
b: op.highlightReverse,
args: op.getIngValues()
});
}
return highlights;
};
export default Recipe; export default Recipe;

View File

@ -234,7 +234,7 @@ const Utils = {
* @returns {string} * @returns {string}
*/ */
printable: function(str, preserveWs) { printable: function(str, preserveWs) {
if (typeof window !== "undefined" && window.app && !window.app.options.treatAsUtf8) { if (ENVIRONMENT_IS_WEB() && window.app && !window.app.options.treatAsUtf8) {
str = Utils.byteArrayToChars(Utils.strToByteArray(str)); str = Utils.byteArrayToChars(Utils.strToByteArray(str));
} }
@ -384,8 +384,12 @@ const Utils = {
let wordArray = CryptoJS.enc.Utf8.parse(str), let wordArray = CryptoJS.enc.Utf8.parse(str),
byteArray = Utils.wordArrayToByteArray(wordArray); byteArray = Utils.wordArrayToByteArray(wordArray);
if (typeof window !== "undefined" && str.length !== wordArray.sigBytes) { if (str.length !== wordArray.sigBytes) {
window.app.options.attemptHighlight = false; if (ENVIRONMENT_IS_WORKER()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
window.app.options.attemptHighlight = false;
}
} }
return byteArray; return byteArray;
}, },
@ -405,7 +409,7 @@ const Utils = {
* Utils.strToCharcode("你好"); * Utils.strToCharcode("你好");
*/ */
strToCharcode: function(str) { strToCharcode: function(str) {
const charcode = new Array(); const charcode = [];
for (let i = 0; i < str.length; i++) { for (let i = 0; i < str.length; i++) {
let ord = str.charCodeAt(i); let ord = str.charCodeAt(i);
@ -448,8 +452,13 @@ const Utils = {
let wordArray = new CryptoJS.lib.WordArray.init(words, byteArray.length), let wordArray = new CryptoJS.lib.WordArray.init(words, byteArray.length),
str = CryptoJS.enc.Utf8.stringify(wordArray); str = CryptoJS.enc.Utf8.stringify(wordArray);
if (typeof window !== "undefined" && str.length !== wordArray.sigBytes) if (str.length !== wordArray.sigBytes) {
window.app.options.attemptHighlight = false; if (ENVIRONMENT_IS_WORKER()) {
self.setOption("attemptHighlight", false);
} else if (ENVIRONMENT_IS_WEB()) {
window.app.options.attemptHighlight = false;
}
}
return str; return str;
} catch (err) { } catch (err) {
// If it fails, treat it as ANSI // If it fails, treat it as ANSI
@ -1235,7 +1244,8 @@ const Utils = {
"Forward slash": /\//g, "Forward slash": /\//g,
"Backslash": /\\/g, "Backslash": /\\/g,
"0x": /0x/g, "0x": /0x/g,
"\\x": /\\x/g "\\x": /\\x/g,
"None": /\s+/g // Included here to remove whitespace when there shouldn't be any
}, },

View File

@ -122,6 +122,8 @@ const Categories = [
"AND", "AND",
"ADD", "ADD",
"SUB", "SUB",
"Bit shift left",
"Bit shift right",
"Rotate left", "Rotate left",
"Rotate right", "Rotate right",
"ROT13", "ROT13",
@ -245,20 +247,24 @@ const Categories = [
"MD2", "MD2",
"MD4", "MD4",
"MD5", "MD5",
"MD6",
"SHA0", "SHA0",
"SHA1", "SHA1",
"SHA224", "SHA2",
"SHA256",
"SHA384",
"SHA512",
"SHA3", "SHA3",
"RIPEMD-160", "Keccak",
"Shake",
"RIPEMD",
"HAS-160",
"Whirlpool",
"Snefru",
"HMAC", "HMAC",
"Fletcher-8 Checksum", "Fletcher-8 Checksum",
"Fletcher-16 Checksum", "Fletcher-16 Checksum",
"Fletcher-32 Checksum", "Fletcher-32 Checksum",
"Fletcher-64 Checksum", "Fletcher-64 Checksum",
"Adler-32 Checksum", "Adler-32 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum", "CRC-32 Checksum",
"TCP/IP Checksum", "TCP/IP Checksum",
] ]
@ -282,6 +288,7 @@ const Categories = [
"XPath expression", "XPath expression",
"JPath expression", "JPath expression",
"CSS selector", "CSS selector",
"Microsoft Script Decoder",
"Strip HTML tags", "Strip HTML tags",
"Diff", "Diff",
"To Snake case", "To Snake case",
@ -296,7 +303,10 @@ const Categories = [
"Frequency distribution", "Frequency distribution",
"Detect File Type", "Detect File Type",
"Scan for Embedded Files", "Scan for Embedded Files",
"Disassemble x86",
"Generate UUID", "Generate UUID",
"Generate TOTP",
"Generate HOTP",
"Render Image", "Render Image",
"Remove EXIF", "Remove EXIF",
"Extract EXIF", "Extract EXIF",
@ -308,6 +318,7 @@ const Categories = [
ops: [ ops: [
"Fork", "Fork",
"Merge", "Merge",
"Register",
"Jump", "Jump",
"Conditional Jump", "Conditional Jump",
"Return", "Return",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
import CharEnc from "../../operations/CharEnc.js";
/**
* CharEnc module.
*
* Libraries:
* - cptable
* - CryptoJS
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.CharEnc = {
"Encode text": CharEnc.runEncode,
"Decode text": CharEnc.runDecode,
};
export default OpModules;

View File

@ -0,0 +1,42 @@
import Cipher from "../../operations/Cipher.js";
/**
* Ciphers module.
*
* Libraries:
* - CryptoJS
* - Blowfish
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Ciphers = {
"AES Encrypt": Cipher.runAesEnc,
"AES Decrypt": Cipher.runAesDec,
"Blowfish Encrypt": Cipher.runBlowfishEnc,
"Blowfish Decrypt": Cipher.runBlowfishDec,
"DES Encrypt": Cipher.runDesEnc,
"DES Decrypt": Cipher.runDesDec,
"Triple DES Encrypt": Cipher.runTripleDesEnc,
"Triple DES Decrypt": Cipher.runTripleDesDec,
"Rabbit Encrypt": Cipher.runRabbitEnc,
"Rabbit Decrypt": Cipher.runRabbitDec,
"Derive PBKDF2 key": Cipher.runPbkdf2,
"Derive EVP key": Cipher.runEvpkdf,
"RC4": Cipher.runRc4,
"RC4 Drop": Cipher.runRc4drop,
"Vigenère Encode": Cipher.runVigenereEnc,
"Vigenère Decode": Cipher.runVigenereDec,
"Bifid Cipher Encode": Cipher.runBifidEnc,
"Bifid Cipher Decode": Cipher.runBifidDec,
"Affine Cipher Encode": Cipher.runAffineEnc,
"Affine Cipher Decode": Cipher.runAffineDec,
"Atbash Cipher": Cipher.runAtbash,
"Substitute": Cipher.runSubstitute,
};
export default OpModules;

View File

@ -0,0 +1,44 @@
import JS from "../../operations/JS.js";
import Code from "../../operations/Code.js";
/**
* Code module.
*
* Libraries:
* - lodash
* - vkbeautify
* - xmldom
* - xpath
* - jpath
* - googlecodeprettify
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Code = {
"JavaScript Parser": JS.runParse,
"JavaScript Beautify": JS.runBeautify,
"JavaScript Minify": JS.runMinify,
"Syntax highlighter": Code.runSyntaxHighlight,
"Generic Code Beautify": Code.runGenericBeautify,
"JSON Beautify": Code.runJsonBeautify,
"JSON Minify": Code.runJsonMinify,
"XML Beautify": Code.runXmlBeautify,
"XML Minify": Code.runXmlMinify,
"SQL Beautify": Code.runSqlBeautify,
"SQL Minify": Code.runSqlMinify,
"CSS Beautify": Code.runCssBeautify,
"CSS Minify": Code.runCssMinify,
"XPath expression": Code.runXpath,
"CSS selector": Code.runCSSQuery,
"To Snake case": Code.runToSnakeCase,
"To Camel case": Code.runToCamelCase,
"To Kebab case": Code.runToKebabCase,
"JPath expression": Code.runJpath,
};
export default OpModules;

View File

@ -0,0 +1,32 @@
import Compress from "../../operations/Compress.js";
/**
* Compression module.
*
* Libraries:
* - zlib.js
* - bzip2.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Compression = {
"Raw Deflate": Compress.runRawDeflate,
"Raw Inflate": Compress.runRawInflate,
"Zlib Deflate": Compress.runZlibDeflate,
"Zlib Inflate": Compress.runZlibInflate,
"Gzip": Compress.runGzip,
"Gunzip": Compress.runGunzip,
"Zip": Compress.runPkzip,
"Unzip": Compress.runPkunzip,
"Bzip2 Decompress": Compress.runBzip2Decompress,
"Tar": Compress.runTar,
"Untar": Compress.runUntar,
};
export default OpModules;

View File

@ -0,0 +1,188 @@
import FlowControl from "../../FlowControl.js";
import Base from "../../operations/Base.js";
import Base58 from "../../operations/Base58.js";
import Base64 from "../../operations/Base64.js";
import BCD from "../../operations/BCD.js";
import BitwiseOp from "../../operations/BitwiseOp.js";
import ByteRepr from "../../operations/ByteRepr.js";
import Convert from "../../operations/Convert.js";
import DateTime from "../../operations/DateTime.js";
import Endian from "../../operations/Endian.js";
import Entropy from "../../operations/Entropy.js";
import Extract from "../../operations/Extract.js";
import FileType from "../../operations/FileType.js";
import Hexdump from "../../operations/Hexdump.js";
import HTML from "../../operations/HTML.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 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 UUID from "../../operations/UUID.js";
/**
* Default module.
*
* The Default module is for operations that are expected to be very commonly used or
* do not require any libraries. This module is loaded into the app at compile time.
*
* Libraries:
* - Utils.js
* - CryptoJS
* - otp
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Default = {
"To Hexdump": Hexdump.runTo,
"From Hexdump": Hexdump.runFrom,
"To Hex": ByteRepr.runToHex,
"From Hex": ByteRepr.runFromHex,
"To Octal": ByteRepr.runToOct,
"From Octal": ByteRepr.runFromOct,
"To Charcode": ByteRepr.runToCharcode,
"From Charcode": ByteRepr.runFromCharcode,
"To Decimal": ByteRepr.runToDecimal,
"From Decimal": ByteRepr.runFromDecimal,
"To Binary": ByteRepr.runToBinary,
"From Binary": ByteRepr.runFromBinary,
"To Hex Content": ByteRepr.runToHexContent,
"From Hex Content": ByteRepr.runFromHexContent,
"To Base64": Base64.runTo,
"From Base64": Base64.runFrom,
"Show Base64 offsets": Base64.runOffsets,
"To Base32": Base64.runTo32,
"From Base32": Base64.runFrom32,
"To Base58": Base58.runTo,
"From Base58": Base58.runFrom,
"To Base": Base.runTo,
"From Base": Base.runFrom,
"To BCD": BCD.runToBCD,
"From BCD": BCD.runFromBCD,
"To HTML Entity": HTML.runToEntity,
"From HTML Entity": HTML.runFromEntity,
"Strip HTML tags": HTML.runStripTags,
"Parse colour code": HTML.runParseColourCode,
"Unescape Unicode Characters": Unicode.runUnescape,
"To Quoted Printable": QuotedPrintable.runTo,
"From Quoted Printable": QuotedPrintable.runFrom,
"Swap endianness": Endian.runSwapEndianness,
"ROT13": Rotate.runRot13,
"ROT47": Rotate.runRot47,
"Rotate left": Rotate.runRotl,
"Rotate right": Rotate.runRotr,
"Bit shift left": BitwiseOp.runBitShiftLeft,
"Bit shift right": BitwiseOp.runBitShiftRight,
"XOR": BitwiseOp.runXor,
"XOR Brute Force": BitwiseOp.runXorBrute,
"OR": BitwiseOp.runXor,
"NOT": BitwiseOp.runNot,
"AND": BitwiseOp.runAnd,
"ADD": BitwiseOp.runAdd,
"SUB": BitwiseOp.runSub,
"To Morse Code": MorseCode.runTo,
"From Morse Code": MorseCode.runFrom,
"Format MAC addresses": MAC.runFormat,
"Encode NetBIOS Name": NetBIOS.runEncodeName,
"Decode NetBIOS Name": NetBIOS.runDecodeName,
"Regular expression": StrUtils.runRegex,
"Offset checker": StrUtils.runOffsetChecker,
"To Upper case": StrUtils.runUpper,
"To Lower case": StrUtils.runLower,
"Find / Replace": StrUtils.runFindReplace,
"Split": StrUtils.runSplit,
"Filter": StrUtils.runFilter,
"Escape string": StrUtils.runEscape,
"Unescape string": StrUtils.runUnescape,
"Head": StrUtils.runHead,
"Tail": StrUtils.runTail,
"Remove whitespace": Tidy.runRemoveWhitespace,
"Remove null bytes": Tidy.runRemoveNulls,
"Drop bytes": Tidy.runDropBytes,
"Take bytes": Tidy.runTakeBytes,
"Pad lines": Tidy.runPad,
"Reverse": SeqUtils.runReverse,
"Sort": SeqUtils.runSort,
"Unique": SeqUtils.runUnique,
"Count occurrences": SeqUtils.runCount,
"Add line numbers": SeqUtils.runAddLineNumbers,
"Remove line numbers": SeqUtils.runRemoveLineNumbers,
"Expand alphabet range": SeqUtils.runExpandAlphRange,
"Convert distance": Convert.runDistance,
"Convert area": Convert.runArea,
"Convert mass": Convert.runMass,
"Convert speed": Convert.runSpeed,
"Convert data units": Convert.runDataSize,
"Parse UNIX file permissions": OS.runParseUnixPerms,
"Parse DateTime": DateTime.runParse,
"Translate DateTime Format": DateTime.runTranslateFormat,
"From UNIX Timestamp": DateTime.runFromUnixTimestamp,
"To UNIX Timestamp": DateTime.runToUnixTimestamp,
"Strings": Extract.runStrings,
"Extract IP addresses": Extract.runIp,
"Extract email addresses": Extract.runEmail,
"Extract MAC addresses": Extract.runMac,
"Extract URLs": Extract.runUrls,
"Extract domains": Extract.runDomains,
"Extract file paths": Extract.runFilePaths,
"Extract dates": Extract.runDates,
"Microsoft Script Decoder": MS.runDecodeScript,
"Entropy": Entropy.runEntropy,
"Frequency distribution": Entropy.runFreqDistrib,
"Detect File Type": FileType.runDetect,
"Scan for Embedded Files": FileType.runScanForEmbeddedFiles,
"Generate UUID": UUID.runGenerateV4,
"Numberwang": Numberwang.run,
"Generate TOTP": OTP.runTOTP,
"Generate HOTP": OTP.runHOTP,
"Fork": FlowControl.runFork,
"Merge": FlowControl.runMerge,
"Register": FlowControl.runRegister,
"Jump": FlowControl.runJump,
"Conditional Jump": FlowControl.runCondJump,
"Return": FlowControl.runReturn,
"Comment": FlowControl.runComment,
/*
Highlighting functions.
This is a temporary solution as highlighting should be entirely
overhauled at some point.
*/
"From Base64-highlight": Base64.highlightFrom,
"From Base64-highlightReverse": Base64.highlightTo,
"To Base64-highlight": Base64.highlightTo,
"To Base64-highlightReverse": Base64.highlightFrom,
"From Hex-highlight": ByteRepr.highlightFrom,
"From Hex-highlightReverse": ByteRepr.highlightTo,
"To Hex-highlight": ByteRepr.highlightTo,
"To Hex-highlightReverse": ByteRepr.highlightFrom,
"From Charcode-highlight": ByteRepr.highlightFrom,
"From Charcode-highlightReverse": ByteRepr.highlightTo,
"To Charcode-highlight": ByteRepr.highlightTo,
"To Charcode-highlightReverse": ByteRepr.highlightFrom,
"From Binary-highlight": ByteRepr.highlightFromBinary,
"From Binary-highlightReverse": ByteRepr.highlightToBinary,
"To Binary-highlight": ByteRepr.highlightToBinary,
"To Binary-highlightReverse": ByteRepr.highlightFromBinary,
"From Hexdump-highlight": Hexdump.highlightFrom,
"From Hexdump-highlightReverse": Hexdump.highlightTo,
"To Hexdump-highlight": Hexdump.highlightTo,
"To Hexdump-highlightReverse": Hexdump.highlightFrom,
};
export default OpModules;

View File

@ -0,0 +1,20 @@
import Diff from "../../operations/Diff.js";
/**
* Diff module.
*
* Libraries:
* - JsDIff
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Diff = {
"Diff": Diff.runDiff,
};
export default OpModules;

View File

@ -0,0 +1,21 @@
import Punycode from "../../operations/Punycode.js";
/**
* Encodings module.
*
* Libraries:
* - punycode
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Encodings = {
"To Punycode": Punycode.runToAscii,
"From Punycode": Punycode.runToUnicode,
};
export default OpModules;

View File

@ -0,0 +1,22 @@
import HTTP from "../../operations/HTTP.js";
/**
* HTTP module.
*
* Libraries:
* - UAS_parser
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.HTTP = {
"HTTP request": HTTP.runHTTPRequest,
"Strip HTTP headers": HTTP.runStripHeaders,
"Parse User Agent": HTTP.runParseUserAgent,
};
export default OpModules;

View File

@ -0,0 +1,48 @@
import Checksum from "../../operations/Checksum.js";
import Hash from "../../operations/Hash.js";
/**
* Hashing module.
*
* Libraries:
* - CryptoApi
* - node-md6
* - js-sha3
* - ./Checksum.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Hashing = {
"Analyse hash": Hash.runAnalyse,
"Generate all hashes": Hash.runAll,
"MD2": Hash.runMD2,
"MD4": Hash.runMD4,
"MD5": Hash.runMD5,
"MD6": Hash.runMD6,
"SHA0": Hash.runSHA0,
"SHA1": Hash.runSHA1,
"SHA2": Hash.runSHA2,
"SHA3": Hash.runSHA3,
"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,
"Fletcher-32 Checksum": Checksum.runFletcher32,
"Fletcher-64 Checksum": Checksum.runFletcher64,
"Adler-32 Checksum": Checksum.runAdler32,
"CRC-16 Checksum": Checksum.runCRC16,
"CRC-32 Checksum": Checksum.runCRC32,
"TCP/IP Checksum": Checksum.runTCPIP,
};
export default OpModules;

View File

@ -0,0 +1,25 @@
import Image from "../../operations/Image.js";
/**
* Image module.
*
* Libraries:
* - exif-parser
* - remove-exif
* - ./FileType.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.Image = {
"Extract EXIF": Image.runExtractEXIF,
"Remove EXIF": Image.runRemoveEXIF,
"Render Image": Image.runRenderImage,
};
export default OpModules;

View File

@ -0,0 +1,28 @@
import IP from "../../operations/IP.js";
import Filetime from "../../operations/Filetime.js";
/**
* JSBN module.
*
* Libraries:
* - jsbn
* - ./Checksum.js
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.JSBN = {
"Parse IP range": IP.runParseIpRange,
"Parse IPv6 address": IP.runParseIPv6,
"Parse IPv4 header": IP.runParseIPv4Header,
"Change IP format": IP.runChangeIpFormat,
"Group IP addresses": IP.runGroupIps,
"Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
"UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
};
export default OpModules;

View File

@ -0,0 +1,41 @@
/**
* Imports all modules for builds which do not load modules separately.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
import OpModules from "./Default.js";
import CharEncModule from "./CharEnc.js";
import CipherModule from "./Ciphers.js";
import CodeModule from "./Code.js";
import CompressionModule from "./Compression.js";
import DiffModule from "./Diff.js";
import EncodingModule from "./Encodings.js";
import HashingModule from "./Hashing.js";
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,
CharEncModule,
CipherModule,
CodeModule,
CompressionModule,
DiffModule,
EncodingModule,
HashingModule,
HTTPModule,
ImageModule,
JSBNModule,
PublicKeyModule,
ShellcodeModule,
URLModule
);
export default OpModules;

View File

@ -0,0 +1,25 @@
import PublicKey from "../../operations/PublicKey.js";
/**
* PublicKey module.
*
* Libraries:
* - jsrsasign
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*/
let OpModules = typeof self === "undefined" ? {} : self.OpModules || {};
OpModules.PublicKey = {
"Parse X.509 certificate": PublicKey.runParseX509,
"Parse ASN.1 hex string": PublicKey.runParseAsn1HexString,
"PEM to Hex": PublicKey.runPemToHex,
"Hex to PEM": PublicKey.runHexToPem,
"Hex to Object Identifier": PublicKey.runHexToObjectIdentifier,
"Object Identifier to Hex": PublicKey.runObjectIdentifierToHex,
};
export default OpModules;

View 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;

View 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;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
/** /**
@ -92,7 +91,7 @@ const BitwiseOp = {
* @constant * @constant
* @default * @default
*/ */
XOR_BRUTE_KEY_LENGTH: ["1", "2"], XOR_BRUTE_KEY_LENGTH: 1,
/** /**
* @constant * @constant
* @default * @default
@ -122,37 +121,62 @@ const BitwiseOp = {
* @returns {string} * @returns {string}
*/ */
runXorBrute: function (input, args) { runXorBrute: function (input, args) {
const keyLength = parseInt(args[0], 10), const keyLength = args[0],
sampleLength = args[1], sampleLength = args[1],
sampleOffset = args[2], sampleOffset = args[2],
scheme = args[3], scheme = args[3],
nullPreserving = args[4], nullPreserving = args[4],
printKey = args[5], printKey = args[5],
outputHex = args[6], outputHex = args[6],
crib = args[7]; crib = args[7].toLowerCase();
let output = "", let output = [],
result, result,
resultUtf8, resultUtf8,
regex; record = "";
input = input.slice(sampleOffset, sampleOffset + sampleLength); input = input.slice(sampleOffset, sampleOffset + sampleLength);
if (crib !== "") { if (ENVIRONMENT_IS_WORKER())
regex = new RegExp(crib, "im"); self.sendStatusMessage("Calculating " + Math.pow(256, keyLength) + " values...");
}
/**
* Converts an integer to an array of bytes expressing that number.
*
* @param {number} int
* @param {number} len - Length of the resulting array
* @returns {array}
*/
const intToByteArray = (int, len) => {
let res = Array(len).fill(0);
for (let i = len - 1; i >= 0; i--) {
res[i] = int & 0xff;
int = int >>> 8;
}
return res;
};
for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) { for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) {
result = BitwiseOp._bitOp(input, Utils.fromHex(key.toString(16)), BitwiseOp._xor, nullPreserving, scheme); if (key % 10000 === 0 && ENVIRONMENT_IS_WORKER()) {
self.sendStatusMessage("Calculating " + l + " values... " + Math.floor(key / l * 100) + "%");
}
result = BitwiseOp._bitOp(input, intToByteArray(key, keyLength), BitwiseOp._xor, nullPreserving, scheme);
resultUtf8 = Utils.byteArrayToUtf8(result); resultUtf8 = Utils.byteArrayToUtf8(result);
if (crib !== "" && resultUtf8.search(regex) === -1) continue; record = "";
if (printKey) output += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
if (outputHex) output += Utils.toHex(result) + "\n"; if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue;
else output += Utils.printable(resultUtf8, false) + "\n"; if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": ";
if (printKey) output += "\n"; if (outputHex) {
record += Utils.toHex(result);
} else {
record += Utils.printable(resultUtf8, false);
}
output.push(record);
} }
return output;
return output.join("\n");
}, },
@ -228,6 +252,46 @@ const BitwiseOp = {
}, },
/**
* Bit shift left operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftLeft: function(input, args) {
const amount = args[0];
return input.map(b => {
return (b << amount) & 0xff;
});
},
/**
* @constant
* @default
*/
BIT_SHIFT_TYPE: ["Logical shift", "Arithmetic shift"],
/**
* Bit shift right operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {byteArray}
*/
runBitShiftRight: function(input, args) {
const amount = args[0],
type = args[1],
mask = type === "Logical shift" ? 0 : 0x80;
return input.map(b => {
return (b >>> amount) ^ (b & mask);
});
},
/** /**
* XOR bitwise calculation. * XOR bitwise calculation.
* *

View File

@ -1,4 +1,3 @@
/* globals app */
import Utils from "../Utils.js"; import Utils from "../Utils.js";
@ -119,11 +118,11 @@ const ByteRepr = {
else if (ordinal < 4294967296) padding = 8; else if (ordinal < 4294967296) padding = 8;
else padding = 2; else padding = 2;
if (padding > 2 && app) app.options.attemptHighlight = false; if (padding > 2 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
output += Utils.hex(ordinal, padding) + delim; output += Utils.hex(ordinal, padding) + delim;
} else { } else {
if (app) app.options.attemptHighlight = false; if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
output += ordinal.toString(base) + delim; output += ordinal.toString(base) + delim;
} }
} }
@ -149,9 +148,7 @@ const ByteRepr = {
throw "Error: Base argument must be between 2 and 36"; throw "Error: Base argument must be between 2 and 36";
} }
if (base !== 16 && app) { if (base !== 16 && ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
app.options.attemptHighlight = false;
}
// Split into groups of 2 if the whole string is concatenated and // Split into groups of 2 if the whole string is concatenated and
// too long to be a single character // too long to be a single character
@ -196,7 +193,7 @@ const ByteRepr = {
/** /**
* Highlight to hex * Highlight from hex
* *
* @param {Object[]} pos * @param {Object[]} pos
* @param {number} pos[].start * @param {number} pos[].start
@ -288,10 +285,8 @@ const ByteRepr = {
* @returns {byteArray} * @returns {byteArray}
*/ */
runFromBinary: function(input, args) { runFromBinary: function(input, args) {
if (args[0] !== "None") { const delimRegex = Utils.regexRep[args[0] || "Space"];
const delimRegex = Utils.regexRep[args[0] || "Space"]; input = input.replace(delimRegex, "");
input = input.replace(delimRegex, "");
}
const output = []; const output = [];
const byteLen = 8; const byteLen = 8;

View File

@ -1,6 +1,4 @@
import cptable from "../lib/js-codepage/cptable.js"; import cptable from "../lib/js-codepage/cptable.js";
import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
/** /**

View File

@ -1,3 +1,4 @@
import * as CRC from "js-crc";
import Utils from "../Utils.js"; import Utils from "../Utils.js";
@ -119,19 +120,24 @@ const Checksum = {
/** /**
* CRC-32 Checksum operation. * CRC-32 Checksum operation.
* *
* @param {byteArray} input * @param {string} input
* @param {Object[]} args * @param {Object[]} args
* @returns {string} * @returns {string}
*/ */
runCRC32: function(input, args) { runCRC32: function(input, args) {
let crcTable = global.crcTable || (global.crcTable = Checksum._genCRCTable()), return CRC.crc32(input);
crc = 0 ^ (-1); },
for (let i = 0; i < input.length; i++) {
crc = (crc >>> 8) ^ crcTable[(crc ^ input[i]) & 0xff];
}
return Utils.hex((crc ^ (-1)) >>> 0); /**
* CRC-16 Checksum operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runCRC16: function(input, args) {
return CRC.crc16(input);
}, },
@ -168,28 +174,6 @@ const Checksum = {
return Utils.hex(0xffff - csum); return Utils.hex(0xffff - csum);
}, },
/**
* Generates a CRC table for use with CRC checksums.
*
* @private
* @returns {array}
*/
_genCRCTable: function() {
let c,
crcTable = [];
for (let n = 0; n < 256; n++) {
c = n;
for (let k = 0; k < 8; k++) {
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
}
crcTable[n] = c;
}
return crcTable;
},
}; };
export default Checksum; export default Checksum;

View File

@ -1,5 +1,3 @@
import {BigInteger} from "jsbn";
/** /**
* Date and time operations. * Date and time operations.
* *
@ -80,85 +78,6 @@ const DateTime = {
}, },
/**
* Windows Filetime to Unix Timestamp operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFromFiletimeToUnix: function(input, args) {
let units = args[0],
format = args[1];
if (format === "Hex") {
input = new BigInteger(input, 16);
} else {
input = new BigInteger(input);
}
input = input.subtract(new BigInteger("116444736000000000"));
if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.toString();
},
/**
* Unix Timestamp to Windows Filetime operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runToFiletimeFromUnix: function(input, args) {
let units = args[0],
format = args[1];
input = new BigInteger(input);
if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
input = input.add(new BigInteger("116444736000000000"));
if (format === "Hex"){
return input.toString(16);
} else {
return input.toString();
}
},
/**
* @constant
* @default
*/
FILETIME_FORMATS: ["Decimal", "Hex"],
/** /**
* @constant * @constant
* @default * @default
@ -273,268 +192,270 @@ const DateTime = {
/** /**
* @constant * @constant
*/ */
FORMAT_EXAMPLES: "Format string tokens:\n\n\ FORMAT_EXAMPLES: `Format string tokens:
<table class='table table-striped table-hover table-condensed table-bordered' style='font-family: sans-serif'>\
<thead>\
<tr>\ <table class="table table-striped table-hover table-condensed table-bordered" style="font-family: sans-serif">
<th>Category</th>\ <thead>
<th>Token</th>\ <tr>
<th>Output</th>\ <th>Category</th>
</tr>\ <th>Token</th>
</thead>\ <th>Output</th>
<tbody>\ </tr>
<tr>\ </thead>
<td><b>Month</b></td>\ <tbody>
<td>M</td>\ <tr>
<td>1 2 ... 11 12</td>\ <td><b>Month</b></td>
</tr>\ <td>M</td>
<tr>\ <td>1 2 ... 11 12</td>
<td></td>\ </tr>
<td>Mo</td>\ <tr>
<td>1st 2nd ... 11th 12th</td>\ <td></td>
</tr>\ <td>Mo</td>
<tr>\ <td>1st 2nd ... 11th 12th</td>
<td></td>\ </tr>
<td>MM</td>\ <tr>
<td>01 02 ... 11 12</td>\ <td></td>
</tr>\ <td>MM</td>
<tr>\ <td>01 02 ... 11 12</td>
<td></td>\ </tr>
<td>MMM</td>\ <tr>
<td>Jan Feb ... Nov Dec</td>\ <td></td>
</tr>\ <td>MMM</td>
<tr>\ <td>Jan Feb ... Nov Dec</td>
<td></td>\ </tr>
<td>MMMM</td>\ <tr>
<td>January February ... November December</td>\ <td></td>
</tr>\ <td>MMMM</td>
<tr>\ <td>January February ... November December</td>
<td><b>Quarter</b></td>\ </tr>
<td>Q</td>\ <tr>
<td>1 2 3 4</td>\ <td><b>Quarter</b></td>
</tr>\ <td>Q</td>
<tr>\ <td>1 2 3 4</td>
<td><b>Day of Month</b></td>\ </tr>
<td>D</td>\ <tr>
<td>1 2 ... 30 31</td>\ <td><b>Day of Month</b></td>
</tr>\ <td>D</td>
<tr>\ <td>1 2 ... 30 31</td>
<td></td>\ </tr>
<td>Do</td>\ <tr>
<td>1st 2nd ... 30th 31st</td>\ <td></td>
</tr>\ <td>Do</td>
<tr>\ <td>1st 2nd ... 30th 31st</td>
<td></td>\ </tr>
<td>DD</td>\ <tr>
<td>01 02 ... 30 31</td>\ <td></td>
</tr>\ <td>DD</td>
<tr>\ <td>01 02 ... 30 31</td>
<td><b>Day of Year</b></td>\ </tr>
<td>DDD</td>\ <tr>
<td>1 2 ... 364 365</td>\ <td><b>Day of Year</b></td>
</tr>\ <td>DDD</td>
<tr>\ <td>1 2 ... 364 365</td>
<td></td>\ </tr>
<td>DDDo</td>\ <tr>
<td>1st 2nd ... 364th 365th</td>\ <td></td>
</tr>\ <td>DDDo</td>
<tr>\ <td>1st 2nd ... 364th 365th</td>
<td></td>\ </tr>
<td>DDDD</td>\ <tr>
<td>001 002 ... 364 365</td>\ <td></td>
</tr>\ <td>DDDD</td>
<tr>\ <td>001 002 ... 364 365</td>
<td><b>Day of Week</b></td>\ </tr>
<td>d</td>\ <tr>
<td>0 1 ... 5 6</td>\ <td><b>Day of Week</b></td>
</tr>\ <td>d</td>
<tr>\ <td>0 1 ... 5 6</td>
<td></td>\ </tr>
<td>do</td>\ <tr>
<td>0th 1st ... 5th 6th</td>\ <td></td>
</tr>\ <td>do</td>
<tr>\ <td>0th 1st ... 5th 6th</td>
<td></td>\ </tr>
<td>dd</td>\ <tr>
<td>Su Mo ... Fr Sa</td>\ <td></td>
</tr>\ <td>dd</td>
<tr>\ <td>Su Mo ... Fr Sa</td>
<td></td>\ </tr>
<td>ddd</td>\ <tr>
<td>Sun Mon ... Fri Sat</td>\ <td></td>
</tr>\ <td>ddd</td>
<tr>\ <td>Sun Mon ... Fri Sat</td>
<td></td>\ </tr>
<td>dddd</td>\ <tr>
<td>Sunday Monday ... Friday Saturday</td>\ <td></td>
</tr>\ <td>dddd</td>
<tr>\ <td>Sunday Monday ... Friday Saturday</td>
<td><b>Day of Week (Locale)</b></td>\ </tr>
<td>e</td>\ <tr>
<td>0 1 ... 5 6</td>\ <td><b>Day of Week (Locale)</b></td>
</tr>\ <td>e</td>
<tr>\ <td>0 1 ... 5 6</td>
<td><b>Day of Week (ISO)</b></td>\ </tr>
<td>E</td>\ <tr>
<td>1 2 ... 6 7</td>\ <td><b>Day of Week (ISO)</b></td>
</tr>\ <td>E</td>
<tr>\ <td>1 2 ... 6 7</td>
<td><b>Week of Year</b></td>\ </tr>
<td>w</td>\ <tr>
<td>1 2 ... 52 53</td>\ <td><b>Week of Year</b></td>
</tr>\ <td>w</td>
<tr>\ <td>1 2 ... 52 53</td>
<td></td>\ </tr>
<td>wo</td>\ <tr>
<td>1st 2nd ... 52nd 53rd</td>\ <td></td>
</tr>\ <td>wo</td>
<tr>\ <td>1st 2nd ... 52nd 53rd</td>
<td></td>\ </tr>
<td>ww</td>\ <tr>
<td>01 02 ... 52 53</td>\ <td></td>
</tr>\ <td>ww</td>
<tr>\ <td>01 02 ... 52 53</td>
<td><b>Week of Year (ISO)</b></td>\ </tr>
<td>W</td>\ <tr>
<td>1 2 ... 52 53</td>\ <td><b>Week of Year (ISO)</b></td>
</tr>\ <td>W</td>
<tr>\ <td>1 2 ... 52 53</td>
<td></td>\ </tr>
<td>Wo</td>\ <tr>
<td>1st 2nd ... 52nd 53rd</td>\ <td></td>
</tr>\ <td>Wo</td>
<tr>\ <td>1st 2nd ... 52nd 53rd</td>
<td></td>\ </tr>
<td>WW</td>\ <tr>
<td>01 02 ... 52 53</td>\ <td></td>
</tr>\ <td>WW</td>
<tr>\ <td>01 02 ... 52 53</td>
<td><b>Year</b></td>\ </tr>
<td>YY</td>\ <tr>
<td>70 71 ... 29 30</td>\ <td><b>Year</b></td>
</tr>\ <td>YY</td>
<tr>\ <td>70 71 ... 29 30</td>
<td></td>\ </tr>
<td>YYYY</td>\ <tr>
<td>1970 1971 ... 2029 2030</td>\ <td></td>
</tr>\ <td>YYYY</td>
<tr>\ <td>1970 1971 ... 2029 2030</td>
<td><b>Week Year</b></td>\ </tr>
<td>gg</td>\ <tr>
<td>70 71 ... 29 30</td>\ <td><b>Week Year</b></td>
</tr>\ <td>gg</td>
<tr>\ <td>70 71 ... 29 30</td>
<td></td>\ </tr>
<td>gggg</td>\ <tr>
<td>1970 1971 ... 2029 2030</td>\ <td></td>
</tr>\ <td>gggg</td>
<tr>\ <td>1970 1971 ... 2029 2030</td>
<td><b>Week Year (ISO)</b></td>\ </tr>
<td>GG</td>\ <tr>
<td>70 71 ... 29 30</td>\ <td><b>Week Year (ISO)</b></td>
</tr>\ <td>GG</td>
<tr>\ <td>70 71 ... 29 30</td>
<td></td>\ </tr>
<td>GGGG</td>\ <tr>
<td>1970 1971 ... 2029 2030</td>\ <td></td>
</tr>\ <td>GGGG</td>
<tr>\ <td>1970 1971 ... 2029 2030</td>
<td><b>AM/PM</b></td>\ </tr>
<td>A</td>\ <tr>
<td>AM PM</td>\ <td><b>AM/PM</b></td>
</tr>\ <td>A</td>
<tr>\ <td>AM PM</td>
<td></td>\ </tr>
<td>a</td>\ <tr>
<td>am pm</td>\ <td></td>
</tr>\ <td>a</td>
<tr>\ <td>am pm</td>
<td><b>Hour</b></td>\ </tr>
<td>H</td>\ <tr>
<td>0 1 ... 22 23</td>\ <td><b>Hour</b></td>
</tr>\ <td>H</td>
<tr>\ <td>0 1 ... 22 23</td>
<td></td>\ </tr>
<td>HH</td>\ <tr>
<td>00 01 ... 22 23</td>\ <td></td>
</tr>\ <td>HH</td>
<tr>\ <td>00 01 ... 22 23</td>
<td></td>\ </tr>
<td>h</td>\ <tr>
<td>1 2 ... 11 12</td>\ <td></td>
</tr>\ <td>h</td>
<tr>\ <td>1 2 ... 11 12</td>
<td></td>\ </tr>
<td>hh</td>\ <tr>
<td>01 02 ... 11 12</td>\ <td></td>
</tr>\ <td>hh</td>
<tr>\ <td>01 02 ... 11 12</td>
<td><b>Minute</b></td>\ </tr>
<td>m</td>\ <tr>
<td>0 1 ... 58 59</td>\ <td><b>Minute</b></td>
</tr>\ <td>m</td>
<tr>\ <td>0 1 ... 58 59</td>
<td></td>\ </tr>
<td>mm</td>\ <tr>
<td>00 01 ... 58 59</td>\ <td></td>
</tr>\ <td>mm</td>
<tr>\ <td>00 01 ... 58 59</td>
<td><b>Second</b></td>\ </tr>
<td>s</td>\ <tr>
<td>0 1 ... 58 59</td>\ <td><b>Second</b></td>
</tr>\ <td>s</td>
<tr>\ <td>0 1 ... 58 59</td>
<td></td>\ </tr>
<td>ss</td>\ <tr>
<td>00 01 ... 58 59</td>\ <td></td>
</tr>\ <td>ss</td>
<tr>\ <td>00 01 ... 58 59</td>
<td><b>Fractional Second</b></td>\ </tr>
<td>S</td>\ <tr>
<td>0 1 ... 8 9</td>\ <td><b>Fractional Second</b></td>
</tr>\ <td>S</td>
<tr>\ <td>0 1 ... 8 9</td>
<td></td>\ </tr>
<td>SS</td>\ <tr>
<td>00 01 ... 98 99</td>\ <td></td>
</tr>\ <td>SS</td>
<tr>\ <td>00 01 ... 98 99</td>
<td></td>\ </tr>
<td>SSS</td>\ <tr>
<td>000 001 ... 998 999</td>\ <td></td>
</tr>\ <td>SSS</td>
<tr>\ <td>000 001 ... 998 999</td>
<td></td>\ </tr>
<td>SSSS ... SSSSSSSSS</td>\ <tr>
<td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>\ <td></td>
</tr>\ <td>SSSS ... SSSSSSSSS</td>
<tr>\ <td>000[0..] 001[0..] ... 998[0..] 999[0..]</td>
<td><b>Timezone</b></td>\ </tr>
<td>z or zz</td>\ <tr>
<td>EST CST ... MST PST</td>\ <td><b>Timezone</b></td>
</tr>\ <td>z or zz</td>
<tr>\ <td>EST CST ... MST PST</td>
<td></td>\ </tr>
<td>Z</td>\ <tr>
<td>-07:00 -06:00 ... +06:00 +07:00</td>\ <td></td>
</tr>\ <td>Z</td>
<tr>\ <td>-07:00 -06:00 ... +06:00 +07:00</td>
<td></td>\ </tr>
<td>ZZ</td>\ <tr>
<td>-0700 -0600 ... +0600 +0700</td>\ <td></td>
</tr>\ <td>ZZ</td>
<tr>\ <td>-0700 -0600 ... +0600 +0700</td>
<td><b>Unix Timestamp</b></td>\ </tr>
<td>X</td>\ <tr>
<td>1360013296</td>\ <td><b>Unix Timestamp</b></td>
</tr>\ <td>X</td>
<tr>\ <td>1360013296</td>
<td><b>Unix Millisecond Timestamp</b></td>\ </tr>
<td>x</td>\ <tr>
<td>1360013296123</td>\ <td><b>Unix Millisecond Timestamp</b></td>
</tr>\ <td>x</td>
</tbody>\ <td>1360013296123</td>
</table>", </tr>
</tbody>
</table>`,
}; };

View File

@ -0,0 +1,94 @@
import Utils from "../Utils.js";
import * as JsDiff from "diff";
/**
* Diff operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*
* @namespace
*/
const Diff = {
/**
* @constant
* @default
*/
DIFF_SAMPLE_DELIMITER: "\\n\\n",
/**
* @constant
* @default
*/
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
/**
* Diff operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runDiff: function(input, args) {
let sampleDelim = args[0],
diffBy = args[1],
showAdded = args[2],
showRemoved = args[3],
ignoreWhitespace = args[4],
samples = input.split(sampleDelim),
output = "",
diff;
if (!samples || samples.length !== 2) {
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
}
switch (diffBy) {
case "Character":
diff = JsDiff.diffChars(samples[0], samples[1]);
break;
case "Word":
if (ignoreWhitespace) {
diff = JsDiff.diffWords(samples[0], samples[1]);
} else {
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
}
break;
case "Line":
if (ignoreWhitespace) {
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
} else {
diff = JsDiff.diffLines(samples[0], samples[1]);
}
break;
case "Sentence":
diff = JsDiff.diffSentences(samples[0], samples[1]);
break;
case "CSS":
diff = JsDiff.diffCss(samples[0], samples[1]);
break;
case "JSON":
diff = JsDiff.diffJson(samples[0], samples[1]);
break;
default:
return "Invalid 'Diff by' option.";
}
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else {
output += Utils.escapeHtml(diff[i].value);
}
}
return output;
},
};
export default Diff;

View File

@ -187,11 +187,8 @@ const Extract = {
* @returns {string} * @returns {string}
*/ */
runDomains: function(input, args) { runDomains: function(input, args) {
let displayTotal = args[0], const displayTotal = args[0],
protocol = "https?://", regex = /\b((?=[a-z0-9-]{1,63}\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,63}\b/ig;
hostname = "[-\\w\\.]+",
tld = "\\.(?:com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+",
regex = new RegExp("(?:" + protocol + ")?" + hostname + tld, "ig");
return Extract._search(input, regex, null, displayTotal); return Extract._search(input, regex, null, displayTotal);
}, },
@ -261,39 +258,6 @@ const Extract = {
return Extract._search(input, regex, null, displayTotal); return Extract._search(input, regex, null, displayTotal);
}, },
/**
* Extract all identifiers operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runAllIdents: function(input, args) {
let output = "";
output += "IP addresses\n";
output += Extract.runIp(input, [true, true, false]);
output += "\nEmail addresses\n";
output += Extract.runEmail(input, []);
output += "\nMAC addresses\n";
output += Extract.runMac(input, []);
output += "\nURLs\n";
output += Extract.runUrls(input, []);
output += "\nDomain names\n";
output += Extract.runDomains(input, []);
output += "\nFile paths\n";
output += Extract.runFilePaths(input, [true, true]);
output += "\nDates\n";
output += Extract.runDates(input, []);
return output;
},
}; };
export default Extract; export default Extract;

View File

@ -0,0 +1,99 @@
import {BigInteger} from "jsbn";
/**
* Windows Filetime operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const Filetime = {
/**
* @constant
* @default
*/
UNITS: ["Seconds (s)", "Milliseconds (ms)", "Microseconds (μs)", "Nanoseconds (ns)"],
/**
* @constant
* @default
*/
FILETIME_FORMATS: ["Decimal", "Hex"],
/**
* Windows Filetime to Unix Timestamp operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runFromFiletimeToUnix: function(input, args) {
let units = args[0],
format = args[1];
if (format === "Hex") {
input = new BigInteger(input, 16);
} else {
input = new BigInteger(input);
}
input = input.subtract(new BigInteger("116444736000000000"));
if (units === "Seconds (s)"){
input = input.divide(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.divide(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.divide(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.multiply(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
return input.toString();
},
/**
* Unix Timestamp to Windows Filetime operation.
*
* @author bwhitn [brian.m.whitney@outlook.com]
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runToFiletimeFromUnix: function(input, args) {
let units = args[0],
format = args[1];
input = new BigInteger(input);
if (units === "Seconds (s)"){
input = input.multiply(new BigInteger("10000000"));
} else if (units === "Milliseconds (ms)") {
input = input.multiply(new BigInteger("10000"));
} else if (units === "Microseconds (μs)") {
input = input.multiply(new BigInteger("10"));
} else if (units === "Nanoseconds (ns)") {
input = input.divide(new BigInteger("100"));
} else {
throw "Unrecognised unit";
}
input = input.add(new BigInteger("116444736000000000"));
if (format === "Hex"){
return input.toString(16);
} else {
return input.toString();
}
},
};
export default Filetime;

View File

@ -225,26 +225,26 @@ const HTML = {
cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")"; cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")";
// Generate output // Generate output
return "<div id='colorpicker' style='display: inline-block'></div>" + return `<div id="colorpicker" style="display: inline-block"></div>
"Hex: " + hex + "\n" + Hex: ${hex}
"RGB: " + rgb + "\n" + RGB: ${rgb}
"RGBA: " + rgba + "\n" + RGBA: ${rgba}
"HSL: " + hsl + "\n" + HSL: ${hsl}
"HSLA: " + hsla + "\n" + HSLA: ${hsla}
"CMYK: " + cmyk + CMYK: ${cmyk}
"<script>\ <script>
$('#colorpicker').colorpicker({\ $('#colorpicker').colorpicker({
format: 'rgba',\ format: 'rgba',
color: '" + rgba + "',\ color: '${rgba}',
container: true,\ container: true,
inline: true,\ inline: true,
}).on('changeColor', function(e) {\ }).on('changeColor', function(e) {
var color = e.color.toRGB();\ var color = e.color.toRGB();
document.getElementById('input-text').value = 'rgba(' +\ document.getElementById('input-text').value = 'rgba(' +
color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';\ color.r + ', ' + color.g + ', ' + color.b + ', ' + color.a + ')';
window.app.autoBake();\ window.app.autoBake();
});\ });
</script>"; </script>`;
}, },

View File

@ -1,6 +1,7 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import CryptoJS from "crypto-js";
import CryptoApi from "crypto-api"; import CryptoApi from "crypto-api";
import MD6 from "node-md6";
import * as SHA3 from "js-sha3";
import Checksum from "./Checksum.js"; import Checksum from "./Checksum.js";
@ -15,6 +16,22 @@ import Checksum from "./Checksum.js";
*/ */
const Hash = { 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. * MD2 operation.
* *
@ -23,7 +40,7 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runMD2: function (input, args) { runMD2: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("md2", input, {})); return Hash.runHash("md2", input);
}, },
@ -35,7 +52,7 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runMD4: function (input, args) { runMD4: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("md4", input, {})); return Hash.runHash("md4", input);
}, },
@ -47,8 +64,39 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runMD5: function (input, args) { runMD5: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray return Hash.runHash("md5", input);
return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex); },
/**
* @constant
* @default
*/
MD6_SIZE: 256,
/**
* @constant
* @default
*/
MD6_LEVELS: 64,
/**
* MD6 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runMD6: function (input, args) {
const size = args[0],
levels = args[1],
key = args[2];
if (size < 0 || size > 512)
return "Size must be between 0 and 512";
if (levels < 0)
return "Levels must be greater than 0";
return MD6.getHashOfText(input, size, key, levels);
}, },
@ -60,7 +108,7 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runSHA0: function (input, args) { runSHA0: function (input, args) {
return Utils.toHexFast(CryptoApi.hash("sha0", input, {})); return Hash.runHash("sha0", input);
}, },
@ -72,60 +120,7 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runSHA1: function (input, args) { runSHA1: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input); return Hash.runHash("sha1", input);
return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA224 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA224: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA256 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA256: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA384 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA384: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
},
/**
* SHA512 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA512: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
}, },
@ -133,7 +128,26 @@ const Hash = {
* @constant * @constant
* @default * @default
*/ */
SHA3_LENGTH: ["512", "384", "256", "224"], SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
/**
* SHA2 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runSHA2: function (input, args) {
const size = args[0];
return Hash.runHash("sha" + size, input);
},
/**
* @constant
* @default
*/
SHA3_SIZE: ["512", "384", "256", "224"],
/** /**
* SHA3 operation. * SHA3 operation.
@ -143,25 +157,27 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runSHA3: function (input, args) { runSHA3: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input); const size = parseInt(args[0], 10);
let sha3Length = args[0], let algo;
options = {
outputLength: parseInt(sha3Length, 10)
};
return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
},
switch (size) {
case 224:
algo = SHA3.sha3_224;
break;
case 384:
algo = SHA3.sha3_384;
break;
case 256:
algo = SHA3.sha3_256;
break;
case 512:
algo = SHA3.sha3_512;
break;
default:
return "Invalid size";
}
/** return algo(input);
* RIPEMD-160 operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runRIPEMD160: function (input, args) {
input = CryptoJS.enc.Latin1.parse(input);
return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
}, },
@ -169,7 +185,181 @@ const Hash = {
* @constant * @constant
* @default * @default
*/ */
HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"], KECCAK_SIZE: ["512", "384", "256", "224"],
/**
* Keccak operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runKeccak: function (input, args) {
const size = parseInt(args[0], 10);
let algo;
switch (size) {
case 224:
algo = SHA3.keccak224;
break;
case 384:
algo = SHA3.keccak384;
break;
case 256:
algo = SHA3.keccak256;
break;
case 512:
algo = SHA3.keccak512;
break;
default:
return "Invalid size";
}
return algo(input);
},
/**
* @constant
* @default
*/
SHAKE_CAPACITY: ["256", "128"],
/**
* @constant
* @default
*/
SHAKE_SIZE: 512,
/**
* Shake operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runShake: function (input, args) {
const capacity = parseInt(args[0], 10),
size = args[1];
let algo;
if (size < 0)
return "Size must be greater than 0";
switch (capacity) {
case 128:
algo = SHA3.shake128;
break;
case 256:
algo = SHA3.shake256;
break;
default:
return "Invalid size";
}
return algo(input, size);
},
/**
* @constant
* @default
*/
RIPEMD_SIZE: ["320", "256", "160", "128"],
/**
* RIPEMD operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runRIPEMD: function (input, args) {
const size = args[0];
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);
},
/**
* @constant
* @default
*/
HMAC_FUNCTIONS: [
"MD2",
"MD4",
"MD5",
"SHA0",
"SHA1",
"SHA224",
"SHA256",
"SHA384",
"SHA512",
"SHA512/224",
"SHA512/256",
"RIPEMD128",
"RIPEMD160",
"RIPEMD256",
"RIPEMD320",
"HAS160",
"Whirlpool",
"Whirlpool-0",
"Whirlpool-T"
],
/** /**
* HMAC operation. * HMAC operation.
@ -179,19 +369,12 @@ const Hash = {
* @returns {string} * @returns {string}
*/ */
runHMAC: function (input, args) { runHMAC: function (input, args) {
const hashFunc = args[1]; const password = args[0],
input = CryptoJS.enc.Latin1.parse(input); hashFunc = args[1].toLowerCase(),
const execute = { hmac = CryptoApi.mac("hmac", password, hashFunc, {});
"MD5": CryptoJS.HmacMD5(input, args[0]),
"SHA1": CryptoJS.HmacSHA1(input, args[0]), hmac.update(input);
"SHA224": CryptoJS.HmacSHA224(input, args[0]), return hmac.finalize().stringify("hex");
"SHA256": CryptoJS.HmacSHA256(input, args[0]),
"SHA384": CryptoJS.HmacSHA384(input, args[0]),
"SHA512": CryptoJS.HmacSHA512(input, args[0]),
"SHA3": CryptoJS.HmacSHA3(input, args[0]),
"RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
};
return execute[hashFunc].toString(CryptoJS.enc.Hex);
}, },
@ -207,24 +390,39 @@ const Hash = {
output = "MD2: " + Hash.runMD2(input, []) + output = "MD2: " + Hash.runMD2(input, []) +
"\nMD4: " + Hash.runMD4(input, []) + "\nMD4: " + Hash.runMD4(input, []) +
"\nMD5: " + Hash.runMD5(input, []) + "\nMD5: " + Hash.runMD5(input, []) +
"\nMD6: " + Hash.runMD6(input, []) +
"\nSHA0: " + Hash.runSHA0(input, []) + "\nSHA0: " + Hash.runSHA0(input, []) +
"\nSHA1: " + Hash.runSHA1(input, []) + "\nSHA1: " + Hash.runSHA1(input, []) +
"\nSHA2 224: " + Hash.runSHA224(input, []) + "\nSHA2 224: " + Hash.runSHA2(input, ["224"]) +
"\nSHA2 256: " + Hash.runSHA256(input, []) + "\nSHA2 256: " + Hash.runSHA2(input, ["256"]) +
"\nSHA2 384: " + Hash.runSHA384(input, []) + "\nSHA2 384: " + Hash.runSHA2(input, ["384"]) +
"\nSHA2 512: " + Hash.runSHA512(input, []) + "\nSHA2 512: " + Hash.runSHA2(input, ["512"]) +
"\nSHA3 224: " + Hash.runSHA3(input, ["224"]) + "\nSHA3 224: " + Hash.runSHA3(input, ["224"]) +
"\nSHA3 256: " + Hash.runSHA3(input, ["256"]) + "\nSHA3 256: " + Hash.runSHA3(input, ["256"]) +
"\nSHA3 384: " + Hash.runSHA3(input, ["384"]) + "\nSHA3 384: " + Hash.runSHA3(input, ["384"]) +
"\nSHA3 512: " + Hash.runSHA3(input, ["512"]) + "\nSHA3 512: " + Hash.runSHA3(input, ["512"]) +
"\nRIPEMD-160: " + Hash.runRIPEMD160(input, []) + "\nKeccak 224: " + Hash.runKeccak(input, ["224"]) +
"\nKeccak 256: " + Hash.runKeccak(input, ["256"]) +
"\nKeccak 384: " + Hash.runKeccak(input, ["384"]) +
"\nKeccak 512: " + Hash.runKeccak(input, ["512"]) +
"\nShake 128: " + Hash.runShake(input, ["128", 256]) +
"\nShake 256: " + Hash.runShake(input, ["256", 512]) +
"\nRIPEMD-128: " + Hash.runRIPEMD(input, ["128"]) +
"\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:" + "\n\nChecksums:" +
"\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) + "\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) +
"\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) + "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
"\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) + "\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
"\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) + "\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
"\nAdler-32: " + Checksum.runAdler32(byteArray, []) + "\nAdler-32: " + Checksum.runAdler32(byteArray, []) +
"\nCRC-32: " + Checksum.runCRC32(byteArray, []); "\nCRC-16: " + Checksum.runCRC16(input, []) +
"\nCRC-32: " + Checksum.runCRC32(input, []);
return output; return output;
}, },

View File

@ -1,4 +1,3 @@
/* globals app */
import Utils from "../Utils.js"; import Utils from "../Utils.js";
@ -92,7 +91,7 @@ const Hexdump = {
const w = (width - 13) / 4; const w = (width - 13) / 4;
// w should be the specified width of the hexdump and therefore a round number // w should be the specified width of the hexdump and therefore a round number
if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) { if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) {
if (app) app.options.attemptHighlight = false; if (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
} }
return output; return output;
}, },

213
src/core/operations/MS.js Normal file
View File

@ -0,0 +1,213 @@
/**
* Microsoft operations.
*
* @author bmwhitn [brian.m.whitney@outlook.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const MS = {
/**
* @constant
* @default
*/
D_DECODE: [
"",
"",
"",
"",
"",
"",
"",
"",
"",
"\x57\x6E\x7B",
"\x4A\x4C\x41",
"\x0B\x0B\x0B",
"\x0C\x0C\x0C",
"\x4A\x4C\x41",
"\x0E\x0E\x0E",
"\x0F\x0F\x0F",
"\x10\x10\x10",
"\x11\x11\x11",
"\x12\x12\x12",
"\x13\x13\x13",
"\x14\x14\x14",
"\x15\x15\x15",
"\x16\x16\x16",
"\x17\x17\x17",
"\x18\x18\x18",
"\x19\x19\x19",
"\x1A\x1A\x1A",
"\x1B\x1B\x1B",
"\x1C\x1C\x1C",
"\x1D\x1D\x1D",
"\x1E\x1E\x1E",
"\x1F\x1F\x1F",
"\x2E\x2D\x32",
"\x47\x75\x30",
"\x7A\x52\x21",
"\x56\x60\x29",
"\x42\x71\x5B",
"\x6A\x5E\x38",
"\x2F\x49\x33",
"\x26\x5C\x3D",
"\x49\x62\x58",
"\x41\x7D\x3A",
"\x34\x29\x35",
"\x32\x36\x65",
"\x5B\x20\x39",
"\x76\x7C\x5C",
"\x72\x7A\x56",
"\x43\x7F\x73",
"\x38\x6B\x66",
"\x39\x63\x4E",
"\x70\x33\x45",
"\x45\x2B\x6B",
"\x68\x68\x62",
"\x71\x51\x59",
"\x4F\x66\x78",
"\x09\x76\x5E",
"\x62\x31\x7D",
"\x44\x64\x4A",
"\x23\x54\x6D",
"\x75\x43\x71",
"\x4A\x4C\x41",
"\x7E\x3A\x60",
"\x4A\x4C\x41",
"\x5E\x7E\x53",
"\x40\x4C\x40",
"\x77\x45\x42",
"\x4A\x2C\x27",
"\x61\x2A\x48",
"\x5D\x74\x72",
"\x22\x27\x75",
"\x4B\x37\x31",
"\x6F\x44\x37",
"\x4E\x79\x4D",
"\x3B\x59\x52",
"\x4C\x2F\x22",
"\x50\x6F\x54",
"\x67\x26\x6A",
"\x2A\x72\x47",
"\x7D\x6A\x64",
"\x74\x39\x2D",
"\x54\x7B\x20",
"\x2B\x3F\x7F",
"\x2D\x38\x2E",
"\x2C\x77\x4C",
"\x30\x67\x5D",
"\x6E\x53\x7E",
"\x6B\x47\x6C",
"\x66\x34\x6F",
"\x35\x78\x79",
"\x25\x5D\x74",
"\x21\x30\x43",
"\x64\x23\x26",
"\x4D\x5A\x76",
"\x52\x5B\x25",
"\x63\x6C\x24",
"\x3F\x48\x2B",
"\x7B\x55\x28",
"\x78\x70\x23",
"\x29\x69\x41",
"\x28\x2E\x34",
"\x73\x4C\x09",
"\x59\x21\x2A",
"\x33\x24\x44",
"\x7F\x4E\x3F",
"\x6D\x50\x77",
"\x55\x09\x3B",
"\x53\x56\x55",
"\x7C\x73\x69",
"\x3A\x35\x61",
"\x5F\x61\x63",
"\x65\x4B\x50",
"\x46\x58\x67",
"\x58\x3B\x51",
"\x31\x57\x49",
"\x69\x22\x4F",
"\x6C\x6D\x46",
"\x5A\x4D\x68",
"\x48\x25\x7C",
"\x27\x28\x36",
"\x5C\x46\x70",
"\x3D\x4A\x6E",
"\x24\x32\x7A",
"\x79\x41\x2F",
"\x37\x3D\x5F",
"\x60\x5F\x4B",
"\x51\x4F\x5A",
"\x20\x42\x2C",
"\x36\x65\x57"
],
/**
* @constant
* @default
*/
D_COMBINATION: [
0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1,
0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1
],
/**
* Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe.
* This is a conversion of a Python script that was originally created by Didier Stevens
* (https://DidierStevens.com).
*
* @private
* @param {string} data
* @returns {string}
*/
_decode: function (data) {
let result = [];
let index = -1;
data = data.replace(/@&/g, String.fromCharCode(10))
.replace(/@#/g, String.fromCharCode(13))
.replace(/@\*/g, ">")
.replace(/@!/g, "<")
.replace(/@\$/g, "@");
for (let i = 0; i < data.length; i++) {
let byte = data.charCodeAt(i);
let char = data.charAt(i);
if (byte < 128) {
index++;
}
if ((byte === 9 || byte > 31 && byte < 128) &&
byte !== 60 &&
byte !== 62 &&
byte !== 64) {
char = MS.D_DECODE[byte].charAt(MS.D_COMBINATION[index % 64]);
}
result.push(char);
}
return result.join("");
},
/**
* Microsoft Script Decoder operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runDecodeScript: function (input, args) {
let matcher = /#@~\^.{6}==(.+).{6}==\^#~@/;
let encodedData = matcher.exec(input);
if (encodedData){
return MS._decode(encodedData[1]);
} else {
return "";
}
}
};
export default MS;

55
src/core/operations/OTP.js Executable file
View File

@ -0,0 +1,55 @@
import otp from "otp";
import Base64 from "./Base64.js";
/**
* One-Time Password operations.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @namespace
*/
const OTP = {
/**
* Generate TOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runTOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
epoch: args[3],
timeSlice: args[4]
});
return `URI: ${otpObj.totpURL}\n\nPassword: ${otpObj.totp()}`;
},
/**
* Generate HOTP operation.
*
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
runHOTP: function(input, args) {
const otpObj = otp({
name: args[0],
keySize: args[1],
codeLength: args[2],
secret: Base64.runTo32(input, []),
});
const counter = args[3];
return `URI: ${otpObj.hotpURL}\n\nPassword: ${otpObj.hotp(counter)}`;
},
};
export default OTP;

View File

@ -341,702 +341,3 @@ ${extensions}`;
}; };
export default PublicKey; export default PublicKey;
/**
* Overwrite DN attribute lookup in jsrasign library with a much more complete version from
* https://github.com/nfephp-org/nfephp/blob/master/libs/Common/Certificate/Oids.php
*
* Various duplicates commented out.
*
* @constant
*/
r.X509.DN_ATTRHEX = {
"0603550403": "commonName",
"0603550404": "surname",
"0603550406": "countryName",
"0603550407": "localityName",
"0603550408": "stateOrProvinceName",
"0603550409": "streetAddress",
"060355040a": "organizationName",
"060355040b": "organizationalUnitName",
"060355040c": "title",
"0603550414": "telephoneNumber",
"060355042a": "givenName",
// "0603551d0e" : "id-ce-subjectKeyIdentifier",
// "0603551d0f" : "id-ce-keyUsage",
// "0603551d11" : "id-ce-subjectAltName",
// "0603551d13" : "id-ce-basicConstraints",
// "0603551d14" : "id-ce-cRLNumber",
// "0603551d1f" : "id-ce-CRLDistributionPoints",
// "0603551d20" : "id-ce-certificatePolicies",
// "0603551d23" : "id-ce-authorityKeyIdentifier",
// "0603551d25" : "id-ce-extKeyUsage",
// "06032a864886f70d010901" : "Email",
// "06032a864886f70d010101" : "RSAEncryption",
// "06032a864886f70d010102" : "md2WithRSAEncryption",
// "06032a864886f70d010104" : "md5withRSAEncryption",
// "06032a864886f70d010105" : "SHA-1WithRSAEncryption",
// "06032a8648ce380403" : "id-dsa-with-sha-1",
// "06032b06010505070302" : "idKpClientAuth",
// "06032b06010505070304" : "idKpSecurityemail",
"06032b06010505070201": "idCertificatePolicies",
"06036086480186f8420101": "netscape-cert-type",
"06036086480186f8420102": "netscape-base-url",
"06036086480186f8420103": "netscape-revocation-url",
"06036086480186f8420104": "netscape-ca-revocation-url",
"06036086480186f8420107": "netscape-cert-renewal-url",
"06036086480186f8420108": "netscape-ca-policy-url",
"06036086480186f842010c": "netscape-ssl-server-name",
"06036086480186f842010d": "netscape-comment",
"0603604c010201": "A1",
"0603604c010203": "A3",
"0603604c01020110": "Certification Practice Statement pointer",
"0603604c010301": "Dados do cert parte 1",
"0603604c010305": "Dados do cert parte 2",
"0603604c010306": "Dados do cert parte 3",
"06030992268993f22c640119": "domainComponent",
"06032a24a0f2a07d01010a": "Signet pilot",
"06032a24a0f2a07d01010b": "Signet intraNet",
"06032a24a0f2a07d010102": "Signet personal",
"06032a24a0f2a07d010114": "Signet securityPolicy",
"06032a24a0f2a07d010103": "Signet business",
"06032a24a0f2a07d010104": "Signet legal",
"06032a24a497a35301640101": "Certificates Australia policyIdentifier",
"06032a85702201": "seis-cp",
"06032a8570220101": "SEIS certificatePolicy-s10",
"06032a85702202": "SEIS pe",
"06032a85702203": "SEIS at",
"06032a8570220301": "SEIS at-personalIdentifier",
"06032a8648ce380201": "holdinstruction-none",
"06032a8648ce380202": "holdinstruction-callissuer",
"06032a8648ce380203": "holdinstruction-reject",
"06032a8648ce380401": "dsa",
"06032a8648ce380403": "dsaWithSha1",
"06032a8648ce3d01": "fieldType",
"06032a8648ce3d0101": "prime-field",
"06032a8648ce3d0102": "characteristic-two-field",
"06032a8648ce3d010201": "ecPublicKey",
"06032a8648ce3d010203": "characteristic-two-basis",
"06032a8648ce3d01020301": "onBasis",
"06032a8648ce3d01020302": "tpBasis",
"06032a8648ce3d01020303": "ppBasis",
"06032a8648ce3d02": "publicKeyType",
"06032a8648ce3d0201": "ecPublicKey",
"06032a8648ce3e0201": "dhPublicNumber",
"06032a864886f67d07": "nsn",
"06032a864886f67d0741": "nsn-ce",
"06032a864886f67d074100": "entrustVersInfo",
"06032a864886f67d0742": "nsn-alg",
"06032a864886f67d07420a": "cast5CBC",
"06032a864886f67d07420b": "cast5MAC",
"06032a864886f67d07420c": "pbeWithMD5AndCAST5-CBC",
"06032a864886f67d07420d": "passwordBasedMac",
"06032a864886f67d074203": "cast3CBC",
"06032a864886f67d0743": "nsn-oc",
"06032a864886f67d074300": "entrustUser",
"06032a864886f67d0744": "nsn-at",
"06032a864886f67d074400": "entrustCAInfo",
"06032a864886f67d07440a": "attributeCertificate",
"06032a864886f70d0101": "pkcs-1",
"06032a864886f70d010101": "rsaEncryption",
"06032a864886f70d010102": "md2withRSAEncryption",
"06032a864886f70d010103": "md4withRSAEncryption",
"06032a864886f70d010104": "md5withRSAEncryption",
"06032a864886f70d010105": "sha1withRSAEncryption",
"06032a864886f70d010106": "rsaOAEPEncryptionSET",
"06032a864886f70d010910020b": "SMIMEEncryptionKeyPreference",
"06032a864886f70d010c": "pkcs-12",
"06032a864886f70d010c01": "pkcs-12-PbeIds",
"06032a864886f70d010c0101": "pbeWithSHAAnd128BitRC4",
"06032a864886f70d010c0102": "pbeWithSHAAnd40BitRC4",
"06032a864886f70d010c0103": "pbeWithSHAAnd3-KeyTripleDES-CBC",
"06032a864886f70d010c0104": "pbeWithSHAAnd2-KeyTripleDES-CBC",
"06032a864886f70d010c0105": "pbeWithSHAAnd128BitRC2-CBC",
"06032a864886f70d010c0106": "pbeWithSHAAnd40BitRC2-CBC",
"06032a864886f70d010c0a": "pkcs-12Version1",
"06032a864886f70d010c0a01": "pkcs-12BadIds",
"06032a864886f70d010c0a0101": "pkcs-12-keyBag",
"06032a864886f70d010c0a0102": "pkcs-12-pkcs-8ShroudedKeyBag",
"06032a864886f70d010c0a0103": "pkcs-12-certBag",
"06032a864886f70d010c0a0104": "pkcs-12-crlBag",
"06032a864886f70d010c0a0105": "pkcs-12-secretBag",
"06032a864886f70d010c0a0106": "pkcs-12-safeContentsBag",
"06032a864886f70d010c02": "pkcs-12-ESPVKID",
"06032a864886f70d010c0201": "pkcs-12-PKCS8KeyShrouding",
"06032a864886f70d010c03": "pkcs-12-BagIds",
"06032a864886f70d010c0301": "pkcs-12-keyBagId",
"06032a864886f70d010c0302": "pkcs-12-certAndCRLBagId",
"06032a864886f70d010c0303": "pkcs-12-secretBagId",
"06032a864886f70d010c0304": "pkcs-12-safeContentsId",
"06032a864886f70d010c0305": "pkcs-12-pkcs-8ShroudedKeyBagId",
"06032a864886f70d010c04": "pkcs-12-CertBagID",
"06032a864886f70d010c0401": "pkcs-12-X509CertCRLBagID",
"06032a864886f70d010c0402": "pkcs-12-SDSICertBagID",
"06032a864886f70d010c05": "pkcs-12-OID",
"06032a864886f70d010c0501": "pkcs-12-PBEID",
"06032a864886f70d010c050101": "pkcs-12-PBEWithSha1And128BitRC4",
"06032a864886f70d010c050102": "pkcs-12-PBEWithSha1And40BitRC4",
"06032a864886f70d010c050103": "pkcs-12-PBEWithSha1AndTripleDESCBC",
"06032a864886f70d010c050104": "pkcs-12-PBEWithSha1And128BitRC2CBC",
"06032a864886f70d010c050105": "pkcs-12-PBEWithSha1And40BitRC2CBC",
"06032a864886f70d010c050106": "pkcs-12-PBEWithSha1AndRC4",
"06032a864886f70d010c050107": "pkcs-12-PBEWithSha1AndRC2CBC",
"06032a864886f70d010c0502": "pkcs-12-EnvelopingID",
"06032a864886f70d010c050201": "pkcs-12-RSAEncryptionWith128BitRC4",
"06032a864886f70d010c050202": "pkcs-12-RSAEncryptionWith40BitRC4",
"06032a864886f70d010c050203": "pkcs-12-RSAEncryptionWithTripleDES",
"06032a864886f70d010c0503": "pkcs-12-SignatureID",
"06032a864886f70d010c050301": "pkcs-12-RSASignatureWithSHA1Digest",
"06032a864886f70d0103": "pkcs-3",
"06032a864886f70d010301": "dhKeyAgreement",
"06032a864886f70d0105": "pkcs-5",
"06032a864886f70d010501": "pbeWithMD2AndDES-CBC",
"06032a864886f70d01050a": "pbeWithSHAAndDES-CBC",
"06032a864886f70d010503": "pbeWithMD5AndDES-CBC",
"06032a864886f70d010504": "pbeWithMD2AndRC2-CBC",
"06032a864886f70d010506": "pbeWithMD5AndRC2-CBC",
"06032a864886f70d010509": "pbeWithMD5AndXOR",
"06032a864886f70d0107": "pkcs-7",
"06032a864886f70d010701": "data",
"06032a864886f70d010702": "signedData",
"06032a864886f70d010703": "envelopedData",
"06032a864886f70d010704": "signedAndEnvelopedData",
"06032a864886f70d010705": "digestData",
"06032a864886f70d010706": "encryptedData",
"06032a864886f70d010707": "dataWithAttributes",
"06032a864886f70d010708": "encryptedPrivateKeyInfo",
"06032a864886f70d0109": "pkcs-9",
"06032a864886f70d010901": "emailAddress",
"06032a864886f70d01090a": "issuerAndSerialNumber",
"06032a864886f70d01090b": "passwordCheck",
"06032a864886f70d01090c": "publicKey",
"06032a864886f70d01090d": "signingDescription",
"06032a864886f70d01090e": "extensionReq",
"06032a864886f70d01090f": "sMIMECapabilities",
"06032a864886f70d01090f01": "preferSignedData",
"06032a864886f70d01090f02": "canNotDecryptAny",
"06032a864886f70d01090f03": "receiptRequest",
"06032a864886f70d01090f04": "receipt",
"06032a864886f70d01090f05": "contentHints",
"06032a864886f70d01090f06": "mlExpansionHistory",
"06032a864886f70d010910": "id-sMIME",
"06032a864886f70d01091000": "id-mod",
"06032a864886f70d0109100001": "id-mod-cms",
"06032a864886f70d0109100002": "id-mod-ess",
"06032a864886f70d01091001": "id-ct",
"06032a864886f70d0109100101": "id-ct-receipt",
"06032a864886f70d01091002": "id-aa",
"06032a864886f70d0109100201": "id-aa-receiptRequest",
"06032a864886f70d0109100202": "id-aa-securityLabel",
"06032a864886f70d0109100203": "id-aa-mlExpandHistory",
"06032a864886f70d0109100204": "id-aa-contentHint",
"06032a864886f70d010902": "unstructuredName",
"06032a864886f70d010914": "friendlyName",
"06032a864886f70d010915": "localKeyID",
"06032a864886f70d010916": "certTypes",
"06032a864886f70d01091601": "x509Certificate",
"06032a864886f70d01091602": "sdsiCertificate",
"06032a864886f70d010917": "crlTypes",
"06032a864886f70d01091701": "x509Crl",
"06032a864886f70d010903": "contentType",
"06032a864886f70d010904": "messageDigest",
"06032a864886f70d010905": "signingTime",
"06032a864886f70d010906": "countersignature",
"06032a864886f70d010907": "challengePassword",
"06032a864886f70d010908": "unstructuredAddress",
"06032a864886f70d010909": "extendedCertificateAttributes",
"06032a864886f70d02": "digestAlgorithm",
"06032a864886f70d0202": "md2",
"06032a864886f70d0204": "md4",
"06032a864886f70d0205": "md5",
"06032a864886f70d03": "encryptionAlgorithm",
"06032a864886f70d030a": "desCDMF",
"06032a864886f70d0302": "rc2CBC",
"06032a864886f70d0303": "rc2ECB",
"06032a864886f70d0304": "rc4",
"06032a864886f70d0305": "rc4WithMAC",
"06032a864886f70d0306": "DESX-CBC",
"06032a864886f70d0307": "DES-EDE3-CBC",
"06032a864886f70d0308": "RC5CBC",
"06032a864886f70d0309": "RC5-CBCPad",
"06032a864886f7140403": "microsoftExcel",
"06032a864886f7140404": "titledWithOID",
"06032a864886f7140405": "microsoftPowerPoint",
"06032b81051086480954": "x9-84",
"06032b8105108648095400": "x9-84-Module",
"06032b810510864809540001": "x9-84-Biometrics",
"06032b810510864809540002": "x9-84-CMS",
"06032b810510864809540003": "x9-84-Identifiers",
"06032b8105108648095401": "biometric",
"06032b810510864809540100": "id-unknown-Type",
"06032b810510864809540101": "id-body-Odor",
"06032b81051086480954010a": "id-palm",
"06032b81051086480954010b": "id-retina",
"06032b81051086480954010c": "id-signature",
"06032b81051086480954010d": "id-speech-Pattern",
"06032b81051086480954010e": "id-thermal-Image",
"06032b81051086480954010f": "id-vein-Pattern",
"06032b810510864809540110": "id-thermal-Face-Image",
"06032b810510864809540111": "id-thermal-Hand-Image",
"06032b810510864809540112": "id-lip-Movement",
"06032b810510864809540113": "id-gait",
"06032b810510864809540102": "id-dna",
"06032b810510864809540103": "id-ear-Shape",
"06032b810510864809540104": "id-facial-Features",
"06032b810510864809540105": "id-finger-Image",
"06032b810510864809540106": "id-finger-Geometry",
"06032b810510864809540107": "id-hand-Geometry",
"06032b810510864809540108": "id-iris-Features",
"06032b810510864809540109": "id-keystroke-Dynamics",
"06032b8105108648095402": "processing-algorithm",
"06032b8105108648095403": "matching-method",
"06032b8105108648095404": "format-Owner",
"06032b810510864809540400": "cbeff-Owner",
"06032b810510864809540401": "ibia-Owner",
"06032b81051086480954040101": "id-ibia-SAFLINK",
"06032b8105108648095404010a": "id-ibia-SecuGen",
"06032b8105108648095404010b": "id-ibia-PreciseBiometric",
"06032b8105108648095404010c": "id-ibia-Identix",
"06032b8105108648095404010d": "id-ibia-DERMALOG",
"06032b8105108648095404010e": "id-ibia-LOGICO",
"06032b8105108648095404010f": "id-ibia-NIST",
"06032b81051086480954040110": "id-ibia-A3Vision",
"06032b81051086480954040111": "id-ibia-NEC",
"06032b81051086480954040112": "id-ibia-STMicroelectronics",
"06032b81051086480954040102": "id-ibia-Bioscrypt",
"06032b81051086480954040103": "id-ibia-Visionics",
"06032b81051086480954040104": "id-ibia-InfineonTechnologiesAG",
"06032b81051086480954040105": "id-ibia-IridianTechnologies",
"06032b81051086480954040106": "id-ibia-Veridicom",
"06032b81051086480954040107": "id-ibia-CyberSIGN",
"06032b81051086480954040108": "id-ibia-eCryp.",
"06032b81051086480954040109": "id-ibia-FingerprintCardsAB",
"06032b810510864809540402": "x9-Owner",
"06032b0e021a05": "sha",
"06032b0e03020101": "rsa",
"06032b0e03020a": "desMAC",
"06032b0e03020b": "rsaSignature",
"06032b0e03020c": "dsa",
"06032b0e03020d": "dsaWithSHA",
"06032b0e03020e": "mdc2WithRSASignature",
"06032b0e03020f": "shaWithRSASignature",
"06032b0e030210": "dhWithCommonModulus",
"06032b0e030211": "desEDE",
"06032b0e030212": "sha",
"06032b0e030213": "mdc-2",
"06032b0e030202": "md4WitRSA",
"06032b0e03020201": "sqmod-N",
"06032b0e030214": "dsaCommon",
"06032b0e030215": "dsaCommonWithSHA",
"06032b0e030216": "rsaKeyTransport",
"06032b0e030217": "keyed-hash-seal",
"06032b0e030218": "md2WithRSASignature",
"06032b0e030219": "md5WithRSASignature",
"06032b0e03021a": "sha1",
"06032b0e03021b": "dsaWithSHA1",
"06032b0e03021c": "dsaWithCommonSHA1",
"06032b0e03021d": "sha-1WithRSAEncryption",
"06032b0e030203": "md5WithRSA",
"06032b0e03020301": "sqmod-NwithRSA",
"06032b0e030204": "md4WithRSAEncryption",
"06032b0e030206": "desECB",
"06032b0e030207": "desCBC",
"06032b0e030208": "desOFB",
"06032b0e030209": "desCFB",
"06032b0e030301": "simple-strong-auth-mechanism",
"06032b0e07020101": "ElGamal",
"06032b0e07020301": "md2WithRSA",
"06032b0e07020302": "md2WithElGamal",
"06032b2403": "algorithm",
"06032b240301": "encryptionAlgorithm",
"06032b24030101": "des",
"06032b240301010101": "desECBPad",
"06032b24030101010101": "desECBPadISO",
"06032b240301010201": "desCBCPad",
"06032b24030101020101": "desCBCPadISO",
"06032b24030102": "idea",
"06032b2403010201": "ideaECB",
"06032b240301020101": "ideaECBPad",
"06032b24030102010101": "ideaECBPadISO",
"06032b2403010202": "ideaCBC",
"06032b240301020201": "ideaCBCPad",
"06032b24030102020101": "ideaCBCPadISO",
"06032b2403010203": "ideaOFB",
"06032b2403010204": "ideaCFB",
"06032b24030103": "des-3",
"06032b240301030101": "des-3ECBPad",
"06032b24030103010101": "des-3ECBPadISO",
"06032b240301030201": "des-3CBCPad",
"06032b24030103020101": "des-3CBCPadISO",
"06032b240302": "hashAlgorithm",
"06032b24030201": "ripemd160",
"06032b24030202": "ripemd128",
"06032b24030203": "ripemd256",
"06032b24030204": "mdc2singleLength",
"06032b24030205": "mdc2doubleLength",
"06032b240303": "signatureAlgorithm",
"06032b24030301": "rsa",
"06032b2403030101": "rsaMitSHA-1",
"06032b2403030102": "rsaMitRIPEMD160",
"06032b24030302": "ellipticCurve",
"06032b240304": "signatureScheme",
"06032b24030401": "iso9796-1",
"06032b2403040201": "iso9796-2",
"06032b2403040202": "iso9796-2rsa",
"06032b2404": "attribute",
"06032b2405": "policy",
"06032b2406": "api",
"06032b240601": "manufacturerSpecific",
"06032b240602": "functionalitySpecific",
"06032b2407": "api",
"06032b240701": "keyAgreement",
"06032b240702": "keyTransport",
"06032b06010401927c0a0101": "UNINETT policyIdentifier",
"06032b0601040195180a": "ICE-TEL policyIdentifier",
"06032b0601040197552001": "cryptlibEnvelope",
"06032b0601040197552002": "cryptlibPrivateKey",
"060a2b060104018237": "Microsoft OID",
"060a2b0601040182370a": "Crypto 2.0",
"060a2b0601040182370a01": "certTrustList",
"060a2b0601040182370a0101": "szOID_SORTED_CTL",
"060a2b0601040182370a0a": "Microsoft CMC OIDs",
"060a2b0601040182370a0a01": "szOID_CMC_ADD_ATTRIBUTES",
"060a2b0601040182370a0b": "Microsoft certificate property OIDs",
"060a2b0601040182370a0b01": "szOID_CERT_PROP_ID_PREFIX",
"060a2b0601040182370a0c": "CryptUI",
"060a2b0601040182370a0c01": "szOID_ANY_APPLICATION_POLICY",
"060a2b0601040182370a02": "nextUpdateLocation",
"060a2b0601040182370a0301": "certTrustListSigning",
"060a2b0601040182370a030a": "szOID_KP_QUALIFIED_SUBORDINATION",
"060a2b0601040182370a030b": "szOID_KP_KEY_RECOVERY",
"060a2b0601040182370a030c": "szOID_KP_DOCUMENT_SIGNING",
"060a2b0601040182370a0302": "timeStampSigning",
"060a2b0601040182370a0303": "serverGatedCrypto",
"060a2b0601040182370a030301": "szOID_SERIALIZED",
"060a2b0601040182370a0304": "encryptedFileSystem",
"060a2b0601040182370a030401": "szOID_EFS_RECOVERY",
"060a2b0601040182370a0305": "szOID_WHQL_CRYPTO",
"060a2b0601040182370a0306": "szOID_NT5_CRYPTO",
"060a2b0601040182370a0307": "szOID_OEM_WHQL_CRYPTO",
"060a2b0601040182370a0308": "szOID_EMBEDDED_NT_CRYPTO",
"060a2b0601040182370a0309": "szOID_ROOT_LIST_SIGNER",
"060a2b0601040182370a0401": "yesnoTrustAttr",
"060a2b0601040182370a0501": "szOID_DRM",
"060a2b0601040182370a0502": "szOID_DRM_INDIVIDUALIZATION",
"060a2b0601040182370a0601": "szOID_LICENSES",
"060a2b0601040182370a0602": "szOID_LICENSE_SERVER",
"060a2b0601040182370a07": "szOID_MICROSOFT_RDN_PREFIX",
"060a2b0601040182370a0701": "szOID_KEYID_RDN",
"060a2b0601040182370a0801": "szOID_REMOVE_CERTIFICATE",
"060a2b0601040182370a0901": "szOID_CROSS_CERT_DIST_POINTS",
"060a2b0601040182370c": "Catalog",
"060a2b0601040182370c0101": "szOID_CATALOG_LIST",
"060a2b0601040182370c0102": "szOID_CATALOG_LIST_MEMBER",
"060a2b0601040182370c0201": "CAT_NAMEVALUE_OBJID",
"060a2b0601040182370c0202": "CAT_MEMBERINFO_OBJID",
"060a2b0601040182370d": "Microsoft PKCS10 OIDs",
"060a2b0601040182370d01": "szOID_RENEWAL_CERTIFICATE",
"060a2b0601040182370d0201": "szOID_ENROLLMENT_NAME_VALUE_PAIR",
"060a2b0601040182370d0202": "szOID_ENROLLMENT_CSP_PROVIDER",
"060a2b0601040182370d0203": "OS Version",
"060a2b0601040182370f": "Microsoft Java",
"060a2b06010401823710": "Microsoft Outlook/Exchange",
"060a2b0601040182371004": "Outlook Express",
"060a2b06010401823711": "Microsoft PKCS12 attributes",
"060a2b0601040182371101": "szOID_LOCAL_MACHINE_KEYSET",
"060a2b06010401823712": "Microsoft Hydra",
"060a2b06010401823713": "Microsoft ISPU Test",
"060a2b06010401823702": "Authenticode",
"060a2b06010401823702010a": "spcAgencyInfo",
"060a2b06010401823702010b": "spcStatementType",
"060a2b06010401823702010c": "spcSpOpusInfo",
"060a2b06010401823702010e": "certExtensions",
"060a2b06010401823702010f": "spcPelmageData",
"060a2b060104018237020112": "SPC_RAW_FILE_DATA_OBJID",
"060a2b060104018237020113": "SPC_STRUCTURED_STORAGE_DATA_OBJID",
"060a2b060104018237020114": "spcLink",
"060a2b060104018237020115": "individualCodeSigning",
"060a2b060104018237020116": "commercialCodeSigning",
"060a2b060104018237020119": "spcLink",
"060a2b06010401823702011a": "spcMinimalCriteriaInfo",
"060a2b06010401823702011b": "spcFinancialCriteriaInfo",
"060a2b06010401823702011c": "spcLink",
"060a2b06010401823702011d": "SPC_HASH_INFO_OBJID",
"060a2b06010401823702011e": "SPC_SIPINFO_OBJID",
"060a2b060104018237020104": "spcIndirectDataContext",
"060a2b0601040182370202": "CTL for Software Publishers Trusted CAs",
"060a2b060104018237020201": "szOID_TRUSTED_CODESIGNING_CA_LIST",
"060a2b060104018237020202": "szOID_TRUSTED_CLIENT_AUTH_CA_LIST",
"060a2b060104018237020203": "szOID_TRUSTED_SERVER_AUTH_CA_LIST",
"060a2b06010401823714": "Microsoft Enrollment Infrastructure",
"060a2b0601040182371401": "szOID_AUTO_ENROLL_CTL_USAGE",
"060a2b0601040182371402": "szOID_ENROLL_CERTTYPE_EXTENSION",
"060a2b060104018237140201": "szOID_ENROLLMENT_AGENT",
"060a2b060104018237140202": "szOID_KP_SMARTCARD_LOGON",
"060a2b060104018237140203": "szOID_NT_PRINCIPAL_NAME",
"060a2b0601040182371403": "szOID_CERT_MANIFOLD",
"06092b06010401823715": "Microsoft CertSrv Infrastructure",
"06092b0601040182371501": "szOID_CERTSRV_CA_VERSION",
"06092b0601040182371514": "Client Information",
"060a2b06010401823719": "Microsoft Directory Service",
"060a2b0601040182371901": "szOID_NTDS_REPLICATION",
"060a2b06010401823703": "Time Stamping",
"060a2b060104018237030201": "SPC_TIME_STAMP_REQUEST_OBJID",
"060a2b0601040182371e": "IIS",
"060a2b0601040182371f": "Windows updates and service packs",
"060a2b0601040182371f01": "szOID_PRODUCT_UPDATE",
"060a2b06010401823704": "Permissions",
"060a2b06010401823728": "Fonts",
"060a2b06010401823729": "Microsoft Licensing and Registration",
"060a2b0601040182372a": "Microsoft Corporate PKI (ITG)",
"060a2b06010401823758": "CAPICOM",
"060a2b0601040182375801": "szOID_CAPICOM_VERSION",
"060a2b0601040182375802": "szOID_CAPICOM_ATTRIBUTE",
"060a2b060104018237580201": "szOID_CAPICOM_DOCUMENT_NAME",
"060a2b060104018237580202": "szOID_CAPICOM_DOCUMENT_DESCRIPTION",
"060a2b0601040182375803": "szOID_CAPICOM_ENCRYPTED_DATA",
"060a2b060104018237580301": "szOID_CAPICOM_ENCRYPTED_CONTENT",
"06032b0601050507": "pkix",
"06032b060105050701": "privateExtension",
"06032b06010505070101": "authorityInfoAccess",
"06032b06010505070c02": "CMC Data",
"06032b060105050702": "policyQualifierIds",
// "06032b06010505070201" : "cps",
"06032b06010505070202": "unotice",
"06032b060105050703": "keyPurpose",
"06032b06010505070301": "serverAuth",
"06032b06010505070302": "clientAuth",
"06032b06010505070303": "codeSigning",
"06032b06010505070304": "emailProtection",
"06032b06010505070305": "ipsecEndSystem",
"06032b06010505070306": "ipsecTunnel",
"06032b06010505070307": "ipsecUser",
"06032b06010505070308": "timeStamping",
"06032b060105050704": "cmpInformationTypes",
"06032b06010505070401": "caProtEncCert",
"06032b06010505070402": "signKeyPairTypes",
"06032b06010505070403": "encKeyPairTypes",
"06032b06010505070404": "preferredSymmAlg",
"06032b06010505070405": "caKeyUpdateInfo",
"06032b06010505070406": "currentCRL",
"06032b06010505073001": "ocsp",
"06032b06010505073002": "caIssuers",
"06032b06010505080101": "HMAC-MD5",
"06032b06010505080102": "HMAC-SHA",
"060360864801650201010a": "mosaicKeyManagementAlgorithm",
"060360864801650201010b": "sdnsKMandSigAlgorithm",
"060360864801650201010c": "mosaicKMandSigAlgorithm",
"060360864801650201010d": "SuiteASignatureAlgorithm",
"060360864801650201010e": "SuiteAConfidentialityAlgorithm",
"060360864801650201010f": "SuiteAIntegrityAlgorithm",
"06036086480186f84201": "cert-extension",
// "06036086480186f8420101" : "netscape-cert-type",
"06036086480186f842010a": "EntityLogo",
"06036086480186f842010b": "UserPicture",
// "06036086480186f842010c" : "netscape-ssl-server-name",
// "06036086480186f842010d" : "netscape-comment",
// "06036086480186f8420102" : "netscape-base-url",
// "06036086480186f8420103" : "netscape-revocation-url",
// "06036086480186f8420104" : "netscape-ca-revocation-url",
// "06036086480186f8420107" : "netscape-cert-renewal-url",
// "06036086480186f8420108" : "netscape-ca-policy-url",
"06036086480186f8420109": "HomePage-url",
"06036086480186f84202": "data-type",
"06036086480186f8420201": "GIF",
"06036086480186f8420202": "JPEG",
"06036086480186f8420203": "URL",
"06036086480186f8420204": "HTML",
"06036086480186f8420205": "netscape-cert-sequence",
"06036086480186f8420206": "netscape-cert-url",
"06036086480186f84203": "directory",
"06036086480186f8420401": "serverGatedCrypto",
"06036086480186f845010603": "Unknown Verisign extension",
"06036086480186f845010606": "Unknown Verisign extension",
"06036086480186f84501070101": "Verisign certificatePolicy",
"06036086480186f8450107010101": "Unknown Verisign policy qualifier",
"06036086480186f8450107010102": "Unknown Verisign policy qualifier",
"0603678105": "TCPA",
"060367810501": "tcpaSpecVersion",
"060367810502": "tcpaAttribute",
"06036781050201": "tcpaAtTpmManufacturer",
"0603678105020a": "tcpaAtSecurityQualities",
"0603678105020b": "tcpaAtTpmProtectionProfile",
"0603678105020c": "tcpaAtTpmSecurityTarget",
"0603678105020d": "tcpaAtFoundationProtectionProfile",
"0603678105020e": "tcpaAtFoundationSecurityTarget",
"0603678105020f": "tcpaAtTpmIdLabel",
"06036781050202": "tcpaAtTpmModel",
"06036781050203": "tcpaAtTpmVersion",
"06036781050204": "tcpaAtPlatformManufacturer",
"06036781050205": "tcpaAtPlatformModel",
"06036781050206": "tcpaAtPlatformVersion",
"06036781050207": "tcpaAtComponentManufacturer",
"06036781050208": "tcpaAtComponentModel",
"06036781050209": "tcpaAtComponentVersion",
"060367810503": "tcpaProtocol",
"06036781050301": "tcpaPrttTpmIdProtocol",
"0603672a00": "contentType",
"0603672a0000": "PANData",
"0603672a0001": "PANToken",
"0603672a0002": "PANOnly",
"0603672a01": "msgExt",
"0603672a0a": "national",
"0603672a0a8140": "Japan",
"0603672a02": "field",
"0603672a0200": "fullName",
"0603672a0201": "givenName",
"0603672a020a": "amount",
"0603672a0202": "familyName",
"0603672a0203": "birthFamilyName",
"0603672a0204": "placeName",
"0603672a0205": "identificationNumber",
"0603672a0206": "month",
"0603672a0207": "date",
"0603672a02070b": "accountNumber",
"0603672a02070c": "passPhrase",
"0603672a0208": "address",
"0603672a0209": "telephone",
"0603672a03": "attribute",
"0603672a0300": "cert",
"0603672a030000": "rootKeyThumb",
"0603672a030001": "additionalPolicy",
"0603672a04": "algorithm",
"0603672a05": "policy",
"0603672a0500": "root",
"0603672a06": "module",
"0603672a07": "certExt",
"0603672a0700": "hashedRootKey",
"0603672a0701": "certificateType",
"0603672a0702": "merchantData",
"0603672a0703": "cardCertRequired",
"0603672a0704": "tunneling",
"0603672a0705": "setExtensions",
"0603672a0706": "setQualifier",
"0603672a08": "brand",
"0603672a0801": "IATA-ATA",
"0603672a081e": "Diners",
"0603672a0822": "AmericanExpress",
"0603672a0804": "VISA",
"0603672a0805": "MasterCard",
"0603672a08ae7b": "Novus",
"0603672a09": "vendor",
"0603672a0900": "GlobeSet",
"0603672a0901": "IBM",
"0603672a090a": "Griffin",
"0603672a090b": "Certicom",
"0603672a090c": "OSS",
"0603672a090d": "TenthMountain",
"0603672a090e": "Antares",
"0603672a090f": "ECC",
"0603672a0910": "Maithean",
"0603672a0911": "Netscape",
"0603672a0912": "Verisign",
"0603672a0913": "BlueMoney",
"0603672a0902": "CyberCash",
"0603672a0914": "Lacerte",
"0603672a0915": "Fujitsu",
"0603672a0916": "eLab",
"0603672a0917": "Entrust",
"0603672a0918": "VIAnet",
"0603672a0919": "III",
"0603672a091a": "OpenMarket",
"0603672a091b": "Lexem",
"0603672a091c": "Intertrader",
"0603672a091d": "Persimmon",
"0603672a0903": "Terisa",
"0603672a091e": "NABLE",
"0603672a091f": "espace-net",
"0603672a0920": "Hitachi",
"0603672a0921": "Microsoft",
"0603672a0922": "NEC",
"0603672a0923": "Mitsubishi",
"0603672a0924": "NCR",
"0603672a0925": "e-COMM",
"0603672a0926": "Gemplus",
"0603672a0904": "RSADSI",
"0603672a0905": "VeriFone",
"0603672a0906": "TrinTech",
"0603672a0907": "BankGate",
"0603672a0908": "GTE",
"0603672a0909": "CompuSource",
"0603551d01": "authorityKeyIdentifier",
"0603551d0a": "basicConstraints",
"0603551d0b": "nameConstraints",
"0603551d0c": "policyConstraints",
"0603551d0d": "basicConstraints",
"0603551d0e": "subjectKeyIdentifier",
"0603551d0f": "keyUsage",
"0603551d10": "privateKeyUsagePeriod",
"0603551d11": "subjectAltName",
"0603551d12": "issuerAltName",
"0603551d13": "basicConstraints",
"0603551d02": "keyAttributes",
"0603551d14": "cRLNumber",
"0603551d15": "cRLReason",
"0603551d16": "expirationDate",
"0603551d17": "instructionCode",
"0603551d18": "invalidityDate",
"0603551d1a": "issuingDistributionPoint",
"0603551d1b": "deltaCRLIndicator",
"0603551d1c": "issuingDistributionPoint",
"0603551d1d": "certificateIssuer",
"0603551d03": "certificatePolicies",
"0603551d1e": "nameConstraints",
"0603551d1f": "cRLDistributionPoints",
"0603551d20": "certificatePolicies",
"0603551d21": "policyMappings",
"0603551d22": "policyConstraints",
"0603551d23": "authorityKeyIdentifier",
"0603551d24": "policyConstraints",
"0603551d25": "extKeyUsage",
"0603551d04": "keyUsageRestriction",
"0603551d05": "policyMapping",
"0603551d06": "subtreesConstraint",
"0603551d07": "subjectAltName",
"0603551d08": "issuerAltName",
"0603551d09": "subjectDirectoryAttributes",
"0603550400": "objectClass",
"0603550401": "aliasObjectName",
// "060355040c" : "title",
"060355040d": "description",
"060355040e": "searchGuide",
"060355040f": "businessCategory",
"0603550410": "postalAddress",
"0603550411": "postalCode",
"0603550412": "postOfficeBox",
"0603550413": "physicalDeliveryOfficeName",
"0603550402": "knowledgeInformation",
// "0603550414" : "telephoneNumber",
"0603550415": "telexNumber",
"0603550416": "teletexTerminalIdentifier",
"0603550417": "facsimileTelephoneNumber",
"0603550418": "x121Address",
"0603550419": "internationalISDNNumber",
"060355041a": "registeredAddress",
"060355041b": "destinationIndicator",
"060355041c": "preferredDeliveryMehtod",
"060355041d": "presentationAddress",
"060355041e": "supportedApplicationContext",
"060355041f": "member",
"0603550420": "owner",
"0603550421": "roleOccupant",
"0603550422": "seeAlso",
"0603550423": "userPassword",
"0603550424": "userCertificate",
"0603550425": "caCertificate",
"0603550426": "authorityRevocationList",
"0603550427": "certificateRevocationList",
"0603550428": "crossCertificatePair",
"0603550429": "givenName",
// "060355042a" : "givenName",
"0603550405": "serialNumber",
"0603550434": "supportedAlgorithms",
"0603550435": "deltaRevocationList",
"060355043a": "crossCertificatePair",
// "0603550409" : "streetAddress",
"06035508": "X.500-Algorithms",
"0603550801": "X.500-Alg-Encryption",
"060355080101": "rsa",
"0603604c0101": "DPC"
};

View File

@ -20,7 +20,7 @@ const Rotate = {
* @constant * @constant
* @default * @default
*/ */
ROTATE_WHOLE: false, ROTATE_CARRY: false,
/** /**
* Runs rotation operations across the input data. * Runs rotation operations across the input data.
@ -53,7 +53,7 @@ const Rotate = {
*/ */
runRotr: function(input, args) { runRotr: function(input, args) {
if (args[1]) { if (args[1]) {
return Rotate._rotrWhole(input, args[0]); return Rotate._rotrCarry(input, args[0]);
} else { } else {
return Rotate._rot(input, args[0], Rotate._rotr); return Rotate._rot(input, args[0], Rotate._rotr);
} }
@ -69,7 +69,7 @@ const Rotate = {
*/ */
runRotl: function(input, args) { runRotl: function(input, args) {
if (args[1]) { if (args[1]) {
return Rotate._rotlWhole(input, args[0]); return Rotate._rotlCarry(input, args[0]);
} else { } else {
return Rotate._rot(input, args[0], Rotate._rotl); return Rotate._rot(input, args[0], Rotate._rotl);
} }
@ -197,7 +197,7 @@ const Rotate = {
* @param {number} amount * @param {number} amount
* @returns {byteArray} * @returns {byteArray}
*/ */
_rotrWhole: function(data, amount) { _rotrCarry: function(data, amount) {
let carryBits = 0, let carryBits = 0,
newByte, newByte,
result = []; result = [];
@ -223,7 +223,7 @@ const Rotate = {
* @param {number} amount * @param {number} amount
* @returns {byteArray} * @returns {byteArray}
*/ */
_rotlWhole: function(data, amount) { _rotlCarry: function(data, amount) {
let carryBits = 0, let carryBits = 0,
newByte, newByte,
result = []; result = [];

View File

@ -249,7 +249,7 @@ const SeqUtils = {
} }
} }
return 0; return a.localeCompare(b);
}, },
}; };

View 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;

View File

@ -1,5 +1,4 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import * as JsDiff from "diff";
/** /**
@ -40,7 +39,7 @@ const StrUtils = {
}, },
{ {
name: "Domain", name: "Domain",
value: "(?:(https?):\\/\\/)?([-\\w.]+)\\.(com|net|org|biz|info|co|uk|onion|int|mobi|name|edu|gov|mil|eu|ac|ae|af|de|ca|ch|cn|cy|es|gb|hk|il|in|io|tv|me|nl|no|nz|ro|ru|tr|us|az|ir|kz|uz|pk)+" value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b"
}, },
{ {
name: "Windows file path", name: "Windows file path",
@ -294,83 +293,6 @@ const StrUtils = {
}, },
/**
* @constant
* @default
*/
DIFF_SAMPLE_DELIMITER: "\\n\\n",
/**
* @constant
* @default
*/
DIFF_BY: ["Character", "Word", "Line", "Sentence", "CSS", "JSON"],
/**
* Diff operation.
*
* @param {string} input
* @param {Object[]} args
* @returns {html}
*/
runDiff: function(input, args) {
let sampleDelim = args[0],
diffBy = args[1],
showAdded = args[2],
showRemoved = args[3],
ignoreWhitespace = args[4],
samples = input.split(sampleDelim),
output = "",
diff;
if (!samples || samples.length !== 2) {
return "Incorrect number of samples, perhaps you need to modify the sample delimiter or add more samples?";
}
switch (diffBy) {
case "Character":
diff = JsDiff.diffChars(samples[0], samples[1]);
break;
case "Word":
if (ignoreWhitespace) {
diff = JsDiff.diffWords(samples[0], samples[1]);
} else {
diff = JsDiff.diffWordsWithSpace(samples[0], samples[1]);
}
break;
case "Line":
if (ignoreWhitespace) {
diff = JsDiff.diffTrimmedLines(samples[0], samples[1]);
} else {
diff = JsDiff.diffLines(samples[0], samples[1]);
}
break;
case "Sentence":
diff = JsDiff.diffSentences(samples[0], samples[1]);
break;
case "CSS":
diff = JsDiff.diffCss(samples[0], samples[1]);
break;
case "JSON":
diff = JsDiff.diffJson(samples[0], samples[1]);
break;
default:
return "Invalid 'Diff by' option.";
}
for (let i = 0; i < diff.length; i++) {
if (diff[i].added) {
if (showAdded) output += "<span class='hl5'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else if (diff[i].removed) {
if (showRemoved) output += "<span class='hl3'>" + Utils.escapeHtml(diff[i].value) + "</span>";
} else {
output += Utils.escapeHtml(diff[i].value);
}
}
return output;
},
/** /**
* @constant * @constant
* @default * @default

View File

@ -1,5 +1,6 @@
/* globals unescape */ /* globals unescape */
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import url from "url";
/** /**
@ -58,56 +59,36 @@ const URL_ = {
* @returns {string} * @returns {string}
*/ */
runParse: function(input, args) { runParse: function(input, args) {
if (!document) { const uri = url.parse(input, true);
throw "This operation only works in a browser.";
}
const a = document.createElement("a"); let output = "";
// Overwrite base href which will be the current CyberChef URL to reduce confusion. if (uri.protocol) output += "Protocol:\t" + uri.protocol + "\n";
a.href = "http://example.com/"; if (uri.auth) output += "Auth:\t\t" + uri.auth + "\n";
a.href = input; 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) { keys.forEach(k => {
let output = ""; padding = (k.length > padding) ? k.length : padding;
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";
}
if (a.pathname && a.pathname !== window.location.pathname) { output += "Arguments:\n";
let pathname = a.pathname; for (let key in uri.query) {
if (pathname.indexOf(window.location.pathname) === 0) output += "\t" + Utils.padRight(key, padding);
pathname = pathname.replace(window.location.pathname, ""); if (uri.query[key].length) {
if (pathname) output += " = " + uri.query[key] + "\n";
output += "Path name:\t" + pathname + "\n"; } else {
} output += "\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";
} }
} }
return output;
} }
if (uri.hash) output += "Hash:\t\t" + uri.hash + "\n";
return "Invalid URI"; return output;
}, },

View File

@ -9,7 +9,7 @@ require("babel-polyfill");
const Chef = require("../core/Chef.js").default; const Chef = require("../core/Chef.js").default;
const CyberChef = module.exports = { const CyberChef = {
bake: function(input, recipeConfig) { bake: function(input, recipeConfig) {
this.chef = new Chef(); this.chef = new Chef();
@ -23,3 +23,5 @@ const CyberChef = module.exports = {
} }
}; };
module.exports = CyberChef;

View File

@ -1,5 +1,4 @@
import Utils from "../core/Utils.js"; import Utils from "../core/Utils.js";
import Chef from "../core/Chef.js";
import Manager from "./Manager.js"; import Manager from "./Manager.js";
import HTMLCategory from "./HTMLCategory.js"; import HTMLCategory from "./HTMLCategory.js";
import HTMLOperation from "./HTMLOperation.js"; import HTMLOperation from "./HTMLOperation.js";
@ -27,7 +26,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
this.doptions = defaultOptions; this.doptions = defaultOptions;
this.options = Utils.extend({}, defaultOptions); this.options = Utils.extend({}, defaultOptions);
this.chef = new Chef();
this.manager = new Manager(this); this.manager = new Manager(this);
this.baking = false; this.baking = false;
@ -35,8 +33,6 @@ const App = function(categories, operations, defaultFavourites, defaultOptions)
this.autoBakePause = false; this.autoBakePause = false;
this.progress = 0; this.progress = 0;
this.ingId = 0; this.ingId = 0;
window.chef = this.chef;
}; };
@ -54,6 +50,8 @@ App.prototype.setup = function() {
this.resetLayout(); this.resetLayout();
this.setCompileMessage(); this.setCompileMessage();
this.loadURIParams(); this.loadURIParams();
this.appLoaded = true;
this.loaded(); this.loaded();
}; };
@ -64,6 +62,11 @@ App.prototype.setup = function() {
* @fires Manager#apploaded * @fires Manager#apploaded
*/ */
App.prototype.loaded = function() { App.prototype.loaded = function() {
// Check that both the app and the worker have loaded successfully, and that
// we haven't already loaded before attempting to remove the loading screen.
if (!this.workerLoaded || !this.appLoaded ||
!document.getElementById("loader-wrapper")) return;
// Trigger CSS animations to remove preloader // Trigger CSS animations to remove preloader
document.body.classList.add("loaded"); document.body.classList.add("loaded");
@ -85,85 +88,34 @@ App.prototype.loaded = function() {
* An error handler for displaying the error to the user. * An error handler for displaying the error to the user.
* *
* @param {Error} err * @param {Error} err
* @param {boolean} [logToConsole=false]
*/ */
App.prototype.handleError = function(err) { App.prototype.handleError = function(err, logToConsole) {
console.error(err); if (logToConsole) console.error(err);
const msg = err.displayStr || err.toString(); const msg = err.displayStr || err.toString();
this.alert(msg, "danger", this.options.errorTimeout, !this.options.showErrors); this.alert(msg, "danger", this.options.errorTimeout, !this.options.showErrors);
}; };
/** /**
* Updates the UI to show if baking is in process or not. * Asks the ChefWorker to bake the current input using the current recipe.
*
* @param {bakingStatus}
*/
App.prototype.setBakingStatus = function(bakingStatus) {
this.baking = bakingStatus;
let inputLoadingIcon = document.querySelector("#input .title .loading-icon"),
outputLoadingIcon = document.querySelector("#output .title .loading-icon"),
outputElement = document.querySelector("#output-text");
if (bakingStatus) {
inputLoadingIcon.style.display = "inline-block";
outputLoadingIcon.style.display = "inline-block";
outputElement.classList.add("disabled");
outputElement.disabled = true;
} else {
inputLoadingIcon.style.display = "none";
outputLoadingIcon.style.display = "none";
outputElement.classList.remove("disabled");
outputElement.disabled = false;
}
};
/**
* Calls the Chef to bake the current input using the current recipe.
* *
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the * @param {boolean} [step] - Set to true if we should only execute one operation instead of the
* whole recipe. * whole recipe.
*/ */
App.prototype.bake = async function(step) { App.prototype.bake = function(step) {
let response;
if (this.baking) return; if (this.baking) return;
this.setBakingStatus(true); // Reset attemptHighlight flag
this.options.attemptHighlight = true;
try { this.manager.worker.bake(
response = await this.chef.bake( this.getInput(), // The user's input
this.getInput(), // The user's input this.getRecipeConfig(), // The configuration of the recipe
this.getRecipeConfig(), // The configuration of the recipe this.options, // Options set by the user
this.options, // Options set by the user this.progress, // The current position in the recipe
this.progress, // The current position in the recipe step // Whether or not to take one step or execute the whole recipe
step // Whether or not to take one step or execute the whole recipe );
);
} catch (err) {
this.handleError(err);
}
this.setBakingStatus(false);
if (!response) return;
if (response.error) {
this.handleError(response.error);
}
this.options = response.options;
this.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
this.progress = response.progress;
this.manager.recipe.updateBreakpointIndicator(response.progress);
this.manager.output.set(response.result, response.type, response.duration);
// If baking took too long, disable auto-bake
if (response.duration > this.options.autoBakeThreshold && this.autoBake_) {
this.manager.controls.setAutoBake(false);
this.alert("Baking took longer than " + this.options.autoBakeThreshold +
"ms, Auto Bake has been disabled.", "warning", 5000);
}
}; };
@ -171,30 +123,36 @@ App.prototype.bake = async function(step) {
* Runs Auto Bake if it is set. * Runs Auto Bake if it is set.
*/ */
App.prototype.autoBake = function() { App.prototype.autoBake = function() {
if (this.autoBake_ && !this.autoBakePause) { // 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(); this.bake();
} else {
this.manager.controls.showStaleIndicator();
} }
}; };
/** /**
* Runs a silent bake forcing the browser to load and cache all the relevant JavaScript code needed * Runs a silent bake, forcing the browser to load and cache all the relevant JavaScript code needed
* to do a real bake. * to do a real bake.
* *
* The output will not be modified (hence "silent" bake). This will only actually execute the * The output will not be modified (hence "silent" bake). This will only actually execute the recipe
* recipe if auto-bake is enabled, otherwise it will just load the recipe, ingredients and dish. * if auto-bake is enabled, otherwise it will just wake up the ChefWorker with an empty recipe.
*
* @returns {number} - The number of miliseconds it took to run the silent bake.
*/ */
App.prototype.silentBake = function() { App.prototype.silentBake = function() {
let startTime = new Date().getTime(), let recipeConfig = [];
recipeConfig = this.getRecipeConfig();
if (this.autoBake_) { if (this.autoBake_) {
this.chef.silentBake(recipeConfig); // If auto-bake is not enabled we don't want to actually run the recipe as it may be disabled
// for a good reason.
recipeConfig = this.getRecipeConfig();
} }
return new Date().getTime() - startTime; this.manager.worker.silentBake(recipeConfig);
}; };
@ -264,7 +222,7 @@ App.prototype.populateOperationsList = function() {
App.prototype.initialiseSplitter = function() { App.prototype.initialiseSplitter = function() {
this.columnSplitter = Split(["#operations", "#recipe", "#IO"], { this.columnSplitter = Split(["#operations", "#recipe", "#IO"], {
sizes: [20, 30, 50], sizes: [20, 30, 50],
minSize: [240, 325, 440], minSize: [240, 325, 450],
gutterSize: 4, gutterSize: 4,
onDrag: function() { onDrag: function() {
this.manager.controls.adjustWidth(); this.manager.controls.adjustWidth();
@ -288,7 +246,7 @@ App.prototype.initialiseSplitter = function() {
App.prototype.loadLocalStorage = function() { App.prototype.loadLocalStorage = function() {
// Load options // Load options
let lOptions; let lOptions;
if (localStorage.options !== undefined) { if (this.isLocalStorageAvailable() && localStorage.options !== undefined) {
lOptions = JSON.parse(localStorage.options); lOptions = JSON.parse(localStorage.options);
} }
this.manager.options.load(lOptions); this.manager.options.load(lOptions);
@ -304,13 +262,17 @@ App.prototype.loadLocalStorage = function() {
* If the user currently has no saved favourites, the defaults from the view constructor are used. * If the user currently has no saved favourites, the defaults from the view constructor are used.
*/ */
App.prototype.loadFavourites = function() { App.prototype.loadFavourites = function() {
let favourites = localStorage.favourites && let favourites;
localStorage.favourites.length > 2 ?
JSON.parse(localStorage.favourites) :
this.dfavourites;
favourites = this.validFavourites(favourites); if (this.isLocalStorageAvailable()) {
this.saveFavourites(favourites); 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) { const favCat = this.categories.filter(function(c) {
return c.name === "Favourites"; return c.name === "Favourites";
@ -354,6 +316,15 @@ App.prototype.validFavourites = function(favourites) {
* @param {string[]} favourites - A list of the user's favourite operations * @param {string[]} favourites - A list of the user's favourite operations
*/ */
App.prototype.saveFavourites = function(favourites) { 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))); localStorage.setItem("favourites", JSON.stringify(this.validFavourites(favourites)));
}; };
@ -404,10 +375,6 @@ App.prototype.loadURIParams = function() {
window.location.hash; window.location.hash;
this.uriParams = Utils.parseURIParams(params); 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 // Read in recipe from URI params
if (this.uriParams.recipe) { if (this.uriParams.recipe) {
try { try {
@ -436,14 +403,16 @@ App.prototype.loadURIParams = function() {
// Read in input data from URI params // Read in input data from URI params
if (this.uriParams.input) { if (this.uriParams.input) {
this.autoBakePause = true;
try { try {
const inputData = Utils.fromBase64(this.uriParams.input); const inputData = Utils.fromBase64(this.uriParams.input);
this.setInput(inputData); this.setInput(inputData);
} catch (err) {} } catch (err) {
} finally {
this.autoBakePause = false;
}
} }
// Unpause auto-bake
this.autoBakePause = false;
this.autoBake(); this.autoBake();
}; };
@ -476,6 +445,10 @@ App.prototype.getRecipeConfig = function() {
App.prototype.setRecipeConfig = function(recipeConfig) { App.prototype.setRecipeConfig = function(recipeConfig) {
document.getElementById("rec-list").innerHTML = null; 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++) { for (let i = 0; i < recipeConfig.length; i++) {
const item = this.manager.recipe.addOperation(recipeConfig[i].op); const item = this.manager.recipe.addOperation(recipeConfig[i].op);
@ -508,6 +481,9 @@ App.prototype.setRecipeConfig = function(recipeConfig) {
this.progress = 0; this.progress = 0;
} }
// Unpause auto bake
this.autoBakePause = false;
}; };
@ -551,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. * Pops up a message to the user and writes it to the console log.
* *

217
src/web/BindingsWaiter.js Normal file
View 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;

View File

@ -78,10 +78,11 @@ ControlsWaiter.prototype.setAutoBake = function(value) {
* Handler to trigger baking. * Handler to trigger baking.
*/ */
ControlsWaiter.prototype.bakeClick = function() { ControlsWaiter.prototype.bakeClick = function() {
this.app.bake(); if (document.getElementById("bake").textContent.indexOf("Bake") > 0) {
const outputText = document.getElementById("output-text"); this.app.bake();
outputText.focus(); } else {
outputText.setSelectionRange(0, 0); this.manager.worker.cancelBake();
}
}; };
@ -90,9 +91,6 @@ ControlsWaiter.prototype.bakeClick = function() {
*/ */
ControlsWaiter.prototype.stepClick = function() { ControlsWaiter.prototype.stepClick = function() {
this.app.bake(true); this.app.bake(true);
const outputText = document.getElementById("output-text");
outputText.focus();
outputText.setSelectionRange(0, 0);
}; };
@ -256,6 +254,15 @@ ControlsWaiter.prototype.loadClick = function() {
* Saves the recipe specified in the save textarea to local storage. * Saves the recipe specified in the save textarea to local storage.
*/ */
ControlsWaiter.prototype.saveButtonClick = function() { 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 recipeName = Utils.escapeHtml(document.getElementById("save-name").value);
const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value; const recipeStr = document.querySelector("#save-texts .tab-pane.active textarea").value;
@ -285,6 +292,8 @@ ControlsWaiter.prototype.saveButtonClick = function() {
* Populates the list of saved recipes in the load dialog box from local storage. * Populates the list of saved recipes in the load dialog box from local storage.
*/ */
ControlsWaiter.prototype.populateLoadRecipesList = function() { ControlsWaiter.prototype.populateLoadRecipesList = function() {
if (!this.app.isLocalStorageAvailable()) return false;
const loadNameEl = document.getElementById("load-name"); const loadNameEl = document.getElementById("load-name");
// Remove current recipes from select // Remove current recipes from select
@ -315,6 +324,8 @@ ControlsWaiter.prototype.populateLoadRecipesList = function() {
* Removes the currently selected recipe from local storage. * Removes the currently selected recipe from local storage.
*/ */
ControlsWaiter.prototype.loadDeleteClick = function() { ControlsWaiter.prototype.loadDeleteClick = function() {
if (!this.app.isLocalStorageAvailable()) return false;
const id = parseInt(document.getElementById("load-name").value, 10); const id = parseInt(document.getElementById("load-name").value, 10);
const rawSavedRecipes = localStorage.savedRecipes ? const rawSavedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : []; JSON.parse(localStorage.savedRecipes) : [];
@ -330,6 +341,8 @@ ControlsWaiter.prototype.loadDeleteClick = function() {
* Displays the selected recipe in the load text box. * Displays the selected recipe in the load text box.
*/ */
ControlsWaiter.prototype.loadNameChange = function(e) { ControlsWaiter.prototype.loadNameChange = function(e) {
if (!this.app.isLocalStorageAvailable()) return false;
const el = e.target; const el = e.target;
const savedRecipes = localStorage.savedRecipes ? const savedRecipes = localStorage.savedRecipes ?
JSON.parse(localStorage.savedRecipes) : []; JSON.parse(localStorage.savedRecipes) : [];
@ -348,6 +361,7 @@ ControlsWaiter.prototype.loadButtonClick = function() {
try { try {
const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value); const recipeConfig = Utils.parseRecipeConfig(document.getElementById("load-text").value);
this.app.setRecipeConfig(recipeConfig); this.app.setRecipeConfig(recipeConfig);
this.app.autoBake();
$("#rec-list [data-toggle=popover]").popover(); $("#rec-list [data-toggle=popover]").popover();
} catch (e) { } catch (e) {
@ -375,4 +389,49 @@ ControlsWaiter.prototype.supportButtonClick = function(e) {
} }
}; };
/**
* Shows the stale indicator to show that the input or recipe has changed
* since the last bake.
*/
ControlsWaiter.prototype.showStaleIndicator = function() {
const staleIndicator = document.getElementById("stale-indicator");
staleIndicator.style.visibility = "visible";
staleIndicator.style.opacity = 1;
};
/**
* Hides the stale indicator to show that the input or recipe has not changed
* since the last bake.
*/
ControlsWaiter.prototype.hideStaleIndicator = function() {
const staleIndicator = document.getElementById("stale-indicator");
staleIndicator.style.opacity = 0;
staleIndicator.style.visibility = "hidden";
};
/**
* Switches the Bake button between 'Bake' and 'Cancel' functions.
*
* @param {boolean} cancel - Whether to change to cancel or not
*/
ControlsWaiter.prototype.toggleBakeButtonFunction = function(cancel) {
const bakeButton = document.getElementById("bake"),
btnText = bakeButton.querySelector("span");
if (cancel) {
btnText.innerText = "Cancel";
bakeButton.classList.remove("btn-success");
bakeButton.classList.add("btn-danger");
} else {
btnText.innerText = "Bake!";
bakeButton.classList.remove("btn-danger");
bakeButton.classList.add("btn-success");
}
};
export default ControlsWaiter; export default ControlsWaiter;

View File

@ -10,9 +10,11 @@ import Utils from "../core/Utils.js";
* *
* @constructor * @constructor
* @param {App} app - The main view object for CyberChef. * @param {App} app - The main view object for CyberChef.
* @param {Manager} manager - The CyberChef event manager.
*/ */
const HighlighterWaiter = function(app) { const HighlighterWaiter = function(app, manager) {
this.app = app; this.app = app;
this.manager = manager;
this.mouseButtonDown = false; this.mouseButtonDown = false;
this.mouseTarget = null; this.mouseTarget = null;
@ -329,41 +331,6 @@ HighlighterWaiter.prototype.removeHighlights = function() {
}; };
/**
* Generates a list of all the highlight functions assigned to operations in the recipe, if the
* entire recipe supports highlighting.
*
* @returns {Object[]} highlights
* @returns {function} highlights[].f
* @returns {function} highlights[].b
* @returns {Object[]} highlights[].args
*/
HighlighterWaiter.prototype.generateHighlightList = function() {
const recipeConfig = this.app.getRecipeConfig();
const highlights = [];
for (let i = 0; i < recipeConfig.length; i++) {
if (recipeConfig[i].disabled) continue;
// If any breakpoints are set, do not attempt to highlight
if (recipeConfig[i].breakpoint) return false;
const op = this.app.operations[recipeConfig[i].op];
// If any of the operations do not support highlighting, fail immediately.
if (op.highlight === false || op.highlight === undefined) return false;
highlights.push({
f: op.highlight,
b: op.highlightReverse,
args: recipeConfig[i].args
});
}
return highlights;
};
/** /**
* Highlights the given offsets in the output. * Highlights the given offsets in the output.
* We will only highlight if: * We will only highlight if:
@ -376,26 +343,8 @@ HighlighterWaiter.prototype.generateHighlightList = function() {
* @param {number} pos.end - The end offset. * @param {number} pos.end - The end offset.
*/ */
HighlighterWaiter.prototype.highlightOutput = function(pos) { HighlighterWaiter.prototype.highlightOutput = function(pos) {
const highlights = this.generateHighlightList(); if (!this.app.autoBake_ || this.app.baking) return false;
this.manager.worker.highlight(this.app.getRecipeConfig(), "forward", pos);
if (!highlights || !this.app.autoBake_) {
return false;
}
for (let i = 0; i < highlights.length; i++) {
// Remove multiple highlights before processing again
pos = [pos[0]];
if (typeof highlights[i].f == "function") {
pos = highlights[i].f(pos, highlights[i].args);
}
}
document.getElementById("output-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
this.highlight(
document.getElementById("output-text"),
document.getElementById("output-highlighter"),
pos);
}; };
@ -411,25 +360,28 @@ HighlighterWaiter.prototype.highlightOutput = function(pos) {
* @param {number} pos.end - The end offset. * @param {number} pos.end - The end offset.
*/ */
HighlighterWaiter.prototype.highlightInput = function(pos) { HighlighterWaiter.prototype.highlightInput = function(pos) {
const highlights = this.generateHighlightList(); if (!this.app.autoBake_ || this.app.baking) return false;
this.manager.worker.highlight(this.app.getRecipeConfig(), "reverse", pos);
};
if (!highlights || !this.app.autoBake_) {
return false;
}
for (let i = 0; i < highlights.length; i++) { /**
// Remove multiple highlights before processing again * Displays highlight offsets sent back from the Chef.
pos = [pos[0]]; *
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
* @param {string} direction
*/
HighlighterWaiter.prototype.displayHighlights = function(pos, direction) {
if (!pos) return;
if (typeof highlights[i].b == "function") { const io = direction === "forward" ? "output" : "input";
pos = highlights[i].b(pos, highlights[i].args);
}
}
document.getElementById("input-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end); document.getElementById(io + "-selection-info").innerHTML = this.selectionInfo(pos[0].start, pos[0].end);
this.highlight( this.highlight(
document.getElementById("input-text"), document.getElementById(io + "-text"),
document.getElementById("input-highlighter"), document.getElementById(io + "-highlighter"),
pos); pos);
}; };

View File

@ -158,18 +158,14 @@ InputWaiter.prototype.inputDrop = function(e) {
const CHUNK_SIZE = 20480; // 20KB const CHUNK_SIZE = 20480; // 20KB
const setInput = function() { const setInput = function() {
if (inputCharcode.length > 100000 && this.app.autoBake_) {
this.manager.controls.setAutoBake(false);
this.app.alert("Turned off Auto Bake as the input is large", "warning", 5000);
}
this.set(inputCharcode);
const recipeConfig = this.app.getRecipeConfig(); const recipeConfig = this.app.getRecipeConfig();
if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") { if (!recipeConfig[0] || recipeConfig[0].op !== "From Hex") {
recipeConfig.unshift({op: "From Hex", args: ["Space"]}); recipeConfig.unshift({op: "From Hex", args: ["Space"]});
this.app.setRecipeConfig(recipeConfig); this.app.setRecipeConfig(recipeConfig);
} }
this.set(inputCharcode);
el.classList.remove("loadingFile"); el.classList.remove("loadingFile");
}.bind(this); }.bind(this);

View File

@ -1,3 +1,4 @@
import WorkerWaiter from "./WorkerWaiter.js";
import WindowWaiter from "./WindowWaiter.js"; import WindowWaiter from "./WindowWaiter.js";
import ControlsWaiter from "./ControlsWaiter.js"; import ControlsWaiter from "./ControlsWaiter.js";
import RecipeWaiter from "./RecipeWaiter.js"; import RecipeWaiter from "./RecipeWaiter.js";
@ -7,6 +8,7 @@ import OutputWaiter from "./OutputWaiter.js";
import OptionsWaiter from "./OptionsWaiter.js"; import OptionsWaiter from "./OptionsWaiter.js";
import HighlighterWaiter from "./HighlighterWaiter.js"; import HighlighterWaiter from "./HighlighterWaiter.js";
import SeasonalWaiter from "./SeasonalWaiter.js"; import SeasonalWaiter from "./SeasonalWaiter.js";
import BindingsWaiter from "./BindingsWaiter.js";
/** /**
@ -49,6 +51,7 @@ const Manager = function(app) {
this.statechange = new CustomEvent("statechange", {bubbles: true}); this.statechange = new CustomEvent("statechange", {bubbles: true});
// Define Waiter objects to handle various areas // Define Waiter objects to handle various areas
this.worker = new WorkerWaiter(this.app, this);
this.window = new WindowWaiter(this.app); this.window = new WindowWaiter(this.app);
this.controls = new ControlsWaiter(this.app, this); this.controls = new ControlsWaiter(this.app, this);
this.recipe = new RecipeWaiter(this.app, this); this.recipe = new RecipeWaiter(this.app, this);
@ -56,8 +59,9 @@ const Manager = function(app) {
this.input = new InputWaiter(this.app, this); this.input = new InputWaiter(this.app, this);
this.output = new OutputWaiter(this.app, this); this.output = new OutputWaiter(this.app, this);
this.options = new OptionsWaiter(this.app); this.options = new OptionsWaiter(this.app);
this.highlighter = new HighlighterWaiter(this.app); this.highlighter = new HighlighterWaiter(this.app, this);
this.seasonal = new SeasonalWaiter(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 // Object to store dynamic handlers to fire on elements that may not exist yet
this.dynamicHandlers = {}; this.dynamicHandlers = {};
@ -70,8 +74,10 @@ const Manager = function(app) {
* Sets up the various components and listeners. * Sets up the various components and listeners.
*/ */
Manager.prototype.setup = function() { Manager.prototype.setup = function() {
this.worker.registerChefWorker();
this.recipe.initialiseOperationDragNDrop(); this.recipe.initialiseOperationDragNDrop();
this.controls.autoBakeChange(); this.controls.autoBakeChange();
this.bindings.updateKeybList();
this.seasonal.load(); this.seasonal.load();
}; };
@ -116,8 +122,8 @@ Manager.prototype.initialiseEventListeners = function() {
this.addDynamicListener("li.operation", "operationadd", this.recipe.opAdd.bind(this.recipe)); this.addDynamicListener("li.operation", "operationadd", this.recipe.opAdd.bind(this.recipe));
// Recipe // Recipe
this.addDynamicListener(".arg", "keyup", this.recipe.ingChange, this.recipe); this.addDynamicListener(".arg:not(select)", "input", this.recipe.ingChange, this.recipe);
this.addDynamicListener(".arg", "change", 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(".disable-icon", "click", this.recipe.disableClick, this.recipe);
this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe); this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe);
this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe); this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe);
@ -139,6 +145,7 @@ Manager.prototype.initialiseEventListeners = function() {
// Output // Output
document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.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("switch").addEventListener("click", this.output.switchClick.bind(this.output));
document.getElementById("undo-switch").addEventListener("click", this.output.undoSwitchClick.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)); document.getElementById("maximise-output").addEventListener("click", this.output.maximiseOutputClick.bind(this.output));
@ -156,12 +163,14 @@ Manager.prototype.initialiseEventListeners = function() {
document.getElementById("reset-options").addEventListener("click", this.options.resetOptionsClick.bind(this.options)); 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.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", 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]", "keyup", this.options.numberChange, this.options);
this.addDynamicListener(".option-item input[type=number]", "change", 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); this.addDynamicListener(".option-item select", "change", this.options.selectChange, this.options);
document.getElementById("theme").addEventListener("change", this.options.themeChange.bind(this.options)); document.getElementById("theme").addEventListener("change", this.options.themeChange.bind(this.options));
// Misc // Misc
window.addEventListener("keydown", this.bindings.parseInput.bind(this.bindings));
document.getElementById("alert-close").addEventListener("click", this.app.alertCloseClick.bind(this.app)); document.getElementById("alert-close").addEventListener("click", this.app.alertCloseClick.bind(this.app));
}; };

View File

@ -38,7 +38,6 @@ OperationsWaiter.prototype.searchOperations = function(e) {
selected = this.getSelectedOp(ops); selected = this.getSelectedOp(ops);
if (selected > -1) { if (selected > -1) {
this.manager.recipe.addOperation(ops[selected].innerHTML); this.manager.recipe.addOperation(ops[selected].innerHTML);
this.app.autoBake();
} }
} }
} }
@ -197,7 +196,6 @@ OperationsWaiter.prototype.operationDblclick = function(e) {
const li = e.target; const li = e.target;
this.manager.recipe.addOperation(li.textContent); this.manager.recipe.addOperation(li.textContent);
this.app.autoBake();
}; };
@ -231,7 +229,7 @@ OperationsWaiter.prototype.editFavouritesClick = function(e) {
filter: ".remove-icon", filter: ".remove-icon",
onFilter: function (evt) { onFilter: function (evt) {
const el = editableList.closest(evt.item); const el = editableList.closest(evt.item);
if (el) { if (el && el.parentNode) {
$(el).popover("destroy"); $(el).popover("destroy");
el.parentNode.removeChild(el); el.parentNode.removeChild(el);
} }

View File

@ -87,7 +87,9 @@ OptionsWaiter.prototype.switchChange = function(e, state) {
const option = el.getAttribute("option"); const option = el.getAttribute("option");
this.app.options[option] = state; 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"); const option = el.getAttribute("option");
this.app.options[option] = parseInt(el.value, 10); 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"); const option = el.getAttribute("option");
this.app.options[option] = el.value; 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));
}; };

View File

@ -105,17 +105,20 @@ OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) {
OutputWaiter.prototype.adjustWidth = function() { OutputWaiter.prototype.adjustWidth = function() {
const output = document.getElementById("output"); const output = document.getElementById("output");
const saveToFile = document.getElementById("save-to-file"); const saveToFile = document.getElementById("save-to-file");
const copyOutput = document.getElementById("copy-output");
const switchIO = document.getElementById("switch"); const switchIO = document.getElementById("switch");
const undoSwitch = document.getElementById("undo-switch"); const undoSwitch = document.getElementById("undo-switch");
const maximiseOutput = document.getElementById("maximise-output"); const maximiseOutput = document.getElementById("maximise-output");
if (output.clientWidth < 680) { if (output.clientWidth < 680) {
saveToFile.childNodes[1].nodeValue = ""; saveToFile.childNodes[1].nodeValue = "";
copyOutput.childNodes[1].nodeValue = "";
switchIO.childNodes[1].nodeValue = ""; switchIO.childNodes[1].nodeValue = "";
undoSwitch.childNodes[1].nodeValue = ""; undoSwitch.childNodes[1].nodeValue = "";
maximiseOutput.childNodes[1].nodeValue = ""; maximiseOutput.childNodes[1].nodeValue = "";
} else { } else {
saveToFile.childNodes[1].nodeValue = " Save to file"; saveToFile.childNodes[1].nodeValue = " Save to file";
copyOutput.childNodes[1].nodeValue = " Copy output";
switchIO.childNodes[1].nodeValue = " Move output to input"; switchIO.childNodes[1].nodeValue = " Move output to input";
undoSwitch.childNodes[1].nodeValue = " Undo"; undoSwitch.childNodes[1].nodeValue = " Undo";
maximiseOutput.childNodes[1].nodeValue = 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. * Handler for switch click events.
* Moves the current output into the input textarea. * Moves the current output into the input textarea.
@ -201,4 +242,44 @@ OutputWaiter.prototype.maximiseOutputClick = function(e) {
} }
}; };
/**
* Shows or hides the loading icon.
*
* @param {boolean} value
*/
OutputWaiter.prototype.toggleLoader = function(value) {
const outputLoader = document.getElementById("output-loader"),
outputElement = document.getElementById("output-text");
if (value) {
this.manager.controls.hideStaleIndicator();
this.bakingStatusTimeout = setTimeout(function() {
outputElement.disabled = true;
outputLoader.style.visibility = "visible";
outputLoader.style.opacity = 1;
this.manager.controls.toggleBakeButtonFunction(true);
}.bind(this), 200);
} else {
clearTimeout(this.bakingStatusTimeout);
outputElement.disabled = false;
outputLoader.style.opacity = 0;
outputLoader.style.visibility = "hidden";
this.manager.controls.toggleBakeButtonFunction(false);
this.setStatusMsg("");
}
};
/**
* Sets the baking status message value.
*
* @param {string} msg
*/
OutputWaiter.prototype.setStatusMsg = function(msg) {
const el = document.querySelector("#output-loader .loading-msg");
el.textContent = msg;
};
export default OutputWaiter; export default OutputWaiter;

View File

@ -1,5 +1,6 @@
import HTMLOperation from "./HTMLOperation.js"; import HTMLOperation from "./HTMLOperation.js";
import Sortable from "sortablejs"; import Sortable from "sortablejs";
import Utils from "../core/Utils.js";
/** /**
@ -191,7 +192,7 @@ RecipeWaiter.prototype.favDrop = function(e) {
* *
* @fires Manager#statechange * @fires Manager#statechange
*/ */
RecipeWaiter.prototype.ingChange = function() { RecipeWaiter.prototype.ingChange = function(e) {
window.dispatchEvent(this.manager.statechange); window.dispatchEvent(this.manager.statechange);
}; };
@ -435,4 +436,30 @@ RecipeWaiter.prototype.opRemove = function(e) {
window.dispatchEvent(this.manager.statechange); 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; export default RecipeWaiter;

183
src/web/WorkerWaiter.js Normal file
View File

@ -0,0 +1,183 @@
import Utils from "../core/Utils.js";
import ChefWorker from "worker-loader?inline&fallback=false!../core/ChefWorker.js";
/**
* Waiter to handle conversations with the ChefWorker.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017
* @license Apache-2.0
*
* @constructor
* @param {App} app - The main view object for CyberChef.
* @param {Manager} manager - The CyberChef event manager.
*/
const WorkerWaiter = function(app, manager) {
this.app = app;
this.manager = manager;
};
/**
* Sets up the ChefWorker and associated listeners.
*/
WorkerWaiter.prototype.registerChefWorker = function() {
this.chefWorker = new ChefWorker();
this.chefWorker.addEventListener("message", this.handleChefMessage.bind(this));
let docURL = document.location.href.split(/[#?]/)[0];
const index = docURL.lastIndexOf("/");
if (index > 0) {
docURL = docURL.substring(0, index);
}
this.chefWorker.postMessage({"action": "docURL", "data": docURL});
};
/**
* Handler for messages sent back by the ChefWorker.
*
* @param {MessageEvent} e
*/
WorkerWaiter.prototype.handleChefMessage = function(e) {
const r = e.data;
switch (r.action) {
case "bakeSuccess":
this.bakingComplete(r.data);
break;
case "bakeError":
this.app.handleError(r.data);
this.setBakingStatus(false);
break;
case "silentBakeComplete":
break;
case "workerLoaded":
this.app.workerLoaded = true;
this.app.loaded();
break;
case "statusMessage":
this.manager.output.setStatusMsg(r.data);
break;
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;
default:
console.error("Unrecognised message from ChefWorker", e);
break;
}
};
/**
* Updates the UI to show if baking is in process or not.
*
* @param {bakingStatus}
*/
WorkerWaiter.prototype.setBakingStatus = function(bakingStatus) {
this.app.baking = bakingStatus;
this.manager.output.toggleLoader(bakingStatus);
};
/**
* Cancels the current bake by terminating the ChefWorker and creating a new one.
*/
WorkerWaiter.prototype.cancelBake = function() {
this.chefWorker.terminate();
this.registerChefWorker();
this.setBakingStatus(false);
this.manager.controls.showStaleIndicator();
};
/**
* Handler for completed bakes.
*
* @param {Object} response
*/
WorkerWaiter.prototype.bakingComplete = function(response) {
this.setBakingStatus(false);
if (!response) return;
if (response.error) {
this.app.handleError(response.error);
}
this.app.dishStr = response.type === "html" ? Utils.stripHtmlTags(response.result, true) : response.result;
this.app.progress = response.progress;
this.manager.recipe.updateBreakpointIndicator(response.progress);
this.manager.output.set(response.result, response.type, response.duration);
};
/**
* Asks the ChefWorker to bake the current input using the current recipe.
*
* @param {string} input
* @param {Object[]} recipeConfig
* @param {Object} options
* @param {number} progress
* @param {boolean} step
*/
WorkerWaiter.prototype.bake = function(input, recipeConfig, options, progress, step) {
this.setBakingStatus(true);
this.chefWorker.postMessage({
action: "bake",
data: {
input: input,
recipeConfig: recipeConfig,
options: options,
progress: progress,
step: step
}
});
};
/**
* Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant
* JavaScript code needed to do a real bake.
*
* @param {Objectp[]} [recipeConfig]
*/
WorkerWaiter.prototype.silentBake = function(recipeConfig) {
this.chefWorker.postMessage({
action: "silentBake",
data: {
recipeConfig: recipeConfig
}
});
};
/**
* Asks the ChefWorker to calculate highlight offsets if possible.
*
* @param {Object[]} recipeConfig
* @param {string} direction
* @param {Object} pos - The position object for the highlight.
* @param {number} pos.start - The start offset.
* @param {number} pos.end - The end offset.
*/
WorkerWaiter.prototype.highlight = function(recipeConfig, direction, pos) {
this.chefWorker.postMessage({
action: "highlight",
data: {
recipeConfig: recipeConfig,
direction: direction,
pos: pos
}
});
};
export default WorkerWaiter;

View File

@ -1,17 +1,17 @@
<!-- htmlmin:ignore --><!-- <!-- htmlmin:ignore --><!--
CyberChef - The Cyber Swiss Army Knife CyberChef - The Cyber Swiss Army Knife
@copyright Crown Copyright 2016 @copyright Crown Copyright 2016
@license Apache-2.0 @license Apache-2.0
Copyright 2016 Crown Copyright Copyright 2016 Crown Copyright
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -24,7 +24,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>CyberChef</title> <title>CyberChef</title>
<meta name="copyright" content="Crown Copyright 2016" /> <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="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" /> <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" />
@ -36,8 +36,10 @@
// Load theme before the preloader is shown // Load theme before the preloader is shown
try { try {
document.querySelector(":root").className = JSON.parse(localStorage.getItem("options")).theme; document.querySelector(":root").className = (JSON.parse(localStorage.getItem("options")) || {}).theme;
} catch (e) {} } catch (err) {
// LocalStorage access is denied by security settings
}
// Define loading messages // Define loading messages
const loadingMsgs = [ const loadingMsgs = [
@ -73,7 +75,8 @@
loadingMsgs.push(msg); loadingMsgs.push(msg);
try { try {
const el = document.getElementById("preloader-msg"); const el = document.getElementById("preloader-msg");
el.className = "loading"; // Causes CSS transition on first message if (!el.classList.contains("loading"))
el.classList.add("loading"); // Causes CSS transition on first message
el.innerHTML = msg; el.innerHTML = msg;
} catch (err) {} // Ignore errors if DOM not yet ready } catch (err) {} // Ignore errors if DOM not yet ready
} }
@ -90,8 +93,8 @@
<body> <body>
<!-- Preloader overlay --> <!-- Preloader overlay -->
<div id="loader-wrapper"> <div id="loader-wrapper">
<div id="preloader"></div> <div id="preloader" class="loader"></div>
<div id="preloader-msg"></div> <div id="preloader-msg" class="loading-msg"></div>
</div> </div>
<!-- End preloader overlay --> <!-- End preloader overlay -->
<span id="edit-favourites" class="btn btn-default btn-sm"><img aria-hidden="true" src="<%- require('../static/images/favourite-16x16.png') %>" alt="Star Icon"/> Edit</span> <span id="edit-favourites" class="btn btn-default btn-sm"><img aria-hidden="true" src="<%- require('../static/images/favourite-16x16.png') %>" alt="Star Icon"/> Edit</span>
@ -132,30 +135,30 @@
<ul id="search-results" class="op-list"></ul> <ul id="search-results" class="op-list"></ul>
<div id="categories" class="panel-group no-select"></div> <div id="categories" class="panel-group no-select"></div>
</div> </div>
<div id="recipe" class="split split-horizontal no-select"> <div id="recipe" class="split split-horizontal no-select">
<div class="title no-select">Recipe</div> <div class="title no-select">Recipe</div>
<ul id="rec-list" class="list-area no-select"></ul> <ul id="rec-list" class="list-area no-select"></ul>
<div id="controls" class="no-select"> <div id="controls" class="no-select">
<div id="operational-controls"> <div id="operational-controls">
<div id="bake-group"> <div id="bake-group">
<button type="button" class="btn btn-success btn-lg" id="bake"> <button type="button" class="btn btn-success btn-lg" id="bake">
<img aria-hidden="true" src="<%- require('../static/images/cook_male-32x32.png') %>" alt="Chef Icon"/> <img aria-hidden="true" src="<%- require('../static/images/cook_male-32x32.png') %>" alt="Chef Icon"/>
Bake! <span>Bake!</span>
</button> </button>
<label class="btn btn-success btn-lg" id="auto-bake-label" for="auto-bake"> <label class="btn btn-success btn-lg" id="auto-bake-label" for="auto-bake">
<input type="checkbox" checked="checked" id="auto-bake"> <input type="checkbox" checked="checked" id="auto-bake">
<div>Auto Bake</div> <div>Auto Bake</div>
</label> </label>
</div> </div>
<div class="btn-group" style="padding-top: 10px;"> <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="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> <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> </div>
<div class="btn-group-vertical" id="extra-controls"> <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="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> <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>
@ -163,12 +166,11 @@
</div> </div>
</div> </div>
</div> </div>
<div class="split split-horizontal" id="IO"> <div class="split split-horizontal" id="IO">
<div id="input" class="split no-select"> <div id="input" class="split no-select">
<div class="title no-select"> <div class="title no-select">
<label for="input-text">Input</label> <label for="input-text">Input</label>
<div class="loading-icon" style="display: none"></div>
<div class="btn-group io-btn-group"> <div class="btn-group io-btn-group">
<button type="button" class="btn btn-default btn-sm" id="clr-io"><img aria-hidden="true" src="<%- require('../static/images/recycle-16x16.png') %>" alt="Recycle Icon"/> Clear I/O</button> <button type="button" class="btn btn-default btn-sm" id="clr-io"><img aria-hidden="true" src="<%- require('../static/images/recycle-16x16.png') %>" alt="Recycle Icon"/> Clear I/O</button>
<button type="button" class="btn btn-default btn-sm" id="reset-layout"><img aria-hidden="true" src="<%- require('../static/images/layout-16x16.png') %>" alt="Grid Icon"/> Reset layout</button> <button type="button" class="btn btn-default btn-sm" id="reset-layout"><img aria-hidden="true" src="<%- require('../static/images/layout-16x16.png') %>" alt="Grid Icon"/> Reset layout</button>
@ -181,30 +183,35 @@
<textarea id="input-text"></textarea> <textarea id="input-text"></textarea>
</div> </div>
</div> </div>
<div id="output" class="split"> <div id="output" class="split">
<div class="title no-select"> <div class="title no-select">
<label for="output-text">Output</label> <label for="output-text">Output</label>
<div class="loading-icon" style="display: none"></div>
<div class="btn-group io-btn-group"> <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="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="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="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> <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>
</div> </div>
<div class="io-info" id="output-info"></div> <div class="io-info" id="output-info"></div>
<div class="io-info" id="output-selection-info"></div> <div class="io-info" id="output-selection-info"></div>
<span id="stale-indicator" title="The output is stale.&#10;The input or recipe has changed since this output was generated. Bake again to get the new value.">&#x1F551;</span>
</div> </div>
<div class="textarea-wrapper"> <div class="textarea-wrapper">
<div id="output-highlighter" class="no-select"></div> <div id="output-highlighter" class="no-select"></div>
<div id="output-html"></div> <div id="output-html"></div>
<textarea id="output-text" readonly="readonly"></textarea> <textarea id="output-text" readonly="readonly"></textarea>
<div id="output-loader">
<div class="loader"></div>
<div class="loading-msg"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="save-modal" tabindex="-1" role="dialog"> <div class="modal" id="save-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -255,7 +262,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="load-modal" tabindex="-1" role="dialog"> <div class="modal" id="load-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -281,7 +288,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="options-modal" tabindex="-1" role="dialog"> <div class="modal" id="options-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -320,12 +327,12 @@
<label for="showErrors"> Operation error reporting (recommended) </label> <label for="showErrors"> Operation error reporting (recommended) </label>
</div> </div>
<div class="option-item"> <div class="option-item">
<input type="number" option="errorTimeout" id="errorTimeout" /> <input type="checkbox" option="useMetaKey" id="useMetaKey" />
<label for="errorTimeout"> Operation error timeout in ms (0 for never) </label> <label for="useMetaKey"> Use meta key for keybindings (Windows ⊞/Command ⌘) </label>
</div> </div>
<div class="option-item"> <div class="option-item">
<input type="number" option="autoBakeThreshold" id="autoBakeThreshold"/> <input type="number" option="errorTimeout" id="errorTimeout" />
<label for="autoBakeThreshold"> Auto Bake threshold in ms </label> <label for="errorTimeout"> Operation error timeout in ms (0 for never) </label>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -335,7 +342,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="favourites-modal" tabindex="-1" role="dialog"> <div class="modal" id="favourites-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -362,7 +369,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="support-modal" tabindex="-1" role="dialog"> <div class="modal" id="support-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -378,6 +385,11 @@
</p> </p>
<p>&copy; Crown Copyright 2016.</p> <p>&copy; Crown Copyright 2016.</p>
<p>Released under the Apache Licence, Version 2.0.</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>
<br> <br>
<div> <div>
@ -394,6 +406,10 @@
<img aria-hidden="true" src="<%- require('../static/images/speech-16x16.png') %>" alt="Speech Balloon Icon"/> <img aria-hidden="true" src="<%- require('../static/images/speech-16x16.png') %>" alt="Speech Balloon Icon"/>
About About
</a></li> </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> </ul>
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="faqs"> <div role="tabpanel" class="tab-pane active" id="faqs">
@ -410,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=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=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=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)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',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=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> </ul>
</div> </div>
<blockquote> <blockquote>
@ -445,20 +463,20 @@
<div role="tabpanel" class="tab-pane" id="about" style="padding: 20px;"> <div role="tabpanel" class="tab-pane" id="about" style="padding: 20px;">
<h5><strong>What</strong></h5> <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> <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> <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> <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> <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>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> <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> <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> <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> <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> <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>
@ -467,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>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>Its the Cyber Swiss Army Knife.</p> <p>Its the Cyber Swiss Army Knife.</p>
</div> </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> </div>
</div> </div>
@ -479,7 +500,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal" id="confirm-modal" tabindex="-1" role="dialog"> <div class="modal" id="confirm-modal" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg"> <div class="modal-dialog modal-lg">
<div class="modal-content"> <div class="modal-content">
@ -500,6 +521,6 @@
</div> </div>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -17,7 +17,7 @@ import CanvasComponents from "../core/lib/canvascomponents.js";
// CyberChef // CyberChef
import App from "./App.js"; import App from "./App.js";
import Categories from "../core/config/Categories.js"; import Categories from "../core/config/Categories.js";
import OperationConfig from "../core/config/OperationConfig.js"; import OperationConfig from "../core/config/MetaConfig.js";
/** /**
@ -44,9 +44,9 @@ function main() {
wordWrap: true, wordWrap: true,
showErrors: true, showErrors: true,
errorTimeout: 4000, errorTimeout: 4000,
autoBakeThreshold: 200,
attemptHighlight: true, attemptHighlight: true,
theme: "classic", theme: "classic",
useMetaKey: false
}; };
document.removeEventListener("DOMContentLoaded", main, false); document.removeEventListener("DOMContentLoaded", main, false);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 233 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 773 B

After

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 702 B

After

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 796 B

After

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 419 B

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 746 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 590 B

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
src/web/static/images/fork_me.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 843 B

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 513 B

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 B

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 B

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 507 B

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 179 B

Some files were not shown because too many files have changed in this diff Show More