Zydis Encoder

The Zydis Encoder API lets you assemble instructions into raw machine code at runtime. It’s designed for:

  • Re-assembling disassembled code into position-independent shellcode

  • Dynamically building/modifying shellcode for Unicorn emulation

  • Inserting breakpoints (int3) or patching code on the fly

This encoder complements your Zydis disassembler by providing a structured way to create ZydisEncoderRequest objects and turn them into bytes.


Concepts

Machine Mode

Most encoding depends on the active CPU mode:

  • MODE_LONG_64 (x86-64)

  • MODE_LONG_COMPAT_32, MODE_LONG_COMPAT_16

  • MODE_LEGACY_32, MODE_LEGACY_16

  • MODE_REAL_16

Set the machine mode either:

  • per-request (ZydisEncoderRequest.set_machine_mode)

  • globally in a builder (ZydisBuilder.set_machine_mode)


Enums

ZYDIS_MACHINE_MODE

  • MODE_LONG_64

  • MODE_LONG_COMPAT_32

  • MODE_LONG_COMPAT_16

  • MODE_LEGACY_32

  • MODE_LEGACY_16

  • MODE_REAL_16

ZYDIS_BRANCH_TYPE

Controls how a branch should be encoded.

  • BRANCH_NONE

  • BRANCH_SHORT

  • BRANCH_NEAR

  • BRANCH_FAR

ZYDIS_BRANCH_WIDTH

Controls displacement width for branch encoding.

  • WIDTH_NONE

  • WIDTH_8

  • WIDTH_16

  • WIDTH_32

  • WIDTH_64


Types

ZydisEncoderRequest (value type)

A request describes a single instruction to be encoded.

Mnemonic & mode

  • void set_mnemonic(int mnemonic)

  • int get_mnemonic()

  • void set_machine_mode(int mode)

  • int get_machine_mode()

Operands

  • void set_operand_count(int count)

  • int get_operand_count()

Branch controls

  • void set_branch_type(int type)

  • void set_branch_width(int width)

Operand setters

  • void set_operand_reg(int index, int reg)

  • void set_operand_imm(int index, int64 imm)

  • void set_operand_mem(int index, int base, int idx, int scale, int64 disp, int size)

  • void set_operand_ptr(int index, uint16 segment, uint32 offset)

Notes

  • Operand indexing is 0-based.

  • You must call set_operand_count(n) before setting operands.

  • For memory operands, base and idx are register IDs (or 0 / none depending on your bindings), with:

    • scale: typically 1, 2, 4, 8

    • disp: signed displacement

    • size: operand size in bytes (e.g., 4 for dword, 8 for qword)


ZydisBuilder (reference type)

A builder collects instructions + raw bytes and emits a single byte array.

Construction

  • ZydisBuilder@ ZydisBuilder() — factory

Configuration

  • void set_machine_mode(int mode)

  • void set_base_address(uint64 addr)

Managing entries

  • void clear()

  • void push(const ZydisEncoderRequest &in req)

  • int get_instruction_count()

Raw bytes helpers

  • void push_bytes(const array<uint8> &in bytes)

  • void push_byte(uint8 b)

  • void push_u16(uint16 value) — little-endian

  • void push_u32(uint32 value) — little-endian

  • void push_u64(uint64 value) — little-endian

Convenience opcodes

  • void push_nop(int count = 1)

  • void push_int3()

  • void push_ret()

Build output

  • bool build(array<uint8> &out bytes)

Notes

  • set_base_address() matters for relative branches and RIP-based calculations.

  • push_* functions let you interleave code and data (useful for shellcode blobs).


Global Functions

Encoding

  • bool zydis_encode(ZydisEncoderRequest &in req, array<uint8> &out bytes)

  • bool zydis_encode_absolute(ZydisEncoderRequest &in req, uint64 runtime_address, array<uint8> &out bytes)

Use zydis_encode_absolute when the instruction’s encoding depends on the actual runtime address (e.g., some branch forms / relative addressing decisions).

Utilities

  • bool zydis_nop_fill(array<uint8> &out bytes, uint32 length)

  • bool zydis_decoded_to_request(const array<uint8> &in bytes, uint64 runtime_rip, ZydisEncoderRequest &out req)

Mnemonic and register conversion

  • int zydis_mnemonic_from_string(const string &in name)

  • string zydis_mnemonic_to_string(int mnemonic)

  • int zydis_register_from_string(const string &in name)

  • string zydis_register_to_string(int reg)


Full Test Example


Examples

1) Basic encoding


2) Building shellcode with ZydisBuilder


3) Mixing instructions + data


4) Decode → Request → Re-encode

Last updated