|
| 1 | +import threading |
| 2 | + |
| 3 | +from frida_tools.application import Reactor |
| 4 | + |
| 5 | +import frida |
| 6 | + |
| 7 | + |
| 8 | +class Application: |
| 9 | + def __init__(self): |
| 10 | + self._stop_requested = threading.Event() |
| 11 | + self._reactor = Reactor(run_until_return=lambda reactor: self._stop_requested.wait()) |
| 12 | + |
| 13 | + self._device = frida.get_usb_device() |
| 14 | + self._sessions = set() |
| 15 | + self._sessions_lock = threading.Lock() |
| 16 | + |
| 17 | + self._device.on("spawn-added", lambda spawn: self._reactor.schedule(lambda: self._on_spawn_added(spawn))) |
| 18 | + self._device.on("spawn-removed", lambda spawn: self._reactor.schedule(lambda: self._on_spawn_removed(spawn))) |
| 19 | + |
| 20 | + def run(self): |
| 21 | + self._reactor.schedule(lambda: self._start()) |
| 22 | + self._reactor.run() |
| 23 | + |
| 24 | + def _start(self): |
| 25 | + self._device.enable_spawn_gating() |
| 26 | + |
| 27 | + def _instrument(self, pid): |
| 28 | + print(f"✔ attach(pid={pid})") |
| 29 | + session = self._device.attach(pid) |
| 30 | + session.on("detached", lambda reason: self._reactor.schedule(lambda: self._on_detached(pid, session, reason))) |
| 31 | + print("✔ create_script()") |
| 32 | + script = session.create_script( |
| 33 | + """\ |
| 34 | +const puts = new NativeFunction(Module.getGlobalExportByName('puts'), 'int', ['pointer']); |
| 35 | +puts(Memory.allocUtf8String('Hello from Frida agent')); |
| 36 | +Interceptor.attach(Module.getGlobalExportByName('open'), { |
| 37 | + onEnter(args) { |
| 38 | + send({ |
| 39 | + type: 'open', |
| 40 | + path: args[0].readUtf8String() |
| 41 | + }); |
| 42 | + } |
| 43 | +}); |
| 44 | +""" |
| 45 | + ) |
| 46 | + script.on("message", lambda message, data: self._reactor.schedule(lambda: self._on_message(pid, message))) |
| 47 | + print("✔ load()") |
| 48 | + script.load() |
| 49 | + print(f"✔ resume(pid={pid})") |
| 50 | + self._device.resume(pid) |
| 51 | + with self._sessions_lock: |
| 52 | + self._sessions.add(session) |
| 53 | + |
| 54 | + def _on_spawn_added(self, spawn): |
| 55 | + print(f"⚡ spawn_added: {spawn}") |
| 56 | + t = threading.Thread(target=self._handle_spawn, args=(spawn,)) |
| 57 | + t.start() |
| 58 | + |
| 59 | + def _handle_spawn(self, spawn): |
| 60 | + if "/bin/ls" in spawn.identifier: |
| 61 | + self._instrument(spawn.pid) |
| 62 | + else: |
| 63 | + pid = spawn.pid |
| 64 | + print(f"✔ resume(pid={pid})") |
| 65 | + self._device.resume(pid) |
| 66 | + |
| 67 | + def _on_spawn_removed(self, spawn): |
| 68 | + print(f"⚡ spawn_removed: {spawn}") |
| 69 | + |
| 70 | + def _on_detached(self, pid, session, reason): |
| 71 | + print(f"⚡ detached: pid={pid}, reason='{reason}'") |
| 72 | + with self._sessions_lock: |
| 73 | + self._sessions.remove(session) |
| 74 | + |
| 75 | + def _on_message(self, pid, message): |
| 76 | + print(f"⚡ message: pid={pid}, payload={message['payload']}") |
| 77 | + |
| 78 | + |
| 79 | +app = Application() |
| 80 | +app.run() |
0 commit comments