c#判断exe文件是不是7z或者rar的自解压文件

发布于:2025-02-19 ⋅ 阅读:(21) ⋅ 点赞:(0)

亲测可以实现检测7z的自解压,但是对于rar的自解压格式,最新版不支持,尝试修改回发现几乎检测成了exe文件,这显然是不正确的,其他版本未测试。

如下图所示,可以检测出自解压格式的7z文件,黑色显示。

直接上代码:

public class SelfExtractingChecker
    {
        public static bool Is7zOrRarSfx(string filePath)
        {
            try
            {
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    // 检查RAR自解压文件签名
                    if (CheckRarSignature(fs))
                    {
                        return true;
                    }

                    // 检查7z自解压文件签名
                    if (Check7zSignature(fs))
                    {
                        return true;
                    }
                }
            }
            catch
            {
                // 处理文件访问异常
                return false;
            }

            return false;
        }

        private static bool CheckRarSignature(FileStream fs)
        {
            // RAR签名:"Rar!\x1A\x07\x00"(7字节)
            byte[] rarSig = { 0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00 };

            // 常见偏移量(按优先级排序)
            int[] possibleOffsets = { 0x200, 0x210, 0x400, 0x1000 };

            foreach (int offset in possibleOffsets)
            {
                if (fs.Length > offset + rarSig.Length)
                {
                    fs.Seek(offset, SeekOrigin.Begin);
                    byte[] buffer = new byte[rarSig.Length];
                    int bytesRead = fs.Read(buffer, 0, buffer.Length);

                    if (bytesRead == buffer.Length && buffer.SequenceEqual(rarSig))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private static bool Check7zSignature(FileStream fs)
        {
            // 7z签名:"7z\xBC\xAF\x27\x1C"(6字节)
            byte[] sevenZipSig = { 0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C };
            const int bufferSize = 4096;
            byte[] buffer = new byte[bufferSize];
            int overlap = sevenZipSig.Length - 1;
            int bytesRead;
            long totalRead = 0;

            fs.Seek(0, SeekOrigin.Begin);

            while ((bytesRead = fs.Read(buffer, 0, bufferSize)) > 0)
            {
                // 检查当前缓冲区
                for (int i = 0; i < bytesRead - overlap; i++)
                {
                    bool match = true;
                    for (int j = 0; j < sevenZipSig.Length; j++)
                    {
                        if (i + j >= bytesRead || buffer[i + j] != sevenZipSig[j])
                        {
                            match = false;
                            break;
                        }
                    }
                    if (match)
                    {
                        return true;
                    }
                }

                // 处理边界情况:保留最后几个字节与下一块组合
                if (bytesRead >= overlap)
                {
                    Array.Copy(buffer, bytesRead - overlap, buffer, 0, overlap);
                    totalRead += bytesRead - overlap;
                }
                else
                {
                    Array.Copy(buffer, 0, buffer, 0, bytesRead);
                    totalRead += bytesRead;
                }

                // 检查是否超过合理搜索范围(前20MB)
                if (totalRead > 20 * 1024 * 1024)
                {
                    break;
                }
            }

            return false;
        }
    }

以上,谨此纪念。


网站公告

今日签到

点亮在社区的每一天
去签到