Skip to content

API Reference

xwings edited this page Jul 6, 2025 · 5 revisions

API Reference

This page provides comprehensive documentation for the Qiling Framework API.

Core Classes

Qiling Class

The main class for all Qiling operations.

class Qiling:
    def __init__(self, argv=None, rootfs=None, env=None, code=None, 
                 ostype=None, archtype=None, bigendian=False, 
                 verbose=QL_VERBOSE.DEFAULT, profile=None, 
                 console=True, log_dir=None, libcache=False, 
                 stdin=None, stdout=None, stderr=None, 
                 multithread=False, filter=None, **kwargs)

Initialization Parameters

Parameter Type Description
argv list[str] Command line arguments for binary emulation
rootfs str Root filesystem path
env dict Environment variables
code bytes Shellcode for shellcode emulation
ostype QL_OS Target OS type
archtype QL_ARCH Target architecture
bigendian bool Big endian architecture
verbose QL_VERBOSE Verbosity level
profile str Profile file path
console bool Enable console output
libcache bool Enable library caching
multithread bool Enable multithreading

Core Methods

Execution Control:

def run(self, begin=None, end=None, timeout=0, count=0)
    """Start emulation with optional constraints"""

def stop(self)
    """Stop emulation"""

def emu_start(self, begin, end, timeout=0, count=0)
    """Low-level emulation start"""

def emu_stop(self)
    """Low-level emulation stop"""

Memory Operations:

def mem_write(self, addr, data)
    """Write data to memory at address"""

def mem_read(self, addr, size)
    """Read data from memory"""

def mem_map(self, addr, size, perms=None, ptr=None)
    """Map memory region"""

def mem_unmap(self, addr, size)
    """Unmap memory region"""

def mem_protect(self, addr, size, perms)
    """Change memory protection"""

def mem_is_mapped(self, addr, size=1)
    """Check if memory is mapped"""

Patching:

def patch(self, addr, code, file_name=None)
    """Patch memory or file"""

def unpatch(self, addr)
    """Remove patch"""

Filesystem:

def add_fs_mapper(self, fm, to)
    """Map filesystem paths"""

def remove_fs_mapper(self, fm)
    """Remove filesystem mapping"""

Hooking:

def hook_address(self, callback, address, user_data=None)
    """Hook specific address"""

def hook_code(self, callback, user_data=None)
    """Hook all instructions"""

def hook_block(self, callback, user_data=None)
    """Hook basic blocks"""

def hook_mem_read(self, callback, user_data=None)
    """Hook memory reads"""

def hook_mem_write(self, callback, user_data=None)
    """Hook memory writes"""

def hook_mem_fetch(self, callback, user_data=None)
    """Hook memory fetches"""

def hook_intr(self, callback, user_data=None)
    """Hook interrupts"""

Architecture API (ql.arch)

Register Access:

# Read registers
ql.arch.regs.rax    # x86_64 RAX register
ql.arch.regs.eip    # x86 EIP register
ql.arch.regs.r0     # ARM R0 register

# Write registers
ql.arch.regs.rax = 0x1234
ql.arch.regs.write("rax", 0x1234)

# Get all registers
all_regs = ql.arch.regs.save()
ql.arch.regs.restore(all_regs)

Architecture Information:

ql.arch.type         # Architecture type
ql.arch.bits         # Architecture bits (32/64)
ql.arch.endian       # Endianness
ql.arch.get_pc()     # Program counter
ql.arch.set_pc(addr) # Set program counter
ql.arch.get_sp()     # Stack pointer
ql.arch.set_sp(addr) # Set stack pointer

Operating System API (ql.os)

File Operations:

ql.os.fd           # File descriptor table
ql.os.fs_mapper    # Filesystem mappings
ql.os.stdin        # Standard input
ql.os.stdout       # Standard output
ql.os.stderr       # Standard error

Process Information:

ql.os.pid          # Process ID
ql.os.ppid         # Parent process ID
ql.os.uid          # User ID
ql.os.gid          # Group ID
ql.os.exit_code    # Exit code

Threading:

ql.os.thread_management    # Thread manager
ql.os.current_thread      # Current thread
ql.os.main_thread         # Main thread

Memory API (ql.mem)

Memory Operations:

def read(self, addr, size)
    """Read memory"""

def write(self, addr, data)
    """Write memory"""

def string(self, addr, encoding='utf-8')
    """Read null-terminated string"""

def map(self, addr, size, perms=UC_PROT_ALL, info=None)
    """Map memory region"""

def unmap(self, addr, size)
    """Unmap memory region"""

def protect(self, addr, size, perms)
    """Change memory permissions"""

def is_mapped(self, addr, size=1)
    """Check if memory is mapped"""

def align(self, addr, alignment=0x1000)
    """Align address"""

def get_mapinfo(self)
    """Get memory map information"""

Stack Operations:

def push(self, data)
    """Push data to stack"""

def pop(self)
    """Pop data from stack"""

def read_ptr(self, addr=None)
    """Read pointer from memory"""

def write_ptr(self, addr, value)
    """Write pointer to memory"""

Constants and Enums

Architecture Types (QL_ARCH)

QL_ARCH.X86        # 32-bit x86
QL_ARCH.X8664      # 64-bit x86
QL_ARCH.ARM        # 32-bit ARM
QL_ARCH.ARM64      # 64-bit ARM
QL_ARCH.MIPS       # MIPS
QL_ARCH.A8086      # 8086
QL_ARCH.CORTEX_M   # Cortex-M
QL_ARCH.RISCV      # RISC-V 32-bit
QL_ARCH.RISCV64    # RISC-V 64-bit
QL_ARCH.PPC        # PowerPC

Operating Systems (QL_OS)

QL_OS.LINUX        # Linux
QL_OS.WINDOWS      # Windows
QL_OS.MACOS        # macOS
QL_OS.FREEBSD      # FreeBSD
QL_OS.UEFI         # UEFI
QL_OS.DOS          # DOS
QL_OS.QNX          # QNX
QL_OS.MCU          # Microcontroller
QL_OS.BLOB         # Raw binary blob

Verbosity Levels (QL_VERBOSE)

QL_VERBOSE.OFF       # No output
QL_VERBOSE.DEFAULT   # Basic output
QL_VERBOSE.DEBUG     # Debug information
QL_VERBOSE.DISASM    # Include disassembly
QL_VERBOSE.DUMP      # Memory dumps

Hook Types

QL_HOOK.CODE         # Instruction hooks
QL_HOOK.BLOCK        # Basic block hooks
QL_HOOK.MEM_READ     # Memory read hooks
QL_HOOK.MEM_WRITE    # Memory write hooks
QL_HOOK.MEM_FETCH    # Memory fetch hooks
QL_HOOK.INTR         # Interrupt hooks

Memory Permissions

UC_PROT_NONE         # No access
UC_PROT_READ         # Read only
UC_PROT_WRITE        # Write only
UC_PROT_EXEC         # Execute only
UC_PROT_ALL          # Read/Write/Execute

Debugging API

QDB Debugger

ql.debugger = "qdb"
ql.run()

QDB provides an interactive debugging interface with commands like:

  • run - Start execution
  • step - Single step
  • continue - Continue execution
  • info reg - Show registers
  • x/10x $rsp - Examine memory
  • breakpoint 0x401000 - Set breakpoint

GDB Server

ql.debugger = "gdb:localhost:9999"
ql.run()

Connect external GDB to the server for advanced debugging.

Loader API

Binary Loaders

Different loaders for various file formats:

# PE Loader (Windows)
from qiling.loader.pe import QlLoaderPE

# ELF Loader (Linux/Unix)
from qiling.loader.elf import QlLoaderELF

# Mach-O Loader (macOS)
from qiling.loader.macho import QlLoaderMACHO

# Access loader
ql.loader.load_address    # Load address
ql.loader.entry_point     # Entry point
ql.loader.images          # Loaded images
ql.loader.import_symbols  # Import table
ql.loader.export_symbols  # Export table

Extension APIs

Fuzzing (AFL++)

def afl_fuzz_custom(ql, input_data, persistent_addr, exits):
    # Custom AFL++ fuzzing logic
    pass

ql.afl_fuzz(input_file, persistent_addr, exits, afl_fuzz_custom)

Tracing

from qiling.extensions.trace import QlTracer

tracer = QlTracer(ql)
tracer.trace_func_call = True
tracer.trace_func_ret = True
ql.run()

Coverage Collection

from qiling.extensions.coverage import QlCoverage

cov = QlCoverage(ql)
ql.run()
coverage_data = cov.get_coverage()

Utility Functions

Common Helpers

from qiling.utils import *

# Address calculations
def align_up(addr, alignment)
def align_down(addr, alignment)

# Data conversions
def int_to_bytes(value, size, byteorder='little')
def bytes_to_int(data, byteorder='little')

# String utilities
def read_cstring(ql, addr)
def read_wstring(ql, addr)

Architecture Utilities

from qiling.arch.utils import *

# Instruction utilities
def disasm(ql, code, addr)
def asm(ql, code, addr)

# Register utilities
def reg_read(ql, reg_name)
def reg_write(ql, reg_name, value)

Hook Callback Signatures

Code Hooks

def code_hook(ql, address, size):
    """Called for each instruction
    
    Args:
        ql: Qiling instance
        address: Instruction address
        size: Instruction size
    """
    pass

Memory Hooks

def mem_hook(ql, access, address, size, value):
    """Called for memory access
    
    Args:
        ql: Qiling instance
        access: Access type (UC_MEM_READ/WRITE/FETCH)
        address: Memory address
        size: Access size
        value: Value (for writes)
    """
    pass

Address Hooks

def addr_hook(ql):
    """Called at specific address
    
    Args:
        ql: Qiling instance
    """
    pass

API Hooks

def api_hook(ql, *args, **kwargs):
    """Called for hooked API
    
    Args:
        ql: Qiling instance
        *args: API arguments
        **kwargs: Additional parameters
        
    Returns:
        API return value or None for original behavior
    """
    pass

Error Handling

Common Exceptions

from qiling.exception import *

QlErrorException       # General Qiling error
QlMemoryMappedError   # Memory mapping error
QlOutOfMemory         # Out of memory
QlErrorFileNotFound   # File not found
QlErrorArch           # Architecture error
QlErrorOS             # OS error
QlErrorExecutionStop  # Execution stopped

Example Error Handling

from qiling import Qiling
from qiling.exception import QlErrorException

try:
    ql = Qiling(['binary'], 'rootfs')
    ql.run()
except QlErrorException as e:
    print(f"Qiling error: {e}")
except Exception as e:
    print(f"General error: {e}")

Best Practices

Performance Tips

  • Use libcache=True for Windows binaries
  • Enable multithread for multithreaded applications
  • Use appropriate verbosity levels
  • Consider memory mapping for large datasets

Security Considerations

  • Always use isolated rootfs directories
  • Validate input data before emulation
  • Monitor memory usage for potential DoS
  • Use timeouts for long-running emulations

Debugging Tips

  • Start with QL_VERBOSE.DEBUG for troubleshooting
  • Use hooks to track program flow
  • Examine memory layout with ql.mem.get_mapinfo()
  • Check register states at critical points

Platform-Specific APIs

Windows-specific

# Registry access
ql.os.registry.read(key, value)
ql.os.registry.write(key, value, data)

# Handle table
ql.os.handle_manager.get(handle_id)
ql.os.handle_manager.create(obj)

# Thread management
ql.os.thread_manager.current_thread

Linux-specific

# Process filesystem
ql.os.proc_fd_table
ql.os.proc_pid

# Signal handling
ql.os.signals

MCU-specific

# Hardware peripherals
ql.hw.gpio
ql.hw.uart
ql.hw.timer

# Interrupt handling
ql.hw.nvic

For more detailed examples and advanced usage patterns, see the Advanced Usage guide.

Clone this wiki locally