secana/PeNet

Sections incorrectly created (with AddImport)

Ceiridge opened this issue · 5 comments

Hello,
I'm trying to use PeNet as a method of dll injection for my Chromium Patcher and I've encountered some errors:
When adding any import, when the import directory is located in .rdata for example, it not only creates a new section with the huge size of .rdata, but then it also doesn't work. The PE instantly crashes.

I looked into this issue with PE-Bear and it shows this (see first screenshot):
rdatasec
The problem is highlighted by PE-Bear apparently. The parsed raw address and virtual address isn't clickable (out of bounds?).

Then I tried to partially do it manually by creating a new section with a big enough size to move the import directory into it (also with PE-Bear) and it had nothing else in that section. Then I added an import again with PeNet and then this happened:
manualsec
(ceisec was my original import directory section)
PE-Bear now warns me that the file is now corrupted, although it now completely works?!

Here is the file I tried it on (64bit) (you can find it in any Chrome installation at C:\Program Files (x86)\Google\Chrome\Application\VERSIONNUMBER and you can try to replace it with the modified dll to see if it crashes:
chrome_elf.zip

Here are the results I showed in the screenshot:
results.zip

Thanks for reporting the bug. Give me some time to have a look at this, as it seems to be complicated.

It looks like each section's raw size somehow always has to end with 00 (e. g.: 0x17E00, 0xA00, 0x200, 0x1800), whereas the virtual size is the actual size that is used of the section, which means that it can't be bigger than the raw size, of course. Maybe it just works if you somehow round the required size up until it reaches such a valid number?

This might also help you:
https://github.com/hasherezade/pe-bear-releases/wiki/Import-adding
https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#section-table-section-headers

sc
This means that maybe you could search for a multiple of the file alignment number that is high enough to exceed the required size.

I have the same problem of .exe crashing on start immediately when I try to add import to it. It works just fine when I use tools like CFF Explorer to import a function.

I don't remember how I originally found it, but I managed to work around this bug by adding padding at the end of the file before patching it to make it the size that divides by 0x10000 without a remainder:

var ExeFile = new {
    rawBytes = File.ReadAllBytes(ExePath).ToList(),
    fullPath = ExePath,
    fileName = Path.GetFileNameWithoutExtension(ExePath),
    directory = Path.GetDirectoryName(ExePath),
    extension = Path.GetExtension(ExePath)
};

int neededForAlignment = 0x10000 - ExeFile.rawBytes.Count % 0x10000;
ExeFile.rawBytes.AddRange(Enumerable.Repeat<byte>(0x00, neededForAlignment));

PeFile ExePeFile = new PeFile(ExeFile.rawBytes.ToArray());
PeFile dllPeFile = new PeFile(DLLPath);
ExePeFile.AddImport(DLLName, dllPeFile.ExportedFunctions?[0].Name ?? throw new InvalidOperationException("Can't access ExportedFunctions."));
File.WriteAllBytes(ExePath, ExePeFile.RawFile.ToArray());

I don't know what is it, it could be just padding itself and just adding 1 or 2 bytes of padding might fix it every time. I made it 0x10000 because it divides nicely by popular file alignment numbers like 200 and 400 iirc.

And the bug doesn't happen on all .exes for me, only on some. I tried to recreate it on a basic Visual C++ console application and it patches just fine.

Hi @KulaGGin and @Ceiridge,

I finally found time to look into the problem in more detail and thanks to the data provided by you I hope I fixed it. The Chrome example works at least now.

I uploaded a new version 2.4.1-alpha2 with the fix to nuget.org. Could you verify that it works for you now?

Hi @KulaGGin and @Ceiridge,

I finally found time to look into the problem in more detail and thanks to the data provided by you I hope I fixed it. The Chrome example works at least now.

I uploaded a new version 2.4.1-alpha2 with the fix to nuget.org. Could you verify that it works for you now?

Thank you for fixing it, although I don't need the import adder anymore, as my project now uses a different method to detect new processes.