Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixed Mode / Unmanaged PE File Builders #554

Draft
wants to merge 6 commits into
base: development
Choose a base branch
from

Conversation

Washi1337
Copy link
Owner

@Washi1337 Washi1337 commented May 8, 2024

Includes:

  • Simplify PEFileBuilderBase into a common PEFileBuilder 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.
  • Move ManagedPEFileBuilder to AsmResolver.PE.Builder.
  • Add UnmanagedPEFileBuilder for rebuilding mixed-mode assemblies or fully native PE files based on a base image.
  • Add TrampolineTableBuffer for building code trampolines for IATs and VTable fixups.
  • Add Platform::CreateAddressTableInitializer to create platform-specific dynamic IAT initializers.
  • Add IPEImage::PEFile and IPEImage::ToPEFile.
  • Add SegmentPatch, allowing for entire segments to be written as a patch.
  • Add IPatch::UpdateOffsets.
  • Add DataDirectory.CreateForSegment(ISegment).
  • Remove 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.

@Washi1337 Washi1337 added enhancement pe-file Issues related to AsmResolver.PE.File pe Issues related to AsmResolver.PE labels May 8, 2024
@Washi1337 Washi1337 added this to the 6.0.0 milestone May 8, 2024
@Washi1337 Washi1337 changed the title New Unmanaged PE File Builders Mixed Mode / Unmanaged PE File Builders May 8, 2024
@Washi1337
Copy link
Owner Author

Washi1337 commented May 12, 2024

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:

  1. The PE file format does not tell us which symbols are functions are which are fields. How do we resolve this?
    • Option A: Add bool ImportedSymbol::TreatAsGlobalVariable { get; set; }, which the user can set directly on the symbol instance.
    • Option B: Add ICollection<ImportedSymbol> GlobalVariables { get; } to UnmanagedPEFileBuilder, letting the user add symbols they know are imported global variables as opposed to functions.
    • Option C: Add a 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.
  2. Where do we inject the initialization code?
    • Option A: Hijack the AddressOfEntryPoint native entry point.
    • Option B: Add as a TLS callback, which are executed even before the entry point.
  3. Can we somehow automatically make a good guess on which are the global variables?
    • Option A: Try resolve the declaring PE and see if the symbol falls in an executable section or not. This is at best a heuristic though.
    • Option B: Do not do this, it may be out of scope of AsmResolver as just a reader/writer

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement pe Issues related to AsmResolver.PE pe-file Issues related to AsmResolver.PE.File
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant