Ejemplo n.º 1
0
        internal Checksum()
        {
            _crc32Ctx  = new Crc32Context();
            _md5Ctx    = new Md5Context();
            _sha1Ctx   = new Sha1Context();
            _sha256Ctx = new Sha256Context();
            _sha384Ctx = new Sha384Context();
            _sha512Ctx = new Sha512Context();

            _crc32Thread  = new Thread(UpdateCrc32);
            _md5Thread    = new Thread(UpdateMd5);
            _sha1Thread   = new Thread(UpdateSha1);
            _sha256Thread = new Thread(UpdateSha256);
            _sha384Thread = new Thread(UpdateSha384);
            _sha512Thread = new Thread(UpdateSha512);

            _crc32Pkt  = new Crc32Packet();
            _md5Pkt    = new Md5Packet();
            _sha1Pkt   = new Sha1Packet();
            _sha256Pkt = new Sha256Packet();
            _sha384Pkt = new Sha384Packet();
            _sha512Pkt = new Sha512Packet();

            _crc32Pkt.context  = _crc32Ctx;
            _md5Pkt.context    = _md5Ctx;
            _sha1Pkt.context   = _sha1Ctx;
            _sha256Pkt.context = _sha256Ctx;
            _sha384Pkt.context = _sha384Ctx;
            _sha512Pkt.context = _sha512Ctx;
        }
Ejemplo n.º 2
0
        public bool?VerifyMediaImage()
        {
            byte[] calculated;
            if (mapVersion >= 3)
            {
                Sha1Context sha1Ctx = new Sha1Context();
                for (uint i = 0; i < totalHunks; i++)
                {
                    sha1Ctx.Update(GetHunk(i));
                }

                calculated = sha1Ctx.Final();
            }
            else
            {
                Md5Context md5Ctx = new Md5Context();
                for (uint i = 0; i < totalHunks; i++)
                {
                    md5Ctx.Update(GetHunk(i));
                }

                calculated = md5Ctx.Final();
            }

            return(expectedChecksum.SequenceEqual(calculated));
        }
Ejemplo n.º 3
0
        public void Sha1RandomData()
        {
            byte[]     data = new byte[1048576];
            FileStream fs   = new FileStream(Path.Combine(Consts.TestFilesRoot, "checksums", "random"), FileMode.Open,
                                             FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha1Context.Data(data, out byte[] result);
            Assert.AreEqual(ExpectedRandom, result);
        }
Ejemplo n.º 4
0
Archivo: SHA1.cs Proyecto: paulyc/Aaru
        public void Sha1EmptyData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"), FileMode.Open,
                                    FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha1Context.Data(data, out byte[] result);
            Assert.AreEqual(_expectedEmpty, result);
        }
Ejemplo n.º 5
0
        public void RandomData()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            Sha1Context.Data(data, out byte[] result);
            result.Should().BeEquivalentTo(_expectedRandom);
        }
Ejemplo n.º 6
0
        public EntropyResults CalculateMediaEntropy(bool duplicatedSectors)
        {
            var entropy = new EntropyResults
            {
                Entropy = 0
            };

            ulong[]       entTable      = new ulong[256];
            ulong         diskSize      = 0;
            List <string> uniqueSectors = new List <string>();

            entropy.Sectors = inputFormat.Info.Sectors;
            AaruConsole.WriteLine("Sectors {0}", entropy.Sectors);
            InitProgressEvent?.Invoke();

            for (ulong i = 0; i < entropy.Sectors; i++)
            {
                UpdateProgressEvent?.Invoke($"Entropying sector {i + 1}", (long)(i + 1), (long)entropy.Sectors);
                byte[] sector = inputFormat.ReadSector(i);

                if (duplicatedSectors)
                {
                    string sectorHash = Sha1Context.Data(sector, out _);

                    if (!uniqueSectors.Contains(sectorHash))
                    {
                        uniqueSectors.Add(sectorHash);
                    }
                }

                foreach (byte b in sector)
                {
                    entTable[b]++;
                }

                diskSize += (ulong)sector.LongLength;
            }

            EndProgressEvent?.Invoke();

            entropy.Entropy += entTable.Select(l => (double)l / (double)diskSize).
                               Select(frequency => - (frequency * Math.Log(frequency, 2))).Sum();

            if (duplicatedSectors)
            {
                entropy.UniqueSectors = uniqueSectors.Count;
            }

            return(entropy);
        }
Ejemplo n.º 7
0
        internal Checksum()
        {
            adler32ctx   = new Adler32Context();
            crc16ctx     = new Crc16Context();
            crc32ctx     = new Crc32Context();
            crc64ctx     = new Crc64Context();
            md5ctx       = new Md5Context();
            ripemd160ctx = new Ripemd160Context();
            sha1ctx      = new Sha1Context();
            sha256ctx    = new Sha256Context();
            sha384ctx    = new Sha384Context();
            sha512ctx    = new Sha512Context();
            ssctx        = new SpamSumContext();

            adlerThread     = new Thread(updateAdler);
            crc16Thread     = new Thread(updateCRC16);
            crc32Thread     = new Thread(updateCRC32);
            crc64Thread     = new Thread(updateCRC64);
            md5Thread       = new Thread(updateMD5);
            ripemd160Thread = new Thread(updateRIPEMD160);
            sha1Thread      = new Thread(updateSHA1);
            sha256Thread    = new Thread(updateSHA256);
            sha384Thread    = new Thread(updateSHA384);
            sha512Thread    = new Thread(updateSHA512);
            spamsumThread   = new Thread(updateSpamSum);

            adlerPkt     = new adlerPacket();
            crc16Pkt     = new crc16Packet();
            crc32Pkt     = new crc32Packet();
            crc64Pkt     = new crc64Packet();
            md5Pkt       = new md5Packet();
            ripemd160Pkt = new ripemd160Packet();
            sha1Pkt      = new sha1Packet();
            sha256Pkt    = new sha256Packet();
            sha384Pkt    = new sha384Packet();
            sha512Pkt    = new sha512Packet();
            spamsumPkt   = new spamsumPacket();

            adlerPkt.context     = adler32ctx;
            crc16Pkt.context     = crc16ctx;
            crc32Pkt.context     = crc32ctx;
            crc64Pkt.context     = crc64ctx;
            md5Pkt.context       = md5ctx;
            ripemd160Pkt.context = ripemd160ctx;
            sha1Pkt.context      = sha1ctx;
            sha256Pkt.context    = sha256ctx;
            sha384Pkt.context    = sha384ctx;
            sha512Pkt.context    = sha512ctx;
            spamsumPkt.context   = ssctx;
        }
Ejemplo n.º 8
0
        public void Sha1EmptyInstance()
        {
            byte[]     data = new byte[1048576];
            FileStream fs   = new FileStream(Path.Combine(Consts.TestFilesRoot, "checksums", "empty"), FileMode.Open,
                                             FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            IChecksum ctx = new Sha1Context();

            ctx.Update(data);
            byte[] result = ctx.Final();
            Assert.AreEqual(ExpectedEmpty, result);
        }
Ejemplo n.º 9
0
Archivo: SHA1.cs Proyecto: paulyc/Aaru
        public void Sha1RandomInstance()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"),
                                    FileMode.Open, FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            IChecksum ctx = new Sha1Context();

            ctx.Update(data);
            byte[] result = ctx.Final();
            Assert.AreEqual(_expectedRandom, result);
        }
Ejemplo n.º 10
0
        public void EmptyInstance()
        {
            byte[] data = new byte[1048576];

            var fs = new FileStream(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"), FileMode.Open,
                                    FileAccess.Read);

            fs.Read(data, 0, 1048576);
            fs.Close();
            fs.Dispose();
            IChecksum ctx = new Sha1Context();

            ctx.Update(data);
            byte[] result = ctx.Final();
            result.Should().BeEquivalentTo(_expectedEmpty);
        }
Ejemplo n.º 11
0
Archivo: SHA1.cs Proyecto: paulyc/Aaru
 public void Sha1RandomFile()
 {
     byte[] result = Sha1Context.File(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "random"));
     Assert.AreEqual(_expectedRandom, result);
 }
Ejemplo n.º 12
0
 public void EmptyFile()
 {
     byte[] result = Sha1Context.File(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"));
     result.Should().BeEquivalentTo(_expectedEmpty);
 }
Ejemplo n.º 13
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.ASCII;
            information = "";
            StringBuilder isoMetadata = new StringBuilder();

            byte[] vdMagic = new byte[5];            // Volume Descriptor magic "CD001"
            byte[] hsMagic = new byte[5];            // Volume Descriptor magic "CDROM"

            string bootSpec = "";

            PrimaryVolumeDescriptor?pvd      = null;
            PrimaryVolumeDescriptor?jolietvd = null;
            BootRecord?bvd = null;
            HighSierraPrimaryVolumeDescriptor?hsvd = null;
            FileStructureVolumeDescriptor?    fsvd = null;
            ElToritoBootRecord?torito = null;

            // ISO9660 is designed for 2048 bytes/sector devices
            if (imagePlugin.Info.SectorSize < 2048)
            {
                return;
            }

            // ISO9660 Primary Volume Descriptor starts at sector 16, so that's minimal size.
            if (partition.End < 16)
            {
                return;
            }

            ulong counter = 0;

            byte[] vdSector = imagePlugin.ReadSector(16 + counter + partition.Start);
            int    xaOff    = vdSector.Length == 2336 ? 8 : 0;

            Array.Copy(vdSector, 0x009 + xaOff, hsMagic, 0, 5);
            bool highSierra = Encoding.GetString(hsMagic) == HIGH_SIERRA_MAGIC;
            int  hsOff      = 0;

            if (highSierra)
            {
                hsOff = 8;
            }
            bool cdi = false;

            while (true)
            {
                DicConsole.DebugWriteLine("ISO9660 plugin", "Processing VD loop no. {0}", counter);
                // Seek to Volume Descriptor
                DicConsole.DebugWriteLine("ISO9660 plugin", "Reading sector {0}", 16 + counter + partition.Start);
                byte[] vdSectorTmp = imagePlugin.ReadSector(16 + counter + partition.Start);
                vdSector = new byte[vdSectorTmp.Length - xaOff];
                Array.Copy(vdSectorTmp, xaOff, vdSector, 0, vdSector.Length);

                byte vdType = vdSector[0 + hsOff]; // Volume Descriptor Type, should be 1 or 2.
                DicConsole.DebugWriteLine("ISO9660 plugin", "VDType = {0}", vdType);

                if (vdType == 255) // Supposedly we are in the PVD.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                Array.Copy(vdSector, 0x001, vdMagic, 0, 5);
                Array.Copy(vdSector, 0x009, hsMagic, 0, 5);

                if (Encoding.GetString(vdMagic) != ISO_MAGIC && Encoding.GetString(hsMagic) != HIGH_SIERRA_MAGIC &&
                    Encoding.GetString(vdMagic) != CDI_MAGIC
                    ) // Recognized, it is an ISO9660, now check for rest of data.
                {
                    if (counter == 0)
                    {
                        return;
                    }

                    break;
                }

                cdi |= Encoding.GetString(vdMagic) == CDI_MAGIC;

                switch (vdType)
                {
                case 0:
                {
                    IntPtr ptr = Marshal.AllocHGlobal(2048);
                    Marshal.Copy(vdSector, hsOff, ptr, 2048 - hsOff);
                    bvd = (BootRecord)Marshal.PtrToStructure(ptr, typeof(BootRecord));
                    Marshal.FreeHGlobal(ptr);

                    bootSpec = "Unknown";

                    if (Encoding.GetString(bvd.Value.system_id).Substring(0, 23) == "EL TORITO SPECIFICATION")
                    {
                        bootSpec = "El Torito";
                        ptr      = Marshal.AllocHGlobal(2048);
                        Marshal.Copy(vdSector, hsOff, ptr, 2048 - hsOff);
                        torito = (ElToritoBootRecord)Marshal.PtrToStructure(ptr, typeof(ElToritoBootRecord));
                        Marshal.FreeHGlobal(ptr);
                    }

                    break;
                }

                case 1:
                {
                    if (highSierra)
                    {
                        IntPtr ptr = Marshal.AllocHGlobal(2048);
                        Marshal.Copy(vdSector, 0, ptr, 2048);
                        hsvd =
                            (HighSierraPrimaryVolumeDescriptor)
                            Marshal.PtrToStructure(ptr, typeof(HighSierraPrimaryVolumeDescriptor));
                        Marshal.FreeHGlobal(ptr);
                    }
                    else if (cdi)
                    {
                        fsvd =
                            BigEndianMarshal.ByteArrayToStructureBigEndian <FileStructureVolumeDescriptor>(vdSector);
                    }
                    else
                    {
                        IntPtr ptr = Marshal.AllocHGlobal(2048);
                        Marshal.Copy(vdSector, 0, ptr, 2048);
                        pvd = (PrimaryVolumeDescriptor)Marshal.PtrToStructure(ptr, typeof(PrimaryVolumeDescriptor));
                        Marshal.FreeHGlobal(ptr);
                    }

                    break;
                }

                case 2:
                {
                    IntPtr ptr = Marshal.AllocHGlobal(2048);
                    Marshal.Copy(vdSector, 0, ptr, 2048);
                    PrimaryVolumeDescriptor svd =
                        (PrimaryVolumeDescriptor)Marshal.PtrToStructure(ptr, typeof(PrimaryVolumeDescriptor));
                    Marshal.FreeHGlobal(ptr);

                    // Check if this is Joliet
                    if (svd.escape_sequences[0] == '%' && svd.escape_sequences[1] == '/')
                    {
                        if (svd.escape_sequences[2] == '@' || svd.escape_sequences[2] == 'C' ||
                            svd.escape_sequences[2] == 'E')
                        {
                            jolietvd = svd;
                        }
                        else
                        {
                            DicConsole.WriteLine("ISO9660 plugin", "Found unknown supplementary volume descriptor");
                        }
                    }

                    break;
                }
                }

                counter++;
            }

            DecodedVolumeDescriptor decodedVd;
            DecodedVolumeDescriptor decodedJolietVd = new DecodedVolumeDescriptor();

            XmlFsType = new FileSystemType();

            if (pvd == null && hsvd == null && fsvd == null)
            {
                information = "ERROR: Could not find primary volume descriptor";
                return;
            }

            if (highSierra)
            {
                decodedVd = DecodeVolumeDescriptor(hsvd.Value);
            }
            else if (cdi)
            {
                decodedVd = DecodeVolumeDescriptor(fsvd.Value);
            }
            else
            {
                decodedVd = DecodeVolumeDescriptor(pvd.Value);
            }

            if (jolietvd != null)
            {
                decodedJolietVd = DecodeJolietDescriptor(jolietvd.Value);
            }

            uint rootLocation = 0;
            uint rootSize     = 0;

            // No need to read root on CD-i, as extensions are not supported...
            if (!cdi)
            {
                rootLocation = highSierra
                                   ? hsvd.Value.root_directory_record.extent
                                   : pvd.Value.root_directory_record.extent;

                if (highSierra)
                {
                    rootSize = hsvd.Value.root_directory_record.size / hsvd.Value.logical_block_size;
                    if (hsvd.Value.root_directory_record.size % hsvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
                else
                {
                    rootSize = pvd.Value.root_directory_record.size / pvd.Value.logical_block_size;
                    if (pvd.Value.root_directory_record.size % pvd.Value.logical_block_size > 0)
                    {
                        rootSize++;
                    }
                }
            }

            byte[] rootDir      = new byte[0];
            int    rootOff      = 0;
            bool   xaExtensions = false;
            bool   apple        = false;
            bool   susp         = false;
            bool   rrip         = false;
            bool   ziso         = false;
            bool   amiga        = false;
            bool   aaip         = false;
            List <ContinuationArea> contareas       = new List <ContinuationArea>();
            List <byte[]>           refareas        = new List <byte[]>();
            StringBuilder           suspInformation = new StringBuilder();

            if (rootLocation + rootSize < imagePlugin.Info.Sectors)
            {
                rootDir = imagePlugin.ReadSectors(rootLocation, rootSize);
            }

            BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

            // Walk thru root directory to see system area extensions in use
            while (rootOff + Marshal.SizeOf(typeof(DirectoryRecord)) < rootDir.Length && !cdi)
            {
                DirectoryRecord record = new DirectoryRecord();
                IntPtr          ptr    = Marshal.AllocHGlobal(Marshal.SizeOf(record));
                Marshal.Copy(rootDir, rootOff, ptr, Marshal.SizeOf(record));
                record = (DirectoryRecord)Marshal.PtrToStructure(ptr, typeof(DirectoryRecord));
                Marshal.FreeHGlobal(ptr);

                int saOff = Marshal.SizeOf(record) + record.name_len;
                saOff += saOff % 2;
                int saLen = record.length - saOff;

                if (saLen > 0 && rootOff + saOff + saLen <= rootDir.Length)
                {
                    byte[] sa = new byte[saLen];
                    Array.Copy(rootDir, rootOff + saOff, sa, 0, saLen);
                    saOff = 0;

                    while (saOff < saLen)
                    {
                        bool noneFound = true;

                        if (Marshal.SizeOf(typeof(CdromXa)) + saOff <= saLen)
                        {
                            CdromXa xa = BigEndianMarshal.ByteArrayToStructureBigEndian <CdromXa>(sa);
                            if (xa.signature == XA_MAGIC)
                            {
                                xaExtensions = true;
                                saOff       += Marshal.SizeOf(typeof(CdromXa));
                                noneFound    = false;
                            }
                        }

                        if (saOff + 2 >= saLen)
                        {
                            break;
                        }

                        ushort nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                        switch (nextSignature)
                        {
                        // Easy, contains size field
                        case APPLE_MAGIC:
                            apple     = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;
                            break;

                        // Not easy, contains size field
                        case APPLE_MAGIC_OLD:
                            apple = true;
                            AppleOldId appleId = (AppleOldId)sa[saOff + 2];
                            noneFound = false;

                            switch (appleId)
                            {
                            case AppleOldId.ProDOS:
                                saOff += Marshal.SizeOf(typeof(AppleProDOSOldSystemUse));
                                break;

                            case AppleOldId.TypeCreator:
                            case AppleOldId.TypeCreatorBundle:
                                saOff += Marshal.SizeOf(typeof(AppleHFSTypeCreatorSystemUse));
                                break;

                            case AppleOldId.TypeCreatorIcon:
                            case AppleOldId.TypeCreatorIconBundle:
                                saOff += Marshal.SizeOf(typeof(AppleHFSIconSystemUse));
                                break;

                            case AppleOldId.HFS:
                                saOff += Marshal.SizeOf(typeof(AppleHFSOldSystemUse));
                                break;
                            }

                            break;

                        // IEEE-P1281 aka SUSP 1.12
                        case SUSP_INDICATOR:
                            susp      = true;
                            saOff    += sa[saOff + 2];
                            noneFound = false;

                            while (saOff + 2 < saLen)
                            {
                                nextSignature = BigEndianBitConverter.ToUInt16(sa, saOff);

                                switch (nextSignature)
                                {
                                case APPLE_MAGIC:
                                    if (sa[saOff + 3] == 1 && sa[saOff + 2] == 7)
                                    {
                                        apple = true;
                                    }
                                    else
                                    {
                                        apple |= sa[saOff + 3] != 1;
                                    }
                                    break;

                                case SUSP_CONTINUATION when saOff + sa[saOff + 2] <= saLen:
                                    byte[] ce = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, ce, 0, ce.Length);
                                    ContinuationArea ca = BigEndianMarshal
                                                          .ByteArrayToStructureBigEndian <ContinuationArea>(ce);
                                    contareas.Add(ca);
                                    break;

                                case SUSP_REFERENCE when saOff + sa[saOff + 2] <= saLen:
                                    byte[] er = new byte[sa[saOff + 2]];
                                    Array.Copy(sa, saOff, er, 0, er.Length);
                                    refareas.Add(er);
                                    break;
                                }

                                rrip |= nextSignature == RRIP_MAGIC ||
                                        nextSignature == RRIP_POSIX_ATTRIBUTES ||
                                        nextSignature == RRIP_POSIX_DEV_NO ||
                                        nextSignature == RRIP_SYMLINK ||
                                        nextSignature == RRIP_NAME ||
                                        nextSignature == RRIP_CHILDLINK ||
                                        nextSignature == RRIP_PARENTLINK ||
                                        nextSignature == RRIP_RELOCATED_DIR ||
                                        nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                                ziso  |= nextSignature == ZISO_MAGIC;
                                amiga |= nextSignature == AMIGA_MAGIC;
                                aaip  |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD &&
                                         sa[saOff + 3] == 1 &&
                                         sa[saOff + 2] >= 9;

                                saOff += sa[saOff + 2];

                                if (nextSignature == SUSP_TERMINATOR)
                                {
                                    break;
                                }
                            }

                            break;
                        }

                        if (noneFound)
                        {
                            break;
                        }
                    }
                }

                rootOff += record.length;

                if (record.length == 0)
                {
                    break;
                }
            }

            foreach (ContinuationArea ca in contareas)
            {
                uint caLen = (ca.ca_length_be + ca.offset_be) /
                             (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size);
                if ((ca.ca_length_be + ca.offset_be) %
                    (highSierra ? hsvd.Value.logical_block_size : pvd.Value.logical_block_size) > 0)
                {
                    caLen++;
                }

                byte[] caSectors = imagePlugin.ReadSectors(ca.block_be, caLen);
                byte[] caData    = new byte[ca.ca_length_be];
                Array.Copy(caSectors, ca.offset_be, caData, 0, ca.ca_length_be);
                int caOff = 0;

                while (caOff < ca.ca_length_be)
                {
                    ushort nextSignature = BigEndianBitConverter.ToUInt16(caData, caOff);

                    switch (nextSignature)
                    {
                    // Apple never said to include its extensions inside a continuation area, but just in case
                    case APPLE_MAGIC:
                        if (caData[caOff + 3] == 1 && caData[caOff + 2] == 7)
                        {
                            apple = true;
                        }
                        else
                        {
                            apple |= caData[caOff + 3] != 1;
                        }
                        break;

                    case SUSP_REFERENCE when caOff + caData[caOff + 2] <= ca.ca_length_be:
                        byte[] er = new byte[caData[caOff + 2]];
                        Array.Copy(caData, caOff, er, 0, er.Length);
                        refareas.Add(er);
                        break;
                    }

                    rrip |= nextSignature == RRIP_MAGIC || nextSignature == RRIP_POSIX_ATTRIBUTES ||
                            nextSignature == RRIP_POSIX_DEV_NO || nextSignature == RRIP_SYMLINK ||
                            nextSignature == RRIP_NAME || nextSignature == RRIP_CHILDLINK ||
                            nextSignature == RRIP_PARENTLINK || nextSignature == RRIP_RELOCATED_DIR ||
                            nextSignature == RRIP_TIMESTAMPS || nextSignature == RRIP_SPARSE;

                    ziso  |= nextSignature == ZISO_MAGIC;
                    amiga |= nextSignature == AMIGA_MAGIC;
                    aaip  |= nextSignature == AAIP_MAGIC || nextSignature == AAIP_MAGIC_OLD && caData[caOff + 3] == 1 &&
                             caData[caOff + 2] >= 9;

                    caOff += caData[caOff + 2];
                }
            }

            if (refareas.Count > 0)
            {
                suspInformation.AppendLine("----------------------------------------");
                suspInformation.AppendLine("SYSTEM USE SHARING PROTOCOL INFORMATION:");
                suspInformation.AppendLine("----------------------------------------");

                counter = 1;
                foreach (byte[] erb in refareas)
                {
                    ReferenceArea er    = BigEndianMarshal.ByteArrayToStructureBigEndian <ReferenceArea>(erb);
                    string        extId =
                        Encoding.GetString(erb, Marshal.SizeOf(er), er.id_len);
                    string extDes =
                        Encoding.GetString(erb, Marshal.SizeOf(er) + er.id_len, er.des_len);
                    string extSrc =
                        Encoding.GetString(erb, Marshal.SizeOf(er) + er.id_len + er.des_len, er.src_len);
                    suspInformation.AppendFormat("Extension: {0}", counter).AppendLine();
                    suspInformation.AppendFormat("\tID: {0}, version {1}", extId, er.ext_ver).AppendLine();
                    suspInformation.AppendFormat("\tDescription: {0}", extDes).AppendLine();
                    suspInformation.AppendFormat("\tSource: {0}", extSrc).AppendLine();
                    counter++;
                }
            }

            byte[]          ipbinSector = imagePlugin.ReadSector(0 + partition.Start);
            CD.IPBin?       segaCd      = CD.DecodeIPBin(ipbinSector);
            Saturn.IPBin?   saturn      = Saturn.DecodeIPBin(ipbinSector);
            Dreamcast.IPBin?dreamcast   = Dreamcast.DecodeIPBin(ipbinSector);

            string fsFormat;

            if (highSierra)
            {
                fsFormat = "High Sierra Format";
            }
            else if (cdi)
            {
                fsFormat = "CD-i";
            }
            else
            {
                fsFormat = "ISO9660";
            }

            isoMetadata.AppendFormat("{0} file system", fsFormat).AppendLine();
            if (xaExtensions)
            {
                isoMetadata.AppendLine("CD-ROM XA extensions present.");
            }
            if (amiga)
            {
                isoMetadata.AppendLine("Amiga extensions present.");
            }
            if (apple)
            {
                isoMetadata.AppendLine("Apple extensions present.");
            }
            if (jolietvd != null)
            {
                isoMetadata.AppendLine("Joliet extensions present.");
            }
            if (susp)
            {
                isoMetadata.AppendLine("System Use Sharing Protocol present.");
            }
            if (rrip)
            {
                isoMetadata.AppendLine("Rock Ridge Interchange Protocol present.");
            }
            if (aaip)
            {
                isoMetadata.AppendLine("Arbitrary Attribute Interchange Protocol present.");
            }
            if (ziso)
            {
                isoMetadata.AppendLine("zisofs compression present.");
            }
            if (bvd != null)
            {
                isoMetadata.AppendFormat("Disc bootable following {0} specifications.", bootSpec).AppendLine();
            }
            if (segaCd != null)
            {
                isoMetadata.AppendLine("This is a SegaCD / MegaCD disc.");
                isoMetadata.AppendLine(CD.Prettify(segaCd));
            }

            if (saturn != null)
            {
                isoMetadata.AppendLine("This is a Sega Saturn disc.");
                isoMetadata.AppendLine(Saturn.Prettify(saturn));
            }

            if (dreamcast != null)
            {
                isoMetadata.AppendLine("This is a Sega Dreamcast disc.");
                isoMetadata.AppendLine(Dreamcast.Prettify(dreamcast));
            }

            isoMetadata.AppendFormat("{0}------------------------------", cdi ? "---------------" : "").AppendLine();
            isoMetadata.AppendFormat("{0}VOLUME DESCRIPTOR INFORMATION:", cdi ? "FILE STRUCTURE " : "").AppendLine();
            isoMetadata.AppendFormat("{0}------------------------------", cdi ? "---------------" : "").AppendLine();
            isoMetadata.AppendFormat("System identifier: {0}", decodedVd.SystemIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume identifier: {0}", decodedVd.VolumeIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume set identifier: {0}", decodedVd.VolumeSetIdentifier).AppendLine();
            isoMetadata.AppendFormat("Publisher identifier: {0}", decodedVd.PublisherIdentifier).AppendLine();
            isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedVd.DataPreparerIdentifier).AppendLine();
            isoMetadata.AppendFormat("Application identifier: {0}", decodedVd.ApplicationIdentifier).AppendLine();
            isoMetadata.AppendFormat("Volume creation date: {0}", decodedVd.CreationTime).AppendLine();
            if (decodedVd.HasModificationTime)
            {
                isoMetadata.AppendFormat("Volume modification date: {0}", decodedVd.ModificationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
            }
            if (decodedVd.HasExpirationTime)
            {
                isoMetadata.AppendFormat("Volume expiration date: {0}", decodedVd.ExpirationTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
            }
            if (decodedVd.HasEffectiveTime)
            {
                isoMetadata.AppendFormat("Volume effective date: {0}", decodedVd.EffectiveTime).AppendLine();
            }
            else
            {
                isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
            }
            isoMetadata.AppendFormat("Volume has {0} blocks of {1} bytes each", decodedVd.Blocks, decodedVd.BlockSize)
            .AppendLine();

            if (jolietvd != null)
            {
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendLine("JOLIET VOLUME DESCRIPTOR INFORMATION:");
                isoMetadata.AppendLine("-------------------------------------");
                isoMetadata.AppendFormat("System identifier: {0}", decodedJolietVd.SystemIdentifier).AppendLine();
                isoMetadata.AppendFormat("Volume identifier: {0}", decodedJolietVd.VolumeIdentifier).AppendLine();
                isoMetadata.AppendFormat("Volume set identifier: {0}", decodedJolietVd.VolumeSetIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Publisher identifier: {0}", decodedJolietVd.PublisherIdentifier).AppendLine();
                isoMetadata.AppendFormat("Data preparer identifier: {0}", decodedJolietVd.DataPreparerIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Application identifier: {0}", decodedJolietVd.ApplicationIdentifier)
                .AppendLine();
                isoMetadata.AppendFormat("Volume creation date: {0}", decodedJolietVd.CreationTime).AppendLine();
                if (decodedJolietVd.HasModificationTime)
                {
                    isoMetadata.AppendFormat("Volume modification date: {0}", decodedJolietVd.ModificationTime)
                    .AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has not been modified.").AppendLine();
                }
                if (decodedJolietVd.HasExpirationTime)
                {
                    isoMetadata.AppendFormat("Volume expiration date: {0}", decodedJolietVd.ExpirationTime)
                    .AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume does not expire.").AppendLine();
                }
                if (decodedJolietVd.HasEffectiveTime)
                {
                    isoMetadata.AppendFormat("Volume effective date: {0}", decodedJolietVd.EffectiveTime).AppendLine();
                }
                else
                {
                    isoMetadata.AppendFormat("Volume has always been effective.").AppendLine();
                }
            }

            if (torito != null)
            {
                vdSector = imagePlugin.ReadSector(torito.Value.catalog_sector + partition.Start);

                int toritoOff = 0;

                if (vdSector[toritoOff] != 1)
                {
                    goto exit_torito;
                }

                IntPtr ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE);
                Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE);
                ElToritoValidationEntry valentry =
                    (ElToritoValidationEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoValidationEntry));
                Marshal.FreeHGlobal(ptr);

                if (valentry.signature != EL_TORITO_MAGIC)
                {
                    goto exit_torito;
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE);
                Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE);
                ElToritoInitialEntry initialEntry =
                    (ElToritoInitialEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoInitialEntry));
                Marshal.FreeHGlobal(ptr);
                initialEntry.boot_type = (ElToritoEmulation)((byte)initialEntry.boot_type & 0xF);

                DicConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.load_rba = {0}",
                                          initialEntry.load_rba);
                DicConsole.DebugWriteLine("DEBUG (ISO9660 plugin)", "initialEntry.sector_count = {0}",
                                          initialEntry.sector_count);

                byte[] bootImage =
                    initialEntry.load_rba + partition.Start + initialEntry.sector_count - 1 <= partition.End
                        ? imagePlugin.ReadSectors(initialEntry.load_rba + partition.Start, initialEntry.sector_count)
                        : null;

                isoMetadata.AppendLine("----------------------");
                isoMetadata.AppendLine("EL TORITO INFORMATION:");
                isoMetadata.AppendLine("----------------------");

                isoMetadata.AppendLine("Initial entry:");
                isoMetadata.AppendFormat("\tDeveloper ID: {0}", Encoding.GetString(valentry.developer_id)).AppendLine();
                if (initialEntry.bootable == ElToritoIndicator.Bootable)
                {
                    isoMetadata.AppendFormat("\tBootable on {0}", valentry.platform_id).AppendLine();
                    isoMetadata.AppendFormat("\tBootable image starts at sector {0} and runs for {1} sectors",
                                             initialEntry.load_rba, initialEntry.sector_count).AppendLine();
                    if (valentry.platform_id == ElToritoPlatform.x86)
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at segment {0:X4}h",
                                                 initialEntry.load_seg == 0 ? 0x7C0 : initialEntry.load_seg)
                        .AppendLine();
                    }
                    else
                    {
                        isoMetadata.AppendFormat("\tBootable image will be loaded at 0x{0:X8}",
                                                 (uint)initialEntry.load_seg * 10).AppendLine();
                    }
                    switch (initialEntry.boot_type)
                    {
                    case ElToritoEmulation.None:
                        isoMetadata.AppendLine("\tImage uses no emulation");
                        break;

                    case ElToritoEmulation.Md2hd:
                        isoMetadata.AppendLine("\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");
                        break;

                    case ElToritoEmulation.Mf2hd:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");
                        break;

                    case ElToritoEmulation.Mf2ed:
                        isoMetadata.AppendLine("\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");
                        break;

                    default:
                        isoMetadata.AppendFormat("\tImage uses unknown emulation type {0}",
                                                 (byte)initialEntry.boot_type).AppendLine();
                        break;
                    }

                    isoMetadata.AppendFormat("\tSystem type: 0x{0:X2}", initialEntry.system_type).AppendLine();
                    if (bootImage != null)
                    {
                        isoMetadata.AppendFormat("\tBootable image's SHA1: {0}", Sha1Context.Data(bootImage, out _))
                        .AppendLine();
                    }
                }
                else
                {
                    isoMetadata.AppendLine("\tNot bootable");
                }

                toritoOff += EL_TORITO_ENTRY_SIZE;

                const int SECTION_COUNTER = 2;

                while (toritoOff < vdSector.Length && (vdSector[toritoOff] == (byte)ElToritoIndicator.Header ||
                                                       vdSector[toritoOff] == (byte)ElToritoIndicator.LastHeader))
                {
                    ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE);
                    Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE);
                    ElToritoSectionHeaderEntry sectionHeader =
                        (ElToritoSectionHeaderEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionHeaderEntry));
                    Marshal.FreeHGlobal(ptr);
                    toritoOff += EL_TORITO_ENTRY_SIZE;

                    isoMetadata.AppendFormat("Boot section {0}:", SECTION_COUNTER);
                    isoMetadata.AppendFormat("\tSection ID: {0}", Encoding.GetString(sectionHeader.identifier))
                    .AppendLine();

                    for (int entryCounter = 1; entryCounter <= sectionHeader.entries && toritoOff < vdSector.Length;
                         entryCounter++)
                    {
                        ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE);
                        Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE);
                        ElToritoSectionEntry sectionEntry =
                            (ElToritoSectionEntry)Marshal.PtrToStructure(ptr, typeof(ElToritoSectionEntry));
                        Marshal.FreeHGlobal(ptr);
                        toritoOff += EL_TORITO_ENTRY_SIZE;

                        isoMetadata.AppendFormat("\tEntry {0}:", entryCounter);
                        if (sectionEntry.bootable == ElToritoIndicator.Bootable)
                        {
                            bootImage =
                                sectionEntry.load_rba + partition.Start + sectionEntry.sector_count - 1 <= partition.End
                                    ? imagePlugin.ReadSectors(sectionEntry.load_rba + partition.Start,
                                                              sectionEntry.sector_count)
                                    : null;

                            isoMetadata.AppendFormat("\t\tBootable on {0}", sectionHeader.platform_id).AppendLine();
                            isoMetadata.AppendFormat("\t\tBootable image starts at sector {0} and runs for {1} sectors",
                                                     sectionEntry.load_rba, sectionEntry.sector_count).AppendLine();
                            if (valentry.platform_id == ElToritoPlatform.x86)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at segment {0:X4}h",
                                                         sectionEntry.load_seg == 0 ? 0x7C0 : sectionEntry.load_seg)
                                .AppendLine();
                            }
                            else
                            {
                                isoMetadata.AppendFormat("\t\tBootable image will be loaded at 0x{0:X8}",
                                                         (uint)sectionEntry.load_seg * 10).AppendLine();
                            }
                            switch ((ElToritoEmulation)((byte)sectionEntry.boot_type & 0xF))
                            {
                            case ElToritoEmulation.None:
                                isoMetadata.AppendLine("\t\tImage uses no emulation");
                                break;

                            case ElToritoEmulation.Md2hd:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 5.25\" high-density (MD2HD, 1.2Mb) floppy");
                                break;

                            case ElToritoEmulation.Mf2hd:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 3.5\" high-density (MF2HD, 1.44Mb) floppy");
                                break;

                            case ElToritoEmulation.Mf2ed:
                                isoMetadata
                                .AppendLine("\t\tImage emulates a 3.5\" extra-density (MF2ED, 2.88Mb) floppy");
                                break;

                            default:
                                isoMetadata.AppendFormat("\t\tImage uses unknown emulation type {0}",
                                                         (byte)initialEntry.boot_type).AppendLine();
                                break;
                            }

                            isoMetadata.AppendFormat("\t\tSelection criteria type: {0}",
                                                     sectionEntry.selection_criteria_type).AppendLine();
                            isoMetadata.AppendFormat("\t\tSystem type: 0x{0:X2}", sectionEntry.system_type)
                            .AppendLine();
                            if (bootImage != null)
                            {
                                isoMetadata.AppendFormat("\t\tBootable image's SHA1: {0}",
                                                         Sha1Context.Data(bootImage, out _)).AppendLine();
                            }
                        }
                        else
                        {
                            isoMetadata.AppendLine("\t\tNot bootable");
                        }

                        ElToritoFlags flags = (ElToritoFlags)((byte)sectionEntry.boot_type & 0xF0);
                        if (flags.HasFlag(ElToritoFlags.ATAPI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains ATAPI drivers");
                        }
                        if (flags.HasFlag(ElToritoFlags.SCSI))
                        {
                            isoMetadata.AppendLine("\t\tImage contains SCSI drivers");
                        }

                        if (!flags.HasFlag(ElToritoFlags.Continued))
                        {
                            continue;
                        }

                        while (toritoOff < vdSector.Length)
                        {
                            ptr = Marshal.AllocHGlobal(EL_TORITO_ENTRY_SIZE);
                            Marshal.Copy(vdSector, toritoOff, ptr, EL_TORITO_ENTRY_SIZE);
                            ElToritoSectionEntryExtension sectionExtension =
                                (ElToritoSectionEntryExtension)
                                Marshal.PtrToStructure(ptr, typeof(ElToritoSectionEntryExtension));
                            Marshal.FreeHGlobal(ptr);
                            toritoOff += EL_TORITO_ENTRY_SIZE;

                            if (!sectionExtension.extension_flags.HasFlag(ElToritoFlags.Continued))
                            {
                                break;
                            }
                        }
                    }

                    if (sectionHeader.header_id == ElToritoIndicator.LastHeader)
                    {
                        break;
                    }
                }
            }

exit_torito:
            if (refareas.Count > 0)
            {
                isoMetadata.Append(suspInformation);
            }

            XmlFsType.Type = fsFormat;

            if (jolietvd != null)
            {
                XmlFsType.VolumeName = decodedJolietVd.VolumeIdentifier;

                if (decodedJolietVd.SystemIdentifier == null ||
                    decodedVd.SystemIdentifier.Length > decodedJolietVd.SystemIdentifier.Length)
                {
                    XmlFsType.SystemIdentifier = decodedVd.SystemIdentifier;
                }
                else
                {
                    XmlFsType.SystemIdentifier = decodedJolietVd.SystemIdentifier;
                }

                if (decodedJolietVd.VolumeSetIdentifier == null || decodedVd.VolumeSetIdentifier.Length >
                    decodedJolietVd.VolumeSetIdentifier.Length)
                {
                    XmlFsType.VolumeSetIdentifier = decodedVd.VolumeSetIdentifier;
                }
                else
                {
                    XmlFsType.VolumeSetIdentifier = decodedJolietVd.VolumeSetIdentifier;
                }

                if (decodedJolietVd.PublisherIdentifier == null || decodedVd.PublisherIdentifier.Length >
                    decodedJolietVd.PublisherIdentifier.Length)
                {
                    XmlFsType.PublisherIdentifier = decodedVd.PublisherIdentifier;
                }
                else
                {
                    XmlFsType.PublisherIdentifier = decodedJolietVd.PublisherIdentifier;
                }

                if (decodedJolietVd.DataPreparerIdentifier == null || decodedVd.DataPreparerIdentifier.Length >
                    decodedJolietVd.DataPreparerIdentifier.Length)
                {
                    XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                }
                else
                {
                    XmlFsType.DataPreparerIdentifier = decodedJolietVd.SystemIdentifier;
                }

                if (decodedJolietVd.ApplicationIdentifier == null || decodedVd.ApplicationIdentifier.Length >
                    decodedJolietVd.ApplicationIdentifier.Length)
                {
                    XmlFsType.ApplicationIdentifier = decodedVd.ApplicationIdentifier;
                }
                else
                {
                    XmlFsType.ApplicationIdentifier = decodedJolietVd.SystemIdentifier;
                }

                XmlFsType.CreationDate          = decodedJolietVd.CreationTime;
                XmlFsType.CreationDateSpecified = true;
                if (decodedJolietVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedJolietVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedJolietVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedJolietVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedJolietVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedJolietVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }
            else
            {
                XmlFsType.SystemIdentifier       = decodedVd.SystemIdentifier;
                XmlFsType.VolumeName             = decodedVd.VolumeIdentifier;
                XmlFsType.VolumeSetIdentifier    = decodedVd.VolumeSetIdentifier;
                XmlFsType.PublisherIdentifier    = decodedVd.PublisherIdentifier;
                XmlFsType.DataPreparerIdentifier = decodedVd.DataPreparerIdentifier;
                XmlFsType.ApplicationIdentifier  = decodedVd.ApplicationIdentifier;
                XmlFsType.CreationDate           = decodedVd.CreationTime;
                XmlFsType.CreationDateSpecified  = true;
                if (decodedVd.HasModificationTime)
                {
                    XmlFsType.ModificationDate          = decodedVd.ModificationTime;
                    XmlFsType.ModificationDateSpecified = true;
                }

                if (decodedVd.HasExpirationTime)
                {
                    XmlFsType.ExpirationDate          = decodedVd.ExpirationTime;
                    XmlFsType.ExpirationDateSpecified = true;
                }

                if (decodedVd.HasEffectiveTime)
                {
                    XmlFsType.EffectiveDate          = decodedVd.EffectiveTime;
                    XmlFsType.EffectiveDateSpecified = true;
                }
            }

            XmlFsType.Bootable   |= bvd != null || segaCd != null || saturn != null || dreamcast != null;
            XmlFsType.Clusters    = decodedVd.Blocks;
            XmlFsType.ClusterSize = decodedVd.BlockSize;

            information = isoMetadata.ToString();
        }
Ejemplo n.º 14
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("ibm850");
            information = "";

            var sb = new StringBuilder();

            byte[] hpfsBpbSector =
                imagePlugin.ReadSector(0 + partition.Start); // Seek to BIOS parameter block, on logical sector 0

            byte[] hpfsSbSector =
                imagePlugin.ReadSector(16 + partition.Start); // Seek to superblock, on logical sector 16

            byte[] hpfsSpSector =
                imagePlugin.ReadSector(17 + partition.Start); // Seek to spareblock, on logical sector 17

            BiosParameterBlock bpb = Marshal.ByteArrayToStructureLittleEndian <BiosParameterBlock>(hpfsBpbSector);

            SuperBlock hpfsSb = Marshal.ByteArrayToStructureLittleEndian <SuperBlock>(hpfsSbSector);

            SpareBlock sp = Marshal.ByteArrayToStructureLittleEndian <SpareBlock>(hpfsSpSector);

            if (StringHandlers.CToString(bpb.fs_type) != "HPFS    " ||
                hpfsSb.magic1 != 0xF995E849 ||
                hpfsSb.magic2 != 0xFA53E9C5 ||
                sp.magic1 != 0xF9911849 ||
                sp.magic2 != 0xFA5229C5)
            {
                sb.AppendLine("This may not be HPFS, following information may be not correct.");
                sb.AppendFormat("File system type: \"{0}\" (Should be \"HPFS    \")", bpb.fs_type).AppendLine();
                sb.AppendFormat("Superblock magic1: 0x{0:X8} (Should be 0xF995E849)", hpfsSb.magic1).AppendLine();
                sb.AppendFormat("Superblock magic2: 0x{0:X8} (Should be 0xFA53E9C5)", hpfsSb.magic2).AppendLine();
                sb.AppendFormat("Spareblock magic1: 0x{0:X8} (Should be 0xF9911849)", sp.magic1).AppendLine();
                sb.AppendFormat("Spareblock magic2: 0x{0:X8} (Should be 0xFA5229C5)", sp.magic2).AppendLine();
            }

            sb.AppendFormat("OEM name: {0}", StringHandlers.CToString(bpb.oem_name)).AppendLine();
            sb.AppendFormat("{0} bytes per sector", bpb.bps).AppendLine();

            //          sb.AppendFormat("{0} sectors per cluster", hpfs_bpb.spc).AppendLine();
            //          sb.AppendFormat("{0} reserved sectors", hpfs_bpb.rsectors).AppendLine();
            //          sb.AppendFormat("{0} FATs", hpfs_bpb.fats_no).AppendLine();
            //          sb.AppendFormat("{0} entries on root directory", hpfs_bpb.root_ent).AppendLine();
            //          sb.AppendFormat("{0} mini sectors on volume", hpfs_bpb.sectors).AppendLine();
            sb.AppendFormat("Media descriptor: 0x{0:X2}", bpb.media).AppendLine();

            //          sb.AppendFormat("{0} sectors per FAT", hpfs_bpb.spfat).AppendLine();
            //          sb.AppendFormat("{0} sectors per track", hpfs_bpb.sptrk).AppendLine();
            //          sb.AppendFormat("{0} heads", hpfs_bpb.heads).AppendLine();
            sb.AppendFormat("{0} sectors hidden before BPB", bpb.hsectors).AppendLine();

            sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfsSb.sectors, hpfsSb.sectors * bpb.bps).AppendLine();

            //          sb.AppendFormat("{0} sectors on volume ({1} bytes)", hpfs_bpb.big_sectors, hpfs_bpb.big_sectors * hpfs_bpb.bps).AppendLine();
            sb.AppendFormat("BIOS Drive Number: 0x{0:X2}", bpb.drive_no).AppendLine();
            sb.AppendFormat("NT Flags: 0x{0:X2}", bpb.nt_flags).AppendLine();
            sb.AppendFormat("Signature: 0x{0:X2}", bpb.signature).AppendLine();
            sb.AppendFormat("Serial number: 0x{0:X8}", bpb.serial_no).AppendLine();
            sb.AppendFormat("Volume label: {0}", StringHandlers.CToString(bpb.volume_label, Encoding)).AppendLine();

            //          sb.AppendFormat("Filesystem type: \"{0}\"", hpfs_bpb.fs_type).AppendLine();

            DateTime lastChk   = DateHandlers.UnixToDateTime(hpfsSb.last_chkdsk);
            DateTime lastOptim = DateHandlers.UnixToDateTime(hpfsSb.last_optim);

            sb.AppendFormat("HPFS version: {0}", hpfsSb.version).AppendLine();
            sb.AppendFormat("Functional version: {0}", hpfsSb.func_version).AppendLine();
            sb.AppendFormat("Sector of root directory FNode: {0}", hpfsSb.root_fnode).AppendLine();
            sb.AppendFormat("{0} sectors are marked bad", hpfsSb.badblocks).AppendLine();
            sb.AppendFormat("Sector of free space bitmaps: {0}", hpfsSb.bitmap_lsn).AppendLine();
            sb.AppendFormat("Sector of bad blocks list: {0}", hpfsSb.badblock_lsn).AppendLine();

            if (hpfsSb.last_chkdsk > 0)
            {
                sb.AppendFormat("Date of last integrity check: {0}", lastChk).AppendLine();
            }
            else
            {
                sb.AppendLine("Filesystem integrity has never been checked");
            }

            if (hpfsSb.last_optim > 0)
            {
                sb.AppendFormat("Date of last optimization {0}", lastOptim).AppendLine();
            }
            else
            {
                sb.AppendLine("Filesystem has never been optimized");
            }

            sb.AppendFormat("Directory band has {0} sectors", hpfsSb.dband_sectors).AppendLine();
            sb.AppendFormat("Directory band starts at sector {0}", hpfsSb.dband_start).AppendLine();
            sb.AppendFormat("Directory band ends at sector {0}", hpfsSb.dband_last).AppendLine();
            sb.AppendFormat("Sector of directory band bitmap: {0}", hpfsSb.dband_bitmap).AppendLine();
            sb.AppendFormat("Sector of ACL directory: {0}", hpfsSb.acl_start).AppendLine();

            sb.AppendFormat("Sector of Hotfix directory: {0}", sp.hotfix_start).AppendLine();
            sb.AppendFormat("{0} used Hotfix entries", sp.hotfix_used).AppendLine();
            sb.AppendFormat("{0} total Hotfix entries", sp.hotfix_entries).AppendLine();
            sb.AppendFormat("{0} free spare DNodes", sp.spare_dnodes_free).AppendLine();
            sb.AppendFormat("{0} total spare DNodes", sp.spare_dnodes).AppendLine();
            sb.AppendFormat("Sector of codepage directory: {0}", sp.codepage_lsn).AppendLine();
            sb.AppendFormat("{0} codepages used in the volume", sp.codepages).AppendLine();
            sb.AppendFormat("SuperBlock CRC32: {0:X8}", sp.sb_crc32).AppendLine();
            sb.AppendFormat("SpareBlock CRC32: {0:X8}", sp.sp_crc32).AppendLine();

            sb.AppendLine("Flags:");
            sb.AppendLine((sp.flags1 & 0x01) == 0x01 ? "Filesystem is dirty." : "Filesystem is clean.");

            if ((sp.flags1 & 0x02) == 0x02)
            {
                sb.AppendLine("Spare directory blocks are in use");
            }

            if ((sp.flags1 & 0x04) == 0x04)
            {
                sb.AppendLine("Hotfixes are in use");
            }

            if ((sp.flags1 & 0x08) == 0x08)
            {
                sb.AppendLine("Disk contains bad sectors");
            }

            if ((sp.flags1 & 0x10) == 0x10)
            {
                sb.AppendLine("Disk has a bad bitmap");
            }

            if ((sp.flags1 & 0x20) == 0x20)
            {
                sb.AppendLine("Filesystem was formatted fast");
            }

            if ((sp.flags1 & 0x40) == 0x40)
            {
                sb.AppendLine("Unknown flag 0x40 on flags1 is active");
            }

            if ((sp.flags1 & 0x80) == 0x80)
            {
                sb.AppendLine("Filesystem has been mounted by an old IFS");
            }

            if ((sp.flags2 & 0x01) == 0x01)
            {
                sb.AppendLine("Install DASD limits");
            }

            if ((sp.flags2 & 0x02) == 0x02)
            {
                sb.AppendLine("Resync DASD limits");
            }

            if ((sp.flags2 & 0x04) == 0x04)
            {
                sb.AppendLine("DASD limits are operational");
            }

            if ((sp.flags2 & 0x08) == 0x08)
            {
                sb.AppendLine("Multimedia is active");
            }

            if ((sp.flags2 & 0x10) == 0x10)
            {
                sb.AppendLine("DCE ACLs are active");
            }

            if ((sp.flags2 & 0x20) == 0x20)
            {
                sb.AppendLine("DASD limits are dirty");
            }

            if ((sp.flags2 & 0x40) == 0x40)
            {
                sb.AppendLine("Unknown flag 0x40 on flags2 is active");
            }

            if ((sp.flags2 & 0x80) == 0x80)
            {
                sb.AppendLine("Unknown flag 0x80 on flags2 is active");
            }

            XmlFsType = new FileSystemType();

            // Theoretically everything from BPB to SB is boot code, should I hash everything or only the sector loaded by BIOS itself?
            if (bpb.jump[0] == 0xEB &&
                bpb.jump[1] > 0x3C &&
                bpb.jump[1] < 0x80 &&
                bpb.signature2 == 0xAA55)
            {
                XmlFsType.Bootable = true;
                string bootChk = Sha1Context.Data(bpb.boot_code, out byte[] _);
                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
            }

            XmlFsType.Dirty           |= (sp.flags1 & 0x01) == 0x01;
            XmlFsType.Clusters         = hpfsSb.sectors;
            XmlFsType.ClusterSize      = bpb.bps;
            XmlFsType.Type             = "HPFS";
            XmlFsType.VolumeName       = StringHandlers.CToString(bpb.volume_label, Encoding);
            XmlFsType.VolumeSerial     = $"{bpb.serial_no:X8}";
            XmlFsType.SystemIdentifier = StringHandlers.CToString(bpb.oem_name);

            information = sb.ToString();
        }
Ejemplo n.º 15
0
        public bool Open(IFilter imageFilter)
        {
            Stream imageStream = imageFilter.GetDataForkStream();

            byte[] header = new byte[512];
            byte[] footer;

            imageStream.Seek(0, SeekOrigin.Begin);
            imageStream.Read(header, 0, 512);

            if (imageStream.Length % 2 == 0)
            {
                footer = new byte[512];
                imageStream.Seek(-512, SeekOrigin.End);
                imageStream.Read(footer, 0, 512);
            }
            else
            {
                footer = new byte[511];
                imageStream.Seek(-511, SeekOrigin.End);
                imageStream.Read(footer, 0, 511);
            }

            BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

            uint  headerChecksum = BigEndianBitConverter.ToUInt32(header, 0x40);
            uint  footerChecksum = BigEndianBitConverter.ToUInt32(footer, 0x40);
            ulong headerCookie   = BigEndianBitConverter.ToUInt64(header, 0);
            ulong footerCookie   = BigEndianBitConverter.ToUInt64(footer, 0);

            header[0x40] = 0;
            header[0x41] = 0;
            header[0x42] = 0;
            header[0x43] = 0;
            footer[0x40] = 0;
            footer[0x41] = 0;
            footer[0x42] = 0;
            footer[0x43] = 0;

            uint headerCalculatedChecksum = VhdChecksum(header);
            uint footerCalculatedChecksum = VhdChecksum(footer);

            DicConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}",
                                      headerChecksum, headerCalculatedChecksum);
            DicConsole.DebugWriteLine("VirtualPC plugin", "Header checksum = 0x{0:X8}, calculated = 0x{1:X8}",
                                      footerChecksum, footerCalculatedChecksum);

            byte[] usableHeader;
            uint   usableChecksum;

            if (headerCookie == IMAGE_COOKIE && headerChecksum == headerCalculatedChecksum)
            {
                usableHeader   = header;
                usableChecksum = headerChecksum;
            }
            else if (footerCookie == IMAGE_COOKIE && footerChecksum == footerCalculatedChecksum)
            {
                usableHeader   = footer;
                usableChecksum = footerChecksum;
            }
            else
            {
                throw new
                      ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened.");
            }

            thisFooter = new HardDiskFooter
            {
                Cookie             = BigEndianBitConverter.ToUInt64(usableHeader, 0x00),
                Features           = BigEndianBitConverter.ToUInt32(usableHeader, 0x08),
                Version            = BigEndianBitConverter.ToUInt32(usableHeader, 0x0C),
                Offset             = BigEndianBitConverter.ToUInt64(usableHeader, 0x10),
                Timestamp          = BigEndianBitConverter.ToUInt32(usableHeader, 0x18),
                CreatorApplication = BigEndianBitConverter.ToUInt32(usableHeader, 0x1C),
                CreatorVersion     = BigEndianBitConverter.ToUInt32(usableHeader, 0x20),
                CreatorHostOs      = BigEndianBitConverter.ToUInt32(usableHeader, 0x24),
                OriginalSize       = BigEndianBitConverter.ToUInt64(usableHeader, 0x28),
                CurrentSize        = BigEndianBitConverter.ToUInt64(usableHeader, 0x30),
                DiskGeometry       = BigEndianBitConverter.ToUInt32(usableHeader, 0x38),
                DiskType           = BigEndianBitConverter.ToUInt32(usableHeader, 0x3C),
                Checksum           = usableChecksum,
                UniqueId           = BigEndianBitConverter.ToGuid(usableHeader, 0x44),
                SavedState         = usableHeader[0x54],
                Reserved           = new byte[usableHeader.Length - 0x55]
            };
            Array.Copy(usableHeader, 0x55, thisFooter.Reserved, 0, usableHeader.Length - 0x55);

            thisDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            thisDateTime = thisDateTime.AddSeconds(thisFooter.Timestamp);

            Sha1Context sha1Ctx = new Sha1Context();

            sha1Ctx.Update(thisFooter.Reserved);

            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.cookie = 0x{0:X8}", thisFooter.Cookie);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.features = 0x{0:X8}", thisFooter.Features);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.version = 0x{0:X8}", thisFooter.Version);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.offset = {0}", thisFooter.Offset);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.timestamp = 0x{0:X8} ({1})", thisFooter.Timestamp,
                                      thisDateTime);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorApplication = 0x{0:X8} (\"{1}\")",
                                      thisFooter.CreatorApplication,
                                      Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter
                                                                                              .CreatorApplication)));
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorVersion = 0x{0:X8}",
                                      thisFooter.CreatorVersion);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.creatorHostOS = 0x{0:X8} (\"{1}\")",
                                      thisFooter.CreatorHostOs,
                                      Encoding.ASCII.GetString(BigEndianBitConverter
                                                               .GetBytes(thisFooter.CreatorHostOs)));
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.originalSize = {0}", thisFooter.OriginalSize);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.currentSize = {0}", thisFooter.CurrentSize);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.diskGeometry = 0x{0:X8} (C/H/S: {1}/{2}/{3})",
                                      thisFooter.DiskGeometry, (thisFooter.DiskGeometry & 0xFFFF0000) >> 16,
                                      (thisFooter.DiskGeometry & 0xFF00) >> 8,
                                      thisFooter.DiskGeometry & 0xFF);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.diskType = 0x{0:X8}", thisFooter.DiskType);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.checksum = 0x{0:X8}", thisFooter.Checksum);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.uniqueId = {0}", thisFooter.UniqueId);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.savedState = 0x{0:X2}", thisFooter.SavedState);
            DicConsole.DebugWriteLine("VirtualPC plugin", "footer.reserved's SHA1 = 0x{0}", sha1Ctx.End());

            if (thisFooter.Version == VERSION1)
            {
                imageInfo.Version = "1.0";
            }
            else
            {
                throw new
                      ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image.");
            }

            switch (thisFooter.CreatorApplication)
            {
            case CREATOR_QEMU:
            {
                imageInfo.Application = "QEMU";
                // QEMU always set same version
                imageInfo.ApplicationVersion = "Unknown";

                break;
            }

            case CREATOR_VIRTUAL_BOX:
            {
                imageInfo.ApplicationVersion =
                    $"{(thisFooter.CreatorVersion & 0xFFFF0000) >> 16}.{thisFooter.CreatorVersion & 0x0000FFFF:D2}";
                switch (thisFooter.CreatorHostOs)
                {
                case CREATOR_MACINTOSH:
                case CREATOR_MACINTOSH_OLD:
                    imageInfo.Application = "VirtualBox for Mac";
                    break;

                case CREATOR_WINDOWS:
                    // VirtualBox uses Windows creator for any other OS
                    imageInfo.Application = "VirtualBox";
                    break;

                default:
                    imageInfo.Application =
                        $"VirtualBox for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
                    break;
                }

                break;
            }

            case CREATOR_VIRTUAL_SERVER:
            {
                imageInfo.Application = "Microsoft Virtual Server";
                switch (thisFooter.CreatorVersion)
                {
                case VERSION_VIRTUAL_SERVER2004:
                    imageInfo.ApplicationVersion = "2004";
                    break;

                default:
                    imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                    break;
                }

                break;
            }

            case CREATOR_VIRTUAL_PC:
            {
                switch (thisFooter.CreatorHostOs)
                {
                case CREATOR_MACINTOSH:
                case CREATOR_MACINTOSH_OLD:
                    switch (thisFooter.CreatorVersion)
                    {
                    case VERSION_VIRTUAL_PC_MAC:
                        imageInfo.Application        = "Connectix Virtual PC";
                        imageInfo.ApplicationVersion = "5, 6 or 7";
                        break;

                    default:
                        imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                        break;
                    }

                    break;

                case CREATOR_WINDOWS:
                    switch (thisFooter.CreatorVersion)
                    {
                    case VERSION_VIRTUAL_PC_MAC:
                        imageInfo.Application        = "Connectix Virtual PC";
                        imageInfo.ApplicationVersion = "5, 6 or 7";
                        break;

                    case VERSION_VIRTUAL_PC2004:
                        imageInfo.Application        = "Microsoft Virtual PC";
                        imageInfo.ApplicationVersion = "2004";
                        break;

                    case VERSION_VIRTUAL_PC2007:
                        imageInfo.Application        = "Microsoft Virtual PC";
                        imageInfo.ApplicationVersion = "2007";
                        break;

                    default:
                        imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                        break;
                    }

                    break;

                default:
                    imageInfo.Application =
                        $"Virtual PC for unknown OS \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
                    imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                    break;
                }

                break;
            }

            case CREATOR_DISCIMAGECHEF:
            {
                imageInfo.Application        = "DiscImageChef";
                imageInfo.ApplicationVersion =
                    $"{(thisFooter.CreatorVersion & 0xFF000000) >> 24}.{(thisFooter.CreatorVersion & 0xFF0000) >> 16}.{(thisFooter.CreatorVersion & 0xFF00) >> 8}.{thisFooter.CreatorVersion & 0xFF}";
            }
            break;

            default:
            {
                imageInfo.Application =
                    $"Unknown application \"{Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisFooter.CreatorHostOs))}\"";
                imageInfo.ApplicationVersion = $"Unknown version 0x{thisFooter.CreatorVersion:X8}";
                break;
            }
            }

            thisFilter           = imageFilter;
            imageInfo.ImageSize  = thisFooter.CurrentSize;
            imageInfo.Sectors    = thisFooter.CurrentSize / 512;
            imageInfo.SectorSize = 512;

            imageInfo.CreationTime         = imageFilter.GetCreationTime();
            imageInfo.LastModificationTime = thisDateTime;
            imageInfo.MediaTitle           = Path.GetFileNameWithoutExtension(imageFilter.GetFilename());

            imageInfo.Cylinders       = (thisFooter.DiskGeometry & 0xFFFF0000) >> 16;
            imageInfo.Heads           = (thisFooter.DiskGeometry & 0xFF00) >> 8;
            imageInfo.SectorsPerTrack = thisFooter.DiskGeometry & 0xFF;

            if (thisFooter.DiskType == TYPE_DYNAMIC || thisFooter.DiskType == TYPE_DIFFERENCING)
            {
                imageStream.Seek((long)thisFooter.Offset, SeekOrigin.Begin);
                byte[] dynamicBytes = new byte[1024];
                imageStream.Read(dynamicBytes, 0, 1024);

                uint dynamicChecksum = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x24);

                dynamicBytes[0x24] = 0;
                dynamicBytes[0x25] = 0;
                dynamicBytes[0x26] = 0;
                dynamicBytes[0x27] = 0;

                uint dynamicChecksumCalculated = VhdChecksum(dynamicBytes);

                DicConsole.DebugWriteLine("VirtualPC plugin",
                                          "Dynamic header checksum = 0x{0:X8}, calculated = 0x{1:X8}", dynamicChecksum,
                                          dynamicChecksumCalculated);

                if (dynamicChecksum != dynamicChecksumCalculated)
                {
                    throw new
                          ImageNotSupportedException("(VirtualPC plugin): Both header and footer are corrupt, image cannot be opened.");
                }

                thisDynamic =
                    new DynamicDiskHeader {
                    LocatorEntries = new ParentLocatorEntry[8], Reserved2 = new byte[256]
                };

                for (int i = 0; i < 8; i++)
                {
                    thisDynamic.LocatorEntries[i] = new ParentLocatorEntry();
                }

                thisDynamic.Cookie          = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x00);
                thisDynamic.DataOffset      = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x08);
                thisDynamic.TableOffset     = BigEndianBitConverter.ToUInt64(dynamicBytes, 0x10);
                thisDynamic.HeaderVersion   = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x18);
                thisDynamic.MaxTableEntries = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x1C);
                thisDynamic.BlockSize       = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x20);
                thisDynamic.Checksum        = dynamicChecksum;
                thisDynamic.ParentId        = BigEndianBitConverter.ToGuid(dynamicBytes, 0x28);
                thisDynamic.ParentTimestamp = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x38);
                thisDynamic.Reserved        = BigEndianBitConverter.ToUInt32(dynamicBytes, 0x3C);
                thisDynamic.ParentName      = Encoding.BigEndianUnicode.GetString(dynamicBytes, 0x40, 512);

                for (int i = 0; i < 8; i++)
                {
                    thisDynamic.LocatorEntries[i].PlatformCode =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x00 + 24 * i);
                    thisDynamic.LocatorEntries[i].PlatformDataSpace =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x04 + 24 * i);
                    thisDynamic.LocatorEntries[i].PlatformDataLength =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x08 + 24 * i);
                    thisDynamic.LocatorEntries[i].Reserved =
                        BigEndianBitConverter.ToUInt32(dynamicBytes, 0x240 + 0x0C + 24 * i);
                    thisDynamic.LocatorEntries[i].PlatformDataOffset =
                        BigEndianBitConverter.ToUInt64(dynamicBytes, 0x240 + 0x10 + 24 * i);
                }

                Array.Copy(dynamicBytes, 0x300, thisDynamic.Reserved2, 0, 256);

                parentDateTime = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc);
                parentDateTime = parentDateTime.AddSeconds(thisDynamic.ParentTimestamp);

                sha1Ctx = new Sha1Context();
                sha1Ctx.Update(thisDynamic.Reserved2);

                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.cookie = 0x{0:X8}", thisDynamic.Cookie);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.dataOffset = {0}", thisDynamic.DataOffset);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.tableOffset = {0}", thisDynamic.TableOffset);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.headerVersion = 0x{0:X8}",
                                          thisDynamic.HeaderVersion);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.maxTableEntries = {0}",
                                          thisDynamic.MaxTableEntries);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.blockSize = {0}", thisDynamic.BlockSize);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.checksum = 0x{0:X8}", thisDynamic.Checksum);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentID = {0}", thisDynamic.ParentId);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentTimestamp = 0x{0:X8} ({1})",
                                          thisDynamic.ParentTimestamp, parentDateTime);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved = 0x{0:X8}", thisDynamic.Reserved);
                for (int i = 0; i < 8; i++)
                {
                    DicConsole.DebugWriteLine("VirtualPC plugin",
                                              "dynamic.locatorEntries[{0}].platformCode = 0x{1:X8} (\"{2}\")", i,
                                              thisDynamic.LocatorEntries[i].PlatformCode,
                                              Encoding.ASCII.GetString(BigEndianBitConverter.GetBytes(thisDynamic
                                                                                                      .LocatorEntries[i]
                                                                                                      .PlatformCode)));
                    DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].platformDataSpace = {1}",
                                              i, thisDynamic.LocatorEntries[i].PlatformDataSpace);
                    DicConsole.DebugWriteLine("VirtualPC plugin",
                                              "dynamic.locatorEntries[{0}].platformDataLength = {1}", i,
                                              thisDynamic.LocatorEntries[i].PlatformDataLength);
                    DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}].reserved = 0x{1:X8}", i,
                                              thisDynamic.LocatorEntries[i].Reserved);
                    DicConsole.DebugWriteLine("VirtualPC plugin",
                                              "dynamic.locatorEntries[{0}].platformDataOffset = {1}", i,
                                              thisDynamic.LocatorEntries[i].PlatformDataOffset);
                }

                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.parentName = \"{0}\"",
                                          thisDynamic.ParentName);
                DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.reserved2's SHA1 = 0x{0}", sha1Ctx.End());

                if (thisDynamic.HeaderVersion != VERSION1)
                {
                    throw new
                          ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image.");
                }

                DateTime startTime = DateTime.UtcNow;

                blockAllocationTable = new uint[thisDynamic.MaxTableEntries];

                // Safe and slow code. It takes 76,572 ms to fill a 30720 entries BAT

                /*
                 * byte[] bat = new byte[thisDynamic.maxTableEntries * 4];
                 * imageStream.Seek((long)thisDynamic.tableOffset, SeekOrigin.Begin);
                 * imageStream.Read(bat, 0, (int)(thisDynamic.maxTableEntries * 4));
                 * for (int i = 0; i < thisDynamic.maxTableEntries; i++)
                 *  blockAllocationTable[i] = BigEndianBitConverter.ToUInt32(bat, 4 * i);
                 *
                 * DateTime endTime = DateTime.UtcNow;
                 * DicConsole.DebugWriteLine("VirtualPC plugin", "Filling the BAT took {0} seconds", (endTime-startTime).TotalSeconds);
                 */

                // How many sectors uses the BAT
                uint batSectorCount = (uint)Math.Ceiling((double)thisDynamic.MaxTableEntries * 4 / 512);

                byte[] batSectorBytes = new byte[512];

                // Unsafe and fast code. It takes 4 ms to fill a 30720 entries BAT
                for (int i = 0; i < batSectorCount; i++)
                {
                    imageStream.Seek((long)thisDynamic.TableOffset + i * 512, SeekOrigin.Begin);
                    imageStream.Read(batSectorBytes, 0, 512);
                    // This does the big-endian trick but reverses the order of elements also
                    Array.Reverse(batSectorBytes);
                    GCHandle  handle    = GCHandle.Alloc(batSectorBytes, GCHandleType.Pinned);
                    BatSector batSector =
                        (BatSector)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(BatSector));
                    handle.Free();
                    // This restores the order of elements
                    Array.Reverse(batSector.blockPointer);
                    if (blockAllocationTable.Length >= i * 512 / 4 + 512 / 4)
                    {
                        Array.Copy(batSector.blockPointer, 0, blockAllocationTable, i * 512 / 4, 512 / 4);
                    }
                    else
                    {
                        Array.Copy(batSector.blockPointer, 0, blockAllocationTable, i * 512 / 4,
                                   blockAllocationTable.Length - i * 512 / 4);
                    }
                }

                DateTime endTime = DateTime.UtcNow;
                DicConsole.DebugWriteLine("VirtualPC plugin", "Filling the BAT took {0} seconds",
                                          (endTime - startTime).TotalSeconds);

                // Too noisy

                /*
                 *  for (int i = 0; i < thisDynamic.maxTableEntries; i++)
                 *      DicConsole.DebugWriteLine("VirtualPC plugin", "blockAllocationTable[{0}] = {1}", i, blockAllocationTable[i]);
                 */

                // Get the roundest number of sectors needed to store the block bitmap
                bitmapSize = (uint)Math.Ceiling((double)thisDynamic.BlockSize / 512
                                                // 1 bit per sector on the bitmap
                                                / 8
                                                // and aligned to 512 byte boundary
                                                / 512);
                DicConsole.DebugWriteLine("VirtualPC plugin", "Bitmap is {0} sectors", bitmapSize);
            }

            imageInfo.XmlMediaType = XmlMediaType.BlockMedia;

            switch (thisFooter.DiskType)
            {
            case TYPE_FIXED:
            case TYPE_DYNAMIC:
            {
                // Nothing to do here, really.
                return(true);
            }

            case TYPE_DIFFERENCING:
            {
                locatorEntriesData = new byte[8][];
                for (int i = 0; i < 8; i++)
                {
                    if (thisDynamic.LocatorEntries[i].PlatformCode != 0x00000000)
                    {
                        locatorEntriesData[i] = new byte[thisDynamic.LocatorEntries[i].PlatformDataLength];
                        imageStream.Seek((long)thisDynamic.LocatorEntries[i].PlatformDataOffset, SeekOrigin.Begin);
                        imageStream.Read(locatorEntriesData[i], 0,
                                         (int)thisDynamic.LocatorEntries[i].PlatformDataLength);

                        switch (thisDynamic.LocatorEntries[i].PlatformCode)
                        {
                        case PLATFORM_CODE_WINDOWS_ABSOLUTE:
                        case PLATFORM_CODE_WINDOWS_RELATIVE:
                            DicConsole.DebugWriteLine("VirtualPC plugin",
                                                      "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                      Encoding.ASCII.GetString(locatorEntriesData[i]));
                            break;

                        case PLATFORM_CODE_WINDOWS_ABSOLUTE_U:
                        case PLATFORM_CODE_WINDOWS_RELATIVE_U:
                            DicConsole.DebugWriteLine("VirtualPC plugin",
                                                      "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                      Encoding.BigEndianUnicode
                                                      .GetString(locatorEntriesData[i]));
                            break;

                        case PLATFORM_CODE_MACINTOSH_URI:
                            DicConsole.DebugWriteLine("VirtualPC plugin",
                                                      "dynamic.locatorEntries[{0}] = \"{1}\"", i,
                                                      Encoding.UTF8.GetString(locatorEntriesData[i]));
                            break;

                        default:
                            DicConsole.DebugWriteLine("VirtualPC plugin", "dynamic.locatorEntries[{0}] =", i);
                            PrintHex.PrintHexArray(locatorEntriesData[i], 64);
                            break;
                        }
                    }
                }

                int    currentLocator = 0;
                bool   locatorFound   = false;
                string parentPath     = null;

                while (!locatorFound && currentLocator < 8)
                {
                    switch (thisDynamic.LocatorEntries[currentLocator].PlatformCode)
                    {
                    case PLATFORM_CODE_WINDOWS_ABSOLUTE:
                    case PLATFORM_CODE_WINDOWS_RELATIVE:
                        parentPath = Encoding.ASCII.GetString(locatorEntriesData[currentLocator]);
                        break;

                    case PLATFORM_CODE_WINDOWS_ABSOLUTE_U:
                    case PLATFORM_CODE_WINDOWS_RELATIVE_U:
                        parentPath = Encoding.BigEndianUnicode.GetString(locatorEntriesData[currentLocator]);
                        break;

                    case PLATFORM_CODE_MACINTOSH_URI:
                        parentPath =
                            Uri.UnescapeDataString(Encoding.UTF8.GetString(locatorEntriesData[currentLocator]));
                        if (parentPath.StartsWith("file://localhost", StringComparison.InvariantCulture))
                        {
                            parentPath = parentPath.Remove(0, 16);
                        }
                        else
                        {
                            DicConsole.DebugWriteLine("VirtualPC plugin",
                                                      "Unsupported protocol classified found in URI parent path: \"{0}\"",
                                                      parentPath);
                            parentPath = null;
                        }

                        break;
                    }

                    if (parentPath != null)
                    {
                        DicConsole.DebugWriteLine("VirtualPC plugin", "Possible parent path: \"{0}\"", parentPath);
                        IFilter parentFilter =
                            new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));

                        if (parentFilter != null)
                        {
                            locatorFound = true;
                        }

                        if (!locatorFound)
                        {
                            parentPath = null;
                        }
                    }

                    currentLocator++;
                }

                if (!locatorFound)
                {
                    throw new
                          FileNotFoundException("(VirtualPC plugin): Cannot find parent file for differencing disk image");
                }

                {
                    parentImage = new Vhd();
                    IFilter parentFilter =
                        new FiltersList().GetFilter(Path.Combine(imageFilter.GetParentFolder(), parentPath));

                    if (parentFilter == null)
                    {
                        throw new ImageNotSupportedException("(VirtualPC plugin): Cannot find parent image filter");
                    }

                    /*                            PluginBase plugins = new PluginBase();
                     *                          plugins.RegisterAllPlugins();
                     *                          if (!plugins.ImagePluginsList.TryGetValue(Name.ToLower(), out parentImage))
                     *                              throw new SystemException("(VirtualPC plugin): Unable to open myself");*/

                    if (!parentImage.Identify(parentFilter))
                    {
                        throw new
                              ImageNotSupportedException("(VirtualPC plugin): Parent image is not a Virtual PC disk image");
                    }

                    if (!parentImage.Open(parentFilter))
                    {
                        throw new ImageNotSupportedException("(VirtualPC plugin): Cannot open parent disk image");
                    }

                    // While specification says that parent and child disk images should contain UUID relationship
                    // in reality it seems that old differencing disk images stored a parent UUID that, nonetheless
                    // the parent never stored itself. So the only real way to know that images are related is
                    // because the parent IS found and SAME SIZE. Ugly...
                    // More funny even, tested parent images show an empty host OS, and child images a correct one.
                    if (parentImage.Info.Sectors != imageInfo.Sectors)
                    {
                        throw new
                              ImageNotSupportedException("(VirtualPC plugin): Parent image is of different size");
                    }
                }

                return(true);
            }

            case TYPE_DEPRECATED1:
            case TYPE_DEPRECATED2:
            case TYPE_DEPRECATED3:
            {
                throw new
                      ImageNotSupportedException("(VirtualPC plugin): Deprecated image type found. Please submit a bug with an example image.");
            }

            default:
            {
                throw new
                      ImageNotSupportedException($"(VirtualPC plugin): Unknown image type {thisFooter.DiskType} found. Please submit a bug with an example image.");
            }
            }
        }
Ejemplo n.º 16
0
        internal static List <ChecksumType> GetChecksums(byte[] data, EnableChecksum enabled = EnableChecksum.All)
        {
            IChecksum adler32CtxData = null;
            IChecksum crc16CtxData   = null;
            IChecksum crc32CtxData   = null;
            IChecksum crc64CtxData   = null;
            IChecksum md5CtxData     = null;
            IChecksum sha1CtxData    = null;
            IChecksum sha256CtxData  = null;
            IChecksum sha384CtxData  = null;
            IChecksum sha512CtxData  = null;
            IChecksum ssctxData      = null;
            IChecksum f16CtxData     = null;
            IChecksum f32CtxData     = null;

            var adlerThreadData   = new Thread(UpdateHash);
            var crc16ThreadData   = new Thread(UpdateHash);
            var crc32ThreadData   = new Thread(UpdateHash);
            var crc64ThreadData   = new Thread(UpdateHash);
            var md5ThreadData     = new Thread(UpdateHash);
            var sha1ThreadData    = new Thread(UpdateHash);
            var sha256ThreadData  = new Thread(UpdateHash);
            var sha384ThreadData  = new Thread(UpdateHash);
            var sha512ThreadData  = new Thread(UpdateHash);
            var spamsumThreadData = new Thread(UpdateHash);
            var f16ThreadData     = new Thread(UpdateHash);
            var f32ThreadData     = new Thread(UpdateHash);

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                adler32CtxData = new Adler32Context();

                var adlerPktData = new HashPacket
                {
                    Context = adler32CtxData,
                    Data    = data
                };

                adlerThreadData.Start(adlerPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                crc16CtxData = new CRC16IBMContext();

                var crc16PktData = new HashPacket
                {
                    Context = crc16CtxData,
                    Data    = data
                };

                crc16ThreadData.Start(crc16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                crc32CtxData = new Crc32Context();

                var crc32PktData = new HashPacket
                {
                    Context = crc32CtxData,
                    Data    = data
                };

                crc32ThreadData.Start(crc32PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                crc64CtxData = new Crc64Context();

                var crc64PktData = new HashPacket
                {
                    Context = crc64CtxData,
                    Data    = data
                };

                crc64ThreadData.Start(crc64PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                md5CtxData = new Md5Context();

                var md5PktData = new HashPacket
                {
                    Context = md5CtxData,
                    Data    = data
                };

                md5ThreadData.Start(md5PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                sha1CtxData = new Sha1Context();

                var sha1PktData = new HashPacket
                {
                    Context = sha1CtxData,
                    Data    = data
                };

                sha1ThreadData.Start(sha1PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                sha256CtxData = new Sha256Context();

                var sha256PktData = new HashPacket
                {
                    Context = sha256CtxData,
                    Data    = data
                };

                sha256ThreadData.Start(sha256PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                sha384CtxData = new Sha384Context();

                var sha384PktData = new HashPacket
                {
                    Context = sha384CtxData,
                    Data    = data
                };

                sha384ThreadData.Start(sha384PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                sha512CtxData = new Sha512Context();

                var sha512PktData = new HashPacket
                {
                    Context = sha512CtxData,
                    Data    = data
                };

                sha512ThreadData.Start(sha512PktData);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                ssctxData = new SpamSumContext();

                var spamsumPktData = new HashPacket
                {
                    Context = ssctxData,
                    Data    = data
                };

                spamsumThreadData.Start(spamsumPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                f16CtxData = new Fletcher16Context();

                var f16PktData = new HashPacket
                {
                    Context = f16CtxData,
                    Data    = data
                };

                f16ThreadData.Start(f16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                f32CtxData = new Fletcher32Context();

                var f32PktData = new HashPacket
                {
                    Context = f32CtxData,
                    Data    = data
                };

                f32ThreadData.Start(f32PktData);
            }

            while (adlerThreadData.IsAlive ||
                   crc16ThreadData.IsAlive ||
                   crc32ThreadData.IsAlive ||
                   crc64ThreadData.IsAlive ||
                   md5ThreadData.IsAlive ||
                   sha1ThreadData.IsAlive ||
                   sha256ThreadData.IsAlive ||
                   sha384ThreadData.IsAlive ||
                   sha512ThreadData.IsAlive ||
                   spamsumThreadData.IsAlive ||
                   f16ThreadData.IsAlive ||
                   f32ThreadData.IsAlive)
            {
            }

            List <ChecksumType> dataChecksums = new List <ChecksumType>();
            ChecksumType        chk;

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.adler32,
                    Value = adler32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc16,
                    Value = crc16CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc32,
                    Value = crc32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.crc64,
                    Value = crc64CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.md5,
                    Value = md5CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha1,
                    Value = sha1CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha256,
                    Value = sha256CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha384,
                    Value = sha384CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.sha512,
                    Value = sha512CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.spamsum,
                    Value = ssctxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.fletcher16,
                    Value = f16CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                chk = new ChecksumType
                {
                    type  = ChecksumTypeType.fletcher32,
                    Value = f32CtxData.End()
                };

                dataChecksums.Add(chk);
            }

            return(dataChecksums);
        }
Ejemplo n.º 17
0
        public EntropyResults[] CalculateTracksEntropy(bool duplicatedSectors)
        {
            List <EntropyResults> entropyResultses = new List <EntropyResults>();

            if (!(inputFormat is IOpticalMediaImage opticalMediaImage))
            {
                DicConsole.ErrorWriteLine("The selected image does not support tracks.");
                return(entropyResultses.ToArray());
            }

            try
            {
                List <Track> inputTracks = opticalMediaImage.Tracks;

                InitProgressEvent?.Invoke();

                foreach (Track currentTrack in inputTracks)
                {
                    EntropyResults trackEntropy = new EntropyResults {
                        Track = currentTrack.TrackSequence, Entropy = 0
                    };
                    UpdateProgressEvent
                    ?.Invoke($"Entropying track {currentTrack.TrackSequence} of {inputTracks.Max(t => t.TrackSequence)}",
                             currentTrack.TrackSequence, inputTracks.Max(t => t.TrackSequence));

                    ulong[]       entTable              = new ulong[256];
                    ulong         trackSize             = 0;
                    List <string> uniqueSectorsPerTrack = new List <string>();

                    trackEntropy.Sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1;
                    DicConsole.VerboseWriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence,
                                                trackEntropy.Sectors);

                    InitProgress2Event?.Invoke();

                    for (ulong i = currentTrack.TrackStartSector; i <= currentTrack.TrackEndSector; i++)
                    {
                        UpdateProgress2Event
                        ?.Invoke($"Entropying sector {i             + 1} of track {currentTrack.TrackSequence}",
                                 (long)(currentTrack.TrackEndSector - (i + 1)),
                                 (long)trackEntropy.Sectors);
                        byte[] sector = opticalMediaImage.ReadSector(i, currentTrack.TrackSequence);

                        if (duplicatedSectors)
                        {
                            string sectorHash = Sha1Context.Data(sector, out _);
                            if (!uniqueSectorsPerTrack.Contains(sectorHash))
                            {
                                uniqueSectorsPerTrack.Add(sectorHash);
                            }
                        }

                        foreach (byte b in sector)
                        {
                            entTable[b]++;
                        }

                        trackSize += (ulong)sector.LongLength;
                    }

                    EndProgress2Event?.Invoke();

                    trackEntropy.Entropy += entTable.Select(l => (double)l / (double)trackSize)
                                            .Select(frequency => - (frequency * Math.Log(frequency, 2))).Sum();

                    if (duplicatedSectors)
                    {
                        trackEntropy.UniqueSectors = uniqueSectorsPerTrack.Count;
                    }

                    entropyResultses.Add(trackEntropy);
                }

                EndProgressEvent?.Invoke();
            }
            catch (Exception ex)
            {
                if (debug)
                {
                    DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
                }
                else
                {
                    DicConsole.ErrorWriteLine("Unable to get separate tracks, not calculating their entropy");
                }
            }

            return(entropyResultses.ToArray());
        }
Ejemplo n.º 18
0
 public void Sha1RandomFile()
 {
     byte[] result = Sha1Context.File(Path.Combine(Consts.TestFilesRoot, "checksums", "random"));
     Assert.AreEqual(ExpectedRandom, result);
 }
Ejemplo n.º 19
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = Encoding.Unicode;
            information = "";

            var sb = new StringBuilder();

            byte[] ntfsBpb = imagePlugin.ReadSector(0 + partition.Start);

            NtfsBootBlock ntfsBb = Marshal.ByteArrayToStructureLittleEndian <NtfsBootBlock>(ntfsBpb);

            sb.AppendFormat("{0} bytes per sector", ntfsBb.bps).AppendLine();
            sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfsBb.spc, ntfsBb.spc * ntfsBb.bps).AppendLine();

            //          sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine();
            //          sb.AppendFormat("{0} FATs", ntfs_bb.fats_no).AppendLine();
            //          sb.AppendFormat("{0} entries in the root folder", ntfs_bb.root_ent).AppendLine();
            //          sb.AppendFormat("{0} sectors on volume (small)", ntfs_bb.sml_sectors).AppendLine();
            sb.AppendFormat("Media descriptor: 0x{0:X2}", ntfsBb.media).AppendLine();

            //          sb.AppendFormat("{0} sectors per FAT", ntfs_bb.spfat).AppendLine();
            sb.AppendFormat("{0} sectors per track", ntfsBb.sptrk).AppendLine();
            sb.AppendFormat("{0} heads", ntfsBb.heads).AppendLine();
            sb.AppendFormat("{0} hidden sectors before filesystem", ntfsBb.hsectors).AppendLine();

            //          sb.AppendFormat("{0} sectors on volume (big)", ntfs_bb.big_sectors).AppendLine();
            sb.AppendFormat("BIOS drive number: 0x{0:X2}", ntfsBb.drive_no).AppendLine();

            //          sb.AppendFormat("NT flags: 0x{0:X2}", ntfs_bb.nt_flags).AppendLine();
            //          sb.AppendFormat("Signature 1: 0x{0:X2}", ntfs_bb.signature1).AppendLine();
            sb.AppendFormat("{0} sectors on volume ({1} bytes)", ntfsBb.sectors, ntfsBb.sectors * ntfsBb.bps).
            AppendLine();

            sb.AppendFormat("Cluster where $MFT starts: {0}", ntfsBb.mft_lsn).AppendLine();
            sb.AppendFormat("Cluster where $MFTMirr starts: {0}", ntfsBb.mftmirror_lsn).AppendLine();

            if (ntfsBb.mft_rc_clusters > 0)
            {
                sb.AppendFormat("{0} clusters per MFT record ({1} bytes)", ntfsBb.mft_rc_clusters,
                                ntfsBb.mft_rc_clusters * ntfsBb.bps * ntfsBb.spc).AppendLine();
            }
            else
            {
                sb.AppendFormat("{0} bytes per MFT record", 1 << -ntfsBb.mft_rc_clusters).AppendLine();
            }

            if (ntfsBb.index_blk_cts > 0)
            {
                sb.AppendFormat("{0} clusters per Index block ({1} bytes)", ntfsBb.index_blk_cts,
                                ntfsBb.index_blk_cts * ntfsBb.bps * ntfsBb.spc).AppendLine();
            }
            else
            {
                sb.AppendFormat("{0} bytes per Index block", 1 << -ntfsBb.index_blk_cts).AppendLine();
            }

            sb.AppendFormat("Volume serial number: {0:X16}", ntfsBb.serial_no).AppendLine();

            //          sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine();

            XmlFsType = new FileSystemType();

            if (ntfsBb.jump[0] == 0xEB &&
                ntfsBb.jump[1] > 0x4E &&
                ntfsBb.jump[1] < 0x80 &&
                ntfsBb.signature2 == 0xAA55)
            {
                XmlFsType.Bootable = true;
                string bootChk = Sha1Context.Data(ntfsBb.boot_code, out _);
                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
            }

            XmlFsType.ClusterSize  = (uint)(ntfsBb.spc * ntfsBb.bps);
            XmlFsType.Clusters     = (ulong)(ntfsBb.sectors / ntfsBb.spc);
            XmlFsType.VolumeSerial = $"{ntfsBb.serial_no:X16}";
            XmlFsType.Type         = "NTFS";

            information = sb.ToString();
        }
Ejemplo n.º 20
0
        internal static void DoEntropy(EntropyOptions options)
        {
            DicConsole.DebugWriteLine("Entropy command", "--debug={0}", options.Debug);
            DicConsole.DebugWriteLine("Entropy command", "--verbose={0}", options.Verbose);
            DicConsole.DebugWriteLine("Entropy command", "--separated-tracks={0}", options.SeparatedTracks);
            DicConsole.DebugWriteLine("Entropy command", "--whole-disc={0}", options.WholeDisc);
            DicConsole.DebugWriteLine("Entropy command", "--input={0}", options.InputFile);
            DicConsole.DebugWriteLine("Entropy command", "--duplicated-sectors={0}", options.DuplicatedSectors);

            FiltersList filtersList = new FiltersList();
            IFilter     inputFilter = filtersList.GetFilter(options.InputFile);

            if (inputFilter == null)
            {
                DicConsole.ErrorWriteLine("Cannot open specified file.");
                return;
            }

            IMediaImage inputFormat = ImageFormat.Detect(inputFilter);

            if (inputFormat == null)
            {
                DicConsole.ErrorWriteLine("Unable to recognize image format, not checksumming");
                return;
            }

            inputFormat.Open(inputFilter);
            Core.Statistics.AddMediaFormat(inputFormat.Format);
            Core.Statistics.AddMedia(inputFormat.Info.MediaType, false);
            Core.Statistics.AddFilter(inputFilter.Name);
            double entropy = 0;

            ulong[] entTable;
            ulong   sectors;

            if (options.SeparatedTracks)
            {
                try
                {
                    List <Track> inputTracks = inputFormat.Tracks;

                    foreach (Track currentTrack in inputTracks)
                    {
                        entTable = new ulong[256];
                        ulong         trackSize             = 0;
                        List <string> uniqueSectorsPerTrack = new List <string>();

                        sectors = currentTrack.TrackEndSector - currentTrack.TrackStartSector + 1;
                        DicConsole.WriteLine("Track {0} has {1} sectors", currentTrack.TrackSequence, sectors);

                        for (ulong i = currentTrack.TrackStartSector; i <= currentTrack.TrackEndSector; i++)
                        {
                            DicConsole.Write("\rEntropying sector {0} of track {1}", i + 1, currentTrack.TrackSequence);
                            byte[] sector = inputFormat.ReadSector(i, currentTrack.TrackSequence);

                            if (options.DuplicatedSectors)
                            {
                                string sectorHash = Sha1Context.Data(sector, out _);
                                if (!uniqueSectorsPerTrack.Contains(sectorHash))
                                {
                                    uniqueSectorsPerTrack.Add(sectorHash);
                                }
                            }

                            foreach (byte b in sector)
                            {
                                entTable[b]++;
                            }

                            trackSize += (ulong)sector.LongLength;
                        }

                        entropy += entTable.Select(l => (double)l / (double)trackSize)
                                   .Select(frequency => - (frequency * Math.Log(frequency, 2))).Sum();

                        DicConsole.WriteLine("Entropy for track {0} is {1:F4}.", currentTrack.TrackSequence, entropy);

                        if (options.DuplicatedSectors)
                        {
                            DicConsole.WriteLine("Track {0} has {1} unique sectors ({1:P3})",
                                                 currentTrack.TrackSequence, uniqueSectorsPerTrack.Count,
                                                 (double)uniqueSectorsPerTrack.Count / (double)sectors);
                        }

                        DicConsole.WriteLine();
                    }
                }
                catch (Exception ex)
                {
                    if (options.Debug)
                    {
                        DicConsole.DebugWriteLine("Could not get tracks because {0}", ex.Message);
                    }
                    else
                    {
                        DicConsole.ErrorWriteLine("Unable to get separate tracks, not calculating their entropy");
                    }
                }
            }

            if (!options.WholeDisc)
            {
                return;
            }

            entTable = new ulong[256];
            ulong         diskSize      = 0;
            List <string> uniqueSectors = new List <string>();

            sectors = inputFormat.Info.Sectors;
            DicConsole.WriteLine("Sectors {0}", sectors);

            for (ulong i = 0; i < sectors; i++)
            {
                DicConsole.Write("\rEntropying sector {0}", i + 1);
                byte[] sector = inputFormat.ReadSector(i);

                if (options.DuplicatedSectors)
                {
                    string sectorHash = Sha1Context.Data(sector, out _);
                    if (!uniqueSectors.Contains(sectorHash))
                    {
                        uniqueSectors.Add(sectorHash);
                    }
                }

                foreach (byte b in sector)
                {
                    entTable[b]++;
                }

                diskSize += (ulong)sector.LongLength;
            }

            entropy += entTable.Select(l => (double)l / (double)diskSize)
                       .Select(frequency => - (frequency * Math.Log(frequency, 2))).Sum();

            DicConsole.WriteLine();

            DicConsole.WriteLine("Entropy for disk is {0:F4}.", entropy);

            if (options.DuplicatedSectors)
            {
                DicConsole.WriteLine("Disk has {0} unique sectors ({1:P3})", uniqueSectors.Count,
                                     (double)uniqueSectors.Count / (double)sectors);
            }

            Core.Statistics.AddCommand("entropy");
        }
Ejemplo n.º 21
0
        public bool GetInformation(IMediaImage imagePlugin, out List <Partition> partitions, ulong sectorOffset)
        {
            partitions = new List <Partition>();

            byte[] sector = imagePlugin.ReadSector(sectorOffset);

            if (sector.Length < 512)
            {
                return(false);
            }

            var table = new AtariTable
            {
                boot       = new byte[342],
                icdEntries = new AtariEntry[8],
                unused     = new byte[12],
                entries    = new AtariEntry[4]
            };

            Array.Copy(sector, 0, table.boot, 0, 342);

            for (int i = 0; i < 8; i++)
            {
                table.icdEntries[i].type   = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 0);
                table.icdEntries[i].start  = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 4);
                table.icdEntries[i].length = BigEndianBitConverter.ToUInt32(sector, 342 + (i * 12) + 8);
            }

            Array.Copy(sector, 438, table.unused, 0, 12);

            table.size = BigEndianBitConverter.ToUInt32(sector, 450);

            for (int i = 0; i < 4; i++)
            {
                table.entries[i].type   = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 0);
                table.entries[i].start  = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 4);
                table.entries[i].length = BigEndianBitConverter.ToUInt32(sector, 454 + (i * 12) + 8);
            }

            table.badStart  = BigEndianBitConverter.ToUInt32(sector, 502);
            table.badLength = BigEndianBitConverter.ToUInt32(sector, 506);
            table.checksum  = BigEndianBitConverter.ToUInt16(sector, 510);

            var sha1Ctx = new Sha1Context();

            sha1Ctx.Update(table.boot);
            AaruConsole.DebugWriteLine("Atari partition plugin", "Boot code SHA1: {0}", sha1Ctx.End());

            for (int i = 0; i < 8; i++)
            {
                AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].flag = 0x{1:X2}", i,
                                           (table.icdEntries[i].type & 0xFF000000) >> 24);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].type = 0x{1:X6}", i,
                                           table.icdEntries[i].type & 0x00FFFFFF);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].start = {1}", i,
                                           table.icdEntries[i].start);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.icdEntries[{0}].length = {1}", i,
                                           table.icdEntries[i].length);
            }

            AaruConsole.DebugWriteLine("Atari partition plugin", "table.size = {0}", table.size);

            for (int i = 0; i < 4; i++)
            {
                AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].flag = 0x{1:X2}", i,
                                           (table.entries[i].type & 0xFF000000) >> 24);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].type = 0x{1:X6}", i,
                                           table.entries[i].type & 0x00FFFFFF);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].start = {1}", i,
                                           table.entries[i].start);

                AaruConsole.DebugWriteLine("Atari partition plugin", "table.entries[{0}].length = {1}", i,
                                           table.entries[i].length);
            }

            AaruConsole.DebugWriteLine("Atari partition plugin", "table.badStart = {0}", table.badStart);
            AaruConsole.DebugWriteLine("Atari partition plugin", "table.badLength = {0}", table.badLength);
            AaruConsole.DebugWriteLine("Atari partition plugin", "table.checksum = 0x{0:X4}", table.checksum);

            bool  validTable        = false;
            ulong partitionSequence = 0;

            for (int i = 0; i < 4; i++)
            {
                uint type = table.entries[i].type & 0x00FFFFFF;

                switch (type)
                {
                case TypeGEMDOS:
                case TypeBigGEMDOS:
                case TypeLinux:
                case TypeSwap:
                case TypeRAW:
                case TypeNetBSD:
                case TypeNetBSDSwap:
                case TypeSysV:
                case TypeMac:
                case TypeMinix:
                case TypeMinix2:
                    validTable = true;

                    if (table.entries[i].start <= imagePlugin.Info.Sectors)
                    {
                        if (table.entries[i].start + table.entries[i].length > imagePlugin.Info.Sectors)
                        {
                            AaruConsole.DebugWriteLine("Atari partition plugin",
                                                       "WARNING: End of partition goes beyond device size");
                        }

                        ulong sectorSize = imagePlugin.Info.SectorSize;

                        if (sectorSize == 2448 ||
                            sectorSize == 2352)
                        {
                            sectorSize = 2048;
                        }

                        byte[] partType = new byte[3];
                        partType[0] = (byte)((type & 0xFF0000) >> 16);
                        partType[1] = (byte)((type & 0x00FF00) >> 8);
                        partType[2] = (byte)(type & 0x0000FF);

                        var part = new Partition
                        {
                            Size     = table.entries[i].length * sectorSize,
                            Length   = table.entries[i].length,
                            Sequence = partitionSequence,
                            Name     = "",
                            Offset   = table.entries[i].start * sectorSize,
                            Start    = table.entries[i].start,
                            Type     = Encoding.ASCII.GetString(partType),
                            Scheme   = Name
                        };

                        switch (type)
                        {
                        case TypeGEMDOS:
                            part.Description = "Atari GEMDOS partition";

                            break;

                        case TypeBigGEMDOS:
                            part.Description = "Atari GEMDOS partition bigger than 32 MiB";

                            break;

                        case TypeLinux:
                            part.Description = "Linux partition";

                            break;

                        case TypeSwap:
                            part.Description = "Swap partition";

                            break;

                        case TypeRAW:
                            part.Description = "RAW partition";

                            break;

                        case TypeNetBSD:
                            part.Description = "NetBSD partition";

                            break;

                        case TypeNetBSDSwap:
                            part.Description = "NetBSD swap partition";

                            break;

                        case TypeSysV:
                            part.Description = "Atari UNIX partition";

                            break;

                        case TypeMac:
                            part.Description = "Macintosh partition";

                            break;

                        case TypeMinix:
                        case TypeMinix2:
                            part.Description = "MINIX partition";

                            break;

                        default:
                            part.Description = "Unknown partition type";

                            break;
                        }

                        partitions.Add(part);
                        partitionSequence++;
                    }

                    break;

                case TypeExtended:
                    byte[] extendedSector = imagePlugin.ReadSector(table.entries[i].start);
                    var    extendedTable  = new AtariTable();
                    extendedTable.entries = new AtariEntry[4];

                    for (int j = 0; j < 4; j++)
                    {
                        extendedTable.entries[j].type =
                            BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 0);

                        extendedTable.entries[j].start =
                            BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 4);

                        extendedTable.entries[j].length =
                            BigEndianBitConverter.ToUInt32(extendedSector, 454 + (j * 12) + 8);
                    }

                    for (int j = 0; j < 4; j++)
                    {
                        uint extendedType = extendedTable.entries[j].type & 0x00FFFFFF;

                        if (extendedType != TypeGEMDOS &&
                            extendedType != TypeBigGEMDOS &&
                            extendedType != TypeLinux &&
                            extendedType != TypeSwap &&
                            extendedType != TypeRAW &&
                            extendedType != TypeNetBSD &&
                            extendedType != TypeNetBSDSwap &&
                            extendedType != TypeSysV &&
                            extendedType != TypeMac &&
                            extendedType != TypeMinix &&
                            extendedType != TypeMinix2)
                        {
                            continue;
                        }

                        validTable = true;

                        if (extendedTable.entries[j].start > imagePlugin.Info.Sectors)
                        {
                            continue;
                        }

                        if (extendedTable.entries[j].start + extendedTable.entries[j].length >
                            imagePlugin.Info.Sectors)
                        {
                            AaruConsole.DebugWriteLine("Atari partition plugin",
                                                       "WARNING: End of partition goes beyond device size");
                        }

                        ulong sectorSize = imagePlugin.Info.SectorSize;

                        if (sectorSize == 2448 ||
                            sectorSize == 2352)
                        {
                            sectorSize = 2048;
                        }

                        byte[] partType = new byte[3];
                        partType[0] = (byte)((extendedType & 0xFF0000) >> 16);
                        partType[1] = (byte)((extendedType & 0x00FF00) >> 8);
                        partType[2] = (byte)(extendedType & 0x0000FF);

                        var part = new Partition
                        {
                            Size     = extendedTable.entries[j].length * sectorSize,
                            Length   = extendedTable.entries[j].length,
                            Sequence = partitionSequence,
                            Name     = "",
                            Offset   = extendedTable.entries[j].start * sectorSize,
                            Start    = extendedTable.entries[j].start,
                            Type     = Encoding.ASCII.GetString(partType),
                            Scheme   = Name
                        };

                        switch (extendedType)
                        {
                        case TypeGEMDOS:
                            part.Description = "Atari GEMDOS partition";

                            break;

                        case TypeBigGEMDOS:
                            part.Description = "Atari GEMDOS partition bigger than 32 MiB";

                            break;

                        case TypeLinux:
                            part.Description = "Linux partition";

                            break;

                        case TypeSwap:
                            part.Description = "Swap partition";

                            break;

                        case TypeRAW:
                            part.Description = "RAW partition";

                            break;

                        case TypeNetBSD:
                            part.Description = "NetBSD partition";

                            break;

                        case TypeNetBSDSwap:
                            part.Description = "NetBSD swap partition";

                            break;

                        case TypeSysV:
                            part.Description = "Atari UNIX partition";

                            break;

                        case TypeMac:
                            part.Description = "Macintosh partition";

                            break;

                        case TypeMinix:
                        case TypeMinix2:
                            part.Description = "MINIX partition";

                            break;

                        default:
                            part.Description = "Unknown partition type";

                            break;
                        }

                        partitions.Add(part);
                        partitionSequence++;
                    }

                    break;
                }
            }

            if (!validTable)
            {
                return(partitions.Count > 0);
            }

            for (int i = 0; i < 8; i++)
            {
                uint type = table.icdEntries[i].type & 0x00FFFFFF;

                if (type != TypeGEMDOS &&
                    type != TypeBigGEMDOS &&
                    type != TypeLinux &&
                    type != TypeSwap &&
                    type != TypeRAW &&
                    type != TypeNetBSD &&
                    type != TypeNetBSDSwap &&
                    type != TypeSysV &&
                    type != TypeMac &&
                    type != TypeMinix &&
                    type != TypeMinix2)
                {
                    continue;
                }

                if (table.icdEntries[i].start > imagePlugin.Info.Sectors)
                {
                    continue;
                }

                if (table.icdEntries[i].start + table.icdEntries[i].length > imagePlugin.Info.Sectors)
                {
                    AaruConsole.DebugWriteLine("Atari partition plugin",
                                               "WARNING: End of partition goes beyond device size");
                }

                ulong sectorSize = imagePlugin.Info.SectorSize;

                if (sectorSize == 2448 ||
                    sectorSize == 2352)
                {
                    sectorSize = 2048;
                }

                byte[] partType = new byte[3];
                partType[0] = (byte)((type & 0xFF0000) >> 16);
                partType[1] = (byte)((type & 0x00FF00) >> 8);
                partType[2] = (byte)(type & 0x0000FF);

                var part = new Partition
                {
                    Size     = table.icdEntries[i].length * sectorSize,
                    Length   = table.icdEntries[i].length,
                    Sequence = partitionSequence,
                    Name     = "",
                    Offset   = table.icdEntries[i].start * sectorSize,
                    Start    = table.icdEntries[i].start,
                    Type     = Encoding.ASCII.GetString(partType),
                    Scheme   = Name
                };

                switch (type)
                {
                case TypeGEMDOS:
                    part.Description = "Atari GEMDOS partition";

                    break;

                case TypeBigGEMDOS:
                    part.Description = "Atari GEMDOS partition bigger than 32 MiB";

                    break;

                case TypeLinux:
                    part.Description = "Linux partition";

                    break;

                case TypeSwap:
                    part.Description = "Swap partition";

                    break;

                case TypeRAW:
                    part.Description = "RAW partition";

                    break;

                case TypeNetBSD:
                    part.Description = "NetBSD partition";

                    break;

                case TypeNetBSDSwap:
                    part.Description = "NetBSD swap partition";

                    break;

                case TypeSysV:
                    part.Description = "Atari UNIX partition";

                    break;

                case TypeMac:
                    part.Description = "Macintosh partition";

                    break;

                case TypeMinix:
                case TypeMinix2:
                    part.Description = "MINIX partition";

                    break;

                default:
                    part.Description = "Unknown partition type";

                    break;
                }

                partitions.Add(part);
                partitionSequence++;
            }

            return(partitions.Count > 0);
        }
Ejemplo n.º 22
0
        internal static List <ChecksumType> GetChecksums(byte[] data)
        {
            Adler32Context   adler32ctxData   = new Adler32Context();
            Crc16Context     crc16ctxData     = new Crc16Context();
            Crc32Context     crc32ctxData     = new Crc32Context();
            Crc64Context     crc64ctxData     = new Crc64Context();
            Md5Context       md5ctxData       = new Md5Context();
            Ripemd160Context ripemd160ctxData = new Ripemd160Context();
            Sha1Context      sha1ctxData      = new Sha1Context();
            Sha256Context    sha256ctxData    = new Sha256Context();
            Sha384Context    sha384ctxData    = new Sha384Context();
            Sha512Context    sha512ctxData    = new Sha512Context();
            SpamSumContext   ssctxData        = new SpamSumContext();

            Thread adlerThreadData     = new Thread(updateAdler);
            Thread crc16ThreadData     = new Thread(updateCRC16);
            Thread crc32ThreadData     = new Thread(updateCRC32);
            Thread crc64ThreadData     = new Thread(updateCRC64);
            Thread md5ThreadData       = new Thread(updateMD5);
            Thread ripemd160ThreadData = new Thread(updateRIPEMD160);
            Thread sha1ThreadData      = new Thread(updateSHA1);
            Thread sha256ThreadData    = new Thread(updateSHA256);
            Thread sha384ThreadData    = new Thread(updateSHA384);
            Thread sha512ThreadData    = new Thread(updateSHA512);
            Thread spamsumThreadData   = new Thread(updateSpamSum);

            adlerPacket     adlerPktData     = new adlerPacket();
            crc16Packet     crc16PktData     = new crc16Packet();
            crc32Packet     crc32PktData     = new crc32Packet();
            crc64Packet     crc64PktData     = new crc64Packet();
            md5Packet       md5PktData       = new md5Packet();
            ripemd160Packet ripemd160PktData = new ripemd160Packet();
            sha1Packet      sha1PktData      = new sha1Packet();
            sha256Packet    sha256PktData    = new sha256Packet();
            sha384Packet    sha384PktData    = new sha384Packet();
            sha512Packet    sha512PktData    = new sha512Packet();
            spamsumPacket   spamsumPktData   = new spamsumPacket();

            adler32ctxData.Init();
            adlerPktData.context = adler32ctxData;
            crc16ctxData.Init();
            crc16PktData.context = crc16ctxData;
            crc32ctxData.Init();
            crc32PktData.context = crc32ctxData;
            crc64ctxData.Init();
            crc64PktData.context = crc64ctxData;
            md5ctxData.Init();
            md5PktData.context = md5ctxData;
            ripemd160ctxData.Init();
            ripemd160PktData.context = ripemd160ctxData;
            sha1ctxData.Init();
            sha1PktData.context = sha1ctxData;
            sha256ctxData.Init();
            sha256PktData.context = sha256ctxData;
            sha384ctxData.Init();
            sha384PktData.context = sha384ctxData;
            sha512ctxData.Init();
            sha512PktData.context = sha512ctxData;
            ssctxData.Init();
            spamsumPktData.context = ssctxData;

            adlerPktData.data = data;
            adlerThreadData.Start(adlerPktData);
            crc16PktData.data = data;
            crc16ThreadData.Start(crc16PktData);
            crc32PktData.data = data;
            crc32ThreadData.Start(crc32PktData);
            crc64PktData.data = data;
            crc64ThreadData.Start(crc64PktData);
            md5PktData.data = data;
            md5ThreadData.Start(md5PktData);
            ripemd160PktData.data = data;
            ripemd160ThreadData.Start(ripemd160PktData);
            sha1PktData.data = data;
            sha1ThreadData.Start(sha1PktData);
            sha256PktData.data = data;
            sha256ThreadData.Start(sha256PktData);
            sha384PktData.data = data;
            sha384ThreadData.Start(sha384PktData);
            sha512PktData.data = data;
            sha512ThreadData.Start(sha512PktData);
            spamsumPktData.data = data;
            spamsumThreadData.Start(spamsumPktData);

            while (adlerThreadData.IsAlive || crc16ThreadData.IsAlive || crc32ThreadData.IsAlive ||
                   crc64ThreadData.IsAlive || md5ThreadData.IsAlive || ripemd160ThreadData.IsAlive ||
                   sha1ThreadData.IsAlive || sha256ThreadData.IsAlive || sha384ThreadData.IsAlive ||
                   sha512ThreadData.IsAlive || spamsumThreadData.IsAlive)
            {
            }

            List <ChecksumType> dataChecksums = new List <ChecksumType>();

            ChecksumType chk = new ChecksumType {
                type = ChecksumTypeType.adler32, Value = adler32ctxData.End()
            };

            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.crc16, Value = crc16ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.crc32, Value = crc32ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.crc64, Value = crc64ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.md5, Value = md5ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.ripemd160, Value = ripemd160ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.sha1, Value = sha1ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.sha256, Value = sha256ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.sha384, Value = sha384ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.sha512, Value = sha512ctxData.End()
            };
            dataChecksums.Add(chk);

            chk = new ChecksumType {
                type = ChecksumTypeType.spamsum, Value = ssctxData.End()
            };
            dataChecksums.Add(chk);

            return(dataChecksums);
        }
Ejemplo n.º 23
0
Archivo: SHA1.cs Proyecto: paulyc/Aaru
 public void Sha1EmptyFile()
 {
     byte[] result = Sha1Context.File(Path.Combine(Consts.TEST_FILES_ROOT, "Checksum test files", "empty"));
     Assert.AreEqual(_expectedEmpty, result);
 }
Ejemplo n.º 24
0
        public bool?VerifyMediaImage()
        {
            if (_discImage.DiscHashes.Count == 0)
            {
                return(null);
            }

            // Read up to 1 MiB at a time for verification
            const int verifySize = 1024 * 1024;
            long      readBytes;

            byte[] verifyBytes;

            IFilter[] filters = _discImage.Tracks.OrderBy(t => t.Sequence).Select(t => t.TrackFile.DataFilter).
                                Distinct().ToArray();

            if (_discImage.DiscHashes.TryGetValue("sha1", out string sha1))
            {
                var ctx = new Sha1Context();

                foreach (IFilter filter in filters)
                {
                    Stream stream = filter.GetDataForkStream();
                    readBytes   = 0;
                    verifyBytes = new byte[verifySize];

                    while (readBytes + verifySize < stream.Length)
                    {
                        stream.Read(verifyBytes, 0, verifyBytes.Length);
                        ctx.Update(verifyBytes);
                        readBytes += verifyBytes.LongLength;
                    }

                    verifyBytes = new byte[stream.Length - readBytes];
                    stream.Read(verifyBytes, 0, verifyBytes.Length);
                    ctx.Update(verifyBytes);
                }

                string verifySha1 = ctx.End();
                AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated SHA1: {0}", verifySha1);
                AaruConsole.DebugWriteLine("CDRWin plugin", "Expected SHA1: {0}", sha1);

                return(verifySha1 == sha1);
            }

            if (_discImage.DiscHashes.TryGetValue("md5", out string md5))
            {
                var ctx = new Md5Context();

                foreach (IFilter filter in filters)
                {
                    Stream stream = filter.GetDataForkStream();
                    readBytes   = 0;
                    verifyBytes = new byte[verifySize];

                    while (readBytes + verifySize < stream.Length)
                    {
                        stream.Read(verifyBytes, 0, verifyBytes.Length);
                        ctx.Update(verifyBytes);
                        readBytes += verifyBytes.LongLength;
                    }

                    verifyBytes = new byte[stream.Length - readBytes];
                    stream.Read(verifyBytes, 0, verifyBytes.Length);
                    ctx.Update(verifyBytes);
                }

                string verifyMd5 = ctx.End();
                AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated MD5: {0}", verifyMd5);
                AaruConsole.DebugWriteLine("CDRWin plugin", "Expected MD5: {0}", md5);

                return(verifyMd5 == md5);
            }

            if (_discImage.DiscHashes.TryGetValue("crc32", out string crc32))
            {
                var ctx = new Crc32Context();

                foreach (IFilter filter in filters)
                {
                    Stream stream = filter.GetDataForkStream();
                    readBytes   = 0;
                    verifyBytes = new byte[verifySize];

                    while (readBytes + verifySize < stream.Length)
                    {
                        stream.Read(verifyBytes, 0, verifyBytes.Length);
                        ctx.Update(verifyBytes);
                        readBytes += verifyBytes.LongLength;
                    }

                    verifyBytes = new byte[stream.Length - readBytes];
                    stream.Read(verifyBytes, 0, verifyBytes.Length);
                    ctx.Update(verifyBytes);
                }

                string verifyCrc = ctx.End();
                AaruConsole.DebugWriteLine("CDRWin plugin", "Calculated CRC32: {0}", verifyCrc);
                AaruConsole.DebugWriteLine("CDRWin plugin", "Expected CRC32: {0}", crc32);

                return(verifyCrc == crc32);
            }

            foreach (string hash in _discImage.DiscHashes.Keys)
            {
                AaruConsole.DebugWriteLine("CDRWin plugin", "Found unsupported hash {0}", hash);
            }

            return(null);
        }
Ejemplo n.º 25
0
 public void Sha1EmptyFile()
 {
     byte[] result = Sha1Context.File(Path.Combine(Consts.TestFilesRoot, "checksums", "empty"));
     Assert.AreEqual(ExpectedEmpty, result);
 }
Ejemplo n.º 26
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding = encoding ?? Encoding.GetEncoding("iso-8859-1");
            StringBuilder sbInformation = new StringBuilder();

            XmlFsType   = new FileSystemType();
            information = null;
            BigEndianBitConverter.IsLittleEndian = BitConverter.IsLittleEndian;

            byte[] bootBlockSectors = imagePlugin.ReadSectors(0 + partition.Start, 2);

            BootBlock bootBlk = Marshal.ByteArrayToStructureBigEndian <BootBlock>(bootBlockSectors);

            bootBlk.bootCode = new byte[bootBlockSectors.Length - 12];
            Array.Copy(bootBlockSectors, 12, bootBlk.bootCode, 0, bootBlk.bootCode.Length);
            bootBlockSectors[4] = bootBlockSectors[5] = bootBlockSectors[6] = bootBlockSectors[7] = 0;
            uint bsum = AmigaBootChecksum(bootBlockSectors);

            ulong bRootPtr = 0;

            // If bootblock is correct, let's take its rootblock pointer
            if (bsum == bootBlk.checksum)
            {
                bRootPtr = bootBlk.root_ptr + partition.Start;
                DicConsole.DebugWriteLine("AmigaDOS plugin", "Bootblock points to {0} as Rootblock", bRootPtr);
            }

            ulong[] rootPtrs =
            {
                bRootPtr + partition.Start,                                      (partition.End - partition.Start + 1) / 2 + partition.Start - 2,
                (partition.End - partition.Start + 1) / 2 + partition.Start - 1,
                (partition.End - partition.Start + 1) / 2 +
                partition.Start,
                (partition.End - partition.Start + 1) / 2 + partition.Start + 4
            };

            RootBlock rootBlk = new RootBlock();

            byte[] rootBlockSector = null;

            bool rootFound = false;
            uint blockSize = 0;

            // So to handle even number of sectors
            foreach (ulong rootPtr in rootPtrs.Where(rootPtr => rootPtr < partition.End && rootPtr >= partition.Start))
            {
                DicConsole.DebugWriteLine("AmigaDOS plugin", "Searching for Rootblock in sector {0}", rootPtr);

                rootBlockSector = imagePlugin.ReadSector(rootPtr);

                rootBlk.type = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x00);
                DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.type = {0}", rootBlk.type);
                if (rootBlk.type != TYPE_HEADER)
                {
                    continue;
                }

                rootBlk.hashTableSize = BigEndianBitConverter.ToUInt32(rootBlockSector, 0x0C);

                DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.hashTableSize = {0}", rootBlk.hashTableSize);

                blockSize = (rootBlk.hashTableSize + 56) * 4;
                uint sectorsPerBlock = (uint)(blockSize / rootBlockSector.Length);

                DicConsole.DebugWriteLine("AmigaDOS plugin", "blockSize = {0}", blockSize);
                DicConsole.DebugWriteLine("AmigaDOS plugin", "sectorsPerBlock = {0}", sectorsPerBlock);

                if (blockSize % rootBlockSector.Length > 0)
                {
                    sectorsPerBlock++;
                }

                if (rootPtr + sectorsPerBlock >= partition.End)
                {
                    continue;
                }

                rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);

                // Clear checksum on sector
                rootBlk.checksum    = BigEndianBitConverter.ToUInt32(rootBlockSector, 20);
                rootBlockSector[20] = rootBlockSector[21] = rootBlockSector[22] = rootBlockSector[23] = 0;
                uint rsum = AmigaChecksum(rootBlockSector);

                DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.checksum = 0x{0:X8}", rootBlk.checksum);
                DicConsole.DebugWriteLine("AmigaDOS plugin", "rsum = 0x{0:X8}", rsum);

                rootBlk.sec_type = BigEndianBitConverter.ToUInt32(rootBlockSector, rootBlockSector.Length - 4);
                DicConsole.DebugWriteLine("AmigaDOS plugin", "rootBlk.sec_type = {0}", rootBlk.sec_type);

                if (rootBlk.sec_type != SUBTYPE_ROOT || rootBlk.checksum != rsum)
                {
                    continue;
                }

                rootBlockSector = imagePlugin.ReadSectors(rootPtr, sectorsPerBlock);
                rootFound       = true;
                break;
            }

            if (!rootFound)
            {
                return;
            }

            rootBlk = MarshalRootBlock(rootBlockSector);

            string diskName = StringHandlers.PascalToString(rootBlk.diskName, Encoding);

            switch (bootBlk.diskType & 0xFF)
            {
            case 0:
                sbInformation.Append("Amiga Original File System");
                XmlFsType.Type = "Amiga OFS";
                break;

            case 1:
                sbInformation.Append("Amiga Fast File System");
                XmlFsType.Type = "Amiga FFS";
                break;

            case 2:
                sbInformation.Append("Amiga Original File System with international characters");
                XmlFsType.Type = "Amiga OFS";
                break;

            case 3:
                sbInformation.Append("Amiga Fast File System with international characters");
                XmlFsType.Type = "Amiga FFS";
                break;

            case 4:
                sbInformation.Append("Amiga Original File System with directory cache");
                XmlFsType.Type = "Amiga OFS";
                break;

            case 5:
                sbInformation.Append("Amiga Fast File System with directory cache");
                XmlFsType.Type = "Amiga FFS";
                break;

            case 6:
                sbInformation.Append("Amiga Original File System with long filenames");
                XmlFsType.Type = "Amiga OFS2";
                break;

            case 7:
                sbInformation.Append("Amiga Fast File System with long filenames");
                XmlFsType.Type = "Amiga FFS2";
                break;
            }

            if ((bootBlk.diskType & 0x6D754600) == 0x6D754600)
            {
                sbInformation.Append(", with multi-user patches");
            }

            sbInformation.AppendLine();

            sbInformation.AppendFormat("Volume name: {0}", diskName).AppendLine();

            if (bootBlk.checksum == bsum)
            {
                Sha1Context sha1Ctx = new Sha1Context();
                sha1Ctx.Update(bootBlk.bootCode);
                sbInformation.AppendLine("Volume is bootable");
                sbInformation.AppendFormat("Boot code SHA1 is {0}", sha1Ctx.End()).AppendLine();
            }

            if (rootBlk.bitmapFlag == 0xFFFFFFFF)
            {
                sbInformation.AppendLine("Volume bitmap is valid");
            }

            if (rootBlk.bitmapExtensionBlock != 0x00000000 && rootBlk.bitmapExtensionBlock != 0xFFFFFFFF)
            {
                sbInformation.AppendFormat("Bitmap extension at block {0}", rootBlk.bitmapExtensionBlock).AppendLine();
            }

            if ((bootBlk.diskType & 0xFF) == 4 || (bootBlk.diskType & 0xFF) == 5)
            {
                sbInformation.AppendFormat("Directory cache starts at block {0}", rootBlk.extension).AppendLine();
            }

            ulong blocks = (partition.End - partition.Start + 1) * imagePlugin.Info.SectorSize / blockSize;

            sbInformation.AppendFormat("Volume block size is {0} bytes", blockSize).AppendLine();
            sbInformation.AppendFormat("Volume has {0} blocks", blocks).AppendLine();
            sbInformation.AppendFormat("Volume created on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks))
            .AppendLine();
            sbInformation.AppendFormat("Volume last modified on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks))
            .AppendLine();
            sbInformation.AppendFormat("Volume root directory last modified on on {0}",
                                       DateHandlers.AmigaToDateTime(rootBlk.rDays, rootBlk.rMins, rootBlk.rTicks))
            .AppendLine();
            sbInformation.AppendFormat("Root block checksum is 0x{0:X8}", rootBlk.checksum).AppendLine();
            information = sbInformation.ToString();

            XmlFsType.CreationDate =
                DateHandlers.AmigaToDateTime(rootBlk.cDays, rootBlk.cMins, rootBlk.cTicks);
            XmlFsType.CreationDateSpecified = true;
            XmlFsType.ModificationDate      =
                DateHandlers.AmigaToDateTime(rootBlk.vDays, rootBlk.vMins, rootBlk.vTicks);
            XmlFsType.ModificationDateSpecified = true;
            XmlFsType.Dirty       = rootBlk.bitmapFlag != 0xFFFFFFFF;
            XmlFsType.Clusters    = blocks;
            XmlFsType.ClusterSize = blockSize;
            XmlFsType.VolumeName  = diskName;
            XmlFsType.Bootable    = bsum == bootBlk.checksum;
            // Useful as a serial
            XmlFsType.VolumeSerial = $"{rootBlk.checksum:X8}";
        }
Ejemplo n.º 27
0
        public static BenchmarkResults Do(int bufferSize, int blockSize)
        {
            BenchmarkResults results = new BenchmarkResults
            {
                Entries      = new Dictionary <string, BenchmarkEntry>(),
                MinMemory    = long.MaxValue,
                MaxMemory    = 0,
                SeparateTime = 0
            };
            MemoryStream ms  = new MemoryStream(bufferSize);
            Random       rnd = new Random();
            DateTime     start;
            DateTime     end;

            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Writing block {0} of {1} with random data.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                rnd.NextBytes(tmp);
                ms.Write(tmp, 0, blockSize);
            }

            EndProgress();
            end = DateTime.Now;

            results.FillTime  = (end - start).TotalSeconds;
            results.FillSpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds;

            ms.Seek(0, SeekOrigin.Begin);
            long mem = GC.GetTotalMemory(false);

            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Reading block {0} of {1}.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
            }

            EndProgress();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.ReadTime  = (end - start).TotalSeconds;
            results.ReadSpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds;

            #region Adler32
            IChecksum ctx = new Adler32Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with Adler32.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("Adler32",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion Adler32

            #region Fletcher16
            ctx = new Fletcher16Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with Fletcher-16.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("Fletcher16",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion Fletcher16

            #region Fletcher32
            ctx = new Fletcher32Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with Fletcher-32.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("Fletcher32",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion Fletcher32

            #region CRC16
            ctx = new Crc16Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with CRC16.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("CRC16",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion CRC16

            #region CRC32
            ctx = new Crc32Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with CRC32.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("CRC32",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion CRC32

            #region CRC64
            ctx = new Crc64Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with CRC64.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("CRC64",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion CRC64

            #region MD5
            ctx = new Md5Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with MD5.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("MD5",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion MD5

            #if !NETSTANDARD2_0
            #region RIPEMD160
            ctx = new Ripemd160Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with RIPEMD160.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("RIPEMD160",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion RIPEMD160
            #endif

            #region SHA1
            ctx = new Sha1Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with SHA1.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("SHA1",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion SHA1

            #region SHA256
            ctx = new Sha256Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with SHA256.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("SHA256",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion SHA256

            #region SHA384
            ctx = new Sha384Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with SHA384.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("SHA384",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion SHA384

            #region SHA512
            ctx = new Sha512Context();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with SHA512.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("SHA512",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion SHA512

            #region SpamSum
            ctx = new SpamSumContext();
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Checksumming block {0} of {1} with SpamSum.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                ctx.Update(tmp);
            }

            EndProgress();
            ctx.End();
            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.Entries.Add("SpamSum",
                                new BenchmarkEntry
            {
                TimeSpan = (end - start).TotalSeconds,
                Speed    = bufferSize / 1048576.0 / (end - start).TotalSeconds
            });
            results.SeparateTime += (end - start).TotalSeconds;
            #endregion SpamSum

            #region Entropy
            ulong[] entTable = new ulong[256];
            ms.Seek(0, SeekOrigin.Begin);
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }
            start = DateTime.Now;
            InitProgress();
            for (int i = 0; i < bufferSize / blockSize; i++)
            {
                UpdateProgress("Entropying block {0} of {1}.", i + 1, bufferSize / blockSize);
                byte[] tmp = new byte[blockSize];
                ms.Read(tmp, 0, blockSize);
                foreach (byte b in tmp)
                {
                    entTable[b]++;
                }
            }

            EndProgress();

            end = DateTime.Now;
            mem = GC.GetTotalMemory(false);
            if (mem > results.MaxMemory)
            {
                results.MaxMemory = mem;
            }
            if (mem < results.MinMemory)
            {
                results.MinMemory = mem;
            }

            results.EntropyTime  = (end - start).TotalSeconds;
            results.EntropySpeed = bufferSize / 1048576.0 / (end - start).TotalSeconds;
            #endregion Entropy

            /*
             #region Multitasking
             * start                 = DateTime.Now;
             * Checksum allChecksums = new Checksum();
             * InitProgress();
             * for(int i = 0; i < bufferSize / blockSize; i++)
             * {
             *  UpdateProgress("Checksumming block {0} of {1} with all algorithms at the same time.", i + 1,
             *                 bufferSize / blockSize);
             *  byte[] tmp = new byte[blockSize];
             *  ms.Read(tmp, 0, blockSize);
             *
             *  allChecksums.Update(tmp);
             * }
             *
             * EndProgress();
             *
             * allChecksums.End();
             * end                                           = DateTime.Now;
             * mem                                           = GC.GetTotalMemory(false);
             * if(mem > results.MaxMemory) results.MaxMemory = mem;
             * if(mem < results.MinMemory) results.MinMemory = mem;
             *
             * results.TotalTime  = (end - start).TotalSeconds;
             * results.TotalSpeed = bufferSize / 1048576.0 / results.TotalTime;
             #endregion
             */
            results.SeparateSpeed = bufferSize / 1048576.0 / results.SeparateTime;

            return(results);
        }
Ejemplo n.º 28
0
        public void GetInformation(IMediaImage imagePlugin, Partition partition, out string information,
                                   Encoding encoding)
        {
            Encoding    = encoding ?? Encoding.GetEncoding("IBM437");
            information = "";

            var sb = new StringBuilder();

            XmlFsType = new FileSystemType();

            uint sectorsPerBpb = imagePlugin.Info.SectorSize < 512 ? 512 / imagePlugin.Info.SectorSize : 1;

            byte[] bpbSector = imagePlugin.ReadSectors(0 + partition.Start, sectorsPerBpb);

            BpbKind bpbKind = DetectBpbKind(bpbSector, imagePlugin, partition, out BiosParameterBlockEbpb fakeBpb,
                                            out HumanParameterBlock humanBpb, out AtariParameterBlock atariBpb,
                                            out byte minBootNearJump, out bool andosOemCorrect, out bool bootable);

            bool   isFat12             = false;
            bool   isFat16             = false;
            bool   isFat32             = false;
            ulong  rootDirectorySector = 0;
            string extraInfo           = null;
            string bootChk             = null;

            XmlFsType.Bootable = bootable;

            // This is needed because for FAT16, GEMDOS increases bytes per sector count instead of using big_sectors field.
            uint sectorsPerRealSector;

            // This is needed because some OSes don't put volume label as first entry in the root directory
            uint sectorsForRootDirectory = 0;

            switch (bpbKind)
            {
            case BpbKind.DecRainbow:
            case BpbKind.Hardcoded:
            case BpbKind.Msx:
            case BpbKind.Apricot:
                isFat12 = true;

                break;

            case BpbKind.ShortFat32:
            case BpbKind.LongFat32:
            {
                isFat32 = true;

                Fat32ParameterBlock fat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlock>(bpbSector);

                Fat32ParameterBlockShort shortFat32Bpb =
                    Marshal.ByteArrayToStructureLittleEndian <Fat32ParameterBlockShort>(bpbSector);

                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fat32Bpb.bps       *= 4;
                    fat32Bpb.spc       /= 4;
                    fat32Bpb.big_spfat /= 4;
                    fat32Bpb.hsectors  /= 4;
                    fat32Bpb.sptrk     /= 4;
                }

                if (fat32Bpb.version != 0)
                {
                    sb.AppendLine("FAT+");
                    XmlFsType.Type = "FAT+";
                }
                else
                {
                    sb.AppendLine("Microsoft FAT32");
                    XmlFsType.Type = "FAT32";
                }

                if (fat32Bpb.oem_name != null)
                {
                    if (fat32Bpb.oem_name[5] == 0x49 &&
                        fat32Bpb.oem_name[6] == 0x48 &&
                        fat32Bpb.oem_name[7] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        XmlFsType.SystemIdentifier = StringHandlers.CToString(fat32Bpb.oem_name);
                    }
                }

                if (!string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
                {
                    sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine();
                }

                sb.AppendFormat("{0} bytes per sector.", fat32Bpb.bps).AppendLine();
                sb.AppendFormat("{0} sectors per cluster.", fat32Bpb.spc).AppendLine();
                XmlFsType.ClusterSize = (uint)(fat32Bpb.bps * fat32Bpb.spc);
                sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fat32Bpb.rsectors).AppendLine();

                if (fat32Bpb.big_sectors == 0 &&
                    fat32Bpb.signature == 0x28)
                {
                    sb.AppendFormat("{0} sectors on volume ({1} bytes).", shortFat32Bpb.huge_sectors,
                                    shortFat32Bpb.huge_sectors * shortFat32Bpb.bps).AppendLine();

                    XmlFsType.Clusters = shortFat32Bpb.huge_sectors / shortFat32Bpb.spc;
                }
                else
                {
                    sb.AppendFormat("{0} sectors on volume ({1} bytes).", fat32Bpb.big_sectors,
                                    fat32Bpb.big_sectors * fat32Bpb.bps).AppendLine();

                    XmlFsType.Clusters = fat32Bpb.big_sectors / fat32Bpb.spc;
                }

                sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
                sb.AppendFormat("Media descriptor: 0x{0:X2}", fat32Bpb.media).AppendLine();
                sb.AppendFormat("{0} sectors per FAT.", fat32Bpb.big_spfat).AppendLine();
                sb.AppendFormat("{0} sectors per track.", fat32Bpb.sptrk).AppendLine();
                sb.AppendFormat("{0} heads.", fat32Bpb.heads).AppendLine();
                sb.AppendFormat("{0} hidden sectors before BPB.", fat32Bpb.hsectors).AppendLine();
                sb.AppendFormat("Cluster of root directory: {0}", fat32Bpb.root_cluster).AppendLine();
                sb.AppendFormat("Sector of FSINFO structure: {0}", fat32Bpb.fsinfo_sector).AppendLine();
                sb.AppendFormat("Sector of backup FAT32 parameter block: {0}", fat32Bpb.backup_sector).AppendLine();
                sb.AppendFormat("Drive number: 0x{0:X2}", fat32Bpb.drive_no).AppendLine();
                sb.AppendFormat("Volume Serial Number: 0x{0:X8}", fat32Bpb.serial_no).AppendLine();
                XmlFsType.VolumeSerial = $"{fat32Bpb.serial_no:X8}";

                if ((fat32Bpb.flags & 0xF8) == 0x00)
                {
                    if ((fat32Bpb.flags & 0x01) == 0x01)
                    {
                        sb.AppendLine("Volume should be checked on next mount.");
                        XmlFsType.Dirty = true;
                    }

                    if ((fat32Bpb.flags & 0x02) == 0x02)
                    {
                        sb.AppendLine("Disk surface should be on next mount.");
                    }
                }

                if ((fat32Bpb.mirror_flags & 0x80) == 0x80)
                {
                    sb.AppendFormat("FATs are out of sync. FAT #{0} is in use.", fat32Bpb.mirror_flags & 0xF).
                    AppendLine();
                }
                else
                {
                    sb.AppendLine("All copies of FAT are the same.");
                }

                if ((fat32Bpb.mirror_flags & 0x6F20) == 0x6F20)
                {
                    sb.AppendLine("DR-DOS will boot this FAT32 using CHS.");
                }
                else if ((fat32Bpb.mirror_flags & 0x4F20) == 0x4F20)
                {
                    sb.AppendLine("DR-DOS will boot this FAT32 using LBA.");
                }

                if (fat32Bpb.signature == 0x29)
                {
                    XmlFsType.VolumeName = Encoding.ASCII.GetString(fat32Bpb.volume_label);

                    sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fat32Bpb.fs_type)).
                    AppendLine();

                    bootChk = Sha1Context.Data(fat32Bpb.boot_code, out _);
                }
                else
                {
                    bootChk = Sha1Context.Data(shortFat32Bpb.boot_code, out _);
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                XmlFsType.Bootable =
                    (fat32Bpb.jump[0] == 0xEB && fat32Bpb.jump[1] >= minBootNearJump && fat32Bpb.jump[1] < 0x80) ||
                    (fat32Bpb.jump[0] == 0xE9 && fat32Bpb.jump.Length >= 3 &&
                     BitConverter.ToUInt16(fat32Bpb.jump, 1) >= minBootNearJump &&
                     BitConverter.ToUInt16(fat32Bpb.jump, 1) <= 0x1FC);

                sectorsPerRealSector = fat32Bpb.bps / imagePlugin.Info.SectorSize;

                // First root directory sector
                rootDirectorySector =
                    (ulong)(((fat32Bpb.root_cluster - 2) * fat32Bpb.spc) + (fat32Bpb.big_spfat * fat32Bpb.fats_no) +
                            fat32Bpb.rsectors) * sectorsPerRealSector;

                sectorsForRootDirectory = 1;

                if (fat32Bpb.fsinfo_sector + partition.Start <= partition.End)
                {
                    byte[] fsinfoSector = imagePlugin.ReadSector(fat32Bpb.fsinfo_sector + partition.Start);

                    FsInfoSector fsInfo = Marshal.ByteArrayToStructureLittleEndian <FsInfoSector>(fsinfoSector);

                    if (fsInfo.signature1 == FSINFO_SIGNATURE1 &&
                        fsInfo.signature2 == FSINFO_SIGNATURE2 &&
                        fsInfo.signature3 == FSINFO_SIGNATURE3)
                    {
                        if (fsInfo.free_clusters < 0xFFFFFFFF)
                        {
                            sb.AppendFormat("{0} free clusters", fsInfo.free_clusters).AppendLine();
                            XmlFsType.FreeClusters          = fsInfo.free_clusters;
                            XmlFsType.FreeClustersSpecified = true;
                        }

                        if (fsInfo.last_cluster > 2 &&
                            fsInfo.last_cluster < 0xFFFFFFFF)
                        {
                            sb.AppendFormat("Last allocated cluster {0}", fsInfo.last_cluster).AppendLine();
                        }
                    }
                }

                break;
            }

            // Some fields could overflow fake BPB, those will be handled below
            case BpbKind.Atari:
            {
                ushort sum = 0;

                for (int i = 0; i < bpbSector.Length; i += 2)
                {
                    sum += BigEndianBitConverter.ToUInt16(bpbSector, i);
                }

                // TODO: Check this
                if (sum == 0x1234)
                {
                    XmlFsType.Bootable = true;
                    var atariSb = new StringBuilder();

                    atariSb.AppendFormat("cmdload will be loaded with value {0:X4}h",
                                         BigEndianBitConverter.ToUInt16(bpbSector, 0x01E)).AppendLine();

                    atariSb.AppendFormat("Boot program will be loaded at address {0:X4}h", atariBpb.ldaaddr).
                    AppendLine();

                    atariSb.AppendFormat("FAT and directory will be cached at address {0:X4}h", atariBpb.fatbuf).
                    AppendLine();

                    if (atariBpb.ldmode == 0)
                    {
                        byte[] tmp = new byte[8];
                        Array.Copy(atariBpb.fname, 0, tmp, 0, 8);
                        string fname = Encoding.ASCII.GetString(tmp).Trim();
                        tmp = new byte[3];
                        Array.Copy(atariBpb.fname, 8, tmp, 0, 3);
                        string extension = Encoding.ASCII.GetString(tmp).Trim();
                        string filename;

                        if (string.IsNullOrEmpty(extension))
                        {
                            filename = fname;
                        }
                        else
                        {
                            filename = fname + "." + extension;
                        }

                        atariSb.AppendFormat("Boot program resides in file \"{0}\"", filename).AppendLine();
                    }
                    else
                    {
                        atariSb.
                        AppendFormat("Boot program starts in sector {0} and is {1} sectors long ({2} bytes)",
                                     atariBpb.ssect, atariBpb.sectcnt, atariBpb.sectcnt * atariBpb.bps).
                        AppendLine();
                    }

                    extraInfo = atariSb.ToString();
                }

                break;
            }

            case BpbKind.Human:
                XmlFsType.Bootable = true;

                break;
            }

            if (!isFat32)
            {
                // This is to support FAT partitions on hybrid ISO/USB images
                if (imagePlugin.Info.XmlMediaType == XmlMediaType.OpticalDisc)
                {
                    fakeBpb.bps      *= 4;
                    fakeBpb.spc      /= 4;
                    fakeBpb.spfat    /= 4;
                    fakeBpb.hsectors /= 4;
                    fakeBpb.sptrk    /= 4;
                    fakeBpb.rsectors /= 4;

                    if (fakeBpb.spc == 0)
                    {
                        fakeBpb.spc = 1;
                    }
                }

                // This assumes no sane implementation will violate cluster size rules
                // However nothing prevents this to happen
                // If first file on disk uses only one cluster there is absolutely no way to differentiate between FAT12 and FAT16,
                // so let's hope implementations use common sense?
                if (!isFat12 &&
                    !isFat16)
                {
                    ulong clusters;

                    if (fakeBpb.sectors == 0)
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        clusters = fakeBpb.spc == 0 ? fakeBpb.sectors : (ulong)fakeBpb.sectors / fakeBpb.spc;
                    }

                    if (clusters < 4089)
                    {
                        isFat12 = true;
                    }
                    else
                    {
                        isFat16 = true;
                    }
                }

                if (isFat12)
                {
                    switch (bpbKind)
                    {
                    case BpbKind.Atari:
                        sb.AppendLine("Atari FAT12");

                        break;

                    case BpbKind.Apricot:
                        sb.AppendLine("Apricot FAT12");

                        break;

                    case BpbKind.Human:
                        sb.AppendLine("Human68k FAT12");

                        break;

                    default:
                        sb.AppendLine("Microsoft FAT12");

                        break;
                    }

                    XmlFsType.Type = "FAT12";
                }
                else if (isFat16)
                {
                    sb.AppendLine(bpbKind == BpbKind.Atari
                                      ? "Atari FAT16"
                                      : bpbKind == BpbKind.Human
                                          ? "Human68k FAT16"
                                          : "Microsoft FAT16");

                    XmlFsType.Type = "FAT16";
                }

                if (bpbKind == BpbKind.Atari)
                {
                    if (atariBpb.serial_no[0] == 0x49 &&
                        atariBpb.serial_no[1] == 0x48 &&
                        atariBpb.serial_no[2] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        XmlFsType.VolumeSerial =
                            $"{atariBpb.serial_no[0]:X2}{atariBpb.serial_no[1]:X2}{atariBpb.serial_no[2]:X2}";
                    }

                    XmlFsType.SystemIdentifier = StringHandlers.CToString(atariBpb.oem_name);

                    if (string.IsNullOrEmpty(XmlFsType.SystemIdentifier))
                    {
                        XmlFsType.SystemIdentifier = null;
                    }
                }
                else if (fakeBpb.oem_name != null)
                {
                    if (fakeBpb.oem_name[5] == 0x49 &&
                        fakeBpb.oem_name[6] == 0x48 &&
                        fakeBpb.oem_name[7] == 0x43)
                    {
                        sb.AppendLine("Volume has been modified by Windows 9x/Me Volume Tracker.");
                    }
                    else
                    {
                        // Later versions of Windows create a DOS 3 BPB without OEM name on 8 sectors/track floppies
                        // OEM ID should be ASCII, otherwise ignore it
                        if (fakeBpb.oem_name[0] >= 0x20 &&
                            fakeBpb.oem_name[0] <= 0x7F &&
                            fakeBpb.oem_name[1] >= 0x20 &&
                            fakeBpb.oem_name[1] <= 0x7F &&
                            fakeBpb.oem_name[2] >= 0x20 &&
                            fakeBpb.oem_name[2] <= 0x7F &&
                            fakeBpb.oem_name[3] >= 0x20 &&
                            fakeBpb.oem_name[3] <= 0x7F &&
                            fakeBpb.oem_name[4] >= 0x20 &&
                            fakeBpb.oem_name[4] <= 0x7F &&
                            fakeBpb.oem_name[5] >= 0x20 &&
                            fakeBpb.oem_name[5] <= 0x7F &&
                            fakeBpb.oem_name[6] >= 0x20 &&
                            fakeBpb.oem_name[6] <= 0x7F &&
                            fakeBpb.oem_name[7] >= 0x20 &&
                            fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name);
                        }
                        else if (fakeBpb.oem_name[0] < 0x20 &&
                                 fakeBpb.oem_name[1] >= 0x20 &&
                                 fakeBpb.oem_name[1] <= 0x7F &&
                                 fakeBpb.oem_name[2] >= 0x20 &&
                                 fakeBpb.oem_name[2] <= 0x7F &&
                                 fakeBpb.oem_name[3] >= 0x20 &&
                                 fakeBpb.oem_name[3] <= 0x7F &&
                                 fakeBpb.oem_name[4] >= 0x20 &&
                                 fakeBpb.oem_name[4] <= 0x7F &&
                                 fakeBpb.oem_name[5] >= 0x20 &&
                                 fakeBpb.oem_name[5] <= 0x7F &&
                                 fakeBpb.oem_name[6] >= 0x20 &&
                                 fakeBpb.oem_name[6] <= 0x7F &&
                                 fakeBpb.oem_name[7] >= 0x20 &&
                                 fakeBpb.oem_name[7] <= 0x7F)
                        {
                            XmlFsType.SystemIdentifier = StringHandlers.CToString(fakeBpb.oem_name, Encoding, start: 1);
                        }
                    }

                    if (fakeBpb.signature == 0x28 ||
                        fakeBpb.signature == 0x29)
                    {
                        XmlFsType.VolumeSerial = $"{fakeBpb.serial_no:X8}";
                    }
                }

                if (XmlFsType.SystemIdentifier != null)
                {
                    sb.AppendFormat("OEM Name: {0}", XmlFsType.SystemIdentifier.Trim()).AppendLine();
                }

                sb.AppendFormat("{0} bytes per sector.", fakeBpb.bps).AppendLine();

                if (bpbKind != BpbKind.Human)
                {
                    if (fakeBpb.sectors == 0)
                    {
                        sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.big_sectors,
                                        fakeBpb.big_sectors * fakeBpb.bps).AppendLine();

                        XmlFsType.Clusters = fakeBpb.spc == 0 ? fakeBpb.big_sectors : fakeBpb.big_sectors / fakeBpb.spc;
                    }
                    else
                    {
                        sb.AppendFormat("{0} sectors on volume ({1} bytes).", fakeBpb.sectors,
                                        fakeBpb.sectors * fakeBpb.bps).AppendLine();

                        XmlFsType.Clusters =
                            (ulong)(fakeBpb.spc == 0 ? fakeBpb.sectors : fakeBpb.sectors / fakeBpb.spc);
                    }
                }
                else
                {
                    XmlFsType.Clusters = humanBpb.clusters == 0 ? humanBpb.big_clusters : humanBpb.clusters;

                    sb.AppendFormat("{0} sectors on volume ({1} bytes).",
                                    (XmlFsType.Clusters * humanBpb.bpc) / imagePlugin.Info.SectorSize,
                                    XmlFsType.Clusters * humanBpb.bpc).AppendLine();
                }

                sb.AppendFormat("{0} sectors per cluster.", fakeBpb.spc).AppendLine();
                sb.AppendFormat("{0} clusters on volume.", XmlFsType.Clusters).AppendLine();
                XmlFsType.ClusterSize = (uint)(fakeBpb.bps * fakeBpb.spc);
                sb.AppendFormat("{0} sectors reserved between BPB and FAT.", fakeBpb.rsectors).AppendLine();
                sb.AppendFormat("{0} FATs.", fakeBpb.fats_no).AppendLine();
                sb.AppendFormat("{0} entries on root directory.", fakeBpb.root_ent).AppendLine();

                if (fakeBpb.media > 0)
                {
                    sb.AppendFormat("Media descriptor: 0x{0:X2}", fakeBpb.media).AppendLine();
                }

                sb.AppendFormat("{0} sectors per FAT.", fakeBpb.spfat).AppendLine();

                if (fakeBpb.sptrk > 0 &&
                    fakeBpb.sptrk < 64 &&
                    fakeBpb.heads > 0 &&
                    fakeBpb.heads < 256)
                {
                    sb.AppendFormat("{0} sectors per track.", fakeBpb.sptrk).AppendLine();
                    sb.AppendFormat("{0} heads.", fakeBpb.heads).AppendLine();
                }

                if (fakeBpb.hsectors <= partition.Start)
                {
                    sb.AppendFormat("{0} hidden sectors before BPB.", fakeBpb.hsectors).AppendLine();
                }

                if (fakeBpb.signature == 0x28 ||
                    fakeBpb.signature == 0x29 ||
                    andosOemCorrect)
                {
                    sb.AppendFormat("Drive number: 0x{0:X2}", fakeBpb.drive_no).AppendLine();

                    if (XmlFsType.VolumeSerial != null)
                    {
                        sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine();
                    }

                    if ((fakeBpb.flags & 0xF8) == 0x00)
                    {
                        if ((fakeBpb.flags & 0x01) == 0x01)
                        {
                            sb.AppendLine("Volume should be checked on next mount.");
                            XmlFsType.Dirty = true;
                        }

                        if ((fakeBpb.flags & 0x02) == 0x02)
                        {
                            sb.AppendLine("Disk surface should be on next mount.");
                        }
                    }

                    if (fakeBpb.signature == 0x29 || andosOemCorrect)
                    {
                        XmlFsType.VolumeName = Encoding.ASCII.GetString(fakeBpb.volume_label);
                        sb.AppendFormat("Filesystem type: {0}", Encoding.ASCII.GetString(fakeBpb.fs_type)).AppendLine();
                    }
                }
                else if (bpbKind == BpbKind.Atari &&
                         XmlFsType.VolumeSerial != null)
                {
                    sb.AppendFormat("Volume Serial Number: {0}", XmlFsType.VolumeSerial).AppendLine();
                }

                bootChk = Sha1Context.Data(fakeBpb.boot_code, out _);

                // Workaround that PCExchange jumps into "FAT16   "...
                if (XmlFsType.SystemIdentifier == "PCX 2.0 ")
                {
                    fakeBpb.jump[1] += 8;
                }

                // Check that jumps to a correct boot code position and has boot signature set.
                // This will mean that the volume will boot, even if just to say "this is not bootable change disk"......
                if (XmlFsType.Bootable == false &&
                    fakeBpb.jump != null)
                {
                    XmlFsType.Bootable |=
                        (fakeBpb.jump[0] == 0xEB && fakeBpb.jump[1] >= minBootNearJump && fakeBpb.jump[1] < 0x80) ||
                        (fakeBpb.jump[0] == 0xE9 && fakeBpb.jump.Length >= 3 &&
                         BitConverter.ToUInt16(fakeBpb.jump, 1) >= minBootNearJump &&
                         BitConverter.ToUInt16(fakeBpb.jump, 1) <= 0x1FC);
                }

                sectorsPerRealSector = fakeBpb.bps / imagePlugin.Info.SectorSize;

                // First root directory sector
                rootDirectorySector =
                    (ulong)((fakeBpb.spfat * fakeBpb.fats_no) + fakeBpb.rsectors) * sectorsPerRealSector;

                sectorsForRootDirectory = (uint)((fakeBpb.root_ent * 32) / imagePlugin.Info.SectorSize);
            }

            if (extraInfo != null)
            {
                sb.Append(extraInfo);
            }

            if (rootDirectorySector + partition.Start < partition.End &&
                imagePlugin.Info.XmlMediaType != XmlMediaType.OpticalDisc)
            {
                byte[] rootDirectory =
                    imagePlugin.ReadSectors(rootDirectorySector + partition.Start, sectorsForRootDirectory);

                if (bpbKind == BpbKind.DecRainbow)
                {
                    var rootMs = new MemoryStream();

                    foreach (byte[] tmp in from ulong rootSector in new[]
                    {
                        0x17, 0x19, 0x1B, 0x1D, 0x1E, 0x20
                    } select imagePlugin.ReadSector(rootSector))
                    {
                        rootMs.Write(tmp, 0, tmp.Length);
                    }

                    rootDirectory = rootMs.ToArray();
                }

                for (int i = 0; i < rootDirectory.Length; i += 32)
                {
                    // Not a correct entry
                    if (rootDirectory[i] < DIRENT_MIN &&
                        rootDirectory[i] != DIRENT_E5)
                    {
                        continue;
                    }

                    // Deleted or subdirectory entry
                    if (rootDirectory[i] == DIRENT_SUBDIR ||
                        rootDirectory[i] == DIRENT_DELETED)
                    {
                        continue;
                    }

                    // Not a volume label
                    if (rootDirectory[i + 0x0B] != 0x08 &&
                        rootDirectory[i + 0x0B] != 0x28)
                    {
                        continue;
                    }

                    DirectoryEntry entry =
                        Marshal.ByteArrayToStructureLittleEndian <DirectoryEntry>(rootDirectory, i, 32);

                    byte[] fullname = new byte[11];
                    Array.Copy(entry.filename, 0, fullname, 0, 8);
                    Array.Copy(entry.extension, 0, fullname, 8, 3);
                    string volname = Encoding.GetString(fullname).Trim();

                    if (!string.IsNullOrEmpty(volname))
                    {
                        XmlFsType.VolumeName =
                            entry.caseinfo.HasFlag(CaseInfo.AllLowerCase) ? volname.ToLower() : volname;
                    }

                    if (entry.ctime > 0 &&
                        entry.cdate > 0)
                    {
                        XmlFsType.CreationDate = DateHandlers.DosToDateTime(entry.cdate, entry.ctime);

                        if (entry.ctime_ms > 0)
                        {
                            XmlFsType.CreationDate = XmlFsType.CreationDate.AddMilliseconds(entry.ctime_ms * 10);
                        }

                        XmlFsType.CreationDateSpecified = true;
                        sb.AppendFormat("Volume created on {0}", XmlFsType.CreationDate).AppendLine();
                    }

                    if (entry.mtime > 0 &&
                        entry.mdate > 0)
                    {
                        XmlFsType.ModificationDate          = DateHandlers.DosToDateTime(entry.mdate, entry.mtime);
                        XmlFsType.ModificationDateSpecified = true;
                        sb.AppendFormat("Volume last modified on {0}", XmlFsType.ModificationDate).AppendLine();
                    }

                    if (entry.adate > 0)
                    {
                        sb.AppendFormat("Volume last accessed on {0:d}", DateHandlers.DosToDateTime(entry.adate, 0)).
                        AppendLine();
                    }

                    break;
                }
            }

            if (!string.IsNullOrEmpty(XmlFsType.VolumeName))
            {
                sb.AppendFormat("Volume label: {0}", XmlFsType.VolumeName).AppendLine();
            }

            if (XmlFsType.Bootable)
            {
                // Intel short jump
                if (bpbSector[0] == 0xEB &&
                    bpbSector[1] < 0x80)
                {
                    int    sigSize  = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
                    byte[] bootCode = new byte[512 - sigSize - bpbSector[1] - 2];
                    Array.Copy(bpbSector, bpbSector[1] + 2, bootCode, 0, bootCode.Length);
                    Sha1Context.Data(bootCode, out _);
                }

                // Intel big jump
                else if (bpbSector[0] == 0xE9 &&
                         BitConverter.ToUInt16(bpbSector, 1) < 0x1FC)
                {
                    int    sigSize  = bpbSector[510] == 0x55 && bpbSector[511] == 0xAA ? 2 : 0;
                    byte[] bootCode = new byte[512 - sigSize - BitConverter.ToUInt16(bpbSector, 1) - 3];
                    Array.Copy(bpbSector, BitConverter.ToUInt16(bpbSector, 1) + 3, bootCode, 0, bootCode.Length);
                    Sha1Context.Data(bootCode, out _);
                }

                sb.AppendLine("Volume is bootable");
                sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
                string bootName = knownBootHashes.FirstOrDefault(t => t.hash == bootChk).name;

                if (string.IsNullOrWhiteSpace(bootName))
                {
                    sb.AppendLine("Unknown boot code.");
                }
                else
                {
                    sb.AppendFormat("Boot code corresponds to {0}", bootName).AppendLine();
                }
            }

            information = sb.ToString();
        }
Ejemplo n.º 29
0
        internal static List <ChecksumType> GetChecksums(byte[] data, EnableChecksum enabled = EnableChecksum.All)
        {
            IChecksum adler32CtxData = null;
            IChecksum crc16CtxData   = null;
            IChecksum crc32CtxData   = null;
            IChecksum crc64CtxData   = null;
            IChecksum md5CtxData     = null;

            #if !NETSTANDARD2_0
            IChecksum ripemd160CtxData = null;
            #endif
            IChecksum sha1CtxData   = null;
            IChecksum sha256CtxData = null;
            IChecksum sha384CtxData = null;
            IChecksum sha512CtxData = null;
            IChecksum ssctxData     = null;
            IChecksum f16CtxData    = null;
            IChecksum f32CtxData    = null;

            Thread adlerThreadData = new Thread(UpdateHash);
            Thread crc16ThreadData = new Thread(UpdateHash);
            Thread crc32ThreadData = new Thread(UpdateHash);
            Thread crc64ThreadData = new Thread(UpdateHash);
            Thread md5ThreadData   = new Thread(UpdateHash);
            #if !NETSTANDARD2_0
            Thread ripemd160ThreadData = new Thread(UpdateHash);
            #endif
            Thread sha1ThreadData    = new Thread(UpdateHash);
            Thread sha256ThreadData  = new Thread(UpdateHash);
            Thread sha384ThreadData  = new Thread(UpdateHash);
            Thread sha512ThreadData  = new Thread(UpdateHash);
            Thread spamsumThreadData = new Thread(UpdateHash);
            Thread f16ThreadData     = new Thread(UpdateHash);
            Thread f32ThreadData     = new Thread(UpdateHash);

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                adler32CtxData = new Adler32Context();
                HashPacket adlerPktData = new HashPacket {
                    Context = adler32CtxData, Data = data
                };
                adlerThreadData.Start(adlerPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                crc16CtxData = new Crc16Context();
                HashPacket crc16PktData = new HashPacket {
                    Context = crc16CtxData, Data = data
                };
                crc16ThreadData.Start(crc16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                crc32CtxData = new Crc32Context();
                HashPacket crc32PktData = new HashPacket {
                    Context = crc32CtxData, Data = data
                };
                crc32ThreadData.Start(crc32PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                crc64CtxData = new Crc64Context();
                HashPacket crc64PktData = new HashPacket {
                    Context = crc64CtxData, Data = data
                };
                crc64ThreadData.Start(crc64PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                md5CtxData = new Md5Context();
                HashPacket md5PktData = new HashPacket {
                    Context = md5CtxData, Data = data
                };
                md5ThreadData.Start(md5PktData);
            }

            #if !NETSTANDARD2_0
            if (enabled.HasFlag(EnableChecksum.Ripemd160))
            {
                ripemd160CtxData = new Ripemd160Context();
                HashPacket ripemd160PktData = new HashPacket {
                    Context = ripemd160CtxData, Data = data
                };
                ripemd160ThreadData.Start(ripemd160PktData);
            }
            #endif

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                sha1CtxData = new Sha1Context();
                HashPacket sha1PktData = new HashPacket {
                    Context = sha1CtxData, Data = data
                };
                sha1ThreadData.Start(sha1PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                sha256CtxData = new Sha256Context();
                HashPacket sha256PktData = new HashPacket {
                    Context = sha256CtxData, Data = data
                };
                sha256ThreadData.Start(sha256PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                sha384CtxData = new Sha384Context();
                HashPacket sha384PktData = new HashPacket {
                    Context = sha384CtxData, Data = data
                };
                sha384ThreadData.Start(sha384PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                sha512CtxData = new Sha512Context();
                HashPacket sha512PktData = new HashPacket {
                    Context = sha512CtxData, Data = data
                };
                sha512ThreadData.Start(sha512PktData);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                ssctxData = new SpamSumContext();
                HashPacket spamsumPktData = new HashPacket {
                    Context = ssctxData, Data = data
                };
                spamsumThreadData.Start(spamsumPktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                f16CtxData = new Fletcher16Context();
                HashPacket f16PktData = new HashPacket {
                    Context = f16CtxData, Data = data
                };
                f16ThreadData.Start(f16PktData);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                f32CtxData = new Fletcher32Context();
                HashPacket f32PktData = new HashPacket {
                    Context = f32CtxData, Data = data
                };
                f32ThreadData.Start(f32PktData);
            }

            while (adlerThreadData.IsAlive || crc16ThreadData.IsAlive || crc32ThreadData.IsAlive ||
                   crc64ThreadData.IsAlive || md5ThreadData.IsAlive ||
                  #if !NETSTANDARD2_0
                   ripemd160ThreadData.IsAlive ||
                  #endif
                   sha1ThreadData.IsAlive || sha256ThreadData.IsAlive || sha384ThreadData.IsAlive ||
                   sha512ThreadData.IsAlive || spamsumThreadData.IsAlive || f16ThreadData.IsAlive ||
                   f32ThreadData.IsAlive)
            {
            }

            List <ChecksumType> dataChecksums = new List <ChecksumType>();
            ChecksumType        chk;

            if (enabled.HasFlag(EnableChecksum.Adler32))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.adler32, Value = adler32CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc16))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.crc16, Value = crc16CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc32))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.crc32, Value = crc32CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Crc64))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.crc64, Value = crc64CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Md5))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.md5, Value = md5CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            #if !NETSTANDARD2_0
            if (enabled.HasFlag(EnableChecksum.Ripemd160))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.ripemd160, Value = ripemd160CtxData.End()
                };
                dataChecksums.Add(chk);
            }
            #endif

            if (enabled.HasFlag(EnableChecksum.Sha1))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.sha1, Value = sha1CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha256))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.sha256, Value = sha256CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha384))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.sha384, Value = sha384CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Sha512))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.sha512, Value = sha512CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.SpamSum))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.spamsum, Value = ssctxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher16))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.fletcher16, Value = f16CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            if (enabled.HasFlag(EnableChecksum.Fletcher32))
            {
                chk = new ChecksumType {
                    type = ChecksumTypeType.fletcher32, Value = f32CtxData.End()
                };
                dataChecksums.Add(chk);
            }

            return(dataChecksums);
        }