Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ try {
Interceptor.attach(libc.getExportByName("connect"), {
onEnter: function(args) {
try{
var memory = Memory.readByteArray(args[1], 64);
var memory = args[1].readByteArray(64);
var b = new Uint8Array(memory);
if (b[2] == 0x69 && b[3] == 0xa2 && b[4] == 0x7f && b[5] == 0x00 && b[6] == 0x00 && b[7] == 0x01) {
this.frida_detection = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ Java.performNow(function () {
Interceptor.attach(libc.getExportByName("fopen"), {
onEnter: function (args) {
try{
var path = Memory.readCString(args[0]);
var path = args[0].readCString();
path = path.split("/");
var executable = path[path.length - 1];
var shouldFakeReturn = (RootBinaries.indexOf(executable) > -1)
Expand All @@ -229,7 +229,7 @@ Java.performNow(function () {
Interceptor.attach(libc.getExportByName("system"), {
onEnter: function (args) {
try{
var cmd = Memory.readCString(args[0]);
var cmd = args[0].readCString();
send("[RootDetection Bypass] SYSTEM CMD: " + cmd);
if (cmd.indexOf("getprop") != -1 || cmd == "mount" || cmd.indexOf("build.prop") != -1 || cmd == "id") {
send("[RootDetection Bypass] native system: " + cmd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Java.perform(function ()
var libName = f.getName()
console.log("Native lib name: " + libName)

var exports = Module.enumerateExportsSync(libName)
var exports = Process.getModuleByName(libName).enumerateExports()
console.log("Exported methods:")

if (exports === undefined || exports.length == 0)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Source: https://github.com/apkunpacker/FridaScripts
// Updated for Frida 17.0.0+ compatibility
var Duplicate = [];
Module.enumerateExportsSync("libart.so").forEach(function(exp) {
Process.getModuleByName("libart.so").enumerateExports().forEach(function(exp) {
if (exp.name.indexOf("ClassLinker") != -1 && exp.name.indexOf("FindClassE") != -1) {
Interceptor.attach(exp.address, {
onEnter: function(args) {
this.name = Memory.readCString(args[2]);
this.name = args[2].readCString();
},
onLeave: function(retval) {
if (Duplicate.indexOf(this.name) >= 0) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ Java.perform(function () {
}
});

send("[] Hook installed on libc open()");
send("[+] Hook installed on libc open()");
} catch (e) {
send("[] Error hooking libc open: " + e);
send("[-] Error hooking libc open: " + e);
}
});
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ setTimeout(function() {
return ret;
};
netBuilder.addPublicKeyPins.implementation = function(hostName, pinsSha256, includeSubdomains, expirationDate) {
console.log("[+] Сronet addPublicKeyPins hostName = " + hostName);
console.log("[+] Cronet addPublicKeyPins hostName = " + hostName);
return this;
};
} catch (err) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ try {
const libc = Process.getModuleByName("libc.so");
Interceptor.attach(libc.getExportByName("system"), {
onEnter: function(args) {
var cmd = Memory.readCString(args[0]);
var cmd = args[0].readCString();
if (cmd.indexOf("kill") != -1) {
console.log("Bypass native system: " + cmd);
var NewKill = args[0].writeUtf8String("bypassed");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ Java.perform(function () {
const path = TraceSysFD["fd-" + fd] || "[unknown path]";
let data = null;
try {
data = Memory.readByteArray(bfr, sz);
data = bfr.readByteArray(sz);
} catch (_) {
data = null;
}
Expand Down Expand Up @@ -344,7 +344,7 @@ Java.perform(function () {
const path = TraceSysFD["fd-" + fd] || "[unknown path]";
let data = null;
try {
data = Memory.readByteArray(bfr, sz);
data = bfr.readByteArray(sz);
} catch (_) {
data = null;
}
Expand Down
119 changes: 76 additions & 43 deletions mobsf/DynamicAnalyzer/tools/frida_scripts/ios/auxiliary/class-trace.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,82 @@
/* Description: Hook all the methods of a particular class
* Mode: S+A
* Version: 1.0
* Credit: https://github.com/interference-security/frida-scripts/blob/master/iOS
* Author: @interference-security
*/
//Twitter: https://twitter.com/xploresec
//GitHub: https://github.com/interference-security
function hook_class_method(class_name, method_name)
{
var hook = ObjC.classes[class_name][method_name];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
send("[AUXILIARY] Detected call to: " + class_name + " -> " + method_name);
}
});
}
function hook_class_method(className, methodName) {
try {
const method = ObjC.classes[className][methodName];
const impl = method?.implementation;

if (!impl || impl.isNull()) {
send(`⚠️ Skipping ${methodName} — no implementation.`);
return;
}

Interceptor.attach(impl, {
onEnter: function (args) {
send(`[AUXILIARY] Detected call to: ${className} -> ${methodName}`);

function run_hook_all_methods_of_specific_class(className_arg)
{
send("Started: Hook all methods of a specific class");
send("Class Name: " + className_arg);
//Your class name here
var className = className_arg;
//var methods = ObjC.classes[className].$methods;
var methods = ObjC.classes[className].$ownMethods;
for (var i = 0; i < methods.length; i++)
{
send("[AUXILIARY] [-] "+methods[i]);
send("[AUXILIARY] \t[*] Hooking into implementation");
//eval('var className2 = "'+className+'"; var funcName2 = "'+methods[i]+'"; var hook = eval(\'ObjC.classes.\'+className2+\'["\'+funcName2+\'"]\'); Interceptor.attach(hook.implementation, { onEnter: function(args) { console.log("[*] Detected call to: " + className2 + " -> " + funcName2); } });');
var className2 = className;
var funcName2 = methods[i];
hook_class_method(className2, funcName2);
// send("[AUXILIARY] \t[*] Hooking successful");
}
send("[AUXILIARY] Completed: Hook all methods of a specific class");
for (let i = 0; i < method.argumentTypes.length; i++) {
try {
const arg = args[i];
if (arg.isNull && arg.isNull()) {
send(`[AUXILIARY] arg[${i}]: null`);
} else {
try {
const str = arg.readUtf8String();
send(`[AUXILIARY] arg[${i}]: "${str}"`);
} catch {
send(`[AUXILIARY] arg[${i}]: ${arg}`);
}
}
} catch (err) {
send(`[AUXILIARY] arg[${i}]: <error reading: ${err.message}>`);
}
}
},

onLeave: function (retval) {
try {
if (retval.isNull && retval.isNull()) {
send(`[AUXILIARY] return: null`);
} else {
send(`[AUXILIARY] return: ${retval}`);
}
} catch (err) {
send(`[AUXILIARY] return: <error reading: ${err.message}>`);
}
}
});
} catch (err) {
send(`❌ Failed to hook ${className} -> ${methodName}: ${err.message}`);
}
}

function hook_all_methods_of_specific_class(className_arg)
{
try {
setImmediate(run_hook_all_methods_of_specific_class,[className_arg])
} catch(err) {}
function run_hook_all_methods_of_specific_class(className) {
send(`📦 Started hooking all methods of: ${className}`);

try {
if (!ObjC.classes.hasOwnProperty(className)) {
send(`❌ Class not found: ${className}`);
return;
}

const methods = ObjC.classes[className].$ownMethods;

for (const methodName of methods) {
send(`[AUXILIARY] Hooking: ${methodName}`);
hook_class_method(className, methodName);
}

send("✅ Completed hooking all methods.");
} catch (err) {
send(`❌ Error while hooking class: ${err.message}`);
}
}

function hook_all_methods_of_specific_class(classNameArg) {
try {
setImmediate(run_hook_all_methods_of_specific_class, classNameArg);
} catch (err) {
send(`❌ Unexpected error: ${err.message}`);
}
}

//Your class name goes here
hook_all_methods_of_specific_class('{{CLASS}}')
// Replace '{{CLASS}}' with the class name you want to hook
hook_all_methods_of_specific_class('{{CLASS}}');
Original file line number Diff line number Diff line change
@@ -1,54 +1,68 @@
/* Description: Dump all methods inside classes owned by the app only
* Mode: S+A
* Version: 1.0
* Credit: PassionFruit (https://github.com/chaitin/passionfruit/blob/master/agent/app/classdump.js) & https://github.com/interference-security/frida-scripts/blob/master/iOS
* Author: @interference-security
*/
//Twitter: https://twitter.com/xploresec
//GitHub: https://github.com/interference-security
// Modified to support Frida 17.0.0+

function run_show_app_classes_methods_only()
{
send("Started: Find App's Classes and Methods")
var free = new NativeFunction(Module.getGlobalExportByName('free'), 'void', ['pointer'])
var copyClassNamesForImage = new NativeFunction(Module.getGlobalExportByName('objc_copyClassNamesForImage'), 'pointer', ['pointer', 'pointer'])
var p = Memory.alloc(Process.pointerSize)
p.writeUInt(0)
var path = ObjC.classes.NSBundle.mainBundle().executablePath().UTF8String()
var pPath = Memory.allocUtf8String(path)
var pClasses = copyClassNamesForImage(pPath, p)
var count = p.readUInt()
var classesArray = new Array(count)
for (var i = 0; i < count; i++)
{
var pClassName = pClasses.add(i * Process.pointerSize).readPointer()
classesArray[i] = pClassName.readUtf8String()
var className = classesArray[i]
send("[AUXILIARY] Class: " + className);
//var methods = ObjC.classes[className].$methods;
var methods = ObjC.classes[className].$ownMethods;
for (var j = 0; j < methods.length; j++)
{
send("[AUXILIARY] \t[-] Method: " + methods[j]);
try
{
send("[AUXILIARY] \t\t[-] Arguments Type: " + ObjC.classes[className][methods[j]].argumentTypes);
send("[AUXILIARY] \t\t[-] Return Type: " + ObjC.classes[className][methods[j]].returnType);
function run_show_app_classes_methods_only() {
send("Started: Find App's Classes and Methods");

try {
const free = new NativeFunction(
Process.getModuleByName('libc++abi.dylib').getExportByName('free'),
'void',
['pointer']
);

const copyClassNamesForImage = new NativeFunction(
Process.getModuleByName('libobjc.A.dylib').getExportByName('objc_copyClassNamesForImage'),
'pointer',
['pointer', 'pointer']
);

const path = ObjC.classes.NSBundle.mainBundle().executablePath().UTF8String();
const pPath = Memory.allocUtf8String(path);
const pCount = Memory.alloc(Process.pointerSize);
pCount.writeUInt(0);

const pClasses = copyClassNamesForImage(pPath, pCount);
const count = pCount.readUInt();

send(`[AUXILIARY] Classes found in app image: ${count}`);

for (let i = 0; i < count; i++) {
const classPtr = pClasses.add(i * Process.pointerSize).readPointer();
const className = classPtr.readUtf8String();

if (!ObjC.classes.hasOwnProperty(className)) {
continue;
}

const klass = ObjC.classes[className];
send(`[AUXILIARY] Class: ${className}`);

const methods = klass.$ownMethods;
for (const methodName of methods) {
send(` [-] Method: ${methodName}`);

try {
const method = klass[methodName];
send(` ├─ Args: ${method.argumentTypes}`);
send(` └─ Return: ${method.returnType}`);
} catch (err) {
send(` ⚠️ Failed to inspect method: ${err.message}`);
}
}
catch(err) {}
}

free(pClasses);
} catch (err) {
send(`❌ Error: ${err.message}`);
}
free(pClasses)
send("App Classes found: " + count);
send("Completed: Find App's Classes")

send("Completed: Find App's Classes");
}

function show_app_classes_methods_only()
{
function show_app_classes_methods_only() {
try {
setImmediate(run_show_app_classes_methods_only)
} catch(err) {}
setImmediate(run_show_app_classes_methods_only);
} catch (err) {
send(`❌ Unexpected error: ${err.message}`);
}
}

show_app_classes_methods_only()
show_app_classes_methods_only();
Loading
Loading