def __get_syscall_mapper(self, archtype: QL_ARCH): qlos_path = f'.os.{self.type.name.lower()}.map_syscall' qlos_func = 'get_syscall_mapper' func = ql_get_module_function(qlos_path, qlos_func) return func(archtype)
def ql_debugger(ql, remotedebugsrv, ip=None, port=None): path = ql.path try: if ip is None: ip = '127.0.0.1' if port is None: port = 9999 port = int(port) sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((ip, port)) ql.nprint("\ndebugger> Initializing loadbase 0x%x\n" % (ql.loader.loadbase)) ql.nprint("debugger> Listening on %s:%u\n" % (ip, port)) sock.listen(1) conn, addr = sock.accept() except: ql.nprint("debugger> Error: Address already in use\n") raise try: mappings = [(hex(ql.loader.entry_point), 0x10)] exit_point = ql.loader.entry_point + os.path.getsize(path) remotedebugsrv = debugger_convert_str(remotedebugsrv) remotedebugsrv = str(remotedebugsrv) + "server" DEBUGSESSION = str.upper(remotedebugsrv) + "session" DEBUGSESSION = ql_get_module_function("qiling.debugger." + remotedebugsrv + "." + remotedebugsrv, DEBUGSESSION) ql.remotedebugsession = DEBUGSESSION(ql, conn, exit_point, mappings) except: ql.nprint("debugger> Error: Not able to initialize Debugging Server\n") raise
def ql_debugger(ql, remotedebugsrv, ip=None, port=None): path = ql.path if ip is None: ip = '127.0.0.1' if port is None: port = 9999 port = int(port) if ql.shellcoder: load_address = ql.os.entry_point exit_point = load_address + len(ql.shellcoder) else: load_address = ql.loader.load_address exit_point = load_address + os.path.getsize(path) mappings = [(hex(load_address))] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind((ip, port)) ql.nprint("debugger> Initializing load_address 0x%x" % (load_address)) ql.nprint("debugger> Listening on %s:%u" % (ip, port)) sock.listen(1) conn, addr = sock.accept() remotedebugsrv = debugger_convert_str(remotedebugsrv) remotedebugsrv = str(remotedebugsrv) + "server" DEBUGSESSION = str.upper(remotedebugsrv) + "session" DEBUGSESSION = ql_get_module_function("qiling.debugger." + remotedebugsrv + "." + remotedebugsrv, DEBUGSESSION) ql.remote_debug = DEBUGSESSION(ql, conn, exit_point, mappings)
def create(self, label: str, struct: "QlPeripheral" = None, base: int = None) -> "QlPeripheral": """ Create the peripheral accroding the label and envs. struct: Structure of the peripheral. Use defualt ql structure if not provide. base: Base address. Use defualt address if not provide. """ env_struct, env_base, kwargs = self.load_env(label.upper()) struct = env_struct if struct is None else struct base = env_base if base is None else base try: entity = ql_get_module_function('qiling.hw', struct)(self.ql, label, **kwargs) setattr(self, label, entity) self.entity[label] = entity self.region[label] = [(lbound + base, rbound + base) for (lbound, rbound) in entity.region] return entity except QlErrorModuleFunctionNotFound: self.ql.log.warning( f'The {struct}({label}) has not been implemented')
def _msg_sendv(ql: Qiling, coid, smsg, sparts, rmsg, rparts, *args, **kw): assert coid in ql.os.connections, "Connection Id must exist in connections mapping" conn = ql.os.connections[coid] if conn.pid == SYSMGR_PID and conn.chid == SYSMGR_CHID: sbody = get_message_body(ql, smsg, sparts) type_ = ql.unpack16(sbody[:2]) msg_name = map_msgtype(ql, type_) _msg_handler = ql_get_module_function(f"qiling.os.qnx", "message") if msg_name in dir(_msg_handler): msg_hook = eval(msg_name) msg_name = msg_hook.__name__ else: msg_hook = None msg_name = None if msg_hook: ret = msg_hook(ql, coid, smsg, sparts, rmsg, rparts, *args, **kw) else: ql.log.warning( f'_msg_sendv: no hook for message type {type_:#04x}') ret = -1 else: ql.log.warn( f'syscall_msg_sendv(coid = {coid}): unhandled message for pid = {conn.pid}, chid = {conn.chid}' ) ret = -1 return ret
def _msg_sendv(ql, coid, smsg, sparts, rmsg, rparts, *args, **kw): sbody = get_message_body(ql, smsg, sparts) type_ = ql.unpack16(sbody[:2]) msg_name = map_msgtype(ql, type_) _msg_handler = ql_get_module_function(f"qiling.os.qnx", "message") if msg_name in dir(_msg_handler): msg_hook = eval(msg_name) msg_name = msg_hook.__name__ else: msg_hook = None msg_name = None if msg_hook: ret = msg_hook(ql, coid, smsg, sparts, rmsg, rparts, *args, **kw) else: ql.log.warning(f'_msg_sendv: no hook for message type {type_:#04x}') ret = -1 return ret
def load_syscall(self): # import syscall mapping function map_syscall = ql_syscall_mapping_function(self.ql.ostype) syscall = self.syscall syscall_name = map_syscall(self.ql, syscall) # get syscall on-enter hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.ENTER] onenter_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall) # get syscall on-exit hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.EXIT] onexit_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall) # get syscall replacement hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.CALL] syscall_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall) if syscall_hook: syscall_name = syscall_hook.__name__ else: _ostype_str = ostype_convert_str(self.ql.ostype) _posix_syscall = ql_get_module_function(f"qiling.os.posix", "syscall") _os_syscall = ql_get_module_function( f"qiling.os.{_ostype_str.lower()}", "syscall") if syscall_name in dir(_posix_syscall) or syscall_name in dir( _os_syscall): syscall_hook = eval(syscall_name) syscall_name = syscall_hook.__name__ else: syscall_hook = None if syscall_hook: args = self.get_syscall_args() self.utils.syscalls.setdefault(syscall_name, []).append({ "params": { "param0": args[0], "param1": args[1], "param2": args[2], "param3": args[3], "param4": args[4], "param5": args[5] }, "result": None, "address": self.ql.reg.arch_pc, "return_address": None, "position": self.utils.syscalls_counter }) self.utils.syscalls_counter += 1 try: if onenter_hook is not None: onenter_hook(self.ql, *self.get_syscall_args()) syscall_basename = syscall_hook.__name__[len(SYSCALL_PREF):] args = [] # ignore first arg, which is 'ql' arg_names = tuple( signature(syscall_hook).parameters.values())[1:] arg_values = self.get_syscall_args() for name, value in zip(arg_names, arg_values): name = str(name) # ignore python special args if name in ('*args', '**kw', '**kwargs'): continue # cut the first part of the arg if it is of form fstatat64_fd if name.startswith(f'{syscall_basename}_'): name = name.partition('_')[-1] args.append(f'{name} = {value:#x}') faddr = f'{self.ql.reg.arch_pc:#0{self.ql.archbit // 4 + 2}x}: ' if self.ql.verbose >= QL_VERBOSE.DEBUG else '' fargs = ', '.join(args) log = f'{faddr}{syscall_basename}({fargs})' if self.ql.verbose >= QL_VERBOSE.DEBUG: self.ql.log.debug(log) else: self.ql.log.info(log) ret = syscall_hook(self.ql, *arg_values) if ret is not None and type(ret) is int: # each name has a list of calls, we want the last one and we want to update the return value self.utils.syscalls[syscall_name][-1]["result"] = ret ret = self.set_syscall_return(ret) self.ql.log.debug( f'{syscall_basename}() = {QlOsPosix.getNameFromErrorCode(ret)}' ) if onexit_hook is not None: onexit_hook(self.ql, *self.get_syscall_args()) except KeyboardInterrupt: raise except Exception as e: self.ql.log.exception("") self.ql.log.info(f'Syscall ERROR: {syscall_name} DEBUG: {e}') raise e else: self.ql.log.warning( f'{self.ql.reg.arch_pc:#x}: syscall {syscall_name} number = {syscall:#x}({syscall:d}) not implemented' ) if self.ql.debug_stop: raise QlErrorSyscallNotFound("Syscall Not Found")
def load_syscall(self): # import syscall mapping function map_syscall = ql_syscall_mapping_function(self.ql.ostype) syscall_id = self.syscall syscall_name = map_syscall(self.ql, syscall_id) # get syscall on-enter hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.ENTER] onenter_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall_id) # get syscall on-exit hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.EXIT] onexit_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall_id) # get syscall replacement hook (if any) hooks_dict = self.posix_syscall_hooks[QL_INTERCEPT.CALL] syscall_hook = hooks_dict.get(syscall_name) or hooks_dict.get(syscall_id) if not syscall_hook: osname = ostype_convert_str(self.ql.ostype) os_syscalls = ql_get_module_function(f"qiling.os.{osname.lower()}", "syscall") posix_syscalls = ql_get_module_function(f"qiling.os.posix", "syscall") # look in os-specific and posix syscall hooks if syscall_name: self.ql.log.debug("syscall hooked 0x%x: %s()" % (self.ql.reg.arch_pc, syscall_name)) syscall_hook = getattr(os_syscalls, syscall_name, None) or getattr(posix_syscalls, syscall_name, None) if syscall_hook: syscall_name = syscall_hook.__name__ # extract the parameters list from hook signature param_names = tuple(signature(syscall_hook).parameters.values()) # skip first arg (always 'ql') and filter out python special args (*args and **kwargs) param_names = [info.name for info in param_names[1:] if info.kind == Parameter.POSITIONAL_OR_KEYWORD] # read parameter values params = [self.__syscall_cc.getRawParam(i) for i in range(len(param_names))] try: # if set, fire up the on-enter hook and let it override original args set if onenter_hook: overrides = onenter_hook(self.ql, *params) if overrides is not None: _, params = overrides # perform syscall retval = syscall_hook(self.ql, *params) # if set, fire up the on-exit hook and let it override the return value if onexit_hook: override = onexit_hook(self.ql, *params, retval) if override is not None: retval = override # set return value if retval is not None: self.__syscall_cc.setReturnValue(retval) except KeyboardInterrupt: raise except Exception as e: self.ql.log.exception(f'Syscall ERROR: {syscall_name} DEBUG: {e}') raise e # print out log entry syscall_basename = syscall_name[len(SYSCALL_PREF) if syscall_name.startswith(SYSCALL_PREF) else 0:] args = [] for name, value in zip(param_names, params): # cut the first part of the arg if it is of form fstatat64_fd if name.startswith(f'{syscall_basename}_'): name = name.partition('_')[-1] args.append((name, f'{value:#x}')) sret = QlOsPosix.getNameFromErrorCode(retval) self.utils.print_function(self.ql.reg.arch_pc, syscall_basename, args, sret, False) # record syscall statistics self.utils.syscalls.setdefault(syscall_name, []).append({ "params": dict(zip(param_names, params)), "result": retval, "address": self.ql.reg.arch_pc, "return_address": None, "position": self.utils.syscalls_counter }) self.utils.syscalls_counter += 1 else: self.ql.log.warning(f'{self.ql.reg.arch_pc:#x}: syscall {syscall_name} number = {syscall_id:#x}({syscall_id:d}) not implemented') if self.ql.debug_stop: raise QlErrorSyscallNotFound(f'Syscall not found: {syscall_name}')