Merge remote-tracking branch 'upstream/master' into dish-fix

This commit is contained in:
n1073645 2019-12-20 15:22:31 +00:00
commit 78d1114869
9 changed files with 321 additions and 16 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.11.14",
"version": "9.11.17",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -1,6 +1,6 @@
{
"name": "cyberchef",
"version": "9.11.14",
"version": "9.11.17",
"description": "The Cyber Swiss Army Knife for encryption, encoding, compression and data analysis.",
"author": "n1474335 <n1474335@gmail.com>",
"homepage": "https://gchq.github.io/CyberChef",

View File

@ -280,7 +280,7 @@ export const FILE_SIGNATURES = {
9: 0x0,
10: [0x0, 0x1]
},
extractor: null
extractor: extractICO
},
{
name: "Radiance High Dynamic Range image",
@ -2933,6 +2933,32 @@ export function extractBMP(bytes, offset) {
}
/**
* ICO extractor.
*
* @param {Uint8Array} bytes
* @param {number} offset
*/
export function extractICO(bytes, offset) {
const stream = new Stream(bytes.slice(offset));
// Move to number of files there are.
stream.moveTo(4);
// Read the number of files stored in the ICO
const numberFiles = stream.readInt(2, "le");
// Move forward to the last file header.
stream.moveForwardsBy(8 + ((numberFiles-1) * 16));
const fileSize = stream.readInt(4, "le");
const fileOffset = stream.readInt(4, "le");
// Move to the end of the last file.
stream.moveTo(fileOffset + fileSize);
return stream.carve();
}
/**
* WAV extractor.
*
@ -3075,15 +3101,127 @@ export function extractSQLITE(bytes, offset) {
export function extractPListXML(bytes, offset) {
const stream = new Stream(bytes.slice(offset));
// Find closing tag (</plist>)
stream.continueUntil([0x3c, 0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e]);
stream.moveForwardsBy(8);
let braceCount = 0;
// Continue to the first (<plist).
stream.continueUntil([0x3c, 0x70, 0x6c, 0x69, 0x73, 0x74]);
stream.moveForwardsBy(6);
braceCount++;
// While we have an unequal amount of braces.
while (braceCount > 0 && stream.hasMore()) {
if (stream.readInt(1) === 0x3c) {
// If we hit an <plist.
if (stream.getBytes(5).join("") === [0x70, 0x6c, 0x69, 0x73, 0x74].join("")) {
braceCount++;
} else {
stream.moveBackwardsBy(5);
}
// If we hit an </plist>.
if (stream.getBytes(7).join("") === [0x2f, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x3e].join("")) {
braceCount--;
} else {
stream.moveBackwardsBy(7);
}
}
}
stream.consumeIf(0x0a);
return stream.carve();
}
/**
* OLE2 extractor.
*
* @param {Uint8Array} bytes
* @param {number} offset
* @returns {Uint8Array}
*/
export function extractOLE2(bytes, offset) {
const stream = new Stream(bytes.slice(offset));
const entries = [
[[0x52, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x72, 0x00, 0x79], 19, "Root Entry"],
[[0x57, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x62, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x6b], 15, "Workbook"],
[[0x43, 0x00, 0x75, 0x00, 0x72, 0x00, 0x72, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x55, 0x00, 0x73, 0x00, 0x65, 0x00, 0x72], 23, "Current User"],
[[0x50, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x65, 0x00, 0x72, 0x00, 0x50, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x20, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74], 37, "PowerPoint Document"],
[[0x57, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x64, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74], 23, "WordDocument"],
[[0x44, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61], 7, "Data"],
[[0x50, 0x00, 0x69, 0x00, 0x63, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73], 15, "Pictures"],
[[0x31, 0x00, 0x54, 0x00, 0x61, 0x00, 0x62, 0x00, 0x6c, 0x00, 0x65], 11, "1Table"],
[[0x05, 0x00, 0x53, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e], 37, "SummaryInformation"],
[[0x05, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x63, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x53, 0x00, 0x75, 0x00, 0x6d, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6d, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e], 53, "DocumentSummaryInformation"],
[[0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x4f, 0x00, 0x62, 0x00, 0x6a], 13, "Comp Obj"],
[[0x01, 0x00], 2, "Entry"]
];
let endianness = "le";
// Move to endianess field.
stream.moveForwardsBy(28);
if (stream.readInt(2, endianness) === 0xfffe)
endianness = "be";
// Calculate the size of the normal sectors.
const sizeOfSector = 2 ** stream.readInt(2, endianness);
// Move to root directory offset field.
stream.moveTo(48);
// Read root directory offset.
const rootStuff = stream.readInt(4, endianness);
// Calculate root directory offset.
let total = 512 + (rootStuff * sizeOfSector);
stream.moveTo(total);
// While valid directory entries.
let found = true;
while (found) {
found = false;
// Attempt to determine what directory entry it is.
for (const element of entries) {
// If the byte pattern matches.
if (stream.getBytes(element[1]).join("") === element[0].join("")) {
stream.moveBackwardsBy(element[1]);
found = true;
// Move forwards by the size of the comp obj.
if (element[2] === "Comp Obj") {
// The size of the Comp Obj entry - 128. Since we add 128 later.
total += 128 * 6;
stream.moveTo(total);
} else if (element[2] === "Entry") {
// If there is an entry move backwards by 126 to then move forwards by 128. Hence a total displacement of 2.
stream.moveBackwardsBy(126);
}
break;
}
stream.moveBackwardsBy(element[1]);
}
// If we have found a valid entry, move forwards by 128.
if (found) {
// Every entry is at least 128 in size, some are bigger which is dealt with by the above if statement.
total += 128;
stream.moveForwardsBy(128);
}
}
// Round up to a multiple of 512.
total = Math.ceil(total / 512) * 512;
stream.moveTo(total);
return stream.carve();
}
/**
* GZIP extractor.
*

View File

@ -5,9 +5,9 @@
*/
import Operation from "../Operation.mjs";
import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js";
import gunzip from "zlibjs/bin/gunzip.min.js";
const Zlib = zlibAndGzip.Zlib;
const Zlib = gunzip.Zlib;
/**
* Gunzip operation
@ -42,8 +42,8 @@ class Gunzip extends Operation {
* @returns {File}
*/
run(input, args) {
const gunzip = new Zlib.Gunzip(new Uint8Array(input));
return new Uint8Array(gunzip.decompress()).buffer;
const gzipObj = new Zlib.Gunzip(new Uint8Array(input));
return new Uint8Array(gzipObj.decompress()).buffer;
}
}

View File

@ -6,9 +6,9 @@
import Operation from "../Operation.mjs";
import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib.mjs";
import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js";
import gzip from "zlibjs/bin/gzip.min.js";
const Zlib = zlibAndGzip.Zlib;
const Zlib = gzip.Zlib;
/**
* Gzip operation
@ -73,12 +73,15 @@ class Gzip extends Operation {
options.filename = filename;
}
if (comment.length) {
options.flags.fcommenct = true;
options.flags.comment = true;
options.comment = comment;
}
const gzip = new Zlib.Gzip(new Uint8Array(input), options);
return new Uint8Array(gzip.compress()).buffer;
const gzipObj = new Zlib.Gzip(new Uint8Array(input), options);
const compressed = new Uint8Array(gzipObj.compress());
if (options.flags.comment && !(compressed[3] & 0x10)) {
compressed[3] |= 0x10;
}
return compressed.buffer;
}
}

View File

@ -51,6 +51,7 @@ class RecipeWaiter {
}
}.bind(this),
onSort: function(evt) {
this.updateZIndices();
if (evt.from.id === "rec-list") {
document.dispatchEvent(this.manager.statechange);
}
@ -149,6 +150,19 @@ class RecipeWaiter {
}
/**
* Sets the z-index property on each operation to make sure that operations higher in the list
* have a higher index, meaning dropdowns are not hidden underneath subsequent operations.
*/
updateZIndices() {
const operations = document.getElementById("rec-list").children;
for (let i = 0; i < operations.length; i++) {
const operation = operations[i];
operation.style.zIndex = 100 + operations.length - i;
}
}
/**
* Handler for favourite dragover events.
* If the element being dragged is an operation, displays a visual cue so that the user knows it can
@ -466,6 +480,7 @@ class RecipeWaiter {
log.debug(`'${e.target.querySelector(".op-title").textContent}' added to recipe`);
this.triggerArgEvents(e.target);
this.updateZIndices();
window.dispatchEvent(this.manager.statechange);
}

View File

@ -41,6 +41,8 @@ import "./tests/DateTime.mjs";
import "./tests/ExtractEmailAddresses.mjs";
import "./tests/Fork.mjs";
import "./tests/FromDecimal.mjs";
import "./tests/Gzip.mjs";
import "./tests/Gunzip.mjs";
import "./tests/Hash.mjs";
import "./tests/HaversineDistance.mjs";
import "./tests/Hexdump.mjs";

View File

@ -0,0 +1,58 @@
/**
* Gunzip Tests.
*
* @author n1073645 [n1073645@gmail.com]
*
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Gunzip: No comment, no checksum and no filename",
input: "1f8b0800f7c8f85d00ff0dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
expectedOutput: "The quick brown fox jumped over the slow dog",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Gunzip",
args: []
}
]
},
{
name: "Gunzip: No comment, no checksum and filename",
input: "1f8b080843c9f85d00ff66696c656e616d65000dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
expectedOutput: "The quick brown fox jumped over the slow dog",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Gunzip",
args: []
}
]
},
{
name: "Gunzip: Has a comment, no checksum and has a filename",
input: "1f8b08186fc9f85d00ff66696c656e616d6500636f6d6d656e74000dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
expectedOutput: "The quick brown fox jumped over the slow dog",
recipeConfig: [
{
op: "From Hex",
args: ["None"]
},
{
op: "Gunzip",
args: []
}
]
}
]);

View File

@ -0,0 +1,89 @@
/**
* Gzip Tests.
*
* @author n1073645 [n1073645@gmail.com]
*
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
TestRegister.addTests([
{
name: "Gzip: No comment, no checksum and no filename",
input: "The quick brown fox jumped over the slow dog",
expectedOutput: "0dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
recipeConfig: [
{
op: "Gzip",
args: ["Dynamic Huffman Coding", "", "", false]
},
{
op: "Drop bytes",
args: [0, 10, false]
},
{
op: "To Hex",
args: ["None"]
}
]
},
{
name: "Gzip: No comment, no checksum and has a filename",
input: "The quick brown fox jumped over the slow dog",
expectedOutput: "636f6d6d656e74000dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
recipeConfig: [
{
op: "Gzip",
args: ["Dynamic Huffman Coding", "comment", "", false]
},
{
op: "Drop bytes",
args: [0, 10, false]
},
{
op: "To Hex",
args: ["None"]
}
]
},
{
name: "Gzip: Has a comment, no checksum and no filename",
input: "The quick brown fox jumped over the slow dog",
expectedOutput: "636f6d6d656e74000dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
recipeConfig: [
{
op: "Gzip",
args: ["Dynamic Huffman Coding", "", "comment", false]
},
{
op: "Drop bytes",
args: [0, 10, false]
},
{
op: "To Hex",
args: ["None"]
}
]
},
{
name: "Gzip: Has a comment, no checksum and has a filename",
input: "The quick brown fox jumped over the slow dog",
expectedOutput: "66696c656e616d6500636f6d6d656e74000dc9dd0180200804e0556ea8262848fb3dc588c6a7e76faa8aeedb726036c68d951f76bf9a0af8aae1f97d9c0c084b02509cbf8c2c000000",
recipeConfig: [
{
op: "Gzip",
args: ["Dynamic Huffman Coding", "filename", "comment", false]
},
{
op: "Drop bytes",
args: [0, 10, false]
},
{
op: "To Hex",
args: ["None"]
}
]
},
]);