Closed Washi1337 closed 1 month ago
The current implementation works, except for one limitation.
As it stands now, the new PE builder injects small chunks of native code to trampoline slots in the original IAT and VTable fixup tables to their newly added counterparts (based on the idea in this blog post). This works really well for functions and has been tested thoroughly. However, functions are not the only type of symbol that can be imported using the IAT: Global variables (such as std::cout
in C++ binaries) can also appear in these tables. Since global variables are not code segments, they will never be called by the original PE either using e.g., a call
or jmp
instruction, and thus they cannot be trampolined.
One way to still support binaries that import global variables is to let the newly constructed PE file manually initialize these original IAT entries based on our new IAT. This requires injecting some additional native code (executed after the new IAT has been initialized by the Windows PE loader but before the PE's entry point is actually called) that copies the populated entries of our new IAT to the old IAT.
Some open problems with this:
bool ImportedSymbol::TreatAsGlobalVariable { get; set; }
, which the user can set directly on the symbol instance.ICollection<ImportedSymbol> GlobalVariables { get; }
to UnmanagedPEFileBuilder
, letting the user add symbols they know are imported global variables as opposed to functions.ISymbolClassifier
or similar delegate to UnmanagedPEFileBuilder
that takes imported symbols and determines whether it is a global variable or not. Users can then customize programmatically this behavior.AddressOfEntryPoint
native entry point.
Includes:
PEFileBuilderBase
into a commonPEFileBuilder
facilitating the general rebuilding of all data directories in a PE. New PE file builders now only have to decide on final section layout as a bare minimum.ManagedPEFileBuilder
toAsmResolver.PE.Builder
.UnmanagedPEFileBuilder
for rebuilding mixed-mode assemblies or fully native PE files based on a base image.TrampolineTableBuffer
for building code trampolines for IATs and VTable fixups.Platform::CreateAddressTableInitializer
to create platform-specific dynamic IAT initializers.IPEImage::PEFile
andIPEImage::ToPEFile
.SegmentPatch
, allowing for entire segments to be written as a patch.IPatch::UpdateOffsets
.DataDirectory.CreateForSegment(ISegment)
.AsmResolver.PE.DotNet.Builder
namespace.Bugfixes:
FieldRvaDataReader
now correctly skips types with custom modifiers in field size determination.OptionalHeader::SetDataDirectory
now ensures that all data directories are present.