From 10280504647e3cc662e5720bed3c9351938a549a Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Thu, 9 Sep 2021 16:29:17 -0700 Subject: [PATCH] Use resource section to find assembly manifest --- BurnOutSharp/Tools/Utilities.cs | 86 +++++++++++++++++++++++++-------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/BurnOutSharp/Tools/Utilities.cs b/BurnOutSharp/Tools/Utilities.cs index 469d1acd..34503cd8 100644 --- a/BurnOutSharp/Tools/Utilities.cs +++ b/BurnOutSharp/Tools/Utilities.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; -using System.Text; using System.Xml; +using BurnOutSharp.ExecutableType.Microsoft; +using BurnOutSharp.ExecutableType.Microsoft.Sections; +using BurnOutSharp.ExecutableType.Microsoft.Tables; using BurnOutSharp.Matching; namespace BurnOutSharp.Tools @@ -307,8 +309,14 @@ namespace BurnOutSharp.Tools /// Version string, null on error public static string GetManifestVersion(byte[] fileContent) { + // If we don't have a PE executable, just return null + PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0); + var resourceSection = pex?.ResourceSection; + if (resourceSection == null) + return null; + // Read in the manifest to a string - string manifestString = GetEmbeddedAssemblyManifest(fileContent); + string manifestString = FindAssemblyManifest(pex.ResourceSection); if (string.IsNullOrWhiteSpace(manifestString)) return null; @@ -341,8 +349,14 @@ namespace BurnOutSharp.Tools /// Version string, null on error public static string GetManifestDescription(byte[] fileContent) { + // If we don't have a PE executable, just return null + PortableExecutable pex = PortableExecutable.Deserialize(fileContent, 0); + var resourceSection = pex?.ResourceSection; + if (resourceSection == null) + return null; + // Read in the manifest to a string - string manifestString = GetEmbeddedAssemblyManifest(fileContent); + string manifestString = FindAssemblyManifest(pex.ResourceSection); if (string.IsNullOrWhiteSpace(manifestString)) return null; @@ -368,29 +382,59 @@ namespace BurnOutSharp.Tools } /// - /// Get the embedded assembly manifest + /// Find the assembly manifest from a resource section, if possible /// - /// Byte array representing the file contents - /// Embedded assembly manifest as a string, if possible - /// - /// TODO: How do we find the manifest specifically better - /// TODO: This should be derived specifically in the .rsrc section - /// - private static string GetEmbeddedAssemblyManifest(byte[] fileContent) + /// ResourceSection from the executable + /// Full assembly manifest, null on error + private static string FindAssemblyManifest(ResourceSection rs) { - // - byte?[] manifestEnd = new byte?[] { 0x3C, 0x2F, 0x61, 0x73, 0x73, 0x65, 0x6D, 0x62, 0x6C, 0x79, 0x3E }; - if (!fileContent.FirstPosition(manifestEnd, out int manifestEndPosition, start: manifestStartPosition)) + return FindAssemblyManifest(rs.ResourceDirectoryTable); + } + + /// + /// Find the assembly manifest from a resource directory table, if possible + /// + /// ResourceDirectoryTable representing a layer + /// Full assembly manifest, null on error + private static string FindAssemblyManifest(ResourceDirectoryTable rdt) + { + if (rdt == null) return null; - // Read in the manifest to a string - int manifestLength = manifestEndPosition + "".Length - manifestStartPosition; - return Encoding.ASCII.GetString(fileContent, manifestStartPosition, manifestLength); + foreach (var rdte in rdt.NamedEntries) + { + if (rdte.IsResourceDataEntry() && rdte.DataEntry != null) + { + if (rdte.DataEntry.EncodedData.StartsWith(" @@ -417,7 +461,7 @@ namespace BurnOutSharp.Tools // Try to read the assembly node return manifestDoc["assembly"]; } - catch + catch (Exception ex) { return null; }