def hook_TerminateProcess(ql: Qiling, address: int, params): # Samples will try to kill other process! We don't want to always stop! process = params["hProcess"] if process == ql.os.profile.getint( "KERNEL", "pid"): # or process == ql.os.image_address: ql.emu_stop() ql.os.PE_RUN = False return 1
def ql_syscall_execve(ql: Qiling, pathname: int, argv: int, envp: int): file_path = ql.os.utils.read_cstring(pathname) real_path = ql.os.path.transform_to_real_path(file_path) def __read_str_array(addr: int) -> Iterator[str]: if addr: while True: elem = ql.mem.read_ptr(addr) if elem == 0: break yield ql.os.utils.read_cstring(elem) addr += ql.arch.pointersize args = [s for s in __read_str_array(argv)] env = {} for s in __read_str_array(envp): k, _, v = s.partition('=') env[k] = v ql.emu_stop() ql.log.debug( f'execve({file_path}, [{", ".join(args)}], [{", ".join(f"{k}={v}" for k, v in env.items())}])' ) ql.loader.argv = args ql.loader.env = env ql._path = real_path ql.mem.map_info = [] ql.clear_ql_hooks() # Clean debugger to prevent port conflicts # ql.debugger = None if ql.code: return # recreate cached uc del ql.arch.uc uc = ql.arch.uc # propagate new uc to arch internals ql.arch.regs.uc = uc if hasattr(ql.arch, 'msr'): ql.arch.msr.uc = uc QlCoreHooks.__init__(ql, uc) ql.os.load() ql.loader.run() ql.run()
def __leaf_53(ql: Qiling): al = ql.arch.regs.al if al == 0x01: ql.os.clear_cf() elif al == 0x0e: ql.arch.regs.ax = 0x0102 ql.os.clear_cf() elif al == 0x07: if (ql.arch.regs.bx == 1) and (ql.arch.regs.cx == 3): ql.log.info("Emulation Stop") ql.emu_stop() else: raise NotImplementedError()
def ql_syscall_futex(ql: Qiling, uaddr: int, op: int, val: int, timeout: int, uaddr2: int, val3: int): FUTEX_WAIT = 0 FUTEX_WAKE = 1 FUTEX_FD = 2 FUTEX_REQUEUE = 3 FUTEX_CMP_REQUEUE = 4 FUTEX_WAKE_OP = 5 FUTEX_LOCK_PI = 6 FUTEX_UNLOCK_PI = 7 FUTEX_TRYLOCK_PI = 8 FUTEX_WAIT_BITSET = 9 FUTEX_WAKE_BITSET = 10 FUTEX_WAIT_REQUEUE_PI = 11 FUTEX_CMP_REQUEUE_PI = 12 FUTEX_PRIVATE_FLAG = 128 if op & (FUTEX_PRIVATE_FLAG - 1) == FUTEX_WAIT: # def futex_wait_addr(ql, th, arg): # addr, val = arg # return ql.unpack32(ql.mem.read(addr, 4)) == val regreturn = ql.os.futexm.futex_wait(ql, uaddr, ql.os.thread_management.cur_thread, val) elif op & (FUTEX_PRIVATE_FLAG - 1) == FUTEX_WAIT_BITSET: regreturn = ql.os.futexm.futex_wait(ql, uaddr, ql.os.thread_management.cur_thread, val, val3) elif op & (FUTEX_PRIVATE_FLAG - 1) == FUTEX_WAKE: regreturn = ql.os.futexm.futex_wake(ql, uaddr, ql.os.thread_management.cur_thread, val) elif op & (FUTEX_PRIVATE_FLAG - 1) == FUTEX_WAKE_BITSET: regreturn = ql.os.futexm.futex_wake(ql, uaddr, ql.os.thread_management.cur_thread, val, val3) else: ql.log.debug(f'futex({uaddr:x}, {op:d}, {val:d}) = ?') ql.emu_stop() #ql.os.thread_management.cur_thread.stop() #ql.os.thread_management.cur_thread.stop_event = THREAD_EVENT_EXIT_GROUP_EVENT regreturn = 0 return regreturn
def ql_syscall_exit_group(ql: Qiling, code: int): if ql.os.child_processes == True: os._exit(0) if ql.multithread: def _sched_cb_exit(cur_thread): ql.log.debug(f"[Thread {cur_thread.get_id()}] Terminated") cur_thread.stop() cur_thread.exit_code = code td = ql.os.thread_management.cur_thread ql.emu_stop() td.sched_cb = _sched_cb_exit else: ql.os.exit_code = code ql.os.stop()
def __sleep_common(ql: Qiling, req: int, rem: int) -> int: n = ql.pointersize tv_sec = ql.unpack(ql.mem.read(req, n)) tv_sec += ql.unpack(ql.mem.read(req + n, n)) / 1000000000 if ql.os.thread_management: def _sched_sleep(cur_thread): gevent.sleep(tv_sec) ql.emu_stop() ql.os.thread_management.cur_thread.sched_cb = _sched_sleep # FIXME: this seems to be incomplete th = ql.os.thread_management.cur_thread else: time.sleep(tv_sec) return 0
def ql_syscall_vfork(ql: Qiling): if ql.host.os == QL_OS.WINDOWS: try: pid = Process() pid = 0 except: pid = -1 else: pid = os.fork() if pid == 0: ql.os.child_processes = True ql.log.debug("vfork(): is this a child process: %r" % (ql.os.child_processes)) regreturn = 0 else: regreturn = pid if ql.os.thread_management: ql.emu_stop() return regreturn
def __sleep_common(ql: Qiling, req: int, rem: int, force_timespec64: bool = False) -> int: tv_sec_size = 8 if force_timespec64 else ql.arch.pointersize tv_nsec_size = ql.arch.pointersize # struct timespec { # long tv_sec; # long tv_nsec; # }; # struct timespec64 { # time64_t tv_sec; # long tv_nsec; # }; tv_sec = ql.unpack64(ql.mem.read( req, tv_sec_size)) if force_timespec64 else ql.unpack( ql.mem.read(req, tv_sec_size)) tv_sec += ql.unpack(ql.mem.read(req + tv_sec_size, tv_nsec_size)) / 1000000000 if ql.os.thread_management: def _sched_sleep(cur_thread): gevent.sleep(tv_sec) ql.emu_stop() ql.os.thread_management.cur_thread.sched_cb = _sched_sleep # FIXME: this seems to be incomplete th = ql.os.thread_management.cur_thread else: time.sleep(tv_sec) return 0
def stop(ql: Qiling): ql.log.info("Ok for now") ql.emu_stop()
def stopatkillerswtich(ql: Qiling): print(f'killerswtch found') ql.emu_stop()
def ql_syscall_clone(ql: Qiling, flags: int, child_stack: int, parent_tidptr: int, newtls: int, child_tidptr: int): CSIGNAL = 0x000000ff CLONE_VM = 0x00000100 CLONE_FS = 0x00000200 CLONE_FILES = 0x00000400 CLONE_SIGHAND = 0x00000800 CLONE_PIDFD = 0x00001000 CLONE_PTRACE = 0x00002000 CLONE_VFORK = 0x00004000 CLONE_PARENT = 0x00008000 CLONE_THREAD = 0x00010000 CLONE_NEWNS = 0x00020000 CLONE_SYSVSEM = 0x00040000 CLONE_SETTLS = 0x00080000 CLONE_PARENT_SETTID = 0x00100000 CLONE_CHILD_CLEARTID = 0x00200000 CLONE_DETACHED = 0x00400000 CLONE_UNTRACED = 0x00800000 CLONE_CHILD_SETTID = 0x01000000 CLONE_NEWCGROUP = 0x02000000 CLONE_NEWUTS = 0x04000000 CLONE_NEWIPC = 0x08000000 CLONE_NEWUSER = 0x10000000 CLONE_NEWPID = 0x20000000 CLONE_NEWNET = 0x40000000 CLONE_IO = 0x80000000 # X8664 flags, child_stack, parent_tidptr, child_tidptr, newtls if ql.archtype== QL_ARCH.X8664: ori_newtls = child_tidptr child_tidptr = newtls newtls = ori_newtls f_th = ql.os.thread_management.cur_thread set_child_tid_addr = None # Shared virtual memory if not (flags & CLONE_VM): # FIXME: need a proper os.fork() for Windows if ql.platform == QL_OS.WINDOWS: try: pid = Process() pid = 0 except: pid = -1 else: pid = os.fork() if pid == 0: ql.os.child_processes = True f_th.update_global_thread_id() f_th.new_thread_id() if flags & CLONE_SETTLS == CLONE_SETTLS: f_th.set_thread_tls(newtls) if flags & CLONE_CHILD_CLEARTID == CLONE_CHILD_CLEARTID: f_th.set_clear_child_tid_addr(child_tidptr) if child_stack != 0: ql.arch.set_sp(child_stack) # ql.log.debug(f'clone(new_stack = {child_stack:#x}, flags = {flags:#x}, tls = {newtls:#x}, ptidptr = {parent_tidptr:#x}, ctidptr = {child_tidptr:#x}) = {regreturn:d}') ql.emu_stop() return pid if flags & CLONE_CHILD_SETTID == CLONE_CHILD_SETTID: set_child_tid_addr = child_tidptr th = ql.os.thread_class.spawn(ql, ql.reg.arch_pc + 2, ql.os.exit_point, set_child_tid_addr = set_child_tid_addr) th.path = f_th.path ql.log.debug(f'{str(th)} created') if flags & CLONE_PARENT_SETTID == CLONE_PARENT_SETTID: ql.mem.write(parent_tidptr, ql.pack32(th.id)) ctx = ql.save(reg=True, mem=False) # Whether to set a new tls if flags & CLONE_SETTLS == CLONE_SETTLS: ql.log.debug(f"new_tls={newtls:#x}") th.set_thread_tls(newtls) if flags & CLONE_CHILD_CLEARTID == CLONE_CHILD_CLEARTID: th.set_clear_child_tid_addr(child_tidptr) # Set the stack and return value of the new thread # (the return value of the child thread is 0, and the return value of the parent thread is the tid of the child thread) # and save the current context. regreturn = 0 ql.reg.arch_sp = child_stack # We have to find next pc manually for some archs since the pc is current instruction (like `syscall`). if ql.archtype in (QL_ARCH.X8664, ): ql.reg.arch_pc += list(ql.disassembler.disasm_lite(bytes(ql.mem.read(ql.reg.arch_pc, 4)), ql.reg.arch_pc))[0][1] ql.log.debug(f"Fix pc for child thread to {hex(ql.reg.arch_pc)}") ql.os.set_syscall_return(0) th.save() if th is None or f_th is None: raise Exception() ql.log.debug(f'Currently running pid is: {os.getpid():d}; tid is: {ql.os.thread_management.cur_thread.id:d}') # ql.log.debug(f'clone(new_stack = {child_stack:#x}, flags = {flags:#x}, tls = {newtls:#x}, ptidptr = {parent_tidptr:#x}, ctidptr = {child_tidptr:#x}) = {regreturn:d}') # Restore the stack and return value of the parent process ql.restore(ctx) regreturn = th.id # Break the parent process and enter the add new thread event ql.emu_stop() f_th.stop_event = THREAD_EVENT_CREATE_THREAD f_th.stop_return_val = th ql.log.debug(f'Currently running pid is: {os.getpid():d}; tid is: {ql.os.thread_management.cur_thread.id:d}') # ql.log.debug(f'clone(new_stack = {child_stack:#x}, flags = {flags:#x}, tls = {newtls:#x}, ptidptr = {parent_tidptr:#x}, ctidptr = {child_tidptr:#x}) = {regreturn:d}') return regreturn
def hook_ResetSystem(ql: Qiling, address: int, params): ql.emu_stop() return EFI_SUCCESS
def hook_third_stop_address(ql: Qiling, stops: List[bool]): ql.log.info( f' >>>> Third stop address: {ql.arch.regs.arch_pc:#010x}') stops[2] = True ql.emu_stop()
def hook_ExitProcess(ql: Qiling, address: int, params): ql.emu_stop() ql.os.PE_RUN = False
def stop(ql: Qiling, addr, data): ql.emu_stop()
def __leaf_4c(ql: Qiling): ql.log.info("Program terminated gracefully") ql.emu_stop()
def hook_FatalExit(ql: Qiling, address: int, params): ql.emu_stop() ql.os.PE_RUN = False
def hook_first_stop_address(ql: Qiling, stops: List[bool]): ql.log.info( f' >>>> First stop address: {ql.arch.regs.arch_pc:#010x}') stops[0] = True ql.emu_stop()