Пример #1
0
        private static BaseRelocationBlock[] GetBaseRelocationsFor(string file, PEFile pe)
        {
            var stream = new MemoryStream(File.ReadAllBytes(file));
            var reader = new BinaryStreamReader(stream, new byte[1024]);
            pe.ReadFrom(reader);

            var baseRelocationDirectory = pe.OptionalHeader.DataDirectories[(int)DataDirectoryKind.BaseRelocation];

            var rvaStream = new RvaStream(
                stream,
                pe.SectionHeaders.Select(
                s => new RvaStream.Range
                {
                    PhysicalAddress = s.PointerToRawData,
                    Size = s.VirtualSize,
                    VirtualAddress = s.VirtualAddress
                })
                .ToArray());

            rvaStream.Position = baseRelocationDirectory.VirtualAddress;

            var sectionReader = new BinaryStreamReader(rvaStream, new byte[32]);

            var result = BaseRelocationBlock.ReadBlocks(sectionReader, baseRelocationDirectory.Size);
            return result;
        }
Пример #2
0
 public static RefType Read(BinaryStreamReader signatureBlobReader)
 {
     var leadByte = (ElementType)signatureBlobReader.ReadByte();
     if (leadByte == ElementType.ByRef)
     {
         Type t = Type.Read(leadByte, signatureBlobReader);
         return new ByRef
         {
             Type = t
         };
     }
     else if (leadByte == ElementType.TypedByRef)
     {
         return TypedByRef.Instance;
     }
     else if (leadByte == ElementType.Void)
     {
         return Void.Instance;
     }
     else
     {
         Type t = Type.Read(leadByte, signatureBlobReader);
         return new DirectType
         {
             Type = t
         };
     }
 }
Пример #3
0
        public static Param Read(BinaryStreamReader signatureBlobReader)
        {
            ElementType leadByte;

            var customMods = CustomMod.ReadCustomModArray(out leadByte, signatureBlobReader);

            switch (leadByte)
            {
                case ElementType.ByRef:
                    leadByte = (ElementType)signatureBlobReader.ReadByte();
                    return new ByRef
                    {
                        Type = Type.Read(leadByte, signatureBlobReader)
                    };

                case ElementType.TypedByRef:
                    return new TypedByRef();

                default:
                    return new DirectType
                    {
                        Type = Type.Read(leadByte, signatureBlobReader)
                    };
            }
        }
Пример #4
0
 public void ReadByteReadByte_213()
 {
     var reader = new BinaryStreamReader(new MemoryStream(new byte[] { 0, 213 }), new byte[20]);
     reader.ReadByte();
     byte value = reader.ReadByte();
     Assert.AreEqual(213, value);
 }
Пример #5
0
 static void ReadResourceDataEntry(BinaryStreamReader reader, DataEntry dataEntry)
 {
     dataEntry.DataRVA = reader.ReadUInt32();
     dataEntry.Size = reader.ReadUInt32();
     dataEntry.Codepage = reader.ReadUInt32();
     dataEntry.Reserved = reader.ReadUInt32();
 }
Пример #6
0
        private static Mi.PE.Unmanaged.Export.Header GetExportFor(string file, PEFile pe)
        {
            var stream = new MemoryStream(File.ReadAllBytes(file));
            var reader = new BinaryStreamReader(stream, new byte[1024]);
            pe.ReadFrom(reader);

            var exportDirectory = pe.OptionalHeader.DataDirectories[(int)DataDirectoryKind.ExportSymbols];

            var rvaStream = new RvaStream(
                stream,
                pe.SectionHeaders.Select(
                s => new RvaStream.Range
                {
                    PhysicalAddress = s.PointerToRawData,
                    Size = s.VirtualSize,
                    VirtualAddress = s.VirtualAddress
                })
                .ToArray());

            rvaStream.Position = exportDirectory.VirtualAddress;

            var sectionReader = new BinaryStreamReader(rvaStream, new byte[32]);

            var exports = new Mi.PE.Unmanaged.Export.Header();
            exports.ReadExports(sectionReader, exportDirectory.Size);
            return exports;
        }
Пример #7
0
        private static ModuleDefinition GetClrBasicsFor(string file, PEFile pe)
        {
            var stream = new MemoryStream(File.ReadAllBytes(file));
            var reader = new BinaryStreamReader(stream, new byte[1024]);
            pe.ReadFrom(reader);

            var clrDirectory = pe.OptionalHeader.DataDirectories[(int)DataDirectoryKind.Clr];

            var rvaStream = new RvaStream(
                stream,
                pe.SectionHeaders.Select(
                s => new RvaStream.Range
                {
                    PhysicalAddress = s.PointerToRawData,
                    Size = s.VirtualSize,
                    VirtualAddress = s.VirtualAddress
                })
                .ToArray());

            rvaStream.Position = clrDirectory.VirtualAddress;

            var sectionReader = new BinaryStreamReader(rvaStream, new byte[32]);

            var clrmod = new ModuleDefinition();
            ClrModuleReader.Read(sectionReader, clrmod);

            return clrmod;
        }
Пример #8
0
        static ResourceDirectory GetResourcesFor(string file, PEFile pe)
        {
            var stream = new MemoryStream(File.ReadAllBytes(file));
            var reader = new BinaryStreamReader(stream, new byte[1024]);
            pe.ReadFrom(reader);

            var resDataDir = pe.OptionalHeader.DataDirectories[(int)DataDirectoryKind.Resources];

            var rvaStream = new RvaStream(
                stream,
                pe.SectionHeaders.Select(
                s => new RvaStream.Range
                {
                    PhysicalAddress = s.PointerToRawData,
                    Size = s.VirtualSize,
                    VirtualAddress = s.VirtualAddress
                })
                .ToArray());

            rvaStream.Position = resDataDir.VirtualAddress;

            var sectionReader = new BinaryStreamReader(rvaStream, new byte[32]);

            var res = new ResourceDirectory();
            res.Read(sectionReader);

            return res;
        }
Пример #9
0
 static PEFile Read(byte[] bytes)
 {
     var stream = new MemoryStream(bytes);
     var reader = new BinaryStreamReader(stream, new byte[32]);
     var pe = new PEFile();
     pe.ReadFrom(reader);
     return pe;
 }
Пример #10
0
 public void ReadBytes_123()
 {
     var reader = new BinaryStreamReader(new MemoryStream(new byte[] { 1, 2, 3, }), new byte[20]);
     byte[] result = new byte[3];
     reader.ReadBytes(result, 0, 3);
     Assert.AreEqual(1, result[0]);
     Assert.AreEqual(2, result[1]);
     Assert.AreEqual(3, result[2]);
 }
Пример #11
0
        public MainPage()
        {
            InitializeComponent();

            var streamInfo = Application.GetResourceStream(new Uri("PEHeaderViewer.dll", UriKind.Relative));

            var reader = new BinaryStreamReader(streamInfo.Stream, new byte[32]);

            var pe = new PEFile();
            pe.ReadFrom(reader);

            {
                var tabControl = LayoutRoot.Children.OfType<TabControl>().FirstOrDefault();
                if (tabControl == null)
                {
                    tabControl = new TabControl();
                    LayoutRoot.Children.Add(tabControl);
                }

                var tabItem = new TabItem
                {
                    Header = "Self",
                    Content = new ScrollViewer
                    {
                        VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
                        HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
                        //Background = Brushes.White,
                        Padding = new Thickness(5),
                        Content = new PEFileView { DataContext = new PEFileViewModel(pe) }
                    }
                };

                tabControl.Items.Add(tabItem);

                tabControl.SelectedIndex = tabControl.Items.Count - 1;
            }

            this.Drop += new DragEventHandler(MainPage_Drop);

            if (Application.Current.IsRunningOutOfBrowser)
            {
                var timer = new DispatcherTimer
                {
                    Interval = TimeSpan.FromSeconds(1)
                };
                timer.Tick += delegate
                {
                    timer.Stop();

                    Application.Current.CheckAndDownloadUpdateAsync();
                };
            }
        }
Пример #12
0
        public void Read(BinaryStreamReader signatureBlobReader)
        {
            byte genericInst = signatureBlobReader.ReadByte();
            if (genericInst != 0x0a)
                throw new BadImageFormatException("Invalid leading byte in MethodSpec: " + genericInst + ".");

            uint? genArgCount = signatureBlobReader.ReadCompressedUInt32();
            if(genArgCount==null)
                throw new BadImageFormatException("Null value for MethodSpec.GenArgCount is not supported.");

            this.GenArgs = new TypeReference[genArgCount.Value];
        }
Пример #13
0
    private static void MeasureManyFilesLoad(string[] dllFiles)
    {
        var buffer = new byte[1024];

        var start = DateTime.UtcNow;
        foreach (var dll in dllFiles)
        {
            using (var dllStream = File.OpenRead(dll))
            {
                var pe = new PEFile();
                pe.ReadFrom(new BinaryStreamReader(dllStream, buffer));
            }
        }

        TimeSpan headersOnly = DateTime.UtcNow - start;

        byte[] buf = new byte[1024];
        byte[] contentBuf = new byte[1024*1024];
        start = DateTime.UtcNow;
        foreach (var dll in dllFiles)
        {
            using (var dllStream = File.OpenRead(dll))
            {
                var pe = new PEFile();
                var reader = new BinaryStreamReader(dllStream, buf);
                pe.ReadFrom(reader);

                while(reader.Position<dllStream.Length)
                {
                    reader.ReadBytes(contentBuf, 0, (int)Math.Min(contentBuf.Length, dllStream.Length - reader.Position));
                }
            }
        }

        TimeSpan headersAndContent = DateTime.UtcNow - start;

        start = DateTime.UtcNow;
        foreach (var dll in dllFiles)
        {
            System.Reflection.Assembly.Load(File.ReadAllBytes(dll));
        }

        TimeSpan reflectionLoad = DateTime.UtcNow - start;

        Console.WriteLine(
            dllFiles.Length + " dlls\t" +
            "Headers only: " + headersOnly.TotalSeconds.ToString("#0.000") + " sec." +
            "  " +
            "Headers and content: " + headersAndContent.TotalSeconds.ToString("#0.000") + " sec." +
            "  " +
            "Reflection: " + reflectionLoad.TotalSeconds.ToString("#0.000") + " sec." +
            "");
    }
Пример #14
0
 static void ReadSectionHeader(BinaryStreamReader reader, SectionHeader section)
 {
     section.Name = reader.ReadFixedZeroFilledAsciiString(SectionHeader.MaximumNameSize);
     section.VirtualSize = reader.ReadUInt32();
     section.VirtualAddress = reader.ReadUInt32();
     section.SizeOfRawData = reader.ReadUInt32();
     section.PointerToRawData = reader.ReadUInt32();
     section.PointerToRelocations = reader.ReadUInt32();
     section.PointerToLinenumbers = reader.ReadUInt32();
     section.NumberOfRelocations = reader.ReadUInt16();
     section.NumberOfLinenumbers = reader.ReadUInt16();
     section.Characteristics = (SectionCharacteristics)reader.ReadUInt32();
 }
Пример #15
0
        public void ReadFrom(BinaryStreamReader reader)
        {
            ReadDosHeader(reader);

            reader.Position = this.DosHeader.lfanew;
            ReadPEHeader(reader);
            ReadOptionalHeader(reader);

            this.SectionHeaders = new SectionHeader[this.PEHeader.NumberOfSections];

            for (int i = 0; i < this.SectionHeaders.Length; i++)
            {
                var sectionHeader = new SectionHeader();
                ReadSectionHeader(reader, sectionHeader);
                this.SectionHeaders[i] = sectionHeader;
            }
        }
Пример #16
0
        private static string ReadAlignedNameString(BinaryStreamReader reader)
        {
            var bytes = new List<byte>();
            while (true)
            {
                var b = reader.ReadByte();
                if (b == 0)
                    break;

                bytes.Add(b);
            }

            int skipCount = -1 + ((bytes.Count + 4) & ~3) - bytes.Count;

            reader.Position += skipCount;

            return Encoding.UTF8.GetString(bytes.ToArray(), 0, bytes.Count);
        }
Пример #17
0
        static void Main(string[] args)
        {
            var pe = new PEFile();
            var originalBytes = Properties.Resources.console_anycpu;
            var reader = new BinaryStreamReader(new MemoryStream(originalBytes), new byte[1024]);
            pe.ReadFrom(reader);

            using (var output = File.Create("console.anycpu.exe"))
            {
                var writer = new BinaryStreamWriter(output);
                pe.WriteTo(writer);

                while (reader.Position < originalBytes.Length)
                {
                    writer.WriteByte(reader.ReadByte());
                }
            }
        }
Пример #18
0
        public static MethodSig Read(BinaryStreamReader signatureBlobReader)
        {
            var callingConvention = (CallingConventions)signatureBlobReader.ReadByte();

            MethodSig result;
            switch (callingConvention & ~CallingConventions.HasThis & ~CallingConventions.ExplicitThis)
            {
                case CallingConventions.Default:
                    result = new Default();
                    break;

                case CallingConventions.C:
                    result = new C();
                    break;

                case CallingConventions.StdCall:
                    result = new StdCall();
                    break;

                case CallingConventions.FastCall:
                    result = new FastCall();
                    break;

                case CallingConventions.VarArg:
                    result = new VarArg();
                    break;

                case CallingConventions.Generic:
                    {
                        var typed = new Generic();
                        typed.ReadDetails(signatureBlobReader);
                        result = typed;
                    }
                    break;

                default:
                    throw new BadImageFormatException("Invalid calling convention byte "+callingConvention+".");
            }

            result.ReadParameters(signatureBlobReader);

            return result;
        }
Пример #19
0
        void ReadDosHeader(BinaryStreamReader reader)
        {
            if (this.DosHeader == null)
                this.DosHeader = new DosHeader();

            var signature = (MZSignature)reader.ReadInt16();
            if (signature != MZSignature.MZ)
                throw new BadImageFormatException("MZ signature expected, " + ((ushort)signature).ToString("X4") + "h found.");

            this.DosHeader.cblp = reader.ReadUInt16();
            this.DosHeader.cp = reader.ReadUInt16();
            this.DosHeader.crlc = reader.ReadUInt16();
            this.DosHeader.cparhdr = reader.ReadUInt16();
            this.DosHeader.minalloc = reader.ReadUInt16();
            this.DosHeader.maxalloc = reader.ReadUInt16();
            this.DosHeader.ss = reader.ReadUInt16();
            this.DosHeader.sp = reader.ReadUInt16();
            this.DosHeader.csum = reader.ReadUInt16();
            this.DosHeader.ip = reader.ReadUInt16();
            this.DosHeader.cs = reader.ReadUInt16();
            this.DosHeader.lfarlc = reader.ReadUInt16();
            this.DosHeader.ovno = reader.ReadUInt16();

            this.DosHeader.res1 = reader.ReadUInt64();

            this.DosHeader.oemid = reader.ReadUInt16();
            this.DosHeader.oeminfo = reader.ReadUInt16();

            this.DosHeader.ReservedNumber0 = reader.ReadUInt32();
            this.DosHeader.ReservedNumber1 = reader.ReadUInt32();
            this.DosHeader.ReservedNumber2 = reader.ReadUInt32();
            this.DosHeader.ReservedNumber3 = reader.ReadUInt32();
            this.DosHeader.ReservedNumber4 = reader.ReadUInt32();
            this.DosHeader.lfanew = reader.ReadUInt32();

            if (this.DosHeader.lfanew > DosHeader.Size)
            {
                this.DosStub = new byte[this.DosHeader.lfanew - DosHeader.Size];
                reader.ReadBytes(this.DosStub, 0, this.DosStub.Length);
            }
        }
Пример #20
0
        public static CustomMod[] ReadCustomModArray(out ElementType leadByte, BinaryStreamReader signatureBlobReader)
        {
            List<CustomMod> customMods = null;

            leadByte = (ElementType)signatureBlobReader.ReadByte();
            while (true)
            {
                var cmod = CustomMod.Read(signatureBlobReader, leadByte);
                if (cmod == null)
                    break;

                if (customMods == null)
                    customMods = new List<CustomMod>();

                customMods.Add(cmod);
            }

            if (customMods == null)
                return null;
            else
                return customMods.ToArray();
        }
Пример #21
0
        public static CustomMod Read(BinaryStreamReader signatureBlobReader, ElementType leadByte)
        {
            CustomMod result;
            if (leadByte == ElementType.CMod_Opt)
            {
                result = new CustomMod();
                result.Required = true;
            }
            else if (leadByte == ElementType.CMod_ReqD)
            {
                result = new CustomMod();
                result.Required = false;
            }
            else
            {
                return null;
            }

            result.Type = signatureBlobReader.ReadTypeDefOrRefOrSpecEncoded();

            return result;
        }
Пример #22
0
        void MainPage_Drop(object sender, DragEventArgs e)
        {
            if (e.Data != null)
            {
                var files = e.Data.GetData(DataFormats.FileDrop) as FileInfo[];

                if (files != null)
                {
                    foreach (var fi in files)
                    {
                        PEFile pe = new PEFile();
                        using(var stream = fi.OpenRead())
                        {
                            var reader = new BinaryStreamReader(stream, new byte[1024]);
                            pe.ReadFrom(reader);
                        }

                        myContentControl.Content = new Model.PEFileModel(fi.Name, pe);
                    }
                }
            }
        }
Пример #23
0
        static void Main(string[] args)
        {
            var pe = new PEFile();
            var stream = new MemoryStream(Properties.Resources.console_anycpu);
            var reader = new BinaryStreamReader(stream, new byte[1024]);
            pe.ReadFrom(reader);

            uint lowestPointerToRawData = uint.MaxValue;
            uint lowestVirtualAddress = uint.MaxValue;
            uint highestVirtualAddress = uint.MinValue;

            foreach (var s in pe.SectionHeaders)
            {
                lowestPointerToRawData = Math.Min(lowestPointerToRawData, s.PointerToRawData);
                lowestVirtualAddress = Math.Min(lowestVirtualAddress, s.VirtualAddress);
                highestVirtualAddress = Math.Max(highestVirtualAddress, s.VirtualAddress + (uint)s.VirtualSize);
            }

            byte[] allSectionContent = new byte[highestVirtualAddress - lowestVirtualAddress];
            foreach (var s in pe.SectionHeaders)
            {
                reader.Position = s.PointerToRawData;
                reader.ReadBytes(allSectionContent, (int)(s.VirtualAddress - lowestVirtualAddress), (int)s.VirtualSize);
            }

            pe.PEHeader.NumberOfSections = 1;
            var singleSection = pe.SectionHeaders[0];
            singleSection.VirtualSize = (uint)allSectionContent.Length;
            pe.SectionHeaders = new[] { singleSection };

            using (var peFileStream = File.Create("console.anycpu.insane.exe"))
            {
                var writer = new BinaryStreamWriter(peFileStream);
                pe.WriteTo(writer);
                writer.Position = lowestPointerToRawData;
                writer.WriteBytes(allSectionContent, 0, allSectionContent.Length);
            }
        }
Пример #24
0
        public MainPage()
        {
            InitializeComponent();

            Application.Current.Host.Settings.EnableAutoZoom = false;

            string fileName = new AssemblyName(this.GetType().Assembly.FullName).Name+".dll";
            var streamInfo = Application.GetResourceStream(new Uri(fileName, UriKind.Relative));

            var reader = new BinaryStreamReader(streamInfo.Stream, new byte[32]);

            var pe = new PEFile();
            pe.ReadFrom(reader);

            myContentControl.Content = new Model.PEFileModel(fileName, pe);
            myContentControl.Visibility = System.Windows.Visibility.Visible;

            this.MouseWheel += new MouseWheelEventHandler(MainPage_MouseWheel);

            this.AllowDrop = true;

            this.Drop += new DragEventHandler(MainPage_Drop);
        }
Пример #25
0
        void Read(BinaryStreamReader reader, long baseOffset)
        {
            this.Characteristics = reader.ReadUInt32();
            uint timestampNum = reader.ReadUInt32();
            this.Timestamp = PEFile.TimestampEpochUTC.AddSeconds(timestampNum);
            this.MajorVersion = reader.ReadUInt16();
            this.MinorVersion = reader.ReadUInt16();
            ushort nameEntryCount = reader.ReadUInt16();
            ushort idEntryCount = reader.ReadUInt16();

            List<DirectoryEntry> subdirectories = null;
            List<DataEntry> dataEntries = null;

            for (int i = 0; i < nameEntryCount + idEntryCount; i++)
            {
                uint idOrNameRva = reader.ReadUInt32();
                uint contentRva = reader.ReadUInt32();

                string name;
                uint id;

                const uint HighBit = 1U << 31;

                if ((idOrNameRva & HighBit)==0)
                {
                    id = idOrNameRva;
                    name = null;
                }
                else
                {
                    id = 0;
                    long savePosition = reader.Position;
                    uint namePositon = idOrNameRva & ~HighBit;
                    reader.Position = baseOffset + namePositon;
                    name = ReadName(reader);
                    reader.Position = savePosition;
                }

                if ((contentRva & HighBit) == 0) // high bit is set
                {
                    var dataEntry = new DataEntry
                    {
                        Name = name,
                        IntegerID = id
                    };

                    long savePosition = reader.Position;
                    reader.Position = baseOffset + contentRva;

                    ReadResourceDataEntry(reader, dataEntry);

                    if (dataEntries == null)
                        dataEntries = new List<DataEntry>();
                    dataEntries.Add(dataEntry);
                    reader.Position = savePosition;
                }
                else
                {
                    contentRva = contentRva & ~HighBit; // clear hight bit

                    long savePosition = reader.Position;
                    reader.Position = baseOffset + contentRva;

                    var directoryEntry = new DirectoryEntry
                    {
                        Name = name,
                        IntegerID = id
                    };

                    directoryEntry.Directory = new ResourceDirectory();
                    directoryEntry.Directory.Read(reader, baseOffset);

                    if (subdirectories == null)
                        subdirectories = new List<DirectoryEntry>();
                    subdirectories.Add(directoryEntry);
                    reader.Position = savePosition;
                }
            }

            this.Subdirectories = subdirectories == null ? EmptyDirectoryEntries : subdirectories.ToArray();
            this.DataEntries = dataEntries == null ? EmptyDataEntries : dataEntries.ToArray();
        }
Пример #26
0
 private static string ReadAsciiZAt(BinaryStreamReader reader, uint nameRva)
 {
     long savePosition = reader.Position;
     reader.Position = (int)nameRva;
     try
     {
         return ReadAsciiZ(reader);
     }
     finally
     {
         reader.Position = savePosition;
     }
 }
Пример #27
0
 public void Read(BinaryStreamReader reader)
 {
     Read(reader, reader.Position);
 }
Пример #28
0
 private string ReadName(BinaryStreamReader reader)
 {
     ushort length = reader.ReadUInt16();
     byte[] buf = new byte[length * 2]; // two-byte Unicode characters
     reader.ReadBytes(buf, 0, buf.Length);
     string result = Encoding.Unicode.GetString(buf, 0, buf.Length);
     return result;
 }
Пример #29
0
        public static Import[] ReadImports(BinaryStreamReader reader)
        {
            var resultList = new List<Import>();

            while(true)
            {
                uint originalFirstThunk = reader.ReadUInt32();
                uint timeDateStamp = reader.ReadUInt32();
                uint forwarderChain = reader.ReadUInt32();
                uint nameRva = reader.ReadUInt32();
                uint firstThunk = reader.ReadUInt32();

                string libraryName =
                    nameRva == 0 ? null : ReadAsciiZAt(reader, nameRva);

                uint thunkAddressPosition = originalFirstThunk == 0 ? firstThunk : originalFirstThunk;

                if (thunkAddressPosition == 0)
                    break;

                long savePosition = reader.Position;
                try
                {
                    while (true)
                    {
                        reader.Position = thunkAddressPosition;

                        uint importPosition = reader.ReadUInt32();
                        if (importPosition == 0)
                            break;

                        Import imp;

                        if ((importPosition & (1 << 31)) != 0)
                        {
                            imp = new Import
                            {
                                DllName = libraryName,
                                FunctionOrdinal = importPosition
                            };
                        }
                        else
                        {
                            reader.Position = (int)importPosition;

                            uint hint = reader.ReadUInt16();
                            string fname = ReadAsciiZ(reader);

                            imp = new Import
                            {
                                DllName = libraryName,
                                FunctionOrdinal = hint,
                                FunctionName = fname
                            };
                        }

                        resultList.Add(imp);

                        thunkAddressPosition += 8;
                    }
                }
                finally
                {
                    reader.Position = savePosition;
                }
            }

            return resultList.ToArray();
        }
Пример #30
0
        private static string ReadAsciiZ(BinaryStreamReader reader)
        {
            var result = new StringBuilder();
            while (true)
            {
                byte b = reader.ReadByte();
                if (b == 0)
                    break;

                const int maxLength = 512;

                if (result.Length > maxLength)
                    throw new InvalidOperationException("String is too long, for safety reasons the size limit for ASCIIZ strings is set to " + maxLength + ".");

                result.Append((char)b);
            }

            return result.ToString();
        }