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

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).

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

  1. Hello,

    It’s with pleasure that I went through your tutorials, while everything works fine with simple programs, I am unable to pack executables with TLS (including with the exe you provided).
    I am on windows 10 using vs2015.
    To repro, you just need to have a piece of code such as:
    const SomeClass& GetInstance()
    {
    static SomeClass instance;
    return instance;
    }

    This will generate TLS code for the do once constructor and will crash.

    Any ideas?
    Thanks again for this great resource!

    1. Hi,

      Have you tried the compiled packer binary that I provided?
      It’s possible that Windows 10 interprets something in PE format differently, or vs2015 compiles something differently. When I’ve developed the packer, there were no vs 2015 and windows 10 :)
      I can’t say what’s wrong right away, but I can advice to debug a simple program with TLS using any assembler debugger (like OllyDbg or x64dbg), this probably will help to spot the problem.

    2. Well, I’ve decided to fix the issue (or at least investigate it), as some other people had the same problems with TLS. But I’m unable to reproduce it. I’ve tried to compile the code you provided using VS2015 in release and debug configurations and then pack it. Everything works fine after packing on Win 7 and Win 10. Could you please provide VS2015 project with the code that can be used to reproduce the problem?

  2. Thanks, I have indeed tried with the executable you provide and it’s a no go as well. I will keep looking and will let you know the solution if I figure it out!

  3. So I finally figured it out, it appears that it is necessary to set write_tls_data to true when calling rebuild_tls, doing this fixed the issue for me.

    1. One problem has been found and fixed:
      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).

      However, I’m still interested in example solution for VS2015, which can help reproduce the problem with TLS.

  4. Hello
    i opened the source code VS13 and get a lot of errors
    any way, i need only thing from it , realize how u deal with TLS
    i build a simple packer and it does not work with Borland exes like delphi
    i read your topic about tls but the code is so hard to understand case of u using unknown classes and variables , any way can u give me a simple steps how deal with TLS (borland exe has not a callbacks ) or better give me a simple source code with fix tls without using your classes (just tls fix no need others)
    thnx in advance

    1. Hi, at first, I recommend using VS 2010, as unpacker can be rebuilt in VS2013 somehow differently, and the resulting application won’t work.
      All the classes you’re talking about are from my “pe bliss” library, you can open source code files related to tls and examine all the code you need. If you don’t have any idea about what is TLS and how it works, then I recommend you to read some articles and documentation on this topic first, as it’s not easy to explain TLS briefly.

  5. i try with visual c++ 10 and same problem
    there problems to include this :
    #include
    #include
    #include
    //PE library header file
    #include
    #include
    i can’t find these headers anywhere in your solution

  6. #include
    #include

    i try with visual c++ 10 and same problem
    there problems to include this :
    pe_lib/pe_bliss_resources.h , pe_lib/pe_bliss.h , boost/timer.hpp , boost/scoped_array.hpp , boost/program_options.hpp, boost/program_options.hpp
    i can’t find these headers anywhere in your solution

  7. I’ve got a problem where I get a access violation exception if I resolve the imports of the packed DLL and load the “user32.dll”.
    The weird thing is that I loaded it already at the beginning of my unpacker code and it worked fine. (loaded it to use MessageBoxA). But if the imports contain “user32.dll” and I load it again it crashes.

    I am new to Assembly and I can’t figure out the problem while debugging with x32dbg.

    The packed DLL contains a load configuration directory. (It’s 40 bytes big)
    Maybe thats the problem?:
    [quote]
    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.
    [/quote]

    1. It’s difficult to determine the issue reason without the sample code. Have you modified the unpacker somehow? Can you provide the code you have the problem with (or at least the packed binary which crashes)?
      Load configuration directory can be a problem only for a packed binary with such a directory. I assume, that the file you’re packing doesn’t have one, and you’re just trying to load user32.dll (unpacked).

Leave a Reply

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