C++ API reference

namespace QBDL
struct Arch
#include <arch.hpp>

Define a binary architecture

It is based on LIEF’s description of an architecture. Based on this description, we need three fields to completely target a binary architecture:

  • the architecture as per LIEF’s description

  • the endianness of the CPU

  • whether the CPU is 64bit

This is a bit unfortunate that LIEF does not have a simple enum that would map every possible architectures.

Here are a few common architectures description that are used:

const auto x86 = Arch{LIEF::ARCHITECTURES::X86, LIEF::ENDIANNESS::LITTLE,
false}; const auto x64 = Arch{LIEF::ARCHITECTURES::X86,
LIEF::ENDIANNESS::LITTLE, true}; const auto armv8 =
Arch{LIEF::ARCHITECTURES::ARM64, LIEF::ENDIANNESS::LITTLE, true}; 

Public Functions

inline constexpr Arch(LIEF::ARCHITECTURES arch, LIEF::ENDIANNESS endianness, bool is64)
inline constexpr bool operator==(Arch const &o) const
inline constexpr bool operator!=(Arch const &o) const

Public Members

LIEF::ARCHITECTURES arch

Architecture as defined by LIEF.

LIEF::ENDIANNESS endianness

Endianness of the binary’s architecture

bool is64

Whether this is a 64bit CPU

Public Static Functions

static Arch from_bin(LIEF::Binary const &bin)

Construct an Arch object from a LIEF binary object

class TargetMemory
#include <Engine.hpp>

Describe the target memory the binary must be loaded into.

This abstraction helps target many different memory system.

To describe your target, you need to subclass this and implement the pure virtual functions. See their documentation below.

Subclassed by QBDL::Engines::Native::TargetMemory

Public Functions

virtual ~TargetMemory() = default
virtual uint64_t mmap(uint64_t hint, size_t len) = 0

Reserve a region of memory in the targeted memory space.

Parameters
  • hint[in] A hint as to where the address should be. 0 means any address.

  • len[in] Size of the memory region to reserve

Returns

0 if an error occurred, any value otherwise.

virtual bool mprotect(uint64_t addr, size_t len, int prot) = 0

Change permissions on a region of memory.

virtual void write(uint64_t addr, const void *buf, size_t len) = 0

Write data to a memory region in the targeted memory space.

This always succeeds.

Parameters
  • addr – Virtual absolute address to write data into

  • buf – Pointer to the data to write

  • len – Length of the data to write

virtual void read(void *dst, uint64_t addr, size_t len) = 0

Read data from a memory region in the targeted memory space.

This always succeeds.

Parameters
  • dst – A pointer to the buffer that will receive the data

  • addr – Virtual absolute address to read the data from

  • len – Length of the data to read

void write_ptr(Arch const &arch, uint64_t addr, uint64_t ptr)

Convenience function that write a pointer value to the targeted memory space, given an architecture.

No efforts are made to verify that arch matches what QBDL::TargetMemory expects.

This always succeeds.

Parameters
  • arch[in] Targeted architecture

  • addr[in] Virtual absolute address to write the pointer value into

  • ptr[in] Value of the address to write

uint64_t read_ptr(Arch const &arch, uint64_t addr)

Convenience function that reads a pointer value from the targeted memory space, given an architecture.

No efforts are made to verify that arch matches what QBDL::TargetMemory expects.

This always succeeds.

Parameters
  • arch[in] Targeted architecture

  • addr[in] Virtual absolute address to read the pointer value from

Returns

The read pointer value

class TargetSystem
#include <Engine.hpp>

Describe the target system the binary must be loaded into.

This abstraction helps describe:

  • how external symbol are resolved

  • if a system supports a given binary (mainly used to choose a binary in fat MachO files)

  • how memory is handled (through a TargetMemory object)

  • the base address that must be used when mapping the binary using TargetMemory::mmap

Subclassed by QBDL::Engines::Native::TargetSystem

Public Functions

inline TargetSystem(TargetMemory &mem)
virtual ~TargetSystem() = default
virtual uint64_t symlink(Loader &loader, LIEF::Symbol const &sym) = 0

Resolve external functions

This function returns the absolute virtual address of an external symbol. This is used by a QBDL::Loader object to write the address of external symbol into the targeted memory.

Parameters
  • loader[in] The current loader object that is calling this function

  • sym[in] The symbol to resolve

Returns

The absolute virtual address of sym

virtual bool supports(LIEF::Binary const &bin) = 0

Verify that the target system supports a binary.

This is mainly used by the QBDL::Loaders::MachO loader to select a valid binary within a universal MachO.

Parameters

bin[in] Binary to verify

Returns

true iif the target system can handle this binary.

virtual uint64_t base_address_hint(uint64_t binary_base_address, uint64_t virtual_size) = 0

Compute the preferred based address where the binary should be mapped.

Parameters
  • binary_base_address[in] The base address extracted from the binary header

  • virtual_size[in] The complete size the binary would take in memory (including all segments contiguously mapped with their relative offsets respected).

Returns

0 if the loader can choose any address, otherwise a hint as to what the base address should be.

inline TargetMemory &mem()
class Loader
#include <Loader.hpp>

Base class for a Loader

Subclassed by QBDL::Loaders::ELF, QBDL::Loaders::MachO, QBDL::Loaders::PE

Public Types

enum BIND

Values:

enumerator NOT_BIND
enumerator NOW
enumerator LAZY

Public Functions

virtual uint64_t get_address(const std::string &sym) const = 0

Get the resolved absolute virtual address of a symbol.

virtual uint64_t get_address(uint64_t offset) const = 0

Compute the absolute virtual address of on offset. This is basically base_address + offset.

virtual uint64_t entrypoint() const = 0

Get the absolute virtual address of the entrypoint.

virtual ~Loader()
virtual Arch arch() const = 0

Get the architecture targeted by the loaded binary.

Public Static Attributes

static constexpr BIND BIND_DEFAULT = BIND::NOW
namespace Engines
namespace Native

Functions

std::unique_ptr<QBDL::TargetMemory> memory()

Allocates and returns a QBDL::Engines::Native::TargetMemory object.

static inline constexpr Arch arch()

Returns a QBDL::Arch object that represents the native architecture QBDL is running onto.

class TargetMemory : public QBDL::TargetMemory
#include <Native.hpp>

Native QBDL::TargetMemory class that matches the OS QBDL is running onto.

It only works for Linux-based system for now.

Public Functions

virtual uint64_t mmap(uint64_t hint, size_t len) override

Reserve a region of memory in the targeted memory space.

Parameters
  • hint[in] A hint as to where the address should be. 0 means any address.

  • len[in] Size of the memory region to reserve

Returns

0 if an error occurred, any value otherwise.

virtual bool mprotect(uint64_t addr, size_t len, int prot) override

Change permissions on a region of memory.

virtual void write(uint64_t addr, const void *buf, size_t len) override

Write data to a memory region in the targeted memory space.

This always succeeds.

Parameters
  • addr – Virtual absolute address to write data into

  • buf – Pointer to the data to write

  • len – Length of the data to write

virtual void read(void *dst, uint64_t addr, size_t len) override

Read data from a memory region in the targeted memory space.

This always succeeds.

Parameters
  • dst – A pointer to the buffer that will receive the data

  • addr – Virtual absolute address to read the data from

  • len – Length of the data to read

class TargetSystem : public QBDL::TargetSystem
#include <Native.hpp>

Native QBDL::TargetMemory class that matches the OS on which QBDL is running on.

Public Functions

virtual bool supports(LIEF::Binary const &bin) override

Verify that the target system supports a binary.

This is mainly used by the QBDL::Loaders::MachO loader to select a valid binary within a universal MachO.

Parameters

bin[in] Binary to verify

Returns

true iif the target system can handle this binary.

virtual uint64_t base_address_hint(uint64_t binary_base_address, uint64_t virtual_size) override

Compute the preferred based address where the binary should be mapped.

Parameters
  • binary_base_address[in] The base address extracted from the binary header

  • virtual_size[in] The complete size the binary would take in memory (including all segments contiguously mapped with their relative offsets respected).

Returns

0 if the loader can choose any address, otherwise a hint as to what the base address should be.

namespace details

Functions

static inline constexpr LIEF::ARCHITECTURES LIEFArch()
static inline constexpr LIEF::ENDIANNESS LIEFEndianess()
static inline constexpr bool Is64Bit()
namespace Loaders
class ELF : public QBDL::Loader
#include <ELF.hpp>

Public Functions

inline operator bool() const
inline bool is_valid() const
virtual uint64_t get_address(const std::string &sym) const override

Get the resolved absolute virtual address of a symbol.

virtual uint64_t get_address(uint64_t offset) const override

Compute the absolute virtual address of on offset. This is basically base_address + offset.

virtual uint64_t entrypoint() const override

Get the absolute virtual address of the entrypoint.

virtual Arch arch() const override

Get the architecture targeted by the loaded binary.

inline LIEF::ELF::Binary &get_binary()
inline const LIEF::ELF::Binary &get_binary() const
~ELF() override

Public Static Functions

static std::unique_ptr<ELF> from_binary(std::unique_ptr<LIEF::ELF::Binary> bin, TargetSystem &engine, BIND binding = BIND::NOW)

Loads an ELF file directly from a LIEF object.

This function also loads the binary into engine, and return an :ELF object with associated information.

Parameters
  • bin[in] a valid LIEF::ELF::Binary object. The returned object takes ownership.

  • engine[in] Reference to a QBDL::TargetSystem object. The returned ELF object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned ELF object lives.

  • binding[in] Binding mode. Only BIND::NOW is supported for now.

Returns

A QBDL::Loaders::ELF object, or nullptr if loading failed.

static std::unique_ptr<ELF> from_file(const char *path, TargetSystem &engine, BIND binding = BIND_DEFAULT)

Loads an ELF file directly from disk.

This function also loads the binary into engine, and return an :ELF object with associated information.

Parameters
  • path[in] Path to the ELF file to load

  • engine[in] Reference to a QBDL::TargetSystem object. The returned ELF object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned ELF object lives.

  • binding[in] Binding mode. Note that BIND::LAZY is only supported with a native engine.

Returns

An QBDL::Loaders::ELF object, or nullptr if loading failed.

class MachO : public QBDL::Loader
#include <MachO.hpp>

Public Functions

inline operator bool() const
inline bool is_valid() const
virtual uint64_t get_address(const std::string &sym) const override

Get the resolved absolute virtual address of a symbol.

virtual uint64_t get_address(uint64_t offset) const override

Compute the absolute virtual address of on offset. This is basically base_address + offset.

virtual uint64_t entrypoint() const override

Get the absolute virtual address of the entrypoint.

virtual Arch arch() const override

Get the architecture targeted by the loaded binary.

~MachO() override

Public Static Functions

static std::unique_ptr<MachO> from_binary(std::unique_ptr<LIEF::MachO::Binary> bin, TargetSystem &engine, BIND binding = BIND_DEFAULT)

Loads a MachO file directly from a LIEF object.

This function also loads the binary into engine, and return a :MachO object with associated information.

Parameters
  • bin[in] a valid LIEF::MachO::Binary object. The returned object takes ownership.

  • engine[in] Reference to a QBDL::TargetSystem object. The returned ELF object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned ELF object lives.

  • binding[in] Binding mode. Only BIND::NOW is supported for now.

Returns

A QBDL::Loaders::MachO object, or nullptr if loading failed.

static std::unique_ptr<LIEF::MachO::Binary> take_arch_binary(LIEF::MachO::FatBinary &fatbin, Arch const &arch)

Select a binary from a universal MachO that matches a given architecture.

Parameters
  • fatbin[in] Reference to a LIEF::MachO::FatBinary object that represents the universal MachO binary

  • arch[in] Architecture to extract

Returns

A LIEF::MachO::Binary object if arch is found successful, nullptr otherwise. The caller gets the ownership of the returned object, and it has been removed from fatbin. Returns nullptr if nothing matches.

static std::unique_ptr<MachO> from_file(const char *path, Arch const &arch, TargetSystem &engine, BIND binding = BIND_DEFAULT)

Loads a (potentially universal) MachO file directly from disk.

If path is a universal MachO, this function will select the first architecture that matches with arch. If no such architecture is found, nullptr is returned. If successful, this function also loads the binary into engine.

Parameters
  • path[in] Path to the MachO file to load

  • arch[in] In case of a universal MachO, specify the architecture to extract

  • engine[in] Reference to a QBDL::TargetSystem object. The returned MachO object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned MachO object lives.

  • binding[in] Binding mode. Note that BIND::LAZY is only supported with a native engine.

Returns

An QBDL::Loaders::MachO object, or nullptr if loading failed.

class PE : public QBDL::Loader
#include <PE.hpp>

Public Functions

inline operator bool() const
inline bool is_valid() const
virtual uint64_t get_address(const std::string &sym) const override

Get the resolved absolute virtual address of a symbol.

virtual uint64_t get_address(uint64_t offset) const override

Compute the absolute virtual address of on offset. This is basically base_address + offset.

virtual uint64_t entrypoint() const override

Get the absolute virtual address of the entrypoint.

virtual Arch arch() const override

Get the architecture targeted by the loaded binary.

inline LIEF::PE::Binary &get_binary()
inline const LIEF::PE::Binary &get_binary() const
~PE() override

Public Static Functions

static std::unique_ptr<PE> from_binary(std::unique_ptr<LIEF::PE::Binary> bin, TargetSystem &engine, BIND binding = BIND_DEFAULT)

Loads an PE file directly from a LIEF object.

This function also loads the binary into engine, and return an :PE object with associated information.

Parameters
  • bin[in] a valid LIEF::PE::Binary object. The returned object takes ownership.

  • engine[in] Reference to a QBDL::TargetSystem object. The returned PE object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned PE object lives.

  • binding[in] Binding mode. Note that the current implementation only supports BIND::NOW.

Returns

A QBDL::Loaders::PE object, or nullptr if loading failed.

static std::unique_ptr<PE> from_file(const char *path, TargetSystem &engine, BIND binding = BIND_DEFAULT)

Loads an PE file directly from disk.

This function also loads the binary into engine, and return an :PE object with associated information.

Parameters
  • path[in] Path to the PE file to load

  • engine[in] Reference to a QBDL::TargetSystem object. The returned PE object does not own this reference. It is the responsibility of the user to ensure this object lives as long as the returned PE object lives.

  • binding[in] Binding mode. Note that the current implementation only supports BIND::DEFAULT and BIND::NOW.

Returns

An QBDL::Loaders::PE object, or nullptr if loading failed.