From e2f72ddea65fd117f2ca38a77f75094b547d567e Mon Sep 17 00:00:00 2001 From: "windhamwong@nva-hk.com" Date: Thu, 23 Mar 2017 13:13:49 +0000 Subject: [PATCH] Adding nTcpdump as new operations --- package.json | 3 + src/js/config/Categories.js | 1 + src/js/config/OperationConfig.js | 9 ++ src/js/operations/nTcpdump.js | 200 +++++++++++++++++++++++++++++++ 4 files changed, 213 insertions(+) create mode 100644 src/js/operations/nTcpdump.js diff --git a/package.json b/package.json index 8878ff97..14eb315e 100644 --- a/package.json +++ b/package.json @@ -42,5 +42,8 @@ "grunt-jsdoc": "^2.1.0", "ink-docstrap": "^1.1.4", "phantomjs-prebuilt": "^2.1.14" + }, + "dependencies": { + "grunt-cli": "^1.2.0" } } diff --git a/src/js/config/Categories.js b/src/js/config/Categories.js index 3a84b0ef..c92cc4c3 100755 --- a/src/js/config/Categories.js +++ b/src/js/config/Categories.js @@ -27,6 +27,7 @@ var Categories = [ ops: [ "To Hexdump", "From Hexdump", + "From nTcpdump", "To Hex", "From Hex", "To Charcode", diff --git a/src/js/config/OperationConfig.js b/src/js/config/OperationConfig.js index e8e3a881..b6d56c6e 100755 --- a/src/js/config/OperationConfig.js +++ b/src/js/config/OperationConfig.js @@ -517,6 +517,15 @@ var OperationConfig = { } ] }, + "From nTcpdump": { + description: "For Tcpdump conversion only. (nva-hk)", + run: nTcpdump.runFrom, + highlight: nTcpdump.highlightFrom, + highlightReverse: nTcpdump.highlightTo, + inputType: "string", + outputType: "byteArray", + args: [] + }, "From Hexdump": { description: "Attempts to convert a hexdump back into raw data. This operation supports many different hexdump variations, but probably not all. Make sure you verify that the data it gives you is correct before continuing analysis.", run: Hexdump.runFrom, diff --git a/src/js/operations/nTcpdump.js b/src/js/operations/nTcpdump.js new file mode 100644 index 00000000..ec250505 --- /dev/null +++ b/src/js/operations/nTcpdump.js @@ -0,0 +1,200 @@ +/* globals app */ + +/** + * Hexdump operations. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * @namespace + */ +var nTcpdump = { + + /** + * @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) { + var length = args[0] || nTcpdump.WIDTH; + var upperCase = args[1]; + var includeFinalLength = 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 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) { + var output = [], + regex = /^\s*(?:0x[\dA-F]{4}:?)?\s*((?:[\dA-F]{4}\s?){1,8})/igm, + regex_header = /^\s*(?:0x0000:){1}\s*((?:[\dA-F]{4}\s?){6})/igm, + block, line; + + while ((block = regex.exec(input))) { + // block[1].replace(regex_header, "0x0000:"); + line = Utils.fromHex(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.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 + 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 startLineNum = Math.floor(pos[0].start / width); + var 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 + var len = pos.length, lineNum = 0; + start = 0; + end = 0; + for (var 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) { + 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; + }, + +};