Compare commits

..

81 Commits
1.4.0 ... 1.5.0

Author SHA1 Message Date
Matt Nadareski
9ebcfdba53 Bump version to 1.5.0 2020-11-03 21:15:36 -08:00
Matt Nadareski
15f020cb06 Fix textfile content scan 2020-11-03 14:57:23 -08:00
Matt Nadareski
4b387f86c1 Hook up MediaMax to scan 2020-11-03 14:47:15 -08:00
Matt Nadareski
1a3a73a86d Add MediaMax CD-3 content detections 2020-11-03 14:41:05 -08:00
Matt Nadareski
31eff196e6 Forgot to fix path in Wise 2020-11-02 15:18:03 -08:00
Matt Nadareski
828d3403f1 Upgrade UnshieldSharp, re-enable ISCab for Core 2020-11-01 23:13:35 -08:00
Matt Nadareski
28d6d06033 Unshield uses zlib.net which isn't .NET Core... 2020-11-01 22:13:46 -08:00
Matt Nadareski
0a2477e1b3 Remove console writes, make LibCrypt read better 2020-11-01 21:53:42 -08:00
Matt Nadareski
01451d7009 A bit of cleanup 2020-11-01 16:01:45 -08:00
Matt Nadareski
cff9582bf5 Comment out one of the 3PLock checks 2020-11-01 14:30:32 -08:00
Matt Nadareski
428d839700 Remove outdated TODOs 2020-11-01 14:18:01 -08:00
Matt Nadareski
50db0044b0 Fix MSCab corner case of trailing periods 2020-11-01 14:06:46 -08:00
SilasLaspada
68b1ec7b3f Fix name of INTENIUM protection (#15)
Change ITENIUM to INTENIUM
2020-11-01 10:45:30 -08:00
Matt Nadareski
fd524e1d5c List archive formats in README 2020-10-31 23:57:02 -07:00
Matt Nadareski
ef581c3f36 Add note for MS-CAB 2020-10-31 23:29:27 -07:00
Matt Nadareski
64e67b8daa Gate non-core compatible includes 2020-10-31 23:17:03 -07:00
Matt Nadareski
8624350b82 Why am I doing this? 2020-10-31 22:44:26 -07:00
Matt Nadareski
e3b32fd974 Clear empty keys as you go 2020-10-31 21:20:16 -07:00
Matt Nadareski
6f789d2454 Fix output of in-archive files 2020-10-31 14:57:47 -07:00
Matt Nadareski
d365dd1164 More consistent naming 2020-10-31 14:48:25 -07:00
Matt Nadareski
aa3afd676b Add option for including packers in scan 2020-10-31 14:46:08 -07:00
Matt Nadareski
69a04ff825 Hook up ITENIUM 2020-10-31 14:43:27 -07:00
Matt Nadareski
938e1f94bb Fix CDCheck message (non-false-positive in XCP) 2020-10-31 14:19:41 -07:00
Matt Nadareski
3eda785a5a Skip files with no protection on output 2020-10-31 14:16:51 -07:00
Matt Nadareski
6b895fa7c8 Fix invalid UPX packing versions 2020-10-31 14:15:33 -07:00
Matt Nadareski
45e10a84ae Strip temp paths, add archive name as prefix 2020-10-31 14:14:35 -07:00
Matt Nadareski
81f0400790 Pass-thru scanner, better return types 2020-10-31 14:00:31 -07:00
Matt Nadareski
df90583f73 Scanner shouldn't include path intrinsically 2020-10-31 13:20:54 -07:00
Matt Nadareski
5b980e138a Add scanner to all archive signatures (nw) 2020-10-31 00:06:41 -07:00
Matt Nadareski
0dd71d72ca Add new, but unused, Scanner class 2020-10-30 23:56:27 -07:00
Matt Nadareski
a7364eab67 Comments and a better guard 2020-10-30 21:43:40 -07:00
Matt Nadareski
99013e3448 Separate out archive and non-archive in code 2020-10-30 21:14:07 -07:00
Matt Nadareski
7f5e93db95 Fix 3PLock scanning finally 2020-10-30 17:02:58 -07:00
Matt Nadareski
4aa9662ebe Update README 2020-10-30 09:16:16 -07:00
Matt Nadareski
68dc6c3139 Region-ize the executable scans 2020-10-30 09:11:17 -07:00
Matt Nadareski
8b99577c66 New namespace for packers 2020-10-30 09:09:16 -07:00
Matt Nadareski
20ea1b4427 Fix formatting 2020-10-30 09:02:48 -07:00
SilasLaspada
cf0c6126b9 Add support for detecting NSIS (#14) 2020-10-30 08:56:34 -07:00
Matt Nadareski
49eef3f45a Update README with changes 2020-10-29 11:07:00 -07:00
Matt Nadareski
23e852bbdb Add first ITENIUM check, not hooked up 2020-10-29 11:01:52 -07:00
Matt Nadareski
f182dccbf2 21 -> 321, add a couple protection notes 2020-10-29 10:05:56 -07:00
Matt Nadareski
2d2cff4d0e Add MSI extraction and scanning 2020-10-28 22:51:33 -07:00
Matt Nadareski
c0621a83cb Enable 21Studios scan 2020-10-28 22:51:14 -07:00
Matt Nadareski
3c5da9f7ec Add 21Studios activator detection 2020-10-28 22:49:55 -07:00
Matt Nadareski
a7b5288277 One more EA CDKey detection 2020-10-28 21:03:45 -07:00
Matt Nadareski
fee980e048 CD Check has a valid case again 2020-10-28 16:33:20 -07:00
Matt Nadareski
21eac43e9f Remove unused vars 2020-10-28 13:31:15 -07:00
Matt Nadareski
b55698004c Make it blindingly obvious the files are from an archive 2020-10-28 13:25:58 -07:00
Matt Nadareski
40bdb9b2d9 Use 'i+1' during progress 2020-10-28 13:21:42 -07:00
Matt Nadareski
dfabb1a244 Strip out temp paths from results and progress 2020-10-28 13:17:26 -07:00
Matt Nadareski
cd5f9561bf Pre-scan progress indicator 2020-10-28 13:06:45 -07:00
Matt Nadareski
d8d6fac67e Fix issue with libmspack4n, again 2020-10-28 12:34:33 -07:00
Matt Nadareski
965c32482d Remove note 2020-10-28 12:24:04 -07:00
Matt Nadareski
c8c9d4ac64 Scan whole path for Wise 2020-10-28 12:23:25 -07:00
Matt Nadareski
5f5abf8a14 Scan whole path for Valve 2020-10-28 12:22:29 -07:00
Matt Nadareski
406791b938 Scan whole path for TAP 2020-10-28 12:21:59 -07:00
Matt Nadareski
eb2e6e7029 Scan whole path for 7zip 2020-10-28 12:21:44 -07:00
Matt Nadareski
9f0b41c6aa Scan whole path for RAR 2020-10-28 12:21:26 -07:00
Matt Nadareski
e2b72d8a5b Scan whole folder for PKZIP 2020-10-28 12:20:55 -07:00
Matt Nadareski
9802840309 Scan whole folder for MPQ 2020-10-28 12:20:36 -07:00
Matt Nadareski
4a6e2fd62d Scan whole folder for MSCab 2020-10-28 12:20:07 -07:00
Matt Nadareski
79c706e35a Scan whole folder for ISCab 2020-10-28 12:19:10 -07:00
Matt Nadareski
9be19d6925 Scan whole folder for BFPK 2020-10-28 12:17:10 -07:00
Matt Nadareski
0cfb9907d0 Make archives use full scan, not just content 2020-10-28 12:05:48 -07:00
Matt Nadareski
c18e9b3538 Combine EA protection checks, add/fix reg checks 2020-10-28 11:13:26 -07:00
Matt Nadareski
3754c3a65b Ensure mspack.dll exists for libmspack4n 2020-10-28 10:49:24 -07:00
Matt Nadareski
513a64df4c Rename Cucko and cleanup misc 2020-10-28 10:42:54 -07:00
Matt Nadareski
d18a51c7fa Add SolidShield wrapper check 2020-10-28 10:23:57 -07:00
Matt Nadareski
b43433b9ed Add more EA protection checks 2020-10-28 10:10:43 -07:00
Matt Nadareski
d553395f3f Reorder CDS path checks, change one to fit code 2020-10-27 17:13:35 -07:00
Matt Nadareski
28dbe8542b Add CDS content checks, fix XCP over-detection 2020-10-27 17:01:33 -07:00
Matt Nadareski
912e605dc8 Clarify SafeDisc version identifiers 2020-10-27 14:47:02 -07:00
Matt Nadareski
039982d02d Cleanup on Cactus for future dev work 2020-10-27 14:37:14 -07:00
Matt Nadareski
1a40c6cbb2 SafeDisc... one OR greater 2020-10-27 13:35:57 -07:00
Matt Nadareski
35921e3cac Be smarter about SecuROM strings 2020-10-26 23:30:35 -07:00
Matt Nadareski
a42040d644 Add UPX checking 2020-10-26 23:30:06 -07:00
Matt Nadareski
e1fb1c7bcf Minor renaming 2020-10-26 22:22:46 -07:00
Matt Nadareski
095de1441d Add XCP content checks (thanks to Silas) 2020-10-26 21:08:39 -07:00
Matt Nadareski
43cbafc0f5 Add better detection for XCP2 2020-10-26 20:34:47 -07:00
Matt Nadareski
9143e4c02c Disable CD Check in source due to false positives 2020-10-09 23:12:11 -07:00
Matt Nadareski
2af0692ab4 Update libraries, fix deps, bump to 1.04.1 2020-09-30 23:19:50 -07:00
49 changed files with 2423 additions and 1401 deletions

View File

@@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<Title>BurnOutSharp</Title>
<AssemblyName>BurnOutSharp</AssemblyName>
<Description>Port of BurnOut to C#, with additions</Description>
@@ -10,9 +11,9 @@
<Copyright>Copyright (c)2005-2010 Gernot Knippen, Copyright (c)2018-2020 Matt Nadareski</Copyright>
<PackageLicenseFile>LICENSE.txt</PackageLicenseFile>
<RepositoryUrl>https://github.com/mnadareski/BurnOutSharp</RepositoryUrl>
<Version>1.4.0</Version>
<AssemblyVersion>1.4.0</AssemblyVersion>
<FileVersion>1.04.0</FileVersion>
<Version>1.5.0</Version>
<AssemblyVersion>1.5.0</AssemblyVersion>
<FileVersion>1.5.0</FileVersion>
<IncludeSource>true</IncludeSource>
<IncludeSymbols>true</IncludeSymbols>
</PropertyGroup>
@@ -20,33 +21,36 @@
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)'!='netcoreapp3.1'">
<DefineConstants>NET_FRAMEWORK</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LessIO" Version="0.6.16" />
<PackageReference Include="libmspack4n" Version="0.9.10" />
<PackageReference Include="SharpCompress" Version="0.25.1" />
<PackageReference Include="UnshieldSharp" Version="1.4.2.3" />
<PackageReference Include="WiseUnpacker" Version="1.0.0" />
<PackageReference Include="zlib.net" Version="1.0.4" />
<PackageReference Include="LessIO" Version="1.0.34" Condition="'$(TargetFramework)'!='netcoreapp3.1'" />
<PackageReference Include="libmspack4n" Version="0.9.10" Condition="'$(TargetFramework)'!='netcoreapp3.1'" />
<PackageReference Include="SharpCompress" Version="0.26.0" />
<PackageReference Include="UnshieldSharp" Version="1.4.2.4" />
<PackageReference Include="WiseUnpacker" Version="1.0.1" />
<PackageReference Include="wix-libs" Version="3.11.1" Condition="'$(TargetFramework)'!='netcoreapp3.1'" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE.txt" Pack="true" PackagePath="$(PackageLicenseFile)"/>
<None Include="LICENSE.txt" Pack="true" PackagePath="$(PackageLicenseFile)" />
</ItemGroup>
<ItemGroup>
<None Update="HLLib.x64.dll">
<None Include="*.dll" Pack="true">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
<None Update="HLLib.x86.dll">
<None Include="*.pdb" Pack="true">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
<PackageCopyToOutput>true</PackageCopyToOutput>
</None>
<None Update="StormLib.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="StormLib.pdb">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,438 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BurnOutSharp.ExecutableType
{
internal enum DirectoryEntries
{
IMAGE_DIRECTORY_ENTRY_EXPORT = 0,
IMAGE_DIRECTORY_ENTRY_IMPORT = 1,
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2,
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3,
IMAGE_DIRECTORY_ENTRY_SECURIT = 4,
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5,
IMAGE_DIRECTORY_ENTRY_DEBUG = 6,
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7,
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8, // (MIPS GP)
IMAGE_DIRECTORY_ENTRY_TLS = 9,
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10,
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11,
IMAGE_DIRECTORY_ENTRY_IAT = 12, // Import Address Table
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14,
}
[Flags]
internal enum DllCharacteristics : ushort
{
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 0x0040,
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 0x0080,
IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 0x0100,
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 0x0200,
IMAGE_DLLCHARACTERISTICS_NO_SEH = 0x0400,
IMAGE_DLLCHARACTERISTICS_NO_BIND = 0x0800,
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 0x2000,
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000,
}
[Flags]
internal enum FileCharacteristics : ushort
{
IMAGE_FILE_RELOCS_STRIPPED = 0x0001, /* No relocation info */
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002,
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004,
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008,
IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010,
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020,
IMAGE_FILE_16BIT_MACHINE = 0x0040,
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080,
IMAGE_FILE_32BIT_MACHINE = 0x0100,
IMAGE_FILE_DEBUG_STRIPPED = 0x0200,
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400,
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800,
IMAGE_FILE_SYSTEM = 0x1000,
IMAGE_FILE_DLL = 0x2000,
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000,
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000,
}
internal enum MachineSettings : ushort
{
IMAGE_FILE_MACHINE_UNKNOWN = 0,
IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001,
IMAGE_FILE_MACHINE_I860 = 0x014d,
IMAGE_FILE_MACHINE_I386 = 0x014c,
IMAGE_FILE_MACHINE_R3000 = 0x0162,
IMAGE_FILE_MACHINE_R4000 = 0x0166,
IMAGE_FILE_MACHINE_R10000 = 0x0168,
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169,
IMAGE_FILE_MACHINE_ALPHA = 0x0184,
IMAGE_FILE_MACHINE_SH3 = 0x01a2,
IMAGE_FILE_MACHINE_SH3DSP = 0x01a3,
IMAGE_FILE_MACHINE_SH3E = 0x01a4,
IMAGE_FILE_MACHINE_SH4 = 0x01a6,
IMAGE_FILE_MACHINE_SH5 = 0x01a8,
IMAGE_FILE_MACHINE_ARM = 0x01c0,
IMAGE_FILE_MACHINE_THUMB = 0x01c2,
IMAGE_FILE_MACHINE_ARMNT = 0x01c4,
IMAGE_FILE_MACHINE_ARM64 = 0xaa64,
IMAGE_FILE_MACHINE_AM33 = 0x01d3,
IMAGE_FILE_MACHINE_POWERPC = 0x01f0,
IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1,
IMAGE_FILE_MACHINE_IA64 = 0x0200,
IMAGE_FILE_MACHINE_MIPS16 = 0x0266,
IMAGE_FILE_MACHINE_ALPHA64 = 0x0284,
IMAGE_FILE_MACHINE_MIPSFPU = 0x0366,
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466,
IMAGE_FILE_MACHINE_AXP64 = 0x0284,
IMAGE_FILE_MACHINE_TRICORE = 0x0520,
IMAGE_FILE_MACHINE_CEF = 0x0cef,
IMAGE_FILE_MACHINE_EBC = 0x0ebc,
IMAGE_FILE_MACHINE_AMD64 = 0x8664,
IMAGE_FILE_MACHINE_M32R = 0x9041,
IMAGE_FILE_MACHINE_CEE = 0xc0ee,
}
[Flags]
internal enum SectionCharacteristics : uint
{
IMAGE_SCN_TYPE_REG = 0x00000000, // Reserved
IMAGE_SCN_TYPE_DSECT = 0x00000001, // Reserved
IMAGE_SCN_TYPE_NOLOAD = 0x00000002, // Reserved
IMAGE_SCN_TYPE_GROUP = 0x00000004, // Reserved
IMAGE_SCN_TYPE_NO_PAD = 0x00000008, // Reserved
IMAGE_SCN_TYPE_COPY = 0x00000010, // Reserved
IMAGE_SCN_CNT_CODE = 0x00000020,
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080,
IMAGE_SCN_LNK_OTHER = 0x00000100,
IMAGE_SCN_LNK_INFO = 0x00000200,
IMAGE_SCN_TYPE_OVER = 0x00000400, // Reserved
IMAGE_SCN_LNK_REMOVE = 0x00000800,
IMAGE_SCN_LNK_COMDAT = 0x00001000,
/* 0x00002000 - Reserved */
IMAGE_SCN_MEM_PROTECTED = 0x00004000, // Obsolete
IMAGE_SCN_MEM_FARDATA = 0x00008000,
IMAGE_SCN_MEM_SYSHEAP = 0x00010000, // Obsolete
IMAGE_SCN_MEM_PURGEABLE = 0x00020000,
IMAGE_SCN_MEM_16BIT = 0x00020000,
IMAGE_SCN_MEM_LOCKED = 0x00040000,
IMAGE_SCN_MEM_PRELOAD = 0x00080000,
IMAGE_SCN_ALIGN_1BYTES = 0x00100000,
IMAGE_SCN_ALIGN_2BYTES = 0x00200000,
IMAGE_SCN_ALIGN_4BYTES = 0x00300000,
IMAGE_SCN_ALIGN_8BYTES = 0x00400000,
IMAGE_SCN_ALIGN_16BYTES = 0x00500000, // Default
IMAGE_SCN_ALIGN_32BYTES = 0x00600000,
IMAGE_SCN_ALIGN_64BYTES = 0x00700000,
IMAGE_SCN_ALIGN_128BYTES = 0x00800000,
IMAGE_SCN_ALIGN_256BYTES = 0x00900000,
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000,
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000,
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000,
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000,
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000,
/* 0x00F00000 - Unused */
IMAGE_SCN_ALIGN_MASK = 0x00F00000,
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000,
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000,
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000,
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000,
IMAGE_SCN_MEM_SHARED = 0x10000000,
IMAGE_SCN_MEM_EXECUTE = 0x20000000,
IMAGE_SCN_MEM_READ = 0x40000000,
IMAGE_SCN_MEM_WRITE = 0x80000000,
}
internal enum Subsystem : ushort
{
IMAGE_SUBSYSTEM_UNKNOWN = 0,
IMAGE_SUBSYSTEM_NATIVE = 1,
IMAGE_SUBSYSTEM_WINDOWS_GUI = 2, // Windows GUI subsystem
IMAGE_SUBSYSTEM_WINDOWS_CUI = 3, // Windows character subsystem
IMAGE_SUBSYSTEM_OS2_CUI = 5,
IMAGE_SUBSYSTEM_POSIX_CUI = 7,
IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8, // native Win9x driver
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9, // Windows CE subsystem
IMAGE_SUBSYSTEM_EFI_APPLICATION = 10,
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11,
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12,
IMAGE_SUBSYSTEM_EFI_ROM = 13,
IMAGE_SUBSYSTEM_XBOX = 14,
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16,
}
internal static class Constants
{
public const ushort IMAGE_DOS_SIGNATURE = 0x5A4D; /* MZ */
public const ushort IMAGE_OS2_SIGNATURE = 0x454E; /* NE */
public const ushort IMAGE_OS2_SIGNATURE_LE = 0x454C; /* LE */
public const ushort IMAGE_OS2_SIGNATURE_LX = 0x584C; /* LX */
public const ushort IMAGE_VXD_SIGNATURE = 0x454C; /* LE */
public const uint IMAGE_NT_SIGNATURE = 0x00004550; /* PE00 */
public const int IMAGE_SIZEOF_FILE_HEADER = 20;
public const int IMAGE_SIZEOF_ROM_OPTIONAL_HEADER = 56;
public const int IMAGE_SIZEOF_STD_OPTIONAL_HEADER = 28;
public const int IMAGE_SIZEOF_NT_OPTIONAL32_HEADER = 224;
public const int IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240;
public const int IMAGE_SIZEOF_SHORT_NAME = 8;
public const int IMAGE_SIZEOF_SECTION_HEADER = 40;
public const int IMAGE_SIZEOF_SYMBOL = 18;
public const int IMAGE_SIZEOF_AUX_SYMBOL = 18;
public const int IMAGE_SIZEOF_RELOCATION = 10;
public const int IMAGE_SIZEOF_BASE_RELOCATION = 8;
public const int IMAGE_SIZEOF_LINENUMBER = 6;
public const int IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR = 60;
// Possible Magic values
public const ushort IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
public const ushort IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
public const ushort IMAGE_ROM_OPTIONAL_HDR_MAGIC = 0x107;
public const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
}
internal class IMAGE_DOS_HEADER
{
ushort e_magic; /* 00: MZ Header signature */
ushort e_cblp; /* 02: Bytes on last page of file */
ushort e_cp; /* 04: Pages in file */
ushort e_crlc; /* 06: Relocations */
ushort e_cparhdr; /* 08: Size of header in paragraphs */
ushort e_minalloc; /* 0a: Minimum extra paragraphs needed */
ushort e_maxalloc; /* 0c: Maximum extra paragraphs needed */
ushort e_ss; /* 0e: Initial (relative) SS value */
ushort e_sp; /* 10: Initial SP value */
ushort e_csum; /* 12: Checksum */
ushort e_ip; /* 14: Initial IP value */
ushort e_cs; /* 16: Initial (relative) CS value */
ushort e_lfarlc; /* 18: File address of relocation table */
ushort e_ovno; /* 1a: Overlay number */
ushort[] e_res; /* 1c: Reserved words [4] */
ushort e_oemid; /* 24: OEM identifier (for e_oeminfo) */
ushort e_oeminfo; /* 26: OEM information; e_oemid specific */
ushort[] e_res2; /* 28: Reserved words [10] */
uint e_lfanew; /* 3c: Offset to extended header */
}
internal class IMAGE_OS2_HEADER
{
ushort ne_magic; /* 00 NE signature 'NE' */
byte ne_ver; /* 02 Linker version number */
byte ne_rev; /* 03 Linker revision number */
ushort ne_enttab; /* 04 Offset to entry table relative to NE */
ushort ne_cbenttab; /* 06 Length of entry table in bytes */
uint ne_crc; /* 08 Checksum */
ushort ne_flags; /* 0c Flags about segments in this file */
ushort ne_autodata; /* 0e Automatic data segment number */
ushort ne_heap; /* 10 Initial size of local heap */
ushort ne_stack; /* 12 Initial size of stack */
uint ne_csip; /* 14 Initial CS:IP */
uint ne_sssp; /* 18 Initial SS:SP */
ushort ne_cseg; /* 1c # of entries in segment table */
ushort ne_cmod; /* 1e # of entries in module reference tab. */
ushort ne_cbnrestab; /* 20 Length of nonresident-name table */
ushort ne_segtab; /* 22 Offset to segment table */
ushort ne_rsrctab; /* 24 Offset to resource table */
ushort ne_restab; /* 26 Offset to resident-name table */
ushort ne_modtab; /* 28 Offset to module reference table */
ushort ne_imptab; /* 2a Offset to imported name table */
uint ne_nrestab; /* 2c Offset to nonresident-name table */
ushort ne_cmovent; /* 30 # of movable entry points */
ushort ne_align; /* 32 Logical sector alignment shift count */
ushort ne_cres; /* 34 # of resource segments */
byte ne_exetyp; /* 36 Flags indicating target OS */
byte ne_flagsothers; /* 37 Additional information flags */
ushort ne_pretthunks; /* 38 Offset to return thunks */
ushort ne_psegrefbytes; /* 3a Offset to segment ref. bytes */
ushort ne_swaparea; /* 3c Reserved by Microsoft */
ushort ne_expver; /* 3e Expected Windows version number */
}
internal class IMAGE_VXD_HEADER
{
ushort e32_magic;
byte e32_border;
byte e32_worder;
uint e32_level;
ushort e32_cpu;
ushort e32_os;
uint e32_ver;
uint e32_mflags;
uint e32_mpages;
uint e32_startobj;
uint e32_eip;
uint e32_stackobj;
uint e32_esp;
uint e32_pagesize;
uint e32_lastpagesize;
uint e32_fixupsize;
uint e32_fixupsum;
uint e32_ldrsize;
uint e32_ldrsum;
uint e32_objtab;
uint e32_objcnt;
uint e32_objmap;
uint e32_itermap;
uint e32_rsrctab;
uint e32_rsrccnt;
uint e32_restab;
uint e32_enttab;
uint e32_dirtab;
uint e32_dircnt;
uint e32_fpagetab;
uint e32_frectab;
uint e32_impmod;
uint e32_impmodcnt;
uint e32_impproc;
uint e32_pagesum;
uint e32_datapage;
uint e32_preload;
uint e32_nrestab;
uint e32_cbnrestab;
uint e32_nressum;
uint e32_autodata;
uint e32_debuginfo;
uint e32_debuglen;
uint e32_instpreload;
uint e32_instdemand;
uint e32_heapsize;
byte[] e32_res3; // [12]
uint e32_winresoff;
uint e32_winreslen;
ushort e32_devid;
ushort e32_ddkver;
}
internal class IMAGE_FILE_HEADER
{
ushort Machine;
ushort NumberOfSections;
uint TimeDateStamp;
uint PointerToSymbolTable;
uint NumberOfSymbols;
ushort SizeOfOptionalHeader;
ushort Characteristics;
}
internal class IMAGE_DATA_DIRECTORY
{
uint VirtualAddress;
uint Size;
}
internal class IMAGE_OPTIONAL_HEADER64
{
ushort Magic; /* 0x20b */
byte MajorLinkerVersion;
byte MinorLinkerVersion;
uint SizeOfCode;
uint SizeOfInitializedData;
uint SizeOfUninitializedData;
uint AddressOfEntryPoint;
uint BaseOfCode;
ulong ImageBase;
uint SectionAlignment;
uint FileAlignment;
ushort MajorOperatingSystemVersion;
ushort MinorOperatingSystemVersion;
ushort MajorImageVersion;
ushort MinorImageVersion;
ushort MajorSubsystemVersion;
ushort MinorSubsystemVersion;
uint Win32VersionValue;
uint SizeOfImage;
uint SizeOfHeaders;
uint CheckSum;
ushort Subsystem;
ushort DllCharacteristics;
ulong SizeOfStackReserve;
ulong SizeOfStackCommit;
ulong SizeOfHeapReserve;
ulong SizeOfHeapCommit;
uint LoaderFlags;
uint NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY[] DataDirectory; // [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
}
internal class IMAGE_NT_HEADERS64
{
uint Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
}
internal class IMAGE_OPTIONAL_HEADER32
{
/* Standard fields */
ushort Magic; /* 0x10b or 0x107 */ /* 0x00 */
byte MajorLinkerVersion;
byte MinorLinkerVersion;
uint SizeOfCode;
uint SizeOfInitializedData;
uint SizeOfUninitializedData;
uint AddressOfEntryPoint; /* 0x10 */
uint BaseOfCode;
uint BaseOfData;
/* NT additional fields */
uint ImageBase;
uint SectionAlignment; /* 0x20 */
uint FileAlignment;
ushort MajorOperatingSystemVersion;
ushort MinorOperatingSystemVersion;
ushort MajorImageVersion;
ushort MinorImageVersion;
ushort MajorSubsystemVersion; /* 0x30 */
ushort MinorSubsystemVersion;
uint Win32VersionValue;
uint SizeOfImage;
uint SizeOfHeaders;
uint CheckSum; /* 0x40 */
ushort Subsystem;
ushort DllCharacteristics;
uint SizeOfStackReserve;
uint SizeOfStackCommit;
uint SizeOfHeapReserve; /* 0x50 */
uint SizeOfHeapCommit;
uint LoaderFlags;
uint NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY[] DataDirectory; /* 0x60, [IMAGE_NUMBEROF_DIRECTORY_ENTRIES] */
/* 0xE0 */
}
internal class IMAGE_NT_HEADERS32
{
uint Signature; /* "PE"\0\0 */ /* 0x00 */
IMAGE_FILE_HEADER FileHeader; /* 0x04 */
IMAGE_OPTIONAL_HEADER32 OptionalHeader; /* 0x18 */
}
internal class IMAGE_SECTION_HEADER
{
byte[] Name; // [IMAGE_SIZEOF_SHORT_NAME];
uint PhysicalAddressOrVirtualSize; // Misc
uint VirtualAddress;
uint SizeOfRawData;
uint PointerToRawData;
uint PointerToRelocations;
uint PointerToLinenumbers;
ushort NumberOfRelocations;
ushort NumberOfLinenumbers;
uint Characteristics;
}
}

View File

@@ -1,146 +1,128 @@
using System;
using System.IO;
using System.Linq;
namespace BurnOutSharp.External.psxt001z
{
/// <summary>
/// LibCrypt detection code
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
/// Ported and changed by darksabre76
/// </summary>
public class LibCrypt
/// <summary>
/// LibCrypt detection code
/// Originally written by Dremora: https://github.com/Dremora/psxt001z
/// Ported and changed by darksabre76
/// </summary>
public class LibCrypt
{
public static bool CheckSubfile(string subFilePath)
{
// Check the file exists first
if (!File.Exists(subFilePath))
{
Console.WriteLine($"{subFilePath} could not be found");
return false;
}
// Check the file exists first
if (!File.Exists(subFilePath))
return false;
// Check the extension is a subfile
string ext = Path.GetExtension(subFilePath).TrimStart('.').ToLowerInvariant();
if (ext != "sub")
{
Console.WriteLine($"{ext}: unknown file extension");
return false;
}
// Check the extension is a subfile
string ext = Path.GetExtension(subFilePath).TrimStart('.').ToLowerInvariant();
if (ext != "sub")
return false;
// Open and check the subfile for LibCrypt
try
{
using (FileStream subfile = File.OpenRead(subFilePath))
{
return CheckSubfile(subfile);
}
}
catch
{
Console.WriteLine($"Error processing {subFilePath}");
return false;
}
}
// Open and check the subfile for LibCrypt
try
{
using (FileStream subfile = File.OpenRead(subFilePath))
{
return CheckSubfile(subfile);
}
}
catch
{
return false;
}
}
public static bool CheckSubfile(Stream subfile)
{
// Check the length is valid for subfiles
long size = subfile.Length;
if (size % 96 != 0)
{
Console.WriteLine($"Wrong size");
return false;
}
public static bool CheckSubfile(Stream subfile)
{
// Check the length is valid for subfiles
long size = subfile.Length;
if (size % 96 != 0)
return false;
// Persistent values
byte[] buffer = new byte[16];
byte[] sub = new byte[16];
int tpos = 0;
int modifiedSectors = 0;
// Persistent values
byte[] buffer = new byte[16];
byte[] sub = new byte[16];
int tpos = 0;
int modifiedSectors = 0;
// Check each sector for modifications
for (uint sector = 150; sector < ((size / 96) + 150); sector++)
{
subfile.Seek(12, SeekOrigin.Current);
if (subfile.Read(buffer, 0, 12) == 0)
return modifiedSectors != 0;
// Check each sector for modifications
for (uint sector = 150; sector < ((size / 96) + 150); sector++)
{
subfile.Seek(12, SeekOrigin.Current);
if (subfile.Read(buffer, 0, 12) == 0)
return modifiedSectors != 0;
subfile.Seek(72, SeekOrigin.Current);
subfile.Seek(72, SeekOrigin.Current);
// New track
if ((btoi(buffer[1]) == (btoi(sub[1]) + 1)) && (buffer[2] == 0 || buffer[2] == 1))
{
Array.Copy(buffer, sub, 6);
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
}
// New track
if ((btoi(buffer[1]) == (btoi(sub[1]) + 1)) && (buffer[2] == 0 || buffer[2] == 1))
{
Array.Copy(buffer, sub, 6);
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
}
// New index
else if (btoi(buffer[2]) == (btoi(sub[2]) + 1) && buffer[1] == sub[1])
{
Array.Copy(buffer, 2, sub, 2, 4);
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
}
// New index
else if (btoi(buffer[2]) == (btoi(sub[2]) + 1) && buffer[1] == sub[1])
{
Array.Copy(buffer, 2, sub, 2, 4);
tpos = ((btoi((byte)(buffer[3] * 60)) + btoi(buffer[4])) * 75) + btoi(buffer[5]);
}
// MSF1 [3-5]
else
{
if (sub[2] == 0)
tpos--;
else
tpos++;
// MSF1 [3-5]
else
{
if (sub[2] == 0)
tpos--;
else
tpos++;
sub[3] = itob((byte)(tpos / 60 / 75));
sub[4] = itob((byte)((tpos / 75) % 60));
sub[5] = itob((byte)(tpos % 75));
}
sub[3] = itob((byte)(tpos / 60 / 75));
sub[4] = itob((byte)((tpos / 75) % 60));
sub[5] = itob((byte)(tpos % 75));
}
// MSF2 [7-9]
sub[7] = itob((byte)(sector / 60 / 75));
sub[8] = itob((byte)((sector / 75) % 60));
sub[9] = itob((byte)(sector % 75));
// MSF2 [7-9]
sub[7] = itob((byte)(sector / 60 / 75));
sub[8] = itob((byte)((sector / 75) % 60));
sub[9] = itob((byte)(sector % 75));
// CRC-16 [10-11]
ushort crc = CRC16.Calculate(sub, 0, 10);
byte[] crcBytes = BitConverter.GetBytes(crc);
sub[10] = crcBytes[0];
sub[11] = crcBytes[1];
// CRC-16 [10-11]
ushort crc = CRC16.Calculate(sub, 0, 10);
byte[] crcBytes = BitConverter.GetBytes(crc);
sub[10] = crcBytes[0];
sub[11] = crcBytes[1];
// TODO: This *was* a memcmp, but that's harder to do. Fix this for C# later
if (buffer[10] != sub[10] && buffer[11] != sub[11] && (buffer[3] != sub[3] || buffer[4] != sub[4] || buffer[5] != sub[5] || buffer[7] != sub[7] || buffer[8] != sub[8] || buffer[9] != sub[9]))
{
if (buffer[3] != sub[3] || buffer[4] != sub[4] || buffer[5] != sub[5] || buffer[7] != sub[7] || buffer[8] != sub[8] || buffer[9] != sub[9] || buffer[10] != sub[10] || buffer[11] != sub[11])
{
Console.Write($"MSF: {sub[7]:x}:{sub[8]:x}:{sub[9]:x} Q-Data: {buffer[0]:x}{buffer[1]:x}{buffer[2]:x} {buffer[3]:x}:{buffer[4]:x}:{buffer[5]:x} {buffer[6]:x} {buffer[7]:x}:{buffer[8]:x}:{buffer[9]:x} {buffer[10]:x}{buffer[11]:x} xor {crc ^ ((buffer[10] << 8) + buffer[11]):x} % {CRC16.Calculate(buffer, 0, 10) ^ ((buffer[10] << 8) + buffer[11]):x}");
//Console.Write($"\nMSF: {sub[7]:x}:{sub[8]:x}:{sub[9]:x} Q-Data: {sub[0]:x}{sub[1]:x}{sub[2]:x} {sub[3]:x}:{sub[4]:x}:{sub[5]:x} {sub[6]:x} {sub[7]:x}:{sub[8]:x}:{sub[9]:x} {sub[10]:x}{sub[11]:x}");
if (buffer[3] != sub[3] && buffer[7] != sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
Console.Write($" P1 xor {buffer[3] ^ sub[3]:x} {buffer[7] ^ sub[7]:x}");
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] != sub[4] && buffer[8] != sub[8] && buffer[5] == sub[5] && buffer[9] == sub[9])
Console.Write($" P2 xor {buffer[4] ^ sub[4]:x} {buffer[8] ^ sub[8]:x}");
else if (buffer[3] == sub[3] && buffer[7] == sub[7] && buffer[4] == sub[4] && buffer[8] == sub[8] && buffer[5] != sub[5] && buffer[9] != sub[9])
Console.Write($" P3 xor {buffer[5] ^ sub[5]:x} {buffer[9] ^ sub[9]:x}");
else
Console.Write(" ?");
// If any byte (except position 6) is different, it's a modified sector
for (int i = 0; i < 12; i++)
{
if (i == 6)
continue;
Console.Write("\n");
modifiedSectors++;
}
}
}
if (buffer[i] != sub[i])
{
modifiedSectors++;
break;
}
}
}
Console.WriteLine($"Number of modified sectors: {modifiedSectors}");
return modifiedSectors != 0;
}
return modifiedSectors != 0;
}
private static byte btoi(byte b)
{
/* BCD to u_char */
return (byte)((b) / 16 * 10 + (b) % 16);
}
private static byte btoi(byte b)
{
/* BCD to u_char */
return (byte)((b) / 16 * 10 + (b) % 16);
}
private static byte itob(byte i)
{
/* u_char to BCD */
return (byte)((i) / 10 * 16 + (i) % 10);
}
}
private static byte itob(byte i)
{
/* u_char to BCD */
return (byte)((i) / 10 * 16 + (i) % 10);
}
}
}

View File

@@ -17,10 +17,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the BFPK file itself fails
try
{
@@ -87,36 +85,31 @@ namespace BurnOutSharp.FileType
}
}
}
string protection = ProtectionFind.ScanContent(tempFile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempFile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add(tempFile);
}
catch { }
br.BaseStream.Seek(current, SeekOrigin.Begin);
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;
@@ -16,10 +17,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the 7-zip file itself fails
try
{
@@ -31,37 +30,33 @@ namespace BurnOutSharp.FileType
// If an individual entry fails
try
{
string tempfile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempfile))
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
bz2File.CopyTo(fs);
}
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{protection}");
}
catch { }
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using BurnOutSharp.PackerType;
using BurnOutSharp.ProtectionType;
namespace BurnOutSharp.FileType
@@ -40,7 +41,7 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, string file = null, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream, string file = null)
{
// Load the current file content
byte[] fileContent = null;
@@ -54,199 +55,242 @@ namespace BurnOutSharp.FileType
stream.Seek(0, SeekOrigin.Begin);
// Files can be protected in multiple ways
List<string> protections = new List<string>();
List<string> subProtections = new List<string>();
var protections = new Dictionary<string, List<string>>();
var subProtections = new Dictionary<string, List<string>>();
string protection;
#region Protections
// 3PLock
protection = ThreePLock.CheckContents(fileContent, includePosition);
protection = ThreePLock.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// 321Studios Online Activation
protection = ThreeTwoOneStudios.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// ActiveMARK
protection = ActiveMARK.CheckContents(fileContent, includePosition);
protection = ActiveMARK.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Alpha-ROM
protection = AlphaROM.CheckContents(fileContent, includePosition);
protection = AlphaROM.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Armadillo
protection = Armadillo.CheckContents(fileContent, includePosition);
// Cactus Data Shield
protection = CactusDataShield.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// CD-Cops
protection = CDCops.CheckContents(fileContent, includePosition);
protection = CDCops.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// CD-Lock
protection = CDLock.CheckContents(fileContent, includePosition);
protection = CDLock.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// CDSHiELD SE
protection = CDSHiELDSE.CheckContents(fileContent, includePosition);
protection = CDSHiELDSE.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// CD Check
protection = CDCheck.CheckContents(fileContent, includePosition);
protection = CDCheck.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Cenega ProtectDVD
protection = CengaProtectDVD.CheckContents(fileContent, includePosition);
protection = CengaProtectDVD.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Code Lock
protection = CodeLock.CheckContents(fileContent, includePosition);
protection = CodeLock.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// CopyKiller
protection = CopyKiller.CheckContents(fileContent, includePosition);
protection = CopyKiller.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Cucko (EA Custom)
protection = Cucko.CheckContents(fileContent, includePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// dotFuscator
protection = dotFuscator.CheckContents(fileContent, includePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// DVD-Cops
protection = DVDCops.CheckContents(fileContent, includePosition);
protection = DVDCops.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// EA CdKey Registration Module
protection = EACdKey.CheckContents(fileContent, includePosition);
// EA Protections
protection = ElectronicArts.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// EXE Stealth
protection = EXEStealth.CheckContents(fileContent, includePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Games for Windows - Live
protection = GFWL.CheckContents(fileContent, includePosition);
protection = GFWL.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Impulse Reactor
protection = ImpulseReactor.CheckContents(file, fileContent, includePosition);
protection = ImpulseReactor.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Inno Setup
protection = InnoSetup.CheckContents(fileContent, includePosition);
protection = InnoSetup.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// INTENIUM Trial & Buy Protection
protection = Intenium.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// JoWooD X-Prot
protection = JoWooDXProt.CheckContents(fileContent, includePosition);
protection = JoWooDXProt.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Key-Lock (Dongle)
protection = KeyLock.CheckContents(fileContent, includePosition);
protection = KeyLock.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// LaserLock
protection = LaserLock.CheckContents(file, fileContent, includePosition);
protection = LaserLock.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// PE Compact
protection = PECompact.CheckContents(fileContent, includePosition);
// MediaMax CD-3
protection = MediaMaxCD3.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// ProtectDisc
protection = ProtectDisc.CheckContents(file, fileContent, includePosition);
protection = ProtectDisc.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Ring PROTECH
protection = RingPROTECH.CheckContents(fileContent, includePosition);
protection = RingPROTECH.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SafeDisc / SafeCast
protection = SafeDisc.CheckContents(file, fileContent, includePosition);
protection = SafeDisc.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SafeLock
protection = SafeLock.CheckContents(fileContent, includePosition);
protection = SafeLock.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SecuROM
protection = SecuROM.CheckContents(file, fileContent, includePosition);
protection = SecuROM.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SmartE
protection = SmartE.CheckContents(fileContent, includePosition);
protection = SmartE.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SolidShield
protection = SolidShield.CheckContents(file, fileContent, includePosition);
protection = SolidShield.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// StarForce
protection = StarForce.CheckContents(file, fileContent, includePosition);
protection = StarForce.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// SVK Protector
protection = SVKProtector.CheckContents(fileContent, includePosition);
protection = SVKProtector.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Sysiphus / Sysiphus DVD
protection = Sysiphus.CheckContents(fileContent, includePosition);
protection = Sysiphus.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// TAGES
protection = Tages.CheckContents(file, fileContent, includePosition);
protection = Tages.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// VOB ProtectCD/DVD
protection = VOBProtectCDDVD.CheckContents(file, fileContent, includePosition);
protection = VOBProtectCDDVD.CheckContents(file, fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// Wise Installer
subProtections = WiseInstaller.CheckContents(file, fileContent, includePosition);
subProtections = WiseInstaller.CheckContents(scanner, file, fileContent);
if (subProtections != null && subProtections.Count > 0)
protections.AddRange(subProtections);
Utilities.AppendToDictionary(protections, subProtections);
// WTM CD Protect
protection = WTMCDProtect.CheckContents(fileContent, includePosition);
protection = WTMCDProtect.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
// XCP 1/2
protection = XCP.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// Xtreme-Protector
protection = XtremeProtector.CheckContents(fileContent, includePosition);
protection = XtremeProtector.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
Utilities.AppendToDictionary(protections, file, protection);
#endregion
#region Packers
// If we're looking for packers too, run scans
if (scanner.ScanPackers)
{
// Armadillo
protection = Armadillo.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// dotFuscator
protection = dotFuscator.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// EXE Stealth
protection = EXEStealth.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// NSIS
protection = NSIS.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// PE Compact
protection = PECompact.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
// UPX
protection = UPX.CheckContents(fileContent, scanner.IncludePosition);
if (!string.IsNullOrWhiteSpace(protection))
Utilities.AppendToDictionary(protections, file, protection);
}
#endregion
return protections;
}

View File

@@ -16,10 +16,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the gzip file itself fails
try
{
@@ -37,34 +35,31 @@ namespace BurnOutSharp.FileType
if (entry.IsDirectory)
continue;
string tempfile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{entry.Key} - {protection}");
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -0,0 +1,296 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace BurnOutSharp.FileType
{
public class IniFile : IDictionary<string, string>
{
private Dictionary<string, string> _keyValuePairs = new Dictionary<string, string>();
public string this[string key]
{
get
{
if (_keyValuePairs == null)
_keyValuePairs = new Dictionary<string, string>();
key = key.ToLowerInvariant();
if (_keyValuePairs.ContainsKey(key))
return _keyValuePairs[key];
return null;
}
set
{
if (_keyValuePairs == null)
_keyValuePairs = new Dictionary<string, string>();
key = key.ToLowerInvariant();
_keyValuePairs[key] = value;
}
}
/// <summary>
/// Create an empty INI file
/// </summary>
public IniFile()
{
}
/// <summary>
/// Populate an INI file from path
/// </summary>
public IniFile(string path)
{
this.Parse(path);
}
/// <summary>
/// Populate an INI file from stream
/// </summary>
public IniFile(Stream stream)
{
this.Parse(stream);
}
/// <summary>
/// Add or update a key and value to the INI file
/// </summary>
public void AddOrUpdate(string key, string value)
{
_keyValuePairs[key.ToLowerInvariant()] = value;
}
/// <summary>
/// Remove a key from the INI file
/// </summary>
public void Remove(string key)
{
_keyValuePairs.Remove(key.ToLowerInvariant());
}
/// <summary>
/// Read an INI file based on the path
/// </summary>
public bool Parse(string path)
{
// If we don't have a file, we can't read it
if (!File.Exists(path))
return false;
using (var fileStream = File.OpenRead(path))
{
return Parse(fileStream);
}
}
/// <summary>
/// Read an INI file from a stream
/// </summary>
public bool Parse(Stream stream)
{
// If the stream is invalid or unreadable, we can't process it
if (stream == null || !stream.CanRead || stream.Position >= stream.Length - 1)
return false;
// Keys are case-insensitive by default
try
{
using (StreamReader sr = new StreamReader(stream))
{
string section = string.Empty;
while (!sr.EndOfStream)
{
string line = sr.ReadLine().Trim();
// Comments start with ';'
if (line.StartsWith(";"))
{
// No-op, we don't process comments
}
// Section titles are surrounded by square brackets
else if (line.StartsWith("["))
{
section = line.TrimStart('[').TrimEnd(']');
}
// Valid INI lines are in the format key=value
else if (line.Contains("="))
{
// Split the line by '=' for key-value pairs
string[] data = line.Split('=');
// If the value field contains an '=', we need to put them back in
string key = data[0].Trim();
string value = string.Join("=", data.Skip(1)).Trim();
// Section names are prepended to the key with a '.' separating
if (!string.IsNullOrEmpty(section))
key = $"{section}.{key}";
// Set or overwrite keys in the returned dictionary
_keyValuePairs[key.ToLowerInvariant()] = value;
}
// All other lines are ignored
}
}
}
catch
{
// We don't care what the error was, just catch and return
return false;
}
return true;
}
/// <summary>
/// Write an INI file to a path
/// </summary>
public bool Write(string path)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
return false;
using (var fileStream = File.OpenWrite(path))
{
return Write(fileStream);
}
}
/// <summary>
/// Write an INI file to a stream
/// </summary>
public bool Write(Stream stream)
{
// If we don't have a valid dictionary with values, we can't write out
if (_keyValuePairs == null || _keyValuePairs.Count == 0)
return false;
// If the stream is invalid or unwritable, we can't output to it
if (stream == null || !stream.CanWrite || stream.Position >= stream.Length - 1)
return false;
try
{
using (StreamWriter sw = new StreamWriter(stream))
{
// Order the dictionary by keys to link sections together
var orderedKeyValuePairs = _keyValuePairs.OrderBy(kvp => kvp.Key);
string section = string.Empty;
foreach (var keyValuePair in orderedKeyValuePairs)
{
// Extract the key and value
string key = keyValuePair.Key;
string value = keyValuePair.Value;
// We assume '.' is a section name separator
if (key.Contains('.'))
{
// Split the key by '.'
string[] data = keyValuePair.Key.Split('.');
// If the key contains an '.', we need to put them back in
string newSection = data[0].Trim();
key = string.Join(".", data.Skip(1)).Trim();
// If we have a new section, write it out
if (!string.Equals(newSection, section, StringComparison.OrdinalIgnoreCase))
{
sw.WriteLine($"[{newSection}]");
section = newSection;
}
}
// Now write out the key and value in a standardized way
sw.WriteLine($"{key}={value}");
}
}
}
catch
{
// We don't care what the error was, just catch and return
return false;
}
return true;
}
#region IDictionary Impelementations
public ICollection<string> Keys => ((IDictionary<string, string>)_keyValuePairs).Keys;
public ICollection<string> Values => ((IDictionary<string, string>)_keyValuePairs).Values;
public int Count => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Count;
public bool IsReadOnly => ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).IsReadOnly;
public void Add(string key, string value)
{
((IDictionary<string, string>)_keyValuePairs).Add(key.ToLowerInvariant(), value);
}
bool IDictionary<string, string>.Remove(string key)
{
return ((IDictionary<string, string>)_keyValuePairs).Remove(key.ToLowerInvariant());
}
public bool TryGetValue(string key, out string value)
{
return ((IDictionary<string, string>)_keyValuePairs).TryGetValue(key.ToLowerInvariant(), out value);
}
public void Add(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Add(newItem);
}
public void Clear()
{
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Clear();
}
public bool Contains(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Contains(newItem);
}
public bool ContainsKey(string key)
{
return _keyValuePairs.ContainsKey(key.ToLowerInvariant());
}
public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<string, string>>)_keyValuePairs).CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<string, string> item)
{
var newItem = new KeyValuePair<string, string>(item.Key.ToLowerInvariant(), item.Value);
return ((ICollection<KeyValuePair<string, string>>)_keyValuePairs).Remove(newItem);
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return ((IEnumerable<KeyValuePair<string, string>>)_keyValuePairs).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_keyValuePairs).GetEnumerator();
}
#endregion
}
}

View File

@@ -17,10 +17,8 @@ namespace BurnOutSharp.FileType
}
// TODO: Add stream opening support
public static List<string> Scan(string file, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
List<string> protections = new List<string>();
// Get the name of the first cabinet file or header
string directory = Path.GetDirectoryName(file);
string noExtension = Path.GetFileNameWithoutExtension(file);
@@ -48,35 +46,30 @@ namespace BurnOutSharp.FileType
try
{
string tempFile = Path.Combine(tempPath, cabfile.FileName(i));
if (cabfile.FileSave(i, tempFile))
{
string protection = ProtectionFind.ScanContent(tempFile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempFile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{cabfile.FileName(i)} - {protection}");
}
cabfile.FileSave(i, tempFile);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
}
return protections;
return null;
}
}
}

View File

@@ -16,10 +16,8 @@ namespace BurnOutSharp.FileType
}
// TODO: Add stream opening support
public static List<string> Scan(string file, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
List<string> protections = new List<string>();
// If the mpq file itself fails
try
{
@@ -35,7 +33,6 @@ namespace BurnOutSharp.FileType
using (StreamReader sr = new StreamReader(listStream))
{
listfile = sr.ReadToEnd();
Console.WriteLine(listfile);
}
string sub = string.Empty;
@@ -44,35 +41,32 @@ namespace BurnOutSharp.FileType
// If an individual entry fails
try
{
string tempfile = Path.Combine(tempPath, sub);
Directory.CreateDirectory(Path.GetDirectoryName(tempfile));
mpqArchive.ExtractFile(sub, tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{sub} - {protection}");
string tempFile = Path.Combine(tempPath, sub);
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
mpqArchive.ExtractFile(sub, tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET_FRAMEWORK
using Microsoft.Deployment.WindowsInstaller;
#endif
namespace BurnOutSharp.FileType
{
internal class MSI
{
public static bool ShouldScan(byte[] magic)
{
#if NET_FRAMEWORK
if (magic.StartsWith(new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }))
return true;
#endif
return false;
}
// TODO: Add stream opening support
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
#if NET_FRAMEWORK
// If the MSI file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly))
{
msidb.ExportAll(tempPath);
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
#endif
return null;
}
}
}

View File

@@ -1,25 +1,29 @@
using System;
using System.Collections.Generic;
using System.IO;
#if NET_FRAMEWORK
using LibMSPackN;
#endif
namespace BurnOutSharp.FileType
{
// Specification available at http://download.microsoft.com/download/5/0/1/501ED102-E53F-4CE0-AA6B-B0F93629DDC6/Exchange/%5BMS-CAB%5D.pdf
internal class MicrosoftCAB
{
public static bool ShouldScan(byte[] magic)
{
#if NET_FRAMEWORK
if (magic.StartsWith(new byte[] { 0x4d, 0x53, 0x43, 0x46 }))
return true;
#endif
return false;
}
// TODO: Add stream opening support
public static List<string> Scan(string file, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
List<string> protections = new List<string>();
#if NET_FRAMEWORK
// If the cab file itself fails
try
{
@@ -33,34 +37,33 @@ namespace BurnOutSharp.FileType
// If an individual entry fails
try
{
string tempfile = Path.Combine(tempPath, sub.Filename);
sub.ExtractTo(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{sub.Filename} - {protection}");
// The trim here is for some very odd and stubborn files
string tempFile = Path.Combine(tempPath, sub.Filename.TrimEnd('.'));
sub.ExtractTo(tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
#endif
return protections;
return null;
}
}
}

View File

@@ -25,10 +25,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the zip file itself fails
try
{
@@ -46,34 +44,31 @@ namespace BurnOutSharp.FileType
if (entry.IsDirectory)
continue;
string tempfile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{entry.Key} - {protection}");
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -21,10 +21,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the rar file itself fails
try
{
@@ -42,34 +40,31 @@ namespace BurnOutSharp.FileType
if (entry.IsDirectory)
continue;
string tempfile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{entry.Key} - {protection}");
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -16,10 +16,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the 7-zip file itself fails
try
{
@@ -37,34 +35,31 @@ namespace BurnOutSharp.FileType
if (entry.IsDirectory)
continue;
string tempfile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{entry.Key} - {protection}");
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -19,10 +19,8 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the tar file itself fails
try
{
@@ -40,34 +38,31 @@ namespace BurnOutSharp.FileType
if (entry.IsDirectory)
continue;
string tempfile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempfile);
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{entry.Key} - {protection}");
string tempFile = Path.Combine(tempPath, entry.Key);
entry.WriteToFile(tempFile);
}
catch { }
}
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -26,13 +26,13 @@ namespace BurnOutSharp.FileType
return true;
// Generic textfile (no header)
if (string.Equals(extension, "txt", StringComparison.OrdinalIgnoreCase))
if (string.Equals(extension.TrimStart('.'), "txt", StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static List<string> Scan(Stream stream)
{
List<string> protections = new List<string>();
@@ -40,17 +40,20 @@ namespace BurnOutSharp.FileType
{
// Load the current file content
string fileContent = null;
using (StreamReader sr = new StreamReader(stream, Encoding.Default, false, 1024 * 1024, true))
using (var sr = new StreamReader(stream, Encoding.Default, true, 1024 * 1024, true))
{
fileContent = sr.ReadToEnd();
}
// CD-Key
if (fileContent.Contains("a valid serial number is required")
|| fileContent.Contains("serial number is located"))
{
if (fileContent.Contains("a valid serial number is required"))
protections.Add("CD-Key / Serial");
}
else if (fileContent.Contains("serial number is located"))
protections.Add("CD-Key / Serial");
// MediaMax
if (fileContent.Contains("MediaMax technology"))
protections.Add("MediaMax CD-3");
}
catch
{

View File

@@ -33,10 +33,8 @@ namespace BurnOutSharp.FileType
}
// TODO: Add stream opening support
public static List<string> Scan(string file, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
List<string> protections = new List<string>();
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempPath);
@@ -51,23 +49,8 @@ namespace BurnOutSharp.FileType
HLExtractProgram.Process(args);
if (Directory.Exists(tempPath))
{
foreach (string tempFile in Directory.EnumerateFiles(tempPath, "*", SearchOption.AllDirectories))
{
string protection = ProtectionFind.ScanContent(tempFile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempFile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add(tempFile);
}
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
@@ -76,6 +59,9 @@ namespace BurnOutSharp.FileType
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
}

View File

@@ -15,11 +15,9 @@ namespace BurnOutSharp.FileType
return false;
}
public static List<string> Scan(Stream stream, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, Stream stream)
{
List<string> protections = new List<string>();
// If the 7-zip file itself fails
// If the xz file itself fails
try
{
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
@@ -30,37 +28,33 @@ namespace BurnOutSharp.FileType
// If an individual entry fails
try
{
string tempfile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempfile))
string tempFile = Path.Combine(tempPath, Guid.NewGuid().ToString());
using (FileStream fs = File.OpenWrite(tempFile))
{
xzFile.CopyTo(fs);
}
string protection = ProtectionFind.ScanContent(tempfile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempfile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{protection}");
}
catch { }
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
}
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}
}

View File

@@ -1,4 +1,4 @@
namespace BurnOutSharp.ProtectionType
namespace BurnOutSharp.PackerType
{
public class Armadillo
{

View File

@@ -1,4 +1,4 @@
namespace BurnOutSharp.ProtectionType
namespace BurnOutSharp.PackerType
{
public class EXEStealth
{

View File

@@ -0,0 +1,47 @@
using System;
using System.Linq;
using System.Text;
namespace BurnOutSharp.PackerType
{
public class NSIS
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// Nullsoft Install System
byte[] check = new byte[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d };
if (fileContent.Contains(check, out int position))
{
string version = GetVersion(fileContent, position);
return $"NSIS {version}" + (includePosition ? $" (Index {position})" : string.Empty);
}
// NullsoftInst
check = new byte[] { 0x4e, 0x75, 0x6c, 0x6c, 0x73, 0x6f, 0x66, 0x74, 0x49, 0x6e, 0x73, 0x74 };
if (fileContent.Contains(check, out position))
{
return $"NSIS" + (includePosition ? $" (Index {position})" : string.Empty);
}
return null;
}
private static string GetVersion(byte[] fileContent, int index)
{
try
{
index += 24;
if (fileContent[index] != 'v')
return "(Unknown Version)";
var versionBytes = new ReadOnlySpan<byte>(fileContent, index, 16).ToArray();
var onlyVersion = versionBytes.TakeWhile(b => b != '<').ToArray();
return Encoding.ASCII.GetString(onlyVersion);
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace BurnOutSharp.ProtectionType
namespace BurnOutSharp.PackerType
{
public class PECompact
{

View File

@@ -0,0 +1,10 @@
namespace BurnOutSharp.PackerType
{
public class Petite
{
/*
* Possible strings for PEtite Win32 Executable Compressor (Unknown how to get version)
* - petite - 40 70 65 74 69 74 65 (Made with Version 2.4, Compression Level 1-9)
*/
}
}

View File

@@ -0,0 +1,37 @@
using System.Text;
namespace BurnOutSharp.PackerType
{
public class UPX
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// UPX!
byte[] check = new byte[] { 0x55, 0x50, 0x58, 0x21 };
if (fileContent.Contains(check, out int position))
{
string version = GetVersion(fileContent, position);
return $"UPX {version}" + (includePosition ? $" (Index {position})" : string.Empty);
}
return null;
}
private static string GetVersion(byte[] fileContent, int index)
{
try
{
index -= 5;
string versionString = Encoding.ASCII.GetString(fileContent, index, 4);
if (!char.IsNumber(versionString[0]))
return "(Unknown Version)";
return versionString;
}
catch
{
return "(Unknown Version)";
}
}
}
}

View File

@@ -1,4 +1,4 @@
namespace BurnOutSharp.ProtectionType
namespace BurnOutSharp.PackerType
{
public class dotFuscator
{

View File

@@ -1,509 +0,0 @@
//this file is part of BurnOut
//Copyright (C)2005-2010 Gernot Knippen
//Ported code with augments Copyright (C)2018 Matt Nadareski
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You can get a copy of the GNU General Public License
//by writing to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using BurnOutSharp.FileType;
using BurnOutSharp.ProtectionType;
namespace BurnOutSharp
{
public static class ProtectionFind
{
/// <summary>
/// Scan a path to find any known copy protection(s)
/// </summary>
/// <param name="path">Path to scan for protection(s)</param>
/// <param name="includePosition">True to include scanned copy protection position, false otherwise (default)</param>
/// <param name="progress">Optional progress indicator that will return a float in the range from 0 to 1</param>
/// <returns>Dictionary of filename to protection mappings, if possible</returns>
public static Dictionary<string, string> Scan(string path, bool includePosition = false, IProgress<FileProtection> progress = null)
{
var protections = new Dictionary<string, string>();
// Checkpoint
progress?.Report(new FileProtection(null, 0, null));
// If we have a file
if (File.Exists(path))
{
// Try using just the file first to get protection info
string fileProtection = ScanPath(path, false);
if (!string.IsNullOrWhiteSpace(fileProtection))
protections[path] = fileProtection;
// Now check to see if the file contains any additional information
string contentProtection = ScanContent(path, includePosition)?.Replace("" + (char)0x00, "");
if (!string.IsNullOrWhiteSpace(contentProtection))
{
if (protections.ContainsKey(path))
protections[path] += $", {contentProtection}";
else
protections[path] = contentProtection;
}
// Checkpoint
progress?.Report(new FileProtection(path, 1, contentProtection));
}
// If we have a directory
else if (Directory.Exists(path))
{
// Get the lists of files to be used
var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
// Try using just the path first to get protection info
string pathProtection = ScanPath(path, true);
if (!string.IsNullOrWhiteSpace(pathProtection))
protections[path] = pathProtection;
// Loop through all files and scan their contents
for (int i = 0; i < files.Count(); i++)
{
// Get the current file
string file = files.ElementAt(i);
// Try using just the file first to get protection info
string fileProtection = ScanPath(file, false);
if (!string.IsNullOrWhiteSpace(fileProtection))
protections[file] = fileProtection;
// Now check to see if the file contains any additional information
string contentProtection = ScanContent(file, includePosition)?.Replace("" + (char)0x00, "");
if (!string.IsNullOrWhiteSpace(contentProtection))
{
if (protections.ContainsKey(file))
protections[file] += $", {contentProtection}";
else
protections[file] = contentProtection;
}
// Checkpoint
progress?.Report(new FileProtection(file, i / (float)files.Count(), contentProtection));
}
}
// If we have an empty list, we need to take care of that
if (protections.Count(p => !string.IsNullOrWhiteSpace(p.Value)) == 0)
{
protections = new Dictionary<string, string>();
}
return protections;
}
/// <summary>
/// Scan a path for indications of copy protection
/// </summary>
/// <param name="path"></param>
/// <param name="isDirectory"></param>
/// <returns></returns>
public static string ScanPath(string path, bool isDirectory)
{
List<string> protections = new List<string>();
string protection;
// If we have a directory, get the files in the directory for searching
IEnumerable<string> files = null;
if (isDirectory)
files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories);
// AACS
protection = AACS.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Alpha-DVD
protection = AlphaDVD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Bitpool
protection = Bitpool.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// ByteShield
protection = ByteShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Cactus Data Shield
protection = CactusDataShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Cops
protection = CDCops.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Lock
protection = CDLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Protector
protection = CDProtector.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-X
protection = CDX.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
/*
// CopyKiller
protection = CopyKiller.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
*/
// DiscGuard
protection = DiscGuard.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// DVD Crypt
protection = DVDCrypt.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// DVD-Movie-PROTECT
protection = DVDMoviePROTECT.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// FreeLock
protection = FreeLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Games for Windows - Live
protection = GFWL.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Hexalock AutoLock
protection = HexalockAutoLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Impulse Reactor
protection = ImpulseReactor.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// IndyVCD
protection = IndyVCD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Key2Audio XS
protection = Key2AudioXS.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// LaserLock
protection = LaserLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// MediaCloQ
protection = MediaCloQ.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// MediaMax CD3
protection = MediaMaxCD3.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Origin
protection = Origin.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Protect DVD-Video
protection = ProtectDVDVideo.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeCast
protection = SafeCast.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeDisc
protection = SafeDisc.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeDisc Lite
protection = SafeDiscLite.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeLock
protection = SafeLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SecuROM
protection = SecuROM.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SmartE
protection = SmartE.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SoftLock
protection = SoftLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SolidShield
protection = SolidShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// StarForce
protection = StarForce.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Steam
protection = Steam.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// TAGES
protection = Tages.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// TZCopyProtector
protection = TZCopyProtector.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Uplay
protection = Uplay.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// VOB ProtectCD/DVD
protection = VOBProtectCDDVD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Winlock
protection = Winlock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// WTM CD Protect
protection = WTMCDProtect.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// XCP
protection = XCP.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Zzxzz
protection = Zzxzz.CheckPath(path, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Now combine any found protections, or null if empty
if (protections.Count() == 0)
return null;
else
return string.Join(", ", protections);
}
/// <summary>
/// Scan an individual file for copy protection
/// </summary>
/// <param name="file">File path for scanning</param>
/// <param name="includePosition">True to include scanned copy protection position, false otherwise (default)</param>
public static string ScanContent(string file, bool includePosition = false)
{
using (FileStream fs = File.OpenRead(file))
{
return ScanContent(fs, file, includePosition);
}
}
/// <summary>
/// Scan an individual stream for copy protection
/// </summary>
/// <param name="stream">Generic stream to scan</param>
/// <param name="file">File path to be used for name checks (optional)</param>
/// <param name="includePosition">True to include scanned copy protection position, false otherwise (default)</param>
public static string ScanContent(Stream stream, string file = null, bool includePosition = false)
{
// Get the extension for certain checks
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
// Assume the first part of the stream is the start of a file
byte[] magic = new byte[16];
try
{
stream.Read(magic, 0, 16);
stream.Seek(-16, SeekOrigin.Current);
}
catch
{
// We don't care what the issue was, we can't read or seek the file
return null;
}
// Files can be protected in multiple ways
List<string> protections = new List<string>();
// 7-Zip archive
if (SevenZip.ShouldScan(magic))
protections.AddRange(SevenZip.Scan(stream, includePosition));
// BFPK archive
if (BFPK.ShouldScan(magic))
protections.AddRange(BFPK.Scan(stream, includePosition));
// BZip2
if (BZip2.ShouldScan(magic))
protections.AddRange(BZip2.Scan(stream, includePosition));
// Executable
if (Executable.ShouldScan(magic))
protections.AddRange(Executable.Scan(stream, file, includePosition));
// GZIP
if (GZIP.ShouldScan(magic))
protections.AddRange(GZIP.Scan(stream, includePosition));
// InstallShield Cabinet
if (file != null && InstallShieldCAB.ShouldScan(magic))
protections.AddRange(InstallShieldCAB.Scan(file, includePosition));
// Microsoft Cabinet
if (file != null && MicrosoftCAB.ShouldScan(magic))
protections.AddRange(MicrosoftCAB.Scan(file, includePosition));
// MPQ archive
if (file != null && MPQ.ShouldScan(magic))
protections.AddRange(MPQ.Scan(file, includePosition));
// PKZIP archive (and derivatives)
if (PKZIP.ShouldScan(magic))
protections.AddRange(PKZIP.Scan(stream, includePosition));
// RAR archive
if (RAR.ShouldScan(magic))
protections.AddRange(RAR.Scan(stream, includePosition));
// Tape Archive
if (TapeArchive.ShouldScan(magic))
protections.AddRange(TapeArchive.Scan(stream, includePosition));
// Text-based files
if (Textfile.ShouldScan(magic, extension))
protections.AddRange(Textfile.Scan(stream, includePosition));
// Valve archive formats
if (file != null && Valve.ShouldScan(magic))
protections.AddRange(Valve.Scan(file, includePosition));
// XZ
if (XZ.ShouldScan(magic))
protections.AddRange(XZ.Scan(stream, includePosition));
// Return blank if nothing found, or comma-separated list of protections
if (protections.Count() == 0)
return string.Empty;
else
return string.Join(", ", protections);
}
/// <summary>
/// Scan a disc sector by sector for protection
/// </summary>
/// <remarks>
/// https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157
/// TODO: Finish implementation
/// </remarks>
private static string ScanSectors(char driveLetter, int sectorsize)
{
string fsName = Utilities.GetFileSystemName(driveLetter);
// Gets a handle to the physical disk
IntPtr hDisk = Utilities.CreateFile($"\\\\.\\{driveLetter}:",
FileAccess.Read,
FileShare.ReadWrite,
IntPtr.Zero,
FileMode.Open,
0,
IntPtr.Zero);
// If we have a good pointer
if (hDisk.ToInt32() != -1)
{
// Setup vars
byte[] buffer = new byte[sectorsize];
IntPtr pt = IntPtr.Zero;
NativeOverlapped no = new NativeOverlapped();
// Set initial offset
Utilities.SetFilePointerEx(
hDisk,
0,
ref pt,
Utilities.FileBegin);
// Read a whole sector
while (true)
{
buffer = new byte[sectorsize];
Utilities.ReadFileEx(
hDisk,
buffer,
(uint)sectorsize,
ref no,
null);
Utilities.SetFilePointerEx(
hDisk,
sectorsize,
ref pt,
Utilities.FileCurrent);
}
}
Utilities.CloseHandle(hDisk);
return null;
}
}
}

View File

@@ -4,12 +4,28 @@
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// "GetDriveType"
// MGS CDCheck
byte[] check = new byte[] { 0x4D, 0x47, 0x53, 0x20, 0x43, 0x44, 0x43, 0x68, 0x65, 0x63, 0x6B };
if (fileContent.Contains(check, out int position))
return "Microsoft Game Studios CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
// CDCheck
check = new byte[] { 0x43, 0x44, 0x43, 0x68, 0x65, 0x63, 0x6B };
if (fileContent.Contains(check, out position))
return "Executable-Based CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
// These content checks are too broad to be useful
private static string CheckContentsBroad(byte[] fileContent, bool includePosition = false)
{
// GetDriveType
byte[] check = new byte[] { 0x47, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65 };
if (fileContent.Contains(check, out int position))
return "CD Check" + (includePosition ? $" (Index {position})" : string.Empty);
// "GetVolumeInformation"
// GetVolumeInformation
check = new byte[] { 0x47, 0x65, 0x74, 0x56, 0x6F, 0x6C, 0x75, 0x6D, 0x65, 0x49, 0x6E, 0x66, 0x6F, 0x72, 0x6D, 0x61, 0x74, 0x69, 0x6F, 0x6E };
if (fileContent.Contains(check, out position))
return "CD Check" + (includePosition ? $" (Index {position})" : string.Empty);

View File

@@ -8,16 +8,22 @@ namespace BurnOutSharp.ProtectionType
{
public class CactusDataShield
{
// TODO: Get header info for CDSPlayer.app so it can be integrated better into the rest of the content checks
public static string CheckContents(string file)
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
if (Path.GetFileName(file) == "CDSPlayer.app")
{
using (var sr = new StreamReader(file, Encoding.Default))
{
return "Cactus Data Shield " + sr.ReadLine().Substring(3) + "(" + sr.ReadLine() + ")";
}
}
// DATA.CDS
byte[] check = new byte[] { 0x44, 0x41, 0x54, 0x41, 0x2E, 0x43, 0x44, 0x53 };
if (fileContent.Contains(check, out int position))
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
// \*.CDS
check = new byte[] { 0x5C, 0x2A, 0x2E, 0x43, 0x44, 0x53 };
if (fileContent.Contains(check, out position))
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
// CDSPlayer
check = new byte[] { 0x43, 0x44, 0x53, 0x50, 0x6C, 0x61, 0x79, 0x65, 0x72 };
if (fileContent.Contains(check, out position))
return "Cactus Data Shield 200" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
@@ -26,34 +32,30 @@ namespace BurnOutSharp.ProtectionType
{
if (isDirectory)
{
// TODO: Verify if these are OR or AND
if (files.Any(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase)))
{
string file = files.First(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase));
string protection = CheckContents(file);
if (!string.IsNullOrWhiteSpace(protection))
return protection;
}
else if (files.Any(f => Path.GetFileName(f).Equals("yucca.cds", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase))
if (files.Any(f => Path.GetFileName(f).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("PJSTREAM.DLL", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase)))
|| files.Any(f => Path.GetFileName(f).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetExtension(f).Trim('.').Equals("cds", StringComparison.OrdinalIgnoreCase)))
{
string versionPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("version.txt", StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(versionPath))
{
string version = GetVersion(versionPath);
if (!string.IsNullOrWhiteSpace(version))
return $"Cactus Data Shield {version}";
}
return "Cactus Data Shield 200";
}
}
else
{
if (Path.GetFileName(path).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase))
{
string protection = CheckContents(path);
if (!string.IsNullOrWhiteSpace(protection))
return protection;
}
else if (Path.GetFileName(path).Equals("yucca.cds", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase)
if (Path.GetFileName(path).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CDSPlayer.app", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("PJSTREAM.DLL", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CACTUSPJ.exe", StringComparison.OrdinalIgnoreCase))
|| Path.GetFileName(path).Equals("wmmp.exe", StringComparison.OrdinalIgnoreCase)
|| Path.GetExtension(path).Trim('.').Equals("cds", StringComparison.OrdinalIgnoreCase))
{
return "Cactus Data Shield 200";
}
@@ -61,5 +63,23 @@ namespace BurnOutSharp.ProtectionType
return null;
}
private static string GetVersion(string path)
{
if (!File.Exists(path))
return null;
try
{
using (var sr = new StreamReader(path, Encoding.Default))
{
return $"{sr.ReadLine().Substring(3)} ({sr.ReadLine()})";
}
}
catch
{
return null;
}
}
}
}

View File

@@ -1,16 +0,0 @@
namespace BurnOutSharp.ProtectionType
{
public class Cucko
{
// TODO: Verify this doesn't over-match
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// "EASTL"
byte[] check = new byte[] { 0x45, 0x41, 0x53, 0x54, 0x4C };
if (fileContent.Contains(check, out int position))
return "Cucko (EA Custom)" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
}
}

View File

@@ -1,15 +0,0 @@
namespace BurnOutSharp.ProtectionType
{
public class EACdKey
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// "ereg.ea-europe.com"
byte[] check = new byte[] { 0x65, 0x72, 0x65, 0x67, 0x2E, 0x65, 0x61, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D };
if (fileContent.Contains(check, out int position))
return "EA CdKey Registration Module" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
}
}

View File

@@ -0,0 +1,46 @@
namespace BurnOutSharp.ProtectionType
{
public class ElectronicArts
{
// TODO: Verify this doesn't over-match
public static string CheckContents(string file, byte[] fileContent, bool includePosition = false)
{
// EASTL
byte[] check = new byte[] { 0x45, 0x41, 0x53, 0x54, 0x4C };
if (fileContent.Contains(check, out int position))
return "Cucko (EA Custom)" + (includePosition ? $" (Index {position})" : string.Empty);
// R + (char)0x00 + e + (char)0x00 + g + (char)0x00 + i + (char)0x00 + s + (char)0x00 + t + (char)0x00 + r + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + C + (char)0x00 + o + (char)0x00 + d + (char)0x00 + e + (char)0x00
check = new byte[] { 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00 };
if (fileContent.Contains(check, out position))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
// R + (char)0x00 + e + (char)0x00 + g + (char)0x00 + i + (char)0x00 + s + (char)0x00 + t + (char)0x00 + r + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00 + + (char)0x00 + c + (char)0x00 + o + (char)0x00 + d + (char)0x00 + e + (char)0x00
check = new byte[] { 0x52, 0x00, 0x65, 0x00, 0x67, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x63, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x65, 0x00 };
if (fileContent.Contains(check, out position))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
// C + (char)0x00 + D + (char)0x00 + K + (char)0x00 + e + (char)0x00 + y + (char)0x00
check = new byte[] { 0x43, 0x00, 0x44, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00 };
if (fileContent.Contains(check, out position))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
// ereg.ea-europe.com
check = new byte[] { 0x65, 0x72, 0x65, 0x67, 0x2E, 0x65, 0x61, 0x2D, 0x65, 0x75, 0x72, 0x6F, 0x70, 0x65, 0x2E, 0x63, 0x6F, 0x6D };
if (fileContent.Contains(check, out position))
return $"EA CdKey Registration Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
// GenericEA + (char)0x00 + (char)0x00 + (char)0x00 + Activation
check = new byte[] { 0x47, 0x65, 0x6E, 0x65, 0x72, 0x69, 0x63, 0x45, 0x41, 0x00, 0x00, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E };
if (fileContent.Contains(check, out position))
return "EA DRM Protection" + (includePosition ? $" (Index {position})" : string.Empty);
// E + (char)0x00 + A + (char)0x00 + + (char)0x00 + D + (char)0x00 + R + (char)0x00 + M + (char)0x00 + + (char)0x00 + H + (char)0x00 + e + (char)0x00 + l + (char)0x00 + p + (char)0x00 + e + (char)0x00 + r
check = new byte[] { 0x45, 0x00, 0x41, 0x00, 0x20, 0x00, 0x44, 0x00, 0x52, 0x00, 0x4D, 0x00, 0x20, 0x00, 0x48, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x70, 0x00, 0x65, 0x00, 0x72 };
if (fileContent.Contains(check, out position))
return "EA DRM Protection" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
}
}

View File

@@ -0,0 +1,31 @@
namespace BurnOutSharp.ProtectionType
{
public class Intenium
{
/*
* Possible strings for finding INTENIUM Trial & Buy Protection
*
* Luxor Only:
* - command_buyNowCb - 63 6F 6D 6D 61 6E 64 5F 62 75 79 4E 6F 77 43 62
* - command_testTrialCb - 63 6F 6D 6D 61 6E 64 5F 74 65 73 74 54 72 69 61 6C 43 62
* - PHRASE_TRIAL - 50 48 52 41 53 45 5F 54 52 49 41 4C
* - V_TRIAL_GAME - 56 5F 54 52 49 41 4C 5F 47 41 4D 45
* - V_FULL_GAME - 56 5F 46 55 4C 4C 5F 47 41 4D 45
*
* Luxor, World, Cradle, and Kingdom:
* - Trial + (char)0x00 + P - 54 72 69 61 6C 00 50
* + This is possibly followed by a version number. Undetermined if it's the software or protection version.
* - NO NESTED PRMS SUPPORTED - 4E 4F 20 4E 45 53 54 45 44 20 50 52 4D 53 20 53 55 50 50 4F 52 54 45 44
*/
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// Trial + (char)0x00 + P
byte[] check = new byte[] { 0x54, 0x72, 0x69, 0x61, 0x6C, 0x00, 0x50 };
if (fileContent.Contains(check, out int position))
return "INTENIUM Trial & Buy Protection" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
}
}

View File

@@ -15,7 +15,7 @@ namespace BurnOutSharp.ProtectionType
if (files.Any(f => Path.GetFileName(f).Equals("SDKHM.EXE", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("SDKHM.DLL", StringComparison.OrdinalIgnoreCase)))
{
return "Key2Audio XS";
return "key2AudioXS";
}
}
else
@@ -23,7 +23,7 @@ namespace BurnOutSharp.ProtectionType
if (Path.GetFileName(path).Equals("SDKHM.EXE", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("SDKHM.DLL", StringComparison.OrdinalIgnoreCase))
{
return "Key2Audio XS";
return "key2AudioXS";
}
}

View File

@@ -7,17 +7,32 @@ namespace BurnOutSharp.ProtectionType
{
public class MediaMaxCD3
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// Cd3Ctl
byte[] check = new byte[] { 0x43, 0x64, 0x33, 0x43, 0x74, 0x6C };
if (fileContent.Contains(check, out int position))
return "MediaMax CD-3" + (includePosition ? $" (Index {position})" : string.Empty);
// DllInstallSbcp
check = new byte[] { 0x44, 0x6C, 0x6C, 0x49, 0x6E, 0x73, 0x74, 0x61, 0x6C, 0x6C, 0x53, 0x62, 0x63, 0x70 };
if (fileContent.Contains(check, out position))
return "MediaMax CD-3" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
public static string CheckPath(string path, IEnumerable<string> files, bool isDirectory)
{
if (isDirectory)
{
if (files.Any(f => Path.GetFileName(f).Equals("LaunchCd.exe", StringComparison.OrdinalIgnoreCase)))
return "MediaMax CD3";
return "MediaMax CD-3";
}
else
{
if (Path.GetFileName(path).Equals("LaunchCd.exe", StringComparison.OrdinalIgnoreCase))
return "MediaMax CD3";
return "MediaMax CD-3";
}
return null;

View File

@@ -88,17 +88,15 @@ namespace BurnOutSharp.ProtectionType
if (Path.GetFileName(path).Equals("CLCD16.DLL", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CLCD32.DLL", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CLOKSPL.EXE", StringComparison.OrdinalIgnoreCase)
|| Path.GetExtension(path).Trim('.').Equals("icd", StringComparison.OrdinalIgnoreCase)
|| Path.GetExtension(path).Trim('.').Equals("016", StringComparison.OrdinalIgnoreCase)
|| Path.GetExtension(path).Trim('.').Equals("256", StringComparison.OrdinalIgnoreCase))
|| Path.GetExtension(path).Trim('.').Equals("icd", StringComparison.OrdinalIgnoreCase))
{
return "SafeDisc 1";
}
// V1 or greater
else if (Path.GetFileName(path).Equals("00000001.TMP", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CLCD32.DLL", StringComparison.OrdinalIgnoreCase)
|| Path.GetFileName(path).Equals("CLOKSPL.EXE", StringComparison.OrdinalIgnoreCase))
|| Path.GetExtension(path).Trim('.').Equals("016", StringComparison.OrdinalIgnoreCase)
|| Path.GetExtension(path).Trim('.').Equals("256", StringComparison.OrdinalIgnoreCase))
{
return "SafeDisc 1 or greater";
}

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace BurnOutSharp.ProtectionType
{
@@ -94,13 +95,13 @@ namespace BurnOutSharp.ProtectionType
char version = (char)fileContent[index];
index += 2;
string subVersion = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
string subVersion = Encoding.ASCII.GetString(fileContent, index, 2);
index += 3;
string subSubVersion = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
string subSubVersion = Encoding.ASCII.GetString(fileContent, index, 2);
index += 3;
string subSubSubVersion = new string(new ArraySegment<byte>(fileContent, index, 4).Select(b => (char)b).ToArray());
string subSubSubVersion = Encoding.ASCII.GetString(fileContent, index, 4);
if (!char.IsNumber(version))
return "(very old, v3 or less)";
@@ -144,7 +145,7 @@ namespace BurnOutSharp.ProtectionType
private static string GetV7Version(byte[] fileContent)
{
int index = 236;
byte[] bytes = new ArraySegment<byte>(fileContent, index, 4).ToArray();
byte[] bytes = new ReadOnlySpan<byte>(fileContent, index, 4).ToArray();
//SecuROM 7 new and 8
if (bytes[3] == 0x5C) // if (bytes[0] == 0xED && bytes[3] == 0x5C {
@@ -156,7 +157,7 @@ namespace BurnOutSharp.ProtectionType
else
{
index = 122;
bytes = new ArraySegment<byte>(fileContent, index, 2).ToArray();
bytes = new ReadOnlySpan<byte>(fileContent, index, 2).ToArray();
return $"7.{bytes[0] ^ 0x10:00}.{bytes[1] ^ 0x10:0000}"; //return "7.01-7.10"
}
}

View File

@@ -9,7 +9,7 @@ namespace BurnOutSharp.ProtectionType
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// "BITARTS"
// BITARTS
byte[] check = new byte[] { 0x42, 0x49, 0x54, 0x41, 0x52, 0x54, 0x53 };
if (fileContent.Contains(check, out int position))
return "SmartE" + (includePosition ? $" (Index {position})" : string.Empty);

View File

@@ -64,6 +64,11 @@ namespace BurnOutSharp.ProtectionType
return $"SolidShield Activation Manager Module {Utilities.GetFileVersion(file)}" + (includePosition ? $" (Index {position})" : string.Empty);
}
// dvm.dll
check = new byte[] { 0x64, 0x76, 0x6D, 0x2E, 0x64, 0x6C, 0x6C };
if (fileContent.Contains(check, out position))
return $"SolidShield EXE Wrapper" + (includePosition ? $" (Index {position})" : string.Empty);
// (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA
check = new byte[] { 0xAD, 0xDE, 0xFE, 0xCA };
if (fileContent.Contains(check, out position))

View File

@@ -4,18 +4,19 @@
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// ".ldr"
// .ldr
byte[] check = new byte[] { 0x2E, 0x6C, 0x64, 0x72 };
if (fileContent.Contains(check, out int position))
return "3PLock" + (includePosition ? $" (Index {position})" : string.Empty);
// ".ldt"
check = new byte[] { 0x2E, 0x6C, 0x64, 0x74 };
if (fileContent.Contains(check, out position))
return "3PLock" + (includePosition ? $" (Index {position})" : string.Empty);
{
// .ldt
byte[] check2 = new byte[] { 0x2E, 0x6C, 0x64, 0x74 };
if (fileContent.Contains(check2, out int position2))
return "3PLock" + (includePosition ? $" (Index {position}, {position2})" : string.Empty);
}
// This produced false positives in some DirectX 9.0c installer files
// "Y" + (char)0xC3 + "U" + (char)0x8B + (char)0xEC + (char)0x83 + (char)0xEC + "0SVW"
// check = new byte[] { 0x59, 0xC3, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x30, 0x53, 0x56, 0x57 };
//check = new byte[] { 0x59, 0xC3, 0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x30, 0x53, 0x56, 0x57 };
//if (fileContent.Contains(check, out position))
// return "3PLock" + (includePosition ? $" (Index {position})" : string.Empty);

View File

@@ -0,0 +1,15 @@
namespace BurnOutSharp.ProtectionType
{
public class ThreeTwoOneStudios
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// 3 + (char)0x00 + 1 + 2 + (char)0x00 + 1 + (char)0x00 + S + (char)0x00 + t + (char)0x00 + u + (char)0x00 + d + (char)0x00 + i + (char)0x00 + o + (char)0x00 + s + (char)0x00 + + (char)0x00 + A + (char)0x00 + c + (char)0x00 + t + (char)0x00 + i + (char)0x00 + v + (char)0x00 + a + (char)0x00 + t + (char)0x00 + i + (char)0x00 + o + (char)0x00 + n + (char)0x00
byte[] check = new byte[] { 0x33, 0x00, 0x32, 0x00, 0x31, 0x00, 0x53, 0x00, 0x74, 0x00, 0x75, 0x00, 0x64, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00 };
if (fileContent.Contains(check, out int position))
return "321Studios Online Activation" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
}
}

View File

@@ -7,19 +7,23 @@ namespace BurnOutSharp.ProtectionType
{
public class WiseInstaller
{
public static List<string> CheckContents(string file, byte[] fileContent, bool includePosition = false)
public static Dictionary<string, List<string>> CheckContents(Scanner scanner, string file, byte[] fileContent)
{
// "WiseMain"
// WiseMain
byte[] check = new byte[] { 0x57, 0x69, 0x73, 0x65, 0x4D, 0x61, 0x69, 0x6E };
if (fileContent.Contains(check, out int position))
{
List<string> protections = new List<string> { "Wise Installation Wizard Module" + (includePosition ? $" (Index {position})" : string.Empty)
};
Dictionary<string, List<string>> protections = new Dictionary<string, List<string>>
{
[file ?? "NO FILENAME"] = new List<string> { "Wise Installation Wizard Module" + (scanner.IncludePosition ? $" (Index {position})" : string.Empty) },
};
if (!File.Exists(file))
if (file == null || !File.Exists(file))
return protections;
protections.AddRange(WiseInstaller.Scan(file, includePosition));
var subProtections = Scan(scanner, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
return protections;
}
@@ -27,10 +31,8 @@ namespace BurnOutSharp.ProtectionType
return null;
}
public static List<string> Scan(string file, bool includePosition = false)
public static Dictionary<string, List<string>> Scan(Scanner scanner, string file)
{
List<string> protections = new List<string>();
// If the installer file itself fails
try
{
@@ -40,24 +42,24 @@ namespace BurnOutSharp.ProtectionType
Wise unpacker = new Wise();
unpacker.ExtractTo(file, tempPath);
foreach (string tempFile in Directory.EnumerateFiles(tempPath, "*", SearchOption.AllDirectories))
// Collect and format all found protections
var protections = scanner.GetProtections(tempPath);
// If temp directory cleanup fails
try
{
string protection = ProtectionFind.ScanContent(tempFile, includePosition);
// If tempfile cleanup fails
try
{
File.Delete(tempFile);
}
catch { }
if (!string.IsNullOrEmpty(protection))
protections.Add($"\r\n{tempFile.Substring(tempPath.Length)} - {protection}");
Directory.Delete(tempPath, true);
}
catch { }
// Remove temporary path references
Utilities.StripFromKeys(protections, tempPath);
return protections;
}
catch { }
return protections;
return null;
}
}

View File

@@ -2,11 +2,32 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BurnOutSharp.FileType;
namespace BurnOutSharp.ProtectionType
{
public class XCP
{
public static string CheckContents(byte[] fileContent, bool includePosition = false)
{
// XCP.DAT
byte[] check = new byte[] { 0x58, 0x43, 0x50, 0x2E, 0x44, 0x41, 0x54 };
if (fileContent.Contains(check, out int position))
return "XCP" + (includePosition ? $" (Index {position})" : string.Empty);
// XCPPlugins.dll
check = new byte[] { 0x58, 0x43, 0x50, 0x50, 0x6C, 0x75, 0x67, 0x69, 0x6E, 0x73, 0x2E, 0x64, 0x6C, 0x6C };
if (fileContent.Contains(check, out position))
return "XCP" + (includePosition ? $" (Index {position})" : string.Empty);
// XCPPhoenix.dll
check = new byte[] { 0x58, 0x43, 0x50, 0x50, 0x68, 0x6F, 0x65, 0x6E, 0x69, 0x78, 0x2E, 0x64, 0x6C, 0x6C };
if (fileContent.Contains(check, out position))
return "XCP" + (includePosition ? $" (Index {position})" : string.Empty);
return null;
}
public static string CheckPath(string path, IEnumerable<string> files, bool isDirectory)
{
if (isDirectory)
@@ -16,6 +37,14 @@ namespace BurnOutSharp.ProtectionType
|| files.Any(f => Path.GetFileName(f).Equals("ECDPlayerControl.ocx", StringComparison.OrdinalIgnoreCase))
|| files.Any(f => Path.GetFileName(f).Equals("go.exe", StringComparison.OrdinalIgnoreCase))) // Path.Combine("contents", "go.exe")
{
string versionDatPath = files.FirstOrDefault(f => Path.GetFileName(f).Equals("VERSION.DAT", StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(versionDatPath))
{
string xcpVersion = GetDatVersion(versionDatPath);
if (!string.IsNullOrWhiteSpace(xcpVersion))
return xcpVersion;
}
return "XCP";
}
}
@@ -31,5 +60,18 @@ namespace BurnOutSharp.ProtectionType
return null;
}
private static string GetDatVersion(string path)
{
try
{
var xcpIni = new IniFile(path);
return xcpIni["XCP.VERSION"];
}
catch
{
return null;
}
}
}
}

578
BurnOutSharp/Scanner.cs Normal file
View File

@@ -0,0 +1,578 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BurnOutSharp.FileType;
using BurnOutSharp.ProtectionType;
namespace BurnOutSharp
{
public class Scanner
{
/// <summary>
/// Optional progress callback during scanning
/// </summary>
public IProgress<FileProtection> FileProgress { get; set; } = null;
/// <summary>
/// Determines whether the byte position of found protection is included or not
/// </summary>
public bool IncludePosition { get; set; } = false;
/// <summary>
/// Determines whether all files are scanned or just executables are
/// </summary>
public bool ScanAllFiles { get; set; } = false;
/// <summary>
/// Determines whether archives are decompressed and scanned
/// </summary>
public bool ScanArchives { get; set; } = true;
/// <summary>
/// Determines if packers are counted as detected protections or not
/// </summary>
public bool ScanPackers { get; set; } = false;
/// <summary>
/// Constructor
/// </summary>
/// <param name="fileProgress">Optional progress callback</param>
public Scanner(IProgress<FileProtection> fileProgress = null)
{
FileProgress = fileProgress;
}
/// <summary>
/// Scan a single path and get all found protections
/// </summary>
/// <param name="path">Path to scan</param>
/// <returns>Dictionary of list of strings representing the found protections</returns>
public Dictionary<string, List<string>> GetProtections(string path)
{
return GetProtections(new List<string> { path });
}
/// <summary>
/// Scan the list of paths and get all found protections
/// </summary>
/// <returns>Dictionary of list of strings representing the found protections</returns>
public Dictionary<string, List<string>> GetProtections(List<string> paths)
{
// If we have no paths, we can't scan
if (paths == null || !paths.Any())
return null;
// Checkpoint
FileProgress?.Report(new FileProtection(null, 0, null));
// Temp variables for reporting
string tempFilePath = Path.GetTempPath();
string tempFilePathWithGuid = Path.Combine(tempFilePath, Guid.NewGuid().ToString());
// Loop through each path and get the returned values
var protections = new Dictionary<string, List<string>>();
foreach (string path in paths)
{
// Directories scan each internal file individually
if (Directory.Exists(path))
{
// Enumerate all files at first for easier access
var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories).ToList();
// Scan for path-detectable protections
var directoryPathProtections = GetPathProtections(path, files);
Utilities.AppendToDictionary(protections, directoryPathProtections);
// Scan each file in directory separately
for (int i = 0; i < files.Count(); i++)
{
// Get the current file
string file = files.ElementAt(i);
// Get the reportable file name
string reportableFileName = file;
if (reportableFileName.StartsWith(tempFilePath))
reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length);
// Checkpoint
FileProgress?.Report(new FileProtection(reportableFileName, i / (float)files.Count(), "Checking file" + (file != reportableFileName ? " from archive" : string.Empty)));
// Scan for path-detectable protections
var filePathProtections = GetPathProtections(file);
Utilities.AppendToDictionary(protections, filePathProtections);
// Scan for content-detectable protections
var fileProtections = GetInternalProtections(file);
if (fileProtections != null && fileProtections.Any())
{
foreach (string key in fileProtections.Keys)
{
if (!protections.ContainsKey(key))
protections[key] = new List<string>();
protections[key].AddRange(fileProtections[key]);
}
}
// Checkpoint
protections.TryGetValue(file, out List<string> fullProtectionList);
string fullProtection = (fullProtectionList != null && fullProtectionList.Any() ? string.Join(", ", fullProtectionList) : null);
FileProgress?.Report(new FileProtection(reportableFileName, (i + 1) / (float)files.Count(), fullProtection ?? string.Empty));
}
}
// Scan a single file by itself
else if (File.Exists(path))
{
// Get the reportable file name
string reportableFileName = path;
if (reportableFileName.StartsWith(tempFilePath))
reportableFileName = reportableFileName.Substring(tempFilePathWithGuid.Length);
// Checkpoint
FileProgress?.Report(new FileProtection(reportableFileName, 0, "Checking file" + (path != reportableFileName ? " from archive" : string.Empty)));
// Scan for path-detectable protections
var filePathProtections = GetPathProtections(path);
Utilities.AppendToDictionary(protections, filePathProtections);
// Scan for content-detectable protections
var fileProtections = GetInternalProtections(path);
if (fileProtections != null && fileProtections.Any())
{
foreach (string key in fileProtections.Keys)
{
if (!protections.ContainsKey(key))
protections[key] = new List<string>();
protections[key].AddRange(fileProtections[key]);
}
}
// Checkpoint
protections.TryGetValue(path, out List<string> fullProtectionList);
string fullProtection = (fullProtectionList != null && fullProtectionList.Any() ? string.Join(", ", fullProtectionList) : null);
FileProgress?.Report(new FileProtection(reportableFileName, 1, fullProtection ?? string.Empty));
}
// Throw on an invalid path
else
{
Console.WriteLine($"{path} is not a directory or file, skipping...");
//throw new FileNotFoundException($"{path} is not a directory or file, skipping...");
}
}
// Clear out any empty keys
Utilities.ClearEmptyKeys(protections);
return protections;
}
/// <summary>
/// Get the path-detectable protections associated with a single path
/// </summary>
/// <param name="path">Path of the directory or file to scan</param>
/// <param name="files">Files contained within if the path is a directory</param>
/// <returns>Dictionary of list of strings representing the found protections</returns>
private Dictionary<string, List<string>> GetPathProtections(string path, List<string> files = null)
{
List<string> protections = new List<string>();
string protection;
// If we have a directory, get the files in the directory for searching
bool isDirectory = false;
if (Directory.Exists(path))
isDirectory = true;
// AACS
protection = AACS.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Alpha-DVD
protection = AlphaDVD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Bitpool
protection = Bitpool.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// ByteShield
protection = ByteShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Cactus Data Shield
protection = CactusDataShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Cops
protection = CDCops.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Lock
protection = CDLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-Protector
protection = CDProtector.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// CD-X
protection = CDX.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
/*
// CopyKiller
protection = CopyKiller.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
*/
// DiscGuard
protection = DiscGuard.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// DVD Crypt
protection = DVDCrypt.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// DVD-Movie-PROTECT
protection = DVDMoviePROTECT.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// FreeLock
protection = FreeLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Games for Windows - Live
protection = GFWL.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Hexalock AutoLock
protection = HexalockAutoLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Impulse Reactor
protection = ImpulseReactor.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// IndyVCD
protection = IndyVCD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Key2Audio XS
protection = Key2AudioXS.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// LaserLock
protection = LaserLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// MediaCloQ
protection = MediaCloQ.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// MediaMax CD3
protection = MediaMaxCD3.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Origin
protection = Origin.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Protect DVD-Video
protection = ProtectDVDVideo.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeCast
protection = SafeCast.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeDisc
protection = SafeDisc.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeDisc Lite
protection = SafeDiscLite.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SafeLock
protection = SafeLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SecuROM
protection = SecuROM.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SmartE
protection = SmartE.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SoftLock
protection = SoftLock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// SolidShield
protection = SolidShield.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// StarForce
protection = StarForce.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Steam
protection = Steam.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// TAGES
protection = Tages.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// TZCopyProtector
protection = TZCopyProtector.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Uplay
protection = Uplay.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// VOB ProtectCD/DVD
protection = VOBProtectCDDVD.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Winlock
protection = Winlock.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// WTM CD Protect
protection = WTMCDProtect.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// XCP
protection = XCP.CheckPath(path, files, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Zzxzz
protection = Zzxzz.CheckPath(path, isDirectory);
if (!string.IsNullOrWhiteSpace(protection))
protections.Add(protection);
// Create and return the dictionary
return new Dictionary<string, List<string>>
{
[path] = protections
};
}
/// <summary>
/// Get the content-detectable protections associated with a single path
/// </summary>
/// <param name="file">Path to the file to scan</param>
/// <returns>Dictionary of list of strings representing the found protections</returns>
private Dictionary<string, List<string>> GetInternalProtections(string file)
{
// Quick sanity check before continuing
if (!File.Exists(file))
return null;
// Initialze the protections found
var protections = new Dictionary<string, List<string>>();
// Get the extension for certain checks
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
// Open the file and begin scanning
using (FileStream fs = File.OpenRead(file))
{
// Get the first 16 bytes for matching
byte[] magic = new byte[16];
try
{
fs.Read(magic, 0, 16);
fs.Seek(-16, SeekOrigin.Current);
}
catch
{
// We don't care what the issue was, we can't read or seek the file
return null;
}
#region Non-Archive File Types
// Executable
if (ScanAllFiles || Executable.ShouldScan(magic))
{
var subProtections = Executable.Scan(this, fs, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// Text-based files
if (ScanAllFiles || Textfile.ShouldScan(magic, extension))
{
var subProtections = Textfile.Scan(fs);
Utilities.AppendToDictionary(protections, file, subProtections);
}
#endregion
#region Archive File Types
// If we're scanning archives, we have a few to try out
if (ScanArchives)
{
// 7-Zip archive
if (SevenZip.ShouldScan(magic))
{
var subProtections = SevenZip.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// BFPK archive
if (BFPK.ShouldScan(magic))
{
var subProtections = BFPK.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// BZip2
if (BZip2.ShouldScan(magic))
{
var subProtections = BZip2.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// GZIP
if (GZIP.ShouldScan(magic))
{
var subProtections = GZIP.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// InstallShield Cabinet
if (file != null && InstallShieldCAB.ShouldScan(magic))
{
var subProtections = InstallShieldCAB.Scan(this, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// Microsoft Cabinet
if (file != null && MicrosoftCAB.ShouldScan(magic))
{
var subProtections = MicrosoftCAB.Scan(this, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// MSI
if (file != null && MSI.ShouldScan(magic))
{
var subProtections = MSI.Scan(this, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// MPQ archive
if (file != null && MPQ.ShouldScan(magic))
{
var subProtections = MPQ.Scan(this, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// PKZIP archive (and derivatives)
if (PKZIP.ShouldScan(magic))
{
var subProtections = PKZIP.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// RAR archive
if (RAR.ShouldScan(magic))
{
var subProtections = RAR.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// Tape Archive
if (TapeArchive.ShouldScan(magic))
{
var subProtections = TapeArchive.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// Valve archive formats
if (file != null && Valve.ShouldScan(magic))
{
var subProtections = Valve.Scan(this, file);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
// XZ
if (XZ.ShouldScan(magic))
{
var subProtections = XZ.Scan(this, fs);
Utilities.PrependToKeys(subProtections, file);
Utilities.AppendToDictionary(protections, subProtections);
}
}
#endregion
}
// Clear out any empty keys
Utilities.ClearEmptyKeys(protections);
return protections;
}
}
}

View File

@@ -1,14 +1,159 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Linq;
namespace BurnOutSharp
{
public static class Utilities
internal static class Utilities
{
#region Dictionary Manipulation
/// <summary>
/// Append one result to a results dictionary
/// </summary>
/// <param name="original">Dictionary to append to</param>
/// <param name="key">Key to add information to</param>
/// <param name="value">String value to add</param>
public static void AppendToDictionary(Dictionary<string, List<string>> original, string key, string value)
{
AppendToDictionary(original, key, new List<string> { value });
}
/// <summary>
/// Append one result to a results dictionary
/// </summary>
/// <param name="original">Dictionary to append to</param>
/// <param name="key">Key to add information to</param>
/// <param name="value">String value to add</param>
public static void AppendToDictionary(Dictionary<string, List<string>> original, string key, List<string> values)
{
// If the dictionary is null, just return
if (original == null)
return;
// Use a placeholder value if the key is null
key = key ?? "NO FILENAME";
// Add the key if needed and then append the lists
if (!original.ContainsKey(key))
original[key] = new List<string>();
original[key].AddRange(values);
}
/// <summary>
/// Append one results dictionary to another
/// </summary>
/// <param name="original">Dictionary to append to</param>
/// <param name="addition">Dictionary to pull from</param>
public static void AppendToDictionary(Dictionary<string, List<string>> original, Dictionary<string, List<string>> addition)
{
// If either dictionary is missing, just return
if (original == null || addition == null)
return;
// Loop through each of the addition keys and add accordingly
foreach (string key in addition.Keys)
{
if (!original.ContainsKey(key))
original[key] = new List<string>();
original[key].AddRange(addition[key]);
}
}
/// <summary>
/// Remove empty or null keys from a results dictionary
/// </summary>
/// <param name="original">Dictionary to clean</param>
public static void ClearEmptyKeys(Dictionary<string, List<string>> original)
{
// If the dictionary is missing, we can't do anything
if (original == null)
return;
// Get a list of all of the keys
var keys = original.Keys.ToList();
// Iterate and reset keys
for (int i = 0; i < keys.Count; i++)
{
// Get the current key
string key = keys[i];
// If the key is empty, remove it
if (original[key] == null || !original[key].Any())
original.Remove(key);
}
}
/// <summary>
/// Prepend a parent path from dictionary keys, if possible
/// </summary>
/// <param name="original">Dictionary to strip values from</param>
/// <param name="pathToPrepend">Path to strip from the keys</param>
public static void PrependToKeys(Dictionary<string, List<string>> original, string pathToPrepend)
{
// If the dictionary is missing, we can't do anything
if (original == null)
return;
// Use a placeholder value if the path is null
pathToPrepend = (pathToPrepend ?? "ARCHIVE").TrimEnd(Path.DirectorySeparatorChar);
// Get a list of all of the keys
var keys = original.Keys.ToList();
// Iterate and reset keys
for (int i = 0; i < keys.Count; i++)
{
// Get the current key
string currentKey = keys[i];
// Otherwise, get the new key name and transfer over
string newKey = $"{pathToPrepend}{Path.DirectorySeparatorChar}{currentKey.Trim(Path.DirectorySeparatorChar)}";
original[newKey] = original[currentKey];
original.Remove(currentKey);
}
}
/// <summary>
/// Strip a parent path from dictionary keys, if possible
/// </summary>
/// <param name="original">Dictionary to strip values from</param>
/// <param name="pathToStrip">Path to strip from the keys</param>
public static void StripFromKeys(Dictionary<string, List<string>> original, string pathToStrip)
{
// If either is missing, we can't do anything
if (original == null || string.IsNullOrEmpty(pathToStrip))
return;
// Get a list of all of the keys
var keys = original.Keys.ToList();
// Iterate and reset keys
for (int i = 0; i < keys.Count; i++)
{
// Get the current key
string currentKey = keys[i];
// If the key doesn't start with the path, don't touch it
if (!currentKey.StartsWith(pathToStrip, StringComparison.OrdinalIgnoreCase))
continue;
// Otherwise, get the new key name and transfer over
string newKey = currentKey.Substring(pathToStrip.Length);
original[newKey] = original[currentKey];
original.Remove(currentKey);
}
}
#endregion
#region Byte Arrays
/// <summary>
/// Search for a byte array in another array
/// </summary>
@@ -69,6 +214,8 @@ namespace BurnOutSharp
return true;
}
#endregion
/// <summary>
/// Get the file version as reported by the filesystem
/// </summary>
@@ -85,267 +232,5 @@ namespace BurnOutSharp
else
return fvinfo.ProductVersion.Replace(", ", ".");
}
/// <summary>
/// Get the filesystem name for the given drive letter
/// </summary>
/// <remarks>
/// http://pinvoke.net/default.aspx/kernel32/GetVolumeInformation.html
/// </remarks>
public static string GetFileSystemName(char driveLetter)
{
string fsName = null;
StringBuilder volname = new StringBuilder(261);
StringBuilder fsname = new StringBuilder(261);
if (GetVolumeInformation($"{driveLetter}:\\", volname, volname.Capacity, out uint sernum, out uint maxlen, out FileSystemFeature flags, fsname, fsname.Capacity))
{
// Now you know the file system of your drive
// NTFS or FAT16 or UDF for instance
fsName = fsname.ToString();
}
return fsName;
}
#region P/Invoke
// https://stackoverflow.com/questions/8819188/c-sharp-classes-to-undelete-files/8820157#8820157
// Move Method
public const uint FileBegin = 0;
public const uint FileCurrent = 1;
public const uint FileEnd = 2;
// Handle Constants
public const uint INVALID_HANDLE_VALUE = 0;
public const int IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x2D1080;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
[MarshalAs(UnmanagedType.U4)] FileAccess access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
IntPtr templateFile);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public extern static bool GetVolumeInformation(
string rootPathName,
StringBuilder volumeNameBuffer,
int volumeNameSize,
out uint volumeSerialNumber,
out uint maximumComponentLength,
out FileSystemFeature fileSystemFlags,
StringBuilder fileSystemNameBuffer,
int nFileSystemNameSize);
[DllImport("Kernel32.dll", SetLastError = true)]
public extern static bool DeviceIoControl(
IntPtr hDevice,
uint IoControlCode,
IntPtr InMediaRemoval,
uint InBufferSize,
IntPtr OutBuffer,
int OutBufferSize,
out int BytesReturned,
IntPtr Overlapped);
// Used to read in a file
[DllImport("kernel32.dll")]
public static extern bool ReadFile(
IntPtr hFile,
byte[] lpBuffer,
uint nNumberOfBytesToRead,
ref uint lpNumberOfBytesRead,
IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
public static extern bool ReadFileEx(
IntPtr hFile,
[Out] byte[] lpBuffer,
uint nNumberOfBytesToRead,
[In] ref NativeOverlapped lpOverlapped,
IOCompletionCallback lpCompletionRoutine);
// Used to set the offset in file to start reading
[DllImport("kernel32.dll")]
public static extern bool SetFilePointerEx(
IntPtr hFile,
long liDistanceToMove,
ref IntPtr lpNewFilePointer,
uint dwMoveMethod);
[StructLayout(LayoutKind.Sequential)]
struct STORAGE_DEVICE_NUMBER
{
public int DeviceType;
public int DeviceNumber;
public int PartitionNumber;
}
public enum MEDIA_TYPE : uint
{
Unknown,
F5_1Pt2_512,
F3_1Pt44_512,
F3_2Pt88_512,
F3_20Pt8_512,
F3_720_512,
F5_360_512,
F5_320_512,
F5_320_1024,
F5_180_512,
F5_160_512,
RemovableMedia,
FixedMedia,
F3_120M_512,
F3_640_512,
F5_640_512,
F5_720_512,
F3_1Pt2_512,
F3_1Pt23_1024,
F5_1Pt23_1024,
F3_128Mb_512,
F3_230Mb_512,
F8_256_128,
F3_200Mb_512,
F3_240M_512,
F3_32M_512
}
[StructLayout(LayoutKind.Sequential)]
public struct DISK_GEOMETRY
{
public long Cylinders;
public MEDIA_TYPE MediaType;
public int TracksPerCylinder;
public int SectorsPerTrack;
public int BytesPerSector;
public long DiskSize
{
get
{
return Cylinders * (long)TracksPerCylinder * (long)SectorsPerTrack * (long)BytesPerSector;
}
}
}
[Flags]
public enum FileSystemFeature : uint
{
/// <summary>
/// The file system preserves the case of file names when it places a name on disk.
/// </summary>
CasePreservedNames = 2,
/// <summary>
/// The file system supports case-sensitive file names.
/// </summary>
CaseSensitiveSearch = 1,
/// <summary>
/// The specified volume is a direct access (DAX) volume. This flag was introduced in Windows 10, version 1607.
/// </summary>
DaxVolume = 0x20000000,
/// <summary>
/// The file system supports file-based compression.
/// </summary>
FileCompression = 0x10,
/// <summary>
/// The file system supports named streams.
/// </summary>
NamedStreams = 0x40000,
/// <summary>
/// The file system preserves and enforces access control lists (ACL).
/// </summary>
PersistentACLS = 8,
/// <summary>
/// The specified volume is read-only.
/// </summary>
ReadOnlyVolume = 0x80000,
/// <summary>
/// The volume supports a single sequential write.
/// </summary>
SequentialWriteOnce = 0x100000,
/// <summary>
/// The file system supports the Encrypted File System (EFS).
/// </summary>
SupportsEncryption = 0x20000,
/// <summary>
/// The specified volume supports extended attributes. An extended attribute is a piece of
/// application-specific metadata that an application can associate with a file and is not part
/// of the file's data.
/// </summary>
SupportsExtendedAttributes = 0x00800000,
/// <summary>
/// The specified volume supports hard links. For more information, see Hard Links and Junctions.
/// </summary>
SupportsHardLinks = 0x00400000,
/// <summary>
/// The file system supports object identifiers.
/// </summary>
SupportsObjectIDs = 0x10000,
/// <summary>
/// The file system supports open by FileID. For more information, see FILE_ID_BOTH_DIR_INFO.
/// </summary>
SupportsOpenByFileId = 0x01000000,
/// <summary>
/// The file system supports re-parse points.
/// </summary>
SupportsReparsePoints = 0x80,
/// <summary>
/// The file system supports sparse files.
/// </summary>
SupportsSparseFiles = 0x40,
/// <summary>
/// The volume supports transactions.
/// </summary>
SupportsTransactions = 0x200000,
/// <summary>
/// The specified volume supports update sequence number (USN) journals. For more information,
/// see Change Journal Records.
/// </summary>
SupportsUsnJournal = 0x02000000,
/// <summary>
/// The file system supports Unicode in file names as they appear on disk.
/// </summary>
UnicodeOnDisk = 4,
/// <summary>
/// The specified volume is a compressed volume, for example, a DoubleSpace volume.
/// </summary>
VolumeIsCompressed = 0x8000,
/// <summary>
/// The file system supports disk quotas.
/// </summary>
VolumeQuotas = 0x20
}
#endregion
}
}

BIN
BurnOutSharp/mspack.dll Normal file

Binary file not shown.

View File

@@ -14,17 +14,18 @@ In addition to the original BurnOut code, the following libraries (or ports ther
- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MPQ extraction
- [UnshieldSharp](https://github.com/mnadareski/UnshieldSharp) - InstallShield CAB extraction
- [WiseUnpacker](https://github.com/mnadareski/WiseUnpacker) - Wise Installer extraction
- [wix-libs](https://wixtoolset.org/) - MSI extraction
## Protections Detected
Below is a list of the protections that can be detected using this code:
- 3PLock
- 321Studios Online Activation
- AACS
- ActiveMARK / ActiveMARK 5
- Alpha-DVD
- Alpha-ROM
- Armadillo
- Bitpool
- ByteShield
- Cactus Data Shield
@@ -36,12 +37,11 @@ Below is a list of the protections that can be detected using this code:
- Cenga ProtectDVD
- Code Lock
- CopyKiller
- Cucko (EA Custom) (partial)
- DiscGuard
- DVD-Cops
- DVD-Movie-PROTECT
- DVD Crypt
- EXE Stealth
- EA Protections (Including Cucko, EA CDKey, and EA DRM)
- Freelock
- Games for Windows - Live (partial)
- Hexalock Autolock
@@ -83,6 +83,35 @@ Below is a list of the protections that can be detected using this code:
- Xtreme-Protector
- Zzxzz
## Executable Packers Detected
Below is a list of the executable packers that can be detected using this code:
- Armadillo
- dotFuscator
- EXE Stealth
- NSIS
- PECompact
- UPX
## Archive Formats
Below is a list of archive or archive-like formats that can be extracted and have contents scanned using this code:
- 7zip
- BFPK
- BZIP2
- GZIP
- InstallShield CAB
- Microsoft CAB (.NET Framework 4.7.2 and 4.8 only)
- MPQ
- Microsoft Installer (MSI) (.NET Framework 4.7.2 and 4.8 only)
- PKZIP and derived files
- RAR
- TAR
- Valve archive formats
- XZ
## Contributions
Contributions to the project are welcome. Please follow the current coding styles and please do not add any keys or legally dubious things to the code. Thank you to all of the testers, particularly from the DICUI project who helped get this rolling.

View File

@@ -9,22 +9,46 @@ namespace Test
{
static void Main(string[] args)
{
// Create progress indicator
var p = new Progress<FileProtection>();
p.ProgressChanged += Changed;
// Create scanner to be shared
var scanner = new Scanner(p)
{
IncludePosition = true,
ScanAllFiles = false,
ScanArchives = true,
ScanPackers = true,
};
foreach (string arg in args)
{
string protections = String.Join("\r\n", ProtectionFind.Scan(arg, true, p).Select(kvp => kvp.Key + ": " + kvp.Value.TrimEnd()));
Console.WriteLine(protections);
using (StreamWriter sw = new StreamWriter(File.OpenWrite($"{DateTime.Now:yyyy-MM-dd_HHmmss}.txt")))
var protections = scanner.GetProtections(arg);
if (protections != null)
{
sw.WriteLine(protections);
using (StreamWriter sw = new StreamWriter(File.OpenWrite($"{DateTime.Now:yyyy-MM-dd_HHmmss}.txt")))
{
foreach (string key in protections.Keys)
{
// Skip over files with no protection
if (protections[key] == null || !protections[key].Any())
continue;
string line = $"{key}: {string.Join(", ", protections[key])}";
Console.WriteLine(line);
sw.WriteLine(line);
}
}
}
else
{
Console.WriteLine($"No protections found for {arg}");
}
}
Console.WriteLine("Press any button to close...");
Console.ReadLine();
//ProtectionFind.ScanSectors('D', 2048);
}
private static void Changed(object source, FileProtection value)

View File

@@ -2,7 +2,9 @@
<PropertyGroup>
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
<PlatformTarget>x86</PlatformTarget>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup>