Bddisasm
bddisasm is a fast, lightweight, x86/x64 instruction decoder. The project also features a fast, basic, x86/x64 instruction emulator, designed specifically to detect shellcode-like behavior.
Install / Use
/learn @bitdefender/BddisasmREADME
The Bitdefender disassembler
The Bitdefender disassembler (bddisasm) is a lightweight, x86/x64 only instruction decoder. It is easy to integrate, easy to work with, it has no external dependencies, it is thread-safe, it allocates no memory at all, it works in virtually any environment (we use it inside user, kernel, hypervisor, on both Windows and Linux environments), and it provides lots of info regarding the decoded instructions, such as: operands (both explicit and implicit), access mode for each operand, CPUID feature flag, flags access, etc. More examples and info about the project can be found on the official documentation: Bitdefender disassembler
Projects
- bddisasm - this is the main disassembler project. In order to use the Bitdefender disassembler, all you have to do is build this project, and link with the output library. The only headers you need are located inside the
incfolder. - bdshemu - this project makes use of the main bddisasm lib in order to build a simple, lightweight, fast, instructions emulator, designated to target shellcodes. This project is also integrated inside the disasmtool, so you can emulate raw binary files, and see their output. Note that this simple emulator supports basic x86/x64 instructions, and does not support emulating any kind of API call. In addition, the only supported memory accesses are inside the shellcode itself, and on the emulated stack.
- isagenerator_x86 - this project contains the instruction definitions and the scripts required to generate the disassembly tables. If you wish to add support for a new instruction, this is the place. This project will automatically generate several header files (instructions.h, mnemonics.h, constants.h, table_*.h), so please make sure you don't manually edit any of these files. You will need Python 3 to run the generation scripts.
- disasmtool - this project is a command line disassembler tool, used mainly as an example of how to integrate the bddisasm and bdshemu libraries.
- bindings - bindings for python, and Rust.
Core Features
- Lightweight - it's written in C, with no external dependencies, no memory allocated, and thread safe by design.
- Fast - measured on an Intel® Core™ Ultra 7 165H using BDDISASM v3.0:
- legacy decoder: around 240 CPU clocks per decoded instruction (~12M decoded instructions per second);
- mini decoder: around 150 CPU clocks per decoded instruction (~17M decoded instructions per second)
- Resilient - tested against internal fuzzers and the famous mishegos tool.
- Easy to work with - just include the main header file, bddisasm.h, link with the bddisasm library, and call the NdDecode API!
- Complete – comprehensive support for Intel and AMD x86 instructions implemented in modern CPUs, including rich per-instruction metadata.
Build and install
Using vcpkg
The easiest way of installing bddisasm is with vcpkg:
vcpkg install bddisasm
This will install bddisasm and bdshemu static libraries.
Note that the version available on vcpkg may not always be the latest.
Using CMake
This is the recommended way of using the library.
Prerequesites:
- CMake 3.16 or newer (older version may work, but they have not been tested)
- Ninja (optional, but recommended, especially on Windows)
The build process was tested with GCC and Clang on Linux and MSVC on Windows. Note that the Windows kernel build target is available only when using MSBuild.
To build the project run:
mkdir build
cmake -B build .
cmake --build build
This will build bddisasm, bdshemu, and disasmtool. For skipping the disasmtool build configure CMake with BDD_INCLUDE_TOOL=OFF:
mkdir build
cmake -B build . -DBDD_INCLUDE_TOOL=OFF
To install the project use:
cmake --build build --target install
This will install the bddisasm and bdshemu static libraries and their public headers. If disasmtool was built it will also be installed. Depending on the install location you may need to run the command as root.
Optionally, if a python 3 interpreter is found the instruction tables can be regenerated with:
cmake --build build --target isagenerator
To disable the isagenerator target configure CMake with BDD_INCLUDE_ISAGENERATOR=OFF.
Once installed, CMake projects can use find_package to find the library:
find_package(bddisasm REQUIRED)
Two targets are provided:
bddisasm::bddisasm- this should be used for targets that need only the decoder, without the shell code emulatorbddisasm::bdshemu- this should be used for targets that need the shell code emulator (note that it will pull inbddisasm::bddisasmautomatically)
There is no need to manually set include or link directories, simply use target_link_libraries with the needed target, for example:
find_package(bddisasm REQUIRED)
# decoder-tool needs only the decoder library
target_link_libraries(decoder-tool PRIVATE bddisasm::bddisasm)
# emulator-tool needs bdshemu
target_link_libraries(emulator-tool PRIVATE bddisasm::bdshemu)
nd_vsnprintf_s and nd_memset
By default, if vsnprintf and memset functions are available, the nd_vsnprintf_s and nd_memset functions are implemented directly by bddisasm. To signal this, BDDISASM_HAS_VSNPRINTF and BDDISASM_HAS_MEMSET will be added to the public compile definitions of bddisasm. This can be disabled by configuring CMake with BDD_USE_EXTERNAL_VSNPRINTF=ON and BDD_USE_EXTERNAL_MEMSET=ON.
Using as a sub-project
The project can be consumed as a sub-project, either by adding it as a git submodule, or by using CMake's FetchContent:
With FetchContent:
FetchContent_Declare(
bddisasm
GIT_REPOSITORY https://github.com/bitdefender/bddisasm
GIT_TAG origin/master
)
FetchContent_MakeAvailable(bddisasm)
As a git submodule:
# Assuming the submodule is checked out at external/bddisasm
add_subdirectory(external/bddisasm)
In both cases the bddisasm::bddisasm and bddisasm::bdshemu targets will be provided.
When used as a sub-project the disasmtool, isagenerator, and install targets are not available.
Using Make on Linux
To build the project run make in the root of the repository. This will build only the bddisasm and bdshemu static libraries, without disasmtool.
To install the project run make install. Depending on the install location you may need to run the command as root.
nd_vsnprintf_s and nd_memset will not be defined by bddisasm, integrators must provide these functions.
Using MSBuild on Windows
In order to build the projects on Windows you need:
- Visual Studio 2019 with the Desktop development with C++ workload.
- Windows SDK 10.0.18362.0.
- Python 3.7 or newer (optional)
When you first open bddisasm.sln in Visual Studio should prompt you to install any missing components.
This should be enough to build bddisasm, bdshemu, and disasmtool.
For the DebugKernel and ReleaseKernel configurations, WDK 1903 is needed, alongside the Windows Driver Kit Visual Studio extension (the WDK installer should take care of this).
For isagenerator, Python 3 is needed.
Building any of the projects is done directly from Visual Studio.
The results will be in the bin directory in the root of the repository.
nd_vsnprintf_s and nd_memset will not be defined by bddisasm, integrators must provide these functions.
Using pre-compiled binaries
Each release publishes static libraries, as well as the disasmtool CLI tool.
You can verify these artifacts using GitHub Artifact Attestation:
# Verify a component
$ gh attestation verify disasmtool -o bitdefender
# Or the entire bundle
$ gh attestation verify x86-windows-release.zip -o bitdefender
This is not available for bddisasm 2.1.4 or older.
Note that this is currently a beta feature (see Introducing Artifact Attestations–now in public beta for details).
Decoding x86 instructions
Decoding API
There are 4 decoding functions, but internally, they all do the same, albeit some of them with implicit arguments:
NDSTATUS NdDecode(INSTRUX *Instrux, const uint8_t *Code, uint8_t DefCode, uint8_t DefData)- this API should be used only if you don't care about the length of the input buffer;NDSTATUS NdDecodeEx(INSTRUX *Instrux, const uint8_t *Code, size_t Size, uint8_t DefCode, uint8_t DefData);- decode instruction from a buffer with maximum lengthSize;NDSTATUS NdDecodeEx2(INSTRUX *Instrux, const uint8_t *Code, size_t Size, uint8_t DefCode, uint8_t DefData, uint8_t DefStack, uint8_t PreferedVendor);- decode instructions with a preferred vendor;- `NDSTATUS NdDecodeWithContext(INSTRUX *Instrux, const uint8_t *Code, size_t Size, ND_CON
Related Skills
product-manager-skills
38PM skill for Claude Code, Codex, Cursor, and Windsurf: diagnose SaaS metrics, critique PRDs, plan roadmaps, run discovery, and coach PM career transitions.
devplan-mcp-server
3MCP server for generating development plans, project roadmaps, and task breakdowns for Claude Code. Turn project ideas into paint-by-numbers implementation plans.
