Beispiel #1
0
    def run(self):
        mgr = frida.get_device_manager()

        on_devices_changed = lambda: self._reactor.schedule(self._try_start)
        mgr.on('changed', on_devices_changed)

        self._reactor.schedule(self._try_start)
        self._reactor.schedule(self._show_message_if_no_device, delay=1)

        signal.signal(signal.SIGTERM, self._on_sigterm)

        self._reactor.run()

        if self._started:
            try:
                self._perform_on_background_thread(self._stop)
            except frida.OperationCancelledError:
                pass

        if self._session is not None:
            self._session.off('detached', self._schedule_on_session_detached)
            try:
                self._perform_on_background_thread(self._session.detach)
            except frida.OperationCancelledError:
                pass
            self._session = None

        if self._device is not None:
            self._device.off('output', self._schedule_on_output)
            self._device.off('lost', self._schedule_on_device_lost)

        mgr.off('changed', on_devices_changed)

        frida.shutdown()
        sys.exit(self._exit_status)
Beispiel #2
0
    def run(self):
        mgr = frida.get_device_manager()

        on_devices_changed = lambda: self._reactor.schedule(self._try_start)
        mgr.on('changed', on_devices_changed)

        self._reactor.schedule(self._try_start)
        self._reactor.schedule(self._show_message_if_no_device, delay=1)

        old_sigterm_handler = signal.signal(signal.SIGTERM, lambda n, f: self._exit(0))

        self._reactor.run()

        signal.signal(signal.SIGTERM, old_sigterm_handler)

        if self._started:
            self._stop()

        if self._session is not None:
            self._session.off('detached', self._schedule_on_session_detached)
            self._session.detach()
            self._session = None

        if self._device is not None:
            self._device.off('output', self._schedule_on_output)
            self._device.off('lost', self._schedule_on_device_lost)

        mgr.off('changed', on_devices_changed)

        frida.shutdown()
        sys.exit(self._exit_status)
Beispiel #3
0
 def run(self):
     while len(self._procstack) > 0:
         name = self._procstack.pop()
         print("[*] Attaching to: " + name)
         pid = frida.spawn([name])
         session = frida.attach(pid)
         session.on('detached', self.on_detached)
         script = session.create_script(code)
         script.on('message', lambda m, d: self.on_message(m, d))
         script.load()
         frida.resume(pid)
         with self._lock:
             self._cond.wait()
     frida.shutdown()
Beispiel #4
0
 def run(self):
     mgr = frida.get_device_manager()
     on_devices_changed = lambda: self._reactor.schedule(self._try_start)
     mgr.on('changed', on_devices_changed)
     self._reactor.schedule(self._try_start)
     self._reactor.schedule(self._show_message_if_no_device, delay=0.1)
     self._reactor.run()
     if self._started:
         self._stop()
     if self._process is not None:
         self._process.off('detached', self._schedule_on_process_detached)
         self._process.detach()
         self._process = None
     if self._device is not None:
         self._device.off('lost', self._schedule_on_device_lost)
     mgr.off('changed', on_devices_changed)
     frida.shutdown()
     sys.exit(self._exit_status)
 def run(self):
     mgr = frida.get_device_manager()
     on_devices_changed = lambda: self._reactor.schedule(self._try_start)
     mgr.on('changed', on_devices_changed)
     self._reactor.schedule(self._try_start)
     self._reactor.schedule(self._show_message_if_no_device, delay=0.1)
     self._reactor.run()
     if self._started:
         self._stop()
     if self._process is not None:
         self._process.off('detached', self._schedule_on_process_detached)
         self._process.detach()
         self._process = None
     if self._device is not None:
         self._device.off('lost', self._schedule_on_device_lost)
     mgr.off('changed', on_devices_changed)
     frida.shutdown()
     sys.exit(self._exit_status)
Beispiel #6
0
 def run(self):
     mgr = frida.get_device_manager()
     on_devices_changed = lambda: self._reactor.schedule(self._try_start)
     mgr.on('changed', on_devices_changed)
     self._reactor.schedule(self._try_start)
     self._reactor.schedule(self._show_message_if_no_device, delay=0.1)
     self._reactor.run()
     if self._started:
         self._stop()
     if self._session is not None:
         self._session.off('detached', self._schedule_on_session_detached)
         self._session.detach()
         self._session = None
     if self._spawned_pid is not None:
         try:
             self._device.kill(self._spawned_pid)
         except:
             pass
     if self._device is not None:
         self._device.off('lost', self._schedule_on_device_lost)
     mgr.off('changed', on_devices_changed)
     frida.shutdown()
     sys.exit(self._exit_status)
Beispiel #7
0
 def run(self):
     mgr = frida.get_device_manager()
     on_devices_changed = lambda: self._reactor.schedule(self._try_start)
     mgr.on('changed', on_devices_changed)
     self._reactor.schedule(self._try_start)
     self._reactor.schedule(self._show_message_if_no_device, delay=0.1)
     self._reactor.run()
     if self._started:
         self._stop()
     if self._session is not None:
         self._session.off('detached', self._schedule_on_session_detached)
         self._session.detach()
         self._session = None
     if self._spawned_pid is not None:
         try:
             self._device.kill(self._spawned_pid)
         except:
             pass
     if self._device is not None:
         self._device.off('output', self._schedule_on_output)
         self._device.off('lost', self._schedule_on_device_lost)
     mgr.off('changed', on_devices_changed)
     frida.shutdown()
     sys.exit(self._exit_status)
Beispiel #8
0
def main():
    import colorama
    from colorama import Fore, Back, Style
    import frida
    from frida.core import Reactor
    from optparse import OptionParser
    import sys

    colorama.init(autoreset=True)

    usage = "usage: %prog [options] process-name-or-id"
    parser = OptionParser(usage=usage)
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("process name or id must be specified")
    try:
        target = int(args[0])
    except:
        target = args[0]

    class Application(UI):
        def __init__(self, target):
            self._target = target
            self._process = None
            self._discoverer = None
            self._status_updated = False
            self._exit_status = 0
            self._reactor = Reactor(await_enter)
            self._reactor.schedule(self._start)

        def run(self):
            self._reactor.run()
            self._stop()
            return self._exit_status

        def _start(self):
            try:
                self._update_status("Attaching...")
                self._process = frida.attach(self._target)
            except Exception as e:
                self._update_status("Failed to attach: %s" % e)
                self._exit_status = 1
                self._reactor.schedule(self._stop)
                return
            self._update_status("Injecting script...")
            self._discoverer = Discoverer(self._reactor)
            self._discoverer.start(self._process, self)

        def _stop(self):
            if self._discoverer is not None:
                print("Stopping...")
                self._discoverer.stop()
                self._discoverer = None
            if self._process is not None:
                self._process.detach()
                self._process = None
            self._reactor.stop()

        def _update_status(self, message):
            if self._status_updated:
                cursor_position = "\033[A"
            else:
                cursor_position = ""
            print("%-80s" % (cursor_position + Style.BRIGHT + message,))
            self._status_updated = True

        def on_sample_progress(self, begin, end, total):
            self._update_status("Sampling %d threads: %d through %d..." % (total, begin, end))

        def on_sample_result(self, module_functions, dynamic_functions):
            for module, functions in module_functions.items():
                print(module.name)
                print("\t%-10s\t%s" % ("Rate", "Function"))
                for function, rate in sorted(functions, key=lambda item: item[1], reverse=True):
                    print("\t%-10d\t%s" % (rate, function))
                print("")

            if len(dynamic_functions) > 0:
                print("Dynamic functions:")
                print("\t%-10s\t%s" % ("Rate", "Function"))
                for function, rate in sorted(dynamic_functions, key=lambda item: item[1], reverse=True):
                    print("\t%-10d\t%s" % (rate, function))

            self._reactor.schedule(self._stop)

    def await_enter():
        if sys.version_info[0] >= 3:
            input()
        else:
            raw_input()

    app = Application(target)
    status = app.run()
    frida.shutdown()
    sys.exit(status)
Beispiel #9
0
def main():
    import colorama
    from colorama import Fore, Back, Style
    import frida
    from frida.core import Reactor
    from optparse import OptionParser
    import sys

    colorama.init(autoreset=True)

    tp = TracerProfileBuilder()
    def process_builder_arg(option, opt_str, value, parser, method, **kwargs):
        method(value)

    usage = "usage: %prog [options] process-name-or-id"
    parser = OptionParser(usage=usage)
    parser.add_option("-I", "--include-module=MODULE", help="include MODULE", metavar="MODULE",
            type='string', action='callback', callback=process_builder_arg, callback_args=(tp.include_modules,))
    parser.add_option("-X", "--exclude-module=MODULE", help="exclude MODULE", metavar="MODULE",
            type='string', action='callback', callback=process_builder_arg, callback_args=(tp.exclude_modules,))
    parser.add_option("-i", "--include=FUNCTION", help="include FUNCTION", metavar="FUNCTION",
            type='string', action='callback', callback=process_builder_arg, callback_args=(tp.include,))
    parser.add_option("-x", "--exclude=FUNCTION", help="exclude FUNCTION", metavar="FUNCTION",
            type='string', action='callback', callback=process_builder_arg, callback_args=(tp.exclude,))
    (options, args) = parser.parse_args()
    if len(args) != 1:
        parser.error("process name or id must be specified")
    try:
        target = int(args[0])
    except:
        target = args[0]
    profile = tp.build()

    class Application(UI):
        def __init__(self, target, profile):
            self._target = target
            self._process = None
            self._tracer = None
            self._profile = profile
            self._status_updated = False
            self._exit_status = 0
            self._reactor = Reactor(await_enter)
            self._reactor.schedule(self._start)

        def run(self):
            self._reactor.run()
            self._stop()
            return self._exit_status

        def _start(self):
            try:
                self._update_status("Attaching...")
                self._process = frida.attach(self._target)
            except Exception as e:
                self._update_status("Failed to attach: %s" % e)
                self._exit_status = 1
                self._reactor.schedule(self._stop)
                return
            self._tracer = Tracer(self._reactor, FileRepository(), self._profile)
            targets = self._tracer.start_trace(self._process, self)
            if len(targets) == 1:
                plural = ""
            else:
                plural = "s"
            self._update_status("Started tracing %d function%s. Press ENTER to stop." % (len(targets), plural))

        def _stop(self):
            if self._tracer is not None:
                print("Stopping...")
                self._tracer.stop()
                self._tracer = None
            if self._process is not None:
                self._process.detach()
                self._process = None
            self._reactor.stop()

        def on_trace_progress(self, operation):
            if operation == 'resolve':
                self._update_status("Resolving functions...")
            elif operation == 'upload':
                self._update_status("Uploading data...")
            elif operation == 'ready':
                self._update_status("Ready!")

        def on_trace_events(self, events):
            self._status_updated = False
            for timestamp, target_address, message in events:
                print("%6d ms\t%s" % (timestamp, message))

        def on_trace_handler_create(self, function, handler, source):
            print("%s: Auto-generated handler at \"%s\"" % (function, source))

        def on_trace_handler_load(self, function, handler, source):
            print("%s: Loaded handler at \"%s\"" % (function, source))

        def _update_status(self, message):
            if self._status_updated:
                cursor_position = "\033[A"
            else:
                cursor_position = ""
            print("%-80s" % (cursor_position + Style.BRIGHT + message,))
            self._status_updated = True

    def await_enter():
        if sys.version_info[0] >= 3:
            input()
        else:
            raw_input()

    app = Application(target, profile)
    status = app.run()
    frida.shutdown()
    sys.exit(status)
Beispiel #10
0
    def run(self):
        main_dir = os.path.join(CUCKOO_ROOT, "storage", "analyses",
                                str(self._id))
        file_dir = os.path.join(main_dir, "file")
        log_dir = os.path.join(main_dir, "logs")
        pending = []
        spawns = {}
        sessions = {}
        scripts = {}
        anti_emulator_events = {}
        self._event = Event()

        def on_child(child):
            log.debug("on_child: {}".format(child))

        def on_spawned(spawn_in):
            log.debug('on_spawned: {}'.format(spawn_in))
            if spawn_in.identifier in exception_list:
                self._device.resume(spawn_in.pid)
            else:
                pending.append(spawn_in)
                self._event.set()

        def on_removed(spawn_out):
            log.debug('on_removed: {}'.format(spawn_out))
            s = sessions.get(spawn_out.pid)
            if s:
                scr = scripts[spawn_out.pid]
                scr.unload()
                log.debug('on_removed - unload: {}'.format(spawn_out))
                s.detach()

        # respond to "send" in javascript
        # message {type:(send || error), payload: (str || list || dict)}

        def on_message(message, data):
            if message.get("type") == "send":
                payload = message.get("payload")
                # log.debug("on_message - payload: {}".format(payload))
                pid = payload.get("Process")
                if pid:
                    pid = spawns.get(pid, pid)
                t = payload.get("type")

                if t == "file":
                    # payload {"Process" : Process.id, "file" : fs.readFileSync(path), "path" : path}
                    # log.debug("on_message: {} - file - path {}".format(pid, payload.get("path")))
                    msg = payload.get("message")
                    # log.debug('on_message: {} {} {}'.format(pid, msg, data))
                    data = payload.get("file")
                    write_to_file(file_dir, payload.get("path"), data)
                    # log.debug("on_message: {} - successfully write file {}".format(pid, payload.get("path")))
                elif t == "msg":
                    # payload {"Process" : Process.id, "message" :  "{Content}"};
                    msg = payload.get("message")
                    log.debug('on_message: {} {} {}'.format(pid, msg, data))
                elif t == 'log':
                    # send({"type":"log", "Process" : Process.id, "log": fs.readFileSync(path) ,"message":msg});
                    msg = payload.get("message")
                    log.debug('on_message: {} {} {}'.format(pid, msg, data))
                    data = payload.get("log")
                    title = payload.get("title", "temp_log")
                    temp = self._log_count
                    self._log_count += 1
                    write_to_file(log_dir, "{}_{}.log".format(title, temp),
                                  data)
                elif t == 'droidmon':
                    msg = payload.get("message")
                    data = payload.get("data")
                    c = data.get('class')
                    if c and anti_emulator_events.get(c):
                        anti_emulator_events[c].append(data)
                    elif not anti_emulator_events.get(c):
                        anti_emulator_events[c] = [data]
                    log.debug('on_message: {} {} {}'.format(pid, msg, data))
                    write_to_file(log_dir,
                                  "emulatorDetect.log",
                                  data,
                                  json_enabled=True)
                elif t == 'recv_wait':  # TODO: server-side intercept
                    msg = payload.get("message")
                    data = payload.get("data")
                    # TODO: Logic handling
                    s = scripts.get(pid)
                    if s:
                        # s.post({JSON})
                        pass
                    log.debug('on_message: {} {} {}'.format(pid, msg, data))
            else:
                log.debug("{} {}".format(message, data))

        try:
            log.debug("Run")
            log.debug("Device: {}".format(self._device))
            self._device.on('spawn-added', on_spawned)
            # self._device.on('child-added', on_child)
            # self._device.on('spawn-removed', on_removed)
            self._device.enable_spawn_gating()
            log.debug("Enabled spawn gating")
            for spawn in self._device.enumerate_pending_spawn():
                self._device.resume(spawn.pid)
            self._ready = True
            while True:
                while len(pending) == 0:
                    self._event.wait()
                    if self._stop_flag:
                        raise ValueError("Task #{}: {} is terminated.".format(
                            self._id, self._device))
                    self._event.clear()
                spawn = pending.pop()
                if spawn.identifier is not None and spawn.identifier not in exception_list:
                    log.debug('Instrumenting: {}'.format(spawn))
                    session = self._device.attach(spawn.pid)
                    # session.enable_jit()
                    # TODO: Handle subprocess
                    # session.enable_child_gating()
                    # Early instrumentation by rpc exports feature
                    script = session.create_script(get_script(self._platform))
                    script.on('message', on_message)
                    script.load()
                    script.exports.init()
                    # script.exports.debug()
                    log.debug('Instrumented: {}'.format(spawn))
                    sessions[spawn.pid] = session
                    scripts[spawn.pid] = script
                    spawns[spawn.pid] = spawn
                    try:
                        self._device.resume(spawn.pid)
                    except Exception as e:
                        if 'unable to find process with pid' in str(e):
                            pass
                        else:
                            raise CuckooFridaError(e)
                    time.sleep(1)
                    # script.exports.modules()
                else:
                    log.debug('Not instrumenting: {}'.format(spawn))
                    self._device.resume(spawn.pid)
                    time.sleep(1)
                log.debug('Processed: {}'.format(spawn))
        except ValueError as normal:
            self._device.off('spawn-added', on_spawned)
            self.unset_adb()
            log.debug(normal)
        except KeyboardInterrupt as k:
            self.unset_adb()
            frida.shutdown()
            log.debug(k)
        except Exception as e:
            self.unset_adb()
            self._stop_flag = True
            raise CuckooFridaError(e)