diff --git a/BurnOutSharp.Wrappers/PortableExecutable.cs b/BurnOutSharp.Wrappers/PortableExecutable.cs
index 748345c2..1757ce01 100644
--- a/BurnOutSharp.Wrappers/PortableExecutable.cs
+++ b/BurnOutSharp.Wrappers/PortableExecutable.cs
@@ -352,6 +352,33 @@ namespace BurnOutSharp.Wrappers
}
}
+ ///
+ /// Header padding strings, if they exist
+ ///
+ public List HeaderPaddingStrings
+ {
+ get
+ {
+ lock (_sourceDataLock)
+ {
+ // If we already have cached data, just use that immediately
+ if (_headerPaddingStrings != null)
+ return _headerPaddingStrings;
+
+ // TODO: Don't scan the known header data as well
+
+ // Populate the raw header padding data based on the source
+ uint headerStartAddress = Stub_NewExeHeaderAddr;
+ uint firstSectionAddress = SectionTable.Select(s => s.PointerToRawData).Where(s => s != 0).OrderBy(s => s).First();
+ int headerLength = (int)(firstSectionAddress - headerStartAddress);
+ _headerPaddingStrings = ReadStringsFromDataSource((int)headerStartAddress, headerLength, charLimit: 3);
+
+ // Cache and return the header padding data, even if null
+ return _headerPaddingStrings;
+ }
+ }
+ }
+
///
/// Overlay data, if it exists
///
@@ -663,6 +690,11 @@ namespace BurnOutSharp.Wrappers
///
private byte[] _headerPaddingData = null;
+ ///
+ /// Header padding data, if it exists
+ ///
+ private List _headerPaddingStrings = null;
+
///
/// Overlay data, if it exists
///
diff --git a/BurnOutSharp/PackerType/UPX.cs b/BurnOutSharp/PackerType/UPX.cs
index 2f6c53e1..670bd581 100644
--- a/BurnOutSharp/PackerType/UPX.cs
+++ b/BurnOutSharp/PackerType/UPX.cs
@@ -1,7 +1,9 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
using BurnOutSharp.Interfaces;
using BurnOutSharp.Matching;
using BurnOutSharp.Wrappers;
@@ -12,6 +14,10 @@ namespace BurnOutSharp.PackerType
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class UPX : IPortableExecutableCheck, IScannable
{
+ private static readonly Regex _oldUpxVersionMatch = new Regex(@"\$Id: UPX (.*?) Copyright \(C\)", RegexOptions.Compiled);
+
+ private static readonly Regex _upxVersionMatch = new Regex(@"^([0-9]\.[0-9]{2})$", RegexOptions.Compiled);
+
///
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
@@ -20,22 +26,40 @@ namespace BurnOutSharp.PackerType
if (sections == null)
return null;
- // Check header padding data
- var headerPaddingData = pex.HeaderPaddingData;
- if (headerPaddingData != null)
+ // Check header padding strings
+ if (pex.HeaderPaddingStrings.Any())
{
- var matchers = new List
+ string match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.Contains("UPX!"));
+ //if (match != null)
+ // return "UPX";
+
+ match = pex.HeaderPaddingStrings.FirstOrDefault(s => s.StartsWith("$Id: UPX"));
+ if (match != null)
{
- // UPX!
- new ContentMatchSet(new byte?[] { 0x55, 0x50, 0x58, 0x21 }, GetVersion, "UPX"),
+ var regexMatch = _oldUpxVersionMatch.Match(match);
+ if (regexMatch.Success)
+ return $"UPX {regexMatch.Groups[1].Value}";
+ else
+ return "UPX (Unknown Version)";
+ }
- // NOS
- new ContentMatchSet(new byte?[] { 0x4E, 0x4F, 0x53, 0x20 }, GetVersion, "UPX (NOS Variant)"),
- };
-
- string match = MatchUtil.GetFirstMatch(file, headerPaddingData, matchers, includeDebug);
- if (!string.IsNullOrEmpty(match))
- return match;
+ match = pex.HeaderPaddingStrings.FirstOrDefault(s => _upxVersionMatch.IsMatch(s));
+ if (pex.HeaderPaddingStrings.Any(s => s == "UPX!" && match != null))
+ {
+ var regexMatch = _upxVersionMatch.Match(match);
+ if (regexMatch.Success)
+ return $"UPX {regexMatch.Groups[1].Value}";
+ else
+ return "UPX (Unknown Version)";
+ }
+ else if (pex.HeaderPaddingStrings.Any(s => s == "NOS " && match != null))
+ {
+ var regexMatch = _upxVersionMatch.Match(match);
+ if (regexMatch.Success)
+ return $"UPX (NOS Variant) {regexMatch.Groups[1].Value}";
+ else
+ return "UPX (NOS Variant) (Unknown Version)";
+ }
}
return null;
diff --git a/BurnOutSharp/ProtectionType/Macrovision.cs b/BurnOutSharp/ProtectionType/Macrovision.cs
index f85dbee0..6fe77315 100644
--- a/BurnOutSharp/ProtectionType/Macrovision.cs
+++ b/BurnOutSharp/ProtectionType/Macrovision.cs
@@ -66,7 +66,7 @@ namespace BurnOutSharp.ProtectionType
List resultsList = new List();
// Check the header padding
- string match = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingData);
+ string match = CheckSectionForProtection(file, includeDebug, pex.HeaderPaddingStrings, pex.HeaderPaddingData);
if (!string.IsNullOrWhiteSpace(match))
{
resultsList.Add(match);
@@ -74,7 +74,7 @@ namespace BurnOutSharp.ProtectionType
else
{
// Get the .data section, if it exists
- match = CheckSectionForProtection(file, includeDebug, pex, ".data");
+ match = CheckSectionForProtection(file, includeDebug, pex.GetFirstSectionStrings(".data"), pex.GetFirstSectionData(".data"));
if (!string.IsNullOrWhiteSpace(match))
resultsList.Add(match);
}
@@ -184,39 +184,16 @@ namespace BurnOutSharp.ProtectionType
return $"{version}.{subVersion:00}.{subsubVersion:000}";
}
- private string CheckSectionForProtection(string file, bool includeDebug, byte[] sectionRaw)
- {
- // If we have null section data
- if (sectionRaw == null)
- return null;
-
- var matchers = new List
- {
- // BoG_ *90.0&!! Yy>
- new ContentMatchSet(new byte?[]
- {
- 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30,
- 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59,
- 0x79, 0x3E
- }, GetMacrovisionVersion, "SafeCast/SafeDisc"),
- };
-
- return MatchUtil.GetFirstMatch(file, sectionRaw, matchers, includeDebug);
- }
-
- private string CheckSectionForProtection(string file, bool includeDebug, PortableExecutable pex, string sectionName)
+ private string CheckSectionForProtection(string file, bool includeDebug, List sectionStrings, byte[] sectionRaw)
{
// Get the section strings, if they exist
- List strs = pex.GetFirstSectionStrings(sectionName);
- if (strs == null)
+ if (sectionStrings == null)
return null;
// If we don't have the "BoG_" string
- if (!strs.Any(s => s.Contains("BoG_ *90.0&!! Yy>")))
+ if (!sectionStrings.Any(s => s.Contains("BoG_ *90.0&!! Yy>")))
return null;
- byte[] sectionRaw = pex.GetFirstSectionData(sectionName);
-
// TODO: Add more checks to help differentiate between SafeDisc and SafeCast.
var matchers = new List
{