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:
UC_X86_INS_SYSCALLUC_X86_INS_INUC_X86_INS_OUT
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].
endomitted → only intercept reads atbegin- both omitted → intercept all reads
valueargument in callback is always 0 (unused)- callback may write a new value to memory before it is read
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()