mirror of
https://github.com/gchq/CyberChef.git
synced 2024-09-06 11:41:35 +02:00
202 lines
5.7 KiB
JavaScript
Executable File
202 lines
5.7 KiB
JavaScript
Executable File
import Utils from "../Utils.js";
|
|
|
|
|
|
/**
|
|
* Hexdump operations.
|
|
*
|
|
* @author n1474335 [n1474335@gmail.com]
|
|
* @copyright Crown Copyright 2016
|
|
* @license Apache-2.0
|
|
*
|
|
* @namespace
|
|
*/
|
|
const Hexdump = {
|
|
|
|
/**
|
|
* @constant
|
|
* @default
|
|
*/
|
|
WIDTH: 16,
|
|
/**
|
|
* @constant
|
|
* @default
|
|
*/
|
|
UPPER_CASE: false,
|
|
/**
|
|
* @constant
|
|
* @default
|
|
*/
|
|
INCLUDE_FINAL_LENGTH: false,
|
|
|
|
/**
|
|
* To Hexdump operation.
|
|
*
|
|
* @param {byteArray} input
|
|
* @param {Object[]} args
|
|
* @returns {string}
|
|
*/
|
|
runTo: function(input, args) {
|
|
const length = args[0] || Hexdump.WIDTH;
|
|
const upperCase = args[1];
|
|
const includeFinalLength = args[2];
|
|
|
|
let output = "", padding = 2;
|
|
for (let i = 0; i < input.length; i += length) {
|
|
const buff = input.slice(i, i+length);
|
|
let hexa = "";
|
|
for (let j = 0; j < buff.length; j++) {
|
|
hexa += Utils.hex(buff[j], padding) + " ";
|
|
}
|
|
|
|
let lineNo = Utils.hex(i, 8);
|
|
|
|
if (upperCase) {
|
|
hexa = hexa.toUpperCase();
|
|
lineNo = lineNo.toUpperCase();
|
|
}
|
|
|
|
output += lineNo + " " +
|
|
Utils.padRight(hexa, (length*(padding+1))) +
|
|
" |" + Utils.padRight(Utils.printable(Utils.byteArrayToChars(buff)), buff.length) + "|\n";
|
|
|
|
if (includeFinalLength && i+buff.length === input.length) {
|
|
output += Utils.hex(i+buff.length, 8) + "\n";
|
|
}
|
|
}
|
|
|
|
return output.slice(0, -1);
|
|
},
|
|
|
|
|
|
/**
|
|
* From Hexdump operation.
|
|
*
|
|
* @param {string} input
|
|
* @param {Object[]} args
|
|
* @returns {byteArray}
|
|
*/
|
|
runFrom: function(input, args) {
|
|
let output = [],
|
|
regex = /^\s*(?:[\dA-F]{4,16}:?)?\s*((?:[\dA-F]{2}\s){1,8}(?:\s|[\dA-F]{2}-)(?:[\dA-F]{2}\s){1,8}|(?:[\dA-F]{2}\s|[\dA-F]{4}\s)+)/igm,
|
|
block, line;
|
|
|
|
while ((block = regex.exec(input))) {
|
|
line = Utils.fromHex(block[1].replace(/-/g, " "));
|
|
for (let i = 0; i < line.length; i++) {
|
|
output.push(line[i]);
|
|
}
|
|
}
|
|
// Is this a CyberChef hexdump or is it from a different tool?
|
|
const width = input.indexOf("\n");
|
|
const w = (width - 13) / 4;
|
|
// 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 (ENVIRONMENT_IS_WORKER()) self.setOption("attemptHighlight", false);
|
|
}
|
|
return output;
|
|
},
|
|
|
|
|
|
/**
|
|
* Highlight to hexdump
|
|
*
|
|
* @param {Object[]} pos
|
|
* @param {number} pos[].start
|
|
* @param {number} pos[].end
|
|
* @param {Object[]} args
|
|
* @returns {Object[]} pos
|
|
*/
|
|
highlightTo: function(pos, args) {
|
|
// Calculate overall selection
|
|
let w = args[0] || 16,
|
|
width = 14 + (w*4),
|
|
line = Math.floor(pos[0].start / w),
|
|
offset = pos[0].start % w,
|
|
start = 0,
|
|
end = 0;
|
|
|
|
pos[0].start = line*width + 10 + offset*3;
|
|
|
|
line = Math.floor(pos[0].end / w);
|
|
offset = pos[0].end % w;
|
|
if (offset === 0) {
|
|
line--;
|
|
offset = w;
|
|
}
|
|
pos[0].end = line*width + 10 + offset*3 - 1;
|
|
|
|
// Set up multiple selections for bytes
|
|
let startLineNum = Math.floor(pos[0].start / width);
|
|
const endLineNum = Math.floor(pos[0].end / width);
|
|
|
|
if (startLineNum === endLineNum) {
|
|
pos.push(pos[0]);
|
|
} else {
|
|
start = pos[0].start;
|
|
end = (startLineNum+1) * width - w - 5;
|
|
pos.push({ start: start, end: end });
|
|
while (end < pos[0].end) {
|
|
startLineNum++;
|
|
start = startLineNum * width + 10;
|
|
end = (startLineNum+1) * width - w - 5;
|
|
if (end > pos[0].end) end = pos[0].end;
|
|
pos.push({ start: start, end: end });
|
|
}
|
|
}
|
|
|
|
// Set up multiple selections for ASCII
|
|
let len = pos.length, lineNum = 0;
|
|
start = 0;
|
|
end = 0;
|
|
for (let i = 1; i < len; i++) {
|
|
lineNum = Math.floor(pos[i].start / width);
|
|
start = (((pos[i].start - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
|
end = (((pos[i].end + 1 - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width);
|
|
pos.push({ start: start, end: end });
|
|
}
|
|
return pos;
|
|
},
|
|
|
|
|
|
/**
|
|
* Highlight from hexdump
|
|
*
|
|
* @param {Object[]} pos
|
|
* @param {number} pos[].start
|
|
* @param {number} pos[].end
|
|
* @param {Object[]} args
|
|
* @returns {Object[]} pos
|
|
*/
|
|
highlightFrom: function(pos, args) {
|
|
const w = args[0] || 16;
|
|
const width = 14 + (w*4);
|
|
|
|
let line = Math.floor(pos[0].start / width);
|
|
let offset = pos[0].start % width;
|
|
|
|
if (offset < 10) { // In line number section
|
|
pos[0].start = line*w;
|
|
} else if (offset > 10+(w*3)) { // In ASCII section
|
|
pos[0].start = (line+1)*w;
|
|
} else { // In byte section
|
|
pos[0].start = line*w + Math.floor((offset-10)/3);
|
|
}
|
|
|
|
line = Math.floor(pos[0].end / width);
|
|
offset = pos[0].end % width;
|
|
|
|
if (offset < 10) { // In line number section
|
|
pos[0].end = line*w;
|
|
} else if (offset > 10+(w*3)) { // In ASCII section
|
|
pos[0].end = (line+1)*w;
|
|
} else { // In byte section
|
|
pos[0].end = line*w + Math.ceil((offset-10)/3);
|
|
}
|
|
|
|
return pos;
|
|
},
|
|
|
|
};
|
|
|
|
export default Hexdump;
|