Last active
June 2, 2023 17:20
-
-
Save miticollo/747d0569360ac7ebbb37e5514c474f6a to your computer and use it in GitHub Desktop.
frida spawn gating with send message on process termination.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import signal | |
import sys | |
import threading | |
from typing import List, Tuple | |
import _frida | |
import frida | |
from frida.core import Session, Device, Script | |
pending: List[Tuple[_frida.Process, _frida.Spawn]] = [] | |
event: threading.Event = threading.Event() | |
signal_event: threading.Event = threading.Event() | |
PREFIXES = ("/var/containers/Bundle/Application/", | |
"/Applications/", | |
"/private/var/containers/Bundle/Application/", | |
"/System/Library/Frameworks/") | |
def signal_handler(sig, frame): | |
print("Interrupted by Ctrl-C, stopping...") | |
signal_event.set() | |
signal.signal(signal.SIGINT, signal_handler) | |
def on_spawned(_spawn: _frida.Spawn): | |
p: _frida.Process = device.enumerate_processes([_spawn.pid], scope='full')[0] | |
if any(p.parameters['path'].startswith(prefix) for prefix in PREFIXES): | |
# this spawned process is interesting | |
print(f'β¬οΈ {p.name} (PID {p.pid}, PPID {p.parameters["ppid"]}, bundleID {_spawn.identifier}) will be resumed!') | |
pending.append((p, _spawn)) | |
event.set() | |
else: | |
device.resume(_spawn.pid) | |
def on_message(_process: _frida.Process, message): | |
if message["type"] == "send": | |
print(f'π {_process.name} (PID {_process.pid}) is nearly {message["payload"]}!') | |
else: | |
print("Unhandled message:", message) | |
device: Device = frida.get_usb_device() | |
device.on('spawn-added', on_spawned) | |
device.on('spawn-removed', lambda _spawn: print(f'π£ {spawn.pid} is gone!')) | |
device.enable_spawn_gating() | |
print('Press Ctrl-C to exit...') | |
process: _frida.Process | |
spawn: _frida.Spawn | |
sessions = [] | |
while not signal_event.wait(.1): | |
if event.is_set(): | |
while len(pending) >= 1: | |
process, spawn = pending.pop() | |
# TODO: this is a bad idea because we CAN'T hook the Safari engine!!! | |
if 'com.apple.WebKit.' not in process.name: | |
try: | |
session: Session = device.attach(process.pid) | |
sessions.append(session) | |
script: Script = session.create_script(source="""\ | |
const msg = "closed"; | |
console.log('π ' + Process.id + ' loading script!'); | |
// https://frida.re/news/2018/04/28/frida-10-8-released/#flush-before-exit | |
rpc.exports = { | |
dispose: function () { | |
send(JSON.stringify(msg)); | |
console.log('π ' + Process.id + ' says Goodbye!'); | |
} | |
};""") | |
script.on("message", lambda message, data, proc=process: on_message(proc, message)) | |
script.load() | |
except frida.ProcessNotRespondingError as e: | |
print(f'π€¬ {e}') | |
else: | |
print(f'β {process.name} skipped!') | |
device.resume(spawn.pid) | |
event.clear() | |
device.disable_spawn_gating() | |
for session in sessions: | |
session.detach() | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment