Hook API

Hook API

ql.hook_address(callback, address)

Registers a callback invoked when execution reaches a specific address.

1from qiling import Qiling
2
3def stop(ql: Qiling) -> None:
4    ql.log.info('killer switch found, stopping')
5    ql.emu_stop()
6
7ql = Qiling([r'examples/rootfs/x86_windows/bin/wannacry.bin'], r'examples/rootfs/x86_windows')
8ql.hook_address(stop, 0x40819a)
9ql.run()

ql.hook_code(callback, user_data=None)

Invoked on every instruction just before execution. Callback signature: (ql, address, size, [user_data]).

 1from capstone import Cs
 2from qiling import Qiling
 3from qiling.const import QL_VERBOSE
 4
 5def simple_disassembler(ql: Qiling, address: int, size: int, md: Cs) -> None:
 6    buf = ql.mem.read(address, size)
 7    for insn in md.disasm(buf, address):
 8        ql.log.debug(f':: {insn.address:#x} : {insn.mnemonic:24s} {insn.op_str}')
 9
10ql = Qiling([r'examples/rootfs/x8664_linux/bin/x8664_hello'], r'examples/rootfs/x8664_linux', verbose=QL_VERBOSE.DEBUG)
11ql.hook_code(simple_disassembler, user_data=ql.arch.disassembler)
12ql.run()

ql.hook_block(callback)

Invoked at the start of each basic block. Callback signature: (ql, address, size).

1def ql_hook_block_disasm(ql, address, size):
2    ql.log.debug("\n[+] Tracing basic block at 0x%x" % address)
3
4ql.hook_block(ql_hook_block_disasm)

ql.hook_intno(callback, intno)

Hooks a specific interrupt number.

1ql.hook_intno(hook_syscall, 0x80)

ql.hook_insn(callback, insn_type)

Intercepts a specific instruction type (limited to Unicorn-supported types).

Supported x86 instruction types:

1from typing import Tuple
2from unicorn.x86_const import UC_X86_INS_IN
3
4def handle_in(ql: Qiling, port: int, size: int) -> Tuple[int, int]:
5    value = lookup_port_value(port, size)
6    ql.log.debug(f'reading from port {port:#x}, size {size:d} -> {value:#0{size * 2 + 2}x}')
7    return (0, value)  # (continue_flag, read_value)
8
9ql.hook_insn(handle_in, UC_X86_INS_IN)

ql.hook_intr(callback)

Hooks all interrupts.

Memory Hooks

ql.hook_mem_read(callback, begin=1, end=0)

Intercepts memory reads in range [begin, end].

1from unicorn.unicorn_const import UC_MEM_READ
2
3def mem_read(ql: Qiling, access: int, address: int, size: int, value: int) -> None:
4    assert access == UC_MEM_READ
5    ql.log.debug(f'intercepted a memory read from {address:#x}')
6
7stack_lbound = ql.arch.regs.arch_sp
8stack_ubound = ql.arch.regs.arch_sp - 0x1000
9ql.hook_mem_read(mem_read, begin=stack_ubound, end=stack_lbound)

ql.hook_mem_write(callback, begin=1, end=0)

Intercepts memory writes in range [begin, end].

1from unicorn.unicorn_const import UC_MEM_WRITE
2
3def mem_write(ql: Qiling, access: int, address: int, size: int, value: int) -> None:
4    assert access == UC_MEM_WRITE
5    ql.log.debug(f'intercepted a memory write to {address:#x} (value = {value:#x})')
6
7ql.hook_mem_write(mem_write, 0xdecaf000)

ql.hook_mem_fetch(callback)

Monitors memory fetch (instruction fetch) on a specific address.

ql.hook_mem_unmapped(callback)

Intercepts memory accesses (read/write/fetch) to unmapped addresses.

ql.hook_mem_read_invalid(callback)

ql.hook_mem_write_invalid(callback)

ql.hook_mem_fetch_invalid(callback)

ql.hook_mem_invalid(callback)

Intercepts invalid memory accesses: unmapped addresses and protection violations (write to read-only, fetch from non-executable).

Hook Management

ql.hook_del(hook)

Removes a specific hook.

ql.clear_hooks()

Removes all registered hooks.

1ql.clear_hooks()