Пример #1
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
Пример #2
0
 def on_session_detached(self, session, reason, crash) -> None:
     logger.info(
         f"Detach process: {session.process_name} ({session.pid}), reason={reason}",
         tag="[*]")
     if reason in ("connection-terminated", "device-lost"):
         self.stop()
     elif len(self._sessions) == 0:
         app.load_script(app.device.spawn(package), resume=True)
Пример #3
0
 def on_session_attached(self, session: FridaSession):
     """
     会话建立连接回调函数,默认只打印log
     :param session: 附加的会话
     """
     logger.info(
         f"Session attached: {session.process_name} ({session.pid})",
         tag="[*]")
Пример #4
0
 def prepare(self):
     if not os.path.exists(self.local_path):
         logger.info("Download frida server ...", tag="[*]")
         utils.download(self._download_url, self._temp_path)
         with lzma.open(self._temp_path,
                        "rb") as read, open(self.local_path,
                                            "wb") as write:
             shutil.copyfileobj(read, write)
         os.remove(self._temp_path)
Пример #5
0
 def on_session_detached(self, session: FridaSession, reason: str,
                         crash: "_frida.Crash"):
     """
     会话结束回调函数,默认只打印log
     :param session: 结束的会话
     :param reason: 结束原因
     :param crash: crash信息
     """
     logger.info(
         f"Session detached: {session.process_name} ({session.pid}), reason={reason}",
         tag="[*]")
Пример #6
0
 def on_script_event(self, script: FridaScript, message: object,
                     data: object):
     """
     脚本发送事件回调
     :param script: frida的脚本
     :param message: 事件消息
     :param data: 事件数据
     """
     logger.info(
         f"Script event: {json.dumps(message, indent=2, ensure_ascii=False)}",
         tag="[*]")
Пример #7
0
 def stop(self) -> bool:
     """
     强制结束frida server
     :return: 结束成功为True,否则为False
     """
     logger.info("Kill frida server ...", tag="[*]")
     try:
         self._stop()
         return True
     except frida.ServerNotRunningError:
         return True
     except:
         return False
Пример #8
0
 def _prepare(self):
     if not self._device.is_file_exist(self._environ.remote_path):
         self._environ.prepare()
         logger.info(f"Push frida server to {self._environ.remote_path}",
                     tag="[*]")
         temp_path = self._device.get_storage_path(
             "frida", self._environ.remote_name)
         self._device.push(self._environ.local_path,
                           temp_path,
                           capture_output=False)
         self._device.sudo("mv",
                           temp_path,
                           self._environ.remote_path,
                           capture_output=False)
         self._device.sudo("chmod", "755", self._environ.remote_path)
Пример #9
0
    def start(self) -> bool:
        """
        根据frida版本和设备abi类型下载并运行server
        :return: 运行成功为True,否则为False
        """
        if self.is_running:
            logger.info("Frida server is running ...", tag="[*]")
            return True

        logger.info("Start frida server ...", tag="[*]")
        self._start()
        for i in range(10):
            time.sleep(0.5)
            if self.is_running:
                logger.info("Frida server is running ...", tag="[*]")
                return True

        raise frida.ServerNotRunningError("Frida server failed to run ...")
Пример #10
0
    def on_script_message(self, script: FridaScript, message: object,
                          data: object):
        """
        脚本消息回调函数,默认按照格式打印
        :param script: frida的脚本
        :param message: frida server发送的数据
        :param data: frida server发送的data
        """
        if utils.get_item(message, "type") == "send":

            payload = utils.get_item(message, "payload")
            if payload is not None and isinstance(payload, dict):

                # log单独解析
                log = payload.pop("log", None)
                if log is not None:
                    self.on_script_log(script, log)

                # event单独解析
                event = payload.pop("event", None)
                if event is not None:
                    self.on_script_event(script, event, data)

                # 解析完log,解析其他的
                while len(payload) > 0:
                    key, value = payload.popitem()
                    self.on_script_send(script, key, value, data)

            # 字符串类型,直接输出
            if not utils.is_empty(payload):
                logger.info(payload, tag="[*]")

        elif utils.get_item(message, "type") == "error" and utils.is_contain(
                message, "stack"):
            logger.info(utils.get_item(message, "stack"),
                        tag="[!]",
                        fore=Fore.RED)

        else:
            logger.info(message, tag="[?]", fore=Fore.RED)
Пример #11
0
 def _load(self) -> Optional[str]:
     with open(self._path, "rb") as f:
         logger.info(f"Load script: {self._path}", tag="[✔]")
         return f.read().decode("utf-8")
Пример #12
0
 def on_device_lost(self):
     logger.info("Device lost", tag="[!]")
     self.stop()