Registers and Expressions

What is an Expression?

An expression is a statement evaluated in the context of the debugger. It can be as simple as 2+2, or a complex calculation involving symbols, scales, and segments. x64dbg Automate provides the debugger's full evaluation capabilities, and adds some convenience methods.

When you request a register in x64dbg Automate it's really just shorthand for evaluating an expression where the only value is your register. This is true unless a full register dump is requested. This is the exception to the above rule - instead providing a full thread context dump in the format the debugger uses internally.

The full register dump can be useful for accessing more nuanced parts of thread state, but is generally overkill for common tasks like retrieving a common register value.

Example: Expressions and Registers

"""
Example: Expressions and Registers (64 bit)
"""
import sys
from x64dbg_automate import X64DbgClient
from x64dbg_automate.models import RegDump64

if len(sys.argv) != 2:
    print("Usage: python hello64.py <x64dbg_path>")
    quit(1)

print('[+] Creating a new x64dbg Automate session')
client = X64DbgClient(x64dbg_path=sys.argv[1])
client.start_session(r'c:\Windows\system32\winver.exe')

print('[+] Getting the value of RIP')
rip = client.get_reg('rip')
print(f'\tRIP: 0x{rip:X}')

print('[+] Setting the value of RIP')
client.set_reg('rip', 0x1234)

print('[+] Setting the value of RIP to an expression')
value, _ = client.eval_sync('LoadLibraryA + 0x20')
client.set_reg('rip', value)

print('[+] Setting the value of a subregister')
client.set_reg('rax', 0)
client.set_reg('ah', 0x99)

print('[+] Performing a full register dump')
dump: RegDump64 = client.get_regs()
print(f'\tRIP: 0x{dump.context.rip:X}')
print(f'\tRAX: 0x{dump.context.rax:X}')

print('[+] Cleaning up')
client.terminate_session()
[+] Creating a new x64dbg Automate session
[+] Getting the value of RIP
        RIP: 0x7FFC97E6142A
[+] Setting the value of RIP
[+] Setting the value of RIP to an expression
[+] Setting the value of a subregister
[+] Performing a full register dump
        RIP: 0x7FFC973C2DA0
        RAX: 0x9900
[+] Cleaning up

API Method Reference

get_reg(reg)

Get a single register or subregister

Parameters:

Name Type Description Default
reg MutableRegister | str

Register to get

required

Returns:

Type Description
int

Success

Source code in x64dbg_automate/hla_xauto.py
def get_reg(self, reg: MutableRegister | str) -> int:
    """
    Get a single register or subregister

    Args:
        reg: Register to get

    Returns:
        Success
    """
    reg = MutableRegister(str(reg).lower())
    res, success = self.eval_sync(f'{reg}')
    if not success:
        raise ValueError(f"Failed to evaluate register {reg}")
    return res

get_regs()

Dump the registers of the debugee

Returns:

Type Description
list[RegDump32] | list[RegDump64]

A list of RegDump objects

Source code in x64dbg_automate/commands_xauto.py
def get_regs(self) -> list[RegDump32] | list[RegDump64]:
    """
    Dump the registers of the debugee

    Returns:
        A list of RegDump objects
    """
    raw_regs = self._send_request(XAutoCommand.XAUTO_REQ_DBG_READ_REGISTERS)
    bitness = raw_regs[0]
    raw_regs = raw_regs[1:]
    if bitness == 64:
        ctx = {k: v for k, v in zip(Context64.model_fields.keys(), raw_regs[0])}
        ctx['x87_fpu'] = X87Fpu(**{k: v for k, v in zip(X87Fpu.model_fields.keys(), ctx['x87_fpu'])})
        ctx['xmm_regs'] = [ctx['xmm_regs'][i:i+16] for i in range(0, len(ctx['xmm_regs']), 16)]
        ctx['ymm_regs'] = [ctx['ymm_regs'][i:i+32] for i in range(0, len(ctx['ymm_regs']), 32)]
        return RegDump64(
            context=Context64(**ctx),
            flags=Flags(**{k: v for k, v in zip(Flags.model_fields.keys(), raw_regs[1])}),
            fpu=[FpuReg(data=raw_regs[2][i][0], st_value=raw_regs[2][i][1], tag=raw_regs[2][i][2]) for i in range(len(raw_regs[2]))],
            mmx=raw_regs[3],
            mxcsr_fields=MxcsrFields(**{k: v for k, v in zip(MxcsrFields.model_fields.keys(), raw_regs[4])}),
            x87_status_word_fields=X87StatusWordFields(**{k: v for k, v in zip(X87StatusWordFields.model_fields.keys(), raw_regs[5])}),
            x87_control_word_fields=X87ControlWordFields(**{k: v for k, v in zip(X87ControlWordFields.model_fields.keys(), raw_regs[6])}),
            last_error=(raw_regs[7][0], raw_regs[7][1].decode().strip('\0')),
            last_status=(raw_regs[8][0], raw_regs[8][1].decode().strip('\0'))
        )
    else:
        ctx = {k: v for k, v in zip(Context32.model_fields.keys(), raw_regs[0])}
        ctx['x87_fpu'] = X87Fpu(**{k: v for k, v in zip(X87Fpu.model_fields.keys(), ctx['x87_fpu'])})
        ctx['xmm_regs'] = [ctx['xmm_regs'][i:i+16] for i in range(0, len(ctx['xmm_regs']), 16)]
        ctx['ymm_regs'] = [ctx['ymm_regs'][i:i+32] for i in range(0, len(ctx['ymm_regs']), 32)]
        return RegDump32(
            context=Context32(**ctx),
            flags=Flags(**{k: v for k, v in zip(Flags.model_fields.keys(), raw_regs[1])}),
            fpu=[FpuReg(data=raw_regs[2][i][0], st_value=raw_regs[2][i][1], tag=raw_regs[2][i][2]) for i in range(len(raw_regs[2]))],
            mmx=raw_regs[3],
            mxcsr_fields=MxcsrFields(**{k: v for k, v in zip(MxcsrFields.model_fields.keys(), raw_regs[4])}),
            x87_status_word_fields=X87StatusWordFields(**{k: v for k, v in zip(X87StatusWordFields.model_fields.keys(), raw_regs[5])}),
            x87_control_word_fields=X87ControlWordFields(**{k: v for k, v in zip(X87ControlWordFields.model_fields.keys(), raw_regs[6])}),
            last_error=(raw_regs[7][0], raw_regs[7][1]),
            last_status=(raw_regs[8][0], raw_regs[8][1])
        )

set_reg(reg, val)

Set a single register or subregister to a value

Parameters:

Name Type Description Default
reg MutableRegister | str

Register to set

required
val int

Value to set

required

Returns:

Type Description
bool

Success

Source code in x64dbg_automate/hla_xauto.py
def set_reg(self, reg: MutableRegister | str, val: int) -> bool:
    """
    Set a single register or subregister to a value

    Args:
        reg: Register to set
        val: Value to set

    Returns:
        Success
    """
    reg = MutableRegister(str(reg).lower())
    if not isinstance(val, int):
        raise TypeError("val must be an integer")
    return self.cmd_sync(f'{reg}=0x{val:X}')

eval_sync(eval_str)

Evaluates an expression that results in a numerical output

Returns:

Type Description
list[int, bool]

A list containing the result and a boolean indicating success

Source code in x64dbg_automate/commands_xauto.py
def eval_sync(self, eval_str) -> list[int, bool]:
    """
    Evaluates an expression that results in a numerical output

    Returns:
        A list containing the result and a boolean indicating success
    """
    return self._send_request(XAutoCommand.XAUTO_REQ_DBG_EVAL, eval_str)

get_symbol_at(addr)

Retrieves the symbol at the specified address

Parameters:

Name Type Description Default
addr int

The address to get the symbol for

required

Returns:

Type Description
Symbol | None

A Symbol object or None if no symbol was found

Source code in x64dbg_automate/commands_xauto.py
def get_symbol_at(self, addr: int) -> Symbol | None:
    """
    Retrieves the symbol at the specified address

    Args:
        addr: The address to get the symbol for

    Returns:
        A Symbol object or None if no symbol was found
    """
    res = self._send_request(XAutoCommand.XAUTO_REQ_GET_SYMBOL, addr)
    if not res[0]:
        return ""
    return Symbol(
        addr=res[1],
        decoratedSymbol=res[2],
        undecoratedSymbol=res[3],
        type=SymbolType(res[4]),
        ordinal=res[5]
    )

API Model Reference

RegDump

Bases: BaseModel

Source code in x64dbg_automate/models.py
class RegDump(BaseModel):
    flags: Flags
    fpu: list[FpuReg]
    mmx: list[int]
    mxcsr_fields: MxcsrFields
    x87_status_word_fields: X87StatusWordFields
    x87_control_word_fields: X87ControlWordFields
    last_error: tuple[int, str]
    last_status: tuple[int, str]

RegDump64

Bases: RegDump

Source code in x64dbg_automate/models.py
class RegDump64(RegDump):
    context: Context64

RegDump32

Bases: RegDump

Source code in x64dbg_automate/models.py
class RegDump32(RegDump):
    context: Context32

Context64

Bases: BaseModel

Source code in x64dbg_automate/models.py
class Context64(BaseModel):
    rax: int
    rbx: int
    rcx: int
    rdx: int
    rbp: int
    rsp: int
    rsi: int
    rdi: int
    r8: int
    r9: int
    r10: int
    r11: int
    r12: int
    r13: int
    r14: int
    r15: int
    rip: int
    eflags: int
    cs: int
    ds: int
    es: int
    fs: int
    gs: int
    ss: int
    dr0: int
    dr1: int
    dr2: int
    dr3: int
    dr6: int
    dr7: int
    reg_area: bytes
    x87_fpu: X87Fpu
    mxcsr: int
    xmm_regs: list[bytes]
    ymm_regs: list[bytes]

Context32

Bases: BaseModel

Source code in x64dbg_automate/models.py
class Context32(BaseModel):
    eax: int
    ebx: int
    ecx: int
    edx: int
    ebp: int
    esp: int
    esi: int
    edi: int
    eip: int
    eflags: int
    cs: int
    ds: int
    es: int
    fs: int
    gs: int
    ss: int
    dr0: int
    dr1: int
    dr2: int
    dr3: int
    dr6: int
    dr7: int
    reg_area: bytes
    x87_fpu: X87Fpu
    mxcsr: int
    xmm_regs: list[bytes]
    ymm_regs: list[bytes]

X87Fpu

Bases: BaseModel

Source code in x64dbg_automate/models.py
class X87Fpu(BaseModel):
    ControlWord: int
    StatusWord: int
    TagWord: int
    ErrorOffset: int
    ErrorSelector: int
    DataOffset: int
    DataSelector: int
    Cr0NpxState: int

Flags

Bases: BaseModel

Source code in x64dbg_automate/models.py
class Flags(BaseModel):
    c: bool
    p: bool
    a: bool
    z: bool
    s: bool
    t: bool
    i: bool
    d: bool
    o: bool

FpuReg

Bases: BaseModel

Source code in x64dbg_automate/models.py
class FpuReg(BaseModel):
    data: bytes
    st_value: int
    tag: int

MxcsrFields

Bases: BaseModel

Source code in x64dbg_automate/models.py
class MxcsrFields(BaseModel):
    FZ: bool
    PM: bool
    UM: bool
    OM: bool
    ZM: bool
    IM: bool
    DM: bool
    DAZ: bool
    PE: bool
    UE: bool
    OE: bool
    ZE: bool
    DE: bool
    IE: bool
    RC: int

X87StatusWordFields

Bases: BaseModel

Source code in x64dbg_automate/models.py
class X87StatusWordFields(BaseModel):
    B: bool
    C3: bool
    C2: bool
    C1: bool
    C0: bool
    ES: bool
    SF: bool
    P: bool
    U: bool
    O: bool
    Z: bool
    D: bool
    I: bool
    TOP: int

X87ControlWordFields

Bases: BaseModel

Source code in x64dbg_automate/models.py
class X87ControlWordFields(BaseModel):
    IC: bool
    IEM: bool
    PM: bool
    UM: bool
    OM: bool
    ZM: bool
    DM: bool
    IM: bool
    RC: int
    PC: int

Symbol

Bases: BaseModel

Source code in x64dbg_automate/models.py
class Symbol(BaseModel):
    addr: int
    decoratedSymbol: str
    undecoratedSymbol: str
    type: int
    ordinal: int

SymbolType

Bases: IntEnum

Source code in x64dbg_automate/models.py
class SymbolType(IntEnum):
    SymImport = 0
    SymExport = 1
    SymSymbol = 2

MutableRegister

Bases: StrEnum

Source code in x64dbg_automate/models.py
class MutableRegister(StrEnum):
    cip = 'cip'
    rax = 'rax'
    rbx = 'rbx'
    rcx = 'rcx'
    rdx = 'rdx'
    rbp = 'rbp'
    rsp = 'rsp'
    rsi = 'rsi'
    rdi = 'rdi'
    r8 = 'r8'
    r9 = 'r9'
    r10 = 'r10'
    r11 = 'r11'
    r12 = 'r12'
    r13 = 'r13'
    r14 = 'r14'
    r15 = 'r15'
    rip = 'rip'
    eip = 'eip'
    eflags = 'eflags'
    rflags = 'rflags'
    cs = 'cs'
    ds = 'ds'
    es = 'es'
    fs = 'fs'
    gs = 'gs'
    ss = 'ss'
    dr0 = 'dr0'
    dr1 = 'dr1'
    dr2 = 'dr2'
    dr3 = 'dr3'
    dr6 = 'dr6'
    dr7 = 'dr7'
    eax = 'eax'
    ebx = 'ebx'
    ecx = 'ecx'
    edx = 'edx'
    ebp = 'ebp'
    esp = 'esp'
    esi = 'esi'
    edi = 'edi'
    ax = 'ax'
    bx = 'bx'
    cx = 'cx'
    dx = 'dx'
    si = 'si'
    di = 'di'
    bp = 'bp'
    sp = 'sp'
    al = 'al'
    bl = 'bl'
    cl = 'cl'
    dl = 'dl'
    ah = 'ah'
    bh = 'bh'
    ch = 'ch'
    dh = 'dh'
    sil = 'sil'
    dil = 'dil'
    bpl = 'bpl'
    spl = 'spl'
    r8d = 'r8d'
    r9d = 'r9d'
    r10d = 'r10d'
    r11d = 'r11d'
    r12d = 'r12d'
    r13d = 'r13d'
    r14d = 'r14d'
    r15d = 'r15d'
    r8w = 'r8w'
    r9w = 'r9w'
    r10w = 'r10w'
    r11w = 'r11w'
    r12w = 'r12w'
    r13w = 'r13w'
    r14w = 'r14w'
    r15w = 'r15w'
    r8b = 'r8b'
    r9b = 'r9b'
    r10b = 'r10b'
    r11b = 'r11b'
    r12b = 'r12b'
    r13b = 'r13b'
    r14b = 'r14b'
    r15b = 'r15b'