CyberChef/src/js/operations/Hexdump.js
2016-11-29 18:36:36 +00:00

198 lines
5.1 KiB
JavaScript
Executable file

/* globals app */
/**
* 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 {byte_array} input
* @param {Object[]} args
* @returns {string}
*/
run_to(input, args) {
const length = args[0] || Hexdump.WIDTH;
const upper_case = args[1];
const include_final_length = 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 line_no = Utils.hex(i, 8);
if (upper_case) {
hexa = hexa.toUpperCase();
line_no = line_no.toUpperCase();
}
output += `${line_no} ${
Utils.pad_right(hexa, (length * (padding + 1)))
} |${Utils.pad_right(Utils.printable(Utils.byte_array_to_chars(buff)), buff.length)}|\n`;
if (include_final_length && 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 {byte_array}
*/
run_from(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.from_hex(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) {
app.options.attempt_highlight = false;
}
return output;
},
/**
* Highlight to hexdump
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlight_to(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 start_line_num = Math.floor(pos[0].start / width);
const end_line_num = Math.floor(pos[0].end / width);
if (start_line_num == end_line_num) {
pos.push(pos[0]);
} else {
start = pos[0].start;
end = (start_line_num + 1) * width - w - 5;
pos.push({ start, end });
while (end < pos[0].end) {
start_line_num++;
start = start_line_num * width + 10;
end = (start_line_num + 1) * width - w - 5;
if (end > pos[0].end) end = pos[0].end;
pos.push({ start, end });
}
}
// Set up multiple selections for ASCII
let len = pos.length,
line_num = 0;
start = 0;
end = 0;
for (let i = 1; i < len; i++) {
line_num = Math.floor(pos[i].start / width);
start = (((pos[i].start - (line_num * width)) - 10) / 3) + (width - w - 2) + (line_num * width);
end = (((pos[i].end + 1 - (line_num * width)) - 10) / 3) + (width - w - 2) + (line_num * width);
pos.push({ start, end });
}
return pos;
},
/**
* Highlight from hexdump
*
* @param {Object[]} pos
* @param {number} pos[].start
* @param {number} pos[].end
* @param {Object[]} args
* @returns {Object[]} pos
*/
highlight_from(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;
},
};