├── .img └── bin.jpg ├── CHANGELOG.md ├── LICENSE ├── ios-snippets ├── raptor_frida_ios_bypass1.js ├── raptor_frida_ios_bypass2.js ├── raptor_frida_ios_lowlevel2.js ├── raptor_frida_ios_touchid.js ├── raptor_frida_ios_lowlevel1.js ├── raptor_frida_ios_debug.js ├── raptor_frida_ios_autoIntercept.js ├── raptor_frida_ios_call.js └── raptor_frida_ios_stalker.js ├── android-snippets ├── raptor_frida_android_bypass.js ├── raptor_frida_android_findClass1.js ├── raptor_frida_android_findClass2.js ├── raptor_frida_android_lowlevel.js └── raptor_frida_android_debug.js ├── README.md ├── raptor_frida_android_enum.js ├── raptor_frida_linux_trace.js ├── raptor_frida_ios_enum.js ├── raptor_frida_linux_enum.js ├── raptor_frida_ios_trace.js └── raptor_frida_android_trace.js /.img/bin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/frida-scripts/HEAD/.img/bin.jpg -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog for frida-scripts 2 | 3 | All notable changes to this project are documented in this file. 4 | 5 | ## [Unreleased] 6 | 7 | ### Changed 8 | 9 | * Improve documentation. 10 | 11 | ## [0.2] - 2025-10-02 12 | 13 | * New release of main scripts ported to Frida >= 17. 14 | 15 | ### Added 16 | 17 | * Add Linux enumeration script. 18 | * Add Linux trace script. 19 | * Add CHANGELOG.md. 20 | 21 | ### Changed 22 | 23 | * Improve documentation. 24 | 25 | ### Fixed 26 | 27 | * Port iOS trace script to Frida 17.x. 28 | * Port Android trace script to Frida 17.x. 29 | 30 | ## [0.1] - 2024-01-04 31 | 32 | * Historical battle-tested stable release that used to work before the [breaking changes](https://frida.re/news/2025/05/17/frida-17-0-0-released/) in Frida 17.x. 33 | 34 | [unreleased]: https://github.com/0xdea/frida-scripts/compare/v0.2...HEAD 35 | 36 | [0.2]: https://github.com/0xdea/frida-scripts/compare/v0.1...v0.2 37 | 38 | [0.1]: https://github.com/0xdea/frida-scripts/releases/tag/v0.1 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Marco Ivaldi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_bypass1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // SSL pinning bypass: change retval, reimplementation technique 22 | 23 | var CertPinning = ObjC.classes.CertPinning; 24 | var getID = CertPinning["- getID:"]; 25 | var getID_oldImpl = getID.implementation; 26 | 27 | getID.implementation = ObjC.implement(getID, function (handle, selector, arg1) { 28 | //return getID_oldImpl(handle, selector, arg1); 29 | console.log("info: entered getID"); 30 | var retnew = ObjC.classes.NSString.stringWithString_("151f09ff42c55a4fcbae2246eb58f1d2f2168c0d"); 31 | return retnew; 32 | }); 33 | 34 | } else { 35 | send("error: Objective-C Runtime is not available!"); 36 | } 37 | -------------------------------------------------------------------------------- /android-snippets/raptor_frida_android_bypass.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_*.js - Frida snippets for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for Android instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause 17 | */ 18 | 19 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 20 | 21 | Java.perform(function() { 22 | 23 | // Root detection bypass example 24 | 25 | var hook = Java.use("com.target.utils.RootCheck"); 26 | console.log("info: hooking target class"); 27 | 28 | hook.isRooted.overload().implementation = function() { 29 | console.log("info: entered target method"); 30 | 31 | // obtain old retval 32 | var retval = this.isRooted.overload().call(this); 33 | console.log("old ret value: " + retval); 34 | 35 | // set new retval 36 | var retnew = false; 37 | console.log("new ret value: " + retnew); 38 | return retnew; 39 | } 40 | 41 | }); 42 | 43 | }, 0); 44 | -------------------------------------------------------------------------------- /android-snippets/raptor_frida_android_findClass1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_*.js - Frida snippets for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for Android instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause 17 | */ 18 | 19 | // find loaded classes that match a pattern (sync) 20 | function findClass(pattern) 21 | { 22 | console.warn("\n*** finding all classes that match pattern: " + pattern + "\n"); 23 | 24 | var allClasses = Java.enumerateLoadedClassesSync(); 25 | allClasses.forEach(function(aClass) { 26 | if (aClass.match(pattern)) 27 | console.log(aClass); 28 | }); 29 | } 30 | 31 | // usage examples 32 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 33 | 34 | Java.perform(function() { 35 | 36 | //findClass(); // print all loaded classes 37 | //findClass("Root"); // print all classes that match a string 38 | //findClass(/root/i); // print all classes that match a regex (e.g., case insensitive) 39 | 40 | }); 41 | 42 | }, 0); 43 | -------------------------------------------------------------------------------- /android-snippets/raptor_frida_android_findClass2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_*.js - Frida snippets for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for Android instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause 17 | */ 18 | 19 | // find loaded classes that match a pattern (async) 20 | function findClass(pattern) 21 | { 22 | console.warn("\n*** finding all classes that match pattern: " + pattern + "\n"); 23 | 24 | Java.enumerateLoadedClasses({ 25 | onMatch: function(aClass) { 26 | if (aClass.match(pattern)) 27 | console.log(aClass); 28 | }, 29 | onComplete: function() {} 30 | }); 31 | } 32 | 33 | // usage examples 34 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 35 | 36 | Java.perform(function() { 37 | 38 | //findClass(); // print all loaded classes 39 | //findClass("Root"); // print all classes that match a string 40 | //findClass(/root/i); // print all classes that match a regex (e.g., case insensitive) 41 | 42 | }); 43 | 44 | }, 0); 45 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_bypass2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // Jailbreak detection bypass: change retval, onLeave technique 22 | 23 | var hook = ObjC.classes.JailbreakChecks["- isJailbroken"]; 24 | 25 | Interceptor.attach(hook.implementation, { 26 | 27 | onLeave: function(retval) { 28 | console.log("info: exiting isJailbroken"); 29 | 30 | // read retval 31 | var obj = ObjC.Object(retval); 32 | console.log("retval type:", obj.$class, obj.$className); 33 | console.log("old retval value:", obj.toString()); 34 | 35 | // change retval 36 | var retnew = ObjC.classes.NSString.stringWithString_("false"); 37 | retval.replace(retnew); 38 | console.log("new retval value:", obj.toString()); 39 | } 40 | }); 41 | 42 | } else { 43 | send("error: Objective-C Runtime is not available!"); 44 | } 45 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_lowlevel2.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // Low-level intercept and backtrace example 22 | 23 | Interceptor.attach(Module.findExportByName("libSystem.B.dylib", "open"), { 24 | 25 | onEnter: function(args) { 26 | 27 | // debug only the intended calls 28 | this.flag = 0; 29 | var filename = Memory.readCString(ptr(args[0])); 30 | 31 | //if (filename.indexOf("Bundle") == -1 && filename.indexOf("Cache") == -1) // exclusion list 32 | if (filename.indexOf("my.interesting.file") != -1) // inclusion list 33 | this.flag = 1; 34 | 35 | if (this.flag) { 36 | console.log("\nopen called from:\n", 37 | Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"), 38 | "\n"); 39 | //console.log(filename); // DEBUG 40 | } 41 | } 42 | }); 43 | 44 | } else { 45 | send("error: Objective-C Runtime is not available!"); 46 | } 47 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_touchid.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Useful snippet ripped from @henryhoggard's Needle module 13 | * "hooking/frida/script_touch-id-bypass". 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | * 18 | */ 19 | 20 | if (ObjC.available) { 21 | 22 | /* 23 | * method to hook: 24 | * - (void)evaluatePolicy:(LAPolicy)policy 25 | * localizedReason:(NSString *)localizedReason 26 | * reply:(void (^)(BOOL success, NSError *error))reply; 27 | */ 28 | var hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"]; 29 | 30 | Interceptor.attach(hook.implementation, { 31 | 32 | onEnter: function(args) { 33 | console.log("info: hooking Touch ID"); 34 | 35 | var block = new ObjC.Block(args[4]); // hook the reply callback 36 | var callback = block.implementation; 37 | block.implementation = function(error, value) { 38 | var reply = callback(1, null); // always return YES 39 | return reply; 40 | }; 41 | } 42 | }); 43 | 44 | } else { 45 | send("error: Objective-C Runtime is not available!"); 46 | } 47 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_lowlevel1.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // Low-level intercept and binary data print example 22 | 23 | Interceptor.attach(Module.findExportByName("libSystem.B.dylib", "CCCrypt"), { 24 | 25 | onEnter: function(args) { 26 | console.log("\n*** entered CCCrypt ***"); 27 | console.log("\nkey:"); 28 | console.log(hexdump(ptr(args[3]), { 29 | offset: 0, 30 | length: parseInt(args[4]), 31 | header: true, 32 | ansi: true 33 | })); 34 | console.log("\ndataIn:"); 35 | console.log(hexdump(ptr(args[6]), { 36 | offset: 0, 37 | length: parseInt(args[7]), 38 | header: true, 39 | ansi: true 40 | })); 41 | this.ret = args[8]; 42 | this.retlen = args[9]; 43 | }, 44 | 45 | onLeave: function(retval) { 46 | console.log("\ndataOut:"); 47 | console.log(hexdump(ptr(this.ret), { 48 | offset: 0, 49 | length: parseInt(this.retlen), 50 | header: true, 51 | ansi: true 52 | })); 53 | console.log("\n*** exiting CCCrypt ***"); 54 | } 55 | }); 56 | 57 | } else { 58 | send("error: Objective-C Runtime is not available!"); 59 | } 60 | -------------------------------------------------------------------------------- /android-snippets/raptor_frida_android_lowlevel.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_*.js - Frida snippets for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for Android instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause 17 | */ 18 | 19 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 20 | 21 | Java.perform(function() { 22 | 23 | // Low-level intercept and backtrace example 24 | 25 | Interceptor.attach(Module.findExportByName("/system/lib/libc.so", "open"), { 26 | 27 | onEnter: function(args) { 28 | 29 | // debug only the intended calls 30 | this.flag = false; 31 | // var filename = Memory.readCString(ptr(args[0])); 32 | // if (filename.indexOf("XYZ") === -1 && filename.indexOf("ZYX") === -1) // exclusion list 33 | // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list 34 | this.flag = true; 35 | 36 | if (this.flag) { 37 | console.warn("\n*** entered open"); 38 | 39 | var filename = Memory.readCString(ptr(args[0])); 40 | console.log("\nfile name: " + filename); 41 | 42 | // print backtrace 43 | console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 44 | .map(DebugSymbol.fromAddress).join("\n")); 45 | } 46 | }, 47 | 48 | onLeave: function(retval) { 49 | 50 | if (this.flag) { 51 | // print retval 52 | console.log("\nretval: " + retval); 53 | console.warn("\n*** exiting open"); 54 | } 55 | } 56 | 57 | }); 58 | 59 | }); 60 | 61 | }, 0); 62 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_debug.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // Debug a method 22 | 23 | var oldImpl = ObjC.classes.KeychainManager["+ readKey:"]; 24 | 25 | // console.log(ptr(oldImpl.implementation)); // DEBUG 26 | 27 | Interceptor.attach(oldImpl.implementation, { 28 | 29 | onEnter: function(args) { 30 | 31 | // debug only the intended calls 32 | this.flag = 0; 33 | //if (ObjC.Object(args[2]).toString() == "1234567890abcdef1234567890abcdef12345678") 34 | this.flag = 1; 35 | 36 | if (this.flag) { 37 | console.log("info: entered method"); 38 | 39 | // 1st arg 40 | if (args[2]) { 41 | var obj = ObjC.Object(args[2]); 42 | console.log("args[2] type:", obj.$class, obj.$className); 43 | console.log("args[2] value:", obj.toString()); 44 | } 45 | 46 | // 2nd arg 47 | if (args[3]) { 48 | var obj = ObjC.Object(args[3]); 49 | console.log("args[3] type:", obj.$class, obj.$className); 50 | console.log("args[3] value:", obj.toString()); 51 | } 52 | } 53 | }, 54 | 55 | onLeave: function(retval) { 56 | 57 | if (this.flag) { 58 | console.log("info: exiting method"); 59 | 60 | // retval 61 | if (retval) { 62 | var obj = ObjC.Object(retval); 63 | console.log("retval type:", obj.$class, obj.$className); 64 | console.log("retval value:", obj.toString()); 65 | } 66 | } 67 | } 68 | 69 | }); 70 | 71 | } else { 72 | send("error: Objective-C Runtime is not available!"); 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frida-scripts 2 | 3 | [![](https://img.shields.io/github/stars/0xdea/frida-scripts.svg?style=flat&color=yellow)](https://github.com/0xdea/frida-scripts) 4 | [![](https://img.shields.io/github/forks/0xdea/frida-scripts.svg?style=flat&color=green)](https://github.com/0xdea/frida-scripts) 5 | [![](https://img.shields.io/github/watchers/0xdea/frida-scripts.svg?style=flat&color=red)](https://github.com/0xdea/frida-scripts) 6 | [![](https://img.shields.io/badge/frida-17.3.2-lightcoral)](https://github.com/frida/frida) 7 | [![](https://img.shields.io/badge/twitter-%400xdea-blue.svg)](https://twitter.com/0xdea) 8 | [![](https://img.shields.io/badge/mastodon-%40raptor-purple.svg)](https://infosec.exchange/@raptor) 9 | 10 | A collection of my Frida.re instrumentation scripts to facilitate reverse engineering of mobile apps and more. 11 | 12 | *Note: My iOS and Android scripts might require some tweakings. For a well-maintained project that includes some of my Frida scripts, refer to [Brida](https://github.com/federicodotta/Brida).* 13 | 14 | ![](https://raw.githubusercontent.com/0xdea/frida-scripts/master/.img/bin.jpg) 15 | 16 | ## Blog post 17 | 18 | * 19 | 20 | ## See also 21 | 22 | * 23 | 24 | ## Scripts 25 | 26 | ### iOS 27 | 28 | * [**raptor_frida_ios_trace.js**](raptor_frida_ios_trace.js). Full-featured ObjC and Module tracer for iOS. 29 | * [**raptor_frida_ios_enum.js**](raptor_frida_ios_enum.js). Collection of functions to enumerate ObjC classes and methods. 30 | * [**ios-snippets/**](ios-snippets). Miscellaneous script snippets for iOS (tested with Frida before 17.0.0). 31 | 32 | ### Android 33 | 34 | * [**raptor_frida_android_trace.js**](raptor_frida_android_trace.js). Full-featured Java and Module tracer for Android. 35 | * [**raptor_frida_android_enum.js**](raptor_frida_android_enum.js). Collection of functions to enumerate Java classes and methods. 36 | * [**android-snippets/**](android-snippets). Miscellaneous script snippets for Android (tested with Frida before 17.0.0). 37 | 38 | ### Linux 39 | 40 | * [**raptor_frida_linux_trace.js**](raptor_frida_linux_trace.js). Full-featured function call tracer for Linux. 41 | * [**raptor_frida_linux_enum.js**](raptor_frida_linux_enum.js). Collection of functions to enumerate modules and functions in a binary. 42 | 43 | ## Changelog 44 | 45 | * [CHANGELOG.md](CHANGELOG.md) 46 | 47 | ## TODO 48 | 49 | * Test extensively with real-world apps. 50 | * Add Windows and macOS scripts. 51 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_autoIntercept.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | // print arg/ret type 20 | function printType(desc, arg) 21 | { 22 | try { 23 | console.log(desc + ObjC.Object(arg).$class + " " + ObjC.Object(arg).$className); 24 | } 25 | catch(err) { 26 | // do nothing 27 | } 28 | } 29 | 30 | // print arg/ret value 31 | function printValue(desc, arg) 32 | { 33 | try { 34 | console.log(desc + ObjC.Object(arg)); 35 | } 36 | catch(err) { 37 | console.log(desc + arg); 38 | } 39 | } 40 | 41 | // main interceptor 42 | function autoIntercept(target) 43 | { 44 | var className = target.match(/^[-+]\[(.*)\s/)[1]; 45 | var methodType = target.match(/^([-+])/)[1]; 46 | var methodName = target.match(/^[-+]\[.*\s(.*)\]/)[1]; 47 | var argCount = (methodName.match(/:/g) || []).length; 48 | 49 | console.log("\ninfo: trying to intercept", target); 50 | var oldImpl = ObjC.classes[className][methodType + " " + methodName]; 51 | 52 | Interceptor.attach(oldImpl.implementation, { 53 | 54 | onEnter: function(args) { 55 | 56 | // debug only the intended calls 57 | this.flag = 0; 58 | //if (ObjC.Object(args[2]).toString() == "1234567890abcdef1234567890abcdef12345678") 59 | this.flag = 1; 60 | 61 | if (this.flag) { 62 | 63 | console.log("\n*** entered", target, "***"); 64 | 65 | // print args 66 | for (var i = 0; i < argCount; i++) { 67 | printType("\narg " + (i + 1) + " type:\t", args[i + 2]); 68 | printValue("arg " + (i + 1) + " value:\t", args[i + 2]); 69 | } 70 | } 71 | }, 72 | 73 | onLeave: function(retval) { 74 | 75 | if (this.flag) { 76 | 77 | // print retval 78 | printType("\nretval type:\t", retval); 79 | printValue("retval value:\t", retval); 80 | 81 | console.log("\n*** exiting", target, "***"); 82 | } 83 | } 84 | 85 | }); 86 | } 87 | 88 | if (ObjC.available) { 89 | 90 | // autoIntercept("-[CredManager setPassword:]"); 91 | 92 | } else { 93 | send("error: Objective-C Runtime is not available!"); 94 | } 95 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_call.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | if (ObjC.available) { 20 | 21 | // Call an Objective-C method with arbitrary parameters 22 | 23 | var oldImpl = ObjC.classes.MyClass["+ sendStrings:array:"]; 24 | 25 | Interceptor.attach(oldImpl.implementation, { 26 | 27 | onEnter: function(args) { 28 | console.log("info: entered sendStrings"); 29 | 30 | // 1st arg 31 | var obj = ObjC.Object(args[2]); 32 | console.log("args[2] type:", obj.$class, obj.$className); 33 | console.log("args[2] value:", obj.toString()); 34 | 35 | // 2nd arg 36 | var obj = ObjC.Object(args[3]); 37 | console.log("args[3] type:", obj.$class, obj.$className); 38 | console.log("args[3] value:", obj.toString()); 39 | 40 | // 2nd arg's contents (array) 41 | for (var i = 0; i < obj.count(); i++) 42 | console.log(ObjC.Object(obj.objectAtIndex_(i)).$class); 43 | }, 44 | 45 | onLeave: function(retval) { 46 | console.log("info: exiting sendStrings"); 47 | 48 | // retval 49 | var obj = ObjC.Object(retval); 50 | console.log("retval type:", obj.$class, obj.$className); 51 | console.log("retval value:", obj.toString()); 52 | } 53 | 54 | }); 55 | 56 | // build 1st arg (string) 57 | // "somestring" 58 | var arg1 = ObjC.classes.NSString.stringWithString_("somestring"); 59 | 60 | // build 2nd arg (NSMutableArray) 61 | // ( 62 | // "foo", 63 | // "bar", 64 | // "someotherstring" 65 | // ) 66 | var arg2_1 = ObjC.classes.NSString.stringWithString_("foo"); 67 | var arg2_2 = ObjC.classes.NSString.stringWithString_("bar"); 68 | var arg2_3 = ObjC.classes.NSString.stringWithString_("someotherstring"); 69 | var arg2 = ObjC.classes.NSMutableArray.alloc().init(); 70 | arg2.addObject_(arg2_1); 71 | arg2.addObject_(arg2_2); 72 | arg2.addObject_(arg2_3); 73 | 74 | // call the target method 75 | var token = ObjC.classes.MyClass.sendStrings_array_(arg1, arg2); 76 | console.log(token.toString()); 77 | 78 | } else { 79 | send("error: Objective-C Runtime is not available!"); 80 | } 81 | -------------------------------------------------------------------------------- /android-snippets/raptor_frida_android_debug.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_*.js - Frida snippets for Android 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for Android instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_android.js --no-pause 17 | */ 18 | 19 | setTimeout(function() { // avoid java.lang.ClassNotFoundException 20 | 21 | Java.perform(function() { 22 | 23 | // Debug some methods 24 | 25 | var CryptoUtils = Java.use("com.target.app.CryptoUtils"); 26 | console.log("info: hooking class CryptoUtils"); 27 | var PrefUtils = Java.use("com.target.app.PrefUtils"); 28 | console.log("info: hooking class PrefUtils"); 29 | 30 | CryptoUtils.decrypt.overload("java.lang.String").implementation = function(arg0) { 31 | console.warn("\n*** entered CryptoUtils.decrypt(java.lang.String arg0)"); 32 | var retval = this.decrypt.overload("java.lang.String").call(this, arg0); 33 | console.log("\narg0: " + arg0); 34 | console.log("\nretval: " + retval); 35 | console.warn("\n*** exiting CryptoUtils.decrypt(java.lang.String arg0)"); 36 | return retval; 37 | } 38 | 39 | CryptoUtils.decrypt.overload("java.lang.String", "java.lang.String").implementation = function(arg0, arg1) { 40 | console.warn("\n*** entered CryptoUtils.decrypt(java.lang.String arg0, java.lang.String arg1)"); 41 | var retval = this.decrypt.overload("java.lang.String", "java.lang.String").call(this, arg0, arg1); 42 | console.log("\narg0: " + arg0); 43 | console.log("arg1: " + arg1); 44 | console.log("\nretval: " + retval); 45 | console.warn("\n*** exiting CryptoUtils.decrypt(java.lang.String arg0, java.lang.String arg1)"); 46 | return retval; 47 | } 48 | 49 | // overload not really necessary here 50 | CryptoUtils.genIv.overload().implementation = function() { 51 | console.warn("\n*** entered CryptoUtils.genIv()"); 52 | var retval = this.genIv.overload().call(this); 53 | console.log("\nretval: " + retval); 54 | console.warn("\n*** exiting CryptoUtils.genIv()"); 55 | // XXX print IvParameterSpec | javax.crypto.spec.IvParameterSpec 56 | return retval; 57 | } 58 | 59 | // overload not really necessary here 60 | PrefUtils.saveUser.overload("java.util.List").implementation = function(arg0) { 61 | console.warn("\n*** entered PrefUtils.saveUser(java.util.List arg0)"); 62 | var retval = this.saveUser.overload("java.util.List").call(this, arg0); 63 | console.log("\narg0: " + arg0); 64 | console.log("\nretval: " + retval); 65 | console.warn("\n*** exiting PrefUtils.saveUser(java.util.List arg0)"); 66 | return retval; 67 | } 68 | 69 | }); 70 | 71 | }, 0); 72 | -------------------------------------------------------------------------------- /raptor_frida_android_enum.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_enum.js - Java class and method enumerator 3 | * Copyright (c) 2017-2025 Marco Ivaldi 4 | * 5 | * "For all is like an ocean, all flows and connects; 6 | * touch it in one place and it echoes at the other end of the world." 7 | * -- Fyodor Dostoevsky, The Brothers Karamazov 8 | * 9 | * Frida.re JS code to enumerate Java classes and methods declared in an 10 | * Android app. See https://www.frida.re/ and https://codeshare.frida.re/ for 11 | * further information on this world-class dynamic instrumentation toolkit. 12 | * 13 | * Example usage: 14 | * $ uv tool install frida-tools 15 | * $ frida -U -f com.target.app -l raptor_frida_android_enum.js 16 | * 17 | * Tested with: 18 | * Frida 17.3.2 on macOS 15.6.1 with Redmi Note 10S (Android 11) 19 | * 20 | * Get the latest version at: 21 | * https://github.com/0xdea/frida-scripts/ 22 | */ 23 | 24 | // Enumerate all Java classes 25 | function enumAllClasses() 26 | { 27 | var allClasses = []; 28 | var classes = Java.enumerateLoadedClassesSync(); 29 | 30 | classes.forEach(function(aClass) { 31 | try { 32 | var className = aClass.match(/[L](.*);/)[1].replace(/\//g, "."); 33 | } 34 | catch(err) {return;} // Avoid TypeError: cannot read property 1 of null 35 | allClasses.push(className); 36 | }); 37 | 38 | return allClasses; 39 | } 40 | 41 | // Find all Java classes that match a pattern 42 | function findClasses(pattern) 43 | { 44 | var allClasses = enumAllClasses(); 45 | var foundClasses = []; 46 | 47 | allClasses.forEach(function(aClass) { 48 | try { 49 | if (aClass.match(pattern)) { 50 | foundClasses.push(aClass); 51 | } 52 | } 53 | catch(err) {} // Avoid TypeError: cannot read property 'match' of undefined 54 | }); 55 | 56 | return foundClasses; 57 | } 58 | 59 | // Enumerate all methods declared in a Java class 60 | function enumMethods(targetClass) 61 | { 62 | var hook = Java.use(targetClass); 63 | var ownMethods = hook.class.getDeclaredMethods(); 64 | hook.$dispose; 65 | 66 | return ownMethods; 67 | } 68 | 69 | /* 70 | * The following functions were not implemented because deemed impractical: 71 | * 72 | * enumAllMethods() - enumerate all methods declared in all Java classes 73 | * findMethods(pattern) - find all Java methods that match a pattern 74 | * 75 | * See raptor_frida_ios_enum.js for a couple of ObjC implementation examples. 76 | */ 77 | 78 | // Usage examples 79 | setTimeout(function() { // Avoid java.lang.ClassNotFoundException 80 | 81 | Java.perform(function() { 82 | 83 | // enumerate all classes 84 | /* 85 | var a = enumAllClasses(); 86 | a.forEach(function(s) { 87 | console.log(s); 88 | }); 89 | */ 90 | 91 | // find classes that match a pattern 92 | /* 93 | var a = findClasses(/password/i); 94 | a.forEach(function(s) { 95 | console.log(s); 96 | }); 97 | */ 98 | 99 | // enumerate all methods in a class 100 | /* 101 | var a = enumMethods("com.target.app.PasswordManager") 102 | a.forEach(function(s) { 103 | console.log(s); 104 | }); 105 | */ 106 | 107 | }); 108 | }, 0); 109 | -------------------------------------------------------------------------------- /raptor_frida_linux_trace.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_linux_trace.js - Function tracer for Linux 3 | * Copyright (c) 2025 Marco Ivaldi 4 | * 5 | * "Life is not like water. Things in life don't necessarily 6 | * flow over the shortest possible route." 7 | * -- Haruki Murakami, 1Q84 8 | * 9 | * Frida.re JS code to trace arbitrary function calls in a Linux ELF binary 10 | * for debugging and reverse engineering. See https://www.frida.re/ and 11 | * https://codeshare.frida.re/ for further information on this world-class 12 | * dynamic instrumentation toolkit. 13 | * 14 | * Example usage: 15 | * $ uv tool install frida-tools 16 | * $ frida -f hello-vuln -l raptor_frida_linux_trace.js 17 | * 18 | * Tested with: 19 | * Frida 17.2.1 on Ubuntu 24.0 20 | * 21 | * Get the latest version at: 22 | * https://github.com/0xdea/frida-scripts/ 23 | */ 24 | 25 | // Generic trace 26 | function trace(pattern) 27 | { 28 | var type = (pattern.toString().indexOf("!") === -1) ? "function" : "module"; 29 | 30 | // Trace exported and imported functions of shared libraries 31 | if (type === "module") { 32 | var res = new ApiResolver("module"); 33 | var matches = res.enumerateMatches(pattern); 34 | var targets = uniqBy(matches, JSON.stringify); 35 | 36 | targets.forEach(function(target) { 37 | traceFunction(target.address, target.name); 38 | }); 39 | 40 | // Trace functions in the target binary 41 | } else if (type === "function") { 42 | var targets = [] 43 | 44 | for (const f of DebugSymbol.findFunctionsMatching(pattern)) { 45 | targets.push(DebugSymbol.fromAddress(ptr(f))); 46 | } 47 | targets.forEach(function(target) { 48 | traceFunction(target.address, target.name); 49 | }); 50 | } 51 | } 52 | 53 | // Trace a function call 54 | function traceFunction(impl, name) 55 | { 56 | console.log("Tracing " + name); 57 | 58 | Interceptor.attach(impl, { 59 | 60 | onEnter: function(args) { 61 | // Trace only the intended calls 62 | this.flag = 0; 63 | //if (args[0].readUtf8String().match("AAA")) 64 | this.flag = 1; 65 | 66 | if (this.flag) { 67 | console.warn("\n*** entered " + name); 68 | 69 | // Print full backtrace 70 | console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 71 | .map(DebugSymbol.fromAddress).join("\n")); 72 | 73 | // Print caller 74 | //console.log("\nCaller: " + DebugSymbol.fromAddress(this.returnAddress)) 75 | 76 | // Print args (see https://frida.re/docs/javascript-api/#interceptor) 77 | //console.log(); 78 | //console.log("arg1: " + args[0]); 79 | //console.log("arg2: " + args[1]); 80 | //console.log("arg3: " + args[2].readUtf8String()); 81 | //console.log("arg4: " + args[3].readUtf8String()); 82 | } 83 | }, 84 | 85 | onLeave: function(retval) { 86 | if (this.flag) { 87 | // Print retval 88 | console.log("\nretval: " + retval); 89 | 90 | console.warn("\n*** exiting " + name); 91 | } 92 | } 93 | 94 | }); 95 | } 96 | 97 | // Remove duplicates from an array 98 | function uniqBy(array, key) 99 | { 100 | var seen = {}; 101 | return array.filter(function(item) { 102 | var k = key(item); 103 | return seen.hasOwnProperty(k) ? false : (seen[k] = true); 104 | }); 105 | } 106 | 107 | // Usage examples 108 | 109 | // Trace all imports 110 | //trace("imports:*!*"); 111 | 112 | // Trace potential command injection sinks 113 | //trace("imports:*!system"); 114 | //trace("imports:*!popen"); 115 | 116 | // Trace an export 117 | //trace("exports:*!snprintf"); 118 | 119 | // Trace a function that matches a glob pattern 120 | //trace("main") 121 | -------------------------------------------------------------------------------- /ios-snippets/raptor_frida_ios_stalker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_*.js - Frida script snippets for iOS 3 | * Copyright (c) 2017 Marco Ivaldi 4 | * 5 | * Frida.re JS script snippets for iOS/ObjC instrumentation. 6 | * See https://www.frida.re/ and https://codeshare.frida.re/ 7 | * for further information on this powerful tool. 8 | * 9 | * "We want to help others achieve interop through reverse 10 | * engineering" -- @oleavr 11 | * 12 | * Many thanks to Maurizio Agazzini 13 | * and Federico Dotta . 14 | * 15 | * Example usage: 16 | * # frida -U -f com.xxx.yyy -l raptor_frida_ios.js --no-pause 17 | */ 18 | 19 | // is stalker active? 20 | var active = false; 21 | 22 | // generic stalker 23 | function stalk(pattern) 24 | { 25 | var type = (pattern.indexOf(' ') === -1) ? 'module' : 'objc'; 26 | var res = new ApiResolver(type); 27 | var matches = res.enumerateMatchesSync(pattern); 28 | var targets = uniqBy(matches, JSON.stringify); 29 | 30 | targets.forEach(function(target) { 31 | stalkFunction(target.address, target.name); 32 | }); 33 | } 34 | 35 | // remove duplicates from array 36 | function uniqBy(array, key) 37 | { 38 | var seen = {}; 39 | return array.filter(function(item) { 40 | var k = key(item); 41 | return seen.hasOwnProperty(k) ? false : (seen[k] = true); 42 | }); 43 | } 44 | 45 | // actual stalker function 46 | function stalkFunction(impl, name) 47 | { 48 | console.log("Stalking " + name); 49 | 50 | Interceptor.attach(impl, { 51 | 52 | onEnter: function(args) { 53 | 54 | // return if stalker is already active 55 | if (active) 56 | return; 57 | 58 | // initialize flag 59 | var flag = {}; 60 | this.flag = flag; 61 | 62 | // activate stalker 63 | active = true; 64 | // console.warn("\n*** Stalker activated on " + name); // DEBUG 65 | 66 | Stalker.follow({ 67 | 68 | events: { 69 | call: true, // CALL instructions: yes please 70 | ret: false, // RET instructions: no thanks 71 | exec: false // all instructions: no thanks 72 | }, 73 | 74 | // onReceive: function (events) { // TODO 75 | // Called with `events` containing a binary blob which is one or more 76 | // GumEvent structs. See `gumevent.h` for the format. This is obviously a 77 | // terrible API that is subject to change once a better trade-off between 78 | // ease-of-use and performance has been found. 79 | // }, 80 | 81 | onCallSummary: function (summary) { 82 | // Called with `summary` being a key-value mapping of call target to number 83 | // of calls, in the current time window. You would typically implement this 84 | // instead of `onReceive` for efficiency. 85 | console.log(); 86 | Object.keys(summary).forEach(function (target) { 87 | console.log(name + " > " + DebugSymbol.fromAddress(ptr(target)).toString()); 88 | flag[target] = true; 89 | }); 90 | } 91 | 92 | }); 93 | }, 94 | 95 | onLeave: function(retval) { 96 | 97 | // return if no flag 98 | var flag = this.flag; 99 | if (flag === undefined) 100 | return; 101 | 102 | // deactivate stalker 103 | Stalker.unfollow(); 104 | active = false; 105 | // console.warn("*** Stalker deactivated on " + name + "\n"); // DEBUG 106 | } 107 | 108 | }); 109 | } 110 | 111 | // some examples 112 | if (ObjC.available) { 113 | 114 | // stalk("*[OWSMessageSender *]"); // Signal 115 | // stalk("-[OWSMessageSender attemptToSendMessage*]"); // Signal 116 | // stalk("-[OWSMessageSender tag]"); // Signal 117 | // stalk("*[* *Password:*]"); 118 | // stalk("exports:libSystem.B.dylib!open"); 119 | // stalk("exports:*!open*"); 120 | 121 | } else { 122 | send("error: Objective-C Runtime is not available!"); 123 | } 124 | -------------------------------------------------------------------------------- /raptor_frida_ios_enum.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_enum.js - ObjC class and method enumerator 3 | * Copyright (c) 2017-2025 Marco Ivaldi 4 | * 5 | * "For all is like an ocean, all flows and connects; 6 | * touch it in one place and it echoes at the other end of the world." 7 | * -- Fyodor Dostoevsky, The Brothers Karamazov 8 | * 9 | * Frida.re JS code to enumerate ObjC classes and methods declared in an 10 | * iOS app. See https://www.frida.re/ and https://codeshare.frida.re/ for 11 | * further information on this world-class dynamic instrumentation toolkit. 12 | * 13 | * Example usage: 14 | * $ uv tool install frida-tools 15 | * $ frida -U -f com.target.app -l raptor_frida_ios_enum.js 16 | * 17 | * Tested with: 18 | * Frida 17.3.2 on macOS 15.6.1 with iPhone 8 (iOS 16.5 + https://palera.in/) 19 | * 20 | * Get the latest version at: 21 | * https://github.com/0xdea/frida-scripts/ 22 | */ 23 | 24 | // Enumerate all ObjC classes 25 | function enumAllClasses() 26 | { 27 | var allClasses = []; 28 | 29 | for (var aClass in ObjC.classes) { 30 | if (ObjC.classes.hasOwnProperty(aClass)) { 31 | allClasses.push(aClass); 32 | } 33 | } 34 | 35 | return allClasses; 36 | } 37 | 38 | // Find all ObjC classes that match a pattern 39 | function findClasses(pattern) 40 | { 41 | var allClasses = enumAllClasses(); 42 | var foundClasses = []; 43 | 44 | allClasses.forEach(function(aClass) { 45 | if (aClass.match(pattern)) { 46 | foundClasses.push(aClass); 47 | } 48 | }); 49 | 50 | return foundClasses; 51 | } 52 | 53 | // Enumerate all methods declared in an ObjC class 54 | function enumMethods(targetClass) 55 | { 56 | var ownMethods = ObjC.classes[targetClass].$ownMethods; 57 | 58 | return ownMethods; 59 | } 60 | 61 | // Enumerate all methods declared in all ObjC classes 62 | function enumAllMethods() 63 | { 64 | var allClasses = enumAllClasses(); 65 | var allMethods = {}; 66 | 67 | allClasses.forEach(function(aClass) { 68 | enumMethods(aClass).forEach(function(method) { 69 | if (!allMethods[aClass]) allMethods[aClass] = []; 70 | allMethods[aClass].push(method); 71 | }); 72 | }); 73 | 74 | return allMethods; 75 | } 76 | 77 | // Find all ObjC methods that match a pattern 78 | function findMethods(pattern) 79 | { 80 | var allMethods = enumAllMethods(); 81 | var foundMethods = {}; 82 | 83 | for (var aClass in allMethods) { 84 | allMethods[aClass].forEach(function(method) { 85 | if (method.match(pattern)) { 86 | if (!foundMethods[aClass]) foundMethods[aClass] = []; 87 | foundMethods[aClass].push(method); 88 | } 89 | }); 90 | } 91 | 92 | return foundMethods; 93 | } 94 | 95 | // Usage examples 96 | if (ObjC.available) { 97 | 98 | // Enumerate all classes 99 | /* 100 | var a = enumAllClasses(); 101 | a.forEach(function(s) { 102 | console.log(s); 103 | }); 104 | */ 105 | 106 | // Find classes that match a pattern 107 | /* 108 | var a = findClasses(/password/i); 109 | a.forEach(function(s) { 110 | console.log(s); 111 | }); 112 | */ 113 | 114 | // Enumerate all methods in a class 115 | /* 116 | var a = enumMethods("PasswordManager") 117 | a.forEach(function(s) { 118 | console.log(s); 119 | }); 120 | */ 121 | 122 | // Enumerate all available methods 123 | // TODO: understand why this doesn't work in script, but works in REPL 124 | /* 125 | var d = enumAllMethods(); 126 | for (k in d) { 127 | console.log(k); 128 | d[k].forEach(function(s) { 129 | console.log("\t" + s); 130 | }); 131 | } 132 | */ 133 | 134 | // Find methods that match a pattern 135 | // TODO: understand why this doesn't work in script, but works in REPL 136 | /* 137 | var d = findMethods(/password/i); 138 | for (k in d) { 139 | console.log(k); 140 | d[k].forEach(function(s) { 141 | console.log("\t" + s); 142 | }); 143 | } 144 | */ 145 | 146 | } else { 147 | send("error: Objective-C Runtime is not available!"); 148 | } 149 | -------------------------------------------------------------------------------- /raptor_frida_linux_enum.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_linux_enum.js - Module/function enumerator 3 | * Copyright (c) 2025 Marco Ivaldi 4 | * 5 | * "For all is like an ocean, all flows and connects; 6 | * touch it in one place and it echoes at the other end of the world." 7 | * -- Fyodor Dostoevsky, The Brothers Karamazov 8 | * 9 | * Frida.re JS code to enumerate modules and functions present in a Linux ELF 10 | * binary. See https://www.frida.re/ and https://codeshare.frida.re/ for 11 | * further information on this world-class dynamic instrumentation toolkit. 12 | * 13 | * Example usage: 14 | * $ uv tool install frida-tools 15 | * $ frida -f hello-vuln -l raptor_frida_linux_enum.js --pause 16 | * 17 | * Tested with: 18 | * Frida 17.2.1 on Ubuntu 24.0 19 | * 20 | * Get the latest version at: 21 | * https://github.com/0xdea/frida-scripts/ 22 | */ 23 | 24 | // Enumerate all loaded modules 25 | function enumAllModules() 26 | { 27 | return Process.enumerateModules(); 28 | } 29 | 30 | // Find all loaded modules that match a pattern 31 | function findModules(pattern) 32 | { 33 | var allModules = enumAllModules(); 34 | var foundModules = []; 35 | 36 | allModules.forEach(function(aModule) { 37 | if (aModule.name.match(pattern)) { 38 | foundModules.push(aModule); 39 | } 40 | }); 41 | 42 | return foundModules; 43 | } 44 | 45 | // Enumerate all functions using the `DebugSymbol` API 46 | // NOTE: `Module.enumerateSymbols()` and `Module.findSymbolByName()` don't work 47 | function enumAllFunctions() 48 | { 49 | var allFunctions = []; 50 | 51 | for (const aFunction of DebugSymbol.findFunctionsMatching("*")) { 52 | allFunctions.push(DebugSymbol.fromAddress(ptr(aFunction))); 53 | } 54 | 55 | return allFunctions; 56 | } 57 | 58 | // Find all functions that match a glob using the `DebugSymbol` API 59 | // NOTE: `Module.enumerateSymbols()` and `Module.findSymbolByName()` don't work 60 | function findFunctions(glob) 61 | { 62 | var foundFunctions = [] 63 | 64 | for (const aFunction of DebugSymbol.findFunctionsMatching(glob)) { 65 | foundFunctions.push(DebugSymbol.fromAddress(ptr(aFunction))); 66 | } 67 | 68 | return foundFunctions; 69 | } 70 | 71 | // Enumerate all functions in a module using the `DebugSymbol` API 72 | // NOTE: `Module.enumerateSymbols()` and `Module.findSymbolByName()` don't work 73 | function enumModuleFunctions(moduleName) 74 | { 75 | var moduleFunctions = []; 76 | 77 | for (const aFunction of enumAllFunctions()) { 78 | if (aFunction.moduleName === moduleName) { 79 | moduleFunctions.push(aFunction) 80 | } 81 | } 82 | 83 | return moduleFunctions; 84 | } 85 | 86 | // Enumerate the imports of a module 87 | function enumModuleImports(moduleName) 88 | { 89 | for (const aModule of enumAllModules()) { 90 | if (aModule.name === moduleName) { 91 | return aModule.enumerateImports(); 92 | } 93 | } 94 | } 95 | 96 | // Enumerate the exports of a module 97 | function enumModuleExports(moduleName) 98 | { 99 | for (const aModule of enumAllModules()) { 100 | if (aModule.name === moduleName) { 101 | return aModule.enumerateExports(); 102 | } 103 | } 104 | } 105 | 106 | // Usage examples 107 | 108 | // Enumerate all modules 109 | /* 110 | var l = enumAllModules() 111 | l.forEach(function(m) { 112 | //console.log(m.base, m.size, m.name, m.path); 113 | console.log(m.base, m.name, m.path); 114 | }); 115 | */ 116 | 117 | // Find modules that match a pattern 118 | /* 119 | var l = findModules(/lib/i); 120 | l.forEach(function(m) { 121 | //console.log(m.base, m.size, m.name, m.path); 122 | console.log(m.base, m.name, m.path); 123 | }); 124 | */ 125 | 126 | // Enumerate all functions 127 | /* 128 | var l = enumAllFunctions() 129 | l.forEach(function(f) { 130 | //console.log(f.address, f.name, f.moduleName, f.fileName, f.lineNumber); 131 | console.log(f.toString()); 132 | }); 133 | */ 134 | 135 | // Find functions that match a glob 136 | /* 137 | var l = findFunctions("*printf*"); 138 | l.forEach(function(f) { 139 | //console.log(f.address, f.name, f.moduleName, f.fileName, f.lineNumber); 140 | console.log(f.toString()) 141 | }); 142 | */ 143 | 144 | // Enumerate all functions in a module 145 | /* 146 | var l = enumModuleFunctions("hello-vuln") 147 | l.forEach(function(f) { 148 | console.log(f); 149 | }); 150 | */ 151 | 152 | // Enumerate the imports of a module 153 | /* 154 | var l = enumModuleImports("hello-vuln"); 155 | l.forEach(function(i) { 156 | console.log(i.name); 157 | }); 158 | */ 159 | 160 | // Enumerate the exports of a module 161 | /* 162 | var l = enumModuleExports("libc.so.6"); 163 | l.forEach(function(e) { 164 | console.log(e.name); 165 | }); 166 | */ 167 | -------------------------------------------------------------------------------- /raptor_frida_ios_trace.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_ios_trace.js - ObjC and Module tracer for iOS 3 | * Copyright (c) 2017-2025 Marco Ivaldi 4 | * 5 | * "Life is not like water. Things in life don't necessarily 6 | * flow over the shortest possible route." 7 | * -- Haruki Murakami, 1Q84 8 | * 9 | * Frida.re JS code to trace arbitrary ObjC methods and Module functions calls 10 | * in an iOS app for debugging and reverse engineering. See https://www.frida.re/ 11 | * and https://codeshare.frida.re/ for further information on this world-class 12 | * dynamic instrumentation toolkit. 13 | * 14 | * Example usage: 15 | * $ uv tool install frida-tools 16 | * $ frida -U -f com.target.app -l raptor_frida_ios_trace.js 17 | * 18 | * Tested with: 19 | * Frida 17.3.2 on macOS 15.6.1 with iPhone 8 (iOS 16.5 + https://palera.in/) 20 | * 21 | * Thanks: 22 | * @inode-, @federicodotta, @mrmacete, @dankluev 23 | * 24 | * Get the latest version at: 25 | * https://github.com/0xdea/frida-scripts/ 26 | */ 27 | 28 | // Generic trace 29 | // TODO: support the "swift" type 30 | function trace(pattern) 31 | { 32 | var type = (pattern.indexOf(" ") === -1) ? "module" : "objc"; 33 | var res = new ApiResolver(type); 34 | var matches = res.enumerateMatches(pattern); 35 | var targets = uniqBy(matches, JSON.stringify); 36 | 37 | targets.forEach(function(target) { 38 | if (type === "objc") 39 | traceObjC(target.address, target.name); 40 | else if (type === "module") 41 | traceModule(target.address, target.name); 42 | }); 43 | } 44 | 45 | // Remove duplicates from array 46 | function uniqBy(array, key) 47 | { 48 | var seen = {}; 49 | return array.filter(function(item) { 50 | var k = key(item); 51 | return seen.hasOwnProperty(k) ? false : (seen[k] = true); 52 | }); 53 | } 54 | 55 | // Trace ObjC methods 56 | function traceObjC(impl, name) 57 | { 58 | console.log("Tracing " + name); 59 | 60 | Interceptor.attach(impl, { 61 | 62 | onEnter: function(args) { 63 | 64 | // Trace only the intended calls 65 | this.flag = 0; 66 | // if (ObjC.Object(args[2]).toString() === "1234567890abcdef1234567890abcdef12345678") 67 | this.flag = 1; 68 | 69 | if (this.flag) { 70 | console.warn("\n*** entered " + name); 71 | 72 | // Print full backtrace 73 | // console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 74 | // .map(DebugSymbol.fromAddress).join("\n")); 75 | 76 | // Print caller 77 | console.log("\nCaller: " + DebugSymbol.fromAddress(this.returnAddress)); 78 | 79 | // Print args 80 | if (name.indexOf(":") !== -1) { 81 | console.log(); 82 | var par = name.split(":"); 83 | par[0] = par[0].split(" ")[1]; 84 | for (var i = 0; i < par.length - 1; i++) 85 | printArg(par[i] + ": ", args[i + 2]); 86 | } 87 | } 88 | }, 89 | 90 | onLeave: function(retval) { 91 | 92 | if (this.flag) { 93 | // Print retval 94 | printArg("\nretval: ", retval); 95 | console.warn("\n*** exiting " + name); 96 | } 97 | } 98 | 99 | }); 100 | } 101 | 102 | // Trace Module functions 103 | function traceModule(impl, name) 104 | { 105 | console.log("Tracing " + name); 106 | 107 | Interceptor.attach(impl, { 108 | 109 | onEnter: function(args) { 110 | 111 | // Trace only intended calls 112 | this.flag = 0; 113 | // var filename = args[0].readCString(); 114 | // if (filename.indexOf("Bundle") === -1 && filename.indexOf("Cache") === -1) // exclusion list 115 | // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list 116 | this.flag = 1; 117 | 118 | if (this.flag) { 119 | console.warn("\n*** entered " + name); 120 | 121 | // Print backtrace 122 | console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 123 | .map(DebugSymbol.fromAddress).join("\n")); 124 | } 125 | }, 126 | 127 | onLeave: function(retval) { 128 | 129 | if (this.flag) { 130 | // Print retval 131 | printArg("\nretval: ", retval); 132 | console.warn("\n*** exiting " + name); 133 | } 134 | } 135 | 136 | }); 137 | } 138 | 139 | // Print helper 140 | // TODO: implement a safe way to print ObjC objects and especially NSStrings/CStrings 141 | function printArg(desc, arg) 142 | { 143 | /* 144 | try { 145 | console.log(desc + ObjC.Object(arg)); 146 | } 147 | catch(err) { 148 | console.log(desc + arg); 149 | } 150 | */ 151 | console.log(desc + arg); 152 | } 153 | 154 | // Usage examples 155 | if (ObjC.available) { 156 | 157 | // trace("-[CredManager setPassword:]"); 158 | // trace("*[CredManager *]"); 159 | // trace("*[* *Password:*]"); 160 | // trace("exports:libSystem.B.dylib!CCCrypt"); 161 | // trace("exports:libSystem.B.dylib!open"); 162 | // trace("exports:*!open*"); 163 | 164 | } else { 165 | send("error: Objective-C Runtime is not available!"); 166 | } 167 | -------------------------------------------------------------------------------- /raptor_frida_android_trace.js: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_frida_android_trace.js - Java/Module tracer for Android 3 | * Copyright (c) 2017-2025 Marco Ivaldi 4 | * 5 | * "Life is not like water. Things in life don't necessarily 6 | * flow over the shortest possible route." 7 | * -- Haruki Murakami, 1Q84 8 | * 9 | * Frida.re JS code to trace arbitrary Java methods and Module functions calls 10 | * in an Android app for debugging and reverse engineering. See https://www.frida.re/ 11 | * and https://codeshare.frida.re/ for further information on this world-class 12 | * dynamic instrumentation toolkit. 13 | * 14 | * Example usage: 15 | * $ uv tool install frida-tools 16 | * $ frida -U -f com.target.app -l raptor_frida_android_trace.js 17 | * 18 | * Tested with: 19 | * Frida 17.3.2 on macOS 15.6.1 with Redmi Note 10S (Android 11) 20 | * 21 | * Thanks: 22 | * @inode-, @federicodotta, @leonjza, @dankluev 23 | * 24 | * Get the latest version at: 25 | * https://github.com/0xdea/frida-scripts/ 26 | */ 27 | 28 | // Generic trace 29 | function trace(pattern) 30 | { 31 | var type = (pattern.toString().indexOf("!") === -1) ? "java" : "module"; 32 | 33 | if (type === "module") { 34 | 35 | // trace Module 36 | var res = new ApiResolver("module"); 37 | var matches = res.enumerateMatches(pattern); 38 | var targets = uniqBy(matches, JSON.stringify); 39 | targets.forEach(function(target) { 40 | traceModule(target.address, target.name); 41 | }); 42 | 43 | } else if (type === "java") { 44 | 45 | // Trace Java class 46 | var found = false; 47 | Java.enumerateLoadedClasses({ 48 | onMatch: function(aClass) { 49 | if (aClass.match(pattern)) { 50 | found = true; 51 | try { 52 | var className = aClass.match(/[L](.*);/)[1].replace(/\//g, "."); 53 | } 54 | catch(err) {return;} // Avoid TypeError: cannot read property 1 of null 55 | traceClass(className); 56 | } 57 | }, 58 | onComplete: function() {} 59 | }); 60 | 61 | // Trace Java method 62 | if (!found) { 63 | try { 64 | traceMethod(pattern); 65 | } 66 | catch(err) { // Catch non-existing classes/methods 67 | console.error(err); 68 | } 69 | } 70 | } 71 | } 72 | 73 | // Find and trace all methods declared in a Java class 74 | function traceClass(targetClass) 75 | { 76 | var hook = Java.use(targetClass); 77 | var methods = hook.class.getDeclaredMethods(); 78 | hook.$dispose; 79 | 80 | var parsedMethods = []; 81 | methods.forEach(function(method) { 82 | parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]); 83 | }); 84 | 85 | var targets = uniqBy(parsedMethods, JSON.stringify); 86 | targets.forEach(function(targetMethod) { 87 | traceMethod(targetClass + "." + targetMethod); 88 | }); 89 | } 90 | 91 | // Trace a specific Java method 92 | function traceMethod(targetClassMethod) 93 | { 94 | var delim = targetClassMethod.lastIndexOf("."); 95 | if (delim === -1) return; 96 | 97 | var targetClass = targetClassMethod.slice(0, delim) 98 | var targetMethod = targetClassMethod.slice(delim + 1, targetClassMethod.length) 99 | 100 | var hook = Java.use(targetClass); 101 | var overloadCount = hook[targetMethod].overloads.length; 102 | 103 | console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]"); 104 | 105 | for (var i = 0; i < overloadCount; i++) { 106 | 107 | hook[targetMethod].overloads[i].implementation = function() { 108 | console.warn("\n*** entered " + targetClassMethod); 109 | 110 | // Print backtrace 111 | // Java.perform(function() { 112 | // var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()); 113 | // console.log("\nBacktrace:\n" + bt); 114 | // }); 115 | 116 | // Print args 117 | // TODO: double check this works without the occasional crash 118 | if (arguments.length) console.log(); 119 | for (var j = 0; j < arguments.length; j++) { 120 | console.log("arg[" + j + "]: " + arguments[j]); 121 | } 122 | 123 | // Print retval 124 | var retval = this[targetMethod].apply(this, arguments); // Rare crash (Frida bug?) 125 | console.log("\nretval: " + retval); 126 | console.warn("\n*** exiting " + targetClassMethod); 127 | return retval; 128 | } 129 | } 130 | } 131 | 132 | // Trace Module functions 133 | function traceModule(impl, name) 134 | { 135 | console.log("Tracing " + name); 136 | 137 | Interceptor.attach(impl, { 138 | 139 | onEnter: function(args) { 140 | 141 | // Trace only intended calls 142 | this.flag = false; 143 | // var filename = args[0].readCString(); 144 | // if (filename.indexOf("XYZ") === -1 && filename.indexOf("ZYX") === -1) // exclusion list 145 | // if (filename.indexOf("my.interesting.file") !== -1) // inclusion list 146 | this.flag = true; 147 | 148 | if (this.flag) { 149 | console.warn("\n*** entered " + name); 150 | 151 | // Print backtrace 152 | // TODO: understand why this crashes sometimes 153 | // console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) 154 | // .map(DebugSymbol.fromAddress).join("\n")); 155 | } 156 | }, 157 | 158 | onLeave: function(retval) { 159 | 160 | if (this.flag) { 161 | // Print retval 162 | console.log("\nretval: " + retval); 163 | console.warn("\n*** exiting " + name); 164 | } 165 | } 166 | 167 | }); 168 | } 169 | 170 | // Remove duplicates from array 171 | function uniqBy(array, key) 172 | { 173 | var seen = {}; 174 | return array.filter(function(item) { 175 | var k = key(item); 176 | return seen.hasOwnProperty(k) ? false : (seen[k] = true); 177 | }); 178 | } 179 | 180 | // Usage examples 181 | setTimeout(function() { // Avoid java.lang.ClassNotFoundException 182 | 183 | Java.perform(function() { 184 | 185 | // trace("com.target.utils.CryptoUtils.decrypt"); 186 | // trace("android.os.storage.StorageVolume"); 187 | // trace("com.target.utils.CryptoUtils"); 188 | // trace("CryptoUtils"); 189 | // trace(/crypto/i); 190 | // trace("exports:*!open*"); 191 | 192 | }); 193 | }, 0); 194 | --------------------------------------------------------------------------------