Developing PE file packer step-by-step. Step 5. Resources

Previous step is here.

It's time to improve our packer. It can pack and run simple binaries already, which have only import table. Binaries with exports, resources, TLS, DLL with relocations are still beyond its powers. We have to work on this. Let's implement processing of second important thing after imports - of resource directory.

Firstly, let's add a couple of fields to packed_file_info structure:

These fields will store information about original resource directory. In the unpacker we will store them in PE file header after unpacking sections data. But this is not all yet. We pack the data of all sections by assembling them into one large block, including resources. Icon and version information are lost from file, if they existed. It may not run at all, if it had some specific manifests in resources, which set up rights or libraries required to launch the file. We need to place original main application icon, version information and manifest next to packed data in new resource directory, and write a pointer to it to PE header.

Let's start with the unpacker (unpacker project), moreover, the changes will be minimal. Let's add lines, similar to import directory code:

That's all with the unpacker. Now we turn to the packer (simple_pe_packer project). Again, we add lines for resource directory similar to import directory ones:

Basically, this should be enough already for file with resources (forms, for example) to launch. Problems will occur, if the file has xp manifest or something like that. So we now need to rebuild resource directory in the packer, as I described above. We add new #include <pe_resource_manager.h> to the beginning of main.cpp. It is necessary to access helper resource management classes. We will add code to certain place in packer, where original file sections are removed (right before this action):

So, what happens in this piece of code? In short, we get original file resources and search them for:

1. Icons
2. Manifest
3. Version information

These three kinds of resources should be placed unpacked to a new resource directory. We get the first icon (actually, the icon group) from original file, it is used by Windows as main file icon. File always has one manifest, and it describes, which rights are required for file to launch, and which DLL files are used. Other information may be stored there. Al last, version information - this is actually information about file, which also can be viewed in Windows Explorer.

I did not describe before how the resource directory is organized, so for general education purposes I will give this information now. Let's take a look at some exe file resources in CFF Explorer:

As you can see, the resources are organized as a tree structure. Root directory recordings begin with resource type ones. They nest directories with recordings containing resource name or ID, and they, in turn, nest language recordings directories. Last ones contain data directory, which points to resource data.

So, the code above lists all the icons with name or ID. We look for first icon because all PE file resources are sorted, and named resources come first, followed by resources with ID. It will be the first icon of application, and we add it to a new resource directory, keeping its name/ID and language. We process manifest and version information in a similar way - all files have no more than one such recording, and they are always unnamed, i.e. having ID, so we get and save first manifest recording and first version information recording.

We created a new resource directory, now we should save it to our file. First, let's add a couple of lines before import rebuilding code:

The fact is that all rebuilders in my PE library will automatically strip all null bytes from the end of the section, into which rebuilt imports/exports/resources etc. are placed, if that section is last in the file. This is an absolutely adequate behavior, which allows to reduce the file size within the limits of file alignment, as the loader will restore null bytes anyway, but in memory, in number of [aligned virtual section size] minus [physical section size]. Thus, if any structure within section ends with null element (for example, final import table descriptor), it will not be physically saved to file, if this import table is placed in last PE file section. By the way, some interesting bugs in editors like CFF Explorer are associated with this fact. It relies on physical file data only, not on virtual. Therefore it can display import table incorrectly with stripped null bytes in its end.

Now we need null bytes related to import table not to be stripped, as we are going to place resources right after imports. If we strip these null bytes, then resource directory will be placed over import directory, as a result we will get total crap.

Let's go further - rebuild resources:

Everything is clear here - if there are any resources, we save them to a new PE file. We place them at the end of added section, right after imports. Because this section is the last at the moment of resource rebuilding, it will expand automatically.

We have only to remove one line, which deletes the resource directory:

Ready! We can test our packer on any exe file with imports, resources and even relocations (although we don't process them yet). Let's take any project in MSVC++ with MFC and view its original resources with CFF explorer:

After packing:

So, one icon group with several icons (application icons), a manifest (configuration files) and version information remain. Of course, the packed file successfully runs!

Full solution for this step: Own PE Packer step 5

Leave a Reply

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