Frida

17.9.1 · active · verified Sat Apr 11

Frida is a dynamic instrumentation toolkit for developers, reverse-engineers, and security researchers. It allows injecting custom scripts into processes on various platforms (Windows, macOS, Linux, Android, iOS, tvOS, watchOS, QNX, etc.) to inspect, modify, and trace their behavior at runtime. The current Python binding version is 17.9.1, and it maintains a rapid release cadence with frequent updates.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates how to attach to an existing process or spawn a new one, inject a basic JavaScript payload to intercept file opening calls, and receive messages from the injected script. It includes platform-specific adjustments for Windows vs. Unix-like systems and error handling for common Frida issues. Ensure `frida-server` is running on a remote target if not working locally.

import frida
import sys
import os
import time

def on_message(message, data):
    print(f"[+] Message from script: {message}, data: {data}")

try:
    # Define a target process. On Windows, try 'notepad.exe'. On Unix-like, try 'bash' or 'sleep 60'.
    # You can set this via an environment variable or change it directly.
    # Example: FRIDA_TARGET_PROCESS=bash python your_script.py
    process_name = os.environ.get('FRIDA_TARGET_PROCESS', 'notepad.exe' if sys.platform == 'win32' else 'bash')

    print(f"[*] Attempting to attach to process: {process_name}")
    session = None
    try:
        session = frida.attach(process_name)
        print(f"[*] Attached to {session.pid}")
    except frida.ProcessNotFoundError:
        print(f"[-] Process '{process_name}' not found. Trying to spawn it.")
        # Spawning might require specific paths or arguments for the process.
        if sys.platform == 'win32':
            spawn_cmd = [process_name] # For notepad.exe
        else:
            # For bash, spawn it with a command that keeps it alive for a bit
            spawn_cmd = [process_name, '-c', 'sleep 60 & exec bash'] # or ['sleep', '60']

        pid = frida.spawn(spawn_cmd)
        session = frida.attach(pid)
        print(f"[*] Spawned PID: {pid}. Attached.")
        # Resume the spawned process if it was suspended (default for frida.spawn)
        frida.resume(pid)
        time.sleep(1) # Give it a moment to stabilize after resume

    script_source = """
    // Example JavaScript payload: Intercept a file opening function.
    // Note: 'open' is common on Unix-like. On Windows, 'CreateFileW' is often used.
    
    var targetFunction = null;
    if (Process.platform === 'windows') {
        targetFunction = Module.findExportByName('kernel32.dll', 'CreateFileW');
        if (targetFunction) {
            Interceptor.attach(targetFunction, {
                onEnter: function(args) {
                    this.filename = Memory.readUtf16String(args[0]);
                    console.log('[JS] CreateFileW() called with filename: ' + this.filename);
                },
                onLeave: function(retval) {
                    // console.log('[JS] CreateFileW() returned: ' + retval);
                }
            });
            console.log('[JS] Frida script for CreateFileW loaded!');
        } else {
            console.log('[JS] CreateFileW not found in kernel32.dll');
        }
    } else {
        targetFunction = Module.findExportByName(null, 'open');
        if (targetFunction) {
            Interceptor.attach(targetFunction, {
                onEnter: function(args) {
                    this.path = Memory.readUtf8String(args[0]);
                    console.log('[JS] open() called with path: ' + this.path);
                },
                onLeave: function(retval) {
                    // console.log('[JS] open() returned: ' + retval);
                }
            });
            console.log('[JS] Frida script for open() loaded!');
        } else {
            console.log('[JS] open not found.');
        }
    }
    console.log('[JS] Frida script initialization complete!');
    """

    script = session.create_script(script_source)
    script.on('message', on_message) # Attach a Python callback for messages from the JS script
    script.load() # Inject and execute the JavaScript

    print("[+] Script loaded. Intercepting calls. Press Enter to detach and exit...")
    sys.stdin.read() # Keep the Python script alive to allow interaction

except frida.core.RPCException as e:
    print(f"[-] Frida RPC Error: {e}")
    if "Unable to connect" in str(e) or "Failed to attach" in str(e):
        print("    Hint: Ensure 'frida-server' is running on the target device/host, or that you have sufficient permissions.")
    elif "Process not found" in str(e):
        print("    Hint: The target process might not be running or the name is incorrect.")
except Exception as e:
    print(f"[-] An unexpected error occurred: {e}")
finally:
    if session:
        print("[*] Detaching from process...")
        session.detach()
    print("[*] Exited.")

view raw JSON →