예제 #1
0
    def set_device(self):
        """
            Set's the target device to work with.

            :return:
        """

        if self.config.device_id is not None:
            self.device = frida.get_device(self.config.device_id)

        elif (self.config.host is not None) or (self.config.device_type
                                                == 'remote'):
            if self.config.host is None:
                self.device = frida.get_remote_device()
            else:
                host = self.config.host
                port = self.config.port
                self.device = frida.get_device_manager() \
                    .add_remote_device(f'{host}:{port}' if host is not None else f'127.0.0.1:{port}')

        elif self.config.device_type is not None:
            for dev in frida.enumerate_devices():
                if dev.type == self.config.device_type:
                    self.device = dev
        else:
            self.device = frida.get_local_device()

        # surely we have a device by now?
        if self.device is None:
            raise Exception('Unable to find a device')

        self.device.on('output', self.handlers.device_output)
        self.device.on('lost', self.handlers.device_lost)

        debug_print(f'device determined as: {self.device}')
예제 #2
0
파일: plugin.py 프로젝트: ylkcy/objection
    def _prepare_source(self):
        """
            Prepares the self.script_src attribute based on a few rules.

            If the script source is already set, simply return as there is
                nothing for us to do.
            If the script path is set, read that and populate the script_src
                attribute.
            If neither script_src not script_path is set, attempt to read the
                index.js that lives next to the plugin file.

            If all of the above fail, simply return, writing a debug warning
                no script source could be found.

            :return:
        """

        if self.script_src:
            return

        if self.script_path:
            self.script_path = os.path.abspath(self.script_path)
            with open(self.script_path, 'r', encoding='utf-8') as f:
                self.script_src = '\n'.join(f.readlines())
            return

        possible_src = os.path.abspath(os.path.join(
            os.path.abspath(os.path.dirname(self.plugin_file)), 'index.js'))
        if os.path.exists(possible_src):
            self.script_path = possible_src
            with open(self.script_path, 'r', encoding='utf-8') as f:
                self.script_src = '\n'.join(f.readlines())
            return

        debug_print('[warning] No Fridascript could be found for plugin {0}'.format(self.namespace))
예제 #3
0
    def __init__(self, config: AgentConfig):
        """ initialises the agent class """

        self.agent_path = Path(__file__).parent.parent / 'agent.js'
        if not self.agent_path.exists():
            raise Exception(
                f'Unable to locate Objection agent sources at: {self.agent_path}. '
                'If this is a development install, check the wiki for more '
                'information on building the agent.')
        debug_print('Agent path is: {path}'.format(path=self.agent_path))

        self.config = config
        debug_print(f'agent config: {self.config}')
        self.handlers = OutputHandlers()

        atexit.register(self.teardown)
예제 #4
0
    def set_target_pid(self):
        """
            Set's the PID we should attach to. This method will spawn the
            target if needed. The resumed value is also toggled here.

            Defaults:
                resumed: bool = True

            :return:
        """

        if (self.config.name is None) and (not self.config.foremost):
            raise Exception('Need a target name to spawn/attach to')

        if self.config.foremost:
            try:
                app = self.device.get_frontmost_application()
            except Exception as e:
                raise Exception(
                    f'Could not get foremost application on {self.device.name}: {e}'
                )

            if app is None:
                raise Exception(
                    f'No foremost application on {self.device.name}')

            self.pid = app.pid
            # update the global state for the prompt etc.
            state_connection.name = app.identifier

        elif self.config.spawn:
            self.pid = self.device.spawn(self.config.name)
            self.resumed = False
        else:
            # check if the name is actually an integer. this way we can
            # assume we got the target PID already
            try:
                self.pid = int(self.config.name)
            except ValueError:
                pass

            if self.pid is None:
                # last resort, maybe we have a process name
                self.pid = self.device.get_process(self.config.name).pid

        debug_print(f'process PID determined as {self.pid}')
예제 #5
0
    def run(self):
        """
            Run the Agent by getting a device, setting the target pid and attaching.
            If we should skip pausing, also resume the process.

            :return:
        """

        self.set_device()
        self.set_target_pid()
        self.attach()

        # internal state
        self.update_device_state()

        if not self.config.pause:
            debug_print('asked to run without pausing, so resuming in run()')
            self.resume()
예제 #6
0
def start(plugin_folder: str, quiet: bool, startup_command: str, file_commands,
          startup_script: click.File, enable_api: bool) -> None:
    """
        Start a new session
    """

    agent = get_agent()
    state_connection.set_agent(agent)

    # load plugins
    if plugin_folder:
        folder = Path(plugin_folder).resolve()
        debug_print(f'[plugin] Plugins path is: {folder}')
        for p in folder.iterdir():
            if p.is_file() or p.name.startswith('.'):
                debug_print(f'[plugin] Skipping {p.name}')
                continue

            debug_print(f'[plugin] Attempting to load plugin at {p}')
            load_plugin([p])

    repl = Repl()

    if startup_script:
        click.secho(
            f'Importing and running startup script at: {startup_script}',
            dim=True)
        agent.attach_script(startup_script.read())

    if startup_command:
        for command in startup_command:
            click.secho(f'Running a startup command... {command}', dim=True)
            repl.run_command(command)

    if file_commands:
        click.secho('Running commands from file...', bold=True)
        for command in file_commands.readlines():

            command = command.strip()
            if command == '':
                continue

            # run the command using the instantiated repl
            click.secho(f'Running: \'{command}\':\n', dim=True)
            repl.run_command(command)

    warn_about_older_operating_systems()

    # start the api server
    if enable_api:

        def api_thread():
            """ Small method to run Flask non-blocking """
            api_state.start(app_state.api_host, app_state.api_port)

        click.secho(
            f'Starting API server on {app_state.api_host}:{app_state.api_port}',
            fg='yellow',
            bold=True)
        thread = threading.Thread(target=api_thread)
        thread.daemon = True
        thread.start()

        time.sleep(2)

    # drop into the repl
    repl.run(quiet=quiet)