Developing PE file packer step-by-step. Step 12 – bugfixes

pack

Thanks to the guy from commentaries in previous posts about the packer, one amazing bug in the code was discovered, which I tried to fix quickly. The commentator, without analyzing the packer operation in detail, stated that the code packed with it will not be able to work with SEH if DEP is turned on. Under such conditions the code worked well (because all unpacked code in memory is located within one single PE file section marked as executable. UPX has same operation logic.). However, suddenly the following bug was discovered: if the program is built in MSVC++, uses SEH and has relocations, it will likely crash on first exception (more precisely, if the file was loaded to the address other than base). DEP, of course, has nothing to do with this. The thing is in disastrous IMAGE_LOAD_CONFIG_DIRECTORY directory. It is created by Visual Studio linker. Of useful information it contains the address table (RVA) of SE handlers and a pointer to CRT internal variable __security_cookie. As it turned out, this directory is necessary not only for CRT internals (although it, as it seems, actually doesn't care about this structure), but also for the system loader (at least, in Win7. WinXP, it seems, ignores this directory too). The packer, which I developed, moves this directory to other section (see here). Thus the issue can be fixed by adding several records to relocations table, which is created by the packer. These records will fix the addresses pointing to security cookie and SE handlers table, to let it read necessary information from this directory at loading stage.

Except correcting this bug I updated the packer code to make it buildable with latest version (1.0.0) of PE library (PE Bliss). It is always available to download here.

By the way, about PE Bliss library. Currently in my free time I develop new version, which will have the following features (the list is exemplary and can be changed):
- high-level work with additional types of PE file resources;
- detailed .NET binaries parsing (metadata, signatures, resources);
- library wrapper in C++/CLI, which allows .NET developers to use library functionality comfortably in C# or Visual Basic .NET software.

Download packer sources: packer source
Download binary: packer binary

PS. In Windows 8 and 8.1 image load configuraton directory has been exanded (to support Control Flow Guard), so the packer will be unable to pack newest binaries from that operation systems, if IMAGE_LOAD_CONFIG_DIRECTORY is present.

UPDATE 24.05.2016: relocations generation has been updated. In some rare cases (when TLS data was big enough, and load config directory was present, relocation table addresses could overflow, which resulted in corrupted packed binary).

4 thoughts on “Developing PE file packer step-by-step. Step 12 – bugfixes”

    1. Thanks! I guess it would not be that difficult, but it'll definitely take some time. In PE+, most of the structures are different in size due to 8-byte pointers. There's also an Exception directory, which is absent in PE32. Moreover, modern Windows versions have introduced some new features to the load configuration directory, which are not handled by this packer (such as the Control flow guard).

      1. Thank you for your fast response. I have been looking into it, and it also seems that the VS compiler does not support inline assembly in x64 architecture making it difficult to port the loader.

        I have some questions about x86 .NET binaries parsing. I guess the COM directory must be preserved and also the metadata that it points to. Can the resources be compressed? What should be done on the loader side?

        1. Packer compatibility with x86 .NET binaries is possible. Everything can be packed as usual, but the COM directory must be stripped from the PE header to avoid the CLR from loading the binary directly. The RVA and size of the COM directory must be restored during unpacking and a few APIs must be hooked...

Leave a Reply to Wallace Cancel reply

Your email address will not be published. Required fields are marked *