mirror of
https://github.com/SabreTools/BinaryObjectScanner.git
synced 2026-07-09 02:16:46 +00:00
Location, Location, Location (#11)
* Add index to all content checks * Get mostly onto byte arrays * Migrate as much as possible to byte array * Minor cleanup * Cleanup comments, fix search * Safer CABs and auto-log on test * Comments and better SecuROM * Cleanup, Wise Detection, archives * Minor fixes * Add externals, cleanup README * Add WiseUnpacker * Add Wise extraction * Better separation of special file format handling * Consistent licencing * Add to README * Fix StartsWith * Fix Valve scanning * Fix build * Remove old TODO * Fix BFPK extraction * More free decompression formats * Fix EVORE * Fix LibCrypt detection * Fix EVORE deletion
This commit is contained in:
@@ -3,12 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29306.81
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BurnOutSharp", "BurnOutSharp\BurnOutSharp.csproj", "{1DA4212E-6071-4951-B45D-BB74A7838246}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{88735BA2-778D-4192-8EB2-FFF6843719E2}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{68D10531-99CB-40B1-8912-73FA286C9433}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
LICENSE = LICENSE
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net462;net472;netcoreapp3.0</TargetFrameworks>
|
||||
<TargetFrameworks>net462;net472;net48;netcoreapp3.0</TargetFrameworks>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="BurnOutSharp.nuspec" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LessIO">
|
||||
<Version>0.6.16</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="libmspack4n">
|
||||
<Version>0.9.10</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UnshieldSharp">
|
||||
<Version>1.4.2.3</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="zlib.net">
|
||||
<Version>1.0.4</Version>
|
||||
</PackageReference>
|
||||
<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" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="HLLib.x64.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="HLLib.x86.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StormLib.dll">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="StormLib.pdb">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<package >
|
||||
<package>
|
||||
<metadata>
|
||||
<id>BurnOutSharp</id>
|
||||
<version>1.03.9.1</version>
|
||||
@@ -16,6 +16,7 @@
|
||||
<dependency id="LessIO" version="0.5.0" />
|
||||
<dependency id="libmspack4n" version="0.8.0" />
|
||||
<dependency id="UnshieldSharp" version="1.4.2.3" />
|
||||
<dependency id="WiseUnpacker" version="1.0.0" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -57,120 +57,115 @@ namespace BurnOutSharp
|
||||
return startingprocess;
|
||||
}
|
||||
|
||||
private static string MakeTempFile(string file, string sExtension = ".exe")
|
||||
private static string MakeTempFile(byte[] fileContent, string sExtension = ".exe")
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
FileInfo filei = new FileInfo(file);
|
||||
string filei = Guid.NewGuid().ToString();
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), "tmp", $"{filei}{sExtension}");
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "tmp", filei.Name + "*" + sExtension));
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
catch { }
|
||||
filei = filei.CopyTo(Path.GetTempPath() + "tmp" + filei.Name + Directory.GetFiles(Path.GetTempPath(), "tmp" + filei.Name + "*" + sExtension).Length + sExtension, true);
|
||||
filei.Attributes = FileAttributes.Temporary | FileAttributes.NotContentIndexed;
|
||||
return filei.FullName;
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempPath));
|
||||
using (BinaryWriter bw = new BinaryWriter(File.OpenWrite(tempPath)))
|
||||
{
|
||||
bw.Write(fileContent);
|
||||
}
|
||||
|
||||
return Path.GetFullPath(tempPath);
|
||||
}
|
||||
|
||||
private static bool IsEXE(string file)
|
||||
private static bool IsEXE(byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return false;
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, 60);
|
||||
short Characteristics = BitConverter.ToInt16(fileContent, PEHeaderOffset + 22);
|
||||
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(file));
|
||||
breader.ReadBytes(60);
|
||||
int PEHeaderOffset = breader.ReadInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset, SeekOrigin.Begin);
|
||||
breader.ReadBytes(22);
|
||||
short Characteristics = breader.ReadInt16();
|
||||
breader.Close();
|
||||
//check if file is dll
|
||||
// Check if file is dll
|
||||
if ((Characteristics & 0x2000) == 0x2000)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string[] CopyDependentDlls(string exefile)
|
||||
private static string[] CopyDependentDlls(string file, byte[] fileContent)
|
||||
{
|
||||
if (exefile == null)
|
||||
return null;
|
||||
Section[] sections = ReadSections(fileContent);
|
||||
|
||||
FileInfo fiExe = new FileInfo(exefile);
|
||||
Section[] sections = ReadSections(exefile);
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(exefile), Encoding.Default);
|
||||
long lastPosition;
|
||||
string[] saDependentDLLs = null;
|
||||
breader.ReadBytes(60);
|
||||
int PEHeaderOffset = breader.ReadInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 120 + 8, SeekOrigin.Begin); //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
|
||||
uint ImportTableRVA = breader.ReadUInt32();
|
||||
uint ImportTableSize = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(RVA2Offset(ImportTableRVA, sections), SeekOrigin.Begin);
|
||||
breader.BaseStream.Seek(12, SeekOrigin.Current);
|
||||
uint DllNameRVA = breader.ReadUInt32();
|
||||
int index = 60;
|
||||
int PEHeaderOffset = BitConverter.ToInt32(fileContent, index);
|
||||
index = PEHeaderOffset + 120 + 8; //120 Bytes till IMAGE_DATA_DIRECTORY array,8 Bytes=size of IMAGE_DATA_DIRECTORY
|
||||
uint ImportTableRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
uint ImportTableSize = BitConverter.ToUInt32(fileContent, index);
|
||||
index = (int)RVA2Offset(ImportTableRVA, sections);
|
||||
index += 12;
|
||||
uint DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
while (DllNameRVA != 0)
|
||||
{
|
||||
string sDllName = "";
|
||||
byte bChar;
|
||||
lastPosition = breader.BaseStream.Position;
|
||||
lastPosition = index;
|
||||
uint DLLNameOffset = RVA2Offset(DllNameRVA, sections);
|
||||
if (DLLNameOffset > 0)
|
||||
{
|
||||
breader.BaseStream.Seek(DLLNameOffset, SeekOrigin.Begin);
|
||||
if (breader.PeekChar() > -1)
|
||||
index = (int)DLLNameOffset;
|
||||
if ((char)fileContent[index] > -1)
|
||||
{
|
||||
do
|
||||
{
|
||||
bChar = breader.ReadByte();
|
||||
bChar = fileContent[index];
|
||||
index++;
|
||||
sDllName += (char)bChar;
|
||||
} while (bChar != 0 && breader.PeekChar() > -1);
|
||||
} while (bChar != 0 && (char)fileContent[index] > -1);
|
||||
|
||||
sDllName = sDllName.Remove(sDllName.Length - 1, 1);
|
||||
if (File.Exists(Path.Combine(fiExe.DirectoryName, sDllName)))
|
||||
if (File.Exists(Path.Combine(Path.GetDirectoryName(file), sDllName)))
|
||||
{
|
||||
if (saDependentDLLs == null)
|
||||
saDependentDLLs = new string[0];
|
||||
else
|
||||
saDependentDLLs = new string[saDependentDLLs.Length];
|
||||
|
||||
FileInfo fiDLL = new FileInfo(Path.Combine(fiExe.DirectoryName, sDllName));
|
||||
FileInfo fiDLL = new FileInfo(Path.Combine(Path.GetDirectoryName(file), sDllName));
|
||||
saDependentDLLs[saDependentDLLs.Length - 1] = fiDLL.CopyTo(Path.GetTempPath() + sDllName, true).FullName;
|
||||
}
|
||||
}
|
||||
|
||||
breader.BaseStream.Seek(lastPosition, SeekOrigin.Begin);
|
||||
index = (int)lastPosition;
|
||||
}
|
||||
|
||||
breader.BaseStream.Seek(4 + 12, SeekOrigin.Current);
|
||||
DllNameRVA = breader.ReadUInt32();
|
||||
index += 4 + 12;
|
||||
DllNameRVA = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
breader.Close();
|
||||
return saDependentDLLs;
|
||||
}
|
||||
|
||||
private static Section[] ReadSections(string exefile)
|
||||
private static Section[] ReadSections(byte[] fileContent)
|
||||
{
|
||||
if (exefile == null)
|
||||
if (fileContent == null)
|
||||
return null;
|
||||
|
||||
BinaryReader breader = new BinaryReader(File.OpenRead(exefile));
|
||||
breader.ReadBytes(60);
|
||||
uint PEHeaderOffset = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 6, SeekOrigin.Begin);
|
||||
ushort NumberOfSections = breader.ReadUInt16();
|
||||
breader.BaseStream.Seek(PEHeaderOffset + 120 + 16 * 8, SeekOrigin.Begin);
|
||||
uint PEHeaderOffset = BitConverter.ToUInt32(fileContent, 60);
|
||||
ushort NumberOfSections = BitConverter.ToUInt16(fileContent, (int)PEHeaderOffset + 6);
|
||||
Section[] sections = new Section[NumberOfSections];
|
||||
int index = (int)PEHeaderOffset + 120 + 16 * 8;
|
||||
for (int i = 0; i < NumberOfSections; i++)
|
||||
{
|
||||
breader.BaseStream.Seek(8, SeekOrigin.Current);
|
||||
uint ivs = breader.ReadUInt32();
|
||||
uint ivo = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(4, SeekOrigin.Current);
|
||||
uint iro = breader.ReadUInt32();
|
||||
breader.BaseStream.Seek(16, SeekOrigin.Current);
|
||||
index += 8;
|
||||
uint ivs = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
uint ivo = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
index += 4;
|
||||
uint iro = BitConverter.ToUInt32(fileContent, index);
|
||||
index += 4;
|
||||
index += 16;
|
||||
|
||||
sections[i] = new Section()
|
||||
{
|
||||
@@ -179,7 +174,7 @@ namespace BurnOutSharp
|
||||
iRawOffset = iro,
|
||||
};
|
||||
}
|
||||
breader.Close();
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
@@ -197,19 +192,15 @@ namespace BurnOutSharp
|
||||
|
||||
#region "EVORE version-search-functions"
|
||||
|
||||
public static string SearchProtectDiscVersion(string file)
|
||||
public static string SearchProtectDiscVersion(string file, byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
Process exe = new Process();
|
||||
Process[] processes = new Process[0];
|
||||
string version = "";
|
||||
DateTime timestart;
|
||||
if (!IsEXE(file))
|
||||
if (!IsEXE(fileContent))
|
||||
return "";
|
||||
string tempexe = MakeTempFile(file);
|
||||
string[] DependentDlls = CopyDependentDlls(file);
|
||||
|
||||
string tempexe = MakeTempFile(fileContent);
|
||||
string[] DependentDlls = CopyDependentDlls(file, fileContent);
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
@@ -228,9 +219,12 @@ namespace BurnOutSharp
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
exe = StartSafe(tempexe);
|
||||
|
||||
Process exe = StartSafe(tempexe);
|
||||
if (exe == null)
|
||||
return "";
|
||||
|
||||
Process[] processes = new Process[0];
|
||||
timestart = DateTime.Now;
|
||||
do
|
||||
{
|
||||
@@ -242,6 +236,7 @@ namespace BurnOutSharp
|
||||
{
|
||||
files = Directory.GetFiles(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ProtectDisc"), "p*.dll");
|
||||
}
|
||||
|
||||
if (files != null)
|
||||
{
|
||||
if (files.Length > 0)
|
||||
@@ -326,11 +321,13 @@ namespace BurnOutSharp
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "a*.tmp"));
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "PCD*.sys"));
|
||||
@@ -355,19 +352,16 @@ namespace BurnOutSharp
|
||||
return version;
|
||||
}
|
||||
|
||||
public static string SearchSafeDiscVersion(string file)
|
||||
public static string SearchSafeDiscVersion(string file, byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
Process exe = new Process();
|
||||
string version = "";
|
||||
DateTime timestart;
|
||||
if (!IsEXE(file))
|
||||
if (!IsEXE(fileContent))
|
||||
return "";
|
||||
|
||||
string tempexe = MakeTempFile(file);
|
||||
string[] DependentDlls = CopyDependentDlls(file);
|
||||
string tempexe = MakeTempFile(fileContent);
|
||||
string[] DependentDlls = CopyDependentDlls(file, fileContent);
|
||||
try
|
||||
{
|
||||
Directory.Delete(Path.Combine(Path.GetTempPath(), "~e*"), true);
|
||||
@@ -419,9 +413,9 @@ namespace BurnOutSharp
|
||||
try
|
||||
{
|
||||
File.Delete(Path.Combine(Path.GetTempPath(), "~e*"));
|
||||
File.Delete(tempexe);
|
||||
}
|
||||
catch { }
|
||||
File.Delete(tempexe);
|
||||
|
||||
if (DependentDlls != null)
|
||||
{
|
||||
|
||||
1663
BurnOutSharp/External/HLLib/HLExtract.Net/HLLib.cs
vendored
Normal file
1663
BurnOutSharp/External/HLLib/HLExtract.Net/HLLib.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1158
BurnOutSharp/External/HLLib/HLExtract.Net/Program.cs
vendored
Normal file
1158
BurnOutSharp/External/HLLib/HLExtract.Net/Program.cs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
414
BurnOutSharp/External/StormLibSharp/MpqArchive.cs
vendored
Normal file
414
BurnOutSharp/External/StormLibSharp/MpqArchive.cs
vendored
Normal file
@@ -0,0 +1,414 @@
|
||||
using StormLibSharp.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public class MpqArchive : IDisposable
|
||||
{
|
||||
private MpqArchiveSafeHandle _handle;
|
||||
private List<MpqFileStream> _openFiles = new List<MpqFileStream>();
|
||||
private FileAccess _accessType;
|
||||
private List<MpqArchiveCompactingEventHandler> _compactCallbacks = new List<MpqArchiveCompactingEventHandler>();
|
||||
private SFILE_COMPACT_CALLBACK _compactCallback;
|
||||
|
||||
#region Constructors / Factories
|
||||
public MpqArchive(string filePath, FileAccess accessType)
|
||||
{
|
||||
_accessType = accessType;
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsFile;
|
||||
if (accessType == FileAccess.Read)
|
||||
flags |= SFileOpenArchiveFlags.AccessReadOnly;
|
||||
else
|
||||
flags |= SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
|
||||
// constant 2 = SFILE_OPEN_HARD_DISK_FILE
|
||||
if (!NativeMethods.SFileOpenArchive(filePath, 2, flags, out _handle))
|
||||
throw new Win32Exception(); // Implicitly calls GetLastError
|
||||
}
|
||||
|
||||
public MpqArchive(MemoryMappedFile file, FileAccess accessType)
|
||||
{
|
||||
_accessType = accessType;
|
||||
string fileName = Win32Methods.GetFileNameOfMemoryMappedFile(file);
|
||||
if (fileName == null)
|
||||
throw new ArgumentException("Could not retrieve the name of the file to initialize.");
|
||||
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsMemoryMapped;
|
||||
if (accessType == FileAccess.Read)
|
||||
flags |= SFileOpenArchiveFlags.AccessReadOnly;
|
||||
else
|
||||
flags |= SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
|
||||
// constant 2 = SFILE_OPEN_HARD_DISK_FILE
|
||||
if (!NativeMethods.SFileOpenArchive(fileName, 2, flags, out _handle))
|
||||
throw new Win32Exception(); // Implicitly calls GetLastError
|
||||
}
|
||||
|
||||
private MpqArchive(string filePath, MpqArchiveVersion version, MpqFileStreamAttributes listfileAttributes, MpqFileStreamAttributes attributesFileAttributes, int maxFileCount)
|
||||
{
|
||||
if (maxFileCount < 0)
|
||||
throw new ArgumentException("maxFileCount");
|
||||
|
||||
SFileOpenArchiveFlags flags = SFileOpenArchiveFlags.TypeIsFile | SFileOpenArchiveFlags.AccessReadWriteShare;
|
||||
flags |= (SFileOpenArchiveFlags)version;
|
||||
|
||||
//SFILE_CREATE_MPQ create = new SFILE_CREATE_MPQ()
|
||||
//{
|
||||
// cbSize = unchecked((uint)Marshal.SizeOf(typeof(SFILE_CREATE_MPQ))),
|
||||
// dwMaxFileCount = unchecked((uint)maxFileCount),
|
||||
// dwMpqVersion = (uint)version,
|
||||
// dwFileFlags1 = (uint)listfileAttributes,
|
||||
// dwFileFlags2 = (uint)attributesFileAttributes,
|
||||
// dwStreamFlags = (uint)flags,
|
||||
//};
|
||||
|
||||
//if (!NativeMethods.SFileCreateArchive2(filePath, ref create, out _handle))
|
||||
// throw new Win32Exception();
|
||||
if (!NativeMethods.SFileCreateArchive(filePath, (uint)flags, int.MaxValue, out _handle))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public static MpqArchive CreateNew(string mpqPath, MpqArchiveVersion version)
|
||||
{
|
||||
return CreateNew(mpqPath, version, MpqFileStreamAttributes.None, MpqFileStreamAttributes.None, int.MaxValue);
|
||||
}
|
||||
|
||||
public static MpqArchive CreateNew(string mpqPath, MpqArchiveVersion version, MpqFileStreamAttributes listfileAttributes,
|
||||
MpqFileStreamAttributes attributesFileAttributes, int maxFileCount)
|
||||
{
|
||||
return new MpqArchive(mpqPath, version, listfileAttributes, attributesFileAttributes, maxFileCount);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
// TODO: Move to common location.
|
||||
// This is a global setting, not per-archive setting.
|
||||
|
||||
//public int Locale
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// throw new NotImplementedException();
|
||||
// }
|
||||
//}
|
||||
|
||||
public long MaxFileCount
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileGetMaxFileCount(_handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > uint.MaxValue)
|
||||
throw new ArgumentException("value");
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileSetMaxFileCount(_handle, unchecked((uint)value)))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyHandle()
|
||||
{
|
||||
if (_handle == null || _handle.IsInvalid)
|
||||
throw new ObjectDisposedException("MpqArchive");
|
||||
}
|
||||
|
||||
public bool IsPatchedArchive
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileIsPatchedArchive(_handle);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
VerifyHandle();
|
||||
if (!NativeMethods.SFileFlushArchive(_handle))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public int AddListFile(string listfileContents)
|
||||
{
|
||||
VerifyHandle();
|
||||
return NativeMethods.SFileAddListFile(_handle, listfileContents);
|
||||
}
|
||||
|
||||
public void AddFileFromDisk(string filePath, string archiveName)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileAddFile(_handle, filePath, archiveName, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public void Compact(string listfile)
|
||||
{
|
||||
VerifyHandle();
|
||||
if (!NativeMethods.SFileCompactArchive(_handle, listfile, false))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
private void _OnCompact(IntPtr pvUserData, uint dwWorkType, ulong bytesProcessed, ulong totalBytes)
|
||||
{
|
||||
MpqArchiveCompactingEventArgs args = new MpqArchiveCompactingEventArgs(dwWorkType, bytesProcessed, totalBytes);
|
||||
OnCompacting(args);
|
||||
}
|
||||
|
||||
protected virtual void OnCompacting(MpqArchiveCompactingEventArgs e)
|
||||
{
|
||||
foreach (var cb in _compactCallbacks)
|
||||
{
|
||||
cb(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public event MpqArchiveCompactingEventHandler Compacting
|
||||
{
|
||||
add
|
||||
{
|
||||
VerifyHandle();
|
||||
_compactCallback = _OnCompact;
|
||||
if (!NativeMethods.SFileSetCompactCallback(_handle, _compactCallback, IntPtr.Zero))
|
||||
throw new Win32Exception();
|
||||
|
||||
_compactCallbacks.Add(value);
|
||||
}
|
||||
remove
|
||||
{
|
||||
_compactCallbacks.Remove(value);
|
||||
|
||||
VerifyHandle();
|
||||
if (_compactCallbacks.Count == 0)
|
||||
{
|
||||
if (!NativeMethods.SFileSetCompactCallback(_handle, null, IntPtr.Zero))
|
||||
{
|
||||
// Don't do anything here. Remove shouldn't fail hard.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Determine if SFileGetAttributes/SFileSetAttributes/SFileUpdateFileAttributes deserves a projection.
|
||||
// It's unclear - these seem to affect the (attributes) file but I can't figure out exactly what that means.
|
||||
|
||||
public void AddPatchArchive(string patchPath)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileOpenPatchArchive(_handle, patchPath, null, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public void AddPatchArchives(IEnumerable<string> patchPaths)
|
||||
{
|
||||
if (patchPaths == null)
|
||||
throw new ArgumentNullException("patchPaths");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
foreach (string path in patchPaths)
|
||||
{
|
||||
// Don't sublet to AddPatchArchive to avoid having to repeatedly call VerifyHandle()
|
||||
if (!NativeMethods.SFileOpenPatchArchive(_handle, path, null, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasFile(string fileToFind)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return NativeMethods.SFileHasFile(_handle, fileToFind);
|
||||
}
|
||||
|
||||
public MpqFileStream OpenFile(string fileName)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
MpqFileSafeHandle fileHandle;
|
||||
if (!NativeMethods.SFileOpenFileEx(_handle, fileName, 0, out fileHandle))
|
||||
throw new Win32Exception();
|
||||
|
||||
MpqFileStream fs = new MpqFileStream(fileHandle, _accessType, this);
|
||||
_openFiles.Add(fs);
|
||||
return fs;
|
||||
}
|
||||
|
||||
public void ExtractFile(string fileToExtract, string destinationPath)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (!NativeMethods.SFileExtractFile(_handle, fileToExtract, destinationPath, 0))
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
public MpqFileVerificationResults VerifyFile(string fileToVerify)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return (MpqFileVerificationResults)NativeMethods.SFileVerifyFile(_handle, fileToVerify, 0);
|
||||
}
|
||||
|
||||
// TODO: Consider SFileVerifyRawData
|
||||
|
||||
public MpqArchiveVerificationResult VerifyArchive()
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return (MpqArchiveVerificationResult)NativeMethods.SFileVerifyArchive(_handle);
|
||||
}
|
||||
|
||||
|
||||
#region IDisposable implementation
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
~MpqArchive()
|
||||
{
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
// Release owned files first.
|
||||
if (_openFiles != null)
|
||||
{
|
||||
foreach (var file in _openFiles)
|
||||
{
|
||||
file.Dispose();
|
||||
}
|
||||
|
||||
_openFiles.Clear();
|
||||
_openFiles = null;
|
||||
}
|
||||
|
||||
// Release
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
_handle.Close();
|
||||
_handle = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void RemoveOwnedFile(MpqFileStream file)
|
||||
{
|
||||
_openFiles.Remove(file);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public enum MpqArchiveVersion
|
||||
{
|
||||
Version1 = 0,
|
||||
Version2 = 0x01000000,
|
||||
Version3 = 0x02000000,
|
||||
Version4 = 0x03000000,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MpqFileStreamAttributes
|
||||
{
|
||||
None = 0x0,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum MpqFileVerificationResults
|
||||
{
|
||||
/// <summary>
|
||||
/// There were no errors with the file.
|
||||
/// </summary>
|
||||
Verified = 0,
|
||||
/// <summary>
|
||||
/// Failed to open the file
|
||||
/// </summary>
|
||||
Error = 0x1,
|
||||
/// <summary>
|
||||
/// Failed to read all data from the file
|
||||
/// </summary>
|
||||
ReadError = 0x2,
|
||||
/// <summary>
|
||||
/// File has sector CRC
|
||||
/// </summary>
|
||||
HasSectorCrc = 0x4,
|
||||
/// <summary>
|
||||
/// Sector CRC check failed
|
||||
/// </summary>
|
||||
SectorCrcError = 0x8,
|
||||
/// <summary>
|
||||
/// File has CRC32
|
||||
/// </summary>
|
||||
HasChecksum = 0x10,
|
||||
/// <summary>
|
||||
/// CRC32 check failed
|
||||
/// </summary>
|
||||
ChecksumError = 0x20,
|
||||
/// <summary>
|
||||
/// File has data MD5
|
||||
/// </summary>
|
||||
HasMd5 = 0x40,
|
||||
/// <summary>
|
||||
/// MD5 check failed
|
||||
/// </summary>
|
||||
Md5Error = 0x80,
|
||||
/// <summary>
|
||||
/// File has raw data MD5
|
||||
/// </summary>
|
||||
HasRawMd5 = 0x100,
|
||||
/// <summary>
|
||||
/// Raw MD5 check failed
|
||||
/// </summary>
|
||||
RawMd5Error = 0x200,
|
||||
}
|
||||
|
||||
public enum MpqArchiveVerificationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// There is no signature in the MPQ
|
||||
/// </summary>
|
||||
NoSignature = 0,
|
||||
/// <summary>
|
||||
/// There was an error during verifying signature (like no memory)
|
||||
/// </summary>
|
||||
VerificationFailed = 1,
|
||||
/// <summary>
|
||||
/// There is a weak signature and sign check passed
|
||||
/// </summary>
|
||||
WeakSignatureVerified = 2,
|
||||
/// <summary>
|
||||
/// There is a weak signature but sign check failed
|
||||
/// </summary>
|
||||
WeakSignatureFailed = 3,
|
||||
/// <summary>
|
||||
/// There is a strong signature and sign check passed
|
||||
/// </summary>
|
||||
StrongSignatureVerified = 4,
|
||||
/// <summary>
|
||||
/// There is a strong signature but sign check failed
|
||||
/// </summary>
|
||||
StrongSignatureFailed = 5,
|
||||
}
|
||||
}
|
||||
49
BurnOutSharp/External/StormLibSharp/MpqArchiveCompactingEventArgs.cs
vendored
Normal file
49
BurnOutSharp/External/StormLibSharp/MpqArchiveCompactingEventArgs.cs
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public delegate void MpqArchiveCompactingEventHandler(MpqArchive sender, MpqArchiveCompactingEventArgs e);
|
||||
|
||||
public class MpqArchiveCompactingEventArgs : EventArgs
|
||||
{
|
||||
internal MpqArchiveCompactingEventArgs(uint dwWorkType, ulong processed, ulong total)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
WorkType = (MpqCompactingWorkType)dwWorkType;
|
||||
BytesProcessed = (long)processed;
|
||||
TotalBytes = (long)total;
|
||||
}
|
||||
}
|
||||
|
||||
public MpqCompactingWorkType WorkType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public long BytesProcessed
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public long TotalBytes
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
public enum MpqCompactingWorkType
|
||||
{
|
||||
CheckingFiles = 1,
|
||||
CheckingHashTable = 2,
|
||||
CopyingNonMpqData = 3,
|
||||
CompactingFiles = 4,
|
||||
ClosingArchive = 5,
|
||||
}
|
||||
}
|
||||
185
BurnOutSharp/External/StormLibSharp/MpqFileStream.cs
vendored
Normal file
185
BurnOutSharp/External/StormLibSharp/MpqFileStream.cs
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
using StormLibSharp.Native;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
namespace StormLibSharp
|
||||
{
|
||||
public class MpqFileStream : Stream
|
||||
{
|
||||
private MpqFileSafeHandle _handle;
|
||||
private FileAccess _accessType;
|
||||
private MpqArchive _owner;
|
||||
|
||||
internal MpqFileStream(MpqFileSafeHandle handle, FileAccess accessType, MpqArchive owner)
|
||||
{
|
||||
_handle = handle;
|
||||
_accessType = accessType;
|
||||
_owner = owner;
|
||||
}
|
||||
|
||||
private void VerifyHandle()
|
||||
{
|
||||
if (_handle == null || _handle.IsInvalid || _handle.IsClosed)
|
||||
throw new ObjectDisposedException("MpqFileStream");
|
||||
}
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get { VerifyHandle(); return true; }
|
||||
}
|
||||
|
||||
public override bool CanSeek
|
||||
{
|
||||
get { VerifyHandle(); return true; }
|
||||
}
|
||||
|
||||
public override bool CanWrite
|
||||
{
|
||||
get { VerifyHandle(); return _accessType != FileAccess.Read; }
|
||||
}
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
_owner.Flush();
|
||||
}
|
||||
|
||||
public override long Length
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
uint high = 0;
|
||||
uint low = NativeMethods.SFileGetFileSize(_handle, ref high);
|
||||
|
||||
ulong val = (high << 32) | low;
|
||||
return unchecked((long)val);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
return NativeMethods.SFileGetFilePointer(_handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
Seek(value, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
public override unsafe int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
bool success;
|
||||
uint read;
|
||||
fixed (byte* pb = &buffer[offset])
|
||||
{
|
||||
NativeOverlapped overlapped = default(NativeOverlapped);
|
||||
success = NativeMethods.SFileReadFile(_handle, new IntPtr(pb), unchecked((uint)count), out read, ref overlapped);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
int lastError = Win32Methods.GetLastError();
|
||||
if (lastError != 38) // EOF
|
||||
throw new Win32Exception(lastError);
|
||||
}
|
||||
|
||||
return unchecked((int)read);
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
uint low, high;
|
||||
low = unchecked((uint)(offset & 0xffffffffu));
|
||||
high = unchecked((uint)(offset >> 32));
|
||||
return NativeMethods.SFileSetFilePointer(_handle, low, ref high, (uint)origin);
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override unsafe void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
VerifyHandle();
|
||||
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset > buffer.Length || (offset + count) > buffer.Length)
|
||||
throw new ArgumentException();
|
||||
if (count < 0)
|
||||
throw new ArgumentOutOfRangeException("count");
|
||||
|
||||
VerifyHandle();
|
||||
|
||||
bool success;
|
||||
fixed (byte* pb = &buffer[offset])
|
||||
{
|
||||
success = NativeMethods.SFileWriteFile(_handle, new IntPtr(pb), unchecked((uint)count), 0u);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
throw new Win32Exception();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_handle != null && !_handle.IsInvalid)
|
||||
{
|
||||
_handle.Close();
|
||||
_handle = null;
|
||||
}
|
||||
|
||||
if (_owner != null)
|
||||
{
|
||||
_owner.RemoveOwnedFile(this);
|
||||
_owner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Seems like the right place for SFileGetFileInfo, but will need to determine
|
||||
// what value add these features have except for sophisticated debugging purposes
|
||||
// (like in Ladis' MPQ Editor app).
|
||||
|
||||
public int ChecksumCrc32
|
||||
{
|
||||
get
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] GetMd5Hash()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
BurnOutSharp/External/StormLibSharp/Native/Callbacks.cs
vendored
Normal file
17
BurnOutSharp/External/StormLibSharp/Native/Callbacks.cs
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_DOWNLOAD_CALLBACK(IntPtr pvUserData, ulong byteOffset, uint dwTotalBytes);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_COMPACT_CALLBACK(IntPtr pvUserData, uint dwWorkType, ulong bytesProcessed, ulong totalBytes);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
internal delegate void SFILE_ADDFILE_CALLBACK(IntPtr pvUserData, uint dwBytesWritte, uint dwTotalBytes, bool bFinalCall);
|
||||
}
|
||||
26
BurnOutSharp/External/StormLibSharp/Native/MpqArchiveSafeHandle.cs
vendored
Normal file
26
BurnOutSharp/External/StormLibSharp/Native/MpqArchiveSafeHandle.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal sealed class MpqArchiveSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public MpqArchiveSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqArchiveSafeHandle()
|
||||
: base(true) { }
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseArchive(this.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
27
BurnOutSharp/External/StormLibSharp/Native/MpqFileSafeHandle.cs
vendored
Normal file
27
BurnOutSharp/External/StormLibSharp/Native/MpqFileSafeHandle.cs
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal sealed class MpqFileSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
|
||||
{
|
||||
public MpqFileSafeHandle(IntPtr handle)
|
||||
: base(true)
|
||||
{
|
||||
this.SetHandle(handle);
|
||||
}
|
||||
|
||||
public MpqFileSafeHandle()
|
||||
: base(true)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
return NativeMethods.SFileCloseFile(this.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
497
BurnOutSharp/External/StormLibSharp/Native/NativeMethods.cs
vendored
Normal file
497
BurnOutSharp/External/StormLibSharp/Native/NativeMethods.cs
vendored
Normal file
@@ -0,0 +1,497 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
private const string STORMLIB = "stormlib.dll";
|
||||
|
||||
#region Functions for manipulation with StormLib global flags
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetLocale();
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileSetLocale(uint lcNewLocale);
|
||||
#endregion
|
||||
|
||||
#region Functions for archive manipulation
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenArchive(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
uint dwPriority,
|
||||
SFileOpenArchiveFlags dwFlags,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateArchive(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
uint dwCreateFlags,
|
||||
uint dwMaxFileCount,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateArchive2(
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szMpqName,
|
||||
ref SFILE_CREATE_MPQ pCreateInfo,
|
||||
out MpqArchiveSafeHandle phMpq
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetDownloadCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.FunctionPtr)] SFILE_DOWNLOAD_CALLBACK pfnCallback,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFlushArchive(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(IntPtr hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Adds another listfile into MPQ.
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileAddListFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Archive compacting
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetCompactCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
SFILE_COMPACT_CALLBACK compactCB,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCompactArchive(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile,
|
||||
bool bReserved
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Maximum file count
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetMaxFileCount(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetMaxFileCount(MpqArchiveSafeHandle hMpq, uint dwMaxFileCount);
|
||||
#endregion
|
||||
|
||||
#region Changing (attributes) file
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetAttributes(MpqArchiveSafeHandle hMpq);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetAttributes(MpqArchiveSafeHandle hMpq, uint dwFlags);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileUpdateFileAttributes(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Functions for manipulation with patch archives
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenPatchArchive(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szPatchMpqName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szPatchPathPrefix,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileIsPatchedArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Functions for file manipulation
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileHasFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileOpenFileEx(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwSearchScope,
|
||||
out MpqFileSafeHandle phFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileGetFileSize(MpqFileSafeHandle hFile, ref uint pdwFileSizeHigh);
|
||||
|
||||
public static unsafe uint SFileGetFilePointer(
|
||||
MpqFileSafeHandle hFile
|
||||
)
|
||||
{
|
||||
if (hFile.IsInvalid || hFile.IsClosed)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
IntPtr handle = hFile.DangerousGetHandle();
|
||||
_TMPQFileHeader* header = (_TMPQFileHeader*)handle.ToPointer();
|
||||
return header->dwFilePos;
|
||||
}
|
||||
|
||||
//public static unsafe uint SFileGetFileSize(
|
||||
// MpqFileSafeHandle hFile
|
||||
// )
|
||||
//{
|
||||
// if (hFile.IsInvalid || hFile.IsClosed)
|
||||
// throw new InvalidOperationException();
|
||||
|
||||
// IntPtr handle = hFile.DangerousGetHandle();
|
||||
// _TMPQFileHeader* header = (_TMPQFileHeader*)handle.ToPointer();
|
||||
// return header->pFileEntry->dwFileSize;
|
||||
//}
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileSetFilePointer(
|
||||
MpqFileSafeHandle hFile,
|
||||
uint lFilePos,
|
||||
ref uint plFilePosHigh,
|
||||
uint dwMoveMethod
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileReadFile(
|
||||
MpqFileSafeHandle hFile,
|
||||
IntPtr lpBuffer,
|
||||
uint dwToRead,
|
||||
out uint pdwRead,
|
||||
ref System.Threading.NativeOverlapped lpOverlapped
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseFile(IntPtr hFile);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCloseFile(MpqFileSafeHandle hFile);
|
||||
|
||||
#region Retrieving info about a file in the archive
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
IntPtr hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
MpqArchiveSafeHandle hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileInfo(
|
||||
MpqFileSafeHandle hMpqOrFile,
|
||||
SFileInfoClass InfoClass,
|
||||
IntPtr pvFileInfo,
|
||||
uint cbFileInfoSize,
|
||||
out uint pcbLengthNeeded
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileName(
|
||||
MpqFileSafeHandle hFile,
|
||||
[MarshalAs(UnmanagedType.LPStr)] out string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFreeFileInfo(
|
||||
IntPtr pvFileInfo,
|
||||
SFileInfoClass infoClass
|
||||
);
|
||||
#endregion
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileExtractFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szToExtract,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szExtracted,
|
||||
uint dwSearchScope
|
||||
);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions for file and archive verification
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileGetFileChecksums(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
out uint pdwCrc32,
|
||||
IntPtr pMD5
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileVerifyFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileVerifyRawData(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
uint dwWhatToVerify,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern uint SFileVerifyArchive(MpqArchiveSafeHandle hMpq);
|
||||
#endregion
|
||||
|
||||
#region Functions for file searching
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern IntPtr SFileFindFirstFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szMask,
|
||||
out _SFILE_FIND_DATA lpFindFileData,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFindNextFile(
|
||||
IntPtr hFind,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFindClose(IntPtr hFind);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern IntPtr SListFileFindFirstFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szListFile,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szMask,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SListFileFindNextFile(
|
||||
IntPtr hFind,
|
||||
[In, Out] ref _SFILE_FIND_DATA lpFindFileData
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SListFileFindClose(IntPtr hFind);
|
||||
#endregion
|
||||
|
||||
#region Locale support
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SFileEnumLocales(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
IntPtr plcLocales,
|
||||
ref uint pdwMaxLocales,
|
||||
uint dwSearchScope
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Support for adding files to the MPQ
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileCreateFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchiveName,
|
||||
ulong fileTime,
|
||||
uint dwFileSize,
|
||||
uint lcLocale,
|
||||
uint dwFlags,
|
||||
out IntPtr phFile
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileWriteFile(
|
||||
MpqFileSafeHandle hFile,
|
||||
IntPtr pvData,
|
||||
uint dwSize,
|
||||
uint dwCompression
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileFinishFile(MpqFileSafeHandle hFile);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddFileEx(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags,
|
||||
uint dwCompression,
|
||||
uint dwCompressionNext
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileAddWave(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPTStr)] string szFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szArchivedName,
|
||||
uint dwFlags,
|
||||
uint dwQuality
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileRemoveFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szFileName,
|
||||
uint dwSearchScope
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileRenameFile(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szOldFileName,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string szNewFileName
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetFileLocale(
|
||||
MpqFileSafeHandle hFile,
|
||||
uint lcNewLocale
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetDataCompression(uint DataCompression);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern bool SFileSetAddFileCallback(
|
||||
MpqArchiveSafeHandle hMpq,
|
||||
SFILE_ADDFILE_CALLBACK AddFileCB,
|
||||
IntPtr pvUserData
|
||||
);
|
||||
#endregion
|
||||
|
||||
#region Compression and decompression
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompImplode(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompExplode(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompCompress(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer,
|
||||
uint uCompressionMask,
|
||||
int nCmpType,
|
||||
int nCmpLevel
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompDecompress(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
[DllImport(STORMLIB, CallingConvention = CallingConvention.Winapi, ExactSpelling = true, PreserveSig = true, SetLastError = true, ThrowOnUnmappableChar = false)]
|
||||
public static extern int SCompDecompress2(
|
||||
IntPtr pvOutBuffer,
|
||||
ref int pcbOutBuffer,
|
||||
IntPtr pvInBuffer,
|
||||
int cbInBuffer
|
||||
);
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#pragma warning disable 0169,0649
|
||||
internal struct SFILE_CREATE_MPQ
|
||||
{
|
||||
public uint cbSize;
|
||||
public uint dwMpqVersion;
|
||||
private IntPtr pvUserData;
|
||||
private uint cbUserData;
|
||||
public uint dwStreamFlags;
|
||||
public uint dwFileFlags1;
|
||||
public uint dwFileFlags2;
|
||||
public uint dwAttrFlags;
|
||||
public uint dwSectorSize;
|
||||
public uint dwRawChunkSize;
|
||||
public uint dwMaxFileCount;
|
||||
}
|
||||
|
||||
internal unsafe struct _SFILE_FIND_DATA
|
||||
{
|
||||
public fixed char cFileName[260]; // Full name of the found file
|
||||
|
||||
public IntPtr szPlainName; // Plain name of the found file
|
||||
public uint dwHashIndex; // Hash table index for the file
|
||||
public uint dwBlockIndex; // Block table index for the file
|
||||
public uint dwFileSize; // File size in bytes
|
||||
public uint dwFileFlags; // MPQ file flags
|
||||
public uint dwCompSize; // Compressed file size
|
||||
public uint dwFileTimeLo; // Low 32-bits of the file time (0 if not present)
|
||||
public uint dwFileTimeHi; // High 32-bits of the file time (0 if not present)
|
||||
public uint lcLocale; // Locale version
|
||||
}
|
||||
|
||||
internal unsafe struct _TFileEntry
|
||||
{
|
||||
public ulong FileNameHash;
|
||||
public ulong ByteOffset;
|
||||
public ulong FileTime;
|
||||
public uint dwHashIndex;
|
||||
public uint dwFileSize;
|
||||
public uint dwCmpSize;
|
||||
public uint dwFlags;
|
||||
public ushort lcLocale;
|
||||
public ushort wPlatform;
|
||||
public uint dwCrc32;
|
||||
public fixed byte md5[16];
|
||||
public IntPtr szFileName;
|
||||
}
|
||||
|
||||
// Provides enough of _TMPQFile to get to the file size and current position.
|
||||
internal unsafe struct _TMPQFileHeader
|
||||
{
|
||||
public IntPtr pStream;
|
||||
public IntPtr ha;
|
||||
public _TFileEntry* pFileEntry;
|
||||
public uint dwFileKey;
|
||||
public uint dwFilePos;
|
||||
}
|
||||
#pragma warning restore 0169,0649
|
||||
|
||||
}
|
||||
70
BurnOutSharp/External/StormLibSharp/Native/SFileInfoClass.cs
vendored
Normal file
70
BurnOutSharp/External/StormLibSharp/Native/SFileInfoClass.cs
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal enum SFileInfoClass
|
||||
{
|
||||
// Info classes for archives
|
||||
SFileMpqFileName, // Name of the archive file (TCHAR [])
|
||||
SFileMpqStreamBitmap, // Array of bits, each bit means availability of one block (BYTE [])
|
||||
SFileMpqUserDataOffset, // Offset of the user data header (ULONGLONG)
|
||||
SFileMpqUserDataHeader, // Raw (unfixed) user data header (TMPQUserData)
|
||||
SFileMpqUserData, // MPQ USer data, without the header (BYTE [])
|
||||
SFileMpqHeaderOffset, // Offset of the MPQ header (ULONGLONG)
|
||||
SFileMpqHeaderSize, // Fixed size of the MPQ header
|
||||
SFileMpqHeader, // Raw (unfixed) archive header (TMPQHeader)
|
||||
SFileMpqHetTableOffset, // Offset of the HET table, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHetTableSize, // Compressed size of the HET table (ULONGLONG)
|
||||
SFileMpqHetHeader, // HET table header (TMPQHetHeader)
|
||||
SFileMpqHetTable, // HET table as pointer. Must be freed using SFileFreeFileInfo
|
||||
SFileMpqBetTableOffset, // Offset of the BET table, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqBetTableSize, // Compressed size of the BET table (ULONGLONG)
|
||||
SFileMpqBetHeader, // BET table header, followed by the flags (TMPQBetHeader + DWORD[])
|
||||
SFileMpqBetTable, // BET table as pointer. Must be freed using SFileFreeFileInfo
|
||||
SFileMpqHashTableOffset, // Hash table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHashTableSize64, // Compressed size of the hash table (ULONGLONG)
|
||||
SFileMpqHashTableSize, // Size of the hash table, in entries (DWORD)
|
||||
SFileMpqHashTable, // Raw (unfixed) hash table (TMPQBlock [])
|
||||
SFileMpqBlockTableOffset, // Block table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqBlockTableSize64, // Compressed size of the block table (ULONGLONG)
|
||||
SFileMpqBlockTableSize, // Size of the block table, in entries (DWORD)
|
||||
SFileMpqBlockTable, // Raw (unfixed) block table (TMPQBlock [])
|
||||
SFileMpqHiBlockTableOffset, // Hi-block table offset, relative to MPQ header (ULONGLONG)
|
||||
SFileMpqHiBlockTableSize64, // Compressed size of the hi-block table (ULONGLONG)
|
||||
SFileMpqHiBlockTable, // The hi-block table (USHORT [])
|
||||
SFileMpqSignatures, // Signatures present in the MPQ (DWORD)
|
||||
SFileMpqStrongSignatureOffset, // Byte offset of the strong signature, relative to begin of the file (ULONGLONG)
|
||||
SFileMpqStrongSignatureSize, // Size of the strong signature (DWORD)
|
||||
SFileMpqStrongSignature, // The strong signature (BYTE [])
|
||||
SFileMpqArchiveSize64, // Archive size from the header (ULONGLONG)
|
||||
SFileMpqArchiveSize, // Archive size from the header (DWORD)
|
||||
SFileMpqMaxFileCount, // Max number of files in the archive (DWORD)
|
||||
SFileMpqFileTableSize, // Number of entries in the file table (DWORD)
|
||||
SFileMpqSectorSize, // Sector size (DWORD)
|
||||
SFileMpqNumberOfFiles, // Number of files (DWORD)
|
||||
SFileMpqRawChunkSize, // Size of the raw data chunk for MD5
|
||||
SFileMpqStreamFlags, // Stream flags (DWORD)
|
||||
SFileMpqIsReadOnly, // Nonzero if the MPQ is read only (DWORD)
|
||||
|
||||
// Info classes for files
|
||||
SFileInfoPatchChain, // Chain of patches where the file is (TCHAR [])
|
||||
SFileInfoFileEntry, // The file entry for the file (TFileEntry)
|
||||
SFileInfoHashEntry, // Hash table entry for the file (TMPQHash)
|
||||
SFileInfoHashIndex, // Index of the hash table entry (DWORD)
|
||||
SFileInfoNameHash1, // The first name hash in the hash table (DWORD)
|
||||
SFileInfoNameHash2, // The second name hash in the hash table (DWORD)
|
||||
SFileInfoNameHash3, // 64-bit file name hash for the HET/BET tables (ULONGLONG)
|
||||
SFileInfoLocale, // File locale (DWORD)
|
||||
SFileInfoFileIndex, // Block index (DWORD)
|
||||
SFileInfoByteOffset, // File position in the archive (ULONGLONG)
|
||||
SFileInfoFileTime, // File time (ULONGLONG)
|
||||
SFileInfoFileSize, // Size of the file (DWORD)
|
||||
SFileInfoCompressedSize, // Compressed file size (DWORD)
|
||||
SFileInfoFlags, // File flags from (DWORD)
|
||||
SFileInfoEncryptionKey, // File encryption key
|
||||
SFileInfoEncryptionKeyRaw, // Unfixed value of the file key
|
||||
}
|
||||
}
|
||||
26
BurnOutSharp/External/StormLibSharp/Native/SFileOpenArchiveFlags.cs
vendored
Normal file
26
BurnOutSharp/External/StormLibSharp/Native/SFileOpenArchiveFlags.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
[Flags]
|
||||
internal enum SFileOpenArchiveFlags : uint
|
||||
{
|
||||
None = 0,
|
||||
TypeIsFile = None,
|
||||
TypeIsMemoryMapped = 1,
|
||||
TypeIsHttp = 2,
|
||||
|
||||
AccessReadOnly = 0x100,
|
||||
AccessReadWriteShare = 0x200,
|
||||
AccessUseBitmap = 0x400,
|
||||
|
||||
DontOpenListfile = 0x10000,
|
||||
DontOpenAttributes = 0x20000,
|
||||
DontSearchHeader = 0x40000,
|
||||
ForceVersion1 = 0x80000,
|
||||
CheckSectorCRC = 0x100000,
|
||||
}
|
||||
}
|
||||
60
BurnOutSharp/External/StormLibSharp/Native/Win32Methods.cs
vendored
Normal file
60
BurnOutSharp/External/StormLibSharp/Native/Win32Methods.cs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.MemoryMappedFiles;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StormLibSharp.Native
|
||||
{
|
||||
internal static class Win32Methods
|
||||
{
|
||||
[DllImport("kernel32", ExactSpelling = false, SetLastError = true)]
|
||||
public static extern uint GetMappedFileName(
|
||||
IntPtr hProcess,
|
||||
IntPtr fileHandle,
|
||||
IntPtr lpFilename,
|
||||
uint nSize
|
||||
);
|
||||
|
||||
[DllImport("kernel32", ExactSpelling = false, SetLastError = true)]
|
||||
public static extern uint GetFinalPathNameByHandle(
|
||||
IntPtr hFile,
|
||||
IntPtr lpszFilePath,
|
||||
uint cchFilePath,
|
||||
uint dwFlags
|
||||
);
|
||||
|
||||
[DllImport("kernel32", SetLastError = false, ExactSpelling = false)]
|
||||
public static extern int GetLastError();
|
||||
|
||||
public static string GetFileNameOfMemoryMappedFile(MemoryMappedFile file)
|
||||
{
|
||||
const uint size = 522;
|
||||
IntPtr path = Marshal.AllocCoTaskMem(unchecked((int)size)); // MAX_PATH + 1 char
|
||||
|
||||
string result = null;
|
||||
try
|
||||
{
|
||||
// constant 0x2 = VOLUME_NAME_NT
|
||||
uint test = GetFinalPathNameByHandle(file.SafeMemoryMappedFileHandle.DangerousGetHandle(), path, size, 0x2);
|
||||
if (test != 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
result = Marshal.PtrToStringAuto(path);
|
||||
}
|
||||
catch
|
||||
{
|
||||
uint test = GetMappedFileName(Process.GetCurrentProcess().Handle, file.SafeMemoryMappedFileHandle.DangerousGetHandle(), path, size);
|
||||
if (test != 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
result = Marshal.PtrToStringAuto(path);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
4
BurnOutSharp/External/psxt001z/LibCrypt.cs
vendored
@@ -63,7 +63,7 @@ namespace BurnOutSharp.External.psxt001z
|
||||
{
|
||||
subfile.Seek(12, SeekOrigin.Current);
|
||||
if (subfile.Read(buffer, 0, 12) == 0)
|
||||
return true;
|
||||
return modifiedSectors != 0;
|
||||
|
||||
subfile.Seek(72, SeekOrigin.Current);
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace BurnOutSharp.External.psxt001z
|
||||
}
|
||||
|
||||
Console.WriteLine($"Number of modified sectors: {modifiedSectors}");
|
||||
return true;
|
||||
return modifiedSectors != 0;
|
||||
}
|
||||
|
||||
private static byte btoi(byte b)
|
||||
|
||||
122
BurnOutSharp/FileType/BFPK.cs
Normal file
122
BurnOutSharp/FileType/BFPK.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.Deflate;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BFPK
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x42, 0x46, 0x50, 0x4b }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the BFPK file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
br.ReadBytes(4); // Skip magic number
|
||||
|
||||
int version = br.ReadInt32();
|
||||
int files = br.ReadInt32();
|
||||
long current = br.BaseStream.Position;
|
||||
|
||||
for (int i = 0; i < files; i++)
|
||||
{
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
|
||||
int nameSize = br.ReadInt32();
|
||||
string name = new string(br.ReadChars(nameSize));
|
||||
|
||||
uint uncompressedSize = br.ReadUInt32();
|
||||
int offset = br.ReadInt32();
|
||||
|
||||
current = br.BaseStream.Position;
|
||||
|
||||
br.BaseStream.Seek(offset, SeekOrigin.Begin);
|
||||
uint compressedSize = br.ReadUInt32();
|
||||
|
||||
// Some files can lack the length prefix
|
||||
if (compressedSize > br.BaseStream.Length)
|
||||
{
|
||||
br.BaseStream.Seek(-4, SeekOrigin.Current);
|
||||
compressedSize = uncompressedSize;
|
||||
}
|
||||
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, name);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(tempFile)))
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
|
||||
|
||||
if (compressedSize == uncompressedSize)
|
||||
{
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
fs.Write(br.ReadBytes((int)uncompressedSize), 0, (int)uncompressedSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (FileStream fs = File.OpenWrite(tempFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
ZlibStream zs = new ZlibStream(br.BaseStream, CompressionMode.Decompress);
|
||||
zs.CopyTo(fs);
|
||||
}
|
||||
catch (ZlibException)
|
||||
{
|
||||
br.BaseStream.Seek(offset + 4, SeekOrigin.Begin);
|
||||
fs.Write(br.ReadBytes((int)compressedSize), 0, (int)compressedSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string protection = ProtectionFind.ScanContent(tempFile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(tempFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
|
||||
br.BaseStream.Seek(current, SeekOrigin.Begin);
|
||||
}
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
BurnOutSharp/FileType/BZip2.cs
Normal file
67
BurnOutSharp/FileType/BZip2.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors;
|
||||
using SharpCompress.Compressors.BZip2;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class BZip2
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x42, 0x52, 0x68 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the 7-zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (BZip2Stream bz2File = new BZip2Stream(stream, CompressionMode.Decompress, true))
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempfile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempfile))
|
||||
{
|
||||
bz2File.CopyTo(fs);
|
||||
}
|
||||
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// 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 { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
254
BurnOutSharp/FileType/Executable.cs
Normal file
254
BurnOutSharp/FileType/Executable.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using BurnOutSharp.ProtectionType;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Executable
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// DOS MZ executable file format (and descendants)
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x5a }))
|
||||
return true;
|
||||
|
||||
// Executable and Linkable Format
|
||||
if (magic.StartsWith(new byte[] { 0x7f, 0x45, 0x4c, 0x46 }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (32-bit)
|
||||
if (magic.StartsWith(new byte[] { 0xfe, 0xed, 0xfa, 0xce }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (32-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte[] { 0xce, 0xfa, 0xed, 0xfe }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (64-bit)
|
||||
if (magic.StartsWith(new byte[] { 0xfe, 0xed, 0xfa, 0xcf }))
|
||||
return true;
|
||||
|
||||
// Mach-O binary (64-bit, reverse byte ordering scheme)
|
||||
if (magic.StartsWith(new byte[] { 0xcf, 0xfa, 0xed, 0xfe }))
|
||||
return true;
|
||||
|
||||
// Prefrred Executable File Format
|
||||
if (magic.StartsWith(new byte[] { 0x4a, 0x6f, 0x79, 0x21, 0x70, 0x65, 0x66, 0x66 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream, string file)
|
||||
{
|
||||
// Load the current file content
|
||||
byte[] fileContent = null;
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
fileContent = br.ReadBytes((int)stream.Length);
|
||||
}
|
||||
|
||||
// If we can, seek to the beginning of the stream
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
List<string> subProtections = new List<string>();
|
||||
string protection;
|
||||
|
||||
// 3PLock
|
||||
protection = ThreePLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ActiveMARK
|
||||
protection = ActiveMARK.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Alpha-ROM
|
||||
protection = AlphaROM.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Armadillo
|
||||
protection = Armadillo.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Cops
|
||||
protection = CDCops.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Lock
|
||||
protection = CDLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CDSHiELD SE
|
||||
protection = CDSHiELDSE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD Check
|
||||
protection = CDCheck.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cenega ProtectDVD
|
||||
protection = CengaProtectDVD.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Code Lock
|
||||
protection = CodeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CopyKiller
|
||||
protection = CopyKiller.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cucko (EA Custom)
|
||||
protection = Cucko.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// dotFuscator
|
||||
protection = dotFuscator.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// DVD-Cops
|
||||
protection = DVDCops.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EA CdKey Registration Module
|
||||
protection = EACdKey.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EXE Stealth
|
||||
protection = EXEStealth.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Games for Windows - Live
|
||||
protection = GFWL.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Impulse Reactor
|
||||
protection = ImpulseReactor.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Inno Setup
|
||||
protection = InnoSetup.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// JoWooD X-Prot
|
||||
protection = JoWooDXProt.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Key-Lock (Dongle)
|
||||
protection = KeyLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// LaserLock
|
||||
protection = LaserLock.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// PE Compact
|
||||
protection = PECompact.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ProtectDisc
|
||||
protection = ProtectDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Ring PROTECH
|
||||
protection = RingPROTECH.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeDisc / SafeCast
|
||||
protection = SafeDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeLock
|
||||
protection = SafeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SecuROM
|
||||
protection = SecuROM.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SmartE
|
||||
protection = SmartE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SolidShield
|
||||
protection = SolidShield.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// StarForce
|
||||
protection = StarForce.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SVK Protector
|
||||
protection = SVKProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Sysiphus / Sysiphus DVD
|
||||
protection = Sysiphus.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// TAGES
|
||||
protection = Tages.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// VOB ProtectCD/DVD
|
||||
protection = VOBProtectCDDVD.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Wise Installer
|
||||
subProtections = WiseInstaller.CheckContents(file, fileContent);
|
||||
if (subProtections != null && subProtections.Count > 0)
|
||||
protections.AddRange(subProtections);
|
||||
|
||||
// WTM CD Protect
|
||||
protection = WTMCDProtect.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Xtreme-Protector
|
||||
protection = XtremeProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
BurnOutSharp/FileType/GZIP.cs
Normal file
70
BurnOutSharp/FileType/GZIP.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.GZip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class GZIP
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x1f, 0x8b }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the gzip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (GZipArchive zipFile = GZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempfile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{entry.Key} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
BurnOutSharp/FileType/InstallShieldCAB.cs
Normal file
82
BurnOutSharp/FileType/InstallShieldCAB.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnshieldSharp;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class InstallShieldCAB
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x49, 0x53, 0x63 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static List<string> Scan(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);
|
||||
string filenamePattern = Path.Combine(directory, noExtension);
|
||||
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
|
||||
|
||||
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
|
||||
bool shouldScanCabinet = cabinetHeaderExists
|
||||
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
|
||||
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// If we have the first file
|
||||
if (shouldScanCabinet)
|
||||
{
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempFile = Path.Combine(tempPath, cabfile.FileName(i));
|
||||
if (cabfile.FileSave(i, tempFile))
|
||||
{
|
||||
string protection = ProtectionFind.ScanContent(tempFile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{cabfile.FileName(i)} - {protection}");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
BurnOutSharp/FileType/MPQ.cs
Normal file
78
BurnOutSharp/FileType/MPQ.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using StormLibSharp;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class MPQ
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x50, 0x51, 0x1a }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static List<string> Scan(string file)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the mpq file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MpqArchive mpqArchive = new MpqArchive(file, FileAccess.Read))
|
||||
{
|
||||
string listfile = null;
|
||||
MpqFileStream listStream = mpqArchive.OpenFile("(listfile)");
|
||||
bool canRead = listStream.CanRead;
|
||||
|
||||
using (StreamReader sr = new StreamReader(listStream))
|
||||
{
|
||||
listfile = sr.ReadToEnd();
|
||||
Console.WriteLine(listfile);
|
||||
}
|
||||
|
||||
string sub = string.Empty;
|
||||
while ((sub = listfile) != null)
|
||||
{
|
||||
// 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);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{sub} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
BurnOutSharp/FileType/MicrosoftCAB.cs
Normal file
66
BurnOutSharp/FileType/MicrosoftCAB.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using LibMSPackN;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class MicrosoftCAB
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x4d, 0x53, 0x43, 0x46 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static List<string> Scan(string file)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the cab file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MSCabinet cabfile = new MSCabinet(file))
|
||||
{
|
||||
foreach (var sub in cabfile.GetFiles())
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempfile = Path.Combine(tempPath, sub.Filename);
|
||||
sub.ExtractTo(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{sub.Filename} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
79
BurnOutSharp/FileType/PKZIP.cs
Normal file
79
BurnOutSharp/FileType/PKZIP.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Zip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class PKZIP
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// PKZIP
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x03, 0x04 }))
|
||||
return true;
|
||||
|
||||
// PKZIP (Empty Archive)
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x05, 0x06 }))
|
||||
return true;
|
||||
|
||||
// PKZIP (Spanned Archive)
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x4b, 0x07, 0x08 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (ZipArchive zipFile = ZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempfile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{entry.Key} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
BurnOutSharp/FileType/RAR.cs
Normal file
75
BurnOutSharp/FileType/RAR.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Rar;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class RAR
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// RAR archive version 1.50 onwards
|
||||
if (magic.StartsWith(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00 }))
|
||||
return true;
|
||||
|
||||
// RAR archive version 5.0 onwards
|
||||
if (magic.StartsWith(new byte[] { 0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x01, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the rar file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (RarArchive zipFile = RarArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in zipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempfile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{entry.Key} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
BurnOutSharp/FileType/SevenZip.cs
Normal file
70
BurnOutSharp/FileType/SevenZip.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.SevenZip;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class SevenZip
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the 7-zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (SevenZipArchive sevenZipFile = SevenZipArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in sevenZipFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempfile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{entry.Key} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
73
BurnOutSharp/FileType/TapeArchive.cs
Normal file
73
BurnOutSharp/FileType/TapeArchive.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Archives;
|
||||
using SharpCompress.Archives.Tar;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class TapeArchive
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x00, 0x30, 0x30 }))
|
||||
return true;
|
||||
|
||||
if (magic.StartsWith(new byte[] { 0x75, 0x73, 0x74, 0x61, 0x72, 0x20, 0x20, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the tar file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (TarArchive tarFile = TarArchive.Open(stream))
|
||||
{
|
||||
foreach (var entry in tarFile.Entries)
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
// If we have a directory, skip it
|
||||
if (entry.IsDirectory)
|
||||
continue;
|
||||
|
||||
string tempfile = Path.Combine(tempPath, entry.Key);
|
||||
entry.WriteToFile(tempfile);
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempfile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{entry.Key} - {protection}");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
63
BurnOutSharp/FileType/Textfile.cs
Normal file
63
BurnOutSharp/FileType/Textfile.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Textfile
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic, string extension)
|
||||
{
|
||||
// Rich Text File
|
||||
if (magic.StartsWith(new byte[] { 0x7b, 0x5c, 0x72, 0x74, 0x66, 0x31 }))
|
||||
return true;
|
||||
|
||||
// HTML
|
||||
if (magic.StartsWith(new byte[] { 0x3c, 0x68, 0x74, 0x6d, 0x6c }))
|
||||
return true;
|
||||
|
||||
// HTML and XML
|
||||
if (magic.StartsWith(new byte[] { 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45 }))
|
||||
return true;
|
||||
|
||||
// Microsoft Office File (old)
|
||||
if (magic.StartsWith(new byte[] { 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 }))
|
||||
return true;
|
||||
|
||||
// Generic textfile (no header)
|
||||
if (string.Equals(extension, "txt", StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(stream, Encoding.Default, false, 1024 * 1024, true))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
// CD-Key
|
||||
if (fileContent.Contains("a valid serial number is required")
|
||||
|| fileContent.Contains("serial number is located"))
|
||||
{
|
||||
protections.Add("CD-Key / Serial");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
82
BurnOutSharp/FileType/Valve.cs
Normal file
82
BurnOutSharp/FileType/Valve.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using HLExtract.Net;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class Valve
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
// GCF
|
||||
if (magic.StartsWith(new byte[] { 0x01, 0x00, 0x00, 0x00 }))
|
||||
return true;
|
||||
|
||||
// PAK
|
||||
if (magic.StartsWith(new byte[] { 0x50, 0x41, 0x43, 0x4b }))
|
||||
return true;
|
||||
|
||||
// SGA
|
||||
if (magic.StartsWith(new byte[] { 0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45 }))
|
||||
return true;
|
||||
|
||||
// VPK
|
||||
if (magic.StartsWith(new byte[] { 0x55, 0xaa, 0x12, 0x34 }))
|
||||
return true;
|
||||
|
||||
// WAD
|
||||
if (magic.StartsWith(new byte[] { 0x57, 0x41, 0x44, 0x33 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Add stream opening support
|
||||
public static List<string> Scan(string file)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
string[] args = new string[]
|
||||
{
|
||||
"-p", file,
|
||||
"-x", "root",
|
||||
"-x", "'extract .'",
|
||||
"-x", "exit",
|
||||
"-d", tempPath,
|
||||
};
|
||||
|
||||
HLExtractProgram.Process(args);
|
||||
|
||||
if (Directory.Exists(tempPath))
|
||||
{
|
||||
foreach (string tempFile in Directory.EnumerateFiles(tempPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
string protection = ProtectionFind.ScanContent(tempFile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(tempFile);
|
||||
}
|
||||
}
|
||||
|
||||
// If temp directory cleanup fails
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
BurnOutSharp/FileType/XZ.cs
Normal file
66
BurnOutSharp/FileType/XZ.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz;
|
||||
|
||||
namespace BurnOutSharp.FileType
|
||||
{
|
||||
internal class XZ
|
||||
{
|
||||
public static bool ShouldScan(byte[] magic)
|
||||
{
|
||||
if (magic.StartsWith(new byte[] { 0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00 }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<string> Scan(Stream stream)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the 7-zip file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (XZStream xzFile = new XZStream(stream))
|
||||
{
|
||||
// If an individual entry fails
|
||||
try
|
||||
{
|
||||
string tempfile = Path.Combine(tempPath, Guid.NewGuid().ToString());
|
||||
using (FileStream fs = File.OpenWrite(tempfile))
|
||||
{
|
||||
xzFile.CopyTo(fs);
|
||||
}
|
||||
|
||||
string protection = ProtectionFind.ScanContent(tempfile);
|
||||
|
||||
// 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 { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
BurnOutSharp/HLLib.x64.dll
Normal file
BIN
BurnOutSharp/HLLib.x64.dll
Normal file
Binary file not shown.
BIN
BurnOutSharp/HLLib.x86.dll
Normal file
BIN
BurnOutSharp/HLLib.x86.dll
Normal file
Binary file not shown.
@@ -20,12 +20,9 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using BurnOutSharp.FileType;
|
||||
using BurnOutSharp.ProtectionType;
|
||||
using LibMSPackN;
|
||||
using UnshieldSharp;
|
||||
|
||||
namespace BurnOutSharp
|
||||
{
|
||||
@@ -53,7 +50,7 @@ namespace BurnOutSharp
|
||||
protections[path] = fileProtection;
|
||||
|
||||
// Now check to see if the file contains any additional information
|
||||
string contentProtection = ScanInFile(path)?.Replace("" + (char)0x00, "");
|
||||
string contentProtection = ScanContent(path)?.Replace("" + (char)0x00, "");
|
||||
if (!string.IsNullOrWhiteSpace(contentProtection))
|
||||
{
|
||||
if (protections.ContainsKey(path))
|
||||
@@ -88,7 +85,7 @@ namespace BurnOutSharp
|
||||
protections[file] = fileProtection;
|
||||
|
||||
// Now check to see if the file contains any additional information
|
||||
string contentProtection = ScanInFile(file)?.Replace("" + (char)0x00, "");
|
||||
string contentProtection = ScanContent(file)?.Replace("" + (char)0x00, "");
|
||||
if (!string.IsNullOrWhiteSpace(contentProtection))
|
||||
{
|
||||
if (protections.ContainsKey(file))
|
||||
@@ -350,190 +347,12 @@ namespace BurnOutSharp
|
||||
/// Scan an individual file for copy protection
|
||||
/// </summary>
|
||||
/// <param name="file">File path for scanning</param>
|
||||
public static string ScanInFile(string file)
|
||||
public static string ScanContent(string file)
|
||||
{
|
||||
// Get the extension for certain checks
|
||||
string extension = Path.GetExtension(file).ToLower().TrimStart('.');
|
||||
|
||||
// Read the first 8 bytes to get the file type
|
||||
string magic = "";
|
||||
try
|
||||
using (FileStream fs = File.OpenRead(file))
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(File.OpenRead(file)))
|
||||
{
|
||||
magic = new string(br.ReadChars(8));
|
||||
}
|
||||
return ScanContent(fs, file);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the issue was, we can't open the file
|
||||
return null;
|
||||
}
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
#region Executable Content Checks
|
||||
|
||||
if (magic.StartsWith("MZ") // Windows Executable and DLL
|
||||
|| magic.StartsWith((char)0x7f + "ELF") // Unix binaries
|
||||
|| magic.StartsWith("" + (char)0xfe + (char)0xed + (char)0xfa + (char)0xce) // Macintosh
|
||||
|| magic.StartsWith("" + (char)0xce + (char)0xfa + (char)0xed + (char)0xfe) // Macintosh
|
||||
|| magic.StartsWith("Joy!peff")) // Macintosh
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(file, Encoding.Default))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
|
||||
protections.AddRange(ScanFileContent(file, fileContent));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Textfile Content Checks
|
||||
|
||||
if (magic.StartsWith("{\rtf") // Rich Text File
|
||||
|| magic.StartsWith("" + (char)0xd0 + (char)0xcf + (char)0x11 + (char)0xe0 + (char)0xa1 + (char)0xb1 + (char)0x1a + (char)0xe1) // Microsoft Office File (old)
|
||||
|| extension == "txt") // Generic textfile (no header)
|
||||
{
|
||||
try
|
||||
{
|
||||
StreamReader sr = File.OpenText(file);
|
||||
string FileContent = sr.ReadToEnd().ToLower();
|
||||
sr.Close();
|
||||
|
||||
// CD-Key
|
||||
if (FileContent.Contains("a valid serial number is required")
|
||||
|| FileContent.Contains("serial number is located"))
|
||||
{
|
||||
protections.Add("CD-Key / Serial");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Archive Content Checks
|
||||
|
||||
// 7-zip
|
||||
if (magic.StartsWith("7z" + (char)0xbc + (char)0xaf + (char)0x27 + (char)0x1c))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// InstallShield CAB
|
||||
else if (magic.StartsWith("ISc"))
|
||||
{
|
||||
// Get the name of the first cabinet file or header
|
||||
string directory = Path.GetDirectoryName(file);
|
||||
string noExtension = Path.GetFileNameWithoutExtension(file);
|
||||
string filenamePattern = Path.Combine(directory, noExtension);
|
||||
filenamePattern = new Regex(@"\d+$").Replace(filenamePattern, string.Empty);
|
||||
|
||||
bool cabinetHeaderExists = File.Exists(Path.Combine(directory, filenamePattern + "1.hdr"));
|
||||
bool shouldScanCabinet = cabinetHeaderExists
|
||||
? file.Equals(Path.Combine(directory, filenamePattern + "1.hdr"), StringComparison.OrdinalIgnoreCase)
|
||||
: file.Equals(Path.Combine(directory, filenamePattern + "1.cab"), StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
// If we have the first file
|
||||
if (shouldScanCabinet)
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
UnshieldCabinet cabfile = UnshieldCabinet.Open(file);
|
||||
for (int i = 0; i < cabfile.FileCount; i++)
|
||||
{
|
||||
string tempFileName = Path.Combine(tempPath, cabfile.FileName(i));
|
||||
if (cabfile.FileSave(i, tempFileName))
|
||||
{
|
||||
string protection = ScanInFile(tempFileName);
|
||||
try
|
||||
{
|
||||
File.Delete(tempFileName);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(protection);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// Microsoft CAB
|
||||
else if (magic.StartsWith("MSCF"))
|
||||
{
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
using (MSCabinet cabfile = new MSCabinet(file))
|
||||
{
|
||||
foreach (var sub in cabfile.GetFiles())
|
||||
{
|
||||
string tempfile = Path.Combine(tempPath, sub.Filename);
|
||||
sub.ExtractTo(tempfile);
|
||||
string protection = ScanInFile(tempfile);
|
||||
File.Delete(tempfile);
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add(protection);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempPath, true);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// PKZIP
|
||||
else if (magic.StartsWith("PK" + (char)03 + (char)04)
|
||||
|| magic.StartsWith("PK" + (char)05 + (char)06)
|
||||
|| magic.StartsWith("PK" + (char)07 + (char)08))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
// RAR
|
||||
else if (magic.StartsWith("Rar!"))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Return blank if nothing found, or comma-separated list of protections
|
||||
if (protections.Count() == 0)
|
||||
return string.Empty;
|
||||
else
|
||||
return string.Join(", ", protections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -541,115 +360,82 @@ namespace BurnOutSharp
|
||||
/// </summary>
|
||||
/// <param name="stream">Generic stream to scan</param>
|
||||
/// <param name="file">File path to be used for name checks (optional)</param>
|
||||
public static string ScanInFile(Stream stream, string file = null)
|
||||
public static string ScanContent(Stream stream, string file = null)
|
||||
{
|
||||
// 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
|
||||
string magic = "";
|
||||
byte[] magic = new byte[16];
|
||||
try
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(stream, Encoding.Default, true))
|
||||
{
|
||||
magic = new string(br.ReadChars(8));
|
||||
}
|
||||
stream.Read(magic, 0, 16);
|
||||
stream.Seek(-16, SeekOrigin.Current);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the issue was, we can't open the file
|
||||
// We don't care what the issue was, we can't read or seek the file
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we can, seek to the beginning of the stream
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
#region Executable Content Checks
|
||||
// 7-Zip archive
|
||||
if (SevenZip.ShouldScan(magic))
|
||||
protections.AddRange(SevenZip.Scan(stream));
|
||||
|
||||
// Windows Executable and DLL
|
||||
if (magic.StartsWith("MZ"))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(stream, Encoding.Default))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
// BFPK archive
|
||||
if (BFPK.ShouldScan(magic))
|
||||
protections.AddRange(BFPK.Scan(stream));
|
||||
|
||||
protections.AddRange(ScanFileContent(file, fileContent));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
// BZip2
|
||||
if (BZip2.ShouldScan(magic))
|
||||
protections.AddRange(BZip2.Scan(stream));
|
||||
|
||||
#endregion
|
||||
// Executable
|
||||
if (Executable.ShouldScan(magic))
|
||||
protections.AddRange(Executable.Scan(stream, file));
|
||||
|
||||
#region Textfile Content Checks
|
||||
// GZIP
|
||||
if (GZIP.ShouldScan(magic))
|
||||
protections.AddRange(GZIP.Scan(stream));
|
||||
|
||||
if (magic.StartsWith("{\rtf") // Rich Text File
|
||||
|| magic.StartsWith("" + (char)0xd0 + (char)0xcf + (char)0x11 + (char)0xe0 + (char)0xa1 + (char)0xb1 + (char)0x1a + (char)0xe1)) // Microsoft Office File (old)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Load the current file content
|
||||
string fileContent = null;
|
||||
using (StreamReader sr = new StreamReader(stream))
|
||||
{
|
||||
fileContent = sr.ReadToEnd();
|
||||
}
|
||||
// InstallShield Cabinet
|
||||
if (file != null && InstallShieldCAB.ShouldScan(magic))
|
||||
protections.AddRange(InstallShieldCAB.Scan(file));
|
||||
|
||||
// CD-Key
|
||||
if (fileContent.Contains("a valid serial number is required")
|
||||
|| fileContent.Contains("serial number is located"))
|
||||
{
|
||||
protections.Add("CD-Key / Serial");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We don't care what the error was
|
||||
}
|
||||
}
|
||||
// Microsoft Cabinet
|
||||
if (file != null && MicrosoftCAB.ShouldScan(magic))
|
||||
protections.AddRange(MicrosoftCAB.Scan(file));
|
||||
|
||||
#endregion
|
||||
// MPQ archive
|
||||
if (file != null && MPQ.ShouldScan(magic))
|
||||
protections.AddRange(MPQ.Scan(file));
|
||||
|
||||
#region Archive Content Checks
|
||||
// PKZIP archive (and derivatives)
|
||||
if (PKZIP.ShouldScan(magic))
|
||||
protections.AddRange(PKZIP.Scan(stream));
|
||||
|
||||
// 7-zip
|
||||
if (magic.StartsWith("7z" + (char)0xbc + (char)0xaf + (char)0x27 + (char)0x1c))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
// RAR archive
|
||||
if (RAR.ShouldScan(magic))
|
||||
protections.AddRange(RAR.Scan(stream));
|
||||
|
||||
// InstallShield CAB
|
||||
else if (magic.StartsWith("ISc"))
|
||||
{
|
||||
// TODO: Update UnshieldSharp to include generic stream support
|
||||
}
|
||||
// Tape Archive
|
||||
if (TapeArchive.ShouldScan(magic))
|
||||
protections.AddRange(TapeArchive.Scan(stream));
|
||||
|
||||
// Microsoft CAB
|
||||
else if (magic.StartsWith("MSCF"))
|
||||
{
|
||||
// TODO: See if LibMSPackN can use generic streams
|
||||
}
|
||||
// Text-based files
|
||||
if (Textfile.ShouldScan(magic, extension))
|
||||
protections.AddRange(Textfile.Scan(stream));
|
||||
|
||||
// PKZIP
|
||||
else if (magic.StartsWith("PK" + (char)03 + (char)04)
|
||||
|| magic.StartsWith("PK" + (char)05 + (char)06)
|
||||
|| magic.StartsWith("PK" + (char)07 + (char)08))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
// Valve archive formats
|
||||
if (file != null && Valve.ShouldScan(magic))
|
||||
protections.AddRange(Valve.Scan(file));
|
||||
|
||||
// RAR
|
||||
else if (magic.StartsWith("Rar!"))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
#endregion
|
||||
// XZ
|
||||
if (XZ.ShouldScan(magic))
|
||||
protections.AddRange(XZ.Scan(stream));
|
||||
|
||||
// Return blank if nothing found, or comma-separated list of protections
|
||||
if (protections.Count() == 0)
|
||||
@@ -658,204 +444,6 @@ namespace BurnOutSharp
|
||||
return string.Join(", ", protections);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan the contents of a file for protection
|
||||
/// </summary>
|
||||
/// TODO: This needs to work on a byte array of file content instead of string
|
||||
private static List<string> ScanFileContent(string file, string fileContent)
|
||||
{
|
||||
// Files can be protected in multiple ways
|
||||
List<string> protections = new List<string>();
|
||||
string protection;
|
||||
|
||||
// 3PLock
|
||||
protection = ThreePLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ActiveMARK
|
||||
protection = ActiveMARK.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Alpha-ROM
|
||||
protection = AlphaROM.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Armadillo
|
||||
protection = Armadillo.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Cops
|
||||
protection = CDCops.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD-Lock
|
||||
protection = CDLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CDSHiELD SE
|
||||
protection = CDSHiELDSE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CD Check
|
||||
protection = CDCheck.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cenega ProtectDVD
|
||||
protection = CengaProtectDVD.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Code Lock
|
||||
protection = CodeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// CopyKiller
|
||||
protection = CopyKiller.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Cucko (EA Custom)
|
||||
protection = Cucko.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// dotFuscator
|
||||
protection = dotFuscator.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// DVD-Cops
|
||||
protection = DVDCops.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EA CdKey Registration Module
|
||||
protection = EACdKey.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// EXE Stealth
|
||||
protection = EXEStealth.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Games for Windows - Live
|
||||
protection = GFWL.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Impulse Reactor
|
||||
protection = ImpulseReactor.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Inno Setup
|
||||
protection = InnoSetup.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// JoWooD X-Prot
|
||||
protection = JoWooDXProt.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Key-Lock (Dongle)
|
||||
protection = KeyLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// LaserLock
|
||||
protection = LaserLock.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// PE Compact
|
||||
protection = PECompact.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// ProtectDisc
|
||||
protection = ProtectDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Ring PROTECH
|
||||
protection = RingPROTECH.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeDisc / SafeCast
|
||||
protection = SafeDisc.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SafeLock
|
||||
protection = SafeLock.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SecuROM
|
||||
protection = SecuROM.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SmartE
|
||||
protection = SmartE.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SolidShield
|
||||
protection = SolidShield.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// StarForce
|
||||
protection = StarForce.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// SVK Protector
|
||||
protection = SVKProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Sysiphus / Sysiphus DVD
|
||||
protection = Sysiphus.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// TAGES
|
||||
protection = Tages.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// VOB ProtectCD/DVD
|
||||
protection = VOBProtectCDDVD.CheckContents(file, fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// WTM CD Protect
|
||||
protection = WTMCDProtect.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
// Xtreme-Protector
|
||||
protection = XtremeProtector.CheckContents(fileContent);
|
||||
if (!string.IsNullOrWhiteSpace(protection))
|
||||
protections.Add(protection);
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan a disc sector by sector for protection
|
||||
/// </summary>
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
{
|
||||
public class ActiveMARK
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("TMSAMVOF"))
|
||||
return "ActiveMARK";
|
||||
// "TMSAMVOF"
|
||||
byte[] check = new byte[] { 0x54, 0x4D, 0x53, 0x41, 0x4D, 0x56, 0x4F, 0x46 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"ActiveMARK (Index {position})";
|
||||
|
||||
if (fileContent.Contains(" " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16
|
||||
+ (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x0
|
||||
+ (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00))
|
||||
{
|
||||
return "ActiveMARK 5";
|
||||
}
|
||||
// " " + (char)0xC2 + (char)0x16 + (char)0x00 + (char)0xA8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0xB8 + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x86 + (char)0xC8 + (char)0x16 + (char)0x0 + (char)0x9A + (char)0xC1 + (char)0x16 + (char)0x00 + (char)0x10 + (char)0xC2 + (char)0x16 + (char)0x00
|
||||
check = new byte[] { 0x20, 0xC2, 0x16, 0x00, 0xA8, 0xC1, 0x16, 0x00, 0xB8, 0xC1, 0x16, 0x00, 0x86, 0xC8, 0x16, 0x0, 0x9A, 0xC1, 0x16, 0x00, 0x10, 0xC2, 0x16, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"ActiveMARK 5 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class AlphaROM
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("SETTEC"))
|
||||
return "Alpha-ROM";
|
||||
// "SETTEC"
|
||||
byte[] check = new byte[] { 0x53, 0x45, 0x54, 0x54, 0x45, 0x43 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Alpha-ROM (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
{
|
||||
public class Armadillo
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains(".nicode" + (char)0x00)
|
||||
|| fileContent.Contains("ARMDEBUG"))
|
||||
return "Armadillo";
|
||||
// ".nicode" + (char)0x00
|
||||
byte[] check = new byte[] { 0x2E, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Armadillo (Index {position})";
|
||||
|
||||
// "ARMDEBUG"
|
||||
check = new byte[] { 0x41, 0x52, 0x4D, 0x44, 0x45, 0x42, 0x55, 0x47 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"Armadillo (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,17 @@
|
||||
{
|
||||
public class CDCheck
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("GetDriveType")
|
||||
|| fileContent.Contains("GetVolumeInformation"))
|
||||
return "CD Check";
|
||||
// "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 (Index {position})";
|
||||
|
||||
// "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 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,14 +7,17 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CDCops
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("CD-Cops, ver. ")) > -1)
|
||||
return "CD-Cops " + GetVersion(file, position);
|
||||
// "CD-Cops, ver. "
|
||||
byte[] check = new byte[] { 0x43, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"CD-Cops {GetVersion(fileContent, position)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains(".grand" + (char)0x00))
|
||||
return "CD-Cops";
|
||||
// ".grand" + (char)0x00
|
||||
check = new byte[] { 0x2E, 0x67, 0x72, 0x61, 0x6E, 0x64, 0x00};
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"CD-Cops (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -47,21 +50,13 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 15, 4).Select(b => (char)b).ToArray();
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 15, SeekOrigin.Begin); // Begin reading after "CD-Cops, ver."
|
||||
char[] version = br.ReadChars(4);
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
return new string(version);
|
||||
}
|
||||
return new string(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CDLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("2" + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B
|
||||
+ "$" + (char)0x99 + (char)0xAD + "'C" + (char)0xE4 + (char)0x9D + "st"
|
||||
+ (char)0x99 + (char)0xFA + "2$" + (char)0x9D + ")4" + (char)0xFF + "t"))
|
||||
{
|
||||
return "CD-Lock";
|
||||
}
|
||||
// "2" + (char)0xF2 + (char)0x02 + (char)0x82 + (char)0xC3 + (char)0xBC + (char)0x0B + "$" + (char)0x99 + (char)0xAD + "'C" + (char)0xE4 + (char)0x9D + "st" + (char)0x99 + (char)0xFA + "2$" + (char)0x9D + ")4" + (char)0xFF + "t"
|
||||
byte[] check = new byte[] { 0x32, 0xF2, 0x02, 0x82, 0xC3, 0xBC, 0x0B, 0x24, 0x99, 0xAD, 0x27, 0x43, 0xE4, 0x9D, 0x73, 0x74, 0x99, 0xFA, 0x32, 0x24, 0x9D, 0x29, 0x34, 0xFF, 0x74 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"CD-Lock (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class CDSHiELDSE
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("~0017.tmp"))
|
||||
return "CDSHiELD SE";
|
||||
// "~0017.tmp"
|
||||
byte[] check = new byte[] { 0x7E, 0x30, 0x30, 0x31, 0x37, 0x2E, 0x74, 0x6D, 0x70 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"CDSHiELD SE (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class CengaProtectDVD
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains(".cenega"))
|
||||
return "Cenega ProtectDVD";
|
||||
// ".cenega"
|
||||
byte[] check = new byte[] { 0x2E, 0x63, 0x65, 0x6E, 0x65, 0x67, 0x61 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Cenega ProtectDVD (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,23 @@
|
||||
{
|
||||
public class CodeLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
// TODO: Verify if these are OR or AND
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
// TODO: Verify if these are OR or AND
|
||||
if (fileContent.Contains("icd1" + (char)0x00)
|
||||
|| fileContent.Contains("icd2" + (char)0x00)
|
||||
|| fileContent.Contains("CODE-LOCK.OCX"))
|
||||
{
|
||||
return "Code Lock";
|
||||
}
|
||||
// "icd1" + (char)0x00
|
||||
byte[] check = new byte[] { 0x69, 0x63, 0x64, 0x31, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Code Lock (Index {position})";
|
||||
|
||||
// "icd2" + (char)0x00
|
||||
check = new byte[] { 0x69, 0x63, 0x64, 0x32, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"Code Lock (Index {position})";
|
||||
|
||||
// "CODE-LOCK.OCX"
|
||||
check = new byte[] { 0x43, 0x4F, 0x44, 0x45, 0x2D, 0x4C, 0x4F, 0x43, 0x4B, 0x2E, 0x4F, 0x43, 0x58 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"Code Lock (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class CopyKiller
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("Tom Commander"))
|
||||
return "CopyKiller";
|
||||
// "Tom Commander"
|
||||
byte[] check = new byte[] { 0x54, 0x6F, 0x6D, 0x20, 0x43, 0x6F, 0x6D, 0x6D, 0x61, 0x6E, 0x64, 0x65, 0x72 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"CopyKiller (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
{
|
||||
public class Cucko
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
// TODO: Verify this doesn't over-match
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
// TODO: Verify this doesn't over-match
|
||||
if (fileContent.Contains("EASTL"))
|
||||
return "Cucko (EA Custom)";
|
||||
// "EASTL"
|
||||
byte[] check = new byte[] { 0x45, 0x41, 0x53, 0x54, 0x4C };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Cucko (EA Custom) (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class DVDCops
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("DVD-Cops, ver. ")) > -1)
|
||||
return "DVD-Cops " + GetVersion(file, position);
|
||||
// "DVD-Cops, ver. "
|
||||
byte[] check = new byte[] { 0x44, 0x56, 0x44, 0x2D, 0x43, 0x6F, 0x70, 0x73, 0x2C, 0x20, 0x20, 0x76, 0x65, 0x72, 0x2E, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"DVD-Cops {GetVersion(fileContent, position)} (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 15, 4).Select(b => (char)b).ToArray();
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 15, SeekOrigin.Begin); // Begin reading after "CD-Cops, ver."
|
||||
char[] version = br.ReadChars(4);
|
||||
if (version[0] == 0x00)
|
||||
return "";
|
||||
|
||||
return new string(version);
|
||||
}
|
||||
return new string(version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class EACdKey
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("ereg.ea-europe.com"))
|
||||
return "EA CdKey Registration Module";
|
||||
// "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 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
{
|
||||
public class EXEStealth
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("??[[__[[_" + (char)0x00 + "{{" + (char)0x0
|
||||
+ (char)0x00 + "{{" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0
|
||||
+ (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "?;??;??"))
|
||||
{
|
||||
return "EXE Stealth";
|
||||
}
|
||||
// "??[[__[[_" + (char)0x00 + "{{" + (char)0x0 + (char)0x00 + "{{" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x0 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "?;??;??"
|
||||
byte[] check = new byte[] { 0x3F, 0x3F, 0x5B, 0x5B, 0x5F, 0x5F, 0x5B, 0x5B, 0x5F, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x7B, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3F, 0x3B, 0x3F, 0x3F, 0x3B, 0x3F, 0x3F };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"EXE Stealth (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class GFWL
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("xlive.dll"))
|
||||
return "Games for Windows - Live";
|
||||
// "xlive.dll"
|
||||
byte[] check = new byte[] { 0x78, 0x6C, 0x69, 0x76, 0x65, 0x2E, 0x64, 0x6C, 0x6C };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Games for Windows - Live (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,22 +7,18 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ImpulseReactor
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("CVPInitializeClient"))
|
||||
// "CVPInitializeClient"
|
||||
byte[] check = new byte[] { 0x43, 0x56, 0x50, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
if (fileContent.Contains("A" + (char)0x00 + "T" + (char)0x00 + "T" + (char)0x00 + "L" + (char)0x00 + "I"
|
||||
+ (char)0x00 + "S" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "E" + (char)0x00 + "L"
|
||||
+ (char)0x00 + "E" + (char)0x00 + "M" + (char)0x00 + "E" + (char)0x00 + "N" + (char)0x00 + "T" + (char)0x00
|
||||
+ (char)0x00 + (char)0x00 + "N" + (char)0x00 + "O" + (char)0x00 + "T" + (char)0x00 + "A" + (char)0x00 + "T"
|
||||
+ (char)0x00 + "I" + (char)0x00 + "O" + (char)0x00 + "N"))
|
||||
{
|
||||
return "Impulse Reactor " + Utilities.GetFileVersion(file);
|
||||
}
|
||||
// "A" + (char)0x00 + "T" + (char)0x00 + "T" + (char)0x00 + "L" + (char)0x00 + "I" + (char)0x00 + "S" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "E" + (char)0x00 + "L" + (char)0x00 + "E" + (char)0x00 + "M" + (char)0x00 + "E" + (char)0x00 + "N" + (char)0x00 + "T" + (char)0x00 + (char)0x00 + (char)0x00 + "N" + (char)0x00 + "O" + (char)0x00 + "T" + (char)0x00 + "A" + (char)0x00 + "T" + (char)0x00 + "I" + (char)0x00 + "O" + (char)0x00 + "N"
|
||||
byte[] check2 = new byte[] { 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x53, 0x00, 0x54, 0x00, 0x00, 0x00, 0x45, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x4E, 0x00, 0x54, 0x00, 0x00, 0x00, 0x4E, 0x00, 0x4F, 0x00, 0x54, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
return $"Impulse Reactor {Utilities.GetFileVersion(file)} (Index {position}, {position2}";
|
||||
else
|
||||
{
|
||||
return "Impulse Reactor";
|
||||
}
|
||||
return $"Impulse Reactor (Index {position})";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,48 +1,55 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class InnoSetup
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
// TOOO: Add Inno Setup extraction
|
||||
// https://github.com/dscharrer/InnoExtract
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.IndexOf("Inno") == 0x30)
|
||||
{
|
||||
// TOOO: Add Inno Setup extraction
|
||||
return "Inno Setup " + GetVersion(file);
|
||||
}
|
||||
// "Inno"
|
||||
byte[] check = new byte[] { 0x49, 0x6E, 0x6E, 0x6F };
|
||||
if (fileContent.Contains(check, out int position) && position == 0x30)
|
||||
return $"Inno Setup {GetVersion(fileContent)} (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file)
|
||||
private static string GetVersion(byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
byte[] signature = new ArraySegment<byte>(fileContent, 0x30, 12).ToArray();
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(0x30, SeekOrigin.Begin);
|
||||
string signature = new string(br.ReadChars(12));
|
||||
// "rDlPtS02" + (char)0x87 + "eVx"
|
||||
if (signature.SequenceEqual( new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x32, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "1.2.10";
|
||||
|
||||
if (signature == "rDlPtS02" + (char)0x87 + "eVx")
|
||||
return "1.2.10";
|
||||
else if (signature == "rDlPtS04" + (char)0x87 + "eVx")
|
||||
return "4.0.0";
|
||||
else if (signature == "rDlPtS05" + (char)0x87 + "eVx")
|
||||
return "4.0.3";
|
||||
else if (signature == "rDlPtS06" + (char)0x87 + "eVx")
|
||||
return "4.0.10";
|
||||
else if (signature == "rDlPtS07" + (char)0x87 + "eVx")
|
||||
return "4.1.6";
|
||||
else if (signature == "rDlPtS" + (char)0xcd + (char)0xe6 + (char)0xd7 + "{" + (char)0x0b + "*")
|
||||
return "5.1.5";
|
||||
else if (signature == "nS5W7dT" + (char)0x83 + (char)0xaa + (char)0x1b + (char)0x0f + "j")
|
||||
return "5.1.5";
|
||||
// "rDlPtS04" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x34, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.0";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
// "rDlPtS05" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x35, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.3";
|
||||
|
||||
// "rDlPtS06" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x36, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.0.10";
|
||||
|
||||
// "rDlPtS07" + (char)0x87 + "eVx"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0x30, 0x37, 0x87, 0x65, 0x56, 0x78 }))
|
||||
return "4.1.6";
|
||||
|
||||
// "rDlPtS" + (char)0xcd + (char)0xe6 + (char)0xd7 + "{" + (char)0x0b + "*"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x72, 0x44, 0x6C, 0x50, 0x74, 0x53, 0xCD, 0xE6, 0xD7, 0x7B, 0x0b, 0x2A }))
|
||||
return "5.1.5";
|
||||
|
||||
// "nS5W7dT" + (char)0x83 + (char)0xaa + (char)0x1b + (char)0x0f + "j"
|
||||
else if (signature.SequenceEqual(new byte[] { 0x6E, 0x53, 0x35, 0x57, 0x37, 0x64, 0x54, 0x83, 0xAA, 0x1B, 0x0F, 0x6A }))
|
||||
return "5.1.5";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +1,36 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class JoWooDXProt
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains(".ext "))
|
||||
// ".ext "
|
||||
byte[] check = new byte[] { 0x2E, 0x65, 0x78, 0x74, 0x20, 0x20, 0x20, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
if ((position = fileContent.IndexOf("kernel32.dll" + (char)0x00 + (char)0x00 + (char)0x00 + "VirtualProtect")) > -1)
|
||||
{
|
||||
return "JoWooD X-Prot " + GetVersion(file, --position);
|
||||
}
|
||||
// "kernel32.dll" + (char)0x00 + (char)0x00 + (char)0x00 + "VirtualProtect"
|
||||
byte[] check2 = new byte[] { 0x6B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x56, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6C, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74 };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
return $"JoWooD X-Prot {GetVersion(fileContent, --position2)} (Index {position}, {position2})";
|
||||
else
|
||||
{
|
||||
return "JoWooD X-Prot v1";
|
||||
}
|
||||
return $"JoWooD X-Prot v1 (Index {position})";
|
||||
}
|
||||
|
||||
if (fileContent.Contains("@HC09 "))
|
||||
return "JoWooD X-Prot v2";
|
||||
// "@HC09 "
|
||||
check = new byte[] { 0x40, 0x48, 0x43, 0x30, 0x39, 0x20, 0x20, 0x20, 0x20 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"JoWooD X-Prot v2 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
char[] version = new char[5];
|
||||
br.BaseStream.Seek(position + 67, SeekOrigin.Begin);
|
||||
version[0] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[1] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[2] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[3] = br.ReadChar();
|
||||
version[4] = br.ReadChar();
|
||||
|
||||
return version[0] + "." + version[1] + "." + version[2] + "." + version[3] + version[4];
|
||||
}
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 67, 8).Select(b => (char)b).ToArray();
|
||||
return $"{version[0]}.{version[2]}.{version[4]}.{version[6]}{version[7]}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class KeyLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("KEY-LOCK COMMAND"))
|
||||
return "Key-Lock (Dongle)";
|
||||
// "KEY-LOCK COMMAND"
|
||||
byte[] check = new byte[] { 0x4B, 0x45, 0x59, 0x2D, 0x4C, 0x4F, 0x43, 0x4B, 0x20, 0x43, 0x4F, 0x4D, 0x4D, 0x41, 0x4E, 0x44 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Key-Lock (Dongle) (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,38 +7,35 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class LaserLock
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains("Packed by SPEEnc V2 Asterios Parlamentas.PE")
|
||||
&& (position = fileContent.IndexOf("GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
+ "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00
|
||||
+ "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF")) > -1)
|
||||
{
|
||||
return "LaserLock " + GetVersion(fileContent, position) + " " + GetBuild(fileContent, true);
|
||||
}
|
||||
// "Packed by SPEEnc V2 Asterios Parlamentas.PE"
|
||||
byte[] check = new byte[] { 0x50, 0x61, 0x63, 0x6B, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x53, 0x50, 0x45, 0x45, 0x6E, 0x63, 0x20, 0x56, 0x32, 0x20, 0x41, 0x73, 0x74, 0x65, 0x72, 0x69, 0x6F, 0x73, 0x20, 0x50, 0x61, 0x72, 0x6C, 0x61, 0x6D, 0x65, 0x6E, 0x74, 0x61, 0x73, 0x2E, 0x50, 0x45 };
|
||||
bool containsCheck = fileContent.Contains(check, out int position);
|
||||
|
||||
if (fileContent.Contains("Packed by SPEEnc V2 Asterios Parlamentas.PE"))
|
||||
return "LaserLock Marathon " + GetBuild(fileContent, false);
|
||||
// "GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00 + "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF"
|
||||
byte[] check2 = { 0x47, 0x65, 0x74, 0x4D, 0x6F, 0x64, 0x75, 0x6C, 0x65, 0x48, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x41, 0x00, 0x00, 0x00, 0x00, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6F, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x6F, 0x61, 0x64, 0x4C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x41, 0x00, 0x00, 0x4B, 0x45, 0x52, 0x4E, 0x45, 0x4C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0xEB, 0x79, 0x01, 0x53, 0x4E, 0x49, 0x46 };
|
||||
bool containsCheck2 = fileContent.Contains(check2, out int position2);
|
||||
|
||||
if ((position = fileContent.IndexOf("GetModuleHandleA" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
+ "GetProcAddress" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "LoadLibraryA" + (char)0x00 + (char)0x00
|
||||
+ "KERNEL32.dll" + (char)0x00 + "ëy" + (char)0x01 + "SNIF")) > -1)
|
||||
{
|
||||
return "LaserLock " + GetVersion(fileContent, --position) + " " + GetBuild(fileContent, false);
|
||||
}
|
||||
if (containsCheck && containsCheck2)
|
||||
return $"LaserLock {GetVersion(fileContent, position2)} {GetBuild(fileContent, true)} (Index {position}, {position2})";
|
||||
else if (containsCheck && !containsCheck2)
|
||||
return $"LaserLock Marathon {GetBuild(fileContent, false)} (Index {position})";
|
||||
else if (!containsCheck && containsCheck2)
|
||||
return $"LaserLock {GetVersion(fileContent, --position2)} {GetBuild(fileContent, false)} (Index {position2})";
|
||||
|
||||
if (file != null && Path.GetFileName(file) == "NOMOUSE.SP")
|
||||
return "LaserLock " + GetVersion16Bit(file);
|
||||
if (file != null && string.Equals(Path.GetFileName(file), "NOMOUSE.SP", StringComparison.OrdinalIgnoreCase))
|
||||
return $"LaserLock {GetVersion16Bit(fileContent)} (Index 71)";
|
||||
|
||||
if (fileContent.Contains(":\\LASERLOK\\LASERLOK.IN" + (char)0x00 + "C:\\NOMOUSE.SP"))
|
||||
return "LaserLock 3";
|
||||
// ":\\LASERLOK\\LASERLOK.IN" + (char)0x00 + "C:\\NOMOUSE.SP"
|
||||
check = new byte[] { 0x3A, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5C, 0x5C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x2E, 0x49, 0x4E, 0x00, 0x43, 0x3A, 0x5C, 0x5C, 0x4E, 0x4F, 0x4D, 0x4F, 0x55, 0x53, 0x45, 0x2E, 0x53, 0x50 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"LaserLock 3 (Index {position})";
|
||||
|
||||
if (fileContent.Contains("LASERLOK_INIT" + (char)0xC + "LASERLOK_RUN" + (char)0xE + "LASERLOK_CHECK"
|
||||
+ (char)0xF + "LASERLOK_CHECK2" + (char)0xF + "LASERLOK_CHECK3"))
|
||||
{
|
||||
return "LaserLock 5";
|
||||
}
|
||||
// "LASERLOK_INIT" + (char)0xC + "LASERLOK_RUN" + (char)0xE + "LASERLOK_CHECK" + (char)0xF + "LASERLOK_CHECK2" + (char)0xF + "LASERLOK_CHECK3"
|
||||
check = new byte[] { 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x49, 0x4E, 0x49, 0x54, 0x0C, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x52, 0x55, 0x4E, 0x0E, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x32, 0x0F, 0x4C, 0x41, 0x53, 0x45, 0x52, 0x4C, 0x4F, 0x4B, 0x5F, 0x43, 0x48, 0x45, 0x43, 0x4B, 0x33 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"LaserLock 5 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -65,6 +62,9 @@ namespace BurnOutSharp.ProtectionType
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path != null && string.Equals(Path.GetFileName(path), "NOMOUSE.SP", StringComparison.OrdinalIgnoreCase))
|
||||
return $"LaserLock {GetVersion16Bit(path)}";
|
||||
|
||||
if (Path.GetFileName(path).Equals("NOMOUSE.SP", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("NOMOUSE.COM", StringComparison.OrdinalIgnoreCase)
|
||||
|| Path.GetFileName(path).Equals("l16dll.dll", StringComparison.OrdinalIgnoreCase)
|
||||
@@ -79,30 +79,37 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetBuild(string fileContent, bool versionTwo)
|
||||
private static string GetBuild(byte[] fileContent, bool versionTwo)
|
||||
{
|
||||
// TODO: Is this supposed to be "Unknown"?
|
||||
int position = fileContent.IndexOf("Unkown" + (char)0 + "Unkown");
|
||||
// "Unkown" + (char)0x00 + "Unkown" // TODO: Is this supposed to be "Unknown"?
|
||||
byte[] check = new byte[] { 0x55, 0x6E, 0x6B, 0x6F, 0x77, 0x6E, 0x00, 0x55, 0x6E, 0x6B, 0x6F, 0x77, 0x6E };
|
||||
fileContent.Contains(check, out int position);
|
||||
string year, month, day;
|
||||
if (versionTwo)
|
||||
{
|
||||
day = fileContent.Substring(position + 14, 2);
|
||||
month = fileContent.Substring(position + 14 + 3, 2);
|
||||
year = "20" + fileContent.Substring(position + 14 + 6, 2);
|
||||
int index = position + 14;
|
||||
day = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
month = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
year = "20" + new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
day = fileContent.Substring(position + 13, 2);
|
||||
month = fileContent.Substring(position + 13 + 3, 2);
|
||||
year = "20" + fileContent.Substring(position + 13 + 6, 2);
|
||||
int index = position + 13;
|
||||
day = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
month = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
year = "20" + new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
}
|
||||
|
||||
return "(Build " + year + "-" + month + "-" + day + ")";
|
||||
return $"(Build {year}-{month}-{day})";
|
||||
}
|
||||
|
||||
private static string GetVersion(string FileContent, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
return FileContent.Substring(position + 76, 4);
|
||||
return new string(new ArraySegment<byte>(fileContent, position + 76, 4).Select(b => (char)b).ToArray());
|
||||
}
|
||||
|
||||
private static string GetVersion16Bit(string file)
|
||||
@@ -110,18 +117,17 @@ namespace BurnOutSharp.ProtectionType
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
char[] version = new char[3];
|
||||
br.BaseStream.Seek(71, SeekOrigin.Begin);
|
||||
version[0] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[1] = br.ReadChar();
|
||||
version[2] = br.ReadChar();
|
||||
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[1]) && char.IsNumber(version[2]))
|
||||
return version[0] + "." + version[1] + version[2];
|
||||
|
||||
return "";
|
||||
return GetVersion16Bit(br.ReadBytes((int)fs.Length));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetVersion16Bit(byte[] fileContent)
|
||||
{
|
||||
char[] version = new ArraySegment<byte>(fileContent, 71, 4).Select(b => (char)b).ToArray();
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
|
||||
return $"{version[0]}.{version[2]}{version[3]}";
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class PECompact
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("PEC2"))
|
||||
return "PE Compact 2";
|
||||
// "PEC2"
|
||||
byte[] check = new byte[] { 0x50, 0x45, 0x43, 0x32 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"PE Compact 2 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,14 +3,18 @@
|
||||
public class PSXAntiModchip
|
||||
{
|
||||
// TODO: Figure out PSX binary header so this can be checked explicitly
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
// TODO: Detect Red Hand protection
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
// TODO: Detect Red Hand protection
|
||||
if (fileContent.Contains(" SOFTWARE TERMINATED\nCONSOLE MAY HAVE BEEN MODIFIED\n CALL 1-888-780-7690"))
|
||||
return "PlayStation Anti-modchip (English)";
|
||||
// " SOFTWARE TERMINATED\nCONSOLE MAY HAVE BEEN MODIFIED\n CALL 1-888-780-7690"
|
||||
byte[] check = new byte[] { 0x20, 0x20, 0x20, 0x20, 0x20, 0x53, 0x4F, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x20, 0x54, 0x45, 0x52, 0x4D, 0x49, 0x4E, 0x41, 0x54, 0x45, 0x44, 0x5C, 0x6E, 0x43, 0x4F, 0x4E, 0x53, 0x4F, 0x4C, 0x45, 0x20, 0x4D, 0x41, 0x59, 0x20, 0x48, 0x41, 0x56, 0x45, 0x20, 0x42, 0x45, 0x45, 0x4E, 0x20, 0x4D, 0x4F, 0x44, 0x49, 0x46, 0x49, 0x45, 0x44, 0x5C, 0x6E, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x41, 0x4C, 0x4C, 0x20, 0x31, 0x2D, 0x38, 0x38, 0x38, 0x2D, 0x37, 0x38, 0x30, 0x2D, 0x37, 0x36, 0x39, 0x30 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"PlayStation Anti-modchip (English) (Index {position})";
|
||||
|
||||
if (fileContent.Contains("強制終了しました。\n本体が改造されている\nおそれがあります。"))
|
||||
return "PlayStation Anti-modchip (Japanese)";
|
||||
// "強制終了しました。\n本体が改造されている\nおそれがあります。"
|
||||
check = new byte[] { 0x5F, 0x37, 0x52, 0x36, 0x7D, 0x42, 0x4E, 0x86, 0x30, 0x57, 0x30, 0x7E, 0x30, 0x57, 0x30, 0x5F, 0x30, 0x02, 0x5C, 0x6E, 0x67, 0x2C, 0x4F, 0x53, 0x30, 0x4C, 0x65, 0x39, 0x90, 0x20, 0x30, 0x55, 0x30, 0x8C, 0x30, 0x66, 0x30, 0x44, 0x30, 0x8B, 0x5C, 0x6E, 0x30, 0x4A, 0x30, 0x5D, 0x30, 0x8C, 0x30, 0x4C, 0x30, 0x42, 0x30, 0x8A, 0x30, 0x7E, 0x30, 0x59, 0x30, 0x02 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"PlayStation Anti-modchip (Japanese) (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,164 +1,172 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class ProtectDisc
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("HúMETINF")) > -1)
|
||||
// "HúMETINF"
|
||||
byte[] check = new byte[] { 0x48, 0xFA, 0x4D, 0x45, 0x54, 0x49, 0x4E, 0x46 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
string version = EVORE.SearchProtectDiscVersion(file);
|
||||
string version = EVORE.SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
if (astrVersionArray[0] == "9")
|
||||
{
|
||||
if (GetVersionBuild76till10(file, position, out int ibuild).Length > 0)
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + astrVersionArray[2] + "." + astrVersionArray[3] + " (Build " + ibuild + ")";
|
||||
if (GetVersionBuild76till10(fileContent, position, out int ibuild).Length > 0)
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}{astrVersionArray[2]}.{astrVersionArray[3]} (Build {ibuild}) (Index {position})";
|
||||
}
|
||||
else
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + "." + astrVersionArray[2] + " (Build " + astrVersionArray[3] + ")";
|
||||
{
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]}) (Index {position})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((position = fileContent.IndexOf("ACE-PCD")) > -1)
|
||||
// "ACE-PCD"
|
||||
check = new byte[] { 0x41, 0x43, 0x45, 0x2D, 0x50, 0x43, 0x44 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = EVORE.SearchProtectDiscVersion(file);
|
||||
string version = EVORE.SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
{
|
||||
string[] astrVersionArray = version.Split('.');
|
||||
return "ProtectDisc " + astrVersionArray[0] + "." + astrVersionArray[1] + "." + astrVersionArray[2] + " (Build " + astrVersionArray[3] + ")";
|
||||
return $"ProtectDisc {astrVersionArray[0]}.{astrVersionArray[1]}.{astrVersionArray[2]} (Build {astrVersionArray[3]}) (Index {position})";
|
||||
}
|
||||
|
||||
return "ProtectDisc " + GetVersionBuild6till8(file, position);
|
||||
return $"ProtectDisc {GetVersionBuild6till8(fileContent, position)} (Index {position})";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersionBuild6till8(string file, int position)
|
||||
private static string GetVersionBuild6till8(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
string version;
|
||||
string strBuild;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
int index = position - 12;
|
||||
if (new ArraySegment<byte>(fileContent, index, 4).SequenceEqual(new byte[] { 0x0A, 0x0D, 0x0A, 0x0D })) // ProtectDisc 6-7 with Build Number in plain text
|
||||
{
|
||||
string version;
|
||||
string strBuild;
|
||||
index = position - 12 - 6;
|
||||
|
||||
br.BaseStream.Seek(position - 12, SeekOrigin.Begin);
|
||||
if (br.ReadByte() == 0xA && br.ReadByte() == 0xD && br.ReadByte() == 0xA && br.ReadByte() == 0xD) // ProtectDisc 6-7 with Build Number in plain text
|
||||
// ProtectDisc 7
|
||||
if (new string(new ArraySegment<byte>(fileContent, index, 6).Select(b => (char)b).ToArray()) == "Henrik")
|
||||
{
|
||||
br.BaseStream.Seek(position - 12 - 6, SeekOrigin.Begin);
|
||||
if (new string(br.ReadChars(6)) == "Henrik") // ProtectDisc 7
|
||||
{
|
||||
version = "7.1-7.5";
|
||||
br.BaseStream.Seek(position - 12 - 6 - 6, SeekOrigin.Begin);
|
||||
}
|
||||
else // ProtectDisc 6
|
||||
{
|
||||
version = "6";
|
||||
br.BaseStream.Seek(position - 12 - 10, SeekOrigin.Begin);
|
||||
while (true) //search for e.g. "Build 050913 - September 2005"
|
||||
{
|
||||
if (Char.IsNumber(br.ReadChar()))
|
||||
break;
|
||||
br.BaseStream.Seek(-2, SeekOrigin.Current); //search upwards
|
||||
}
|
||||
|
||||
br.BaseStream.Seek(-5, SeekOrigin.Current);
|
||||
}
|
||||
version = "7.1-7.5";
|
||||
index = position - 12 - 6 - 6;
|
||||
}
|
||||
|
||||
// ProtectDisc 6
|
||||
else
|
||||
{
|
||||
br.BaseStream.Seek(position + 28, SeekOrigin.Begin);
|
||||
if (br.ReadByte() == 0xFB)
|
||||
version = "6";
|
||||
index = position - 12 - 10;
|
||||
while (true) //search for e.g. "Build 050913 - September 2005"
|
||||
{
|
||||
return "7.6-7.x";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "8.0";
|
||||
if (Char.IsNumber((char)fileContent[index]))
|
||||
break;
|
||||
|
||||
index -= 1; //search upwards
|
||||
}
|
||||
|
||||
index -= 5;
|
||||
}
|
||||
strBuild = "" + br.ReadChar() + br.ReadChar() + br.ReadChar() + br.ReadChar() + br.ReadChar();
|
||||
return version + " (Build " + strBuild + ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
index = position + 28;
|
||||
if (fileContent[index] == 0xFB)
|
||||
return "7.6-7.x";
|
||||
else
|
||||
return "8.0";
|
||||
}
|
||||
|
||||
strBuild = new string(new ArraySegment<byte>(fileContent, index, 5).Select(b => (char)b).ToArray());
|
||||
return $"{version} (Build {strBuild})";
|
||||
}
|
||||
|
||||
private static string GetVersionBuild76till10(string file, int position, out int irefBuild)
|
||||
private static string GetVersionBuild76till10(byte[] fileContent, int position, out int irefBuild)
|
||||
{
|
||||
irefBuild = 0;
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position + 37;
|
||||
byte subversion = fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
byte version = fileContent[index];
|
||||
index = position + 49;
|
||||
irefBuild = BitConverter.ToInt32(fileContent, index);
|
||||
index = position + 53;
|
||||
byte versionindicatorPD9 = fileContent[index];
|
||||
index = position + 0x40;
|
||||
byte subsubversionPD9x = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x2 = fileContent[index];
|
||||
index++;
|
||||
byte subversionPD9x1 = fileContent[index];
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
// version 7
|
||||
if (version == 0xAC)
|
||||
return $"7.{subversion ^ 0x43} (Build {irefBuild})";
|
||||
|
||||
// version 8
|
||||
else if (version == 0xA2)
|
||||
{
|
||||
br.BaseStream.Seek(position + 37, SeekOrigin.Begin);
|
||||
byte subversion = br.ReadByte();
|
||||
br.ReadByte();
|
||||
byte version = br.ReadByte();
|
||||
br.BaseStream.Seek(position + 49, SeekOrigin.Begin);
|
||||
irefBuild = br.ReadInt32();
|
||||
br.BaseStream.Seek(position + 53, SeekOrigin.Begin);
|
||||
byte versionindicatorPD9 = br.ReadByte();
|
||||
br.BaseStream.Seek(position + 0x40, SeekOrigin.Begin);
|
||||
byte subsubversionPD9x = br.ReadByte();
|
||||
byte subversionPD9x2 = br.ReadByte();
|
||||
byte subversionPD9x1 = br.ReadByte();
|
||||
|
||||
// version 7
|
||||
if (version == 0xAC)
|
||||
return "7." + (subversion ^ 0x43) + " (Build " + irefBuild + ")";
|
||||
// version 8
|
||||
else if (version == 0xA2)
|
||||
if (subversion == 0x46)
|
||||
{
|
||||
if (subversion == 0x46)
|
||||
{
|
||||
if ((irefBuild & 0x3A00) == 0x3A00)
|
||||
return "8.2" + " (Build " + irefBuild + ")";
|
||||
else
|
||||
return "8.1" + " (Build " + irefBuild + ")";
|
||||
}
|
||||
return "8." + (subversion ^ 0x47) + " (Build " + irefBuild + ")";
|
||||
}
|
||||
// version 9
|
||||
else if (version == 0xA3)
|
||||
{
|
||||
// version removed or not given
|
||||
if ((subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61) || (subversionPD9x1 == 0 && subversionPD9x2 == 0))
|
||||
{
|
||||
if (versionindicatorPD9 == 0xB)
|
||||
return "9.0-9.4" + " (Build " + irefBuild + ")";
|
||||
else if (versionindicatorPD9 == 0xC)
|
||||
{
|
||||
if (subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61)
|
||||
return "9.5-9.11" + " (Build " + irefBuild + ")";
|
||||
else if (subversionPD9x1 == 0 && subversionPD9x2 == 0)
|
||||
return "9.11-9.20" + " (Build " + irefBuild + ")";
|
||||
}
|
||||
else
|
||||
return "9." + subversionPD9x1 + subversionPD9x2 + "." + subsubversionPD9x + " (Build " + irefBuild + ")";
|
||||
}
|
||||
}
|
||||
else if (version == 0xA0)
|
||||
{
|
||||
// version removed
|
||||
if (subversionPD9x1 != 0 || subversionPD9x2 != 0)
|
||||
return "10." + subversionPD9x1 + "." + subsubversionPD9x + " (Build " + irefBuild + ")";
|
||||
if ((irefBuild & 0x3A00) == 0x3A00)
|
||||
return $"8.2 (Build {irefBuild})";
|
||||
else
|
||||
return "10.x (Build " + irefBuild + ")";
|
||||
return $"8.1 (Build {irefBuild})";
|
||||
}
|
||||
else
|
||||
return "7.6-10.x (Build " + irefBuild + ")";
|
||||
|
||||
return "";
|
||||
return $"8.{subversion ^ 0x47} (Build {irefBuild})";
|
||||
}
|
||||
|
||||
// version 9
|
||||
else if (version == 0xA3)
|
||||
{
|
||||
// version removed or not given
|
||||
if ((subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61) || (subversionPD9x1 == 0 && subversionPD9x2 == 0))
|
||||
{
|
||||
if (versionindicatorPD9 == 0xB)
|
||||
{
|
||||
return $"9.0-9.4 (Build {irefBuild})";
|
||||
}
|
||||
else if (versionindicatorPD9 == 0xC)
|
||||
{
|
||||
if (subversionPD9x2 == 0x5F && subversionPD9x1 == 0x61)
|
||||
return $"9.5-9.11 (Build {irefBuild})";
|
||||
else if (subversionPD9x1 == 0 && subversionPD9x2 == 0)
|
||||
return $"9.11-9.20 (Build {irefBuild})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return $"9.{subversionPD9x1}{subversionPD9x2}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// version 10
|
||||
else if (version == 0xA0)
|
||||
{
|
||||
// version removed
|
||||
if (subversionPD9x1 != 0 || subversionPD9x2 != 0)
|
||||
return $"10.{subversionPD9x1}.{subsubversionPD9x} (Build {irefBuild})";
|
||||
else
|
||||
return $"10.x (Build {irefBuild})";
|
||||
}
|
||||
|
||||
// unknown version
|
||||
else
|
||||
{
|
||||
return $"7.6-10.x (Build {irefBuild})";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class RingPROTECH
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains((char)0x00 + "Allocator" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00))
|
||||
return "Ring PROTECH";
|
||||
// (char)0x00 + "Allocator" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
byte[] check = new byte[] { 0x00, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x6F, 0x72, 0x00, 0x00, 0x00, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Ring PROTECH (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class SVKProtector
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("?SVKP" + (char)0x00 + (char)0x00))
|
||||
return "SVK Protector";
|
||||
// "?SVKP" + (char)0x00 + (char)0x00
|
||||
byte[] check = new byte[] { 0x3F, 0x53, 0x56, 0x4B, 0x50, 0x00, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"SVK Protector (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,26 +7,51 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class SafeDisc
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("BoG_ *90.0&!! Yy>")) > -1)
|
||||
// "BoG_ *90.0&!! Yy>"
|
||||
byte[] check = new byte[] { 0x42, 0x6F, 0x47, 0x5F, 0x20, 0x2A, 0x39, 0x30, 0x2E, 0x30, 0x26, 0x21, 0x21, 0x20, 0x20, 0x59, 0x79, 0x3E };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
if (fileContent.IndexOf("product activation library") > 0)
|
||||
return "SafeCast " + GetVersion(file, position);
|
||||
// "product activation library"
|
||||
byte[] check2 = new byte[] { 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x6C, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79 };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
return $"SafeCast {GetVersion(fileContent, position)} (Index {position}, {position2})";
|
||||
else
|
||||
return "SafeDisc " + GetVersion(file, position);
|
||||
return $"SafeDisc {GetVersion(fileContent, position)} (Index {position})";
|
||||
}
|
||||
|
||||
if (fileContent.Contains((char)0x00 + (char)0x00 + "BoG_")
|
||||
|| fileContent.Contains("stxt774")
|
||||
|| fileContent.Contains("stxt371"))
|
||||
// (char)0x00 + (char)0x00 + "BoG_"
|
||||
check = new byte[] { 0x00, 0x00, 0x42, 0x6F, 0x47, 0x5F };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = EVORE.SearchSafeDiscVersion(file);
|
||||
string version = EVORE.SearchSafeDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
return "SafeDisc " + version;
|
||||
return $"SafeDisc {version} (Index {position})";
|
||||
|
||||
return "SafeDisc 3.20-4.xx (version removed)";
|
||||
return $"SafeDisc 3.20-4.xx (version removed) (Index {position})";
|
||||
}
|
||||
|
||||
// "stxt774"
|
||||
check = new byte[] { 0x73, 0x74, 0x78, 0x74, 0x37, 0x37, 0x34 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = EVORE.SearchSafeDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
return $"SafeDisc {version} (Index {position})";
|
||||
|
||||
return $"SafeDisc 3.20-4.xx (version removed) (Index {position})";
|
||||
}
|
||||
|
||||
// "stxt371"
|
||||
check = new byte[] { 0x73, 0x74, 0x78, 0x74, 0x33, 0x37, 0x31 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = EVORE.SearchSafeDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
return $"SafeDisc {version} (Index {position})";
|
||||
|
||||
return $"SafeDisc 3.20-4.xx (version removed) (Index {position})";
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -192,32 +217,29 @@ namespace BurnOutSharp.ProtectionType
|
||||
return "SafeDisc 2 or greater";
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position + 20; // Begin reading after "BoG_ *90.0&!! Yy>" for old SafeDisc
|
||||
int version = BitConverter.ToInt32(fileContent, index);
|
||||
index += 4;
|
||||
int subVersion = BitConverter.ToInt32(fileContent, index);
|
||||
index += 4;
|
||||
int subsubVersion = BitConverter.ToInt32(fileContent, index);
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 20, SeekOrigin.Begin); // Begin reading after "BoG_ *90.0&!! Yy>" for old SafeDisc
|
||||
int version = br.ReadInt32();
|
||||
int subVersion = br.ReadInt32();
|
||||
int subsubVersion = br.ReadInt32();
|
||||
if (version != 0)
|
||||
return $"{version}.{subVersion:00}.{subsubVersion:000}";
|
||||
|
||||
if (version != 0)
|
||||
return version + "." + subVersion.ToString("00") + "." + subsubVersion.ToString("000");
|
||||
index = position + 18 + 14; // Begin reading after "BoG_ *90.0&!! Yy>" for newer SafeDisc
|
||||
version = BitConverter.ToInt32(fileContent, index);
|
||||
index += 4;
|
||||
subVersion = BitConverter.ToInt32(fileContent, index);
|
||||
index += 4;
|
||||
subsubVersion = BitConverter.ToInt32(fileContent, index);
|
||||
|
||||
br.BaseStream.Seek(position + 18 + 14, SeekOrigin.Begin); // Begin reading after "BoG_ *90.0&!! Yy>" for newer SafeDisc
|
||||
version = br.ReadInt32();
|
||||
subVersion = br.ReadInt32();
|
||||
subsubVersion = br.ReadInt32();
|
||||
if (version == 0)
|
||||
return "";
|
||||
|
||||
if (version == 0)
|
||||
return "";
|
||||
|
||||
return version + "." + subVersion.ToString("00") + "." + subsubVersion.ToString("000");
|
||||
}
|
||||
return $"{version}.{subVersion:00}.{subsubVersion:000}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class SafeLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("SafeLock"))
|
||||
return "SafeLock";
|
||||
// "SafeLock"
|
||||
byte[] check = new byte[] { 0x53, 0x61, 0x66, 0x65, 0x4C, 0x6F, 0x63, 0x6B };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"SafeLock (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,32 +7,42 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class SecuROM
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("AddD" + (char)0x03 + (char)0x00 + (char)0x00 + (char)0x00)) > -1)
|
||||
return "SecuROM " + GetV4Version(file, position);
|
||||
// "AddD" + (char)0x03 + (char)0x00 + (char)0x00 + (char)0x00)
|
||||
byte[] check = new byte[] { 0x41, 0x64, 0x64, 0x44, 0x03, 0x00, 0x00, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"SecuROM {GetV4Version(fileContent, position)} (Index {position})";
|
||||
|
||||
if ((position = fileContent.IndexOf("" + (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03)) > -1)
|
||||
return "SecuROM " + GetV5Version(file, position);
|
||||
// (char)0xCA + (char)0xDD + (char)0xDD + (char)0xAC + (char)0x03
|
||||
check = new byte[] { 0xCA, 0xDD, 0xDD, 0xAC, 0x03 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SecuROM {GetV5Version(fileContent, position)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains(".securom")
|
||||
|| fileContent.StartsWith(".securom" + (char)0xE0 + (char)0xC0))
|
||||
{
|
||||
return "SecuROM " + GetV7Version(file);
|
||||
}
|
||||
// ".securom" + (char)0xE0 + (char)0xC0
|
||||
check = new byte[] { 0x2E, 0x73, 0x65, 0x63, 0x75, 0x72, 0x6F, 0x6D, 0xE0, 0xC0 };
|
||||
if (fileContent.Contains(check, out position) && position == 0)
|
||||
return $"SecuROM {GetV7Version(fileContent)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains("_and_play.dll" + (char)0x00 + "drm_pagui_doit"))
|
||||
return "SecuROM Product Activation " + Utilities.GetFileVersion(file);
|
||||
// ".securom"
|
||||
check = new byte[] { 0x2E, 0x73, 0x65, 0x63, 0x75, 0x72, 0x6F, 0x6D };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SecuROM {GetV7Version(fileContent)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains("_and_play.dll" + (char)0x00 + "drm_pagui_doit"))
|
||||
return "SecuROM Product Activation " + Utilities.GetFileVersion(file);
|
||||
// "_and_play.dll" + (char)0x00 + "drm_pagui_doit"
|
||||
check = new byte[] { 0x5F, 0x61, 0x6E, 0x64, 0x5F, 0x70, 0x6C, 0x61, 0x79, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x64, 0x72, 0x6D, 0x5F, 0x70, 0x61, 0x67, 0x75, 0x69, 0x5F, 0x64, 0x6F, 0x69, 0x74 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SecuROM Product Activation {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains(".cms_t" + (char)0x00)
|
||||
|| fileContent.Contains(".cms_d" + (char)0x00))
|
||||
{
|
||||
return "SecuROM 1-3";
|
||||
}
|
||||
// ".cms_t" + (char)0x00
|
||||
check = new byte[] { 0x2E, 0x63, 0x6D, 0x73, 0x5F, 0x74, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SecuROM 1-3 (Index {position})";
|
||||
|
||||
// ".cms_d" + (char)0x00
|
||||
check = new byte[] { 0x2E, 0x63, 0x6D, 0x73, 0x5F, 0x64, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SecuROM 1-3 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -78,84 +88,76 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetV4Version(string file, int position)
|
||||
private static string GetV4Version(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position + 8; // Begin reading after "AddD"
|
||||
char version = (char)fileContent[index];
|
||||
index += 2;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 8, SeekOrigin.Begin); // Begin reading after "AddD"
|
||||
char version = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subVersion1 = br.ReadChar();
|
||||
char subVersion2 = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subsubVersion1 = br.ReadChar();
|
||||
char subsubVersion2 = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subsubsubVersion1 = br.ReadChar();
|
||||
char subsubsubVersion2 = br.ReadChar();
|
||||
char subsubsubVersion3 = br.ReadChar();
|
||||
char subsubsubVersion4 = br.ReadChar();
|
||||
string subVersion = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
|
||||
return version + "." + subVersion1 + subVersion2 + "." + subsubVersion1 + subsubVersion2 + "." + subsubsubVersion1 + subsubsubVersion2 + subsubsubVersion3 + subsubsubVersion4;
|
||||
}
|
||||
string subSubVersion = new string(new ArraySegment<byte>(fileContent, index, 2).Select(b => (char)b).ToArray());
|
||||
index += 3;
|
||||
|
||||
string subSubSubVersion = new string(new ArraySegment<byte>(fileContent, index, 4).Select(b => (char)b).ToArray());
|
||||
|
||||
if (!char.IsNumber(version))
|
||||
return "(very old, v3 or less)";
|
||||
|
||||
return $"{version}.{subVersion}.{subSubVersion}.{subSubSubVersion}";
|
||||
}
|
||||
|
||||
private static string GetV5Version(string file, int position)
|
||||
private static string GetV5Version(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position + 8; // Begin reading after "ÊÝݬ"
|
||||
byte version = (byte)(fileContent[index] & 0x0F);
|
||||
index += 2;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 8, SeekOrigin.Begin); // Begin reading after "ÊÝݬ"
|
||||
byte version = (byte)(br.ReadByte() & 0xF);
|
||||
br.ReadByte();
|
||||
byte subVersion1 = (byte)(br.ReadByte() ^ 36);
|
||||
byte subVersion2 = (byte)(br.ReadByte() ^ 28);
|
||||
br.ReadByte();
|
||||
byte subsubVersion1 = (byte)(br.ReadByte() ^ 42);
|
||||
byte subsubVersion2 = (byte)(br.ReadByte() ^ 8);
|
||||
br.ReadByte();
|
||||
byte subsubsubVersion1 = (byte)(br.ReadByte() ^ 16);
|
||||
byte subsubsubVersion2 = (byte)(br.ReadByte() ^ 116);
|
||||
byte subsubsubVersion3 = (byte)(br.ReadByte() ^ 34);
|
||||
byte subsubsubVersion4 = (byte)(br.ReadByte() ^ 22);
|
||||
byte[] subVersion = new byte[2];
|
||||
subVersion[0] = (byte)(fileContent[index] ^ 36);
|
||||
index++;
|
||||
subVersion[1] = (byte)(fileContent[index] ^ 28);
|
||||
index += 2;
|
||||
|
||||
if (version == 0 || version > 9)
|
||||
return "";
|
||||
byte[] subSubVersion = new byte[2];
|
||||
subSubVersion[0] = (byte)(fileContent[index] ^ 42);
|
||||
index++;
|
||||
subSubVersion[0] = (byte)(fileContent[index] ^ 8);
|
||||
index += 2;
|
||||
|
||||
return version + "." + subVersion1 + subVersion2 + "." + subsubVersion1 + subsubVersion2 + "." + subsubsubVersion1 + subsubsubVersion2 + subsubsubVersion3 + subsubsubVersion4;
|
||||
}
|
||||
byte[] subSubSubVersion = new byte[4];
|
||||
subSubSubVersion[0] = (byte)(fileContent[index] ^ 16);
|
||||
index++;
|
||||
subSubSubVersion[1] = (byte)(fileContent[index] ^ 116);
|
||||
index++;
|
||||
subSubSubVersion[2] = (byte)(fileContent[index] ^ 34);
|
||||
index++;
|
||||
subSubSubVersion[3] = (byte)(fileContent[index] ^ 22);
|
||||
|
||||
if (version == 0 || version > 9)
|
||||
return "";
|
||||
|
||||
return $"{version}.{subVersion[0]}{subVersion[1]}.{subSubVersion[0]}{subSubVersion[1]}.{subSubSubVersion[0]}{subSubSubVersion[1]}{subSubSubVersion[2]}{subSubSubVersion[3]}";
|
||||
}
|
||||
|
||||
private static string GetV7Version(string file)
|
||||
private static string GetV7Version(byte[] fileContent)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
int index = 236;
|
||||
byte[] bytes = new ArraySegment<byte>(fileContent, index, 4).ToArray();
|
||||
|
||||
//SecuROM 7 new and 8
|
||||
if (bytes[3] == 0x5C) // if (bytes[0] == 0xED && bytes[3] == 0x5C {
|
||||
{
|
||||
br.BaseStream.Seek(236, SeekOrigin.Begin);
|
||||
byte[] bytes = br.ReadBytes(4);
|
||||
// if (bytes[0] == 0xED && bytes[3] == 0x5C {
|
||||
if (bytes[3] == 0x5C)
|
||||
{
|
||||
//SecuROM 7 new and 8
|
||||
return (bytes[0] ^ 0xEA).ToString() + "." + (bytes[1] ^ 0x2C).ToString("00") + "." + (bytes[2] ^ 0x8).ToString("0000");
|
||||
}
|
||||
else // SecuROM 7 old
|
||||
{
|
||||
br.BaseStream.Seek(122, SeekOrigin.Begin);
|
||||
bytes = br.ReadBytes(2);
|
||||
return "7." + (bytes[0] ^ 0x10).ToString("00") + "." + (bytes[1] ^ 0x10).ToString("0000");
|
||||
//return "7.01-7.10"
|
||||
}
|
||||
return $"{bytes[0] ^ 0xEA}.{bytes[1] ^ 0x2C:00}.{bytes[2] ^ 0x8:0000}";
|
||||
}
|
||||
|
||||
// SecuROM 7 old
|
||||
else
|
||||
{
|
||||
index = 122;
|
||||
bytes = new ArraySegment<byte>(fileContent, index, 2).ToArray();
|
||||
return $"7.{bytes[0] ^ 0x10:00}.{bytes[1] ^ 0x10:0000}"; //return "7.01-7.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class SmartE
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("BITARTS"))
|
||||
return "SmartE";
|
||||
// "BITARTS"
|
||||
byte[] check = new byte[] { 0x42, 0x49, 0x54, 0x41, 0x52, 0x54, 0x53 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"SmartE (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -8,96 +8,101 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class SolidShield
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains("D" + (char)0x00 + "V" + (char)0x00 + "M" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00
|
||||
+ "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y"))
|
||||
{
|
||||
return "SolidShield " + Utilities.GetFileVersion(file);
|
||||
}
|
||||
// "D" + (char)0x00 + "V" + (char)0x00 + "M" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y"
|
||||
byte[] check = new byte[] { 0x44, 0x00, 0x56, 0x00, 0x4D, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"SolidShield {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains("S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00
|
||||
+ "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (char)0x00
|
||||
+ " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00
|
||||
+ "r" + (char)0x00 + "y")
|
||||
|| fileContent.Contains("S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00
|
||||
+ "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (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 + " " + (char)0x00
|
||||
+ "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y"))
|
||||
// "S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00 + "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y"
|
||||
check = new byte[] { 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string companyName = string.Empty;
|
||||
if (file != null)
|
||||
companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower();
|
||||
|
||||
if (companyName.Contains("solidshield") || companyName.Contains("tages"))
|
||||
return "SolidShield Core.dll " + Utilities.GetFileVersion(file);
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
}
|
||||
|
||||
if ((position = fileContent.IndexOf("" + (char)0xEF + (char)0xBE + (char)0xAD + (char)0xDE)) > -1)
|
||||
{
|
||||
var id1 = fileContent.Substring(position + 5, 3);
|
||||
var id2 = fileContent.Substring(position + 16, 4);
|
||||
|
||||
if (id1 == "" + (char)0x00 + (char)0x00 + (char)0x00 && id2 == "" + (char)0x00 + (char)0x10 + (char)0x00 + (char)0x00)
|
||||
return "SolidShield 1 (SolidShield EXE Wrapper)";
|
||||
else if (id1 == ".o&" && id2 == "ÛÅ›¹")
|
||||
return "SolidShield 2 (SolidShield v2 EXE Wrapper)"; // TODO: Verify against other SolidShield 2 discs
|
||||
}
|
||||
|
||||
if (fileContent.Contains("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 + " " + (char)0x00
|
||||
+ "M" + (char)0x00 + "a" + (char)0x00 + "n" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "r"))
|
||||
// "S" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "i" + (char)0x00 + "d" + (char)0x00 + "s" + (char)0x00 + "h" + (char)0x00 + "i" + (char)0x00 + "e" + (char)0x00 + "l" + (char)0x00 + "d" + (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 + " " + (char)0x00 + "L" + (char)0x00 + "i" + (char)0x00 + "b" + (char)0x00 + "r" + (char)0x00 + "a" + (char)0x00 + "r" + (char)0x00 + "y"
|
||||
check = new byte[] { 0x53, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x64, 0x00, 0x73, 0x00, 0x68, 0x00, 0x69, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x64, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x69, 0x00, 0x62, 0x00, 0x72, 0x00, 0x61, 0x00, 0x72, 0x00, 0x79 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string companyName = string.Empty;
|
||||
if (file != null)
|
||||
companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower();
|
||||
|
||||
if (companyName.Contains("solidshield") || companyName.Contains("tages"))
|
||||
return "SolidShield Activation Manager Module " + Utilities.GetFileVersion(file);
|
||||
return $"SolidShield Core.dll {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
}
|
||||
|
||||
if ((position = fileContent.IndexOf("" + (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA)) > -1)
|
||||
// (char)0xEF + (char)0xBE + (char)0xAD + (char)0xDE
|
||||
check = new byte[] { };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
if ((fileContent[position + 3] == (char)0x04 || fileContent[position + 3] == (char)0x05)
|
||||
&& fileContent.Substring(position + 4, 3) == "" + (char)0x00 + (char)0x00 + (char)0x00
|
||||
&& fileContent.Substring(position + 15, 4) == "" + (char)0x00 + (char)0x10 + (char)0x00 + (char)0x00)
|
||||
var id1 = new ArraySegment<byte>(fileContent, position + 5, 3);
|
||||
var id2 = new ArraySegment<byte>(fileContent, position + 16, 4);
|
||||
|
||||
if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 }) && id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 }))
|
||||
return $"SolidShield 1 (SolidShield EXE Wrapper) (Index {position})";
|
||||
else if (id1.SequenceEqual(new byte[] { 0x2E, 0x6F, 0x26 }) && id2.SequenceEqual(new byte[] { 0xDB, 0xC5, 0x20, 0x3A, 0xB9 }))
|
||||
return $"SolidShield 2 (SolidShield v2 EXE Wrapper) (Index {position})"; // TODO: Verify against other SolidShield 2 discs
|
||||
}
|
||||
|
||||
// "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 + " " + (char)0x00 + "M" + (char)0x00 + "a" + (char)0x00 + "n" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "r"
|
||||
check = new byte[] { 0x41, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x76, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string companyName = string.Empty;
|
||||
if (file != null)
|
||||
companyName = FileVersionInfo.GetVersionInfo(file).CompanyName.ToLower();
|
||||
|
||||
if (companyName.Contains("solidshield") || companyName.Contains("tages"))
|
||||
return $"SolidShield Activation Manager Module {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
}
|
||||
|
||||
// (char)0xAD + (char)0xDE + (char)0xFE + (char)0xCA
|
||||
check = new byte[] { 0xAD, 0xDE, 0xFE, 0xCA };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
var id1 = new ArraySegment<byte>(fileContent, position + 4, 3);
|
||||
var id2 = new ArraySegment<byte>(fileContent, position + 15, 4);
|
||||
|
||||
if ((fileContent[position + 3] == 0x04 || fileContent[position + 3] == 0x05)
|
||||
&& id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 })
|
||||
&& id2.SequenceEqual(new byte[] { 0x00, 0x10, 0x00, 0x00 }))
|
||||
{
|
||||
return "SolidShield 2 (SolidShield v2 EXE Wrapper)";
|
||||
return $"SolidShield 2 (SolidShield v2 EXE Wrapper) (Index {position})";
|
||||
}
|
||||
else if (fileContent.Substring(position + 4, 3) == "" + (char)0x00 + (char)0x00 + (char)0x00
|
||||
&& fileContent.Substring(position + 15, 4) == "" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00)
|
||||
else if (id1.SequenceEqual(new byte[] { 0x00, 0x00, 0x00 })
|
||||
&& id2.SequenceEqual(new byte[] { 0x00, 0x00, 0x00, 0x00 }))
|
||||
{
|
||||
position = fileContent.IndexOf("T" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "s"
|
||||
+ (char)0x00 + "S" + (char)0x00 + "e" + (char)0x00 + "t" + (char)0x00 + "u" + (char)0x00 + "p"
|
||||
+ (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "0" + (char)0x00 + (char)0x8
|
||||
+ (char)0x00 + (char)0x1 + (char)0x0 + "F" + (char)0x00 + "i" + (char)0x00 + "l" + (char)0x00 + "e"
|
||||
+ (char)0x00 + "V" + (char)0x00 + "e" + (char)0x00 + "r" + (char)0x00 + "s" + (char)0x00 + "i" + (char)0x00
|
||||
+ "o" + (char)0x00 + "n" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00);
|
||||
if (position > -1)
|
||||
// "T" + (char)0x00 + "a" + (char)0x00 + "g" + (char)0x00 + "e" + (char)0x00 + "s" + (char)0x00 + "S" + (char)0x00 + "e" + (char)0x00 + "t" + (char)0x00 + "u" + (char)0x00 + "p" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00 + "0" + (char)0x00 + (char)0x8 + (char)0x00 + (char)0x1 + (char)0x0 + "F" + (char)0x00 + "i" + (char)0x00 + "l" + (char)0x00 + "e" + (char)0x00 + "V" + (char)0x00 + "e" + (char)0x00 + "r" + (char)0x00 + "s" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0x00
|
||||
byte[] check2 = new byte[] { 0x54, 0x61, 0x67, 0x65, 0x73, 0x53, 0x65, 0x74, 0x75, 0x70, 0x30, 0x08, 0x01, 0x00, 0x46, 0x69, 0x6C, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x00, 0x00, 0x00 };
|
||||
if (fileContent.Contains(check2, out int position2))
|
||||
{
|
||||
position--; // TODO: Verify this subtract
|
||||
return "SolidShield 2 + Tagès " + fileContent.Substring(position + 0x38, 1) + "." + fileContent.Substring(position + 0x38 + 4, 1) + "." + fileContent.Substring(position + 0x38 + 8, 1) + "." + fileContent.Substring(position + 0x38 + 12, 1);
|
||||
position2--; // TODO: Verify this subtract
|
||||
return $"SolidShield 2 + Tagès {fileContent[position2 + 0x38]}.{fileContent[position2 + 0x38 + 4]}.{fileContent[position2 + 0x38 + 8]}.{fileContent[position + 0x38 + 12]} (Index {position}, {position2})";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "SolidShield 2 (SolidShield v2 EXE Wrapper)";
|
||||
return $"SolidShield 2 (SolidShield v2 EXE Wrapper) (Index {position})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((position = fileContent.IndexOf("Solidshield")) > 0)
|
||||
{
|
||||
return "SolidShield " + GetVersion(file, position);
|
||||
}
|
||||
// "Solidshield"
|
||||
check = new byte[] { 0x53, 0x6F, 0x6C, 0x69, 0x64, 0x73, 0x68, 0x69, 0x65, 0x6C, 0x64 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SolidShield {GetVersion(fileContent, position)} (Index {position})";
|
||||
|
||||
if (fileContent.Contains("B" + (char)0x00 + "I" + (char)0x00 + "N" + (char)0x00 + (char)0x7 + (char)0x00 +
|
||||
"I" + (char)0x00 + "D" + (char)0x00 + "R" + (char)0x00 + "_" + (char)0x00 +
|
||||
"S" + (char)0x00 + "G" + (char)0x00 + "T" + (char)0x0))
|
||||
{
|
||||
return "SolidShield";
|
||||
}
|
||||
// "B" + (char)0x00 + "I" + (char)0x00 + "N" + (char)0x00 + (char)0x7 + (char)0x00 + "I" + (char)0x00 + "D" + (char)0x00 + "R" + (char)0x00 + "_" + (char)0x00 + "S" + (char)0x00 + "G" + (char)0x00 + "T" + (char)0x0
|
||||
check = new byte[] { 0x42, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x07, 0x00, 0x49, 0x00, 0x44, 0x00, 0x52, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x47, 0x00, 0x54, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"SolidShield (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -129,24 +134,21 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position + 12, SeekOrigin.Begin); // Begin reading after "Solidshield"
|
||||
char version = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subVersion = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subsubVersion = br.ReadChar();
|
||||
br.ReadByte();
|
||||
char subsubsubVersion = br.ReadChar();
|
||||
return version + "." + subVersion + "." + subsubVersion + "." + subsubsubVersion;
|
||||
}
|
||||
int index = position + 12; // Begin reading after "Solidshield"
|
||||
char version = (char)fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
char subVersion = (char)fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
char subSubVersion = (char)fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
char subSubSubVersion = (char)fileContent[index];
|
||||
|
||||
return $"{version}.{subVersion}.{subSubVersion}.{subSubSubVersion}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,37 +7,58 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class StarForce
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains("(" + (char)0x00 + "c" + (char)0x00 + ")" + (char)0x00 + " " + (char)0x00 + "P" + (char)0x00
|
||||
+ "r" + (char)0x00 + "o" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00
|
||||
+ "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + " " + (char)0x00 + "T" + (char)0x00 + "e" + (char)0x00
|
||||
+ "c" + (char)0x00 + "h" + (char)0x00 + "n" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "o" + (char)0x00
|
||||
+ "g" + (char)0x00 + "y" + (char)0x00)
|
||||
|| fileContent.Contains("Protection Technology, Ltd."))
|
||||
// "(" + (char)0x00 + "c" + (char)0x00 + ")" + (char)0x00 + " " + (char)0x00 + "P" + (char)0x00 + "r" + (char)0x00 + "o" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00 + "i" + (char)0x00 + "o" + (char)0x00 + "n" + (char)0x00 + " " + (char)0x00 + "T" + (char)0x00 + "e" + (char)0x00 + "c" + (char)0x00 + "h" + (char)0x00 + "n" + (char)0x00 + "o" + (char)0x00 + "l" + (char)0x00 + "o" + (char)0x00 + "g" + (char)0x00 + "y" + (char)0x00
|
||||
byte[] check = new byte[] { 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x63, 0x00, 0x68, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x79, 0x00 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
{
|
||||
//if (FileContent.Contains("PSA_GetDiscLabel")
|
||||
//if (FileContent.Contains("(c) Protection Technology")
|
||||
position = fileContent.IndexOf("TradeName") - 1;
|
||||
if (position != -1 && position != -2)
|
||||
return "StarForce " + Utilities.GetFileVersion(file) + " (" + fileContent.Substring(position + 22, 30).Split((char)0x00)[0] + ")";
|
||||
// "PSA_GetDiscLabel"
|
||||
// byte[] check2 = new byte[] { 0x50, 0x53, 0x41, 0x5F, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x4C, 0x61, 0x62, 0x65, 0x6C };
|
||||
|
||||
// "(c) Protection Technology"
|
||||
// byte[] check2 = new byte[] { 0x28, 0x63, 0x29, 0x20, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x79 };
|
||||
|
||||
// "TradeName"
|
||||
byte[] check2 = new byte[] { 0x54, 0x72, 0x61, 0x64, 0x65, 0x4E, 0x61, 0x6D, 0x65 };
|
||||
if (fileContent.Contains(check2, out int position2) && position2 != 0)
|
||||
return $"StarForce {Utilities.GetFileVersion(file)} ({fileContent.Skip(position2 + 22).TakeWhile(c => c != 0x00)}) (Index {position}, {position2})";
|
||||
else
|
||||
return "StarForce " + Utilities.GetFileVersion(file);
|
||||
return $"StarForce {Utilities.GetFileVersion(file)} (Index {position}, {position2})";
|
||||
}
|
||||
|
||||
if (fileContent.Contains(".sforce")
|
||||
|| fileContent.Contains(".brick"))
|
||||
// "Protection Technology, Ltd."
|
||||
check = new byte[] { 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x79, 0x2C, 0x20, 0x4C, 0x74, 0x64, 0x2E };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
return "StarForce 3-5";
|
||||
// "PSA_GetDiscLabel"
|
||||
// byte[] check2 = new byte[] { 0x50, 0x53, 0x41, 0x5F, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x4C, 0x61, 0x62, 0x65, 0x6C };
|
||||
|
||||
// "(c) Protection Technology"
|
||||
// byte[] check2 = new byte[] { 0x28, 0x63, 0x29, 0x20, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6E, 0x6F, 0x6C, 0x6F, 0x67, 0x79 };
|
||||
|
||||
// "TradeName"
|
||||
byte[] check2 = new byte[] { 0x54, 0x72, 0x61, 0x64, 0x65, 0x4E, 0x61, 0x6D, 0x65 };
|
||||
if (fileContent.Contains(check2, out int position2) && position2 != 0)
|
||||
return $"StarForce {Utilities.GetFileVersion(file)} ({fileContent.Skip(position2 + 22).TakeWhile(c => c != 0x00)}) (Index {position}, {position2})";
|
||||
else
|
||||
return $"StarForce {Utilities.GetFileVersion(file)} (Index {position}, {position2})";
|
||||
}
|
||||
|
||||
if (fileContent.Contains("P" + (char)0x00 + "r" + (char)0x00 + "o" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00
|
||||
+ "c" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "M" + (char)0x00
|
||||
+ "o" + (char)0x00 + "d" + (char)0x00 + "u" + (char)0x00 + "l" + (char)0x00 + "e"))
|
||||
{
|
||||
return "StarForce 5";
|
||||
}
|
||||
// ".sforce"
|
||||
check = new byte[] { 0x2E, 0x73, 0x66, 0x6F, 0x72, 0x63, 0x65 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"StarForce 3-5 (Index {position})";
|
||||
|
||||
// ".brick"
|
||||
check = new byte[] { 0x2E, 0x62, 0x72, 0x69, 0x63, 0x6B };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"StarForce 3-5 (Index {position})";
|
||||
|
||||
// "P" + (char)0x00 + "r" + (char)0x00 + "o" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "c" + (char)0x00 + "t" + (char)0x00 + "e" + (char)0x00 + "d" + (char)0x00 + " " + (char)0x00 + "M" + (char)0x00 + "o" + (char)0x00 + "d" + (char)0x00 + "u" + (char)0x00 + "l" + (char)0x00 + "e"
|
||||
check = new byte[] { 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x74, 0x00, 0x65, 0x00, 0x63, 0x00, 0x74, 0x00, 0x65, 0x00, 0x64, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x6c, 0x00, 0x65 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"StarForce 5 (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,39 +1,34 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class Sysiphus
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("V SUHPISYSDVD")) > -1)
|
||||
return "Sysiphus DVD " + GetVersion(file, position);
|
||||
// "V SUHPISYSDVD"
|
||||
byte[] check = new byte[] { 0x56, 0x20, 0x53, 0x55, 0x48, 0x50, 0x49, 0x53, 0x59, 0x53, 0x44, 0x56, 0x44 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Sysiphus DVD {GetVersion(fileContent, position)} (Index {position})";
|
||||
|
||||
if ((position = fileContent.IndexOf("V SUHPISYS")) > -1)
|
||||
return "Sysiphus " + GetVersion(file, position);
|
||||
// "V SUHPISYS"
|
||||
check = new byte[] { 0x56, 0x20, 0x53, 0x55, 0x48, 0x50, 0x49, 0x53, 0x59, 0x53 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"Sysiphus {GetVersion(fileContent, position)} (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
int index = position - 3;
|
||||
char subVersion = (char)fileContent[index];
|
||||
index++;
|
||||
index++;
|
||||
char version = (char)fileContent[index];
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position - 3, SeekOrigin.Begin);
|
||||
char subVersion = br.ReadChar();
|
||||
br.ReadChar();
|
||||
char version = br.ReadChar();
|
||||
|
||||
if (char.IsNumber(version) && char.IsNumber(subVersion))
|
||||
return version + "." + subVersion;
|
||||
else
|
||||
return "";
|
||||
}
|
||||
if (char.IsNumber(version) && char.IsNumber(subVersion))
|
||||
return $"{version}.{subVersion}";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,26 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class Tages
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if (fileContent.Contains("protected-tages-runtime.exe") ||
|
||||
fileContent.Contains("tagesprotection.com"))
|
||||
return "TAGES " + Utilities.GetFileVersion(file);
|
||||
// "protected-tages-runtime.exe"
|
||||
byte[] check = new byte[] { 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2D, 0x74, 0x61, 0x67, 0x65, 0x73, 0x2D, 0x72, 0x75, 0x6E, 0x74, 0x69, 0x6D, 0x65, 0x2E, 0x65, 0x78, 0x65 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"TAGES {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
|
||||
if ((position = fileContent.IndexOf("" + (char)0xE8 + "u" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0xE8)) > -1
|
||||
&& fileContent.Substring(--position + 8, 3) == "" + (char)0xFF + (char)0xFF + "h") // TODO: Verify this subtract
|
||||
return "TAGES " + GetVersion(file, position);
|
||||
// "tagesprotection.com"
|
||||
check = new byte[] { 0x74, 0x61, 0x67, 0x65, 0x73, 0x70, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6F, 0x6E, 0x2E, 0x63, 0x6F, 0x6D };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"TAGES {Utilities.GetFileVersion(file)} (Index {position})";
|
||||
|
||||
// (char)0xE8 + "u" + (char)0x00 + (char)0x00 + (char)0x00 + (char)0xE8
|
||||
check = new byte[] { 0xE8, 0x75, 0x00, 0x00, 0x00, 0xE8 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
// (char)0xFF + (char)0xFF + "h"
|
||||
if (new ArraySegment<byte>(fileContent, --position + 8, 3).SequenceEqual(new byte[] { 0xFF, 0xFF, 0x68 })) // TODO: Verify this subtract
|
||||
return $"TAGES {GetVersion(fileContent, position)} (Index {position})";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -78,27 +88,19 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
switch (fileContent[position + 7])
|
||||
{
|
||||
br.BaseStream.Seek(position + 7, SeekOrigin.Begin);
|
||||
byte bVersion = br.ReadByte();
|
||||
switch (bVersion)
|
||||
{
|
||||
case 0x1B:
|
||||
return "5.3-5.4";
|
||||
case 0x14:
|
||||
return "5.5.0";
|
||||
case 0x4:
|
||||
return "5.5.2";
|
||||
}
|
||||
return "";
|
||||
case 0x1B:
|
||||
return "5.3-5.4";
|
||||
case 0x14:
|
||||
return "5.5.0";
|
||||
case 0x4:
|
||||
return "5.5.2";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,22 @@
|
||||
{
|
||||
public class ThreePLock
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains(".ldr")
|
||||
|| fileContent.Contains(".ldt"))
|
||||
// || fileContent.Contains("Y" + (char)0xC3 + "U" + (char)0x8B + (char)0xEC + (char)0x83 + (char)0xEC + "0SVW")
|
||||
{
|
||||
return "3PLock";
|
||||
}
|
||||
// ".ldr"
|
||||
byte[] check = new byte[] { 0x2E, 0x6C, 0x64, 0x72 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"3PLock (Index {position})";
|
||||
|
||||
// ".ldt"
|
||||
check = new byte[] { 0x2E, 0x6C, 0x64, 0x74 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"3PLock (Index {position})";
|
||||
|
||||
// "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 };
|
||||
//if (fileContent.Contains(check, out position))
|
||||
// return $"3PLock (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -7,35 +7,37 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class VOBProtectCDDVD
|
||||
{
|
||||
public static string CheckContents(string file, string fileContent)
|
||||
public static string CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
int position;
|
||||
if ((position = fileContent.IndexOf("VOB ProtectCD")) > -1)
|
||||
return "VOB ProtectCD/DVD " + GetOldVersion(file, --position); // TODO: Verify this subtract
|
||||
// "VOB ProtectCD"
|
||||
byte[] check = new byte[] { 0x56, 0x4F, 0x42, 0x20, 0x50, 0x72, 0x6F, 0x74, 0x65, 0x63, 0x74, 0x43, 0x44 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"VOB ProtectCD/DVD {GetOldVersion(fileContent, --position)} (Index {position})"; // TODO: Verify this subtract
|
||||
|
||||
if ((position = fileContent.IndexOf("DCP-BOV" + (char)0x00 + (char)0x00)) > -1)
|
||||
// "DCP-BOV" + (char)0x00 + (char)0x00
|
||||
check = new byte[] { 0x44, 0x43, 0x50, 0x2D, 0x42, 0x4F, 0x56, 0x00, 0x00 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
{
|
||||
string version = GetVersion(file, --position); // TODO: Verify this subtract
|
||||
string version = GetVersion(fileContent, --position); // TODO: Verify this subtract
|
||||
if (version.Length > 0)
|
||||
{
|
||||
return "VOB ProtectCD/DVD " + version;
|
||||
}
|
||||
return $"VOB ProtectCD/DVD {version} (Index {position})";
|
||||
|
||||
version = EVORE.SearchProtectDiscVersion(file);
|
||||
version = EVORE.SearchProtectDiscVersion(file, fileContent);
|
||||
if (version.Length > 0)
|
||||
{
|
||||
if (version.StartsWith("2"))
|
||||
{
|
||||
version = "6" + version.Substring(1);
|
||||
}
|
||||
return "VOB ProtectCD/DVD " + version;
|
||||
version = $"6{version.Substring(1)}";
|
||||
|
||||
return $"VOB ProtectCD/DVD {version} (Index {position})";
|
||||
}
|
||||
|
||||
return "VOB ProtectCD/DVD 5.9-6.0" + GetBuild(file, position);
|
||||
return $"VOB ProtectCD/DVD 5.9-6.0 {GetBuild(fileContent, position)} (Index {position})";
|
||||
}
|
||||
|
||||
if (fileContent.Contains(".vob.pcd"))
|
||||
return "VOB ProtectCD";
|
||||
// ".vob.pcd"
|
||||
check = new byte[] { 0x2E, 0x76, 0x6F, 0x62, 0x2E, 0x70, 0x63, 0x64 };
|
||||
if (fileContent.Contains(check, out position))
|
||||
return $"VOB ProtectCD (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -56,68 +58,36 @@ namespace BurnOutSharp.ProtectionType
|
||||
return null;
|
||||
}
|
||||
|
||||
private static string GetBuild(string file, int position)
|
||||
private static string GetBuild(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
if (!char.IsNumber((char)fileContent[position - 13]))
|
||||
return ""; //Build info removed
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
br.BaseStream.Seek(position - 13, SeekOrigin.Begin);
|
||||
if (!char.IsNumber(br.ReadChar()))
|
||||
return ""; //Build info removed
|
||||
|
||||
br.BaseStream.Seek(position - 4, SeekOrigin.Begin);
|
||||
int build = br.ReadInt16();
|
||||
return " (Build " + build + ")";
|
||||
}
|
||||
int build = BitConverter.ToInt16(fileContent, position - 4); // Check if this is supposed to be a 4-byte read
|
||||
return $" (Build {build})";
|
||||
}
|
||||
|
||||
private static string GetOldVersion(string file, int position)
|
||||
private static string GetOldVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
char[] version = new ArraySegment<byte>(fileContent, position + 16, 4).Select(b => (char)b).ToArray(); // Begin reading after "VOB ProtectCD"
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[2]) && char.IsNumber(version[3]))
|
||||
return $"{version[0]}.{version[2]}{version[3]}";
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
{
|
||||
char[] version = new char[3];
|
||||
br.BaseStream.Seek(position + 16, SeekOrigin.Begin); // Begin reading after "VOB ProtectCD"
|
||||
version[0] = br.ReadChar();
|
||||
br.ReadByte();
|
||||
version[1] = br.ReadChar();
|
||||
version[2] = br.ReadChar();
|
||||
|
||||
if (char.IsNumber(version[0]) && char.IsNumber(version[1]) && char.IsNumber(version[2]))
|
||||
return version[0] + "." + version[1] + version[2];
|
||||
|
||||
return "old";
|
||||
}
|
||||
return "old";
|
||||
}
|
||||
|
||||
private static string GetVersion(string file, int position)
|
||||
private static string GetVersion(byte[] fileContent, int position)
|
||||
{
|
||||
if (file == null || !File.Exists(file))
|
||||
return string.Empty;
|
||||
|
||||
using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var br = new BinaryReader(fs))
|
||||
if (fileContent[position - 2] == 5)
|
||||
{
|
||||
br.BaseStream.Seek(position - 2, SeekOrigin.Begin);
|
||||
byte version = br.ReadByte();
|
||||
if (version == 5)
|
||||
{
|
||||
br.BaseStream.Seek(position - 4, SeekOrigin.Begin);
|
||||
byte subsubVersion = (byte)((br.ReadByte() & 0xF0) >> 4);
|
||||
byte subVersion = (byte)((br.ReadByte() & 0xF0) >> 4);
|
||||
return version + "." + subVersion + "." + subsubVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
int index = position - 4;
|
||||
byte subsubVersion = (byte)((fileContent[index] & 0xF0) >> 4);
|
||||
index++;
|
||||
byte subVersion = (byte)((fileContent[index] & 0xF0) >> 4);
|
||||
return $"5.{subVersion}.{subsubVersion}";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class WTMCDProtect
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("WTM76545"))
|
||||
return "WTM CD Protect";
|
||||
// "WTM76545"
|
||||
byte[] check = new byte[] { 0x57, 0x54, 0x4D, 0x37, 0x36, 0x35, 0x34, 0x35 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"WTM CD Protect (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
63
BurnOutSharp/ProtectionType/WiseInstaller.cs
Normal file
63
BurnOutSharp/ProtectionType/WiseInstaller.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Wise = WiseUnpacker.WiseUnpacker;
|
||||
|
||||
namespace BurnOutSharp.ProtectionType
|
||||
{
|
||||
public class WiseInstaller
|
||||
{
|
||||
public static List<string> CheckContents(string file, byte[] fileContent)
|
||||
{
|
||||
// "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 (Index {position})" };
|
||||
|
||||
if (!File.Exists(file))
|
||||
return protections;
|
||||
|
||||
protections.AddRange(WiseInstaller.Scan(file));
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<string> Scan(string file)
|
||||
{
|
||||
List<string> protections = new List<string>();
|
||||
|
||||
// If the installer file itself fails
|
||||
try
|
||||
{
|
||||
string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(tempPath);
|
||||
|
||||
Wise unpacker = new Wise();
|
||||
unpacker.ExtractTo(file, tempPath);
|
||||
|
||||
foreach (string tempFile in Directory.EnumerateFiles(tempPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
string protection = ProtectionFind.ScanContent(tempFile);
|
||||
|
||||
// If tempfile cleanup fails
|
||||
try
|
||||
{
|
||||
File.Delete(tempFile);
|
||||
}
|
||||
catch { }
|
||||
|
||||
if (!string.IsNullOrEmpty(protection))
|
||||
protections.Add($"\r\n{tempFile.Substring(tempPath.Length)} - {protection}");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return protections;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class XtremeProtector
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("XPROT "))
|
||||
return "Xtreme-Protector";
|
||||
// "XPROT "
|
||||
byte[] check = new byte[] { 0x58, 0x50, 0x52, 0x4F, 0x54, 0x20, 0x20, 0x20 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"Xtreme-Protector (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
{
|
||||
public class dotFuscator
|
||||
{
|
||||
public static string CheckContents(string fileContent)
|
||||
public static string CheckContents(byte[] fileContent)
|
||||
{
|
||||
if (fileContent.Contains("DotfuscatorAttribute"))
|
||||
return "dotFuscator";
|
||||
// "DotfuscatorAttribute"
|
||||
byte[] check = new byte[] { 0x44, 0x6F, 0x74, 0x66, 0x75, 0x73, 0x63, 0x61, 0x74, 0x6F, 0x72, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65 };
|
||||
if (fileContent.Contains(check, out int position))
|
||||
return $"dotFuscator (Index {position})";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
BIN
BurnOutSharp/StormLib.dll
Normal file
BIN
BurnOutSharp/StormLib.dll
Normal file
Binary file not shown.
@@ -9,6 +9,66 @@ namespace BurnOutSharp
|
||||
{
|
||||
public static class Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Search for a byte array in another array
|
||||
/// </summary>
|
||||
public static bool Contains(this byte[] stack, byte[] needle, out int position, int start = 0, int end = -1)
|
||||
{
|
||||
// Initialize the found position to -1
|
||||
position = -1;
|
||||
|
||||
// If either array is null or empty, we can't do anything
|
||||
if (stack == null || stack.Length == 0 || needle == null || needle.Length == 0)
|
||||
return false;
|
||||
|
||||
// If the needle array is larger than the stack array, it can't be contained within
|
||||
if (needle.Length > stack.Length)
|
||||
return false;
|
||||
|
||||
// If start or end are not set properly, set them to defaults
|
||||
if (start < 0)
|
||||
start = 0;
|
||||
if (end < 0)
|
||||
end = stack.Length - needle.Length;
|
||||
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (stack.EqualAt(needle, i))
|
||||
{
|
||||
position = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See if a byte array starts with another
|
||||
/// </summary>
|
||||
public static bool StartsWith(this byte[] stack, byte[] needle)
|
||||
{
|
||||
return stack.Contains(needle, out int _, start: 0, end: 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get if a stack at a certain index is equal to a needle
|
||||
/// </summary>
|
||||
private static bool EqualAt(this byte[] stack, byte[] needle, int index)
|
||||
{
|
||||
// If we're too close to the end of the stack, return false
|
||||
if (needle.Length >= stack.Length - index)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < needle.Length; i++)
|
||||
{
|
||||
if (stack[i + index] != needle[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the file version as reported by the filesystem
|
||||
/// </summary>
|
||||
|
||||
149
LICENSE
149
LICENSE
@@ -1,21 +1,23 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
@@ -24,34 +26,44 @@ them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
@@ -60,7 +72,7 @@ modification follow.
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
@@ -537,45 +549,35 @@ to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
@@ -633,29 +635,40 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
13
README.md
13
README.md
@@ -4,7 +4,16 @@
|
||||
|
||||
C# port of the protection scanning ability of [BurnOut](http://burnout.sourceforge.net/) plus numerous updates and additions. This currently compiles as a library so it can be used in any C# application. For an example of usage, see [DICUI](https://github.com/reignstumble/DICUI).
|
||||
|
||||
In addition to the original BurnOut code, this port adds the ability to scan inside of Microsoft CAB files (courtesy of [libmspack4n](https://github.com/activescott/libmspack4n)) and InstallShield CAB files (courtesy of [UnshieldSharp](https://github.com/mnadareski/UnshieldSharp)).
|
||||
In addition to the original BurnOut code, the following libraries (or ports thereof) are used for file handling:
|
||||
|
||||
- [HLExtract](https://github.com/Rupan/HLLib) - Various Valve archive format extraction
|
||||
- [libmspack4n](https://github.com/activescott/libmspack4n) - Microsoft CAB extraction
|
||||
- [psxt001z](https://github.com/Dremora/psxt001z) - PS1 LibCrypt detection
|
||||
- [SharpCompress](https://github.com/adamhathcock/sharpcompress) - 7zip/GZip/RAR/PKZIP extraction
|
||||
- [StormLib](https://github.com/ladislav-zezula/StormLib) - MPQ extraction
|
||||
- [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
|
||||
|
||||
## Protections Detected
|
||||
|
||||
@@ -38,6 +47,7 @@ Below is a list of the protections that can be detected using this code:
|
||||
- Hexalock Autolock
|
||||
- Impulse Reactor
|
||||
- IndyVCD
|
||||
- Inno Setup
|
||||
- JoWooD X-Prot (v1/v2)
|
||||
- Key2Audio XS
|
||||
- Key-Lock (Dongle)
|
||||
@@ -66,6 +76,7 @@ Below is a list of the protections that can be detected using this code:
|
||||
- Uplay (partial)
|
||||
- VOB ProtectCD/DVD
|
||||
- Winlock
|
||||
- WISE Installer
|
||||
- WTM CD Protect
|
||||
- WTM Copy Protection
|
||||
- XCP
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using BurnOutSharp;
|
||||
|
||||
@@ -12,9 +13,15 @@ namespace Test
|
||||
p.ProgressChanged += Changed;
|
||||
foreach (string arg in args)
|
||||
{
|
||||
Console.WriteLine(String.Join("\r\n", ProtectionFind.Scan(arg, p).Select(kvp => kvp.Key + ": " + kvp.Value)));
|
||||
string protections = String.Join("\r\n", ProtectionFind.Scan(arg, 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")))
|
||||
{
|
||||
sw.WriteLine(protections);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Press any button to close...");
|
||||
Console.ReadLine();
|
||||
|
||||
//ProtectionFind.ScanSectors('D', 2048);
|
||||
|
||||
Reference in New Issue
Block a user