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

Adding a single exports section causes 2 sections to be added. #588

Closed
mercurial-moon opened this issue Oct 7, 2024 · 4 comments
Closed
Labels
bug pe Issues related to AsmResolver.PE
Milestone

Comments

@mercurial-moon
Copy link

AsmResolver Version

6.0.0-beta.1

.NET Version

Net Framework 4.8

Operating System

Windows

Describe the Bug

I am trying to append a export section to an existing dll.
When I run the code because I was expecting a ".edata" exports section in the final dll.

var pe = PEImage.FromFile(@"hellotest.dll");

pe.Exports = new ExportDirectory(".edata");
pe.Exports.Name = "hellotest.dll";
pe.Exports.BaseOrdinal = 1;

var expS = new ExportedSymbol(new VirtualAddress(0x3000), "hello");
pe.Exports.Entries.Add(expS);

var pef = pe.ToPEFile(new UnmanagedPEFileBuilder());
pef.Write("hellotest_out.dll");

How To Reproduce

Run the code above on an existing dll.

Expected Behavior

single .edata section should be present in the final output.

Actual Behavior

Instead I see sections named like ".auxtext" and ".auxdata" which seem to be duplicates.
image

Additional Context

No response

@Washi1337 Washi1337 added this to the 6.0.0 milestone Oct 7, 2024
@Washi1337 Washi1337 added the pe Issues related to AsmResolver.PE label Oct 7, 2024
@Washi1337
Copy link
Owner

Washi1337 commented Oct 7, 2024

Thanks for the catch. #589 has a potential fix. If you could verify this is indeed solving the issue of duplicated export directories then that would be great. (Build artifacts: https://github.com/Washi1337/AsmResolver/actions/runs/11217464280/artifacts/2024294167)

As a note: The constructor string parameter of ExportDirectory does not determine the section to which the directory is added, but rather corresponds to the Name RVA field in the export directory (See PE Format - Exports Directory Table). UnmanagedPEFileBuilder moves data directories into custom auxiliary sections if they are new or do not fit anymore in their original location.

@mercurial-moon
Copy link
Author

Hi,
Can confirm that this resolves the issue. No duplicate sections this time., I used the same code as above. Just that instead of the section being called .edata it seems to be called .rdata
image
But it shows correctly under the exports section in PE-bear
Its probably something wrong with my code as you indicated. What would be the correct way to add a exports directory with the name .edata?

@Washi1337
Copy link
Owner

Washi1337 commented Oct 12, 2024

Note that data directories are not necessarily bound to a specific section with a specific name. Sections can be named anything, it has zero effect on the runtime behavior of the PE from the Windows PE loader's perspective.

The constructor argument of ExportDirectory is the name of the export directory usually the name of the DLL itself (e.g., "MyLibrary.dll"), and not the name of the target section. UnmanagedPEFileBuilder as it is now moves any reconstructed read-only data directory, such as an exports directory, to a read-only section (which it calls .rdata). Currently it is not possible using UnmanagedPEFileBuilder to move things to a separate section as it kind of follows a predetermined PE file blueprint. You can change this blueprint by overriding its CreateSections method or one of its related methods. I plan on making this easier in the future.

If you really need it to be in .edata and seek to only change the export section of an existing PE file, you can also choose to edit the PEFile instance directly. Something like the following should work then:

// Open file.
var file = PEFile.FromFile("file.dll");

// Create new exports dir.
var newDirectory = new ExportDirectory("file.dll");
newDirectory.Entries.Add(new ExportedSymbol(new VirtualAddress(0x3000), "MyExport"));

// Create new exports buffer (this ensures the directory is reconstructed into a new segment buffer).
var newExportsBuffer = new ExportDirectoryBuffer();
newExportsBuffer.AddDirectory(newDirectory);

// Add the buffer to a new section.
var newSection = new PESection(
    ".edata",
    SectionFlags.MemoryRead | SectionFlags.ContentInitializedData,
    newExportsBuffer
);

// Add the section.
file.Sections.Add(newSection);

// Recalculate all offsets.
file.AlignSections();

// Update the export data dir in the optional header.
file.OptionalHeader.SetDataDirectory(DataDirectoryIndex.ExportDirectory, newExportsBuffer);

// Save file.
file.Write("file.output.dll");

@Washi1337
Copy link
Owner

Closing this as solved, will be present on nightly nuget shortly and in 6.0.0.

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

No branches or pull requests

2 participants