Hide section complexity from content checks

This commit is contained in:
Matt Nadareski
2022-03-14 23:01:06 -07:00
parent ceae505f4d
commit 65eea4301d
9 changed files with 64 additions and 58 deletions

View File

@@ -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);
}
/// <summary>
@@ -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);
}
/// <summary>
@@ -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
/// <summary>
/// Get the raw bytes from a section, if possible
/// </summary>
/// <remarks>TODO: These can be combined and use SourceArray and SourceStream instead</remarks>
public byte[] ReadRawSection(Stream stream, string sectionName, bool force = false, bool first = true, int offset = 0)
/// <param name="sectionName">The name of the section to attempt to read</param>
/// <param name="force">True to force reading the section from the underlying source, false to use cached values, if possible</param>
/// <param name="first">True to use the first section with a matching name, false to use the last section</param>
/// <param name="offset">Offset to start reading at, default is 0</param>
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;
}
/// <summary>
/// Get the raw bytes from a section, if possible
/// </summary>
/// <remarks>TODO: These can be combined and use SourceArray and SourceStream instead</remarks>
public byte[] ReadRawSection(byte[] content, string sectionName, bool force = false, bool first = true, int offset = 0)
/// <param name="sectionName">The name of the section to attempt to read</param>
/// <param name="first">True to use the first section with a matching name, false to use the last section</param>
/// <param name="sectionName"></param>
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;
}
}
/// <summary>
/// Get the raw bytes from a section, if possible
/// </summary>
/// <param name="sectionName">The name of the section to attempt to read</param>
/// <param name="first">True to use the first section with a matching name, false to use the last section</param>
/// <param name="offset">Offset to start reading at, default is 0</param>
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
{

View File

@@ -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<ContentMatchSet>
{
// ARMDEBUG

View File

@@ -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<ContentMatchSet>

View File

@@ -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<ContentMatchSet>

View File

@@ -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<ContentMatchSet>

View File

@@ -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<ContentMatchSet>

View File

@@ -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;

View File

@@ -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<ContentMatchSet>
@@ -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<ContentMatchSet>

View File

@@ -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<ContentMatchSet>