Skip to content
Merged
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
50 changes: 28 additions & 22 deletions .github/instructions/mastg-frida-scripts.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ This guide defines how to write and use Frida scripts in MASTG demos. Scripts li

**Note:** Prefer Frooky hooks over Frida scripts where possible, as they require less code. See `mastg-frooky-scripts.instructions.md` for details.

Version requirement

- Use Frida 17 or later. See @MASTG-TOOL-0031 ([Frida 17](https://mas.owasp.org/MASTG/tools/generic/MASTG-TOOL-0031/#frida-17)

## Location and naming

- Place scripts inside the demo folder and name them `script.js` unless multiple scripts are needed.
Expand All @@ -36,6 +32,34 @@ Examples:
- Backtraces: use `DebugSymbol.fromAddress` and cap lines.
- In `onEnter/onLeave`, capture context first (for example, `const ctx = this.context;`) before using nested arrow functions.

## Use and Validation of Frida APIs

When writing new Frida scripts for MASTG demos, always validate against the latest [frida-gum typings](https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/refs/heads/master/types/frida-gum/index.d.ts) (human-readable version: [JavaScript API](https://frida.re/docs/javascript-api/)).

Consider the following key changes introduced in Frida 17 and if you encounter any of the old APIs in existing scripts, update them accordingly:

| Area | Before Frida 17 | Frida 17 and later | Notes |
| -------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| Global exports | `Module.getExportByName(null, "open")` and `Module.findExportByName(null, "open")` | `Module.getGlobalExportByName("open")` and `Module.findGlobalExportByName("open")` | Global lookups are now explicit. `get*` throws if missing, `find*` returns null. |
| Global symbol special case | `Module.getSymbolByName(null, "open")` | `Module.getGlobalExportByName("open")` | Only the null module symbol case maps to global exports. Not a general symbol replacement. |
| Module exports | `Module.getExportByName("libc.so", "open")` and `Module.findExportByName("libc.so", "open")` | `Process.getModuleByName("libc.so").getExportByName("open")` and `Process.getModuleByName("libc.so").findExportByName("open")` | Static helpers removed. Use a `Module` instance. `get*` throws, `find*` returns null. |
| Module symbols | `Module.getSymbolByName("libart.so", "ExecuteNterpImpl")` | `Process.getModuleByName("libart.so").getSymbolByName("ExecuteNterpImpl")` | Symbol lookup still exists but only on `Module` instances, not statically and not on pointers. |
| Module base | `Module.getBaseAddress("libc.so")` | `Process.getModuleByName("libc.so").base` | Base address helpers removed. Base is a property of a `Module` instance. |
| Module initialization | `Module.ensureInitialized("libobjc.A.dylib")` | `Process.getModuleByName("libobjc.A.dylib").ensureInitialized()` | Static initializer removed. Instance method ensures initializers have run for that module. |
| Enumeration | `Process.enumerateModules({ onMatch, onComplete })` | `Process.enumerateModules()` | Callback based enumeration removed. Now returns arrays. Same model for threads and ranges. |
| Memory access | `Memory.read*`, `Memory.write*`, `Memory.readUtf8String`, `Memory.writeUtf8String`, `Memory.readByteArray`, `Memory.writeByteArray` | `ptr.read*`, `ptr.write*`, `ptr.readUtf8String()`, `ptr.writeUtf8String()`, `ptr.readByteArray()`, `ptr.writeByteArray()` | All memory read and write helpers moved onto `NativePointer` instances, including numeric reads and writes, strings, and byte arrays. The `Memory.*` forms are replaced by instance methods on the pointer you want to access. |

Here's one example of updating code for Frida 17 that can serve as a reference: <https://patch-diff.githubusercontent.com/raw/AloneMonkey/frida-ios-dump/pull/200.diff>.

**Using ObjC and Java runtime bridges in Frida 17+:**

The Frida scripts we're creating for MASTG demos are meant to be run with the Frida CLI, so you can keep using the `ObjC` and `Java` runtime bridges as before. However, be aware that starting with Frida 17, these APIs are no longer part of the [frida-gum typings](https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/refs/heads/master/types/frida-gum/index.d.ts). The Frida CLI pre-bundles these runtime bridges for you.

For more details, see:

- <https://mas.owasp.org/MASTG/tools/generic/MASTG-TOOL-0031/#frida-17>
- <https://frida.re/news/2025/05/17/frida-17-0-0-released/>

## Inspiration

- Don't reinvent the wheel when something already exists. Use existing open-source sources when available, for example, <https://codeshare.frida.re/browse>.
Expand All @@ -55,24 +79,6 @@ var config = {
...
```

```js
// SOURCE: https://github.com/iddoeldor/frida-snippets?tab=readme-ov-file#os-log

var m = 'libsystem_trace.dylib';
// bool os_log_type_enabled(os_log_t oslog, os_log_type_t type);
var isEnabledFunc = Module.findExportByName(m, 'os_log_type_enabled');
// _os_log_impl(void *dso, os_log_t log, os_log_type_t type, const char *format, uint8_t *buf, unsigned int size);
var logFunc = Module.findExportByName(m, '_os_log_impl');

// Enable all logs
Interceptor.attach(isEnabledFunc, {
onLeave: function (ret) {
ret.replace(0x1);
}
});
...
```

## Logging and outputs

- Redirect script output to `output.txt` from `run.sh`.
Expand Down
12 changes: 9 additions & 3 deletions tools/generic/MASTG-TOOL-0031.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Frida 17 introduces [breaking changes](https://frida.re/news/2025/05/17/frida-17

**Bridges:**

Frida 17 removes the bundled [runtime bridges](https://frida.re/docs/bridges/) (`frida-{objc,swift,java}-bridge`) within Frida's GumJS runtime. When you use the commands `frida` and `frida-trace`, this doesn't have any noticeable impact, as they come with the Java, Objective-C, and Swift bridges pre-bundled, so you can still use them as before.
Frida 17 removes the bundled [runtime bridges](https://frida.re/docs/bridges/) (`frida-{objc,swift,java}-bridge`) within Frida's GumJS runtime. When you use CLI tools such as `frida`, `frida-trace` or @MASTG-TOOL-0145, this doesn't have any noticeable impact, as they come with the Java, Objective-C, and Swift bridges pre-bundled, so you can still use them as before.

However, if you are writing your own custom Frida-based tooling or scripts that depend on these bridges, you will now need to install them separately via `frida-pm`, Frida's package manager. For example, to install the Java bridge, run:

Expand All @@ -76,7 +76,9 @@ npx frida-compile -o agent.js -o _agent.js

**API Changes:**

Frida has made changes to its native APIs. While these changes may break some of your existing scripts, they encourage you to write more readable and performant code. For instance, now, `Process.enumerateModules()` returns an array of `Module` objects, allowing you to work with them directly.
Frida has made changes to its native APIs. While these changes may break some of your existing scripts, they encourage you to write more readable and performant code. See a full overview in the [MASTG Frida scripts writing guide](https://mas.owasp.org/contributing/writing-content/mastg-frida-scripts.instructions#use-and-validation-of-frida-apis).

For instance, now, `Process.enumerateModules()` returns an array of `Module` objects, allowing you to work with them directly.

```js
for (const module of Process.enumerateModules()) {
Expand All @@ -94,7 +96,11 @@ Process.getModuleByName('libc.so').getExportByName('open')
Module.getGlobalExportByName('open');
```

For more details, refer to the [Frida 17.0.0 Release Notes](https://frida.re/news/2025/05/17/frida-17-0-0-released/).
For more details, see:

- the [Frida 17.0.0 Release Notes](https://frida.re/news/2025/05/17/frida-17-0-0-released/)
- the [updated Frida JavaScript API documentation](https://frida.re/docs/javascript-api/)
- the [frida-gum typings](https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/refs/heads/master/types/frida-gum/index.d.ts)

## Tools

Expand Down