/// <summary> /// Relocate the produced PE file and output the result into a given stream. /// </summary> /// <param name="peFile">Blob builder representing the complete PE file</param> /// <param name="defaultImageBase">Default load address for the image</param> /// <param name="corHeaderBuilder">COR header</param> /// <param name="corHeaderFileOffset">File position of the COR header</param> /// <param name="outputStream">Stream to receive the relocated PE file</param> public void RelocateOutputFile( BlobBuilder peFile, ulong defaultImageBase, CorHeaderBuilder corHeaderBuilder, int corHeaderFileOffset, Stream outputStream) { RelocationHelper relocationHelper = new RelocationHelper(outputStream, defaultImageBase, peFile); if (corHeaderBuilder != null) { relocationHelper.CopyToFilePosition(corHeaderFileOffset); UpdateCorHeader(corHeaderBuilder); BlobBuilder corHeaderBlob = new BlobBuilder(); corHeaderBuilder.WriteTo(corHeaderBlob); int writtenSize = corHeaderBlob.Count; corHeaderBlob.WriteContentTo(outputStream); relocationHelper.AdvanceOutputPos(writtenSize); // Just skip the bytes that were emitted by the COR header writer byte[] skipBuffer = new byte[writtenSize]; relocationHelper.CopyBytesToBuffer(skipBuffer, writtenSize); } // Traverse relocations in all sections in their RVA order foreach (Section section in _sections.OrderBy((sec) => sec.RVAWhenPlaced)) { int rvaToFilePosDelta = section.FilePosWhenPlaced - section.RVAWhenPlaced; foreach (ObjectDataRelocations objectDataRelocs in section.Relocations) { foreach (Relocation relocation in objectDataRelocs.Relocs) { // Process a single relocation int relocationRVA = section.RVAWhenPlaced + objectDataRelocs.Offset + relocation.Offset; int relocationFilePos = relocationRVA + rvaToFilePosDelta; // Flush parts of PE file before the relocation to the output stream relocationHelper.CopyToFilePosition(relocationFilePos); // Look up relocation target SymbolTarget relocationTarget = _symbolMap[relocation.Target]; Section targetSection = _sections[relocationTarget.SectionIndex]; int targetRVA = targetSection.RVAWhenPlaced + relocationTarget.Offset; // Apply the relocation relocationHelper.ProcessRelocation(relocation.RelocType, relocationRVA, targetRVA); } } } // Flush remaining PE file blocks after the last relocation relocationHelper.CopyRestOfFile(); }
/// <summary> /// Relocate the produced PE file and output the result into a given stream. /// </summary> /// <param name="peFile">Blob builder representing the complete PE file</param> /// <param name="defaultImageBase">Default load address for the image</param> /// <param name="corHeaderBuilder">COR header</param> /// <param name="corHeaderFileOffset">File position of the COR header</param> /// <param name="outputStream">Stream to receive the relocated PE file</param> public void RelocateOutputFile( BlobBuilder peFile, ulong defaultImageBase, Stream outputStream) { RelocationHelper relocationHelper = new RelocationHelper(outputStream, defaultImageBase, peFile); // Traverse relocations in all sections in their RVA order foreach (Section section in _sections.OrderBy((sec) => sec.RVAWhenPlaced)) { int rvaToFilePosDelta = section.FilePosWhenPlaced - section.RVAWhenPlaced; foreach (PlacedObjectData placedObjectData in section.PlacedObjectDataToRelocate) { foreach (Relocation relocation in placedObjectData.Relocs) { // Process a single relocation int relocationRVA = section.RVAWhenPlaced + placedObjectData.Offset + relocation.Offset; int relocationFilePos = relocationRVA + rvaToFilePosDelta; // Flush parts of PE file before the relocation to the output stream relocationHelper.CopyToFilePosition(relocationFilePos); // Look up relocation target SymbolTarget relocationTarget = _symbolMap[relocation.Target]; Section targetSection = _sections[relocationTarget.SectionIndex]; int targetRVA = targetSection.RVAWhenPlaced + relocationTarget.Offset; int filePosWhenPlaced = targetSection.FilePosWhenPlaced + relocationTarget.Offset; // If relocating to a node's size, switch out the target RVA with data length if (relocation.RelocType == RelocType.IMAGE_REL_SYMBOL_SIZE) { targetRVA = relocationTarget.Size; } // Apply the relocation relocationHelper.ProcessRelocation(relocation.RelocType, relocationRVA, targetRVA, filePosWhenPlaced); } } } // Flush remaining PE file blocks after the last relocation relocationHelper.CopyRestOfFile(); }