Move packer scans to their own library

This commit is contained in:
Matt Nadareski
2023-03-09 23:52:58 -05:00
parent 95755b930d
commit 439c141c2c
30 changed files with 41 additions and 31 deletions

View File

@@ -0,0 +1,659 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class ASPack : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .aspack section, if it exists
bool aspackSection = pex.ContainsSection(".aspack", exact: true);
if (aspackSection)
return "ASPack 2.29";
// TODO: Re-enable all Entry Point checks after implementing
// Use the entry point data, if it exists
// if (pex.EntryPointRaw != null)
// {
// var matchers = GenerateMatchers();
// string match = MatchUtil.GetFirstMatch(file, pex.EntryPointRaw, matchers, includeDebug);
// if (!string.IsNullOrWhiteSpace(match))
// return match;
// }
// Get the .adata* section, if it exists
var adataSection = pex.GetFirstSection(".adata", exact: false);
if (adataSection != null)
{
var adataSectionRaw = pex.GetFirstSectionData(Encoding.UTF8.GetString(adataSection.Name));
if (adataSectionRaw != null)
{
var matchers = GenerateMatchers();
string match = MatchUtil.GetFirstMatch(file, adataSectionRaw, matchers, includeDebug);
if (!string.IsNullOrWhiteSpace(match))
return match;
}
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
/// <summary>
/// Generate the set of matchers used for each section
/// </summary>
/// <returns></returns>
private List<ContentMatchSet> GenerateMatchers()
{
return new List<ContentMatchSet>
{
#region No Wildcards (Long)
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x92, 0x1A, 0x44, 0x00, 0xB8, 0x8C, 0x1A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xCD, 0x1D,
0x44, 0x00, 0x89, 0x85, 0xD9, 0x1D, 0x44, 0x00,
0x80, 0xBD, 0xC4, 0x1D, 0x44,
}, "ASPack 1.00b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
0x80, 0xBD, 0x9C, 0x2E, 0x44, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x9C, 0x2E, 0x44, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xE4, 0x01, 0x00,
0x00, 0xE8, 0x7A, 0x02, 0x00, 0x00, 0x8B, 0x85,
0x9D, 0x2E, 0x44, 0x00, 0x03, 0x85, 0xB1, 0x2E,
0x44, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.01b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, 0x00, 0xB8, 0xCC, 0x2A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, 0x00, 0x89, 0x85, 0xB1, 0x2E, 0x44, 0x00,
0x80, 0xBD, 0x9C, 0x2E, 0x44
}, "ASPack 1.01b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0xF7, 0x01, 0x00,
0x00, 0xE8, 0x8E, 0x02, 0x00, 0x00, 0x8B, 0x85,
0x75, 0x7C, 0x43, 0x00, 0x03, 0x85, 0x89, 0x7C,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.02b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, 0x00, 0x89, 0x85, 0x89, 0x7C, 0x43, 0x00,
0x80, 0xBD, 0x74, 0x7C, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x74, 0x7C, 0x43
}, "ASPack 1.02b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x8A, 0x1C, 0x40, 0x00, 0xB9, 0x9E, 0x00,
0x00, 0x00, 0x8D, 0xBD, 0x4C, 0x23, 0x40, 0x00,
0x8B, 0xF7, 0x33
}, "ASPack 1.02b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, 0x00, 0xB8, 0x90, 0x78,
0x43, 0x00, 0x03, 0xC5
}, "ASPack 1.02b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xAE, 0x98, 0x43, 0x00, 0xB8, 0xA8, 0x98,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
0x43, 0x00, 0x89, 0x85, 0x24, 0x9D, 0x43, 0x00,
0x80, 0xBD, 0x0E, 0x9D, 0x43
}, "ASPack 1.03b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xCE, 0x3A, 0x44, 0x00, 0xB8, 0xC8, 0x3A,
0x44, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
0x44, 0x00, 0x89, 0x85, 0xC1, 0x3E, 0x44, 0x00,
0x80, 0xBD, 0xAC, 0x3E, 0x44
}, "ASPack 1.05b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x73, 0x02, 0x00,
0x00, 0xE8, 0x0A, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x70, 0xAD, 0x43, 0x00, 0x03, 0x85, 0x84, 0xAD,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.06.01b (DLL)"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, 0x00, 0xB8, 0xE4, 0xA8,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, 0x00, 0x89, 0x85, 0x84, 0xAD, 0x43, 0x00,
0x80, 0xBD, 0x6E, 0xAD, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x6E, 0xAD, 0x43
}, "ASPack 1.06.01b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, 0xD9,
0x43, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.07b (DLL)"),
new ContentMatchSet(new byte?[]
{
0x60, 0xEB, 0x03, 0x5D, 0xFF, 0xE5, 0xE8, 0xF8,
0xFF, 0xFF, 0xFF, 0x81, 0xED, 0x1B, 0x6A, 0x44,
0x00, 0xBB, 0x10, 0x6A, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D, 0x2A
}, "ASPack 1.08"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E, 0x44, 0x00, 0x0F,
0x85, 0x17, 0x05, 0x00, 0x00, 0x8D, 0x85, 0xD1,
0x50, 0x44, 0x00, 0x50, 0xFF, 0x95, 0x94, 0x51,
0x44, 0x00, 0x89, 0x85, 0xCD, 0x50, 0x44, 0x00,
0x8B, 0xF8, 0x8D, 0x9D, 0xDE, 0x50, 0x44, 0x00,
0x53, 0x50, 0xFF, 0x95, 0x90, 0x51, 0x44, 0x00
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x0A, 0x4A, 0x44, 0x00, 0xBB, 0x04, 0x4A,
0x44, 0x00, 0x03, 0xDD
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x33,
0x87, 0xDB, 0x90, 0x00
}, "ASPack 2.00.01"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
0xFF, 0x03, 0xDD, 0x81, 0xEB
}, "ASPack 2.1"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, 0x3D, 0x04, 0x00, 0x00
}, "ASPack 2.11b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55
}, "ASPack 2.11b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, 0x59, 0x04, 0x00, 0x00
}, "ASPack 2.11c"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xCD, 0x20,
0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x2B, 0xC9,
0x58, 0x74, 0x02
}, "ASPack 2.11d"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
}, "ASPack 2.12"),
#endregion
#region Wildcards (Long)
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, null, 0xB8, 0x38, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, null, 0x89, 0x85, 0x17, 0xDE, 0x43, null,
0x80, 0xBD, 0x01, 0xDE, 0x43, null, null, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, null, 0xE8,
0x1D, null, null, null, 0xE8, 0x79, 0x02, null,
null, 0xE8, 0x12, 0x03, null, null, 0x8B, 0x85,
0x03, 0xDE, 0x43, null, 0x03, 0x85, 0x17, 0xDE,
0x43, null, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.00b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xD2, 0x2A, 0x44, null, 0xB8, 0xCC, 0x2A,
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xA5, 0x2E,
0x44, null, 0x89, 0x85, 0xB1, 0x2E, 0x44, null,
0x80, 0xBD, 0x9C, 0x2E, 0x44
}, "ASPack 1.01b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xCE, 0x3A, 0x44, null, 0xB8, 0xC8, 0x3A,
0x44, null, 0x03, 0xC5, 0x2B, 0x85, 0xB5, 0x3E,
0x44, null, 0x89, 0x85, 0xC1, 0x3E, 0x44, null,
0x80, 0xBD, 0xAC, 0x3E, 0x44
}, "ASPack 1.01b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, 0x3E, 0xD9, 0x43, 0x00, 0xB8, 0x38, null,
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, 0x0B, 0xDE,
0x43, 0x00, 0x89, 0x85, 0x17, 0xDE, 0x43, 0x00,
0x80, 0xBD, 0x01, 0xDE, 0x43, 0x00, 0x00, 0x75,
0x15, 0xFE, 0x85, 0x01, 0xDE, 0x43, 0x00, 0xE8,
0x1D, 0x00, 0x00, 0x00, 0xE8, 0x79, 0x02, 0x00,
0x00, 0xE8, 0x12, 0x03, 0x00, 0x00, 0x8B, 0x85,
0x03, 0xDE, 0x43, 0x00, 0x03, 0x85, 0x17, 0xDE,
0x43, 0x00, 0x89, 0x44, 0x24, 0x1C, 0x61, 0xFF
}, "ASPack 1.02a -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x06, null, null, null, 0x64, 0xA0, 0x23
}, "ASPack 1.02a"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0x96, 0x78, 0x43, null, 0xB8, 0x90, 0x78,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x7D, 0x7C,
0x43, null, 0x89, 0x85, 0x89, 0x7C, 0x43, null,
0x80, 0xBD, 0x74, 0x7C, 0x43
}, "ASPack 1.02b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xAE, 0x98, 0x43, null, 0xB8, 0xA8, 0x98,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x18, 0x9D,
0x43, null, 0x89, 0x85, 0x24, 0x9D, 0x43, null,
0x80, 0xBD, 0x0E, 0x9D, 0x43
}, "ASPack 1.03b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xE8, 0x0D, null,
null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, 0x58
}, "ASPack 1.03b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81,
0xED, null, null, null, 0x00, 0xB8, null, null,
null, 0x00, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, 0x00,
0x80, 0xBD, 0x08, 0x9D, null, 0x00, 0x00
}, "ASPack 1.04b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x12,
0x9D, null, 0x89, 0x85, 0x1E, 0x9D, null, null,
0x80, 0xBD, 0x08, 0x9D
}, "ASPack 1.04b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5, 0x2B, 0x85, null, 0x0B,
0xDE, null, 0x89, 0x85, 0x17, 0xDE, null, null,
0x80, 0xBD, 0x01, 0xDE
}, "ASPack 1.04b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, 0xEA, 0xA8, 0x43, null, 0xB8, 0xE4, 0xA8,
0x43, null, 0x03, 0xC5, 0x2B, 0x85, 0x78, 0xAD,
0x43, null, 0x89, 0x85, 0x84, 0xAD, 0x43, null,
0x80, 0xBD, 0x6E, 0xAD, 0x43
}, "ASPack 1.06.1b"),
new ContentMatchSet(new byte?[]
{
0x90, 0x61, 0xBE, null, null, null, null, 0x8D,
0xBE, null, null, null, null, 0x57, 0x83, 0xCD,
0xFF
}, "ASPack 1.06.1b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xB8, null, null,
null, null, 0x03, 0xC5
}, "ASPack 1.07b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, null, null, null, null, 0x5D, 0x81,
0xED, null, null, null, null, 0x60, 0xE8, 0x2B,
0x03, 0x00, 0x00
}, "ASPack 1.07b"),
new ContentMatchSet(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D
}, "ASPack 1.08.01"),
new ContentMatchSet(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, null, null, null, 0x44,
null, 0xBB, 0x10, null, 0x44, null, 0x03, 0xDD,
0x2B, 0x9D
}, "ASPack 1.08.01"),
new ContentMatchSet(new byte?[]
{
0x60, 0xEB, 0x0A, 0x5D, 0xEB, 0x02, 0xFF, 0x25,
0x45, 0xFF, 0xE5, 0xE8, 0xE9, 0xE8, 0xF1, 0xFF,
0xFF, 0xFF, 0xE9, 0x81, 0xED, 0x23, 0x6A, 0x44,
0x00, 0xBB, 0x10, null, 0x44, 0x00, 0x03, 0xDD,
0x2B, 0x9D, 0x72
}, "ASPack 1.08.02"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xBB, null, null,
null, null, 0x03, 0xDD, 0x2B, 0x9D, 0xB1, 0x50,
0x44, 0x00, 0x83, 0xBD, 0xAC, 0x50, 0x44, 0x00,
0x00, 0x89, 0x9D, 0xBB, 0x4E
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, null,
null, null, null, null, null, 0xBB, null, null,
null, null, 0x03, 0xDD
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x55, 0x57, 0x51, 0x53, 0xE8, null, null, null,
null, 0x5D, 0x8B, 0xC5, 0x81, 0xED, null, null,
null, null, 0x2B, 0x85, null, null, null, null,
0x83, 0xE8, 0x09, 0x89, 0x85, null, null, null,
null, 0x0F, 0xB6
}, "ASPack 1.08.03"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE9, null, null, null, null, 0xEF, 0x40,
0x03, 0xA7, 0x07, 0x8F, 0x07, 0x1C, 0x37, 0x5D,
0x43, 0xA7, 0x04, 0xB9, 0x2C, 0x3A
}, "ASPack 1.08.x"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x02, 0x00, 0x00, 0x00, 0xEB, 0x09,
0x5D, 0x55, 0x81, 0xED, 0x39, 0x39, 0x44, 0x00,
0xC3, 0xE9, null, 0x04, 0x00, 0x00
}, "ASPack 2.11.x -> Alexey Solodovnikov"),
new ContentMatchSet(new byte?[]
{
null, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01
}, "ASPack 2.12 (without Poly) -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, null,
null, 0x00, 0x83, 0xBD, 0x22, 0x04, 0x00, 0x00,
0x00, 0x89, 0x9D, 0x22, 0x04, 0x00, 0x00, 0x0F,
0x85, 0x65, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x2E,
0x04, 0x00, 0x00, 0x50, 0xFF, 0x95, 0x4C, 0x0F,
0x00, 0x00, 0x89, 0x85, 0x26, 0x04, 0x00, 0x00,
0x8B, 0xF8, 0x8D, 0x5D, 0x5E, 0x53, 0x50, 0xFF,
0x95, 0x48, 0x0F, 0x00, 0x00, 0x89, 0x85, 0x4C,
0x05, 0x00, 0x00, 0x8D, 0x5D, 0x6B, 0x53, 0x57,
0xFF, 0x95, 0x48, 0x0F
}, "ASPack 2.12b -> Solodovnikov Alexey"),
new ContentMatchSet(new byte?[]
{
0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9, 0xEB,
0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01, 0x00,
0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xED, 0xFF, 0xFF,
0xFF, 0x03, 0xDD, null, null, null, null, null,
null, 0x83, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0x00,
0x89, 0x9D, 0x7D, 0x04, 0x00, 0x00, 0x0F, 0x85,
0xC0, 0x03, 0x00, 0x00, 0x8D, 0x85, 0x89, 0x04,
0x00, 0x00, 0x50, 0xFF, 0x95, 0x09, 0x0F, 0x00,
0x00, 0x89, 0x85, 0x81, 0x04, 0x00, 0x00, 0x8B,
0xF0, 0x8D, 0x7D, 0x51, 0x57, 0x56, 0xFF, 0x95,
0x05, 0x0F, 0x00, 0x00, 0xAB, 0xB0, 0x00, 0xAE,
0x75, 0xFD, 0x38, 0x07, 0x75, 0xEE, 0x8D, 0x45,
0x7A, 0xFF, 0xE0, 0x56, 0x69, 0x72, 0x74, 0x75,
0x61, 0x6C, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x00,
0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x46,
0x72, 0x65, 0x65, 0x00, 0x56, 0x69, 0x72, 0x74,
0x75, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65,
0x63, 0x74, 0x00, 0x00, 0x8B, 0x9D, 0x8D, 0x05,
0x00, 0x00, 0x0B, 0xDB, 0x74, 0x0A, 0x8B, 0x03,
0x87, 0x85, 0x91, 0x05, 0x00, 0x00, 0x89, 0x03,
0x8D, 0xB5, 0xBD, 0x05, 0x00, 0x00, 0x83, 0x3E,
0x00, 0x0F, 0x84, 0x15, 0x01, 0x00, 0x00, 0x6A,
0x04, 0x68, 0x00, 0x10, 0x00, 0x00, 0x68, 0x00,
0x18, 0x00, 0x00, 0x6A, 0x00, 0xFF, 0x55, 0x51,
0x89, 0x85, 0x53, 0x01, 0x00, 0x00, 0x8B, 0x46,
0x04, 0x05, 0x0E, 0x01, 0x00, 0x00, 0x6A, 0x04,
0x68, 0x00, 0x10, 0x00, 0x00, 0x50, 0x6A, 0x00,
0xFF, 0x55, 0x51, 0x89, 0x85, 0x4F, 0x01, 0x00,
0x00, 0x56, 0x8B, 0x1E, 0x03, 0x9D, 0x7D, 0x04,
0x00, 0x00, 0xFF, 0xB5, 0x53, 0x01, 0x00, 0x00,
0xFF, 0x76, 0x04, 0x50, 0x53, 0xE8, 0x2D, 0x05,
0x00, 0x00, 0xB3, 0x00, 0x80, 0xFB, 0x00, 0x75,
0x5E, 0xFE, 0x85, 0xE9, 0x00, 0x00, 0x00, 0x8B,
0x3E, 0x03, 0xBD, 0x7D, 0x04, 0x00, 0x00, 0xFF,
0x37, 0xC6, 0x07, 0xC3, 0xFF, 0xD7, 0x8F, 0x07,
0x50, 0x51, 0x56, 0x53, 0x8B, 0xC8, 0x83, 0xE9,
0x06, 0x8B, 0xB5, 0x4F, 0x01, 0x00, 0x00, 0x33,
0xDB, 0x0B, 0xC9, 0x74, 0x2E, 0x78, 0x2C, 0xAC,
0x3C, 0xE8, 0x74, 0x0A, 0xEB, 0x00, 0x3C, 0xE9,
0x74, 0x04, 0x43, 0x49, 0xEB, 0xEB, 0x8B, 0x06,
0xEB, 0x00, null, null, null, 0x75, 0xF3, 0x24,
0x00, 0xC1, 0xC0, 0x18, 0x2B, 0xC3, 0x89, 0x06,
0x83, 0xC3, 0x05, 0x83, 0xC6, 0x04, 0x83, 0xE9,
0x05, 0xEB, 0xCE, 0x5B, 0x5E, 0x59, 0x58, 0xEB,
0x08
}, "ASPack 2.2 -> Alexey Solodovnikov & StarForce * 2009408"),
new ContentMatchSet(new byte?[]
{
null, 0x60, 0xE8, 0x03, 0x00, 0x00, 0x00, 0xE9,
0xEB, 0x04, 0x5D, 0x45, 0x55, 0xC3, 0xE8, 0x01,
0x00, 0x00, 0x00, 0xEB, 0x5D, 0xBB, 0xEC, 0xFF,
0xFF, 0xFF, 0x03, 0xDD, 0x81, 0xEB, 0x00, 0x40,
0x1C, 0x00
}, "ASPack 2.x (without Poly) -> Solodovnikov Alexey"),
#endregion
#region 2.xx (Long)
new ContentMatchSet(new byte?[]
{
0xA8, 0x03, 0x00, 0x00, 0x61, 0x75, 0x08, 0xB8,
0x01, 0x00, 0x00, 0x00, 0xC2, 0x0C, 0x00, 0x68,
0x00, 0x00, 0x00, 0x00, 0xC3, 0x8B, 0x85, 0x26,
0x04, 0x00, 0x00, 0x8D, 0x8D, 0x3B, 0x04, 0x00,
0x00, 0x51, 0x50, 0xFF, 0x95
}, "ASPack 2.xx"),
new ContentMatchSet(new byte?[]
{
0xA8, 0x03, null, null, 0x61, 0x75, 0x08, 0xB8,
0x01, null, null, null, 0xC2, 0x0C, null, 0x68,
null, null, null, null, 0xC3, 0x8B, 0x85, 0x26,
0x04, null, null, 0x8D, 0x8D, 0x3B, 0x04, null,
null, 0x51, 0x50, 0xFF, 0x95
}, "ASPack 2.xx"),
#endregion
#region Short
new ContentMatchSet(new byte?[] { 0x75, 0x00, 0xE9 }, "ASPack 1.05b"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x00, 0xE9 }, "ASPack 1.06.1b"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0xE9 }, "ASPack 1.07b"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0xFF, 0xE9 }, "ASPack 1.08"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new ContentMatchSet(new byte?[] { 0x90, 0x75, null, 0x90, 0xE9 }, "ASPack 1.08.01"),
new ContentMatchSet(new byte?[] { 0x90, 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
new ContentMatchSet(new byte?[] { 0x90, 0x75, 0x01, 0x90, 0xE9 }, "ASPack 1.08.02"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x41, 0x06, 0x00, 0x00, 0xEB, 0x41 }, "ASPack 1.08.04"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, null, null, null, 0xEB }, "ASPack 1.08.04"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x70, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.00"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x48, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.00.00"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x72, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.01"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, null, 0x05, 0x00, 0x00, 0xEB, 0x4C }, "ASPack 2.00.x -> Alexey Solodovnikov"),
new ContentMatchSet(new byte?[] { 0x60, 0xE9, 0x3D, 0x04, 0x00, 0x00 }, "ASPack 2.11"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0xF9, 0x11, 0x00, 0x00, 0xC3, 0x83 }, "ASPack 2.11"),
new ContentMatchSet(new byte?[] { 0x60, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x81, 0xED }, "ASPack 1.02b/1.08.03"),
#endregion
};
}
}
}

View File

@@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// TODO: Verify that all versions are detected
public class AdvancedInstaller : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .rdata section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Any(s => s.Contains("Software\\Caphyon\\Advanced Installer")))
return "Caphyon Advanced Installer";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,60 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// TODO: Add version checking, if possible
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Armadillo : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .nicode section, if it exists
bool nicodeSection = pex.ContainsSection(".nicode", exact: true);
if (nicodeSection)
return "Armadillo";
// Loop through all "extension" sections -- usually .data1 or .text1
foreach (var sectionName in pex.SectionNames.Where(s => s != null && s.EndsWith("1")))
{
// Get the section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(sectionName);
if (strs != null)
{
if (strs.Any(s => s.Contains("ARMDEBUG")))
return "Armadillo";
}
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// Created by IndigoRose (creators of Setup Factory), primarily to be used to create autorun menus for various media.
// Official website: https://www.autoplay.org/
// TODO: Add extraction
public class AutoPlayMediaStudio : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Known to detect versions 5.0.0.3 - 8.1.0.0
string name = pex.ProductName;
if (name?.StartsWith("AutoPlay Media Studio", StringComparison.OrdinalIgnoreCase) == true)
return $"AutoPlay Media Studio {GetVersion(pex)}";
// Currently too vague, may be re-enabled in the future
/*
name = Utilities.GetLegalCopyright(pex);
if (name?.StartsWith("Runtime Engine", StringComparison.OrdinalIgnoreCase) == true)
return $"AutoPlay Media Studio {GetVersion(pex)}";
*/
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
string version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version;
// Check the internal versions
version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version;
return "(Unknown Version)";
}
}
}

View File

@@ -20,6 +20,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="WiseUnpacker" Version="1.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BinaryObjectScanner.Interfaces\BinaryObjectScanner.Interfaces.csproj" />
<ProjectReference Include="..\BinaryObjectScanner.Matching\BinaryObjectScanner.Matching.csproj" />

View File

@@ -0,0 +1,144 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Compression;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
using ICSharpCode.SharpZipLib.Zip.Compression;
namespace BinaryObjectScanner.Packer
{
// The official website for CExe also includes the source code (which does have to be retrieved by the Wayback Machine)
// http://www.scottlu.com/Content/CExe.html
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class CExe : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// If there are exactly 2 resources with type 99
if (pex.FindResourceByNamedType("99, ").Count() == 2)
return "CExe";
var matchers = new List<ContentMatchSet>
{
new ContentMatchSet(new byte?[]
{
0x25, 0x57, 0x6F, 0xC1, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x01, 0x92, 0x61, 0x36, 0x01, 0x92,
0x61, 0x36, 0x00, 0x92, 0x7B, 0x36, 0x01, 0x92,
0x03, 0x29, 0x12, 0x92, 0x66, 0x36, 0x01, 0x92,
0x89, 0x29, 0x0A, 0x92, 0x60, 0x36, 0x01, 0x92,
0xD9, 0x30, 0x07, 0x92, 0x60, 0x36, 0x01, 0x92
}, "CExe")
};
string match = MatchUtil.GetFirstMatch(file, pex.StubExecutableData, matchers, includeDebug);
if (!string.IsNullOrWhiteSpace(match))
return match;
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
try
{
// Parse into an executable again for easier extraction
PortableExecutable pex = PortableExecutable.Create(stream);
if (pex == null)
return null;
// Get the first resource of type 99 with index 2
byte[] payload = pex.FindResourceByNamedType("99, 2").FirstOrDefault();
if (payload == null || payload.Length == 0)
return null;
// Determine which compression was used
bool zlib = pex.FindResourceByNamedType("99, 1").Any();
// Create the output data buffer
byte[] data;
// If we had the decompression DLL included, it's zlib
if (zlib)
{
try
{
// Inflate the data into the buffer
Inflater inflater = new Inflater();
inflater.SetInput(payload);
data = new byte[payload.Length * 4];
int read = inflater.Inflate(data);
// Trim the buffer to the proper size
data = new ReadOnlySpan<byte>(data, 0, read).ToArray();
}
catch
{
// Reset the data
data = null;
}
}
// Otherwise, LZ is used via the Windows API
else
{
try
{
data = LZ.Decompress(payload);
}
catch
{
// Reset the data
data = null;
}
}
// If we have no data
if (data == null)
return null;
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Create the temp filename
string tempFile = string.IsNullOrEmpty(file) ? "temp.sxe" : $"{Path.GetFileNameWithoutExtension(file)}.sxe";
tempFile = Path.Combine(tempPath, tempFile);
// Write the file data to a temp file
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(data, 0, data.Length);
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,95 @@
using System.Collections.Generic;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Figure out how to more granularly determine versions like PiD
// TODO: Detect 3.15 and up (maybe looking for `Metamorphism`)
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class EXEStealth : IContentCheck, IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckContents(string file, byte[] fileContent, bool includeDebug)
{
// TODO: Obtain a sample to find where this string is in a typical executable
if (includeDebug)
{
var contentMatchSets = new List<ContentMatchSet>
{
// ??[[__[[_ + (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 ContentMatchSet(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 MatchUtil.GetFirstMatch(file, fileContent, contentMatchSets, includeDebug);
}
return null;
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// The ExeS/EXES/*mtw sections seem to map to the Import Table
// 2.6/2.51
// `ExeStealth - www.webtoolmaster.com`
// 2.72/2.73
// `Shareware - ExeStealth`
// `www.webtoolmaster.com`
// 2.74
// `Shareware - ExeStealth`
// 2.76
// `ExeStealth V2 Shareware not for public - This text not in registered version - www.webtoolmaster.com`
// Get the ExeS/EXES section, if it exists
bool exesSection = pex.ContainsSection("ExeS", exact: true) || pex.ContainsSection("EXES", exact: true);
if (exesSection)
return "EXE Stealth 2.41-2.75";
// Get the mtw section, if it exists
bool mtwSection = pex.ContainsSection("mtw", exact: true);
if (mtwSection)
return "EXE Stealth 1.1";
// Get the rsrr section, if it exists
bool rsrrSection = pex.ContainsSection("rsrr", exact: true);
if (rsrrSection)
return "EXE Stealth 2.76";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
/// <summary>
/// Though not technically a packer, this detection is for any executables that include
/// others in their resources in some uncompressed manner to be used at runtime.
/// </summary>
public class EmbeddedExecutable : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the resources that have an executable signature
if (pex.ResourceData?.Any(kvp => kvp.Value is byte[] ba && ba.StartsWith(BinaryObjectScanner.Models.MSDOS.Constants.SignatureBytes)) == true)
return "Embedded Executable";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
try
{
// Parse into an executable again for easier extraction
PortableExecutable pex = PortableExecutable.Create(stream);
if (pex?.ResourceData == null)
return null;
// Get the resources that have an executable signature
var resources = pex.ResourceData
.Where(kvp => kvp.Value != null && kvp.Value is byte[])
.Where(kvp => (kvp.Value as byte[]).StartsWith(BinaryObjectScanner.Models.MSDOS.Constants.SignatureBytes))
.ToList();
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
for (int i = 0; i < resources.Count; i++)
{
try
{
// Get the resource data
var resource = resources[i];
byte[] data = resource.Value as byte[];
// Create the temp filename
string tempFile = $"embedded_resource_{i}.bin";
tempFile = Path.Combine(tempPath, tempFile);
// Write the resource data to a temp file
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(data, 0, data.Length);
}
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class GenteeInstaller : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Any(s => s.Contains("Gentee installer")))
return "Gentee Installer";
if (strs.Any(s => s.Contains("ginstall.dll")))
return "Gentee Installer";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,52 @@
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// CrackProof is a packer/obfuscator created by Japanese company HyperTech (https://www.hypertech.co.jp/products/windows/).
// It is known to be used along with other DRM, such as Shury2 (Redump entry 97135) and BDL.
// https://www.reddit.com/r/riseofincarnates/comments/m3vbnm/subreddit_revival_does_anyone_still_have_rise_of/
// https://steamcommunity.com/app/310950/discussions/0/4224890554455490819/
// https://github.com/horsicq/Detect-It-Easy/blob/63a1aa8bb23ca02d8a7fd5936db8dbc5c5d52dea/db/PE/HyperTech%20Crackproof.2.sg
public class HyperTechCrackProof : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// This check may be overly limiting, as it excludes the sample provided to DiE (https://github.com/horsicq/Detect-It-Easy/issues/102).
// TODO: Find further samples and invesitgate if the "peC" section is only present on specific versions.
bool peCSection = pex.ContainsSection("peC", exact: true);
bool importTableMatch = (pex.ImportTable?.ImportDirectoryTable?.Any(idte => idte.Name == "KeRnEl32.dLl") ?? false);
if (peCSection && importTableMatch)
return "HyperTech CrackProof";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,101 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction - https://github.com/dscharrer/InnoExtract
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InnoSetup : IExtractable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check we have a valid executable
if (nex == null)
return null;
// Check for "Inno" in the reserved words
if (nex.Stub_Reserved2[4] == 0x6E49 && nex.Stub_Reserved2[5] == 0x6F6E)
{
string version = GetOldVersion(file, nex);
if (!string.IsNullOrWhiteSpace(version))
return $"Inno Setup {version}";
return "Inno Setup (Unknown Version)";
}
return null;
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
string str = strs.FirstOrDefault(s => s.StartsWith("Inno Setup Setup Data"));
if (str != null)
{
return str.Replace("Inno Setup Setup Data", "Inno Setup")
.Replace("(u)", "[Unicode]")
.Replace("(", string.Empty)
.Replace(")", string.Empty)
.Replace("[Unicode]", "(Unicode)");
}
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
private static string GetOldVersion(string file, NewExecutable nex)
{
// Notes:
// Look into `SETUPLDR` in the resident-name table
// Look into `SETUPLDR.EXE` in the nonresident-name table
// TODO: Don't read entire file
// TODO: Only 64 bytes at the end of the file is needed
var data = nex.ReadArbitraryRange();
if (data != null)
{
var matchers = new List<ContentMatchSet>
{
// "rDlPtS02" + (char)0x87 + "eVx"
new ContentMatchSet(new byte?[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }, "1.2.16 or earlier"),
};
return MatchUtil.GetFirstMatch(file, data, matchers, false) ?? "Unknown 1.X";
}
return "Unknown 1.X";
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, which may be possible with the current libraries but needs to be investigated further.
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InstallAnywhere : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string name = pex.FileDescription;
if (name?.StartsWith("InstallAnywhere Self Extractor", StringComparison.OrdinalIgnoreCase) == true)
return $"InstallAnywhere {GetVersion(pex)}";
name = pex.ProductName;
if (name?.StartsWith("InstallAnywhere", StringComparison.OrdinalIgnoreCase) == true)
return $"InstallAnywhere {GetVersion(pex)}";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
// Check the internal versions
string version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction - https://github.com/Bioruebe/UniExtract2
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class InstallerVISE : IExtractable, IPortableExecutableCheck
{
//TODO: Add exact version detection for Windows builds, make sure versions before 3.X are detected as well, and detect the Mac builds.
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Any(s => s.Contains("ViseMain")))
return "Installer VISE";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, seems to primarily use MSZip compression.
public class IntelInstallationFramework : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string name = pex.FileDescription;
if (name?.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase) == true
|| name?.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase) == true)
{
return $"Intel Installation Framework {pex.GetInternalVersion()}";
}
name = pex.ProductName;
if (name?.Equals("Intel(R) Installation Framework", StringComparison.OrdinalIgnoreCase) == true
|| name?.Equals("Intel Installation Framework", StringComparison.OrdinalIgnoreCase) == true)
{
return $"Intel Installation Framework {pex.GetInternalVersion()}";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, which should be possible with LibMSPackN, but it refuses to extract due to SFX files lacking the typical CAB identifiers.
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class MicrosoftCABSFX : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string name = pex.InternalName;
if (name?.Equals("Wextract", StringComparison.OrdinalIgnoreCase) == true)
return $"Microsoft CAB SFX {GetVersion(pex)}";
name = pex.OriginalFilename;
if (name?.Equals("WEXTRACT.EXE", StringComparison.OrdinalIgnoreCase) == true)
return $"Microsoft CAB SFX {GetVersion(pex)}";
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Any(s => s.Contains("wextract_cleanup")))
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
// Get the .text section strings, if they exist
strs = pex.GetFirstSectionStrings(".text");
if (strs != null)
{
// This detects a different but similar type of SFX that uses Microsoft CAB files.
// Further research is needed to see if it's just a different version or entirely separate.
if (strs.Any(s => s.Contains("MSCFu")))
return $"Microsoft CAB SFX {GetVersion(pex)}";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
// Check the internal versions
string version = pex.GetInternalVersion();
if (!string.IsNullOrWhiteSpace(version))
return $"v{version}";
return string.Empty;
}
}
}

View File

@@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class NSIS : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string description = pex.AssemblyDescription;
if (!string.IsNullOrWhiteSpace(description) && description.StartsWith("Nullsoft Install System"))
return $"NSIS {description.Substring("Nullsoft Install System".Length).Trim()}";
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Any(s => s.Contains("NullsoftInst")))
return "NSIS";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,62 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Better version detection - https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
// TODO: Add extraction
public class PECompact : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// 0x4F434550 is "PECO"
if (pex.PointerToSymbolTable == 0x4F434550)
return "PE Compact v1.x";
// TODO: Get more granular version detection. PiD is somehow able to detect version ranges based
// on the data in the file. This may be related to information in other fields
// Get the pec1 section, if it exists
bool pec1Section = pex.ContainsSection("pec1", exact: true);
if (pec1Section)
return "PE Compact v1.x";
// Get the PEC2 section, if it exists -- TODO: Verify this comment since it's pulling the .text section
var textSection = pex.GetFirstSection(".text", exact: true);
if (textSection != null && textSection.PointerToRelocations == 0x32434550)
{
if (textSection.PointerToLinenumbers != 0)
return $"PE Compact v{textSection.PointerToLinenumbers} (internal version)";
return "PE Compact v2.x (or newer)";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,45 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class PEtite : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .petite section, if it exists -- TODO: Is there a version number that can be found?
bool petiteSection = pex.ContainsSection(".petite", exact: true);
if (petiteSection)
return "PEtite";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,74 @@
using System;
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction, which is possible but the only tools available that can
// do this seem to be Universal Extractor 2 and InstallExplorer (https://totalcmd.net/plugring/InstallExplorer.html)
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class SetupFactory : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Known to detect versions 7.0.5.1 - 9.1.0.0
string name = pex.LegalCopyright;
if (name?.StartsWith("Setup Engine", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
name = pex.ProductName;
if (name?.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
// Known to detect version 5.0.1 - 6.0.1.3
name = pex.FileDescription;
if (name?.StartsWith("Setup Factory", StringComparison.OrdinalIgnoreCase) == true)
return $"Setup Factory {GetVersion(pex)}";
// Longer version of the check that can be used if false positves become an issue:
// "Setup Factory is a trademark of Indigo Rose Corporation"
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
private string GetVersion(PortableExecutable pex)
{
// Check the product version explicitly
string version = pex.ProductVersion;
if (!string.IsNullOrEmpty(version))
return version;
// Check the internal versions
version = pex.GetInternalVersion();
if (!string.IsNullOrEmpty(version))
return version;
return "(Unknown Version)";
}
}
}

View File

@@ -0,0 +1,66 @@
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class SevenZipSFX : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the assembly description, if possible
if (pex.AssemblyDescription?.StartsWith("7-Zip Self-extracting Archive") == true)
return $"7-Zip SFX {pex.AssemblyDescription.Substring("7-Zip Self-extracting Archive ".Length)}";
// Get the file description, if it exists
if (pex.FileDescription?.Equals("7z SFX") == true)
return "7-Zip SFX";
if (pex.FileDescription?.Equals("7z Self-Extract Setup") == true)
return "7-Zip SFX";
// Get the original filename, if it exists
if (pex.OriginalFilename?.Equals("7z.sfx.exe") == true)
return "7-Zip SFX";
else if (pex.OriginalFilename?.Equals("7zS.sfx") == true)
return "7-Zip SFX";
// Get the internal name, if it exists
if (pex.InternalName?.Equals("7z.sfx") == true)
return "7-Zip SFX";
else if (pex.InternalName?.Equals("7zS.sfx") == true)
return "7-Zip SFX";
// If any dialog boxes match
if (pex.FindDialogByTitle("7-Zip self-extracting archive").Any())
return "7-Zip SFX";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,46 @@
using System.IO;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class Shrinker : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .shrink0 and .shrink2 sections, if they exist -- TODO: Confirm if both are needed or either/or is fine
bool shrink0Section = pex.ContainsSection(".shrink0", true);
bool shrink2Section = pex.ContainsSection(".shrink2", true);
if (shrink0Section || shrink2Section)
return "Shrinker";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}

View File

@@ -0,0 +1,113 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class UPX : IExtractable, IPortableExecutableCheck
{
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)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Check header padding strings
if (pex.HeaderPaddingStrings?.Any() == true)
{
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)
{
var regexMatch = _oldUpxVersionMatch.Match(match);
if (regexMatch.Success)
return $"UPX {regexMatch.Groups[1].Value}";
else
return "UPX (Unknown Version)";
}
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;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
public static string GetVersion(string file, byte[] fileContent, List<int> positions)
{
try
{
// Check the normal version location first
int index = positions[0] - 5;
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
// Check for the old-style string
//
// Example:
// $Info: This file is packed with the UPX executable packer http://upx.tsx.org $
// $Id: UPX 1.02 Copyright (C) 1996-2000 the UPX Team. All Rights Reserved. $
// UPX!
index = positions[0] - 67;
versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (char.IsNumber(versionString[0]))
return versionString;
return "(Unknown Version)";
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -0,0 +1,82 @@
using System;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
using SharpCompress.Archives;
using SharpCompress.Archives.Rar;
namespace BinaryObjectScanner.Packer
{
public class WinRARSFX : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
string name = pex.AssemblyDescription;
if (name?.Contains("WinRAR archiver") == true)
return "WinRAR SFX";
var resources = pex.FindDialogByTitle("WinRAR self-extracting archive");
if (resources.Any())
return "WinRAR SFX";
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (RarArchive zipFile = RarArchive.Open(file, new SharpCompress.Readers.ReaderOptions() { LookForHeader = true }))
{
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
}
}

View File

@@ -0,0 +1,877 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
namespace BinaryObjectScanner.Packer
{
public class WinZipSFX : IExtractable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
{
// Check we have a valid executable
if (nex == null)
return null;
// If the resident-name table doesnt exist
if (nex.ResidentNameTable == null)
return null;
// Check for the WinZip name string
bool winZipNameFound = nex.ResidentNameTable.Where(rnte => rnte?.NameString != null)
.Select(rnte => Encoding.ASCII.GetString(rnte.NameString))
.Any(s => s.Contains("WZ-SE-01"));
// If we didn't find it
if (!winZipNameFound)
return null;
// Try to get a known version
string version = GetNEHeaderVersion(nex);
if (!string.IsNullOrWhiteSpace(version))
return $"WinZip SFX {version}";
return $"WinZip SFX Unknown Version (16-bit)";
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Check the export directory table, if it exists
if (pex.ExportTable?.ExportDirectoryTable != null)
{
string version = GetPEExportDirectoryVersion(pex);
if (!string.IsNullOrWhiteSpace(version))
return $"WinZip SFX {version}";
}
// Get the _winzip_ section, if it exists
if (pex.ContainsSection("_winzip_", exact: true))
return "WinZip SFX Unknown Version (32-bit)";
return null;
}
// TODO: Find a way to generically detect 2.X versions and improve exact version detection for SFX PE versions bundled with WinZip 11+
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// Should be using stream instead of file, but stream fails to extract anything. My guess is that the executable portion of the archive is causing stream to fail, but not file.
using (ZipArchive zipFile = ZipArchive.Open(file))
{
foreach (var entry in zipFile.Entries)
{
try
{
// If we have a directory, skip it
if (entry.IsDirectory)
continue;
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
}
}
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <summary>
/// Get the version from the NE header value combinations
/// </summary>
/// TODO: Reduce the checks to only the ones that differ between versions
/// TODO: Research to see if the versions are embedded elsewhere in these files
private string GetNEHeaderVersion(NewExecutable nex)
{
#region 2.0 Variants
// 2.0 (MS-DOS/16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0086
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x00012BE6
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006C
&& nex.NonResidentNamesTableOffset == 0x000044B8
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.0 (MS-DOS/16-bit)";
// 2.0 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0086
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x00013174
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006C
&& nex.NonResidentNamesTableOffset == 0x00000198
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.0 (16-bit)";
// Compact 2.0 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0080
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x000124A0
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0003
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006A
&& nex.NonResidentNamesTableOffset == 0x00000192
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Compact 2.0 (16-bit)";
// Software Installation 2.0 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00CD
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x000136FA
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0005
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0097
&& nex.ModuleReferenceTableOffset == 0x00A3
&& nex.ImportedNamesTableOffset == 0x00AD
&& nex.NonResidentNamesTableOffset == 0x000001DF
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Software Installation 2.0 (16-bit)";
#endregion
#region 2.1 RC2 Variants
// 2.1 RC2 (MS-DOS/16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0086
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x00013386
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006C
&& nex.NonResidentNamesTableOffset == 0x000043C8
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.1 RC2 (MS-DOS/16-bit)";
// 2.1 RC2 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00BE
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x00013E56
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A4
&& nex.NonResidentNamesTableOffset == 0x000001D0
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.1 RC2 (16-bit)";
// Compact 2.1 RC2 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0080
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x00012B84
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0003
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006A
&& nex.NonResidentNamesTableOffset == 0x00000192
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Compact 2.1 RC2 (16-bit)";
// Software Installation 2.1 RC2 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00BE
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x000143AC
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A4
&& nex.NonResidentNamesTableOffset == 0x000001D0
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Software Installation 2.1 RC2 (16-bit)";
#endregion
#region 2.1 Variants
// 2.1 (MS-DOS/16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0086
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x3A00
&& nex.InitialCSIPSetting == 0x00013396
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006C
&& nex.NonResidentNamesTableOffset == 0x000043C8
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.1 (MS-DOS/16-bit)";
// 2.1 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00BE
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x3A00
&& nex.InitialCSIPSetting == 0x00013E7E
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A4
&& nex.NonResidentNamesTableOffset == 0x000001D0
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "2.1 (16-bit)";
// Compact 2.1 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0080
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x3A00
&& nex.InitialCSIPSetting == 0x00012B90
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0003
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006A
&& nex.NonResidentNamesTableOffset == 0x00000192
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Compact 2.1 (16-bit)";
// Software Installation 2.1 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00BE
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x3A00
&& nex.InitialCSIPSetting == 0x00014408
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A4
&& nex.NonResidentNamesTableOffset == 0x000001D0
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Software Installation 2.1 (16-bit)";
#endregion
#region Misc. Variants
// Personal Edition (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x0086
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.ProtectedModeOnly
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x4000
&& nex.InitialCSIPSetting == 0x0001317C
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0058
&& nex.ModuleReferenceTableOffset == 0x0064
&& nex.ImportedNamesTableOffset == 0x006C
&& nex.NonResidentNamesTableOffset == 0x00000198
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Personal Edition (16-bit)";
// Personal Edition 32-bit (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00BE
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x2000
&& nex.InitialStackAlloc == 0x3C00
&& nex.InitialCSIPSetting == 0x00013E7C
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0004
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A4
&& nex.NonResidentNamesTableOffset == 0x000001D0
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Personal Edition 32-bit (16-bit)";
// Personal Edition 32-bit Build 1260/1285 (16-bit)
if (nex.LinkerVersion == 0x11
&& nex.LinkerRevision == 0x20
&& nex.EntryTableOffset == 0x00C6
&& nex.EntryTableSize == 0x0002
&& nex.CrcChecksum == 0x00000000
&& nex.FlagWord == (BinaryObjectScanner.Models.NewExecutable.HeaderFlag.MULTIPLEDATA
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.FullScreen
| BinaryObjectScanner.Models.NewExecutable.HeaderFlag.WindowsPMCompatible)
&& nex.AutomaticDataSegmentNumber == 0x0003
&& nex.InitialHeapAlloc == 0x43DC
&& nex.InitialStackAlloc == 0x2708
&& nex.InitialCSIPSetting == 0x00014ADC
&& nex.InitialSSSPSetting == 0x00030000
&& nex.FileSegmentCount == 0x0003
&& nex.ModuleReferenceTableSize == 0x0005
&& nex.NonResidentNameTableSize == 0x004B
&& nex.SegmentTableOffset == 0x0040
&& nex.ResourceTableOffset == 0x0058
&& nex.ResidentNameTableOffset == 0x0090
&& nex.ModuleReferenceTableOffset == 0x009C
&& nex.ImportedNamesTableOffset == 0x00A6
&& nex.NonResidentNamesTableOffset == 0x000001D8
&& nex.MovableEntriesCount == 0x0000
&& nex.SegmentAlignmentShiftCount == 0x0001
&& nex.ResourceEntriesCount == 0x0000
&& nex.TargetOperatingSystem == BinaryObjectScanner.Models.NewExecutable.OperatingSystem.WINDOWS
&& nex.AdditionalFlags == 0x00
&& nex.ReturnThunkOffset == 0x0000
&& nex.SegmentReferenceThunkOffset == 0x0000
&& nex.MinCodeSwapAreaSize == 0x0000
&& nex.WindowsSDKRevision == 0x00
&& nex.WindowsSDKVersion == 0x03)
return "Personal Edition 32-bit Build 1260/1285 (16-bit)";
#endregion
return null;
}
/// <summary>
/// Get the version from the PE export directory table value combinations
/// </summary>
/// TODO: Research to see if the versions are embedded elsewhere in these files
private string GetPEExportDirectoryVersion(PortableExecutable pex)
{
string sfxFileName = pex.ExportTable.ExportDirectoryTable.Name;
uint sfxTimeDateStamp = pex.ExportTable.ExportDirectoryTable.TimeDateStamp;
string assemblyVersion = pex.AssemblyVersion ?? "Unknown Version";
// Standard
if (sfxFileName == "VW95SE.SFX" || sfxFileName == "ST32E.SFX"
|| sfxFileName == "WZIPSE32.exe" || sfxFileName == "SI32LPG.SFX"
|| sfxFileName == "ST32E.WZE")
{
switch (sfxTimeDateStamp)
{
case 842636344:
return "2.0 (32-bit)";
case 865370756:
return "2.1 RC2 (32-bit)";
case 869059925:
return "2.1 (32-bit)";
case 979049321:
return "2.2.4003";
case 1149714685:
return "3.0.7158";
case 1185211734:
return "3.1.7556";
case 1185211920:
return "3.1.7556";
case 1235490556:
return "4.0.8421";
case 1235490757:
return "4.0.8421";
case 1235490687:
return "4.0.8421"; // 3.1.8421.0, SI32LPG?
case 1257193383:
return "4.0.8672"; // 3.1.8672.0
case 1257193543:
return "4.0.8672";
case 1470410848:
return "4.0.12218"; // 4.0.1221.0
default:
return $"{assemblyVersion} (32-bit)";
}
}
// Personal Edition
if (sfxFileName == "VW95LE.SFX" || sfxFileName == "PE32E.SFX"
|| sfxFileName == "wzsepe32.exe" || sfxFileName == "SI32PE.SFX"
|| sfxFileName == "SI32LPE.SFX")
{
switch (sfxTimeDateStamp)
{
case 845061601:
return "Personal Edition (32-bit)"; // TODO: Find version
case 868303343:
return "Personal Edition (32-bit)"; // TODO: Find version
case 868304170:
return "Personal Edition (32-bit)"; // TODO: Find version
case 906039079:
return "Personal Edition 2.2.1260 (32-bit)";
case 906040543:
return "Personal Edition 2.2.1260 (32-bit)";
case 908628435:
return "Personal Edition 2.2.1285 (32-bit)";
case 908628785:
return "Personal Edition 2.2.1285 (32-bit)";
case 956165981:
return "Personal Edition 2.2.3063";
case 956166038:
return "Personal Edition 2.2.3063";
case 1006353695:
return "Personal Edition 2.2.4325";
case 1006353714:
return "Personal Edition 2.2.4325"; // 8.1.0.0
case 1076515698:
return "Personal Edition 2.2.6028";
case 1076515784:
return "Personal Edition 2.2.6028"; // 9.0.6028.0
case 1092688561:
return "Personal Edition 2.2.6224";
case 1092688645:
return "Personal Edition 2.2.6224"; // 9.0.6224.0
case 1125074095:
return "Personal Edition 2.2.6604";
case 1125074162:
return "Personal Edition 2.2.6604"; // 10.0.6604.0
case 1130153399:
return "Personal Edition 2.2.6663";
case 1130153428:
return "Personal Edition 2.2.6663"; // 10.0.6663.0
case 1149714176:
return "Personal Edition 3.0.7158";
case 1163137967:
return "Personal Edition 3.0.7305";
case 1163137994:
return "Personal Edition 3.0.7313"; // 11.0.7313.0
case 1176345383:
return "Personal Edition 3.0.7452";
case 1176345423:
return "Personal Edition 3.1.7466"; // 11.1.7466.0
case 1184106698:
return "Personal Edition 3.1.7556";
case 1207280880:
return "Personal Edition 4.0.8060"; // 2.3.7382.0
case 1207280892:
return "Personal Edition 4.0.8094"; // 11.2.8094.0
case 1220904506:
return "Personal Edition 4.0.8213"; // 2.3.7382.0
case 1220904518:
return "Personal Edition 4.0.8252"; // 12.0.8252.0
case 1235490648:
return "Personal Edition 4.0.8421"; // 3.1.8421.0
case 1242049399:
return "Personal Edition 4.0.8497"; // 12.1.8497.0
case 1257193469:
return "Personal Edition 4.0.8672"; // 3.1.8672.0, SI32LPE?
default:
return $"Personal Edition {assemblyVersion} (32-bit)";
}
}
// Software Installation
else if (sfxFileName == "VW95SRE.SFX" || sfxFileName == "SI32E.SFX"
|| sfxFileName == "SI32E.WZE")
{
switch (sfxTimeDateStamp)
{
case 842636381:
return "Software Installation 2.0 (32-bit)";
case 865370800:
return "Software Installation 2.1 RC2 (32-bit)";
case 869059963:
return "Software Installation 2.1 (32-bit)";
case 893107697:
return "Software Installation 2.2.1110 (32-bit)";
case 952007369:
return "Software Installation 2.2.3063";
case 1006352634:
return "Software Installation 2.2.4325"; // +Personal Edition?
case 979049345:
return "Software Installation 2.2.4403";
case 1026227373:
return "Software Installation 2.2.5196"; // +Personal Edition?
case 1090582390:
return "Software Installation 2.2.6202"; // +Personal Edition?
case 1149714757:
return "Software Installation 3.0.7158";
case 1154357628:
return "Software Installation 3.0.7212";
case 1175234637:
return "Software Installation 3.0.7454";
case 1185211802:
return "Software Installation 3.1.7556";
case 1470410906:
return "Software Installation 4.0.12218"; // 4.0.1221.0
default:
return $"Software Installation {assemblyVersion} (32-bit)";
}
}
switch (sfxFileName)
{
// Standard
case "VW95SE.SFX":
return "Unknown Version (32-bit)"; // TODO: Find starting version
case "ST32E.SFX":
return "Unknown Version (32-bit)"; // TODO: Find starting version
case "WZIPSE32.exe":
return "Unknown Version (32-bit)"; // TODO: Find starting version
case "SI32LPG.SFX":
return "Unknown Version (32-bit)"; // TODO: Find starting version
case "ST32E.WZE":
return "Unknown Version (32-bit)"; // TODO: Find starting version
// Personal Edition
case "VW95LE.SFX":
return "Unknown Version before Personal Edition Build 1285 (32-bit)";
case "PE32E.SFX":
return "Unknown Version after Personal Edition Build 1285 (32-bit)";
case "wzsepe32.exe":
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
case "SI32PE.SFX":
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
case "SI32LPE.SFX":
return "Unknown Version Personal Edition (32-bit)"; // TODO: Find starting version
// Software Installation
case "VW95SRE.SFX":
return "Unknown Version before Software Installation 2.1 (32-bit)";
case "SI32E.SFX":
return "Unknown Version after Software Installation 2.1 (32-bit)";
case "SI32E.WZE":
return "Unknown Version Software Installation (32-bit)"; // TODO: Find starting version
}
return null;
}
}
}

View File

@@ -0,0 +1,390 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Matching;
using BinaryObjectScanner.Utilities;
using BinaryObjectScanner.Wrappers;
using Wise = WiseUnpacker.WiseUnpacker;
namespace BinaryObjectScanner.Packer
{
// https://raw.githubusercontent.com/wolfram77web/app-peid/master/userdb.txt
public class WiseInstaller : IExtractable, INewExecutableCheck, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckNewExecutable(string file, NewExecutable nex, bool includeDebug)
{
/// Check we have a valid executable
if (nex == null)
return null;
// If we match a known header
if (MatchesNEVersion(nex) != null)
return "Wise Installation Wizard Module";
// TODO: Investigate STUB.EXE in nonresident-name table
// TODO: Don't read entire file
var data = nex.ReadArbitraryRange();
if (data == null)
return null;
var neMatchSets = new List<ContentMatchSet>
{
// WiseInst
new ContentMatchSet(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x49, 0x6E, 0x73, 0x74 }, "Wise Installation Wizard Module"),
// WiseMain
new ContentMatchSet(new byte?[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E }, "Wise Installation Wizard Module"),
};
return MatchUtil.GetFirstMatch(file, data, neMatchSets, includeDebug);
}
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// If we match a known header
if (GetPEFormat(pex) != null)
return "Wise Installation Wizard Module";
// TODO: Investigate STUB32.EXE in export directory table
// Get the .data/DATA section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".data") ?? pex.GetFirstSectionStrings("DATA");
if (strs != null)
{
if (strs.Any(s => s.Contains("WiseMain")))
return "Wise Installation Wizard Module";
}
// Get the .rdata section strings, if they exist
strs = pex.GetFirstSectionStrings(".rdata");
if (strs != null)
{
if (strs.Any(s => s.Contains("WiseMain")))
return "Wise Installation Wizard Module";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
try
{
// Try to parse as a New Executable
NewExecutable nex = NewExecutable.Create(stream);
if (nex != null)
return ExtractNewExecutable(nex, file, includeDebug);
// Try to parse as a Portable Executable
PortableExecutable pex = PortableExecutable.Create(stream);
if (pex != null)
return ExtractPortableExecutable(pex, file, includeDebug);
return null;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <summary>
/// Checks an NE header to see if it matches a known signature
/// </summary>
/// <param name="nex">New executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty MatchesNEVersion(NewExecutable nex)
{
// TODO: Offset is _not_ the EXE header address, rather where the data starts. Fix this.
switch (nex.Stub_NewExeHeaderAddr)
{
case 0x84b0:
return new FormatProperty { Dll = false, ArchiveStart = 0x11, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = true };
case 0x3e10:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3e50:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3c20:
return new FormatProperty { Dll = false, ArchiveStart = 0x1e, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3c30:
return new FormatProperty { Dll = false, ArchiveStart = 0x22, ArchiveEnd = -1, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x3660:
return new FormatProperty { Dll = false, ArchiveStart = 0x40, ArchiveEnd = 0x3c, InitText = false, FilenamePosition = 0x04, NoCrc = false };
case 0x36f0:
return new FormatProperty { Dll = false, ArchiveStart = 0x48, ArchiveEnd = 0x44, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3770:
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3780:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x37b0:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x37d0:
return new FormatProperty { Dll = true, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
case 0x3c80:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
case 0x3bd0:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
case 0x3c10:
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
default:
return null;
}
}
/// <summary>
/// Checks a PE header to see if it matches a known signature
/// </summary>
/// <param name="pex">Portable executable to check</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private FormatProperty GetPEFormat(PortableExecutable pex)
{
if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4
&& pex.GetFirstSection(".data")?.VirtualSize == 0x1528)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3cf4
&& pex.GetFirstSection(".data")?.VirtualSize == 0x1568)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d54)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d44)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x6e00
&& pex.GetFirstSection(".text")?.VirtualSize == 0x3d04)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
// Found in Binary.WiseCustomCalla
else if (pex.OverlayAddress == 0x6200)
return new FormatProperty { Dll = true, ArchiveStart = 0x62, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3000)
return new FormatProperty { Dll = false, ArchiveStart = 0x50, ArchiveEnd = 0x4c, InitText = false, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3800)
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
else if (pex.OverlayAddress == 0x3a00)
return new FormatProperty { Dll = true, ArchiveStart = 0x5a, ArchiveEnd = 0x4c, InitText = true, FilenamePosition = 0x1c, NoCrc = false };
return null;
}
/// <summary>
/// Attempt to extract Wise data from a New Executable
/// </summary>
/// <param name="nex">New executable to check</param>
/// <param name="file">Path to the input file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private string ExtractNewExecutable(NewExecutable nex, string file, bool includeDebug)
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
try
{
// TODO: Try to find where the file data lives and how to get it
Wise unpacker = new Wise();
unpacker.ExtractTo(file, tempPath);
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
return tempPath;
}
/// <summary>
/// Attempt to extract Wise data from a Portable Executable
/// </summary>
/// <param name="pex">Portable executable to check</param>
/// <param name="file">Path to the input file</param>
/// <param name="includeDebug">True to include debug data, false otherwise</param>
/// <returns>True if it matches a known version, false otherwise</returns>
private string ExtractPortableExecutable(PortableExecutable pex, string file, bool includeDebug)
{
try
{
// Get the matching PE format
var format = GetPEFormat(pex);
if (format == null)
return null;
// Get the overlay data for easier reading
int overlayOffset = 0, dataStart = 0;
byte[] overlayData = pex.OverlayData;
if (overlayData == null)
return null;
// Skip over the additional DLL name, if we expect it
if (format.Dll)
{
// Read the name length
byte dllNameLength = overlayData.ReadByte(ref overlayOffset);
dataStart++;
// Read the name, if it exists
if (dllNameLength != 0)
{
// Ignore the name for now
_ = overlayData.ReadBytes(ref overlayOffset, dllNameLength);
dataStart += dllNameLength;
// Named DLLs also have a DLL length that we ignore
_ = overlayData.ReadUInt32(ref overlayOffset);
dataStart += 4;
}
}
// Check if flags are consistent
if (!format.NoCrc)
{
// Unlike WiseUnpacker, we ignore the flag value here
_ = overlayData.ReadUInt32(ref overlayOffset);
}
// Ensure that we have an archive end
if (format.ArchiveEnd > 0)
{
overlayOffset = dataStart + format.ArchiveEnd;
int archiveEndLoaded = overlayData.ReadInt32(ref overlayOffset);
if (archiveEndLoaded != 0)
format.ArchiveEnd = archiveEndLoaded;
}
// Skip to the start of the archive
overlayOffset = dataStart + format.ArchiveStart;
// Skip over the initialization text, if we expect it
if (format.InitText)
{
int initTextLength = overlayData.ReadByte(ref overlayOffset);
_ = overlayData.ReadBytes(ref overlayOffset, initTextLength);
}
// Cache the current offset in the overlay as the "start of data"
int offsetReal = overlayOffset;
// If the first entry is PKZIP, we assume it's an embedded zipfile
byte[] magic = overlayData.ReadBytes(ref overlayOffset, 4); overlayOffset -= 4;
bool pkzip = magic.StartsWith(new byte?[] { (byte)'P', (byte)'K' });
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
// If we have PKZIP
if (pkzip)
{
string tempFile = Path.Combine(tempPath, "WISEDATA.zip");
using (Stream tempStream = File.Open(tempFile, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
{
tempStream.Write(overlayData, overlayOffset, overlayData.Length - overlayOffset);
}
}
// If we have DEFLATE -- TODO: Port implementation here or use DeflateStream
else
{
Wise unpacker = new Wise();
unpacker.ExtractTo(file, tempPath);
}
return tempPath;
}
catch (Exception ex)
{
if (includeDebug) Console.WriteLine(ex);
return null;
}
}
/// <summary>
/// Class representing the properties of each recognized Wise installer format
/// </summary>
/// <see href="https://github.com/mnadareski/WiseUnpacker/blob/master/WiseUnpacker/FormatProperty.cs"/>
private class FormatProperty
{
/// <summary>
/// Offset to the executable data
/// </summary>
public int ExecutableOffset { get; set; }
/// <summary>
/// Indicates if this format includes a DLL at the start or not
/// </summary>
public bool Dll { get; set; }
/// <summary>
/// Offset within the data where the archive starts
/// </summary>
public int ArchiveStart { get; set; }
/// <summary>
/// Position in the archive head of the archive end
/// </summary>
public int ArchiveEnd { get; set; }
/// <summary>
/// Format includes initialization text
/// </summary>
public bool InitText { get; set; }
/// <summary>
/// Position of the filename within the data
/// </summary>
public int FilenamePosition { get; set; }
/// <summary>
/// Format does not include a CRC
/// </summary>
public bool NoCrc { get; set; }
}
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BinaryObjectScanner.Interfaces;
using BinaryObjectScanner.Wrappers;
namespace BinaryObjectScanner.Packer
{
// TODO: Add extraction
public class dotFuscator : IExtractable, IPortableExecutableCheck
{
/// <inheritdoc/>
public string CheckPortableExecutable(string file, PortableExecutable pex, bool includeDebug)
{
// Get the sections from the executable, if possible
var sections = pex?.SectionTable;
if (sections == null)
return null;
// Get the .text section strings, if they exist
List<string> strs = pex.GetFirstSectionStrings(".text");
if (strs != null)
{
if (strs.Any(s => s.Contains("DotfuscatorAttribute")))
return "dotFuscator";
}
return null;
}
/// <inheritdoc/>
public string Extract(string file, bool includeDebug)
{
if (!File.Exists(file))
return null;
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
return Extract(fs, file, includeDebug);
}
}
/// <inheritdoc/>
public string Extract(Stream stream, string file, bool includeDebug)
{
return null;
}
}
}