diff --git a/BurnOutSharp/PackerType/UPX.cs b/BurnOutSharp/PackerType/UPX.cs
index e8c1bce3..a5bdf03c 100644
--- a/BurnOutSharp/PackerType/UPX.cs
+++ b/BurnOutSharp/PackerType/UPX.cs
@@ -1,53 +1,60 @@
using System.Collections.Generic;
+using System.Linq;
using System.Text;
+using BurnOutSharp.ExecutableType.Microsoft;
using BurnOutSharp.Matching;
+using BurnOutSharp.Tools;
namespace BurnOutSharp.PackerType
{
public class UPX : IContentCheck
{
///
- public List GetContentMatchSets()
- {
- return new List
- {
- // UPX!
- new ContentMatchSet(new byte?[] { 0x55, 0x50, 0x58, 0x21 }, GetVersion, "UPX"),
-
- // NOS
- new ContentMatchSet(
- new ContentMatch(new byte?[] { 0x4E, 0x4F, 0x53, 0x20 }, end: 2048),
- GetVersion,
- "UPX (NOS Variant)"),
-
- new ContentMatchSet(
- new List
- {
- // UPX0
- new byte?[] { 0x55, 0x50, 0x58, 0x30 },
-
- // UPX1
- new byte?[] { 0x55, 0x50, 0x58, 0x31 },
- },
- "UPX (Unknown Version)"
- ),
-
- new ContentMatchSet(
- new List
- {
- // NOS0
- new byte?[] { 0x4E, 0x4F, 0x53, 0x30 },
-
- // NOS1
- new byte?[] { 0x4E, 0x4F, 0x53, 0x31 },
- },
- "UPX (NOS Variant) (Unknown Version)"
- ),
- };
- }
+ public List GetContentMatchSets() => null;
///
- public string CheckContents(string file, byte[] fileContent, bool includeDebug = false) => null;
+ public string CheckContents(string file, byte[] fileContent, bool includeDebug = false)
+ {
+ // Get the sections from the executable, if possible
+ PEExecutable pex = PEExecutable.Deserialize(fileContent, 0);
+ var sections = pex?.SectionHeaders;
+ if (sections == null)
+ return null;
+
+ // Standard UPX
+ int foundPosition = FindData(fileContent, sections, "UPX");
+ if (foundPosition > -1)
+ {
+ var matchers = new List
+ {
+ // UPX!
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0x55, 0x50, 0x58, 0x21 }, end: foundPosition),
+ GetVersion,
+ "UPX"),
+ };
+
+ return MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ }
+
+ // NOS Variant
+ foundPosition = FindData(fileContent, sections, "NOS");
+ if (foundPosition > -1)
+ {
+ var matchers = new List
+ {
+ // NOS
+ new ContentMatchSet(
+ new ContentMatch(new byte?[] { 0x4E, 0x4F, 0x53, 0x20 }, end: foundPosition),
+ GetVersion,
+ "UPX (NOS Variant)"),
+ };
+
+ return MatchUtil.GetFirstMatch(file, fileContent, matchers, includeDebug);
+ }
+
+ return null;
+ }
public static string GetVersion(string file, byte[] fileContent, List positions)
{
@@ -66,5 +73,26 @@ namespace BurnOutSharp.PackerType
return "(Unknown Version)";
}
}
+
+ ///
+ /// Find the location of the first matched section, if possible
+ ///
+ /// Byte array representing the file contents
+ /// Array of sections to check against
+ /// Prefix of the sections to check for
+ /// Real address of the section data, -1 on error
+ private int FindData(byte[] fileContent, IMAGE_SECTION_HEADER[] sections, string sectionPrefix)
+ {
+ // Get the two matching sections, if possible
+ var firstSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith($"{sectionPrefix}0"));
+ var secondSection = sections.FirstOrDefault(s => Encoding.ASCII.GetString(s.Name).StartsWith($"{sectionPrefix}1"));
+
+ // If either section is null, we can't do anything
+ if (firstSection == null || secondSection == null)
+ return -1;
+
+ // Return the first section address
+ return (int)EVORE.ConvertVirtualAddress(firstSection.VirtualAddress, sections);
+ }
}
}
\ No newline at end of file