From 65eea4301d1a4dda48e8fa409b34a113d0019dac Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 14 Mar 2022 23:01:06 -0700 Subject: [PATCH] Hide section complexity from content checks --- .../Microsoft/PE/PortableExecutable.cs | 104 +++++++++--------- BurnOutSharp/PackerType/Armadillo.cs | 2 +- BurnOutSharp/ProtectionType/ActiveMARK.cs | 2 +- BurnOutSharp/ProtectionType/CDSHiELDSE.cs | 2 +- BurnOutSharp/ProtectionType/JoWood.cs | 2 +- BurnOutSharp/ProtectionType/SafeDisc.cs | 2 +- BurnOutSharp/ProtectionType/SmartE.cs | 2 +- BurnOutSharp/ProtectionType/SolidShield.cs | 4 +- BurnOutSharp/ProtectionType/WTMCDProtect.cs | 2 +- 9 files changed, 64 insertions(+), 58 deletions(-) diff --git a/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs b/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs index 7f2e2e54..8132bc40 100644 --- a/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs +++ b/BurnOutSharp/ExecutableType/Microsoft/PE/PortableExecutable.cs @@ -189,8 +189,8 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE if (stream == null || !stream.CanRead || !stream.CanSeek) return; - this.Initialized = Deserialize(stream); this.SourceStream = stream; + this.Initialized = Deserialize(stream); } /// @@ -203,8 +203,8 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE if (fileContent == null || fileContent.Length == 0 || offset < 0) return; - this.Initialized = Deserialize(fileContent, offset); this.SourceArray = fileContent; + this.Initialized = Deserialize(fileContent, offset); } /// @@ -279,19 +279,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE #region Freeform Sections // Data Section - this.DataSectionRaw = this.ReadRawSection(stream, ".data", force: true, first: false) ?? this.ReadRawSection(stream, "DATA", force: true, first: false); + this.DataSectionRaw = this.ReadRawSection(".data", force: true, first: false) ?? this.ReadRawSection("DATA", force: true, first: false); // Export Table - this.ExportDataSectionRaw = this.ReadRawSection(stream, ".edata", force: true, first: false); + this.ExportDataSectionRaw = this.ReadRawSection(".edata", force: true, first: false); // Import Table - this.ImportDataSectionRaw = this.ReadRawSection(stream, ".idata", force: true, first: false); + this.ImportDataSectionRaw = this.ReadRawSection(".idata", force: true, first: false); // Resource Data Section - this.ResourceDataSectionRaw = this.ReadRawSection(stream, ".rdata", force: true, first: false); + this.ResourceDataSectionRaw = this.ReadRawSection(".rdata", force: true, first: false); // Text Section - this.TextSectionRaw = this.ReadRawSection(stream, ".text", force: true, first: false); + this.TextSectionRaw = this.ReadRawSection(".text", force: true, first: false); #endregion } @@ -378,19 +378,19 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE #region Freeform Sections // Data Section - this.DataSectionRaw = this.ReadRawSection(content, ".data", force: true, first: false) ?? this.ReadRawSection(content, "DATA", force: true, first: false); + this.DataSectionRaw = this.ReadRawSection(".data", force: true, first: false) ?? this.ReadRawSection("DATA", force: true, first: false); // Export Table - this.ExportDataSectionRaw = this.ReadRawSection(content, ".edata", force: true, first: false); + this.ExportDataSectionRaw = this.ReadRawSection(".edata", force: true, first: false); // Import Table - this.ImportDataSectionRaw = this.ReadRawSection(content, ".idata", force: true, first: false); + this.ImportDataSectionRaw = this.ReadRawSection(".idata", force: true, first: false); // Resource Data Section - this.ResourceDataSectionRaw = this.ReadRawSection(content, ".rdata", force: true, first: false); + this.ResourceDataSectionRaw = this.ReadRawSection(".rdata", force: true, first: false); // Text Section - this.TextSectionRaw = this.ReadRawSection(content, ".text", force: true, first: false); + this.TextSectionRaw = this.ReadRawSection(".text", force: true, first: false); #endregion } @@ -528,8 +528,11 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE /// /// Get the raw bytes from a section, if possible /// - /// TODO: These can be combined and use SourceArray and SourceStream instead - public byte[] ReadRawSection(Stream stream, string sectionName, bool force = false, bool first = true, int offset = 0) + /// The name of the section to attempt to read + /// True to force reading the section from the underlying source, false to use cached values, if possible + /// True to use the first section with a matching name, false to use the last section + /// Offset to start reading at, default is 0 + public byte[] ReadRawSection(string sectionName, bool force = false, bool first = true, int offset = 0) { // Special cases for non-forced, non-offset data if (!force && offset == 0) @@ -549,58 +552,61 @@ namespace BurnOutSharp.ExecutableType.Microsoft.PE } } - var section = first ? GetFirstSection(sectionName, true) : GetLastSection(sectionName, true); - if (section == null) - return null; + // If we have a source stream, use that + if (this.SourceStream != null) + return ReadRawSectionFromSourceStream(sectionName, first, offset); - lock (stream) - { - int startingIndex = (int)Math.Max(section.PointerToRawData + offset, 0); - int readLength = (int)Math.Min(section.VirtualSize - offset, stream.Length); + // If we have a source array, use that + if (this.SourceArray != null) + return ReadRawSectionFromSourceArray(sectionName, first, offset); - long originalPosition = stream.Position; - stream.Seek(startingIndex, SeekOrigin.Begin); - byte[] sectionData = stream.ReadBytes(readLength); - stream.Seek(originalPosition, SeekOrigin.Begin); - return sectionData; - } - + // Otherwise, return null + return null; } /// /// Get the raw bytes from a section, if possible /// - /// TODO: These can be combined and use SourceArray and SourceStream instead - public byte[] ReadRawSection(byte[] content, string sectionName, bool force = false, bool first = true, int offset = 0) + /// The name of the section to attempt to read + /// True to use the first section with a matching name, false to use the last section + /// + private byte[] ReadRawSectionFromSourceStream(string sectionName, bool first, int offset) { - // Special cases for non-forced, non-offset data - if (!force && offset == 0) - { - switch (sectionName) - { - case ".data": - return DataSectionRaw; - case ".edata": - return ExportDataSectionRaw; - case ".idata": - return ImportDataSectionRaw; - case ".rdata": - return ResourceDataSectionRaw; - case ".text": - return TextSectionRaw; - } - } + var section = first ? GetFirstSection(sectionName, true) : GetLastSection(sectionName, true); + if (section == null) + return null; + lock (this.SourceStream) + { + int startingIndex = (int)Math.Max(section.PointerToRawData + offset, 0); + int readLength = (int)Math.Min(section.VirtualSize - offset, this.SourceStream.Length); + + long originalPosition = this.SourceStream.Position; + this.SourceStream.Seek(startingIndex, SeekOrigin.Begin); + byte[] sectionData = this.SourceStream.ReadBytes(readLength); + this.SourceStream.Seek(originalPosition, SeekOrigin.Begin); + return sectionData; + } + } + + /// + /// Get the raw bytes from a section, if possible + /// + /// The name of the section to attempt to read + /// True to use the first section with a matching name, false to use the last section + /// Offset to start reading at, default is 0 + private byte[] ReadRawSectionFromSourceArray(string sectionName, bool first, int offset) + { var section = first ? GetFirstSection(sectionName, true) : GetLastSection(sectionName, true); if (section == null) return null; int startingIndex = (int)Math.Max(section.PointerToRawData + offset, 0); - int readLength = (int)Math.Min(section.VirtualSize - offset, content.Length); + int readLength = (int)Math.Min(section.VirtualSize - offset, this.SourceArray.Length); try { - return content.ReadBytes(ref startingIndex, readLength); + return this.SourceArray.ReadBytes(ref startingIndex, readLength); } catch { diff --git a/BurnOutSharp/PackerType/Armadillo.cs b/BurnOutSharp/PackerType/Armadillo.cs index c8041aab..5730b88e 100644 --- a/BurnOutSharp/PackerType/Armadillo.cs +++ b/BurnOutSharp/PackerType/Armadillo.cs @@ -26,7 +26,7 @@ namespace BurnOutSharp.PackerType foreach (var section in sections.Where(s => s != null && Encoding.ASCII.GetString(s.Name).Trim('\0').EndsWith("1"))) { string sectionName = Encoding.ASCII.GetString(section.Name).Trim('\0'); - var sectionRaw = pex.ReadRawSection(pex.SourceArray, sectionName); + var sectionRaw = pex.ReadRawSection(sectionName); var matchers = new List { // ARMDEBUG diff --git a/BurnOutSharp/ProtectionType/ActiveMARK.cs b/BurnOutSharp/ProtectionType/ActiveMARK.cs index eca23797..2a11725b 100644 --- a/BurnOutSharp/ProtectionType/ActiveMARK.cs +++ b/BurnOutSharp/ProtectionType/ActiveMARK.cs @@ -40,7 +40,7 @@ namespace BurnOutSharp.ProtectionType return null; // Get the last .bss section, if it exists - var bssSectionRaw = pex.ReadRawSection(pex.SourceArray, ".bss", first: false); + var bssSectionRaw = pex.ReadRawSection(".bss", first: false); if (bssSectionRaw != null) { var matchers = new List diff --git a/BurnOutSharp/ProtectionType/CDSHiELDSE.cs b/BurnOutSharp/ProtectionType/CDSHiELDSE.cs index 0df779ad..6448b7e8 100644 --- a/BurnOutSharp/ProtectionType/CDSHiELDSE.cs +++ b/BurnOutSharp/ProtectionType/CDSHiELDSE.cs @@ -15,7 +15,7 @@ namespace BurnOutSharp.ProtectionType return null; // Get the code/CODE section, if it exists - var codeSectionRaw = pex.ReadRawSection(pex.SourceArray, "code", first: true) ?? pex.ReadRawSection(pex.SourceArray, "CODE", first: true); + var codeSectionRaw = pex.ReadRawSection("code", first: true) ?? pex.ReadRawSection("CODE", first: true); if (codeSectionRaw != null) { var matchers = new List diff --git a/BurnOutSharp/ProtectionType/JoWood.cs b/BurnOutSharp/ProtectionType/JoWood.cs index a3459e9b..24bd7192 100644 --- a/BurnOutSharp/ProtectionType/JoWood.cs +++ b/BurnOutSharp/ProtectionType/JoWood.cs @@ -24,7 +24,7 @@ namespace BurnOutSharp.ProtectionType if (extSection) { // Get the .dcrtext section, if it exists - var dcrtextSectionRaw = pex.ReadRawSection(pex.SourceArray, ".dcrtext"); + var dcrtextSectionRaw = pex.ReadRawSection(".dcrtext"); if (dcrtextSectionRaw != null) { var matchers = new List diff --git a/BurnOutSharp/ProtectionType/SafeDisc.cs b/BurnOutSharp/ProtectionType/SafeDisc.cs index 5fccd0e3..ff436004 100644 --- a/BurnOutSharp/ProtectionType/SafeDisc.cs +++ b/BurnOutSharp/ProtectionType/SafeDisc.cs @@ -272,7 +272,7 @@ namespace BurnOutSharp.ProtectionType private string CheckSectionForProtection(string file, byte[] fileContent, bool includeDebug, PortableExecutable pex, string sectionName) { // This subtract is needed because BoG_ starts before the section - var sectionRaw = pex.ReadRawSection(fileContent, sectionName, first: true, offset: -64); + var sectionRaw = pex.ReadRawSection(sectionName, first: true, offset: -64); if (sectionRaw != null) { var matchers = new List diff --git a/BurnOutSharp/ProtectionType/SmartE.cs b/BurnOutSharp/ProtectionType/SmartE.cs index 8c4efec8..cf574291 100644 --- a/BurnOutSharp/ProtectionType/SmartE.cs +++ b/BurnOutSharp/ProtectionType/SmartE.cs @@ -33,7 +33,7 @@ namespace BurnOutSharp.ProtectionType return match; // Get the .tls section, if it exists - var tlsSectionRaw = pex.ReadRawSection(pex.SourceArray, ".tls", first: false); + var tlsSectionRaw = pex.ReadRawSection(".tls", first: false); match = GetMatchForSection(file, tlsSectionRaw, includeDebug); if (!string.IsNullOrWhiteSpace(match)) return match; diff --git a/BurnOutSharp/ProtectionType/SolidShield.cs b/BurnOutSharp/ProtectionType/SolidShield.cs index d66a1c68..a14ee224 100644 --- a/BurnOutSharp/ProtectionType/SolidShield.cs +++ b/BurnOutSharp/ProtectionType/SolidShield.cs @@ -37,7 +37,7 @@ namespace BurnOutSharp.ProtectionType return $"SolidShield Activation Manager Module {GetFileVersion(pex)}"; // Get the .init section, if it exists - var initSectionRaw = pex.ReadRawSection(pex.SourceArray, ".init", first: true); + var initSectionRaw = pex.ReadRawSection(".init", first: true); if (initSectionRaw != null) { var matchers = new List @@ -66,7 +66,7 @@ namespace BurnOutSharp.ProtectionType var sectionNames = pex.GetSectionNames(); for (int i = (sectionNames.Length >= 2 ? sectionNames.Length - 2 : 0); i < sectionNames.Length; i++) { - var nthSectionRaw = pex.ReadRawSection(pex.SourceArray, sectionNames[i], first: false); + var nthSectionRaw = pex.ReadRawSection(sectionNames[i], first: false); if (nthSectionRaw != null) { var matchers = new List diff --git a/BurnOutSharp/ProtectionType/WTMCDProtect.cs b/BurnOutSharp/ProtectionType/WTMCDProtect.cs index b28edacf..bddeace0 100644 --- a/BurnOutSharp/ProtectionType/WTMCDProtect.cs +++ b/BurnOutSharp/ProtectionType/WTMCDProtect.cs @@ -25,7 +25,7 @@ namespace BurnOutSharp.ProtectionType return "WTM Protection Viewer"; // Get the CODE section, if it exists - var codeSectionRaw = pex.ReadRawSection(pex.SourceArray, "CODE", first: true); + var codeSectionRaw = pex.ReadRawSection("CODE", first: true); if (codeSectionRaw != null) { var matchers = new List