首页 > 解决方案 > 如何检查文件头结构以识别 MSI 文件

问题描述

我正在开发一个解决方案,我需要能够检查文件是否属于我无法信任该文件的扩展名的特定类型。

我已经能够识别 EXE 和 DLL 文件,只需要识别最后一个。

目前我不知道如何识别 MSI MSI 与 EXE 和 DLL 有什么不同?我应该去哪里看?

例如,要找到一个 DLL,我正在执行以下操作:

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;
}

是否有类似的解决方案来确定文件是否为 MSI 类型?

编辑 1 这就是我现在根据 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;
}

但是这种方法无法将我的测试 msi 文件调用为 msi 文件,所以我猜我做错了什么?

我的解决方案:

在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;
}

标签: c#.netasp.net-mvc

解决方案


MSI 文件格式是 Microsoft 私人指定的格式。这真是一个奇怪的野兽,我的意思是,谁会拿一个 SQL 数据库,把它强制转换成 COM 存储格式并称之为 MSI?但事实就是如此。

相关: Windows 安装程序 MSI 格式

一个干净的方法是引用Windows Installer SDK并尝试对您怀疑是 MSI 的文件调用MsiVerifyPackage文档ERROR_SUCCESS),如果调用返回您认为它是真的。

有一个可用于 .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 */
}

一种更实用、更轻量且更快的方法是检查序列

D0 CF 11 E0 A1 B1 1A E1

这将它与具有相同扩展名的 Cerius2 文件区分开来。

来源


推荐阅读