public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            var blocks = CreateBlocks();

            int size = 0;

            foreach (var block in blocks)
            {
                size += (8 + (block.Entries.Count * 2).Align(4));
            }

            _blob = new BuildBlob(new byte[size]);

            // Build relocation blob fixup
            PE.Fixups.Add(new BuildRelocationFixup(_blob, blocks));

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.BaseRelocationTable, _blob));

            // Add blobs
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);

            // Set flags
            PE.Characteristics &= ~ImageCharacteristics.RELOCS_STRIPPED;
        }
예제 #2
0
        public override void Build()
        {
            var metadataBuilder = PE.Tasks.Get <MetadataBuilder>();

            if (metadataBuilder == null)
            {
                return;
            }

            var metadataBlob = metadataBuilder.Blob;

            if (metadataBlob == null)
            {
                return;
            }

            _blob = new BuildBlob(new byte[72]);

            // Add fixup
            PE.Fixups.Add(new CLIFixup(this));

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.CLIHeader, _blob));

            // Add blob
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
예제 #3
0
        public override void Build()
        {
            if (_metadata == null)
            {
                return;
            }

            FinalizeBuildModule();

            Initialize();

            SortTables();

            DoBuild();

            Write();

            // Add fixups
            PE.Fixups.Add(new MetadataFixup(this));

            // Add blobs
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);

            _state = null;
        }
        public override void Build()
        {
            if (_table == null)
            {
                return;
            }

            _state    = new State();
            _codeBlob = new BuildBlob();

            Initialize();

            switch (PE.Machine)
            {
            case MachineType.I386:
                BuildX86();
                break;

            case MachineType.IA64:
                BuildIA64();
                break;

            case MachineType.AMD64:
                BuildAMD64();
                break;

            default:
                throw new NotImplementedException();
            }

            // Add blobs
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_codeBlob, _blobPriority);

            // Change CLI flags
            var corHeaderBuilder = PE.Tasks.Get <CorHeaderBuilder>(true);

            if (PE.Is32Bits)
            {
                corHeaderBuilder.Flags &= ~CorFlags.ILOnly;
                corHeaderBuilder.Flags |= CorFlags.F32BitsRequired;
            }
            else
            {
                corHeaderBuilder.Flags &= ~CorFlags.ILOnly;
            }

            _state = null;
        }
        public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            _blob     = new BuildBlob();
            _dataBlob = new BuildBlob();

            int pos     = 0;
            int dataPos = 0;

            for (int i = 0; i < _table.Count; i++)
            {
                var fixup = _table[i];
                if (fixup.Count == 0)
                {
                    continue;
                }

                _blob.Write(ref pos, (uint)dataPos);                 // RVA
                _blob.Write(ref pos, (ushort)fixup.Count);           // Count
                _blob.Write(ref pos, (ushort)fixup.Type);            // Type

                bool is32Bits = ((fixup.Type & VTableFixupType.SlotSize32Bit) == VTableFixupType.SlotSize32Bit);

                for (int j = 0; j < fixup.Count; j++)
                {
                    _dataBlob.Write(ref dataPos, (uint)fixup[j]);

                    if (!is32Bits)
                    {
                        _dataBlob.Write(ref dataPos, (uint)0);
                    }
                }
            }

            // Add fixups
            PE.Fixups.Add(new WriteDataRVAFixup(this));

            // Add blobs
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);

            section = PE.GetSection(_dataSectionName);
            section.Blobs.Add(_dataBlob, _dataBlobPriority);
        }
        public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            _blob = new BuildBlob();

            int pos = 0;

            for (int i = 0; i < _table.Count; i++)
            {
                var entry = _table[i];

                if (entry.Data == null)
                {
                    continue;
                }

                int alignLength = entry.Data.Length.Align(8);

                int length = 8 + alignLength;
                _blob.Write(ref pos, (int)length);
                _blob.Write(ref pos, (ushort)entry.Revision);
                _blob.Write(ref pos, (ushort)entry.Type);
                _blob.Write(ref pos, entry.Data);

                int alignCount = alignLength - entry.Data.Length;
                if (alignCount > 0)
                {
                    _blob.Write(ref pos, 0, alignCount);
                }
            }

            // Set data directories
            PE.Fixups.Add(new SetDataDirectoryFixup(_blob));

            // Add blobs
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
        public override void Build()
        {
            if (_noCorStub)
            {
                return;
            }

            _blob = new BuildBlob();

            var relocBuilder = PE.Tasks.Get <BaseRelocationBuilder>(true);

            _relocTable = relocBuilder.GetOrCreateTable();

            DoBuild();

            // Add blob
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
예제 #8
0
        public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            _state = new State();

            var _tableData = new TableData();

            _tableData.Table = _table;

            BuildTable(_tableData);
            BuildEntries(_tableData);

            _state.StringPos          = _state.TreeSize;
            _state.DataDescriptionPos = _state.StringPos + _state.StringSize;
            _state.DataPos            = _state.DataDescriptionPos + _state.DataDescriptionSize;
            _state.DataPos            = _state.DataPos.Align(4);

            WriteTable(_tableData);
            WriteChildTables(_tableData);

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.ResourceTable, _state.Blob));

            // Add blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_state.Blob, _blobPriority);

            // Set state
            _blob = _state.Blob;

            _state = null;
        }
예제 #9
0
        public override void Build()
        {
            if (!_isSigned)
            {
                return;
            }

            int size = 0x80;

            _blob = new BuildBlob(new byte[size]);

            // Add blob
            var section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);

            // Set flags
            var corHeaderBuilder = PE.Tasks.Get <CorHeaderBuilder>(true);

            if (corHeaderBuilder != null)
            {
                corHeaderBuilder.Flags |= CorFlags.StrongNameSigned;
            }
        }
        public override void Build()
        {
            if (_table == null)
            {
                return;
            }

            _blob = new BuildBlob();

            // Calculate
            int addressTablePos  = 40;            // entry header
            int addressTableSize = _table.Count * 4;
            int nameTableSize    = (_table.DllName ?? "").Length + 1;
            var ordinals         = new List <int>();

            for (int i = 0; i < _table.Count; i++)
            {
                var entry = _table[i];

                if (!string.IsNullOrEmpty(entry.Name))
                {
                    nameTableSize += entry.Name.Length + 1;
                    ordinals.Add(i);
                }

                if (entry is BuildForwarderEntry)
                {
                    var forwarderEntry = (BuildForwarderEntry)entry;
                    nameTableSize += forwarderEntry.Forwarder.Length + 1;
                }
            }

            ordinals.Sort(delegate(int x, int y)
            {
                return(string.Compare(_table[x].Name, _table[y].Name));
            });

            int namePointerTablePos  = addressTablePos + addressTableSize;
            int namePointerTableSize = ordinals.Count * 4;
            int ordinalTablePos      = namePointerTablePos + namePointerTableSize;
            int ordinalTableSize     = ordinals.Count * 2;
            int nameTablePos         = ordinalTablePos + ordinalTableSize;

            // Write
            // Header
            int headerPos = 0;

            _blob.Write(ref headerPos, (uint)0);             // Characteristics
            _blob.Write(ref headerPos, (uint)PE.TimeDateStamp.To_time_t());
            _blob.Write(ref headerPos, (ushort)_table.MajorVersion);
            _blob.Write(ref headerPos, (ushort)_table.MinorVersion);

            PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, nameTablePos));
            _blob.Write(ref headerPos, (uint)0);                  // Name

            _blob.Write(ref headerPos, (uint)_table.OrdinalBase); // Base
            _blob.Write(ref headerPos, (uint)_table.Count);       // NumberOfFunctions
            _blob.Write(ref headerPos, (uint)ordinals.Count);     // NumberOfNames

            PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, addressTablePos));
            _blob.Write(ref headerPos, (uint)0);             // AddressOfFunctions

            PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, namePointerTablePos));
            _blob.Write(ref headerPos, (uint)0);             // AddressOfNames

            PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, ordinalTablePos));
            _blob.Write(ref headerPos, (uint)0);             // AddressOfNameOrdinals

            // Dll name
            string dllName = _table.DllName + '\0';

            _blob.Write(ref nameTablePos, dllName, Encoding.ASCII);

            // Export Address Table
            for (int i = 0; i < _table.Count; i++)
            {
                var entry = _table[i];
                if (entry is BuildRVAEntry)
                {
                    var rvaEntry = (BuildRVAEntry)entry;

                    PE.Fixups.Add(new WriteFunctionRVAFixup(_blob, addressTablePos, rvaEntry));
                    _blob.Write(ref addressTablePos, (uint)0);
                }
                else
                {
                    var forwarderEntry = (BuildForwarderEntry)entry;

                    PE.Fixups.Add(new WriteRVAFixup(_blob, addressTablePos, nameTablePos));
                    _blob.Write(ref addressTablePos, (uint)0);

                    string forwarder = forwarderEntry.Forwarder + '\0';
                    _blob.Write(ref nameTablePos, forwarder, Encoding.ASCII);
                }
            }

            // Name pointer/Ordinal
            for (int i = 0; i < ordinals.Count; i++)
            {
                int ordinal = ordinals[i];

                PE.Fixups.Add(new WriteRVAFixup(_blob, namePointerTablePos, nameTablePos));
                _blob.Write(ref namePointerTablePos, (uint)0);

                _blob.Write(ref ordinalTablePos, (ushort)ordinal);

                string name = _table[ordinal].Name + '\0';
                _blob.Write(ref nameTablePos, name, Encoding.ASCII);
            }

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.ExportTable, _blob));

            // Add blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
        public unsafe override void Build()
        {
            if (_dataBlob == null || _dataBlob.Length == 0)
            {
                return;
            }

            var relocBuilder = PE.Tasks.Get <BaseRelocationBuilder>();

            if (relocBuilder == null)
            {
                return;
            }

            var relocTable = relocBuilder.GetOrCreateTable();

            _blob = new BuildBlob();

            int pos = 0;

            if (PE.Is32Bits)
            {
                // Header
                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, 0));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (uint)0);                 // StartAddressOfRawData

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, _dataBlob.Length));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (uint)0);                  // EndAddressOfRawData

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader32) + 4));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (uint)0);                 // AddressOfIndex

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader32)));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (uint)0);                // AddressOfCallBacks

                _blob.Write(ref pos, (int)0);                 // SizeOfZeroFill
                _blob.Write(ref pos, (uint)0);                // Characteristics

                // CallBacks
                _blob.Write(ref pos, (uint)0);

                // Index
                _blob.Write(ref pos, (uint)0xCCCCCCCC);                 // Does't really matter, the OS will fill it in
            }
            else
            {
                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, 0));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (ulong)0);                 // StartAddressOfRawData

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, _dataBlob.Length));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (ulong)0);                  // EndAddressOfRawData

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader64) + 8));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (ulong)0);                 // AddressOfIndex

                PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader64)));
                relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW);
                _blob.Write(ref pos, (ulong)0);               // AddressOfCallBacks

                _blob.Write(ref pos, (int)0);                 // SizeOfZeroFill
                _blob.Write(ref pos, (uint)0);                // Characteristics

                // CallBacks
                _blob.Write(ref pos, (ulong)0);

                // Index
                _blob.Write(ref pos, (ulong)0xCCCCCCCC);                 // Does't really matter, the OS will fill it in
            }

            // Set data directories
            PE.Fixups.Add(new SetDataDirectoryFixup(_blob));

            // Add _blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
예제 #12
0
        public override void Build()
        {
            if (_info == null)
            {
                return;
            }

            var _blob = new BuildBlob();

            int pos = 0;

            if (PE.Is32Bits)
            {
                _blob.Write(ref pos, (int)_info.Characteristics);
                _blob.Write(ref pos, (int)_info.TimeDateStamp.To_time_t());
                _blob.Write(ref pos, (short)_info.MajorVersion);
                _blob.Write(ref pos, (short)_info.MinorVersion);
                _blob.Write(ref pos, (uint)_info.GlobalFlagsClear);
                _blob.Write(ref pos, (uint)_info.GlobalFlagsSet);
                _blob.Write(ref pos, (int)_info.CriticalSectionDefaultTimeout);
                _blob.Write(ref pos, (int)_info.DeCommitFreeBlockThreshold);
                _blob.Write(ref pos, (int)_info.DeCommitTotalFreeThreshold);
                _blob.Write(ref pos, (uint)_info.LockPrefixTable);
                _blob.Write(ref pos, (int)_info.MaximumAllocationSize);
                _blob.Write(ref pos, (int)_info.VirtualMemoryThreshold);
                _blob.Write(ref pos, (int)_info.ProcessHeapFlags);
                _blob.Write(ref pos, (uint)_info.ProcessAffinityMask);
                _blob.Write(ref pos, (short)_info.CSDVersion);
                _blob.Write(ref pos, (short)_info.Reserved1);
                _blob.Write(ref pos, (uint)_info.EditList);
                _blob.Write(ref pos, (uint)_info.SecurityCookie);
                _blob.Write(ref pos, (uint)_info.SEHandlerTable);
                _blob.Write(ref pos, (uint)_info.SEHandlerCount);
            }
            else
            {
                _blob.Write(ref pos, (int)_info.Characteristics);
                _blob.Write(ref pos, (int)_info.TimeDateStamp.To_time_t());
                _blob.Write(ref pos, (short)_info.MajorVersion);
                _blob.Write(ref pos, (short)_info.MinorVersion);
                _blob.Write(ref pos, (uint)_info.GlobalFlagsClear);
                _blob.Write(ref pos, (uint)_info.GlobalFlagsSet);
                _blob.Write(ref pos, (int)_info.CriticalSectionDefaultTimeout);
                _blob.Write(ref pos, (long)_info.DeCommitFreeBlockThreshold);
                _blob.Write(ref pos, (long)_info.DeCommitTotalFreeThreshold);
                _blob.Write(ref pos, (ulong)_info.LockPrefixTable);
                _blob.Write(ref pos, (long)_info.MaximumAllocationSize);
                _blob.Write(ref pos, (long)_info.VirtualMemoryThreshold);
                _blob.Write(ref pos, (ulong)_info.ProcessAffinityMask);
                _blob.Write(ref pos, (int)_info.ProcessHeapFlags);
                _blob.Write(ref pos, (short)_info.CSDVersion);
                _blob.Write(ref pos, (short)_info.Reserved1);
                _blob.Write(ref pos, (ulong)_info.EditList);
                _blob.Write(ref pos, (ulong)_info.SecurityCookie);
                _blob.Write(ref pos, (ulong)_info.SEHandlerTable);
                _blob.Write(ref pos, (ulong)_info.SEHandlerCount);
            }

            // Set data directories
            // For compatibility with Windows XP and earlier versions of Windows,
            // the size must be 64 for x86 images.
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.LoadConfigTable, _blob, 0, 64));

            // Add _blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }
        public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            _blob    = new BuildBlob();
            _iatBlob = new BuildBlob();

            // Calculate
            int lookupTableSize   = 0;
            int hintNameTableSize = 0;
            int lookupEntrySize   = PE.Is32Bits ? 4 : 8;

            for (int i = 0; i < _table.Count; i++)
            {
                var module = _table[i];

                for (int j = 0; j < module.Count; j++)
                {
                    var entry = module[j];

                    lookupTableSize += lookupEntrySize;

                    if (!string.IsNullOrEmpty(entry.Name))
                    {
                        hintNameTableSize += 2;                         // hint
                        hintNameTableSize += entry.Name.Length + 1;
                    }
                }

                lookupTableSize += lookupEntrySize;                 // null
            }

            int iatPos           = 0;
            int lookupTablePos   = (_table.Count + 1) * 20;           // header + null
            int hintNameTablePos = lookupTablePos + lookupTableSize;
            int dllNamePos       = hintNameTablePos + hintNameTableSize;

            // Write
            int headerPos = 0;

            for (int i = 0; i < _table.Count; i++)
            {
                var module = _table[i];

                // Header
                PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, lookupTablePos));
                _blob.Write(ref headerPos, (uint)0);                    // ImportLookupTableRVA

                _blob.Write(ref headerPos, (uint)0);                    // TimeDateStamp

                _blob.Write(ref headerPos, (int)module.ForwarderChain); // ForwarderChain

                PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, dllNamePos));
                _blob.Write(ref headerPos, (uint)0);                 // Name

                PE.Fixups.Add(new WriteRVAFixup(_blob, _iatBlob, headerPos, iatPos));
                _blob.Write(ref headerPos, (uint)0);                 // ImportAddressTableRVA

                // DllName
                string dllName = (module.DllName ?? "") + '\0';
                _blob.Write(ref dllNamePos, dllName, Encoding.ASCII);

                // ImportLookupTable / ImportAddressTable
                for (int j = 0; j < module.Count; j++)
                {
                    var entry = module[j];

                    if (PE.Is32Bits)
                    {
                        if (!string.IsNullOrEmpty(entry.Name))
                        {
                            // Import by name.
                            PE.Fixups.Add(
                                new WriteHintNameRVAFixup(
                                    _blob, _iatBlob, lookupTablePos, iatPos, hintNameTablePos));
                            _blob.Write(ref lookupTablePos, (uint)0);
                            _iatBlob.Write(ref iatPos, (uint)0);

                            // Hint/Name
                            _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal);
                            string name = entry.Name + '\0';
                            _blob.Write(ref hintNameTablePos, name, Encoding.ASCII);
                        }
                        else
                        {
                            // Import by ordinal.
                            uint ordinal = (uint)entry.Ordinal | 0x80000000;
                            _blob.Write(ref lookupTablePos, (uint)ordinal);
                            _iatBlob.Write(ref iatPos, (uint)ordinal);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(entry.Name))
                        {
                            // Import by name.
                            PE.Fixups.Add(
                                new WriteHintNameRVAFixup(
                                    _blob, _iatBlob, lookupTablePos, iatPos, hintNameTablePos));
                            _blob.Write(ref lookupTablePos, (ulong)0);
                            _iatBlob.Write(ref iatPos, (ulong)0);

                            // Hint/Name
                            _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal);
                            string name = entry.Name + '\0';
                            _blob.Write(ref hintNameTablePos, name, Encoding.ASCII);
                        }
                        else
                        {
                            // Import by ordinal.
                            ulong ordinal = (uint)entry.Ordinal | 0x8000000000000000;
                            _blob.Write(ref lookupTablePos, (ulong)ordinal);
                            _iatBlob.Write(ref iatPos, (ulong)ordinal);
                        }
                    }
                }

                if (PE.Is32Bits)
                {
                    // Null ImportLookupTable / ImportAddressTable
                    _blob.Write(ref lookupTablePos, 0, 4);
                    _iatBlob.Write(ref iatPos, 0, 4);
                }
                else
                {
                    // Null ImportLookupTable / ImportAddressTable
                    _blob.Write(ref lookupTablePos, 0, 8);
                    _iatBlob.Write(ref iatPos, 0, 8);
                }
            }

            // Null header
            _blob.Write(ref headerPos, 0, 20);

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.ImportTable, _blob));

            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.IAT, _iatBlob));

            // Add _blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);

            BuildSection iatSection = PE.GetSection(_iatSectionName);

            iatSection.Blobs.Add(_iatBlob, _iatBlobPriority);
        }
예제 #14
0
        public override void Build()
        {
            if (_table == null || _table.Count == 0)
            {
                return;
            }

            _blob = new BuildBlob();

            // Calculate
            int iatSize = 0;
            int namePointerTableSize = 0;
            int namePointerSize      = PE.Is32Bits ? 4 : 8;
            int hintNameTableSize    = 0;

            for (int i = 0; i < _table.Count; i++)
            {
                var module = _table[i];

                for (int j = 0; j < module.Count; j++)
                {
                    var entry = module[j];

                    iatSize += 4;
                    namePointerTableSize += namePointerSize;

                    if (!string.IsNullOrEmpty(entry.Name))
                    {
                        hintNameTableSize += 2;                         // hint
                        hintNameTableSize += entry.Name.Length + 1;
                    }
                }

                iatSize += 4;                            // null IAT
                namePointerTableSize += namePointerSize; // null
            }

            int iatPos = (_table.Count + 1) * 32;             // header + null;
            int namePointerTablePos = iatPos + iatSize;
            int hintNameTablePos    = namePointerTablePos + namePointerTableSize;
            int dllNamePos          = hintNameTablePos + hintNameTableSize;

            // Write
            int headerPos = 0;

            for (int i = 0; i < _table.Count; i++)
            {
                var module = _table[i];

                // Header
                _blob.Write(ref headerPos, (uint)0);                 // Attributes

                PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, dllNamePos));
                _blob.Write(ref headerPos, (uint)0);                      // Name

                _blob.Write(ref headerPos, (uint)module.ModuleHandleRVA); // ModuleHandle

                PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, iatPos));
                _blob.Write(ref headerPos, (uint)0);                 // DelayImportAddressTable

                PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, namePointerTablePos));
                _blob.Write(ref headerPos, (uint)0);                 // DelayImportNameTable
                _blob.Write(ref headerPos, (uint)0);                 // BoundDelayImportTable
                _blob.Write(ref headerPos, (uint)0);                 // UnloadDelayImportTable
                _blob.Write(ref headerPos, (uint)0);                 // TimeDateStamp

                // DllName
                string dllName = (module.DllName ?? "") + '\0';
                _blob.Write(ref dllNamePos, dllName, Encoding.ASCII);

                // DelayImportNameTable
                for (int j = 0; j < module.Count; j++)
                {
                    var entry = module[j];

                    _blob.Write(ref iatPos, (uint)entry.FuncRVA);

                    if (PE.Is32Bits)
                    {
                        if (!string.IsNullOrEmpty(entry.Name))
                        {
                            // DelayImport by name.
                            PE.Fixups.Add(
                                new WriteHintNameRVAFixup(
                                    _blob, namePointerTablePos, hintNameTablePos));
                            _blob.Write(ref namePointerTablePos, (uint)0);

                            // Hint/Name
                            _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal);
                            string name = entry.Name + '\0';
                            _blob.Write(ref hintNameTablePos, name, Encoding.ASCII);
                        }
                        else
                        {
                            // DelayImport by ordinal.
                            uint ordinal = (uint)entry.Ordinal | 0x80000000;
                            _blob.Write(ref namePointerTablePos, (uint)ordinal);
                        }
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(entry.Name))
                        {
                            // DelayImport by name.
                            PE.Fixups.Add(
                                new WriteHintNameRVAFixup(
                                    _blob, namePointerTablePos, hintNameTablePos));
                            _blob.Write(ref namePointerTablePos, (ulong)0);

                            // Hint/Name
                            _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal);
                            string name = entry.Name + '\0';
                            _blob.Write(ref hintNameTablePos, name, Encoding.ASCII);
                        }
                        else
                        {
                            // DelayImport by ordinal.
                            ulong ordinal = (uint)entry.Ordinal | 0x8000000000000000;
                            _blob.Write(ref namePointerTablePos, (ulong)ordinal);
                        }
                    }
                }

                // Null IAT
                _blob.Write(ref iatPos, 0, 4);

                // Null DelayImportNameTable
                if (PE.Is32Bits)
                {
                    _blob.Write(ref namePointerTablePos, 0, 4);
                }
                else
                {
                    _blob.Write(ref namePointerTablePos, 0, 8);
                }
            }

            // Null header
            _blob.Write(ref headerPos, 0, 32);

            // Set data directories
            PE.Fixups.Add(
                new PEBuilder.SetDataDirectoryFromBlobRVAFixup(
                    DataDirectories.DelayImportDescriptor, _blob));

            // Add blobs
            BuildSection section = PE.GetSection(_sectionName);

            section.Blobs.Add(_blob, _blobPriority);
        }