diff --git a/src/core/lib/FileSignatures.mjs b/src/core/lib/FileSignatures.mjs index 6bc366e7..dc7ced4d 100644 --- a/src/core/lib/FileSignatures.mjs +++ b/src/core/lib/FileSignatures.mjs @@ -3350,12 +3350,11 @@ export function extractEVTX(bytes, offset) { while (stream.hasMore()) { // Loop through ELFCHNKs. - if (stream.getBytes(7).join("") === "\x45\x6c\x66\x43\x68\x6e\x6b") - stream.moveForwardsBy(0xfff9); - else + if (stream.getBytes(7).join("") !== [0x45, 0x6c, 0x66, 0x43, 0x68, 0x6e, 0x6b].join("")) break; + stream.moveForwardsBy(0xfff9); } - + stream.consumeWhile(0x00); return stream.carve(); } diff --git a/src/core/lib/Stream.mjs b/src/core/lib/Stream.mjs index 7e82a5eb..da299b65 100644 --- a/src/core/lib/Stream.mjs +++ b/src/core/lib/Stream.mjs @@ -155,16 +155,69 @@ export default class Stream { } // val is an array - let found = false; - while (!found && this.position < this.length) { - while (++this.position < this.length && this.bytes[this.position] !== val[0]) { - continue; - } + + + /** + * Builds the skip forward table from the value to be searched. + * + * @param {Uint8Array} val + * @param {Number} len + * @returns {Uint8Array} + */ + function preprocess(val, len) { + const skiptable = new Array(); + val.forEach((element, index) => { + skiptable[element] = len - index; + }); + return skiptable; + } + + const length = val.length; + + const initial = val[length-1]; + + this.position = length; + + // Get the skip table. + const skiptable = preprocess(val, length); + let found = true; + + while (this.position < this.length) { + + // Until we hit the final element of val in the stream. + while ((this.position < this.length) && (this.bytes[this.position++] !== initial)); + found = true; - for (let i = 1; i < val.length; i++) { - if (this.position + i > this.length || this.bytes[this.position + i] !== val[i]) + + // Loop through the elements comparing them to val. + for (let x = length-1; x >= 0; x--) { + if (this.bytes[this.position-length + x] !== val[x]) { found = false; + + // If element is not equal to val's element then jump forward by the correct amount. + this.position += skiptable[val[x]]; + break; + } } + if (found) { + this.position -= length; + break; + } + } + } + + + /** + * Consume bytes if it matches the supplied value. + * + * @param {Number} val + */ + consumeWhile(val) { + while (this.position < this.length) { + if (this.bytes[this.position] !== val) { + break; + } + this.position++; } }