public sealed class CertificateDirectoryParser
{
    public IReadOnlyList<CertificateInfo> Parse(byte[] rawBytes, NtHeaders nt)
    {
        if (nt.OptionalHeader.DataDirectories.Count <= 4)
        {
            return Array.Empty<CertificateInfo>();
        }

        var dir = nt.OptionalHeader.DataDirectories[4];
        if (dir.VirtualAddress == 0 || dir.Size == 0)
        {
            return Array.Empty<CertificateInfo>();
        }

        // Certificate directory uses file offsets, not RVA.
        var pos = (int)dir.VirtualAddress;
        var end = Math.Min(rawBytes.Length, pos + (int)dir.Size);
        var items = new List<CertificateInfo>();

        while (pos + 8 <= end)
        {
            var length = BitConverter.ToUInt32(rawBytes, pos);
            var revision = BitConverter.ToUInt16(rawBytes, pos + 4);
            var type = BitConverter.ToUInt16(rawBytes, pos + 6);

            if (length < 8 || pos + length > end)
            {
                break;
            }

            var dataLen = (int)length - 8;
            var data = new byte[dataLen];
            Buffer.BlockCopy(rawBytes, pos + 8, data, 0, dataLen);
            items.Add(new CertificateInfo(length, revision, type, data));

            var aligned = (int)length + 7 & ~7;
            pos += aligned;
        }

        return items;
    }
}