AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Frida Instrumentation

skill-jph4cks-redhound-arsenal-frida-instrumentation · by jph4cks

>

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

Install

$ agentstack add skill-jph4cks-redhound-arsenal-frida-instrumentation

✓ 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 No
  • Shell / process execution Used
  • Environment & secrets No
  • 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.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-jph4cks-redhound-arsenal-frida-instrumentation)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
4mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Frida Instrumentation? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

frida-instrumentation Agent Skill

When to Use This Skill

Use this skill when:

  • Bypassing SSL certificate pinning in Android or iOS apps during DAST
  • Hooking Java/Kotlin/Objective-C/Swift methods at runtime without modifying APK/IPA
  • Tracing native function calls in a running process
  • Reversing mobile app encryption, license checks, or anti-tampering mechanisms
  • Bypassing root detection, emulator detection, or jailbreak detection
  • Automating mobile app pentesting with Objection
  • Building dynamic analysis scripts for malware or binary research

What Frida Does

Frida is a cross-platform dynamic instrumentation framework that injects a JavaScript engine (V8/Duktape) into a target process at runtime. It enables reading/writing memory, hooking arbitrary functions, intercepting calls across Java, Objective-C, and native code layers, and exporting RPC interfaces for external control — all without recompilation or source access. It runs on Windows, macOS, Linux, Android, and iOS, making it the primary tool for mobile application security testing and runtime analysis.

Installation

frida-tools (host machine)

# Python package (pip) — installs frida, frida-trace, frida-ps, frida-ls-devices
pip install frida-tools

# Verify
frida --version
frida-ps --version

# Upgrade
pip install -U frida-tools

# Specific version (pin to match frida-server version)
pip install frida==16.2.1 frida-tools==12.4.3

frida-server (Android device)

# 1. Find device architecture
adb shell getprop ro.product.cpu.abi
# → arm64-v8a, armeabi-v7a, x86, x86_64

# 2. Download matching frida-server from:
# https://github.com/frida/frida/releases
# e.g.: frida-server-16.2.1-android-arm64.xz

# 3. Push and start
xz -d frida-server-16.2.1-android-arm64.xz
adb push frida-server-16.2.1-android-arm64 /data/local/tmp/frida-server
adb shell chmod +x /data/local/tmp/frida-server
adb shell /data/local/tmp/frida-server &

# 4. Verify connection
frida-ps -U        # -U = USB device
frida-ps -U | grep -i target_app

frida-server (iOS device — jailbroken)

# Via Cydia/Sileo — add Frida repo: https://build.frida.re
# Install: Frida (package)

# Verify
frida-ps -U        # USB, or -R for remote TCP

# TCP connection (if USB unavailable)
frida-ps -H 192.168.1.50:27042

frida-gadget (non-rooted / non-jailbroken)

# Inject frida-gadget.so into APK (requires APK repackaging)
# Tool: objection patchapk (easiest method)
objection patchapk -s target.apk

# Or manual:
# 1. Download frida-gadget-XX-android-arm64.so.xz
# 2. Embed in APK lib directory
# 3. Load via modified smali or patched native library entry point

Core Concepts

Attach vs Spawn

# Attach to running process (by name or PID)
frida -U -n "com.target.app"              # attach by package name
frida -U -p 1234                          # attach by PID

# Spawn (start app, pause before main, inject)
frida -U -f com.target.app --no-pause     # spawn and run
frida -U -f com.target.app                # spawn, pause at entry (for early hooks)

# Load script at attach/spawn
frida -U -f com.target.app -l hook.js --no-pause

Script execution modes

# Interactive REPL
frida -U -n com.target.app
# → JavaScript REPL prompt

# One-shot script
frida -U -n com.target.app -l script.js

# Script with output (eval mode)
frida -U -n com.target.app -e "Java.perform(function(){ console.log('hi'); })"

JavaScript API Reference

Java API (Android)

// All Java hooking must be inside Java.perform()
Java.perform(function() {

    // Hook a class method
    var MainActivity = Java.use('com.target.app.MainActivity');

    // Hook instance method
    MainActivity.checkPin.implementation = function(pin) {
        console.log('[*] checkPin called with: ' + pin);
        var result = this.checkPin(pin);   // call original
        console.log('[*] checkPin result: ' + result);
        return result;
    };

    // Override return value
    MainActivity.isRooted.implementation = function() {
        console.log('[*] isRooted hooked — returning false');
        return false;
    };

    // Hook overloaded method (specify signature)
    var String = Java.use('java.lang.String');
    String.equals.overload('java.lang.String').implementation = function(other) {
        var result = this.equals(other);
        if (this.toString().indexOf('password') !== -1) {
            console.log('[*] String.equals: ' + this + ' == ' + other + ' → ' + result);
        }
        return result;
    };

    // Enumerate loaded classes
    Java.enumerateLoadedClasses({
        onMatch: function(className) {
            if (className.indexOf('target') !== -1) {
                console.log('[*] Found class: ' + className);
            }
        },
        onComplete: function() {}
    });

    // Instantiate a Java object
    var SecretClass = Java.use('com.target.app.SecretClass');
    var instance = SecretClass.$new('arg1');
    console.log(instance.getSecret());

    // Access static field
    console.log(MainActivity.SECRET_KEY.value);

    // Modify instance field
    MainActivity.checkPin.implementation = function(pin) {
        this.mMaxAttempts.value = 9999;   // modify field
        return this.checkPin(pin);
    };
});

Interceptor API (Native / C functions)

// Hook by exported symbol name
Interceptor.attach(Module.findExportByName('libc.so', 'strcmp'), {
    onEnter: function(args) {
        // args[0], args[1] are NativePointer objects
        var s1 = args[0].readUtf8String();
        var s2 = args[1].readUtf8String();
        if (s1 !== null && s2 !== null) {
            console.log('[strcmp] "' + s1 + '" vs "' + s2 + '"');
        }
        this.s2 = s2;   // save for onLeave
    },
    onLeave: function(retval) {
        console.log('[strcmp] returned: ' + retval);
        // Force return 0 (strings equal)
        retval.replace(0);
    }
});

// Hook by absolute address
var targetAddr = Module.findBaseAddress('libapp.so').add(0x1234);
Interceptor.attach(targetAddr, {
    onEnter: function(args) {
        console.log('[*] hit target function, arg0 = ' + args[0]);
    },
    onLeave: function(retval) {
        retval.replace(ptr(1));   // return 1 (true)
    }
});

// Replace entire function
Interceptor.replace(targetAddr, new NativeCallback(function(a, b) {
    console.log('[*] replaced function called');
    return 1;    // always return 1
}, 'int', ['int', 'int']));

Module API

// List loaded modules
Process.enumerateModules().forEach(function(m) {
    console.log(m.name, m.base, m.size);
});

// Find module by name
var lib = Process.findModuleByName('libssl.so');
console.log('Base:', lib.base);

// Enumerate exports of a module
Module.enumerateExports('libc.so').forEach(function(exp) {
    if (exp.name.indexOf('SSL') !== -1) {
        console.log(exp.name, exp.address);
    }
});

// Find base address
var base = Module.findBaseAddress('libapp.so');
console.log('libapp.so base:', base);

// Get all symbols (including non-exported)
Module.enumerateSymbols('libapp.so').forEach(function(sym) {
    if (sym.name.indexOf('check') !== -1) {
        console.log(sym.name, sym.address);
    }
});

Memory API

// Read memory
var addr = ptr('0x7f001234');
console.log(addr.readU8());           // 1 byte unsigned
console.log(addr.readU32());          // 4 bytes
console.log(addr.readUtf8String());   // null-terminated C string
console.log(addr.readByteArray(16));  // raw 16 bytes

// Write memory
addr.writeU8(0x90);                   // write single byte (NOP)
addr.writeByteArray([0x90, 0x90]);    // write bytes
addr.writeUtf8String('patched');      // write string

// Allocate new memory
var buf = Memory.alloc(64);
buf.writeUtf8String('injected_string');

// Search memory for pattern
Memory.scan(base, 0x1000, '41 42 43 ?? 45', {
    onMatch: function(address, size) {
        console.log('[*] Pattern at: ' + address);
    },
    onComplete: function() {}
});

// Protect / change permissions
Memory.protect(ptr('0x401000'), 0x1000, 'rwx');

NativeFunction and NativeCallback

// Call an existing native function
var strlen = new NativeFunction(
    Module.findExportByName('libc.so', 'strlen'),
    'size_t',         // return type
    ['pointer']       // argument types
);
var len = strlen(Memory.allocUtf8String('hello'));
console.log('length:', len);

// Create a native function to pass as callback
var myCallback = new NativeCallback(function(data, len) {
    console.log('[*] callback triggered, len =', len);
    return 0;
}, 'int', ['pointer', 'int']);

// Register as callback with a target function
var setCallback = new NativeFunction(
    Module.findExportByName('libapp.so', 'register_callback'),
    'void',
    ['pointer']
);
setCallback(myCallback);

ObjC API (iOS)

// Hook Objective-C method
var className = 'AppDelegate';
var methodName = '- validateLicense:';

if (ObjC.available) {
    var klass = ObjC.classes[className];
    var method = klass[methodName];

    Interceptor.attach(method.implementation, {
        onEnter: function(args) {
            // args[0] = self, args[1] = selector, args[2+] = method args
            var licenseKey = ObjC.Object(args[2]).toString();
            console.log('[*] validateLicense called: ' + licenseKey);
        },
        onLeave: function(retval) {
            // ObjC BOOL is int (0/1)
            retval.replace(ptr(1));  // always return YES
        }
    });

    // Enumerate all methods of a class
    klass.$ownMethods.forEach(function(method) {
        console.log(method);
    });
}

frida-trace — Automatic Hooking

# Trace all calls to functions matching pattern
frida-trace -U -n com.target.app -i "Java_*"     # all JNI functions
frida-trace -U -n com.target.app -i "SSL_*"      # all SSL functions
frida-trace -U -n com.target.app -i "strcmp"     # single function

# Trace Objective-C methods (iOS)
frida-trace -U -n TargetApp -m "-[AppDelegate *]"  # all AppDelegate methods
frida-trace -U -n TargetApp -m "*validate*"         # methods containing 'validate'

# Trace ObjC + native
frida-trace -U -f com.target.app -i "open*" -m "-[NSURLSession *]" --no-pause

# Custom handler output directory
frida-trace -U -n com.target.app -i "SSL_read" -o ./handlers
# Creates handlers/SSL_read.js — auto-generated, edit for custom logic

RPC Exports (Calling Frida from Python)

// script.js — export functions for Python caller
rpc.exports = {
    dumpStrings: function() {
        var results = [];
        Java.perform(function() {
            Java.enumerateLoadedClasses({
                onMatch: function(c) { results.push(c); },
                onComplete: function() {}
            });
        });
        return results;
    },
    callDecrypt: function(ciphertext) {
        var result = null;
        Java.perform(function() {
            var Crypto = Java.use('com.target.app.CryptoUtils');
            result = Crypto.decrypt(Java.use('java.lang.String').$new(ciphertext));
        });
        return result ? result.toString() : null;
    }
};
# caller.py
import frida, sys

def on_message(message, data):
    print('[msg]', message)

device = frida.get_usb_device()
session = device.attach('com.target.app')

with open('script.js', 'r') as f:
    script = session.create_script(f.read())

script.on('message', on_message)
script.load()

# Call exported RPC functions
api = script.exports
classes = api.dump_strings()
print(f'Found {len(classes)} classes')

plaintext = api.call_decrypt('U2FsdGVkX1+...')
print('Decrypted:', plaintext)

Common Workflows

SSL Pinning Bypass (Android)

// Universal SSL bypass — covers OkHttp3, Trustmanager, Network Security Config
Java.perform(function() {

    // Method 1: TrustManager override
    var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
    TrustManagerImpl.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
        console.log('[*] TrustManagerImpl.verifyChain bypassed for: ' + host);
        return untrustedChain;
    };

    // Method 2: OkHttp3 CertificatePinner
    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function(hostname, certs) {
            console.log('[*] OkHttp3 CertificatePinner.check bypassed for: ' + hostname);
        };
    } catch(e) { console.log('[!] OkHttp3 not found: ' + e); }

    // Method 3: SSLContext
    var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
    var TrustAllManager = Java.registerClass({
        name: 'com.frida.TrustAll',
        implements: [X509TrustManager],
        methods: {
            checkClientTrusted: function(chain, authType) {},
            checkServerTrusted: function(chain, authType) {},
            getAcceptedIssuers: function() { return []; }
        }
    });
    var SSLContext = Java.use('javax.net.ssl.SSLContext');
    var ctx = SSLContext.getInstance('TLS');
    ctx.init(null, [TrustAllManager.$new()], null);
    SSLContext.getDefault.implementation = function() { return ctx; };
});
# Or use Objection for one-liner SSL bypass
objection --gadget com.target.app explore
objection> android sslpinning disable

Root Detection Bypass

Java.perform(function() {

    // RootBeer / common root check classes
    var classes = [
        'com.scottyab.rootbeer.RootBeer',
        'com.topjohnwu.superuser.Shell',
    ];

    classes.forEach(function(cls) {
        try {
            var c = Java.use(cls);
            if (c.isRooted) {
                c.isRooted.implementation = function() { return false; };
                console.log('[*] Hooked ' + cls + '.isRooted');
            }
        } catch(e) {}
    });

    // Hook common file existence checks
    var File = Java.use('java.io.File');
    File.exists.implementation = function() {
        var path = this.getAbsolutePath();
        var rootPaths = ['/su', '/system/bin/su', '/sbin/su', '/system/xbin/su'];
        if (rootPaths.indexOf(path) !== -1) {
            console.log('[*] File.exists blocked for: ' + path);
            return false;
        }
        return this.exists();
    };

    // Block Runtime.exec calls for 'su'
    var Runtime = Java.use('java.lang.Runtime');
    Runtime.exec.overload('[Ljava.lang.String;').implementation = function(cmd) {
        var command = cmd.join(' ');
        if (command.indexOf('su') !== -1 || command.indexOf('which') !== -1) {
            console.log('[*] Blocked exec: ' + command);
            throw Java.use('java.io.IOException').$new('File not found');
        }
        return this.exec(cmd);
    };
});

Crypto Key Extraction

// Hook javax.crypto.SecretKeySpec to grab AES keys
Java.perform(function() {
    var SecretKeySpec = Java.use('javax.crypto.SecretKeySpec');
    SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function(keyBytes, algorithm) {
        console.log('[*] SecretKeySpec created:');
        console.log('    Algorithm: ' + algorithm);
        console.log('    Key (hex): ' + bytesToHex(keyBytes));
        return this.$init(keyBytes, algorithm);
    };

    // Hook Cipher for encrypt/decrypt
    var Cipher = Java.use('javax.crypto.Cipher');
    Cipher.doFinal.overload('[B').implementation = function(input) {
        var result = this.doFinal(input);
        console.log('[Cipher.doFinal]');
        console.log('    Input:  ' + bytesToHex(input));
        console.log('    Output: ' + bytesToHex(result));
        return result;
    };
});

function bytesToHex(bytes) {
    var hex = '';
    for (var i = 0; i  path && path.includes(p))) {
                console.log('[*] access() blocked for: ' +

…

## Source & license

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

- **Author:** [jph4cks](https://github.com/jph4cks)
- **Source:** [jph4cks/redhound-arsenal](https://github.com/jph4cks/redhound-arsenal)
- **License:** MIT
- **Homepage:** https://redhound.us

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.