From 7c72871c0200d8d0b51580f8ef6d1a0dbd291110 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Thu, 14 Nov 2019 17:17:25 +0000 Subject: [PATCH 1/8] Added Tar and Mach-O extractors --- src/core/lib/FileSignatures.mjs | 177 +++++++++++++++++++++++++++++--- 1 file changed, 164 insertions(+), 13 deletions(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index dc7ced4d..8877881d 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -1282,17 +1282,25 @@ export const FILE_SIGNATURES = { extension: "dylib", mime: "application/octet-stream", description: "", - signature: { - 0: 0xca, - 1: 0xfe, - 2: 0xba, - 3: 0xbe, - 4: 0x00, - 5: 0x00, - 6: 0x00, - 7: [0x01, 0x02, 0x03] - }, - extractor: null + signature: [ + { + 0: 0xca, + 1: 0xfe, + 2: 0xba, + 3: 0xbe, + 4: 0x00, + 5: 0x00, + 6: 0x00, + 7: [0x01, 0x02, 0x03] + }, + { + 0: 0xce, + 1: 0xfa, + 2: 0xed, + 3: 0xfe + } + ], + extractor: extractMACHO }, { name: "MacOS Mach-O 64-bit object", @@ -1305,7 +1313,7 @@ export const FILE_SIGNATURES = { 2: 0xed, 3: 0xfe }, - extractor: null + extractor: extractMACHO }, { name: "Adobe Flash", @@ -1404,7 +1412,7 @@ export const FILE_SIGNATURES = { 260: 0x61, 261: 0x72 }, - extractor: null + extractor: extractTAR }, { name: "Roshal Archive", @@ -2720,6 +2728,149 @@ export function extractZIP(bytes, offset) { } +/** + * MACHO extractor + * + * @param {Uint8Array} bytes + * @param {number} offset + * @returns {Uint8Array} + */ +export function extractMACHO(bytes, offset) { + + + /** + * Checks to see if the file is 64-bit. + * + * @param {string} magic + * @returns {bool} + */ + function isMagic64(magic) { + return magic === MHCIGAM64 || magic === MHCIGAM64; + } + + + /** + * Checks the endianness of the file. + * + * @param {string} magic + * @returns {bool} + */ + function shouldSwapBytes(magic) { + return magic === MHCIGAM || magic === MHCIGAM64; + } + + + /** + * Jumps through segment information and calculates the sum of the segement sizes. + * + * @param {Stream} stream + * @param {number} offset + * @param {string} isSwap + * @param {number} ncmds + * @returns {number} + */ + function dumpSegmentCommands(stream, offset, isSwap, ncmds) { + let total = 0; + for (let i = 0; i < ncmds; i++) { + + // Move to start of segment. + stream.moveTo(offset); + const cmd = stream.readInt(4, isSwap); + if (cmd === LCSEGEMENT64) { + + // Move to size of segment field. + stream.moveTo(offset + 48); + + // Extract size of segement. + total += stream.readInt(8, isSwap); + stream.moveTo(offset + 4); + + // Move to offset of next segment. + offset += stream.readInt(4, isSwap); + } else if (cmd === LCSEGEMENT) { + stream.moveTo(offset + 36); + + // Extract size of segement. + total += stream.readInt(4, isSwap); + stream.moveTo(offset + 4); + offset += stream.readInt(4, isSwap); + } + } + return total; + } + + + /** + * Reads the number of command segments. + * + * @param {Stream} stream + * @param {bool} is64 + * @param {string} isSwap + * @returns {number} + */ + function dumpMachHeader(stream, is64, isSwap) { + let loadCommandsOffset = 28; + if (is64) + loadCommandsOffset += 4; + + // Move to number of commands field. + stream.moveTo(16); + const ncmds = stream.readInt(4, isSwap); + return dumpSegmentCommands(stream, loadCommandsOffset, isSwap, ncmds); + } + + + const MHCIGAM64 = "207250237254"; + const MHCIGAM = "206250237254"; + const LCSEGEMENT64 = 0x19; + const LCSEGEMENT = 0x1; + const stream = new Stream(bytes.slice(offset)); + const magic = stream.getBytes(4).join(""); + const is64 = isMagic64(magic); + const isSwap = shouldSwapBytes(magic) ? "le" : "be"; + + // Move to the end of the final segment. + stream.moveTo(dumpMachHeader(stream, is64, isSwap)); + return stream.carve(); +} + + +/** + * TAR extractor. + * + * @param {Uint8Array} bytes + * @param {number} offset + * @returns {Uint8Array} + */ +export function extractTAR(bytes, offset) { + const stream = new Stream(bytes.slice(offset)); + while (stream.hasMore()) { + + // Move to ustar identifier. + stream.moveForwardsBy(0x101); + if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) + break; + + // Move back to file size field. + stream.moveBackwardsBy(0x8a); + let fsize = 0; + + // Read file size field. + stream.getBytes(11).forEach((element, index) => { + fsize += (element - 48).toString(); + }); + + // Round number up from octet to nearest 512. + fsize = (Math.ceil(parseInt(fsize, 8) / 512) * 512); + + // Move forwards to the end of that file. + stream.moveForwardsBy(fsize + 0x179); + } + stream.consumeWhile(0x00); + return stream.carve(); +} + + /** * PNG extractor. * From 7c25e295156006b788eeac2122d92d992ae2bec9 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 15 Nov 2019 09:21:46 +0000 Subject: [PATCH 2/8] Rectified magic bytes for MACHO extractor --- src/core/lib/FileSignatures.mjs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 8877881d..2ef390cd 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -2745,7 +2745,7 @@ export function extractMACHO(bytes, offset) { * @returns {bool} */ function isMagic64(magic) { - return magic === MHCIGAM64 || magic === MHCIGAM64; + return magic === MHCIGAM64 || magic === MHMAGIC64; } @@ -2821,16 +2821,16 @@ export function extractMACHO(bytes, offset) { const MHCIGAM64 = "207250237254"; + const MHMAGIC64 = "254237250207"; const MHCIGAM = "206250237254"; const LCSEGEMENT64 = 0x19; const LCSEGEMENT = 0x1; + const stream = new Stream(bytes.slice(offset)); const magic = stream.getBytes(4).join(""); - const is64 = isMagic64(magic); - const isSwap = shouldSwapBytes(magic) ? "le" : "be"; // Move to the end of the final segment. - stream.moveTo(dumpMachHeader(stream, is64, isSwap)); + stream.moveTo(dumpMachHeader(stream, isMagic64(magic), shouldSwapBytes(magic) ? "le" : "be")); return stream.carve(); } From acf5c733c2fa74ac59cb8a4f3352ff0dc56443c8 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 15 Nov 2019 09:26:49 +0000 Subject: [PATCH 3/8] Tidied up local and global variables for Mach-o --- src/core/lib/FileSignatures.mjs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 2ef390cd..cf8a5373 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -2737,6 +2737,11 @@ export function extractZIP(bytes, offset) { */ export function extractMACHO(bytes, offset) { + // Magic bytes. + const MHCIGAM64 = "207250237254"; + const MHMAGIC64 = "254237250207"; + const MHCIGAM = "206250237254"; + /** * Checks to see if the file is 64-bit. @@ -2771,6 +2776,9 @@ export function extractMACHO(bytes, offset) { */ function dumpSegmentCommands(stream, offset, isSwap, ncmds) { let total = 0; + const LCSEGEMENT64 = 0x19; + const LCSEGEMENT = 0x1; + for (let i = 0; i < ncmds; i++) { // Move to start of segment. @@ -2820,12 +2828,6 @@ export function extractMACHO(bytes, offset) { } - const MHCIGAM64 = "207250237254"; - const MHMAGIC64 = "254237250207"; - const MHCIGAM = "206250237254"; - const LCSEGEMENT64 = 0x19; - const LCSEGEMENT = 0x1; - const stream = new Stream(bytes.slice(offset)); const magic = stream.getBytes(4).join(""); From e1cb62848c0a22e0cdb4d8200421f862612e12e2 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 15 Nov 2019 15:35:37 +0000 Subject: [PATCH 4/8] Made TAR extractor and MACHO signature more robust --- src/core/lib/FileSignatures.mjs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index cf8a5373..8c5a6557 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -1297,7 +1297,12 @@ export const FILE_SIGNATURES = { 0: 0xce, 1: 0xfa, 2: 0xed, - 3: 0xfe + 3: 0xfe, + 4: 0x07, + 5: 0x00, + 6: 0x00, + 7: 0x00, + 8: 0x03 } ], extractor: extractMACHO @@ -2850,8 +2855,12 @@ export function extractTAR(bytes, offset) { // Move to ustar identifier. stream.moveForwardsBy(0x101); - if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) + if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) { + + // This is needed since if it were not here it relies on there being at least 0x106 padding of 0s at the end of the TAR + stream.moveBackwardsBy(0x101); break; + } // Move back to file size field. stream.moveBackwardsBy(0x8a); From 0a7b78b7ee7cc851799f8462f616c10f964987ca Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 15 Nov 2019 15:46:13 +0000 Subject: [PATCH 5/8] Made TAR extractor and MACHO signature more robust --- src/core/lib/FileSignatures.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 8c5a6557..0442b3b0 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -2858,7 +2858,7 @@ export function extractTAR(bytes, offset) { if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) { // This is needed since if it were not here it relies on there being at least 0x106 padding of 0s at the end of the TAR - stream.moveBackwardsBy(0x101); + stream.moveBackwardsBy(0x106); break; } From c1a22ef639ad92d3b035e0a922edea1de5dadc83 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Fri, 15 Nov 2019 16:01:33 +0000 Subject: [PATCH 6/8] Made TAR extractor and MACHO signature more robust --- src/core/lib/FileSignatures.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 0442b3b0..2fa630e1 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -1302,7 +1302,7 @@ export const FILE_SIGNATURES = { 5: 0x00, 6: 0x00, 7: 0x00, - 8: 0x03 + 8: [0x01, 0x02, 0x03] } ], extractor: extractMACHO From 2e7ce477d70fd9b6c93744c5f9119babb7bada43 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Mon, 18 Nov 2019 08:40:57 +0000 Subject: [PATCH 7/8] Tidied up ExtractTAR --- src/core/lib/FileSignatures.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 2fa630e1..939672f2 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -2857,7 +2857,7 @@ export function extractTAR(bytes, offset) { stream.moveForwardsBy(0x101); if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) { - // This is needed since if it were not here it relies on there being at least 0x106 padding of 0s at the end of the TAR + // Needed since if it were not here it relies on there being at least 0x106 padding of 0s at the end of the TAR. stream.moveBackwardsBy(0x106); break; } From 7a4ebbf47e11bea8a00b2521f13779c3868197a6 Mon Sep 17 00:00:00 2001 From: n1073645 Date: Mon, 18 Nov 2019 08:42:46 +0000 Subject: [PATCH 8/8] Tidied up ExtractTAR --- src/core/lib/FileSignatures.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 939672f2..2e85baf5 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -2857,7 +2857,7 @@ export function extractTAR(bytes, offset) { stream.moveForwardsBy(0x101); if (stream.getBytes(5).join("") !== [0x75, 0x73, 0x74, 0x61, 0x72].join("")) { - // Needed since if it were not here it relies on there being at least 0x106 padding of 0s at the end of the TAR. + // Needed since we cannot rely on there being at least 0x106 padding of 0s at the end of the TAR(even though there usually is). stream.moveBackwardsBy(0x106); break; }