mirror of
https://github.com/gchq/CyberChef.git
synced 2025-05-13 09:36:52 -04:00
Functioning prototype
This commit is contained in:
parent
4762cc5442
commit
a5f071dd36
2 changed files with 168 additions and 16 deletions
|
@ -266,6 +266,7 @@
|
||||||
"Extract URLs",
|
"Extract URLs",
|
||||||
"Extract domains",
|
"Extract domains",
|
||||||
"Extract file paths",
|
"Extract file paths",
|
||||||
|
"Extract Entropies",
|
||||||
"Extract dates",
|
"Extract dates",
|
||||||
"Regular expression",
|
"Regular expression",
|
||||||
"XPath expression",
|
"XPath expression",
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Entropy from "./Entropy.mjs";
|
//import Entropy from "./Entropy.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract Entropies operation
|
* Extract Entropies operation
|
||||||
|
@ -28,37 +28,188 @@ class ExtractEntropies extends Operation {
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "Entropies",
|
name: "Entropies",
|
||||||
type: "option",
|
type: "argSelector",
|
||||||
value: ["High", "Low", "High and Low", "Value Range"]
|
value: [
|
||||||
|
{
|
||||||
|
name: "High",
|
||||||
|
off: [2, 3]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Upper bound Entropy",
|
name: "Low",
|
||||||
type: "number",
|
off: [2, 3]
|
||||||
value: ""
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Lower bound Entropy",
|
name: "Low and High",
|
||||||
|
off: [2, 3]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ascii Range",
|
||||||
|
off: [2, 3]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Enter Value Range",
|
||||||
|
on: [2, 3]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Block Size",
|
||||||
type: "number",
|
type: "number",
|
||||||
value: ""
|
value: "8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Lower Entropy Bound",
|
||||||
|
type: "number",
|
||||||
|
value: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Upper Entropy Bound",
|
||||||
|
type: "number",
|
||||||
|
value: 0
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the frequency of bytes in the input.
|
||||||
|
*
|
||||||
|
* @param {Uint8Array} input
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
calculateShannonEntropy(input) {
|
||||||
|
const prob = [],
|
||||||
|
occurrences = new Array(256).fill(0);
|
||||||
|
|
||||||
|
// Count occurrences of each byte in the input
|
||||||
|
let i;
|
||||||
|
for (i = 0; i < input.length; i++) {
|
||||||
|
occurrences[input[i]]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store probability list
|
||||||
|
for (i = 0; i < occurrences.length; i++) {
|
||||||
|
if (occurrences[i] > 0) {
|
||||||
|
prob.push(occurrences[i] / input.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate Shannon entropy
|
||||||
|
let entropy = 0,
|
||||||
|
p;
|
||||||
|
|
||||||
|
for (i = 0; i < prob.length; i++) {
|
||||||
|
p = prob[i];
|
||||||
|
entropy += p * Math.log(p) / Math.log(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -entropy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the scanning entropy of the input
|
||||||
|
*
|
||||||
|
* @param {Uint8Array} inputBytes
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
calculateScanningEntropy(inputBytes, binWidth) {
|
||||||
|
const entropyData = [];
|
||||||
|
// const binWidth = inputBytes.length < 256 ? 8 : 256;
|
||||||
|
|
||||||
|
for (let bytePos = 0; bytePos < inputBytes.length; bytePos += binWidth) {
|
||||||
|
const block = inputBytes.slice(bytePos, bytePos+binWidth);
|
||||||
|
entropyData.push(this.calculateShannonEntropy(block));
|
||||||
|
}
|
||||||
|
|
||||||
|
return { entropyData, binWidth };
|
||||||
|
}
|
||||||
|
|
||||||
|
generateAverage(entropies) {
|
||||||
|
return entropies.reduce((previous, current) => current += previous) / entropies.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAboveMean(entropies, meanEntropy) {
|
||||||
|
const result = [];
|
||||||
|
entropies.forEach((element) =>{
|
||||||
|
if (element > meanEntropy)
|
||||||
|
result.push(element - meanEntropy);
|
||||||
|
});
|
||||||
|
return this.generateAverage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
getBelowMean(entropies, meanEntropy) {
|
||||||
|
const result = [];
|
||||||
|
entropies.forEach((element) =>{
|
||||||
|
if (element < meanEntropy)
|
||||||
|
result.push(meanEntropy - element);
|
||||||
|
});
|
||||||
|
return this.generateAverage(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllAbove(entropies, highEntropy) {
|
||||||
|
const result = [];
|
||||||
|
entropies.forEach((element, index) => {
|
||||||
|
if(element > highEntropy)
|
||||||
|
result.push([element, index]);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllBelow(entropies, lowEntropy) {
|
||||||
|
const result = [];
|
||||||
|
entropies.forEach((element, index) => {
|
||||||
|
if(element < lowEntropy)
|
||||||
|
result.push([element, index]);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ArrayBuffer} input
|
* @param {ArrayBuffer} input
|
||||||
* @param {Object[]} args
|
* @param {Object[]} args
|
||||||
* @returns {List<File>}
|
* @returns {List<File>}
|
||||||
*/
|
*/
|
||||||
run(input, args) {
|
run(input, args) {
|
||||||
let entropies = new Entropy().calculateScanningEntropy(new Uint8Array(input));
|
args[1] = parseInt(args[1]);
|
||||||
let currentMin = [8, -1];
|
if (args[2] < 0)
|
||||||
entropies.entropyData.forEach((element, index) => {
|
throw new OperationError("Cannot have a lower bound entropy lower than 0");
|
||||||
if (element < currentMin[0]) {
|
if (args[3] > 8)
|
||||||
currentMin = [element, index]
|
throw new OperationError("Cannot have an upper bound entropy greater than 8");
|
||||||
}
|
if (args[1] >= input.byteLength)
|
||||||
});
|
throw new OperationError("Block size is larger than the input");
|
||||||
console.log(currentMin);
|
|
||||||
|
|
||||||
|
let highMean = 0;
|
||||||
|
let lowMean = 0;
|
||||||
|
let highResults = [];
|
||||||
|
let lowResults = [];
|
||||||
|
switch (args[0]) {
|
||||||
|
case "Ascii Range":
|
||||||
|
break;
|
||||||
|
case "Enter Value Range":
|
||||||
|
if (args[2] === args[3])
|
||||||
|
throw new OperationError("Should not have the upper bound entropy and the lower bound entropy equal to one another");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const entropies = this.calculateScanningEntropy(new Uint8Array(input), args[1]);
|
||||||
|
const meanEntropy = this.generateAverage(entropies.entropyData);
|
||||||
|
switch (args[0]) {
|
||||||
|
case "High":
|
||||||
|
highMean = this.getAboveMean(entropies.entropyData, meanEntropy);
|
||||||
|
highResults = this.getAllAbove(entropies.entropyData, meanEntropy+highMean);
|
||||||
|
break;
|
||||||
|
case "Low":
|
||||||
|
lowMean = this.getBelowMean(entropies.entropyData, meanEntropy);
|
||||||
|
lowResults = this.getAllBelow(entropies.entropyData, meanEntropy-lowMean);
|
||||||
|
console.log(lowResults);
|
||||||
|
console.log("All entropies: ", entropies);
|
||||||
|
break;
|
||||||
|
case "Low and High":
|
||||||
|
highMean = this.getAboveMean(entropies.entropyData, meanEntropy);
|
||||||
|
highResults = this.getAllAbove(entropies.entropyData, meanEntropy+highMean);
|
||||||
|
lowMean = this.getBelowMean(entropies.entropyData, meanEntropy);
|
||||||
|
lowResults = this.getAllBelow(entropies.entropyData, meanEntropy-lowMean);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue