I'm developing a solution where I need to be able to check if the file is of specific types where I cannot trust the extension name of that file.
I'm already able to identify EXE and DLL files and just need the last one to be identified.
currently I do not know how to identify a MSI what in the MSI is different from an EXE and a DLL? Where should I look?
for instance to find a DLL I am doing the following:
if ((ntHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0)
{
    //If DLL then this returns True Else Return False
    return (ntHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) == 8192;
}
is there a similar solution to find out if the file is of type MSI ?
EDIT 1 this is how I'm doing it now based on the idea of dlatikay
private static ulong FIRST_8_BYTES_OF_MSI_FILE =0xD0CF11E0A1B11AE1;
private bool MSICheck(FileStream fileData)
{
    byte[] first8bytes = new byte[8];
    using (BinaryReader reader = new BinaryReader(fileData))
    {
        reader.BaseStream.Seek(0, SeekOrigin.Begin);
        reader.Read(first8bytes, 0, 7);
    }
    ulong sum = BitConverter.ToUInt64(first8bytes, 0);
    //string hexString = BitConverter.ToString(first8bytes);
    bool returnval = sum == FIRST_8_BYTES_OF_MSI_FILE;
    return returnval;
    //D0 CF 11 E0 A1 B1 1A E1 First 8 hexadecimal of a MSI package
    //return false;
}
however this method fails to call out my test msi file as a msi file so I'm guessing I'm doing something wrong ?
My solution:
with the guidance of dlatikay
private static string FIRST_8_BYTES_OF_MSI_FILE = "D0CF11E0A1B11AE1";
private bool MSICheck(FileStream fileData)
{
    byte[] first8bytes = new byte[8];
    using (BinaryReader reader = new BinaryReader(fileData))
    {
        reader.BaseStream.Seek(0, SeekOrigin.Begin);
        reader.Read(first8bytes, 0, first8bytes.Length);
    }
    string sum = BitConverter.ToString(first8bytes).Replace("-",""); ;
    bool returnval = sum.Equals(FIRST_8_BYTES_OF_MSI_FILE);
    return returnval;
    //D0 CF 11 E0 A1 B1 1A E1 First 8 hexadecimal of a MSI package
    //return false;
}
The MSI file format is a privately specified format of Microsoft. It is really a strange beast, I mean who would take a SQL database, force it into a COM storage format and call that MSI? But that's what it is.
Related: Windows installer MSI format
A clean way would be to reference the Windows Installer SDK and attempt a call to MsiVerifyPackage (documentation) on the file you suspect to be an MSI, if the call returns ERROR_SUCCESS you consider it true.
There is a managed version available for .NET:
using Microsoft.Deployment.WindowsInstaller;
...
if(Installer.VerifyPackage(fullpath))
{
    /* positive. it may still be corrupt,
     * but the API says it is a Microsoft Installer package */
}
A more practical, lightweight, and faster approach would be to check for the sequence
D0 CF 11 E0 A1 B1 1A E1
which distinguishes it from Cerius2 files, which have the same extension.
(Source)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With