Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
packer-tutorial — A tutorial on how to write a packer for Windows! | Kitploit
Tools/GitHubGitHub/frank2/packer-tutorial
Reverse EngineeringMalware AnalysisBinary AnalysisLearning & Education
GitHubfrank2/packer-tutorial

packer-tutorial

A tutorial on how to write a packer for Windows!

View Repository
31932243 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

PACKERS

Table of Contents

  1. What is a packer?: An introduction into the purpose of packers and a guide through what the development necessities of a packer are.
  2. Prerequisites: Tools needed to work with this tutorial.
  3. Getting a taste: A demonstration of what you will be building with this tutorial.
  4. Sketching out our CMake project: A mini CMake tutorial on creating a build system for the somewhat complex needs of a packer.
  5. Packing binaries into your stub: A tutorial on how to write the packer portion of the packer/stub combo, and also an introduction to the Windows executable file format.
    1. Managing resources
    2. Parsing a PE file
    3. Manipulating a PE file
  6. Simulating the loader: A tutorial on how to build a minimal stub executable to unpack and load a target executable, and also an introduction into more advanced Windows executable manipulation.
    1. Reading our PE from memory
    2. Loading our PE for execution
    3. Resolving API imports
    4. Resolving addresses
    5. Transferring execution
  7. Further exercises: Some exercises to further expand on your packer development knowledge.

Seem like a daunting read? Try the presentation version, which summarizes this readme. YouTube video coming soon!

What is a packer?

A packer is a program that decompresses and launches another program within its address space (or sometimes, another process's address space). It is sometimes known for being the vector that attacks analysis environments, such as debuggers and virtual sandboxes. It's primarily used for a few things:

  • Compression: Packers are commonly employed to compress the code of a given binary. This is one of its few legitimate uses. See UPX for an example of a compressing packer.
  • Obfuscation: Packers are also employed when attempting to obfuscate or otherwise defend a program from reverse engineering. See Riot Games's packman packer for an example of an anti-reversing packer.
  • Evasion: Malware frequently uses a variety of packers in order to evade antivirus and even EDR. See this analysis of a SmokeLoader packer for an example of an evasive packer.

Fundamentally, a packer only has a few basic steps:

  1. Compression stage: This is where the original executable is either compressed, obfuscated or both, into a new binary.
  2. Decompression stage: This is where the packed executable decompresses or deobfuscates its original executable for loading.
  3. Loading stage: This is where the packer mimics a variety of steps similar to the host platform's executable loader. Because of the complexity of executable binaries, this is the most complicated step, depending on the level of depth you wish to emulate.
  4. Execution stage: This is where code transfers from the host stub executable into the newly loaded (i.e., unpacked) code.

Equally as simple, a packer only consists of a few pieces:

  • The packer: This piece is responsible for preparing what's called the stub executable and giving it the data required to unpack a given binary. This is ultimately the compression stage.
  • The stub: This binary is the piece of code responsible for decompressing, loading, and executing the original binary. As you can see, the stub executable does most of the heavy lifting for a packer.

Building a packer can be tricky, since the stub needs to be built and imported somehow into the packer executable. For Windows, learning the build system for Visual Studio beyond simple compilation can be a laborious chore. Luckily, CMake provides a simple, cross-platform build system that supports Visual Studio, and is highly customizable!

This tutorial aims to teach the following:

  • How to segment and integrate the two main pieces of a packer into a cohesive, testable build environment.
  • How to manipulate a Windows executable to add additional, loadable data.
  • How to navigate a Windows executable to retrieve and load arbitrary data.
  • How to emulate parts of the Windows loader to load and execute a Windows executable.

If you're already familiar with C++ and CMake, feel free to skip directly to the packing section. Otherwise, keep reading!

Prerequisites

  • Knowledge of C++: This tutorial is kind of useless if you don't know C++, as we're going to be doing pointer arithmetic a lot.
  • Visual Studio: Visual Studio contains a fully featured Windows C++ compiler. This project is tested against Visual Studio 2019, but newer versions should be fine.
  • CMake: CMake is the build system we use to help instrument our builds for the Visual Studio compiler.

Getting a taste

First, let's prove, somehow, that this build system works and creates a properly packed executable. Once you've got CMake and Visual Studio installed, navigate to the root directory of this repository with your terminal of choice and execute the following:

$ mkdir build
$ cd build
$ cmake ../

This will create the necessary project files to build the packer tutorial code. Then run:

$ cmake --build ./ --config Release

This will build the packer project in Release mode. Then, you can run the following test:

$ ctest -C Release ./

If all goes well, test_pack and test_unpack should succeed. If you want to see the results of the packing yourself, you should see this:

$ ./packed.exe
I'm just a little guy!

Let's talk about all the moving parts that made this happen.

Sketching out our CMake project

So we know what the main components of a packer are, but how can we test our packer immediately as part of the development cycle? We'll need to add a third binary to our overall project to properly test the pack and unpack process of our binary. So overall, we need three projects:

  • the packer
  • the stub
  • the dummy executable to pack

We also need a compression library to make sure the binary compresses into the stub executable. zlib will work out nicely for this.

Our project hierarchy, to start out with, should look like this:

packer/
+---+ CMakeLists.txt
    + dummy/
    | |
    | +---+ CMakeLists.txt
    |     + src/
    |       |
    |       +---+ main.cpp
    |
    + stub/
    | |
    | +---+ CMakeLists.txt
    |     + src/
    |       |
    |       +---+ main.cpp
    |
    + src/
    | |
    | +---+ main.cpp
    |
    + zlib-1.2.13/
      |
      +---+ CMakeLists.txt
          + ...

Our main.cpp in each folder can simply look like this for now:

#include <iostream>

int main(int argc, char *argv[]) {
    std::cout << "I'm just a little guy!" << std::endl;
    
    return 0;
}

Already, we should establish that we have a simple dependency chain to deal with, which CMake will nicely resolve for us with some instrumentation:

  • packer and stub depend on zlib
  • packer depends on stub
  • dummy depends on packer (because it needs to be packed by the packer)
Download Tool