mal_unpack: dumping the payload out of a packed Windows sample
Dynamic unpacker based on PE-sieve
At a glance
- What is it?
- mal_unpack is a Windows tool that runs a suspected packed sample in a controlled environment, waits for it to unpack, dumps the payload to disk and kills the original process, all through the PE-sieve library. It is BSD-2-Clause licensed and C, and the documentation is emphatic that it deploys the original malware and must only be used inside a virtual machine.
- Who is it for?
- Adopt mal_unpack if you analyse Windows samples and need the unpacked payload rather than the packed dropper, and if you have a virtual machine and a driver-assisted workflow available. Do not run it on a host machine, since the tool deliberately executes the original malware, and skip it if you need a static approach or if your environment cannot isolate the sample.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A tool that deliberately runs the malware
mal_unpack is described as a dynamic unpacker based on PE-sieve, and the repository links to the PE-sieve FAQ entry explaining the difference between the two tools. The mechanism is stated in one sentence: it deploys a packed malware, waits for it to unpack the payload, dumps the payload, and kills the original process.
That sentence is the whole design, and it is also the whole risk. This is not a static analyser and not a scanner. It executes the sample you give it, in the expectation that the sample will unpack itself in memory the way packed malware normally does, and then it captures the resulting memory regions as a file on disk.
The repository carries a warning that is worth reading before anything else. The unpacker deploys the original malware, and the instruction is to use it only on a VirtualMachine. There is no sandbox inside the tool, no emulation, no attempt to contain what the sample does. Containment is the operator's responsibility, and the tool is designed for the analysis workflow where a sample is already known to be dangerous.
The audience is therefore reverse engineers and malware analysts, not developers looking for a general purpose unpacker. The topic tags on the repository say as much: malware-analysis, malware-unpacker, memory-forensics, pe-sieve and libpeconv.
The repository layout confirms the shape of the project. There is a main.cpp, a CMakeLists.txt, a params.h and a paramkit directory for argument handling, an unpack_scanner pair for the scanning logic, a driver_comm pair for communication with the optional kernel driver, a util directory, and a pe-sieve directory which is the library it is built on, present as a git submodule along with a .gitmodules file.
Basic usage and the three switches that matter
The invocation takes the path to the sample and a timeout in milliseconds:
mal_unpack.exe /exe <path_to_the_malware> /timeout <timeout: ms>The timeout is in milliseconds rather than seconds, which is worth noting because a packed sample that takes a while to unpack is normal and a timeout in the wrong unit either truncates the run or wastes time.
Three options change what gets captured. By default the tool dumps implanted PEs, which is the common case where the packer allocates memory, writes a PE image into it and jumps to it. If you want shellcodes instead, the option is /shellc, and the documentation links it to the PE-sieve documentation on detecting shellcodes. If you want modified, hooked or patched PEs, the option is /hooks, which covers the case where the payload is not a clean PE image but a modified region of an existing module.
A fourth switch changes the exit condition rather than the output. By default the unpacker terminates on the first found implant, and /trigger T makes it terminate on the timeout instead. That is the difference between a quick run that grabs the first unpacking and a patient run that lets the sample finish and yields more.
The full argument list is documented on the PE-sieve wiki, and the README notes that the available arguments can also be listed using the argument /help. Pointing users at a wiki rather than restating the options is sensible, since the same argument set belongs to the underlying library, but it does mean the tool's full behaviour is documented outside this repository.
Building from source and the driver that makes it fast
The simplest route is the releases page, which the README points to for the latest release download. The platform badge in the README is for Windows, and the repository contains a mal_unpack.manifest and a resource script, which is consistent with a Windows executable rather than a cross platform tool.
To build from source, clone recursively so the submodules come along, which matters because PE-sieve is a submodule of this repository:
git clone --recursive https://github.com/hasherezade/mal_unpack.gitThe recursive flag is the important part of that command. Without it you get the wrapper but not the scanning library it depends on.
The build system is CMake, with the CMakeLists.txt at the repository root and an AppVeyor configuration for continuous integration on Windows, alongside a Codacy badge for static analysis and a commit activity badge.
The performance note is the other thing to know before a first run. The README says that for the best performance you should install the MalUnpackCompanion driver, which lives in a separate repository. The presence of driver_comm.cpp and driver_comm.h in the tree, along with an ntddk.h header, shows how that works: the tool can talk to a kernel mode component to read process memory more directly, and the communication layer is a separate interface from the user mode scanning code.
Two Python helpers are also offered. MalUnpack Runner is a wrapper under the runner directory of the mal_unpack_py repository, and MalUnpack Lib is a Python library under the mal_unpack_lib directory of the same repository. If you want to drive unpacking from a script rather than from a console, those are the route, and they are separate projects with their own documentation.
How this differs from PE-sieve itself
The relationship to PE-sieve is the thing to understand, because the two tools are easy to confuse and they do different jobs.
PE-sieve is the library and the standalone scanner. It injects into a process, inspects its memory, finds modules that were injected rather than loaded normally, and can dump them. It also has the more general purpose of being a memory forensics and anti-malware research tool that can be pointed at a running process to look for interesting regions.
mal_unpack is the automation around that. It starts the sample for you, gives it time to unpack, watches for the implant, dumps it, and then terminates the original process. The point is to turn a manual procedure into one command. An analyst who already runs PE-sieve interactively does not need mal_unpack; an analyst triaging a folder of a hundred packed samples does.
That difference in purpose also shapes the output. PE-sieve can be used to look at a process without killing it, which matters when the sample is still doing something interesting. mal_unpack's contract is that the process ends. If your workflow needs the sample to keep running, for example to observe its network behaviour or its persistence mechanism, this tool is the wrong shape for the job and the underlying library is the one to reach for.
There is a related family of tools in the same author's workspace. PE-sieve's own documentation covers detecting shellcodes and the different implant types, and the /shellc and /hooks switches in mal_unpack map onto those categories directly. The other option in this space is a general reverse engineering framework such as a debugger driven workflow, where you set breakpoints on the unpacking stub yourself. The difference in approach is that a debugger gives you the point of unpacking and the register state at that moment, while mal_unpack takes the simpler route of running the sample and dumping the result, which is faster per sample and gives you far less insight into the packing technique.
What the documentation does not cover
Several practical questions are not answered in the README, and it is worth naming them because they are the questions you will have.
The output format is not described. The README says it dumps the payload and that it can dump implanted PEs, shellcodes or hooked PEs, but it does not state where the dumped file lands, what it is named, or whether a log of the run is written. The repository does contain an unpack_dir.bat script, which suggests a directory is used for output, and the PE-sieve wiki linked from the README likely documents the details, but for a tool whose whole purpose is producing an artifact, the artifact's location is a notable omission.
The timeout behaviour is also unstated. The /timeout option is given in milliseconds, and /trigger T changes the exit condition, but what happens to a partially unpacked sample that never produces an implant before the timeout expires is not described.
The reporting of what was found is unclear from this documentation. Whether the tool prints the same kind of summary that PE-sieve prints, listing the detected modules and their hashes, is not stated here, and that summary is often what an analyst records in a ticket.
The requirements list is thin beyond the driver note. There is no statement of which Windows versions are supported, whether a 64-bit host is needed, or what happens when the sample requires administrator rights, which many do. The build badge covers Windows, and the driver is a Windows kernel component, so the platform is settled, but the details are not in this repository.
The repository also carries an unpack_dir.bat at the root, which appears to be a convenience script for the output directory, and the mal_unpack_ver.h header, which is where the version string lives, consistent with the release numbering in the tags.
Licence, maintenance and how to fit it in a workflow
The licence is BSD-2-Clause, with the badge in the README and the LICENSE file at the repository root. A two clause BSD grant is about as permissive as software licences get, with a disclaimer of warranty and no requirement that derived work be published. For an analyst who wants to modify the dumping logic or add an output format, there is no licence friction at all.
On maintenance, the repository is not archived and the last push was on 2026-04-14. The release history shows 1.0 from 2025-09-13, 0.9.9 from 2024-02-26 and 0.9.8 from 2023-11-10. The move to a 1.0 tag is a reasonable signal that the author considers the interface stable, though the last push was in April 2026 and the release cadence is slow, so expect to build from the latest release rather than count on frequent updates.
The interesting operational question is how this fits alongside the rest of an analysis setup. The natural pipeline is: a triage tool identifies the sample as packed, mal_unpack produces the unpacked payload, and a static analyser then works on the clean file. The output of mal_unpack is the input to the next stage, which is why the artifact details matter so much and why the PE-sieve wiki is the place to check them.
One point about the driver deserves emphasis for anyone rolling this out. The MalUnpackCompanion driver is a separate kernel component from a separate repository, and installing a kernel driver on the analysis host is a decision with its own blast radius. The README frames it as optional, for the best performance, which means the tool works without it, more slowly. For a shared analysis environment, running without the driver keeps the host surface smaller, and for a single dedicated VM, the driver is a reasonable trade for speed across a large sample set.
Editorial conclusion
Adopt mal_unpack if you analyse Windows samples and need the unpacked payload rather than the packed dropper, and if you have a virtual machine and a driver-assisted workflow available. Do not run it on a host machine, since the tool deliberately executes the original malware, and skip it if you need a static approach or if your environment cannot isolate the sample. Verify first that you are on a disposable Windows virtual machine, that the MalUnpackCompanion driver is installed if you want the best performance, and that the dumped output is what your analysis workflow expects rather than the original file.
Frequently asked questions
What does mal_unpack do with a packed sample?
It deploys the original malware, waits for it to unpack the payload, dumps the payload and kills the original process. By default it dumps implanted PEs, with /shellc for shellcodes and /hooks for modified, hooked or patched PEs.
How do I run mal_unpack from the command line?
The basic form is `mal_unpack.exe /exe <path_to_the_malware> /timeout <timeout: ms>`, with the timeout in milliseconds. Adding /trigger T makes the unpacker stop on the timeout rather than on the first implant it finds.
Is it safe to run mal_unpack on a normal machine?
No. The README carries a caution that the unpacker deploys the original malware and says to use it only on a VirtualMachine. There is no sandbox or containment inside the tool.
How do I build mal_unpack from source?
Clone the repository recursively with `git clone --recursive https://github.com/hasherezade/mal_unpack.git` so the PE-sieve submodule comes with it, then build with the CMakeLists.txt at the root. The project is a Windows tool and CI runs on Windows through AppVeyor.
What is the difference between mal_unpack and PE-sieve?
PE-sieve is the underlying library and scanner that can be pointed at a running process to find and dump injected modules, while mal_unpack automates the whole cycle of starting the sample, waiting, dumping and killing the process. The README links to the PE-sieve FAQ entry that covers the difference in detail.
What license is mal_unpack released under?
BSD-2-Clause, with the LICENSE file at the repository root. There is no requirement to publish modifications, and the tool itself runs only on Windows.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/hasherezade-mal-unpack)Was this useful?