-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
Follow-up from: #3359
The current script supports Java-level hooking using Frida’s Java API. This covers most use cases during mobile app penetration testing, 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.
To handle these cases, the script must support Frida's Interceptor
API, which allows hooking into native functions in shared libraries (e.g., .so
files).
Why This Is Needed:
- Many apps offload sensitive logic (e.g., crypto, certificate pinning, JNI wrappers) to native code.
- Without native hooking, we miss a large surface area, including custom implementations not visible in the Java layer.
- Full coverage during dynamic analysis and reverse engineering requires both Java and native hooks.
Proposed Behavior:
- Allow
hooks.js
definitions to optionally target native functions. - New hook type for native entries, e.g.:
{
category: "NATIVE_CRYPTO",
hooks: [
{
native: true,
module: "libcrypto.so",
symbol: "AES_encrypt"
}
]
}
- The base script detects if
native: true
is present and usesModule.findExportByName
andInterceptor.attach
accordingly.
Benefits:
- Enables analysis of hybrid apps and native-heavy implementations.
- Complements Java hooks for deeper coverage.
- Aligns with real-world testing needs where native code is commonly involved in critical operations.
This feature ensures the script is versatile enough for both high-level and low-level instrumentation during mobile assessments.
Use Case Example: MASTG-DEMO-0002
https://mas.owasp.org/MASTG/demos/android/MASVS-STORAGE/MASTG-DEMO-0002/MASTG-DEMO-0002/
In this demo, the app creates files in external storage using both Java APIs (ContentResolver.insert
). However, internally, the system also calls native methods (open
from libc.so
). The current script mixes both Java and native hooks manually.
Java hook:
let ContentResolver = Java.use("android.content.ContentResolver");
ContentResolver.insert.overload('android.net.Uri', 'android.content.ContentValues').implementation = ...
Native hook:
Interceptor.attach(
Process.getModuleByName('libc.so').getExportByName('open'),
{
onEnter: function(args) {
const path = args[0].readCString();
if (path.startsWith('/sdcard')) {
console.log(path);
}
}
}
);
Instead, we want to define this in hooks.js
like:
var target = {
category: "STORAGE",
demo: "0002",
hooks: [
{
class: "android.content.ContentResolver",
method: "insert",
overloads: [
{
args: ["android.net.Uri", "android.content.ContentValues"]
}
]
},
{
native: true,
module: "libc.so",
symbol: "open",
filter: {
arg1: ["/sdcard", "/storage/emulated"]
},
maxFrames: 15
}
]
}
Behavior:
- Native hooks are specified with
native: true
, amodule
, and asymbol
. - Optional fields like
filter
andmaxFrames
provide control over when and how to log. - The base script handles attaching via
Interceptor
, decoding arguments, and printing stack traces.