mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-16 22:05:13 +00:00
Use content matching helper, part 2
This commit is contained in:
30
BurnOutSharp/Matching/ContentMatch.cs
Normal file
30
BurnOutSharp/Matching/ContentMatch.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace BurnOutSharp.Matching
|
||||
{
|
||||
/// <summary>
|
||||
/// Single matching criteria
|
||||
/// </summary>
|
||||
internal class ContentMatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Content to match
|
||||
/// </summary>
|
||||
public byte?[] Needle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Starting index for matching
|
||||
/// </summary>
|
||||
public int Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Ending index for matching
|
||||
/// </summary>
|
||||
public int End { get; set; }
|
||||
|
||||
public ContentMatch(byte?[] needle, int start = -1, int end = -1)
|
||||
{
|
||||
Needle = needle;
|
||||
Start = start;
|
||||
End = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
59
BurnOutSharp/Matching/Matcher.cs
Normal file
59
BurnOutSharp/Matching/Matcher.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.Matching
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper for a single set of matching criteria
|
||||
/// </summary>
|
||||
internal class Matcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of all content matches
|
||||
/// </summary>
|
||||
public IEnumerable<ContentMatch> ContentMatches { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Function to get a version for this Matcher
|
||||
/// </summary>
|
||||
public Func<string, byte[], int, string> GetVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Name of the protection to show
|
||||
/// </summary>
|
||||
public string ProtectionName { get; set; }
|
||||
|
||||
#region Constructors
|
||||
|
||||
public Matcher(byte?[] needle, string protectionName)
|
||||
: this(new List<byte?[]>() { needle }, null, protectionName) { }
|
||||
|
||||
public Matcher(List<byte?[]> needles, string protectionName)
|
||||
: this(needles, null, protectionName) { }
|
||||
|
||||
public Matcher(byte?[] needle, Func<string, byte[], int, string> getVersion, string protectionName)
|
||||
: this(new List<byte?[]>() { needle }, getVersion, protectionName) { }
|
||||
|
||||
public Matcher(List<byte?[]> needles, Func<string, byte[], int, string> getVersion, string protectionName)
|
||||
: this(needles.Select(n => new ContentMatch(n)).ToList(), getVersion, protectionName) { }
|
||||
|
||||
public Matcher(ContentMatch needle, string protectionName)
|
||||
: this(new List<ContentMatch>() { needle }, null, protectionName) { }
|
||||
|
||||
public Matcher(List<ContentMatch> needles, string protectionName)
|
||||
: this(needles, null, protectionName) { }
|
||||
|
||||
public Matcher(ContentMatch needle, Func<string, byte[], int, string> getVersion, string protectionName)
|
||||
: this(new List<ContentMatch>() { needle }, getVersion, protectionName) { }
|
||||
|
||||
public Matcher(List<ContentMatch> needles, Func<string, byte[], int, string> getVersion, string protectionName)
|
||||
{
|
||||
ContentMatches = needles;
|
||||
GetVersion = getVersion;
|
||||
ProtectionName = protectionName;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -7,16 +8,16 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
var mappings = new Dictionary<byte?[], string>
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// .nicode + (char)0x00
|
||||
[new byte?[] { 0x2E, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00 }] = "Armadillo",
|
||||
new Matcher(new byte?[] { 0x2E, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00 }, "Armadillo"),
|
||||
|
||||
// ARMDEBUG
|
||||
[new byte?[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 }] = "Armadillo",
|
||||
new Matcher(new byte?[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 }, "Armadillo"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(fileContent, mappings, includePosition);
|
||||
return Utilities.GetContentMatches(fileContent, matchers, includePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -7,13 +8,20 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
var mappings = new Dictionary<byte?[], string>
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// ??[[__[[_ + (char)0x00 + {{ + (char)0x0 + (char)0x00 + {{ + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + ?;??;??
|
||||
[new byte?[] { 0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B, 0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F, 0x3F }] = "EXE Stealth",
|
||||
new Matcher(new byte?[]
|
||||
{
|
||||
0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B,
|
||||
0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F,
|
||||
0x3F
|
||||
}, "EXE Stealth"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(fileContent, mappings, includePosition);
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -10,16 +11,19 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public bool ShouldScan(byte[] magic) => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Inno
|
||||
byte?[] check = new byte?[] { 0x49, 0x6E, 0x6E, 0x6F };
|
||||
if (fileContent.FirstPosition(check, out int position) && position == 0x30)
|
||||
return $"Inno Setup {GetVersion(fileContent)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// Inno
|
||||
new Matcher(
|
||||
new ContentMatch(new byte?[] { 0x49, 0x6E, 0x6E, 0x6F }, start: 0x30, end: 0x31),
|
||||
GetVersion,
|
||||
"Inno Setup"),
|
||||
};
|
||||
|
||||
return null;
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -42,7 +46,7 @@ namespace BurnOutSharp.PackerType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent)
|
||||
public static string GetVersion(string file, byte[] fileContent, int position)
|
||||
{
|
||||
byte[] signature = new ArraySegment<byte>(fileContent, 0x30, 12).ToArray();
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -9,23 +11,19 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Nullsoft Install System
|
||||
byte?[] check = new byte?[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d };
|
||||
if (fileContent.FirstPosition(check, out int position))
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
string version = GetVersion(fileContent, position);
|
||||
return $"NSIS {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
// Nullsoft Install System
|
||||
new Matcher(new byte?[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d }, GetVersion, "NSIS"),
|
||||
|
||||
// NullsoftInst
|
||||
check = new byte?[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x49, 0x6e, 0x73, 0x74 };
|
||||
if (fileContent.FirstPosition(check, out position))
|
||||
return $"NSIS" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
// NullsoftInst
|
||||
new Matcher(new byte?[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x49, 0x6e, 0x73, 0x74 }, "NSIS"),
|
||||
};
|
||||
|
||||
return null;
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent, int index)
|
||||
public static string GetVersion(string file, byte[] fileContent, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -10,26 +11,24 @@ namespace BurnOutSharp.PackerType
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// Another possible version string for version 1 is "PECO" (50 45 43 4F)
|
||||
|
||||
// "pec1"
|
||||
byte?[] check = new byte?[] { 0x70, 0x65, 0x63, 0x31 };
|
||||
if (fileContent.FirstPosition(check, out int position, end: 2048))
|
||||
return "PE Compact 1" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// "PEC2"
|
||||
check = new byte?[] { 0x50, 0x45, 0x43, 0x32 };
|
||||
if (fileContent.FirstPosition(check, out position, end: 2048))
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
int version = BitConverter.ToInt16(fileContent, position + 4);
|
||||
return $"PE Compact 2 v{version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
// pec1
|
||||
new Matcher(new byte?[] { 0x70, 0x65, 0x63, 0x31 }, "PE Compact 1"),
|
||||
|
||||
// "PECompact2"
|
||||
check = new byte?[] { 0x50, 0x45, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x32 };
|
||||
if (fileContent.FirstPosition(check, out position))
|
||||
return "PE Compact 2" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
// PEC2
|
||||
new Matcher(new byte?[] { 0x50, 0x45, 0x43, 0x32 }, GetVersion, "PE Compact 2 v"),
|
||||
|
||||
return null;
|
||||
// PECompact2
|
||||
new Matcher(new byte?[] { 0x50, 0x45, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x63, 0x74, 0x32 }, "PE Compact 2"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
public static string GetVersion(string file, byte[] fileContent, int position)
|
||||
{
|
||||
return BitConverter.ToInt16(fileContent, position + 4).ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -11,27 +12,17 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
/* Longer version of the check that can be used if false positves become an issue:
|
||||
"S.e.t.u.p. .F.a.c.t.o.r.y. .i.s. .a. .t.r.a.d.e.m.a.r.k. .o.f. .I.n.d.i.g.o. .R.o.s.e. .C.o.r.p.o.r.a.t.i.o.n"
|
||||
byte?[] check = new byte?[] { 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6B, 0x00, 0x20, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x52, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E }; */
|
||||
// "S.e.t.u.p. .F.a.c.t.o.r.y."
|
||||
byte?[] check = new byte?[] { 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00 };
|
||||
if (fileContent.FirstPosition(check, out int position))
|
||||
// Longer version of the check that can be used if false positves become an issue:
|
||||
// S.e.t.u.p. .F.a.c.t.o.r.y. .i.s. .a. .t.r.a.d.e.m.a.r.k. .o.f. .I.n.d.i.g.o. .R.o.s.e. .C.o.r.p.o.r.a.t.i.o.n
|
||||
// byte?[] check = new byte?[] { 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x61, 0x00, 0x20, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x72, 0x00, 0x6B, 0x00, 0x20, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6F, 0x00, 0x20, 0x00, 0x52, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x65, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E };
|
||||
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// Check the manifest version first
|
||||
string version = Utilities.GetManifestVersion(fileContent);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"Setup Factory {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
|
||||
// Then check the file version
|
||||
version = Utilities.GetFileVersion(file);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return $"Setup Factory {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
// S.e.t.u.p. .F.a.c.t.o.r.y.
|
||||
new Matcher(new byte?[] { 0x53, 0x00, 0x65, 0x00, 0x74, 0x00, 0x75, 0x00, 0x70, 0x00, 0x20, 0x00, 0x46, 0x00, 0x61, 0x00, 0x63, 0x00, 0x74, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00 }, GetVersion, "Setup Factory"),
|
||||
};
|
||||
|
||||
return $"Setup Factory (Unknown Version)" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -52,5 +43,20 @@ namespace BurnOutSharp.PackerType
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetVersion(string file, byte[] fileContent, int position)
|
||||
{
|
||||
// Check the manifest version first
|
||||
string version = Utilities.GetManifestVersion(fileContent);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
// Then check the file version
|
||||
version = Utilities.GetFileVersion(file);
|
||||
if (!string.IsNullOrEmpty(version))
|
||||
return version;
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -7,50 +9,43 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// UPX!
|
||||
byte?[] check = new byte?[] { 0x55, 0x50, 0x58, 0x21 };
|
||||
if (fileContent.FirstPosition(check, out int position))
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
string version = GetVersion(fileContent, position);
|
||||
return $"UPX {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
// UPX!
|
||||
new Matcher(new byte?[] { 0x55, 0x50, 0x58, 0x21 }, GetVersion, "Inno Setup"),
|
||||
|
||||
// NOS
|
||||
check = new byte?[] { 0x55, 0x50, 0x58, 0x21 };
|
||||
if (fileContent.FirstPosition(check, out position))
|
||||
{
|
||||
string version = GetVersion(fileContent, position);
|
||||
return $"UPX (NOS Variant) {version}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
}
|
||||
// NOS
|
||||
new Matcher(new byte?[] { 0x4E, 0x4F, 0x53 }, GetVersion, "UPX (NOS Variant)"),
|
||||
|
||||
// UPX0
|
||||
check = new byte?[] { 0x55, 0x50, 0x58, 0x30 };
|
||||
if (fileContent.FirstPosition(check, out position, end: 2048))
|
||||
{
|
||||
// UPX1
|
||||
byte?[] check2 = new byte?[] { 0x55, 0x50, 0x58, 0x31 };
|
||||
if (fileContent.FirstPosition(check2, out int position2, end: 2048))
|
||||
{
|
||||
return $"UPX (Unknown Version)" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
|
||||
}
|
||||
}
|
||||
new Matcher(
|
||||
new List<byte?[]>
|
||||
{
|
||||
// UPX0
|
||||
new byte?[] { 0x55, 0x50, 0x58, 0x30 },
|
||||
|
||||
// NOS0
|
||||
check = new byte?[] { 0x4E, 0x4F, 0x53, 0x30 };
|
||||
if (fileContent.FirstPosition(check, out position, end: 2048))
|
||||
{
|
||||
// NOS1
|
||||
byte?[] check2 = new byte?[] { 0x4E, 0x4F, 0x53, 0x31 };
|
||||
if (fileContent.FirstPosition(check2, out int position2, end: 2048))
|
||||
{
|
||||
return $"UPX (NOS Variant) (Unknown Version)" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
|
||||
}
|
||||
}
|
||||
// UPX1
|
||||
new byte?[] { 0x55, 0x50, 0x58, 0x31 },
|
||||
},
|
||||
"UPX (Unknown Version)"
|
||||
),
|
||||
|
||||
return null;
|
||||
new Matcher(
|
||||
new List<byte?[]>
|
||||
{
|
||||
// NOS0
|
||||
new byte?[] { 0x4E, 0x4F, 0x53, 0x30 },
|
||||
|
||||
// NOS1
|
||||
new byte?[] { 0x4E, 0x4F, 0x53, 0x31 },
|
||||
},
|
||||
"UPX (NOS Variant) (Unknown Version)"
|
||||
),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent, int index)
|
||||
public static string GetVersion(string file, byte[] fileContent, int index)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Matching;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
|
||||
@@ -14,13 +15,18 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
var mappings = new Dictionary<byte?[], string>
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// Software\WinRAR SFX
|
||||
[new byte?[] { 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x5C, 0x57, 0x69, 0x6E, 0x52, 0x41, 0x52, 0x20, 0x53, 0x46, 0x58 }] = "WinRAR SFX",
|
||||
new Matcher(new byte?[]
|
||||
{
|
||||
0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
|
||||
0x5C, 0x57, 0x69, 0x6E, 0x52, 0x41, 0x52, 0x20,
|
||||
0x53, 0x46, 0x58
|
||||
}, "WinRAR SFX"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(fileContent, mappings, includePosition);
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
public Dictionary<string, List<string>> Scan(Scanner scanner, string file)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Matching;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
@@ -14,17 +15,21 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
// WinZip Self-Extractor
|
||||
byte?[] check = new byte?[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70, 0x20, 0x53, 0x65, 0x6C, 0x66, 0x2D, 0x45, 0x78, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6F, 0x72 };
|
||||
if (fileContent.FirstPosition(check, out int position))
|
||||
return $"WinZip SFX {GetVersion(fileContent)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// WinZip Self-Extractor
|
||||
new Matcher(new byte?[]
|
||||
{
|
||||
0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70, 0x20, 0x53,
|
||||
0x65, 0x6C, 0x66, 0x2D, 0x45, 0x78, 0x74, 0x72,
|
||||
0x61, 0x63, 0x74, 0x6F, 0x72
|
||||
}, GetVersion, "WinZip SFX"),
|
||||
|
||||
// _winzip_
|
||||
check = new byte?[] { 0x5F, 0x77, 0x69, 0x6E, 0x7A, 0x69, 0x70, 0x5F };
|
||||
if (fileContent.FirstPosition(check, out position))
|
||||
return $"WinZip SFX {GetVersion(fileContent)}" + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
// _winzip_
|
||||
new Matcher(new byte?[] { 0x5F, 0x77, 0x69, 0x6E, 0x7A, 0x69, 0x70, 0x5F }, GetVersion, "WinZip SFX"),
|
||||
};
|
||||
|
||||
return null;
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -87,7 +92,7 @@ namespace BurnOutSharp.PackerType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(byte[] fileContent)
|
||||
public static string GetVersion(string file, byte[] fileContent, int position)
|
||||
{
|
||||
// Check the manifest version first
|
||||
string version = Utilities.GetManifestVersion(fileContent);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using BurnOutSharp.Matching;
|
||||
using Wise = WiseUnpacker.WiseUnpacker;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
@@ -13,13 +14,13 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
var mappings = new Dictionary<byte?[], string>
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// WiseMain
|
||||
[new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }] = "Wise Installation Wizard Module",
|
||||
new Matcher(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(fileContent, mappings, includePosition);
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
@@ -7,13 +8,18 @@ namespace BurnOutSharp.PackerType
|
||||
/// <inheritdoc/>
|
||||
public string CheckContents(string file, byte[] fileContent, bool includePosition = false)
|
||||
{
|
||||
var mappings = new Dictionary<byte?[], string>
|
||||
var matchers = new List<Matcher>
|
||||
{
|
||||
// DotfuscatorAttribute
|
||||
[new byte?[] { 0x44, 0x6F, 0x74, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x6F, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65 }] = "dotFuscator",
|
||||
new Matcher(new byte?[]
|
||||
{
|
||||
0x44, 0x6F, 0x74, 0x66, 0x75, 0x73, 0x63, 0x61,
|
||||
0x74, 0x6F, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69,
|
||||
0x62, 0x75, 0x74, 0x65
|
||||
}, "dotFuscator"),
|
||||
};
|
||||
|
||||
return Utilities.GetContentMatches(fileContent, mappings, includePosition);
|
||||
return Utilities.GetContentMatches(file, fileContent, matchers, includePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using BurnOutSharp.Matching;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
@@ -246,49 +247,56 @@ namespace BurnOutSharp
|
||||
#region Protection
|
||||
|
||||
/// <summary>
|
||||
/// Get simple content matches for a given protection
|
||||
/// Get content matches for a given protection
|
||||
/// </summary>
|
||||
/// <param name="file">File to check for matches</param>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="mappings">Mapping of byte array to string for matching</param>
|
||||
/// <param name="matchers">Enumerable of matchers to be run on the file</param>
|
||||
/// <param name="includePosition">True to include positional data, false otherwise</param>
|
||||
/// <returns>String representing the matched protection, null otherwise</returns>
|
||||
/// <remarks>
|
||||
/// This is useful for checks that don't do anything special with versions or other positions.
|
||||
/// TODO: Make variant of this that returns *all* content matches for later
|
||||
/// TODO: Make variant of this that can take multiple content checks per check for later
|
||||
/// </remarks>
|
||||
public static string GetContentMatches(byte[] fileContent, Dictionary<byte?[], string> mappings, bool includePosition = false)
|
||||
{
|
||||
return GetVersionedContentMatches(fileContent, mappings.Select(kvp => (kvp.Key, (Func<byte[], int, string>)null, kvp.Value)).ToList(), includePosition);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get versioned content matches for a given protection
|
||||
/// </summary>
|
||||
/// <param name="fileContent">Byte array representing the file contents</param>
|
||||
/// <param name="mappings">Tuple of matching byte array, version method, and string to output</param>
|
||||
/// <param name="includePosition">True to include positional data, false otherwise</param>
|
||||
/// <returns>String representing the matched protection, null otherwise</returns>
|
||||
/// <remarks>
|
||||
/// This is useful for checks that don't do anything special with versions or other positions.
|
||||
/// TODO: Make variant of this that returns *all* content matches for later
|
||||
/// TODO: Make variant of this that can take multiple content checks per check for later
|
||||
/// </remarks>
|
||||
public static string GetVersionedContentMatches(byte[] fileContent, List<(byte?[], Func<byte[], int, string>, string)> mappings, bool includePosition = false)
|
||||
public static string GetContentMatches(string file, byte[] fileContent, IEnumerable<Matcher> matchers, bool includePosition = false)
|
||||
{
|
||||
// If there's no mappings, we can't match
|
||||
if (mappings == null || !mappings.Any())
|
||||
if (matchers == null || !matchers.Any())
|
||||
return null;
|
||||
|
||||
// Loop through and try everything otherwise
|
||||
foreach (var mapping in mappings)
|
||||
foreach (var matcher in matchers)
|
||||
{
|
||||
if (fileContent.FirstPosition(mapping.Item1, out int position))
|
||||
// Setup for a single matcher
|
||||
bool allMatches = true;
|
||||
List<int> positions = new List<int>();
|
||||
|
||||
// Loop through all content matches and make sure all pass
|
||||
foreach (var contentMatch in matcher.ContentMatches)
|
||||
{
|
||||
string version = mapping.Item2 == null ? string.Empty : (mapping.Item2(fileContent, position) ?? "Unknown Version");
|
||||
string protection = string.IsNullOrWhiteSpace(version) ? mapping.Item3 : $"{mapping.Item3} {version}";
|
||||
return protection + (includePosition ? $" (Index {position})" : string.Empty);
|
||||
if (!fileContent.FirstPosition(contentMatch.Needle, out int position, contentMatch.Start, contentMatch.End))
|
||||
{
|
||||
allMatches = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
positions.Add(position);
|
||||
}
|
||||
}
|
||||
|
||||
// If not all matches pass, then we continue
|
||||
if (!allMatches)
|
||||
continue;
|
||||
|
||||
// Format the list of all positions found
|
||||
string positionsString = string.Join(", ", positions);
|
||||
|
||||
// If we there is no version method, just return the protection name
|
||||
if (matcher.GetVersion == null)
|
||||
return (matcher.ProtectionName ?? "Unknown Protection") + (includePosition ? $" (Index {positionsString})" : string.Empty);
|
||||
|
||||
// Otherwise, invoke the version method
|
||||
// TODO: Pass all positions to the version finding method
|
||||
string version = matcher.GetVersion(file, fileContent, positions[0]) ?? "Unknown Version";
|
||||
return $"{matcher.ProtectionName} {version}" + (includePosition ? $" (Index {positionsString})" : string.Empty);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user