From b7afad5a4a3d5e0110a07431ac4e5f9eb33161d5 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Tue, 20 Feb 2024 19:59:43 -0500 Subject: [PATCH] Enable MS-CAB extraction on at least x86 --- .../BinaryObjectScanner.csproj | 6 +-- BinaryObjectScanner/FileType/MicrosoftCAB.cs | 45 +++++++++++++++++-- README.md | 4 +- Test/Extractor.cs | 28 ++++++++++-- Test/Options.cs | 2 +- Test/Test.csproj | 4 +- 6 files changed, 75 insertions(+), 14 deletions(-) diff --git a/BinaryObjectScanner/BinaryObjectScanner.csproj b/BinaryObjectScanner/BinaryObjectScanner.csproj index ee822dcf..4ca0440c 100644 --- a/BinaryObjectScanner/BinaryObjectScanner.csproj +++ b/BinaryObjectScanner/BinaryObjectScanner.csproj @@ -24,8 +24,8 @@ - - WIN + + $(DefineConstants);WIN @@ -50,7 +50,7 @@ - + true contentFiles;content diff --git a/BinaryObjectScanner/FileType/MicrosoftCAB.cs b/BinaryObjectScanner/FileType/MicrosoftCAB.cs index f1f7192d..e3629531 100644 --- a/BinaryObjectScanner/FileType/MicrosoftCAB.cs +++ b/BinaryObjectScanner/FileType/MicrosoftCAB.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.IO; using BinaryObjectScanner.Interfaces; +#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN +using LibMSPackN; +#endif namespace BinaryObjectScanner.FileType { @@ -18,16 +21,50 @@ namespace BinaryObjectScanner.FileType if (!File.Exists(file)) return null; - using (var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - return Extract(fs, file, includeDebug); - } + using var fs = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + return Extract(fs, file, includeDebug); } /// public string? Extract(Stream? stream, string file, bool includeDebug) { +#if NET20 || NET35 || NET40 || !WIN + // Not supported for old .NET due to feature requirements + // Not supported in non-Windows builds due to DLL requirements return null; +#else + try + { + // Create a temp output directory + string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(tempPath); + + using (var cabArchive = new MSCabinet(file)) + { + // Loop over each entry + foreach (var compressedFile in cabArchive.GetFiles()) + { + try + { + string tempFile = Path.Combine(tempPath, compressedFile.Filename); + Directory.CreateDirectory(Path.GetDirectoryName(tempFile)); + compressedFile.ExtractTo(tempFile); + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + } + } + } + + return tempPath; + } + catch (Exception ex) + { + if (includeDebug) Console.WriteLine(ex); + return null; + } +#endif } } } diff --git a/README.md b/README.md index 02809f38..f576f811 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,12 @@ C# protection, packer, and archive scanning library. This currently compiles as The following libraries (or ports thereof) are used for file handling: +- [LessIO](https://github.com/activescott/LessIO) - Used by libmspack4n for IO handling +- [libmspack4n](https://github.com/activescott/libmspack4n) MS-CAB extraction [Unused in .NET Frawework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries] - [openmcdf](https://github.com/ironfede/openmcdf) - MSI extraction - [SharpCompress](https://github.com/adamhathcock/sharpcompress) - Common archive format extraction - [SharpZipLib](https://github.com/icsharpcode/SharpZipLib) - zlib-based extraction -- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in .NET 6, .NET 7, or .NET 8 builds due to Windows-specific libraries] +- [StormLibSharp](https://github.com/robpaveza/stormlibsharp) - MoPaQ extraction [Unused in .NET Frawework 2.0/3.5/4.0 and non-Windows builds due to Windows-specific libraries] - [UnshieldSharp](https://github.com/mnadareski/UnshieldSharp) - InstallShield CAB extraction - [WiseUnpacker](https://github.com/mnadareski/WiseUnpacker) - Wise Installer extraction diff --git a/Test/Extractor.cs b/Test/Extractor.cs index 0d9b0468..8b33d070 100644 --- a/Test/Extractor.cs +++ b/Test/Extractor.cs @@ -408,6 +408,7 @@ namespace Test #endif } +#if ((NETFRAMEWORK && !NET20 && !NET35 && !NET40) || NETCOREAPP) && WIN // Microsoft Cabinet archive else if (ft == SupportedFileType.MicrosoftCAB) { @@ -415,7 +416,7 @@ namespace Test Console.WriteLine("Extracting MS-CAB contents"); Console.WriteLine(); - var cabinet = MicrosoftCabinet.Create(stream); + var cabinet = new LibMSPackN.MSCabinet(file); if (cabinet == null) { Console.WriteLine("Something went wrong parsing MS-CAB archive"); @@ -425,7 +426,24 @@ namespace Test try { - Console.WriteLine("MS-CAB extraction is disabled"); + // Extract the MS-CAB contents to the directory + foreach (var compressedFile in cabinet.GetFiles()) + { + try + { + string tempFile = Path.Combine(outputDirectory, compressedFile.Filename); + string? directoryName = Path.GetDirectoryName(tempFile); + if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + + compressedFile.ExtractTo(tempFile); + } + catch (Exception ex) + { + Console.WriteLine($"Something went wrong extracting Microsoft Cabinet entry {compressedFile.Filename}: {ex}"); + Console.WriteLine(); + } + } } catch (Exception ex) { @@ -433,6 +451,7 @@ namespace Test Console.WriteLine(); } } +#endif // Microsoft LZ / LZ32 else if (ft == SupportedFileType.MicrosoftLZ) @@ -514,7 +533,10 @@ namespace Test try { string tempFile = Path.Combine(outputDirectory, sub); - Directory.CreateDirectory(Path.GetDirectoryName(tempFile)); + string? directoryName = Path.GetDirectoryName(tempFile); + if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + mpqArchive.ExtractFile(sub, tempFile); } catch (Exception ex) diff --git a/Test/Options.cs b/Test/Options.cs index f8b34387..bf4256ad 100644 --- a/Test/Options.cs +++ b/Test/Options.cs @@ -166,7 +166,7 @@ namespace Test #if NET6_0_OR_GREATER options.Json = true; #else - Console.WriteLine("JSON output not available in .NET Framework 4.8"); + Console.WriteLine("JSON output not available in .NET Framework"); #endif break; diff --git a/Test/Test.csproj b/Test/Test.csproj index d229f8dd..cf2a6d63 100644 --- a/Test/Test.csproj +++ b/Test/Test.csproj @@ -12,8 +12,8 @@ - - WIN + + $(DefineConstants);WIN