Ejemplo n.º 1
0
 def on_spawn_added(self, spawn: "_frida.Spawn"):
     """
     spaw进程添加回调,默认resume所有spawn进程
     :param spawn: spawn进程信息
     """
     logger.debug(f"Spawn added: {spawn}", tag="[✔]")
     self.device.resume(spawn.pid)
Ejemplo n.º 2
0
    def _load_script(self, pid: int, resume: bool = False):
        logger.debug(f"Attempt to load script: pid={pid}, resume={resume}",
                     tag="[✔]")

        session = self._attach_session(pid)
        self._unload_script(session)

        # read the internal script as an entrance
        entry_code = self._internal_debug_script.source \
            if self._debug \
            else self._internal_script.source
        script = FridaScript(session, entry_code)

        script.on(
            "message", lambda message, data: self.on_script_message(
                script, message, data))
        script.on("destroyed", lambda: self.on_script_destroyed(script))

        session.script = script

        try:
            script.load()
            script.exports.load_scripts(self._load_script_files(),
                                        self._user_parameters)
        finally:
            if resume:
                self.device.resume(pid)

        self._reactor.schedule(lambda: self.on_script_loaded(script))
Ejemplo n.º 3
0
 def on_child_added(self, child: "_frida.Child"):
     """
     子进程添加回调,默认resume所有子进程
     :param child: 子进程信息
     """
     logger.debug(f"Child added: {child}", tag="[✔]")
     self.device.resume(child.pid)
Ejemplo n.º 4
0
    def _load(self):

        with FileLock(self._path + ".share.lock"):  # 文件锁,避免多进程同时操作

            if not self._cached or not os.path.exists(self._path):
                if os.path.exists(self._path):
                    logger.debug(f"Remove shared script cache: {self._path}",
                                 tag="[*]")
                    os.remove(self._path)
                logger.info(f"Download shared script: {self._url}", tag="[*]")
                utils.download(self._url, self._path)

            with open(self._path, "rb") as f:
                source = f.read().decode("utf-8")

            if self._trusted:
                logger.info(f"Load trusted shared script: {self._path}",
                            tag="[✔]")
                return source

            cached_md5 = ""
            cached_md5_path = self._path + ".md5"
            if os.path.exists(cached_md5_path):
                with open(cached_md5_path, "rt") as fd:
                    cached_md5 = fd.read()

            source_md5 = utils.get_md5(source)
            if cached_md5 == source_md5:
                logger.info(f"Load trusted shared script: {self._path}",
                            tag="[✔]")
                return source

            line_count = 20
            source_lines = source.splitlines(keepends=True)
            source_summary = "".join(source_lines[:line_count])
            if len(source_lines) > line_count:
                source_summary += "... ..."

            logger.warning(
                f"This is the first time you're running this particular snippet, "
                f"or the snippet's source code has changed.{os.linesep}"
                f"Url: {self._url}{os.linesep}"
                f"Original md5: {cached_md5}{os.linesep}"
                f"Current md5: {source_md5}{os.linesep}{os.linesep}",
                f"{source_summary}",
                tag="[!]")
            while True:
                response = input(
                    ">>> Are you sure you'd like to trust it? [y/N]: ")
                if response.lower() in ('n', 'no') or response == '':
                    logger.info(
                        f"Ignore untrusted shared script: {self._path}",
                        tag="[✔]")
                    return None
                if response.lower() in ('y', 'yes'):
                    with open(cached_md5_path, "wt") as fd:
                        fd.write(source_md5)
                    logger.info(f"Load trusted shared script: {self._path}",
                                tag="[✔]")
                    return source
Ejemplo n.º 5
0
 def on_script_destroyed(self, script: FridaScript):
     """
     脚本结束回调函数,默认只打印log
     :param script: frida的脚本
     """
     logger.debug(
         f"Script destroyed: {script.session.process_name} ({script.session.pid})",
         tag="[✔]")
Ejemplo n.º 6
0
 def on_script_loaded(self, script: FridaScript):
     """
     脚本加载回调,默认只打印log
     :param script: frida的脚本
     """
     logger.debug(
         f"Script loaded: {script.session.process_name} ({script.session.pid})",
         tag="[✔]")
Ejemplo n.º 7
0
 def on_file_change(self, file: FridaScriptFile):
     """
     脚本文件改变回调,默认重新加载脚本
     :param file: 脚本文件路径
     """
     logger.debug(f"File changed", tag="[✔]")
     for session in self.sessions.values():
         self.load_script(session.pid)
Ejemplo n.º 8
0
 def monitor_file(file):
     logger.debug(f"Monitor file: {file.path}", tag="[✔]")
     monitor = frida.FileMonitor(file.path)
     monitor.on(
         "change",
         lambda changed_file, other_file, event_type: on_change(
             event_type, file))
     monitor.enable()
     return monitor
Ejemplo n.º 9
0
 def on_script_send(self, script: FridaScript, type: str, message: object,
                    data: object):
     """
     脚本调用send是收到的回调,例send({trace: "xxx"}, null)
     :param script: frida的脚本
     :param type: 上述例子的"trace"
     :param message: json/字符串消息,上述例子的"xxx"
     :param data: 上述例子的null
     """
     logger.debug(f"Script send, type={type}, message={message}", tag="[*]")
Ejemplo n.º 10
0
 def on_change(event_type, changed_file):
     if event_type == "changes-done-hint":
         logger.debug(
             f"Monitor event: {event_type}, file: {changed_file}",
             tag="[✔]")
         self._last_change_id += 1
         change_id = self._last_change_id
         changed_file.clear()
         self._reactor.schedule(
             lambda: on_change_schedule(change_id, changed_file),
             delay=0.5)
Ejemplo n.º 11
0
    def _init(self):
        logger.debug(f"FridaApplication init", tag="[✔]")

        self._finished.clear()
        self._monitor_all()

        self.device.on("spawn-added", self._cb_spawn_added)
        self.device.on("spawn-removed", self._cb_spawn_removed)
        self.device.on("child-added", self._cb_child_added)
        self.device.on("child-removed", self._cb_child_removed)
        self.device.on("output", self._cb_output)
        # self.device.on('process-crashed', self._cb_process_crashed)
        # self.device.on('uninjected', self._cb_uninjected)
        self.device.on("lost", self._cb_lost)

        if self._enable_spawn_gating:
            self.device.enable_spawn_gating()
Ejemplo n.º 12
0
    def _deinit(self):
        logger.debug(f"FridaApplication deinit", tag="[✔]")

        utils.ignore_error(self.device.off, "spawn-added",
                           self._cb_spawn_added)
        utils.ignore_error(self.device.off, "spawn-removed",
                           self._cb_spawn_removed)
        utils.ignore_error(self.device.off, "child-added",
                           self._cb_child_added)
        utils.ignore_error(self.device.off, "child-removed",
                           self._cb_child_removed)
        utils.ignore_error(self.device.off, "output", self._cb_output)
        # utils.ignore_error(self.device.off, "process-crashed", self._cb_process_crashed)
        # utils.ignore_error(self.device.off, "uninjected", self._cb_uninjected)
        utils.ignore_error(self.device.off, "lost", self._cb_lost)

        with frida.Cancellable():
            self._demonitor_all()

        self._finished.set()
Ejemplo n.º 13
0
    def _attach_session(self, pid: int):
        with self._lock:
            session = self._sessions.get(pid)
            if session is not None:
                if not session.is_detached:
                    return session
                self._sessions.pop(pid)

        logger.debug(f"Attempt to attach process: pid={pid}", tag="[✔]")

        target_process = None
        for process in self.enumerate_processes():
            if process.pid == pid:
                target_process = process
        if target_process is None:
            raise frida.ProcessNotFoundError(
                f"unable to find process with pid '{pid}'")

        session = FridaSession(self.device.attach(target_process.pid))
        session.pid = target_process.pid
        session.process_name = target_process.name

        if self._enable_child_gating:
            logger.debug(f"Enable child gating: {pid}", tag="[✔]")
            session.enable_child_gating()

        def on_session_detached(reason, crash):
            with self._lock:
                self._sessions.pop(pid, None)
            self._reactor.schedule(
                lambda: self.on_session_detached(session, reason, crash))

        session.on("detached", on_session_detached)
        with self._lock:
            self._sessions[target_process.pid] = session
        self._reactor.schedule(lambda: self.on_session_attached(session))

        return session
Ejemplo n.º 14
0
 def on_child_removed(self, child: "_frida.Child"):
     """
     子进程移除回调,默认只打印log
     :param child: 子进程信息
     """
     logger.debug(f"Child removed: {child}", tag="[✔]")
Ejemplo n.º 15
0
 def on_spawn_removed(self, spawn: "_frida.Spawn"):
     """
     spaw进程移除回调,默认只打印log
     :param spawn: spawn进程信息
     """
     logger.debug(f"Spawn removed: {spawn}", tag="[✔]")
Ejemplo n.º 16
0
 def on_output(self, pid: int, fd, data):
     logger.debug(f"Output: pid={pid}, fd={fd}, data={data}", tag="[✔]")
Ejemplo n.º 17
0
 def on_spawn_added(self, spawn):
     logger.debug(f"Spawn added: {spawn}", tag="[✔]")
     if device.extract_package(spawn.identifier) == package:
         self.load_script(spawn.pid, resume=True)
     else:
         self.resume(spawn.pid)
Ejemplo n.º 18
0
 def _eternalize_script(self, session: FridaSession):
     if session is not None and session.script is not None:
         logger.debug(f"Eternalize script: pid={session.pid}", tag="[✔]")
         utils.ignore_error(session.script.eternalize)
         session.script = None
Ejemplo n.º 19
0
 def _unload_script(self, session: FridaSession):
     if session is not None and session.script is not None:
         logger.debug(f"Unload script: pid={session.pid}", tag="[✔]")
         utils.ignore_error(session.script.unload)
         session.script = None
Ejemplo n.º 20
0
 def _detach_session(self, session: FridaSession):
     if session is not None:
         logger.debug(f"Detach process: pid={session.pid}", tag="[✔]")
         utils.ignore_error(session.detach)
Ejemplo n.º 21
0
 def on_stop(self):
     logger.debug("Application stopped", tag="[✔]")
Ejemplo n.º 22
0
 def on_spawn_added(self, spawn):
     logger.debug(f"Spawn added: {spawn}", tag="[✔]")
     if spawn.identifier == bundle_id:
         self.load_script(spawn.pid, resume=True)
     else:
         self.resume(spawn.pid)