Installation and Integration

C/C++ API installation

When a new stable version of QBDI is released, prebuilt packages can be downloaded through the release page on Github. In order to make sure you have downloaded the right package, you can verify its integrity with the file SHA256.

A GPG signature of SHA256 by our developer key (2763 2215 DED8 D717 AD08 477D 874D 3F16 4D45 2193) is available in SHA256.sig.

# check the hash of the prebuilt package
sha256 -c SHA256

# verify the signature
wget https://qbdi.quarkslab.com/qbdi.asc -O - | gpg --import -
gpg --verify SHA256.sig

Debian / Ubuntu

Debian and Ubuntu packages are provided for stable and LTS releases, and can be installed using dpkg:

dpkg -i QBDI-*-*-X86_64.deb

Arch Linux

Arch Linux packages can be installed using pacman:

pacman -U QBDI-*-*-X86_64.tar.zst

macOS

A software installer is provided for macOS. Opening the .pkg in Finder and following the instructions should install QBDI seamlessly.

Windows

A software installer is provided for Windows. Running the .exe and following the instructions should install QBDI seamlessly.

Android

The Android package is an archive you solely need to extract. Afterwards, you have to manually push the files onto the device.

Devel packages

Devel packages embed the latest features the developers are currently working on for the next release (available on the dev-next branch). It’s worth mentioning that since some parts are still under development, those are likely to be unstable – you must be aware that it may contain some bugs and are not as reliable as release packages.

PyQBDI installation

Every time a new stable release of PyQBDI is available, it is automatically pushed onto the PyPI platform, thus can be easily installed with pip (>= 19.3).

pip install --user --update pip
pip install --user PyQBDI

If you want to use a devel version, download the corresponding prebuilt wheel file and run the following commands:

pip install --user --update pip
pip install --user PyQBDI-*.whl

The devel wheel files which contain the latest versions of the dev-next branch are available at:

Note

Only Python3 is supported. If you need to use Python2, we recommend using QBDI 0.7.0 instead.

Note

A 32-bit version of Python is needed if you want to use PyQBDI on x86 targets.

Frida/QBDI installation

QBDI can be used alongside Frida to make it even more powerful. This feature is included in the C/C++ package. Using it requires having Frida installed (>= 14.0) on your workstation as well as frida-compile for compiling your scripts.

# install Frida
pip install frida-tools

# install frida-compile and add the binary directory to your PATH env variable
npm install frida-compile babelify
export PATH=$PATH:$(pwd)/node_modules/.bin

Android target

In order to use Frida/QBDI on an Android device, the Frida server must be running on the target device and the libQBDI.so library have to be placed in /data/local/tmp.

Note

Latest Frida server binaries are available on the Frida official release page.

Docker Linux images

The Docker image is available on Docker Hub. It has been built to keep it as small as possible so it does not contain any compiler. You have to install the needed application or modify the following Dockerfile according to your needs.

FROM qbdi/qbdi:x86_ubuntu

ENV USER="docker" \
    HOME="/home/docker"

# install some needed tools
RUN apt-get update && \
    apt-get upgrade -y && \
    apt-get install -y \
        build-essential \
        cmake \
        libstdc++-8-dev \
        zlib1g-dev \
        python \
        python-dev \
        #gdb \
        #vim \
        sudo \
        bash && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# create a user
RUN adduser --disabled-password --gecos '' $USER && \
    adduser $USER sudo && \
    echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

# switch to new user
USER $USER
WORKDIR $HOME

# TODO : Add yours needed files
#ADD --chown=$USER . $HOME/

CMD ["/bin/bash"]

To run the container, we recommend allowing the usage of PTRACE which is mandatory to use QBDIPreload.

docker run -it --rm --cap-add=SYS_PTRACE --security-opt seccomp:unconfined <image> bash

Compilation from source code

To build this project, the following dependencies are needed on your system:

  • cmake >= 3.5

  • ninja or make

  • C++17 toolchain (gcc, clang, Visual Studio 2019, …)

The compilation is a two-step process:

  • local library distribution of LLVM is built.

  • QBDI is built using the LLVM library.

This local built of LLVM is required because QBDI uses private APIs not exported by regular LLVM installations and because our code is only compatible with a specific version of those APIs. This first step is cached and only needs to be run once, subsequent builds only need to repeat the second step.

QBDI build system relies on CMake and requires to pass build configuration flags. To help with this step we provide shell scripts for common build configurations which follow the naming pattern config-OS-ARCH.sh. Modifying these scripts is necessary if you want to compile in debug mode or cross-compile QBDI.

Linux

x86-64

Create a new directory at the root of the source tree, and execute the Linux configuration script:

mkdir build
cd build
../cmake/config/config-linux-X86_64.sh

If the build script warns you about missing dependencies for your platform (in the case of a first compilation), or if you want to rebuild them, execute the following commands:

make llvm

This will rebuild the binary distribution of those dependencies for your platform. You can then relaunch the configuration script from above and compile:

../cmake/config/config-linux-X86_64.sh
make -j4

x86

You can follow the same instructions as for x86-64 but instead, use the config-linux-X86.sh configuration script.

macOS

Compiling QBDI on macOS requires a few things:

  • A modern version of macOS (like Sierra)

  • Xcode (from the App Store or Apple Developer Tools)

  • the Command Line Tools (xcode-select --install)

  • a package manager (preferably MacPorts, but HomeBrew should also be fine)

  • some packages (port install cmake wget)

Once requirements are met, create a new directory at the root of the source tree, and execute the macOS configuration script:

mkdir build
cd build
../cmake/config/config-macOS-X86_64.sh

If the build script warns you about missing dependencies for your platform (in the case of a first compilation), or if you want to rebuild them, execute the following commands:

make llvm

This will rebuild the binary distribution of those dependencies for your platform. You can then relaunch the build script from above and compile:

../cmake/config/config-macOS-X86_64.sh
make -j4

Windows

Building on Windows requires a pure Windows installation of Python 3 (from the official packages, this is mandatory) in order to build our dependencies (we really hope to improve this in the future). It also requires an up-to-date CMake and Ninja.

First of all, the Visual Studio environment must be set up. This can be done with a command such as:

"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x64

Then, the following commands must be run:

mkdir build
cd build
python ../cmake/config/config-win-X86_64.py

If the build script warns you about missing dependencies for your platform (in the case of a first compilation), or if you want to rebuild them, execute the following commands:

ninja llvm

This will rebuild the binary distribution of those dependencies for your platform. You can then relaunch the build script from above and compile:

python ../cmake/config/config-win-X86_64.py
ninja

Android

Cross-compiling for Android requires the NDK to be installed on your workstation. For now, it has only been tested under Linux. If not already installed, you can download the latest Android NDK package through the official website. Afterwards, the config-android-*.sh configuration script needs to be customised to match your NDK installation directory and the target platform:

  • NDK_PATH should point to your Android NDK

At this point, you should be able to continue following the instructions of the Linux section since the procedure is the same.

PyQBDI compilation

The PyQDBI library (apart from the wheel package) can be built by solely passing the ‘-DQBDI_TOOLS_PYQBDI=ON’ option to the CMake build system.

However, if you want to build the wheel package, you have to compile the LLVM libraries beforehand. Once done, you can run these commands:

python -m pip install --upgrade pip
python -m pip install setuptools wheel
python setup.py bdist_wheel

A 32-bit version of Python is mandatory for the X86 architecture whereas a 64-bit one is required for the X86-64 architecture.

CMake integration

Single architecture

If you want to use only one architecture of QBDI in your CMake project, you can import the QBDI and QBDIPreload packages:

find_package(QBDI REQUIRED)
find_package(QBDIPreload REQUIRED) # if available for your current platform
# or
find_package(QBDI REQUIRED HINTS "${EXTRACT_DIRECTORY}" NO_DEFAULT_PATH)
find_package(QBDIPreload REQUIRED HINTS "${EXTRACT_DIRECTORY}" NO_DEFAULT_PATH)

Once the CMake package is found, you can link your executable either with the dynamic or the static library:

add_executable(example example.c)

target_link_libraries(example QBDI::QBDI)
# or
target_link_libraries(example QBDI::QBDI_static)

add_executable(example_preload example_preload.c)
target_link_libraries(example_preload QBDI::QBDI_static QBDIPreload::QBDIPreload)

Multi-architecture

If two or more architectures of QBDI are needed within the same project, you should import the package QBDI<arch> and QBDIPreload<arch>.

find_package(QBDIX86 REQUIRED HINTS "${EXTRACT_DIRECTORY_X86}" NO_DEFAULT_PATH)
find_package(QBDIPreloadX86 REQUIRED HINTS "${EXTRACT_DIRECTORY_X86}" NO_DEFAULT_PATH)

add_executable(example_preload86 example_preload.c)
set_target_properties(example_preload86 PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
target_link_libraries(example_preload86 QBDI::X86::QBDI_static QBDIPreload::X86::QBDIPreload)

find_package(QBDIX86_64 REQUIRED HINTS "${EXTRACT_DIRECTORY_X86_64}" NO_DEFAULT_PATH)
find_package(QBDIPreloadX86_64 REQUIRED HINTS "${EXTRACT_DIRECTORY_X86_64}" NO_DEFAULT_PATH)

add_executable(example_preload64 example_preload.c)
target_link_libraries(example_preload64 QBDI::X86_64::QBDI_static QBDIPreload::X86_64::QBDIPreload)