/* globals app */ /** * Hexdump operations. * * @author n1474335 [n1474335@gmail.com] * @copyright Crown Copyright 2016 * @license Apache-2.0 * * @namespace */ var 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: function(input, args) { var length = args[0] || Hexdump.WIDTH; var upper_case = args[1]; var include_final_length = args[2]; var output = "", padding = 2; for (var i = 0; i < input.length; i += length) { var buff = input.slice(i, i+length); var hexa = ""; for (var j = 0; j < buff.length; j++) { hexa += Utils.hex(buff[j], padding) + " "; } var 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: function(input, args) { var 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 (var i = 0; i < line.length; i++) { output.push(line[i]); } } // Is this a CyberChef hexdump or is it from a different tool? var width = input.indexOf("\n"); var 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: function(pos, args) { // Calculate overall selection var 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 var start_line_num = Math.floor(pos[0].start / width); var 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: start, end: 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: start, end: end }); } } // Set up multiple selections for ASCII var len = pos.length, line_num = 0; start = 0; end = 0; for (var 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: 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 */ highlight_from: function(pos, args) { var w = args[0] || 16; var width = 14 + (w*4); var line = Math.floor(pos[0].start / width); var 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; }, };