From 242bad09eaa2c081ec4a497711efe4ff812fab8f Mon Sep 17 00:00:00 2001 From: n1474335 Date: Sun, 4 Mar 2018 18:41:41 +0000 Subject: [PATCH] Added SSDEEP and CTPH operations --- package-lock.json | 10 +++++ package.json | 2 + src/core/config/Categories.js | 4 ++ src/core/config/OperationConfig.js | 40 +++++++++++++++++++ src/core/config/modules/Hashing.js | 54 ++++++++++++++------------ src/core/operations/Hash.js | 62 ++++++++++++++++++++++++++++++ 6 files changed, 147 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index aca47b6..254399f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2419,6 +2419,11 @@ "cssom": "0.3.2" } }, + "ctph.js": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/ctph.js/-/ctph.js-0.0.5.tgz", + "integrity": "sha1-F+xd3R2+aPFRvj1EbPGNRhuV8uc=" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -11044,6 +11049,11 @@ "number-is-nan": "1.0.1" } }, + "ssdeep.js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/ssdeep.js/-/ssdeep.js-0.0.2.tgz", + "integrity": "sha1-mItJTQ3JwxkAX9rJZj1jOO/tHyI=" + }, "sshpk": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", diff --git a/package.json b/package.json index 69ba222..5a82a64 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "bootstrap-switch": "^3.3.4", "crypto-api": "^0.8.0", "crypto-js": "^3.1.9-1", + "ctph.js": "0.0.5", "diff": "^3.4.0", "escodegen": "^1.9.1", "esmangle": "^1.0.1", @@ -101,6 +102,7 @@ "sladex-blowfish": "^0.8.1", "sortablejs": "^1.7.0", "split.js": "^1.3.5", + "ssdeep.js": "0.0.2", "ua-parser-js": "^0.7.17", "utf8": "^3.0.0", "vkbeautify": "^0.99.3", diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js index 5285fff..6f04267 100755 --- a/src/core/config/Categories.js +++ b/src/core/config/Categories.js @@ -270,6 +270,10 @@ const Categories = [ "HAS-160", "Whirlpool", "Snefru", + "SSDEEP", + "CTPH", + "Compare SSDEEP hashes", + "Compare CTPH hashes", "HMAC", "Fletcher-8 Checksum", "Fletcher-16 Checksum", diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 214b71b..6a8f5d3 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -3174,6 +3174,46 @@ const OperationConfig = { } ] }, + "SSDEEP": { + module: "Hashing", + description: "SSDEEP is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.

SSDEEP hashes are now widely used for simple identification purposes (e.g. the 'Basic Properties' section in VirusTotal). Although 'better' fuzzy hashes are available, SSDEEP is still one of the primary choices because of its speed and being a de facto standard.

This operation is fundamentally the same as the CTPH operation, however their outputs differ in format.", + inputType: "string", + outputType: "string", + args: [] + }, + "CTPH": { + module: "Hashing", + description: "Context Triggered Piecewise Hashing, also called Fuzzy Hashing, can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.

CTPH was originally based on the work of Dr. Andrew Tridgell and a spam email detector called SpamSum. This method was adapted by Jesse Kornblum and published at the DFRWS conference in 2006 in a paper 'Identifying Almost Identical Files Using Context Triggered Piecewise Hashing'.", + inputType: "string", + outputType: "string", + args: [] + }, + "Compare SSDEEP hashes": { + module: "Hashing", + description: "Compares two SSDEEP fuzzy hashes to determine the similarity between them on a scale of 0 to 100.", + inputType: "string", + outputType: "Number", + args: [ + { + name: "Delimiter", + type: "option", + value: Hash.DELIM_OPTIONS + } + ] + }, + "Compare CTPH hashes": { + module: "Hashing", + description: "Compares two Context Triggered Piecewise Hashing (CTPH) fuzzy hashes to determine the similarity between them on a scale of 0 to 100.", + inputType: "string", + outputType: "Number", + args: [ + { + name: "Delimiter", + type: "option", + value: Hash.DELIM_OPTIONS + } + ] + }, "HMAC": { module: "Hashing", description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.", diff --git a/src/core/config/modules/Hashing.js b/src/core/config/modules/Hashing.js index c19fc3e..2b9ffea 100644 --- a/src/core/config/modules/Hashing.js +++ b/src/core/config/modules/Hashing.js @@ -18,31 +18,35 @@ import Hash from "../../operations/Hash.js"; let OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; OpModules.Hashing = { - "Analyse hash": Hash.runAnalyse, - "Generate all hashes": Hash.runAll, - "MD2": Hash.runMD2, - "MD4": Hash.runMD4, - "MD5": Hash.runMD5, - "MD6": Hash.runMD6, - "SHA0": Hash.runSHA0, - "SHA1": Hash.runSHA1, - "SHA2": Hash.runSHA2, - "SHA3": Hash.runSHA3, - "Keccak": Hash.runKeccak, - "Shake": Hash.runShake, - "RIPEMD": Hash.runRIPEMD, - "HAS-160": Hash.runHAS, - "Whirlpool": Hash.runWhirlpool, - "Snefru": Hash.runSnefru, - "HMAC": Hash.runHMAC, - "Fletcher-8 Checksum": Checksum.runFletcher8, - "Fletcher-16 Checksum": Checksum.runFletcher16, - "Fletcher-32 Checksum": Checksum.runFletcher32, - "Fletcher-64 Checksum": Checksum.runFletcher64, - "Adler-32 Checksum": Checksum.runAdler32, - "CRC-16 Checksum": Checksum.runCRC16, - "CRC-32 Checksum": Checksum.runCRC32, - "TCP/IP Checksum": Checksum.runTCPIP, + "Analyse hash": Hash.runAnalyse, + "Generate all hashes": Hash.runAll, + "MD2": Hash.runMD2, + "MD4": Hash.runMD4, + "MD5": Hash.runMD5, + "MD6": Hash.runMD6, + "SHA0": Hash.runSHA0, + "SHA1": Hash.runSHA1, + "SHA2": Hash.runSHA2, + "SHA3": Hash.runSHA3, + "Keccak": Hash.runKeccak, + "Shake": Hash.runShake, + "RIPEMD": Hash.runRIPEMD, + "HAS-160": Hash.runHAS, + "Whirlpool": Hash.runWhirlpool, + "Snefru": Hash.runSnefru, + "CTPH": Hash.runCTPH, + "SSDEEP": Hash.runSSDEEP, + "Compare CTPH hashes": Hash.runCompareCTPH, + "Compare SSDEEP hashes": Hash.runCompareSSDEEP, + "HMAC": Hash.runHMAC, + "Fletcher-8 Checksum": Checksum.runFletcher8, + "Fletcher-16 Checksum": Checksum.runFletcher16, + "Fletcher-32 Checksum": Checksum.runFletcher32, + "Fletcher-64 Checksum": Checksum.runFletcher64, + "Adler-32 Checksum": Checksum.runAdler32, + "CRC-16 Checksum": Checksum.runCRC16, + "CRC-32 Checksum": Checksum.runCRC32, + "TCP/IP Checksum": Checksum.runTCPIP, }; export default OpModules; diff --git a/src/core/operations/Hash.js b/src/core/operations/Hash.js index f785a92..1e3e8a9 100755 --- a/src/core/operations/Hash.js +++ b/src/core/operations/Hash.js @@ -3,6 +3,8 @@ import CryptoApi from "babel-loader!crypto-api"; import MD6 from "node-md6"; import * as SHA3 from "js-sha3"; import Checksum from "./Checksum.js"; +import ctph from "ctph.js"; +import ssdeep from "ssdeep.js"; /** @@ -336,6 +338,64 @@ const Hash = { }, + /** + * CTPH operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runCTPH: function (input, args) { + return ctph.digest(input); + }, + + + /** + * SSDEEP operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + runSSDEEP: function (input, args) { + return ssdeep.digest(input); + }, + + + /** + * @constant + * @default + */ + DELIM_OPTIONS: ["Line feed", "CRLF", "Space", "Comma", "Semi-colon", "Colon"], + + /** + * Compare CTPH hashes operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {Number} + */ + runCompareCTPH: function (input, args) { + const samples = input.split(Utils.charRep[args[0]]); + if (samples.length !== 2) throw "Incorrect number of samples."; + return ctph.similarity(samples[0], samples[1]); + }, + + + /** + * Compare SSDEEP hashes operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {Number} + */ + runCompareSSDEEP: function (input, args) { + const samples = input.split(Utils.charRep[args[0]]); + if (samples.length !== 2) throw "Incorrect number of samples."; + return ssdeep.similarity(samples[0], samples[1]); + }, + + /** * @constant * @default @@ -428,6 +488,8 @@ const Hash = { "\nWhirlpool-0: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-0"]) + "\nWhirlpool-T: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool-T"]) + "\nWhirlpool: " + Hash.runWhirlpool(arrayBuffer, ["Whirlpool"]) + + "\nSSDEEP: " + Hash.runSSDEEP(str) + + "\nCTPH: " + Hash.runCTPH(str) + "\n\nChecksums:" + "\nFletcher-8: " + Checksum.runFletcher8(byteArray, []) + "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +