From a9c71ced47030fb7026cccd92d52cecb080694ab Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Fri, 9 Dec 2022 11:53:58 -0800 Subject: [PATCH] Add skelton for section string finding --- BurnOutSharp.Wrappers/PortableExecutable.cs | 144 ++++++++++++++++++++ BurnOutSharp.Wrappers/WrapperBase.cs | 20 ++- 2 files changed, 163 insertions(+), 1 deletion(-) diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs index 715ff7de..d68b5363 100644 --- a/BurnOutSharp.Wrappers/PortableExecutable.cs +++ b/BurnOutSharp.Wrappers/PortableExecutable.cs @@ -683,6 +683,11 @@ namespace BurnOutSharp.Wrappers /// private byte[][] _sectionData = null; + /// + /// Cached found string data in sections + /// + private List[] _sectionStringData = null; + /// /// Cached resource data /// @@ -3183,6 +3188,145 @@ namespace BurnOutSharp.Wrappers } } + /// + /// Get the first section strings based on name, if possible + /// + /// Name of the section to check for + /// True to enable exact matching of names, false for starts-with + /// Section strings on success, null on error + public List GetFirstSectionStrings(string name, bool exact = false) + { + // If we have no sections + if (SectionTable == null || !SectionTable.Any()) + return null; + + // If the section doesn't exist + if (!ContainsSection(name, exact)) + return null; + + // Get the first index of the section + int index = Array.IndexOf(SectionNames, name); + if (index == -1) + return null; + + // Get the section data from the table + var section = SectionTable[index]; + uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable); + if (address == 0) + return null; + + // Set the section size + uint size = section.SizeOfRawData; + lock (_sourceDataLock) + { + // Create the section string array if we have to + if (_sectionStringData == null) + _sectionStringData = new List[SectionNames.Length]; + + // If we already have cached data, just use that immediately + if (_sectionStringData[index] != null) + return _sectionStringData[index]; + + // Populate the section string data based on the source + List sectionStringData = ReadStringsFromDataSource((int)address, (int)size); + + // Cache and return the section string data, even if null + _sectionStringData[index] = sectionStringData; + return sectionStringData; + } + } + + /// + /// Get the last section strings based on name, if possible + /// + /// Name of the section to check for + /// True to enable exact matching of names, false for starts-with + /// Section strings on success, null on error + public List GetLastSectionStrings(string name, bool exact = false) + { + // If we have no sections + if (SectionTable == null || !SectionTable.Any()) + return null; + + // If the section doesn't exist + if (!ContainsSection(name, exact)) + return null; + + // Get the last index of the section + int index = Array.LastIndexOf(SectionNames, name); + if (index == -1) + return null; + + // Get the section data from the table + var section = SectionTable[index]; + uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable); + if (address == 0) + return null; + + // Set the section size + uint size = section.SizeOfRawData; + lock (_sourceDataLock) + { + // Create the section string array if we have to + if (_sectionStringData == null) + _sectionStringData = new List[SectionNames.Length]; + + // If we already have cached data, just use that immediately + if (_sectionStringData[index] != null) + return _sectionStringData[index]; + + // Populate the section string data based on the source + List sectionStringData = ReadStringsFromDataSource((int)address, (int)size); + + // Cache and return the section string data, even if null + _sectionStringData[index] = sectionStringData; + return sectionStringData; + } + } + + /// + /// Get the section strings based on index, if possible + /// + /// Name of the section to check for + /// True to enable exact matching of names, false for starts-with + /// Section strings on success, null on error + public List GetSectionStrings(int index) + { + // If we have no sections + if (SectionTable == null || !SectionTable.Any()) + return null; + + // If the section doesn't exist + if (index < 0 || index >= SectionTable.Length) + return null; + + // Get the section data from the table + var section = SectionTable[index]; + uint address = section.VirtualAddress.ConvertVirtualAddress(SectionTable); + if (address == 0) + return null; + + // Set the section size + uint size = section.SizeOfRawData; + lock (_sourceDataLock) + { + // Create the section string array if we have to + if (_sectionStringData == null) + _sectionStringData = new List[SectionNames.Length]; + + // If we already have cached data, just use that immediately + if (_sectionStringData[index] != null) + return _sectionStringData[index]; + + // Populate the section string data based on the source + List sectionStringData = ReadStringsFromDataSource((int)address, (int)size); + + // Cache and return the section string data, even if null + _sectionStringData[index] = sectionStringData; + return sectionStringData; + } + } + #endregion } } \ No newline at end of file diff --git a/BurnOutSharp.Wrappers/WrapperBase.cs b/BurnOutSharp.Wrappers/WrapperBase.cs index ca4dd15e..f776dc5f 100644 --- a/BurnOutSharp.Wrappers/WrapperBase.cs +++ b/BurnOutSharp.Wrappers/WrapperBase.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using static BurnOutSharp.Builder.Extensions; @@ -93,7 +94,7 @@ namespace BurnOutSharp.Wrappers /// Byte array containing the requested data, null on error protected byte[] ReadFromDataSource(int position, int length) { - // Validate the data souece + // Validate the data source if (!DataSourceIsValid()) return null; @@ -121,6 +122,23 @@ namespace BurnOutSharp.Wrappers return sectionData; } + /// + /// Read string data from the source + /// + /// Position in the source to read from + /// Length of the requested data + /// String list containing the requested data, null on error + protected List ReadStringsFromDataSource(int position, int length) + { + // Read the data as a byte array first + byte[] sourceData = ReadFromDataSource(position, length); + if (sourceData == null) + return null; + + // TODO: Complete implementation of string finding + return null; + } + /// /// Get the ending offset of the source ///