private static void WriteCorHeader(Stream peStream, CorHeader corHeader) { var writer = new BlobWriter(72); writer.WriteUint(72); // Number of bytes in this header 4 writer.WriteUshort(corHeader.MajorRuntimeVersion); // 6 writer.WriteUshort(corHeader.MinorRuntimeVersion); // 8 writer.WriteUint(corHeader.MetadataDirectory.RelativeVirtualAddress); // 12 writer.WriteUint(corHeader.MetadataDirectory.Size); // 16 writer.WriteUint((uint)corHeader.Flags); // 20 writer.WriteUint(corHeader.EntryPointToken); // 24 writer.WriteUint(corHeader.Resources.Size == 0 ? 0u : corHeader.Resources.RelativeVirtualAddress); // 28 writer.WriteUint(corHeader.Resources.Size); // 32 writer.WriteUint(corHeader.StrongNameSignature.Size == 0 ? 0u : corHeader.StrongNameSignature.RelativeVirtualAddress); // 36 writer.WriteUint(corHeader.StrongNameSignature.Size); // 40 writer.WriteUint(corHeader.CodeManagerTable.RelativeVirtualAddress); // 44 writer.WriteUint(corHeader.CodeManagerTable.Size); // 48 writer.WriteUint(corHeader.VTableFixups.RelativeVirtualAddress); // 52 writer.WriteUint(corHeader.VTableFixups.Size); // 56 writer.WriteUint(corHeader.ExportAddressTableJumps.RelativeVirtualAddress); // 60 writer.WriteUint(corHeader.ExportAddressTableJumps.Size); // 64 writer.WriteUlong(0); // 72 writer.WriteTo(peStream); }
private void WriteRuntimeStartupStub(Stream peStream) { var writer = new BlobWriter(16); // entry point code, consisting of a jump indirect to _CorXXXMain if (!_module.Requires64bits) { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 4) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUshort(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //4 writer.WriteUint(_ntHeader.ImportAddressTable.RelativeVirtualAddress + (uint)_module.BaseAddress); //8 } else { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 8) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUint(0); writer.WriteUshort(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //8 writer.WriteUlong(_ntHeader.ImportAddressTable.RelativeVirtualAddress + _module.BaseAddress); //16 } writer.WriteTo(peStream); }
private void WriteImportAddressTable(Stream peStream) { var writer = new BlobWriter(16); bool use32bitAddresses = !_module.Requires64bits; uint importTableRVA = _ntHeader.ImportTable.RelativeVirtualAddress; uint ilRVA = importTableRVA + 40; uint hintRva = ilRVA + (use32bitAddresses ? 12u : 16u); // Import Address Table if (use32bitAddresses) { writer.WriteUint(hintRva); // 4 writer.WriteUint(0); // 8 } else { writer.WriteUlong(hintRva); // 8 writer.WriteUlong(0); // 16 } writer.WriteTo(peStream); }
private void WriteImportTable(Stream peStream) { var writer = new BlobWriter(70); bool use32bitAddresses = !_module.Requires64bits; uint importTableRVA = _ntHeader.ImportTable.RelativeVirtualAddress; uint ilRVA = importTableRVA + 40; uint hintRva = ilRVA + (use32bitAddresses ? 12u : 16u); uint nameRva = hintRva + 12 + 2; // Import table writer.WriteUint(ilRVA); // 4 writer.WriteUint(0); // 8 writer.WriteUint(0); // 12 writer.WriteUint(nameRva); // 16 writer.WriteUint(_ntHeader.ImportAddressTable.RelativeVirtualAddress); // 20 writer.Position += 20; // 40 // Import Lookup table if (use32bitAddresses) { writer.WriteUint(hintRva); // 44 writer.WriteUint(0); // 48 writer.WriteUint(0); // 52 } else { writer.WriteUlong(hintRva); // 48 writer.WriteUlong(0); // 56 } // Hint table writer.WriteUshort(0); // Hint 54|58 string entryPointName = (_module.Kind == ModuleKind.DynamicallyLinkedLibrary || _module.Kind == ModuleKind.WindowsRuntimeMetadata) ? "_CorDllMain" : "_CorExeMain"; foreach (char ch in entryPointName) { writer.WriteByte((byte)ch); // 65|69 } writer.WriteByte(0); // 66|70 writer.WriteTo(peStream); }
private void WriteRuntimeStartupStub(Stream peStream, int importAddressTableRva) { var writer = new BlobWriter(16); // entry point code, consisting of a jump indirect to _CorXXXMain if (_is32bit) { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 4 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 4) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUshort(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //4 writer.WriteUint((uint)importAddressTableRva + (uint)_properties.BaseAddress); //8 } else { //emit 0's (nops) to pad the entry point code so that the target address is aligned on a 8 byte boundary. for (uint i = 0, n = (uint)(BitArithmeticUtilities.Align((uint)peStream.Position, 8) - peStream.Position); i < n; i++) { writer.WriteByte(0); } writer.WriteUint(0); writer.WriteUshort(0); writer.WriteByte(0xff); writer.WriteByte(0x25); //8 writer.WriteUlong((ulong)importAddressTableRva + _properties.BaseAddress); //16 } writer.WriteTo(peStream); }
private void WriteHeaders(Stream peStream, NtHeader ntHeader, CoffHeader coffHeader, List<SectionHeader> sectionHeaders, out long ntHeaderTimestampPosition) { var writer = new BlobWriter(1024); // MS-DOS stub (128 bytes) writer.WriteBytes(s_dosHeader); // PE Signature "PE\0\0" writer.WriteUint(0x00004550); // COFF Header (20 bytes) writer.WriteUshort((ushort)coffHeader.Machine); writer.WriteUshort((ushort)coffHeader.NumberOfSections); ntHeaderTimestampPosition = writer.Position + peStream.Position; writer.WriteUint((uint)coffHeader.TimeDateStamp); writer.WriteUint((uint)coffHeader.PointerToSymbolTable); writer.WriteUint((uint)coffHeader.NumberOfSymbols); writer.WriteUshort((ushort)(_is32bit ? 224 : 240)); // SizeOfOptionalHeader writer.WriteUshort((ushort)coffHeader.Characteristics); // PE Headers: writer.WriteUshort((ushort)(_is32bit ? PEMagic.PE32 : PEMagic.PE32Plus)); // 2 writer.WriteByte(ntHeader.MajorLinkerVersion); // 3 writer.WriteByte(ntHeader.MinorLinkerVersion); // 4 writer.WriteUint((uint)ntHeader.SizeOfCode); // 8 writer.WriteUint((uint)ntHeader.SizeOfInitializedData); // 12 writer.WriteUint((uint)ntHeader.SizeOfUninitializedData); // 16 writer.WriteUint((uint)ntHeader.AddressOfEntryPoint); // 20 writer.WriteUint((uint)ntHeader.BaseOfCode); // 24 if (_is32bit) { writer.WriteUint((uint)ntHeader.BaseOfData); // 28 writer.WriteUint((uint)ntHeader.ImageBase); // 32 } else { writer.WriteUlong(ntHeader.ImageBase); // 32 } // NT additional fields: writer.WriteUint((uint)ntHeader.SectionAlignment); // 36 writer.WriteUint((uint)ntHeader.FileAlignment); // 40 writer.WriteUshort(ntHeader.MajorOperatingSystemVersion); // 42 writer.WriteUshort(ntHeader.MinorOperatingSystemVersion); // 44 writer.WriteUshort(ntHeader.MajorImageVersion); // 46 writer.WriteUshort(ntHeader.MinorImageVersion); // 48 writer.WriteUshort(ntHeader.MajorSubsystemVersion); // MajorSubsystemVersion 50 writer.WriteUshort(ntHeader.MinorSubsystemVersion); // MinorSubsystemVersion 52 // Win32VersionValue (reserved, should be 0) writer.WriteUint(0); // 56 writer.WriteUint((uint)ntHeader.SizeOfImage); // 60 writer.WriteUint((uint)ntHeader.SizeOfHeaders); // 64 writer.WriteUint(ntHeader.Checksum); // 68 writer.WriteUshort((ushort)ntHeader.Subsystem); // 70 writer.WriteUshort((ushort)ntHeader.DllCharacteristics); if (_is32bit) { writer.WriteUint((uint)ntHeader.SizeOfStackReserve); // 76 writer.WriteUint((uint)ntHeader.SizeOfStackCommit); // 80 writer.WriteUint((uint)ntHeader.SizeOfHeapReserve); // 84 writer.WriteUint((uint)ntHeader.SizeOfHeapCommit); // 88 } else { writer.WriteUlong(ntHeader.SizeOfStackReserve); // 80 writer.WriteUlong(ntHeader.SizeOfStackCommit); // 88 writer.WriteUlong(ntHeader.SizeOfHeapReserve); // 96 writer.WriteUlong(ntHeader.SizeOfHeapCommit); // 104 } // LoaderFlags writer.WriteUint(0); // 92|108 // The number of data-directory entries in the remainder of the header. writer.WriteUint(16); // 96|112 // directory entries: writer.WriteUint((uint)ntHeader.ExportTable.RelativeVirtualAddress); // 100|116 writer.WriteUint((uint)ntHeader.ExportTable.Size); // 104|120 writer.WriteUint((uint)ntHeader.ImportTable.RelativeVirtualAddress); // 108|124 writer.WriteUint((uint)ntHeader.ImportTable.Size); // 112|128 writer.WriteUint((uint)ntHeader.ResourceTable.RelativeVirtualAddress); // 116|132 writer.WriteUint((uint)ntHeader.ResourceTable.Size); // 120|136 writer.WriteUint((uint)ntHeader.ExceptionTable.RelativeVirtualAddress); // 124|140 writer.WriteUint((uint)ntHeader.ExceptionTable.Size); // 128|144 writer.WriteUint((uint)ntHeader.CertificateTable.RelativeVirtualAddress); // 132|148 writer.WriteUint((uint)ntHeader.CertificateTable.Size); // 136|152 writer.WriteUint((uint)ntHeader.BaseRelocationTable.RelativeVirtualAddress); // 140|156 writer.WriteUint((uint)ntHeader.BaseRelocationTable.Size); // 144|160 writer.WriteUint((uint)ntHeader.DebugTable.RelativeVirtualAddress); // 148|164 writer.WriteUint((uint)ntHeader.DebugTable.Size); // 152|168 writer.WriteUint((uint)ntHeader.CopyrightTable.RelativeVirtualAddress); // 156|172 writer.WriteUint((uint)ntHeader.CopyrightTable.Size); // 160|176 writer.WriteUint((uint)ntHeader.GlobalPointerTable.RelativeVirtualAddress); // 164|180 writer.WriteUint((uint)ntHeader.GlobalPointerTable.Size); // 168|184 writer.WriteUint((uint)ntHeader.ThreadLocalStorageTable.RelativeVirtualAddress); // 172|188 writer.WriteUint((uint)ntHeader.ThreadLocalStorageTable.Size); // 176|192 writer.WriteUint((uint)ntHeader.LoadConfigTable.RelativeVirtualAddress); // 180|196 writer.WriteUint((uint)ntHeader.LoadConfigTable.Size); // 184|200 writer.WriteUint((uint)ntHeader.BoundImportTable.RelativeVirtualAddress); // 188|204 writer.WriteUint((uint)ntHeader.BoundImportTable.Size); // 192|208 writer.WriteUint((uint)ntHeader.ImportAddressTable.RelativeVirtualAddress); // 196|212 writer.WriteUint((uint)ntHeader.ImportAddressTable.Size); // 200|216 writer.WriteUint((uint)ntHeader.DelayImportTable.RelativeVirtualAddress); // 204|220 writer.WriteUint((uint)ntHeader.DelayImportTable.Size); // 208|224 writer.WriteUint((uint)ntHeader.CliHeaderTable.RelativeVirtualAddress); // 212|228 writer.WriteUint((uint)ntHeader.CliHeaderTable.Size); // 216|232 writer.WriteUlong(0); // 224|240 // Section Headers foreach (var sectionHeader in sectionHeaders) { WriteSectionHeader(sectionHeader, writer); } writer.WriteTo(peStream); }
private static void WriteCorHeader(Stream peStream, CorHeader corHeader) { var writer = new BlobWriter(CorHeaderSize); writer.WriteUint(CorHeaderSize); writer.WriteUshort(corHeader.MajorRuntimeVersion); writer.WriteUshort(corHeader.MinorRuntimeVersion); writer.WriteUint((uint)corHeader.MetadataDirectory.RelativeVirtualAddress); writer.WriteUint((uint)corHeader.MetadataDirectory.Size); writer.WriteUint((uint)corHeader.Flags); writer.WriteUint((uint)corHeader.EntryPointTokenOrRelativeVirtualAddress); writer.WriteUint((uint)(corHeader.ResourcesDirectory.Size == 0 ? 0 : corHeader.ResourcesDirectory.RelativeVirtualAddress)); // 28 writer.WriteUint((uint)corHeader.ResourcesDirectory.Size); writer.WriteUint((uint)(corHeader.StrongNameSignatureDirectory.Size == 0 ? 0 : corHeader.StrongNameSignatureDirectory.RelativeVirtualAddress)); // 36 writer.WriteUint((uint)corHeader.StrongNameSignatureDirectory.Size); writer.WriteUint((uint)corHeader.CodeManagerTableDirectory.RelativeVirtualAddress); writer.WriteUint((uint)corHeader.CodeManagerTableDirectory.Size); writer.WriteUint((uint)corHeader.VtableFixupsDirectory.RelativeVirtualAddress); writer.WriteUint((uint)corHeader.VtableFixupsDirectory.Size); writer.WriteUint((uint)corHeader.ExportAddressTableJumpsDirectory.RelativeVirtualAddress); writer.WriteUint((uint)corHeader.ExportAddressTableJumpsDirectory.Size); writer.WriteUlong(0); Debug.Assert(writer.Length == CorHeaderSize); Debug.Assert(writer.Length % 4 == 0); writer.WriteTo(peStream); }
private void WriteImportTable(Stream peStream, int importTableRva, int importAddressTableRva) { var writer = new BlobWriter(SizeOfImportTable); int ilRVA = importTableRva + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); int nameRva = hintRva + 12 + 2; // Import table writer.WriteUint((uint)ilRVA); // 4 writer.WriteUint(0); // 8 writer.WriteUint(0); // 12 writer.WriteUint((uint)nameRva); // 16 writer.WriteUint((uint)importAddressTableRva); // 20 writer.Position += 20; // 40 // Import Lookup table if (_is32bit) { writer.WriteUint((uint)hintRva); // 44 writer.WriteUint(0); // 48 writer.WriteUint(0); // 52 } else { writer.WriteUlong((uint)hintRva); // 48 writer.WriteUlong(0); // 56 } // Hint table writer.WriteUshort(0); // Hint 54|58 foreach (char ch in CorEntryPointName) { writer.WriteByte((byte)ch); // 65|69 } writer.WriteByte(0); // 66|70 Debug.Assert(writer.Length == SizeOfImportTable); writer.WriteTo(peStream); }
private void WriteImportAddressTable(Stream peStream, int importTableRva) { var writer = new BlobWriter(SizeOfImportAddressTable); int ilRVA = importTableRva + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); // Import Address Table if (_is32bit) { writer.WriteUint((uint)hintRva); // 4 writer.WriteUint(0); // 8 } else { writer.WriteUlong((uint)hintRva); // 8 writer.WriteUlong(0); // 16 } Debug.Assert(writer.Length == SizeOfImportAddressTable); writer.WriteTo(peStream); }
private void WriteImportTable(Stream peStream) { var writer = new BlobWriter(70); int importTableRVA = _ntHeader.ImportTable.RelativeVirtualAddress; int ilRVA = importTableRVA + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); int nameRva = hintRva + 12 + 2; // Import table writer.WriteUint((uint)ilRVA); // 4 writer.WriteUint(0); // 8 writer.WriteUint(0); // 12 writer.WriteUint((uint)nameRva); // 16 writer.WriteUint((uint)_ntHeader.ImportAddressTable.RelativeVirtualAddress); // 20 writer.Position += 20; // 40 // Import Lookup table if (_is32bit) { writer.WriteUint((uint)hintRva); // 44 writer.WriteUint(0); // 48 writer.WriteUint(0); // 52 } else { writer.WriteUlong((uint)hintRva); // 48 writer.WriteUlong(0); // 56 } // Hint table writer.WriteUshort(0); // Hint 54|58 string entryPointName = (_properties.ImageCharacteristics & Characteristics.Dll) != 0 ? "_CorDllMain" : "_CorExeMain"; foreach (char ch in entryPointName) { writer.WriteByte((byte)ch); // 65|69 } writer.WriteByte(0); // 66|70 writer.WriteTo(peStream); }
private void WriteImportAddressTable(Stream peStream) { var writer = new BlobWriter(16); int importTableRVA = _ntHeader.ImportTable.RelativeVirtualAddress; int ilRVA = importTableRVA + 40; int hintRva = ilRVA + (_is32bit ? 12 : 16); // Import Address Table if (_is32bit) { writer.WriteUint((uint)hintRva); // 4 writer.WriteUint(0); // 8 } else { writer.WriteUlong((uint)hintRva); // 8 writer.WriteUlong(0); // 16 } writer.WriteTo(peStream); }