for insn in md.disasm(buf, address): ql.log.debug(f':: {insn.address:#x} : {insn.mnemonic:24s}{insn.op_str}')
if __name__ == "__main__": ql = Qiling([r'examples/rootfs/x8664_linux/bin/x8664_hello'], r'examples/rootfs/x8664_linux', verbose=QL_VERBOSE.DEBUG)
# have 'simple_disassembler' called on each instruction, passing a Capstone disassembler instance bound to # the underlying architecture as an optional argument ql.hook_code(simple_diassembler, user_data=ql.arch.disassembler)
from typing importTuple from unicorn.x86_const import UC_X86_INS_IN
defhandle_in(ql: Qiling, port: int, size: int) -> Tuple[int, int]: # call some function to look up the value held in the specified port (not implemented by Qiling) value = lookup_port_value(port, size) ql.log.debug(f'reading from port {port:#x}, size {size:d} -> {value:#0{size * 2 + 2}x}') # return a tuple indicating other hooks may be processed (0) and the read value (value) return (0, value) ql.hook_insn(handle_in, UC_X86_INS_IN)
其它hook
可以对内存的访问做hook来模拟硬件断点
1 2 3 4 5 6 7 8 9
ql.hook_int() ql.hook_mem_unmapped() ql.hook_mem_read_invalid() ql.hook_mem_write_invalid() ql.hook_mem_fetch_invalid() ql.hook_mem_invalid() ql.hook_mem_read(callback: Callable, begin: int = 1, end: int = 0) ql.hook_mem_write(callback: Callable, begin: int = 1, end: int = 0) ql.hook_mem_fetch()
hook管理
1 2
ql.hook_del() ql.clear_hooks()
API劫持
标准流
from qiling.extensions import pipe中有模拟流用的对象:SimpleInStream(fd)或SimpleOutStream(fd)替换掉标准输入流后可以直接write
from qiling import Qiling from qiling.extensions import pipe
if __name__ == "__main__": ql = Qiling([r'rootfs/x86_linux/bin/crackme_linux'], r'rootfs/x86_linux') ql.os.stdin = pipe.InteractiveInStream() # you will want to type L1NUX when the program waits for input ql.run()
from qiling import Qiling from qiling.os.disk import QlDisk
if __name__ == "__main__": ql = Qiling([r'rootfs/8086_dos/petya/mbr.bin'], r'rootfs/8086_dos')
# Note that this image is only intended for PoC purposes since the core petya code # resides in the sepecific sectors of a hard disk. It doesn't contain any data, either # encryted or unencrypted.
from qiling import Qiling from qiling.const import QL_INTERCEPT
# customized system calls always use the same arguments list as the original # ones, but with a Qiling instance on front. The Qiling instance may be used # to interact with various subsystems, such as the memory or registers defmy_syscall_write(ql: Qiling, fd: int, buf: int, count: int) -> int: try: # read data from emulated memory data = ql.mem.read(buf, count)
# select the emulated file object that corresponds to the requested # file descriptor fobj = ql.os.fd[fd]
# write the data into the file object, if it supports write operations ifhasattr(fobj, 'write'): fobj.write(data) except: ret = -1 else: ret = count
if __name__ == "__main__": ql = Qiling([r'rootfs/arm_linux/bin/arm_hello'], r'rootfs/arm_linux')
# the following call to 'set_syscall' sets 'my_syscall_write' to execute whenever # the 'write' system call is about to be called. that practically replaces the # existing implementation with the one in 'my_syscall_write'. ql.os.set_syscall('write', my_syscall_write, QL_INTERCEPT.CALL)
# note that system calls may be referred to either by their name or number. # an equivalent alternative that replaces the write syscall by refering its number: # #ql.os.set_syscall(4, my_syscall_write)