mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-02-04 21:30:10 +00:00
Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ebcfdba53 | ||
|
|
15f020cb06 | ||
|
|
4b387f86c1 | ||
|
|
1a3a73a86d | ||
|
|
31eff196e6 | ||
|
|
828d3403f1 | ||
|
|
28d6d06033 | ||
|
|
0a2477e1b3 | ||
|
|
01451d7009 | ||
|
|
cff9582bf5 | ||
|
|
428d839700 | ||
|
|
50db0044b0 | ||
|
|
68b1ec7b3f | ||
|
|
fd524e1d5c | ||
|
|
ef581c3f36 | ||
|
|
64e67b8daa | ||
|
|
8624350b82 | ||
|
|
e3b32fd974 | ||
|
|
6f789d2454 | ||
|
|
d365dd1164 | ||
|
|
aa3afd676b | ||
|
|
69a04ff825 | ||
|
|
938e1f94bb | ||
|
|
3eda785a5a | ||
|
|
6b895fa7c8 | ||
|
|
45e10a84ae | ||
|
|
81f0400790 | ||
|
|
df90583f73 | ||
|
|
5b980e138a | ||
|
|
0dd71d72ca | ||
|
|
a7364eab67 | ||
|
|
99013e3448 | ||
|
|
7f5e93db95 | ||
|
|
4aa9662ebe | ||
|
|
68dc6c3139 | ||
|
|
8b99577c66 | ||
|
|
20ea1b4427 | ||
|
|
cf0c6126b9 | ||
|
|
49eef3f45a | ||
|
|
23e852bbdb | ||
|
|
f182dccbf2 | ||
|
|
2d2cff4d0e | ||
|
|
c0621a83cb | ||
|
|
3c5da9f7ec | ||
|
|
a7b5288277 | ||
|
|
fee980e048 | ||
|
|
21eac43e9f | ||
|
|
b55698004c | ||
|
|
40bdb9b2d9 | ||
|
|
dfabb1a244 | ||
|
|
cd5f9561bf | ||
|
|
d8d6fac67e | ||
|
|
965c32482d | ||
|
|
c8c9d4ac64 | ||
|
|
5f5abf8a14 | ||
|
|
406791b938 | ||
|
|
eb2e6e7029 | ||
|
|
9f0b41c6aa | ||
|
|
e2b72d8a5b | ||
|
|
9802840309 | ||
|
|
4a6e2fd62d | ||
|
|
79c706e35a | ||
|
|
9be19d6925 | ||
|
|
0cfb9907d0 | ||
|
|
c18e9b3538 | ||
|
|
3754c3a65b | ||
|
|
513a64df4c | ||
|
|
d18a51c7fa | ||
|
|
b43433b9ed | ||
|
|
d553395f3f | ||
|
|
28dbe8542b | ||
|
|
912e605dc8 | ||
|
|
039982d02d | ||
|
|
1a40c6cbb2 | ||
|
|
35921e3cac | ||
|
|
a42040d644 | ||
|
|
e1fb1c7bcf | ||
|
|
095de1441d | ||
|
|
43cbafc0f5 | ||
|
|
9143e4c02c | ||
|
|
2af0692ab4 |
@@ -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>
|
||||
|
||||
438
BurnOutSharp/ExecutableType/PortableExecutable.cs
Normal file
438
BurnOutSharp/ExecutableType/PortableExecutable.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
222
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
222
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
296
BurnOutSharp/FileType/IniFile.cs
Normal file
296
BurnOutSharp/FileType/IniFile.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
BurnOutSharp/FileType/MSI.cs
Normal file
58
BurnOutSharp/FileType/MSI.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class Armadillo
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class EXEStealth
|
||||
{
|
||||
47
BurnOutSharp/PackerType/NSIS.cs
Normal file
47
BurnOutSharp/PackerType/NSIS.cs
Normal 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)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class PECompact
|
||||
{
|
||||
10
BurnOutSharp/PackerType/Petite.cs
Normal file
10
BurnOutSharp/PackerType/Petite.cs
Normal 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)
|
||||
*/
|
||||
}
|
||||
}
|
||||
37
BurnOutSharp/PackerType/UPX.cs
Normal file
37
BurnOutSharp/PackerType/UPX.cs
Normal 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)";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.PackerType
|
||||
{
|
||||
public class dotFuscator
|
||||
{
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
BurnOutSharp/ProtectionType/ElectronicArts.cs
Normal file
46
BurnOutSharp/ProtectionType/ElectronicArts.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
31
BurnOutSharp/ProtectionType/Intenium.cs
Normal file
31
BurnOutSharp/ProtectionType/Intenium.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
15
BurnOutSharp/ProtectionType/ThreeTwoOneStudios.cs
Normal file
15
BurnOutSharp/ProtectionType/ThreeTwoOneStudios.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
578
BurnOutSharp/Scanner.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
BIN
BurnOutSharp/mspack.dll
Normal file
Binary file not shown.
35
README.md
35
README.md
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net48;netcoreapp3.1</TargetFrameworks>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user