public void WritePortableExecutable(BinaryWriter writer) { writer.BaseStream.Seek(0, SeekOrigin.Begin); m_dosHeader.Write(writer); writer.Write(m_dosStubBytes); m_coffHeader.Write(writer); m_peHeaderOffset = (uint)writer.BaseStream.Position; m_peHeader.Write(writer); for (int i = 0; i < m_coffHeader.NumberOfSections; i++) { m_sectionHeaders[i].Write(writer); } writer.Write(m_filler); for (int i = 0; i < m_coffHeader.NumberOfSections; i++) { writer.Write(m_sections[i]); } writer.Write(m_remainingBytes); // Write Import Directory: PEDataDirectory importDirectoryEntry = m_peHeader.DataDirectories[(int)DataDirectoryName.Import]; if (importDirectoryEntry.VirtualAddress > 0) { uint importDirectoryFileOffset = GetOffsetFromRVA(importDirectoryEntry.VirtualAddress); writer.Seek((int)importDirectoryFileOffset, SeekOrigin.Begin); m_importDirectory.Write(writer); } // Update PE checksum: writer.Seek(0, SeekOrigin.Begin); byte[] fileBytes = new byte[writer.BaseStream.Length]; writer.BaseStream.Read(fileBytes, 0, (int)writer.BaseStream.Length); uint checksumOffset = m_peHeaderOffset + PEHeader.ChecksumRelativeAddress; uint checksum = PortableExecutableUtils.CalculcateChecksum(fileBytes, checksumOffset); writer.Seek((int)checksumOffset, SeekOrigin.Begin); writer.Write(checksum); writer.Flush(); }
public static void RenameDependencyFileName(string filePath, string oldFileName, string newFileName) { if (oldFileName.Length != newFileName.Length) { throw new NotImplementedException("when renaming dependencies, old file name must have the same size as new file name"); } PortableExecutableInfo peInfo = new PortableExecutableInfo(filePath); uint oldNameRVA = 0; PESectionHeader header = null; int sectionIndex = -1; foreach (ImageImportDescriptor descriptor in peInfo.ImportDirectory.Descriptors) { uint nameRVA = descriptor.NameRVA; header = peInfo.FindSectionByRVA(nameRVA); if (header != null) { sectionIndex = peInfo.SectionHeaders.IndexOf(header); uint fileNameAddressInSection = peInfo.GetAddressInSectionFromRVA(header, nameRVA); string fileName = PortableExecutableUtils.ReadNullTerminatedAsciiString(peInfo.Sections[sectionIndex], fileNameAddressInSection); if (fileName.Equals(oldFileName, StringComparison.InvariantCultureIgnoreCase)) { oldNameRVA = nameRVA; } } } if (oldNameRVA > 0) { byte[] newFileNameAsciiBytes = ASCIIEncoding.ASCII.GetBytes(newFileName); uint addressInSection = peInfo.GetAddressInSectionFromRVA(header, oldNameRVA); byte[] section = peInfo.Sections[sectionIndex]; Buffer.BlockCopy(newFileNameAsciiBytes, 0, section, (int)addressInSection, newFileNameAsciiBytes.Length); } PortableExecutableInfo.WritePortableExecutable(peInfo, filePath); }