Skip to content

[Frida Util] Add Support for Interceptor to Hook Native Methods #3384

@cpholguera

Description

@cpholguera

Follow-up from: #3359

The current version of the Frida Util, located in utils/frida/ and used from demos having hooks.js files, supports Java-level hooking using Frida's Java API. This covers most use cases during mobile app penetration testing on Android, especially when working with Java or Kotlin code. However, many critical security-related operations are implemented in native libraries, especially in apps that rely on custom cryptography, native obfuscation, or performance-critical code. And we also need support for iOS apps.

To handle these cases, the script must support Frida's Interceptor API, which allows hooking into native functions.

Proposed Behavior:

  • Allow hooks.js definitions to optionally target native functions.
  • New hook type for native entries, e.g.:
{
  category: "CRYPTO",
  hooks: [
    {
      native: true,
      module: "libcrypto.so",
      symbol: "AES_encrypt"
    }
  ]
}
  • The base script detects if native: true is present and uses Interceptor.attach accordingly.
    • If the module is known it uses Process.getModuleByName(module).getExportByName(symbol)
    • Otherwise, Module.getGlobalExportByName(symbol)

Notes:

  • Feel free to suggest a more efficient way of defining the hooks if there is one.
  • Feel free to restructure the tool un utils/

Use Case Example 1

An app that calls the native method open from libc.so.

Native hook:

Interceptor.attach(
    Process.getModuleByName('libc.so').getExportByName('open'),
    {
        onEnter: function(args) {
            const path = args[0].readCString();
            console.log(path);
        }
    }
);

Instead, we want to define this in hooks.js like (along other different hooks):

var target = {
  category: "STORAGE",
  hooks: [
    {
      class: "android.content.ContentResolver",
      method: "insert",
      overloads: [
        {
          args: ["android.net.Uri", "android.content.ContentValues"]
        }
      ]
    },
    {
      native: true,
      module: "libc.so",
      symbol: "open",
      maxFrames: 15
    }
  ]
}

Use Case Example 2

Swift hook:

Interceptor.attach(Module.getGlobalExportByName('SecAccessControlCreateWithFlags'), {
  onEnter(args) {
    const flags = args[2]
    const flags_description = parseAccessControlFlags(flags)
    console.log(`\SecAccessControlCreateWithFlags(..., 0x${flags.toString(16)}) called with ${flags_description}\n`)
    ...
  }
});

Instead, we want to define this in hooks.js like:

var target = {
  category: "AUTH",
  hooks: [
    {
      native: true,
      symbol: "SecAccessControlCreateWithFlags",
      maxFrames: 15
    }
  ]
}

Use Case Example: MASTG-DEMO-0042

ObjC hook:

Interceptor.attach(ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"].implementation, {
  onEnter(args) {
      const policy = args[2].toInt32();
      console.log(`\nLAContext.canEvaluatePolicy(${args[2]}) called\n`);
    ...
  }
});

Instead, we want to define this in hooks.js like:

var target = {
  category: "AUTH",
  hooks: [
    {
      native: true,
      objClass: "LAContext"
      symbol: "- evaluatePolicy:localizedReason:reply:",
      maxFrames: 15
    }
  ]
}

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions