/// <summary> /// Process a single file path as an InstallShield archive /// </summary> /// <param name="file">Name of the file to process</param> /// <param name="outputInfo">True to display the cabinet information, false otherwise</param> /// <param name="extract">True to extract the cabinet, false otherwise</param> private static void ProcessArchivePath(string file, bool outputInfo = true, bool extract = true) { if (!File.Exists(file)) { return; } var archive = new InstallShieldArchiveV3(file); if (outputInfo) { Console.WriteLine($"File count: {archive.Header.FileCount}"); Console.WriteLine($"Archive size: {archive.Header.ArchiveSize}"); Console.WriteLine($"Directory count: {archive.Header.DirCount}"); Console.WriteLine("Directory List:"); foreach (ArchiveDirectory directory in archive.Directories) { Console.WriteLine($"Directory: {directory.Name ?? string.Empty}, File Count: {directory.FileCount}"); } Console.WriteLine("File list:"); foreach (CompressedFile cfile in archive.Files.Select(kvp => kvp.Value)) { Console.WriteLine($"File: {cfile.FullPath ?? string.Empty}, Compressed Size: {cfile.CompressedSize}, Offset: {cfile.Offset}"); } } if (extract) { string baseDirectory = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(file)), Path.GetFileNameWithoutExtension(file)); if (!Directory.Exists(baseDirectory)) { Directory.CreateDirectory(baseDirectory); } foreach (CompressedFile internalFile in archive.Files.Select(kvp => kvp.Value)) { string newfile = Path.Combine(baseDirectory, internalFile.FullPath); if (!Directory.Exists(Path.GetDirectoryName(newfile))) { Directory.CreateDirectory(Path.GetDirectoryName(newfile)); } (byte[] fileContents, string error) = archive.Extract(internalFile.FullPath); if (!string.IsNullOrWhiteSpace(error)) { Console.WriteLine($"Error detected while reading '{internalFile.FullPath}': {error}"); continue; } Console.WriteLine($"Outputting file {internalFile.FullPath} to {newfile}..."); using (FileStream fs = File.OpenWrite(newfile)) { fs.Write(fileContents, 0, fileContents.Length); } } } }
/// <summary> /// Get the content-detectable protections associated with a single path /// </summary> /// <param name="file">Path to the file to scan</param> /// <returns>Dictionary of list of strings representing the found protections</returns> private ConcurrentDictionary <string, ConcurrentQueue <string> > GetInternalProtections(string file) { // Quick sanity check before continuing if (!File.Exists(file)) { return(null); } // Initialze the protections found var protections = new ConcurrentDictionary <string, ConcurrentQueue <string> >(); // Get the extension for certain checks string extension = Path.GetExtension(file).ToLower().TrimStart('.'); // Open the file and begin scanning using (FileStream fs = File.OpenRead(file)) { // Get the first 16 bytes for matching byte[] magic = new byte[16]; try { fs.Read(magic, 0, 16); fs.Seek(-16, SeekOrigin.Current); } catch { // We don't care what the issue was, we can't read or seek the file return(null); } #region Non-Archive File Types // Executable if (ScanAllFiles || new Executable().ShouldScan(magic)) { var subProtections = new Executable().Scan(this, fs, file); Utilities.AppendToDictionary(protections, subProtections); } // Text-based files if (ScanAllFiles || new Textfile().ShouldScan(magic, extension)) { var subProtections = new Textfile().Scan(this, fs, file); Utilities.AppendToDictionary(protections, subProtections); } #endregion #region Archive File Types // If we're scanning archives, we have a few to try out if (ScanArchives) { // 7-Zip archive if (new SevenZip().ShouldScan(magic)) { var subProtections = new SevenZip().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // BFPK archive if (new BFPK().ShouldScan(magic)) { var subProtections = new BFPK().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // BZip2 if (new BZip2().ShouldScan(magic)) { var subProtections = new BZip2().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // GZIP if (new GZIP().ShouldScan(magic)) { var subProtections = new GZIP().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // InstallShield Archive V3 (Z) if (file != null && new InstallShieldArchiveV3().ShouldScan(magic)) { var subProtections = new InstallShieldArchiveV3().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // InstallShield Cabinet if (file != null && new InstallShieldCAB().ShouldScan(magic)) { var subProtections = new InstallShieldCAB().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // Microsoft Cabinet if (file != null && new MicrosoftCAB().ShouldScan(magic)) { var subProtections = new MicrosoftCAB().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // MSI if (file != null && new MSI().ShouldScan(magic)) { var subProtections = new MSI().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // MPQ archive if (file != null && new MPQ().ShouldScan(magic)) { var subProtections = new MPQ().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // PKZIP archive (and derivatives) if (new PKZIP().ShouldScan(magic)) { var subProtections = new PKZIP().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // RAR archive if (new RAR().ShouldScan(magic)) { var subProtections = new RAR().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // Tape Archive if (new TapeArchive().ShouldScan(magic)) { var subProtections = new TapeArchive().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // Valve archive formats if (file != null && new Valve().ShouldScan(magic)) { var subProtections = new Valve().Scan(this, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } // XZ if (new XZ().ShouldScan(magic)) { var subProtections = new XZ().Scan(this, fs, file); Utilities.PrependToKeys(subProtections, file); Utilities.AppendToDictionary(protections, subProtections); } } #endregion } // Clear out any empty keys Utilities.ClearEmptyKeys(protections); return(protections); }