AgentStack
SKILL verified Apache-2.0 Self-run

Frida

skill-as0ler-skills-frida · by as0ler

Use this skill whenever writing, debugging, or reviewing Frida instrumentation scripts targeting iOS ARM64 or Android. Triggers include: any mention of 'Frida', 'dynamic instrumentation', 'hooking', 'Interceptor', 'Stalker', 'ObjC bridge', 'Java bridge', 'frida-server', 'frida-gadget', 'NativeFunction', or requests to hook/trace/patch native or managed functions at runtime. Also use when bypassin…

No reviews yet
0 installs
11 views
0.0% view→install

Install

$ agentstack add skill-as0ler-skills-frida

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Frida? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Frida 17 JavaScript API Reference

> Version: Frida 17.x (latest: 17.6.2, Feb 2026) · frida-tools 14+ > Runtimes: QuickJS (default), V8 (opt-in) · TypeScript supported via frida-compile > Script templates: See [EXAMPLES.md](./EXAMPLES.md) for ready-to-use iOS ARM64 & Android scripts.


Table of Contents

  1. [Setup & Tooling](#1-setup--tooling)
  2. [Migration Notes from Frida 16.x](#2-migration-notes-from-frida-16x)
  3. [Global / Script Scope](#3-global--script-scope)
  4. [Process](#4-process)
  5. [Module](#5-module)
  6. [Memory](#6-memory)
  7. [NativePointer](#7-nativepointer)
  8. [NativeFunction & NativeCallback](#8-nativefunction--nativecallback)
  9. [Interceptor](#9-interceptor)
  10. [Stalker](#10-stalker)
  11. [Thread](#11-thread)
  12. [DebugSymbol](#12-debugsymbol)
  13. [CModule](#13-cmodule)
  14. [ObjC Bridge (iOS/macOS)](#14-objc-bridge-iosmacos)
  15. [Java Bridge (Android)](#15-java-bridge-android)
  16. [Socket](#16-socket)
  17. [File & I/O](#17-file--io)
  18. [Hexdump & Utilities](#18-hexdump--utilities)
  19. [Script IPC (send / recv)](#19-script-ipc-send--recv)
  20. [Frida.Compiler](#20-fridacompiler)
  21. [Arm64Writer / X86Writer / ThumbWriter](#21-arm64writer--x86writer--thumbwriter)
  22. [Platform Tips: iOS ARM64](#22-platform-tips-ios-arm64)
  23. [Platform Tips: Android](#23-platform-tips-android)
  24. [Quick Reference Table](#24-quick-reference-table)

1. Setup & Tooling

Install Frida and launch an agent against a target process over USB, TCP, or locally.

# Minimal working setup
pip install frida frida-tools
frida -U -f com.example.App -l script.js   # spawn via USB
frida -U -F -l script.js                   # attach to frontmost iOS app
# Full tooling reference
pip install frida frida-tools

# Spawn and inject
frida -U -f com.example.App -l script.js          # USB, spawn
frida -U -F -l script.js                           # USB, frontmost app (iOS)
frida -H 192.168.1.10:27042 -f com.example.App -l script.js  # remote TCP

# Interactive REPL (ObjC/Java bridges auto-loaded in frida-tools 14+)
frida -U -F

# Compile TypeScript agent
frida-compile agent.ts -o agent.js
frida-compile agent.ts -o agent.js -w   # watch mode

# Auto-trace functions by name or glob pattern
frida-trace -U -F -i "open" -I "NSURLSession*"

# Push frida-server to Android device
adb push frida-server /data/local/tmp/
adb shell "chmod +x /data/local/tmp/frida-server && /data/local/tmp/frida-server &"

# iOS (jailbroken): install via Cydia/Sileo — package: re.frida.server

2. Migration Notes from Frida 16.x

Frida 17 removed three categories of long-deprecated APIs — update existing scripts before running them against a 17.x agent.

// Quick migration checklist — if your script uses any of these patterns, update it:
// ❌ enumerateModulesSync() or callback-style enumerate  → ✅ returns array directly
// ❌ Memory.readU32(ptr)                                 → ✅ ptr.readU32()
// ❌ Module.getExportByName('lib', 'fn')                 → ✅ Process.getModuleByName('lib').getExportByName('fn')
// ❌ ObjC/Java globals without import in TS agents       → ✅ import "frida-objc-bridge"
// ── Enumeration APIs ──────────────────────────────────────────────────────
// ❌ OLD
Process.enumerateModules({ onMatch(m) { ... }, onComplete() { } });
Process.enumerateModulesSync();
// ✅ NEW — returns array directly
for (const mod of Process.enumerateModules()) { console.log(mod.name); }

// ── Memory read/write ─────────────────────────────────────────────────────
// ❌ OLD
Memory.readU32(ptr('0x1234'));
Memory.writeU32(ptr('0x1234'), 100);
// ✅ NEW — methods on NativePointer, chainable
ptr('0x1234').readU32();
ptr('0x1234').writeU32(100);
ptr('0x1234').add(4).writeU32(10).add(4).writeU16(20);

// ── Static Module helpers ─────────────────────────────────────────────────
// ❌ OLD
Module.getBaseAddress('libc.so');
Module.getExportByName('libc.so', 'open');
Module.findExportByName('libc.so', 'open');
Module.ensureInitialized('libc.so');
// ✅ NEW
Process.getModuleByName('libc.so').base;
Process.getModuleByName('libc.so').getExportByName('open');
Process.getModuleByName('libc.so').findExportByName('open');
Module.getGlobalExportByName('open');   // replaces getExportByName(null, 'open')

// ── Runtime bridges ───────────────────────────────────────────────────────
// ObjC / Java / Swift no longer bundled in Frida core.
// frida-tools 14+ REPL auto-loads them. TypeScript agents must import explicitly:
import "frida-objc-bridge";   // provides ObjC global
import "frida-java-bridge";   // provides Java global

3. Global / Script Scope

Top-level globals and built-ins available in every Frida agent without any import.

// Typical agent preamble
const base     = Process.mainModule.base;
const libc     = Process.getModuleByName('libc.so');
const openAddr = libc.getExportByName('open');
send({ type: 'ready', base: base.toString() });
// Full global reference
ptr(val)           // Create NativePointer from hex string or number
NULL               // NativePointer(0x0)
Process            // Current process introspection
Memory             // Memory utilities (alloc, scan, patch, protect)
Interceptor        // Function hook engine
Stalker            // Code tracing engine
Thread             // Thread enumeration + backtrace
DebugSymbol        // Address ↔ symbol resolution
CModule            // Inline C compilation
Module             // Static module helpers (getGlobalExportByName, load)
ObjC               // Objective-C runtime bridge (iOS/macOS)
Java               // Android ART/JVM bridge
console            // console.log / console.warn / console.error
hexdump(buf)       // Pretty hex dump to string
send(msg, data?)   // Send message + optional binary to Python host
recv(type, cb)     // Register handler for message from Python host
rpc.exports        // Expose JS functions as RPC callable from host

// Script lifecycle
Script.pin();      // Prevent GC of this script object
Script.unpin();

// Top-level await is supported
const result = await SomeAsyncOperation();

4. Process

Provides identity, module lookup, memory range enumeration, thread listing, and exception handling for the instrumented process.

// Log process info and look up a module
console.log(Process.id, Process.arch, Process.platform);
const libc = Process.getModuleByName('libc.so');
console.log('libc base:', libc.base, 'size:', libc.size);
// ── Identity ──────────────────────────────────────────────────────────────
Process.id                  // PID (number)
Process.arch                // 'arm64' | 'x64' | 'arm' | 'ia32'
Process.platform            // 'darwin' | 'linux' | 'windows' | 'freebsd'
Process.pageSize            // page size in bytes
Process.pointerSize         // 4 or 8
Process.codeSigningPolicy   // 'optional' | 'required'
Process.mainModule          // Module object for the main executable
Process.currentDir          // working directory string

// ── Module lookup ─────────────────────────────────────────────────────────
Process.enumerateModules()                   // → Module[]
Process.getModuleByName('libc.so')           // throws if not found
Process.findModuleByName('libc.so')          // → Module | null
Process.getModuleByAddress(ptr('0x1234'))
Process.findModuleByAddress(ptr('0x1234'))

// ── Memory ranges ─────────────────────────────────────────────────────────
Process.enumerateRanges('r-x')                             // → RangeDetails[]
Process.enumerateRanges({ protection: 'r-x', coalesce: true })
Process.enumerateMallocRanges()                            // heap chunks

// RangeDetails: { base: NativePointer, size: number, protection: string,
//                 file?: { path, offset, size } }

// ── Threads ───────────────────────────────────────────────────────────────
Process.enumerateThreads()          // → ThreadDetails[] (Frida threads hidden)
Process.getCurrentThreadId()        // → number

// ── Exception handler ─────────────────────────────────────────────────────
Process.setExceptionHandler((details) => {
  console.log('Exception:', details.type, details.address);
  return false; // false = propagate to OS
});

5. Module

Represents a loaded binary (.so, .dylib, or executable) and exposes its exports, symbols, imports, and sections.

// Look up a module and find two exports without redundant lookups
const libc   = Process.getModuleByName('libc.so');
const openFn = libc.getExportByName('open');
const readFn = libc.getExportByName('read');
console.log('open @', openFn, 'read @', readFn);
// ── Module object properties ──────────────────────────────────────────────
mod.name    // 'libgame.so'
mod.path    // full filesystem path
mod.base    // NativePointer — load address
mod.size    // size in bytes

// ── Instance methods (Frida 17+) ──────────────────────────────────────────
mod.enumerateImports()        // → ImportDetails[]
mod.enumerateExports()        // → ExportDetails[]
mod.enumerateSymbols()        // → SymbolDetails[]
mod.enumerateSections()       // → SectionDetails[]
mod.enumerateDependencies()   // → string[]

mod.findExportByName('fn')    // → NativePointer | null
mod.getExportByName('fn')     // → NativePointer (throws if missing)
mod.findSymbolByName('_ZN…')  // → NativePointer | null
mod.getSymbolByName('_ZN…')   // → NativePointer

// ExportDetails: { type: 'function'|'variable', name: string, address: NativePointer }

// ── Static global helpers ─────────────────────────────────────────────────
Module.getGlobalExportByName('open')    // search all loaded modules; throws if missing
Module.findGlobalExportByName('open')   // → NativePointer | null
Module.load('/path/to/lib.so')          // dlopen and return Module

6. Memory

Allocates, copies, protects, patches, and scans process memory.

// Allocate a C string and scan for its bytes
const buf = Memory.allocUtf8String('FIND_ME');
Memory.scan(buf, 8, '46 49 4e 44', {
  onMatch(addr) { console.log('found at', addr); },
  onError() {},
  onComplete() {}
});
// ── Allocation ────────────────────────────────────────────────────────────
Memory.alloc(256)                            // zeroed buffer → NativePointer
Memory.allocUtf8String('hello')              // null-terminated UTF-8
Memory.allocUtf16String('hello')             // null-terminated UTF-16
Memory.allocByteArray(new Uint8Array([0x90, 0x90]))

// ── Copy / duplicate ──────────────────────────────────────────────────────
Memory.copy(dst, src, n)       // copy n bytes src → dst
Memory.dup(src, n)             // allocate + copy → new NativePointer

// ── Protection ────────────────────────────────────────────────────────────
Memory.protect(addr, size, 'rwx')          // change page protection
Memory.queryProtection(addr)               // → 'r-x' | 'rwx' | etc.

// ── Code patching (W^X safe) ──────────────────────────────────────────────
Memory.patchCode(addr, size, (code) => {
  const w = new Arm64Writer(code, { pc: addr });
  w.putNop();
  w.flush();
});

// ── Scanning (async, callback-based — remains async in Frida 17) ──────────
// Pattern format: 'AA BB ?? DD'  — ?? is a wildcard byte
Memory.scan(base, size, 'DE AD BE EF', {
  onMatch(address, size)  { console.log('found @', address); },
  onError(reason)         { /* skip unreadable pages */ },
  onComplete()            { }
});

// NOTE: Memory.readXxx() / Memory.writeXxx() static methods REMOVED in 17.
// Use NativePointer instance methods instead — see §7.

7. NativePointer

The universal address type in Frida — every memory address is a NativePointer with built-in arithmetic, read, and write methods.

// Read a simple struct: vtable pointer + two 32-bit fields
const obj  = ptr('0x200000');
const vtbl = obj.readPointer();
const hp   = obj.add(8).readU32();
const mp   = obj.add(12).readU32();
console.log('vtable:', vtbl, 'hp:', hp, 'mp:', mp);
const p = ptr('0x100400000');

// ── Arithmetic (returns new NativePointer) ────────────────────────────────
p.add(0x10)   p.sub(4)
p.and(0xFFF)  p.or(1)   p.xor(0xFF)
p.shl(2)      p.shr(1)  p.not()

// ── Comparison ────────────────────────────────────────────────────────────
p.equals(q)          // boolean
p.compare(q)         // -1 | 0 | 1
p.isNull()

// ── Conversion ────────────────────────────────────────────────────────────
p.toInt32()   p.toUInt32()
p.toString()  p.toString(16)
p.toMatchPattern()   // → 'AA BB CC DD' byte string for use in Memory.scan

// ── Read ──────────────────────────────────────────────────────────────────
p.readPointer()      // → NativePointer
p.readS8()   p.readU8()
p.readS16()  p.readU16()
p.readS32()  p.readU32()
p.readS64()  p.readU64()
p.readFloat()   p.readDouble()
p.readByteArray(n)    // → ArrayBuffer
p.readCString()       // null-terminated ASCII/UTF-8
p.readUtf8String(len?)
p.readUtf16String(len?)
p.readAnsiString(len?)  // Windows only

// ── Write (returns same NativePointer for chaining) ───────────────────────
p.writePointer(q)
p.writeS8(v)   p.writeU8(v)
p.writeS16(v)  p.writeU16(v)
p.writeS32(v)  p.writeU32(v)
p.writeS64(v)  p.writeU64(v)
p.writeFloat(v)   p.writeDouble(v)
p.writeByteArray(arrayBuffer)
p.writeUtf8String('hello')
p.writeUtf16String('hello')

// ── Chaining ──────────────────────────────────────────────────────────────
ptr('0x5000')
  .add(8).writeU32(100)
  .add(4).writeU16(42)
  .add(2).writeU8(1);

8. NativeFunction & NativeCallback

Wraps a native C function so it can be called directly from JavaScript, and creates a native-callable stub backed by a JavaScript function.

// Call strlen directly from JS
const strlen = new NativeFunction(
  Module.getGlobalExportByName('strlen'), 'int', ['pointer']
);
console.log('length:', strlen(Memory.allocUtf8String('hello'))); // → 5
// ── NativeFunction: call any native function from JS ─────────────────────
const open = new NativeFunction(
  Process.getModuleByName('libc.so').getExportByName('open'),
  'int',               // return type
  ['pointer', 'int'],  // argument types
  { abi: 'default' }   // optional: 'win64' | 'sysv' | 'stdcall' | 'fastcall'
);
const fd = open(Memory.allocUtf8String('/etc/hosts'), 0 /* O_RDONLY */);

// Supported type strings:
// 'void' 'bool' 'char' 'uchar' 'short' 'ushort' 'int' 'uint'
// 'long' 'ulong' 'longlong' 'ulonglong' 'float' 'double'
// 'pointer' 'size_t' 'ssize_t' 'int8_t' … 'uint64_t'

// ── NativeCallback: expose a JS function as a native C function ───────────
const myHook = new NativeCallback(
  (a, b) => {
    console.log('called with:', a, b);
    return a + b;
  },
  'int',          // return type
  ['int', 'int']  // argument types
);
// myHook is a NativePointer — pass it to Interceptor.replace() or any C API

9. Interceptor

The primary hooking engine — attaches onEnter/onLeave callbacks to observe any native function, or replaces it entirely with a new implementation.

// Log every call to open() and override the return value
Interceptor.attach(Module.getGlobalExportByName('open'), {
  onEnter(args) {
    console.log('[open]', args[0].readCString(), 'flags:', args[1].toInt32());
  },
  onLeave(retval) {
    console.log('[open] fd =', retval.toInt32());
  }
});
// ── attach: observe without replacing ─────────────────────────────────────
const hook = Interceptor.attach(targetPtr, {
  onEnter(args) {
    // args[n]       → NativePointer (n-th argument)
    // this.context  → CpuContext: pc, sp, fp, x0–x28 (ARM64) / rax… (x64)
    // this.threadId, this.returnAddress, this.depth, this.errno
    this.savedArg = args[0].readUtf8String();  // stash state for onLeave
  },
  onLeave(retval) {
    retval.replace(ptr(1));   // override return value
  }
});
hook.detach();   // remove this specific

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [as0ler](https://github.com/as0ler)
- **Source:** [as0ler/skills](https://github.com/as0ler/skills)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.