mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-04-24 15:13:23 +00:00
Add header padding strings
This commit is contained in:
@@ -352,6 +352,33 @@ namespace BurnOutSharp.Wrappers
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Header padding strings, if they exist
|
||||
/// </summary>
|
||||
public List<string> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overlay data, if it exists
|
||||
/// </summary>
|
||||
@@ -663,6 +690,11 @@ namespace BurnOutSharp.Wrappers
|
||||
/// </summary>
|
||||
private byte[] _headerPaddingData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Header padding data, if it exists
|
||||
/// </summary>
|
||||
private List<string> _headerPaddingStrings = null;
|
||||
|
||||
/// <summary>
|
||||
/// Overlay data, if it exists
|
||||
/// </summary>
|
||||
|
||||
@@ -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);
|
||||
|
||||
/// <inheritdoc/>
|
||||
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<ContentMatchSet>
|
||||
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;
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace BurnOutSharp.ProtectionType
|
||||
List<string> resultsList = new List<string>();
|
||||
|
||||
// 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<ContentMatchSet>
|
||||
{
|
||||
// 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<string> sectionStrings, byte[] sectionRaw)
|
||||
{
|
||||
// Get the section strings, if they exist
|
||||
List<string> 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<ContentMatchSet>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user