From 2d2cff4d0e53930d8f75222e3a9cc54aeb5e34a3 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Wed, 28 Oct 2020 22:51:33 -0700 Subject: [PATCH] Add MSI extraction and scanning --- BurnOutSharp/BurnOutSharp.csproj | 1 + BurnOutSharp/FileType/MSI.cs | 55 +++++++++++++++++++++++++++ BurnOutSharp/FileType/MicrosoftCAB.cs | 22 +++++------ BurnOutSharp/ProtectionFind.cs | 4 ++ 4 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 BurnOutSharp/FileType/MSI.cs diff --git a/BurnOutSharp/BurnOutSharp.csproj b/BurnOutSharp/BurnOutSharp.csproj index 59cb0b27..659fdad5 100644 --- a/BurnOutSharp/BurnOutSharp.csproj +++ b/BurnOutSharp/BurnOutSharp.csproj @@ -28,6 +28,7 @@ + diff --git a/BurnOutSharp/FileType/MSI.cs b/BurnOutSharp/FileType/MSI.cs new file mode 100644 index 00000000..7120255e --- /dev/null +++ b/BurnOutSharp/FileType/MSI.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using LibMSPackN; +using Microsoft.Deployment.WindowsInstaller; +using Microsoft.Deployment.WindowsInstaller.Package; + +namespace BurnOutSharp.FileType +{ + internal class MSI + { + public static bool ShouldScan(byte[] magic) + { + if (magic.StartsWith(new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 })) + return true; + + return false; + } + + // TODO: Add stream opening support + public static List Scan(string file, bool includePosition = false) + { + List protections = new List(); + + // If the MSI file itself fails + try + { + string tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(tempPath); + + using (Database msidb = new Database(file, DatabaseOpenMode.ReadOnly)) + { + msidb.ExportAll(tempPath); + } + + // Collect and format all found protections + var fileProtections = ProtectionFind.Scan(tempPath, includePosition); + protections = fileProtections.Select(kvp => kvp.Key.Substring(tempPath.Length) + ": " + kvp.Value.TrimEnd()).ToList(); + + // If temp directory cleanup fails + try + { + Directory.Delete(tempPath, true); + } + catch { } + } + catch { } + + return protections; + } + } +} diff --git a/BurnOutSharp/FileType/MicrosoftCAB.cs b/BurnOutSharp/FileType/MicrosoftCAB.cs index 2f91e93b..4f875ff4 100644 --- a/BurnOutSharp/FileType/MicrosoftCAB.cs +++ b/BurnOutSharp/FileType/MicrosoftCAB.cs @@ -39,18 +39,18 @@ namespace BurnOutSharp.FileType } catch { } } - - // Collect and format all found protections - var fileProtections = ProtectionFind.Scan(tempPath, includePosition); - protections = fileProtections.Select(kvp => kvp.Key.Substring(tempPath.Length) + ": " + kvp.Value.TrimEnd()).ToList(); - - // If temp directory cleanup fails - try - { - Directory.Delete(tempPath, true); - } - catch { } } + + // Collect and format all found protections + var fileProtections = ProtectionFind.Scan(tempPath, includePosition); + protections = fileProtections.Select(kvp => kvp.Key.Substring(tempPath.Length) + ": " + kvp.Value.TrimEnd()).ToList(); + + // If temp directory cleanup fails + try + { + Directory.Delete(tempPath, true); + } + catch { } } catch { } diff --git a/BurnOutSharp/ProtectionFind.cs b/BurnOutSharp/ProtectionFind.cs index dbf966a6..3cf45921 100644 --- a/BurnOutSharp/ProtectionFind.cs +++ b/BurnOutSharp/ProtectionFind.cs @@ -444,6 +444,10 @@ namespace BurnOutSharp if (file != null && MicrosoftCAB.ShouldScan(magic)) protections.AddRange(MicrosoftCAB.Scan(file, includePosition)); + // MSI + if (file != null && MSI.ShouldScan(magic)) + protections.AddRange(MSI.Scan(file, includePosition)); + // MPQ archive if (file != null && MPQ.ShouldScan(magic)) protections.AddRange(MPQ.Scan(file, includePosition));