Frida 17 compatibility: migrate from removed Module.findExportByName#1
Frida 17 compatibility: migrate from removed Module.findExportByName#1ymuuuu wants to merge 2 commits into
Conversation
- mono-module.js: Module.findExportByName(null, ...) -> Module.findGlobalExportByName(...) - mono-api.js: switch to module-instance findExportByName() - README: banner about Frida 17 compatibility branch Frida 17.0.0 (May 2025) removed Module.findExportByName and the rest of the static Module.* helpers. Instance-method lookups are now the only supported form for module-scoped resolution; findGlobalExportByName replaces the null-as-first-arg form for module-agnostic export lookup.
There was a problem hiding this comment.
Pull request overview
This PR updates frida-mono-api to remain compatible with Frida 17 by replacing removed static Module.* export-lookup helpers with supported alternatives, preventing module-load crashes when running under Frida 17.x.
Changes:
- Replace
Module.findExportByName(null, ...)withModule.findGlobalExportByName(...)for module-agnostic Mono runtime detection. - Replace
Module.findExportByName(monoModule.name, ...)with the instance methodmonoModule.findExportByName(...)when binding Mono exports. - Add README context explaining the Frida 17 compatibility migration.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/mono-module.js | Updates Mono runtime detection to use Frida 17-supported global export lookup. |
| src/mono-api.js | Updates export binding to use the Module instance findExportByName method. |
| README.md | Documents the Frida 17 compatibility purpose and links to upstream release notes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| > **Frida 17 compatibility (community contribution)** — this `frida-17` branch ports the | ||
| > `frida-mono-api` runtime detection to Frida 17.x's new `Module` API. The original code | ||
| > calls `Module.findExportByName(...)`, which was removed in Frida 17.0.0 (May 2025). | ||
| > Submitted as a small contribution to the GoSecure tooling that powers | ||
| > [frida-xamarin-unpin](https://github.com/GoSecure/frida-xamarin-unpin). See the upstream | ||
| > [Frida 17.0.0 release notes](https://frida.re/news/2025/05/17/frida-17-0-0-released/) for | ||
| > the full migration guide. |
There was a problem hiding this comment.
This new intro says the branch ports only "runtime detection", but this PR also changes export resolution/binding in src/mono-api.js (switching to monoModule.findExportByName). Update the wording to reflect the broader Frida 17 compatibility change so readers don’t miss the API-side migration.
| > **Frida 17 compatibility (community contribution)** — this `frida-17` branch ports the | |
| > `frida-mono-api` runtime detection to Frida 17.x's new `Module` API. The original code | |
| > calls `Module.findExportByName(...)`, which was removed in Frida 17.0.0 (May 2025). | |
| > Submitted as a small contribution to the GoSecure tooling that powers | |
| > [frida-xamarin-unpin](https://github.com/GoSecure/frida-xamarin-unpin). See the upstream | |
| > [Frida 17.0.0 release notes](https://frida.re/news/2025/05/17/frida-17-0-0-released/) for | |
| > the full migration guide. | |
| > **Frida 17 compatibility (community contribution)** — this `frida-17` branch updates | |
| > `frida-mono-api` for Frida 17.x's new `Module` API, including both runtime detection and | |
| > API-side export resolution/binding changes. In particular, the original code relied on | |
| > `Module.findExportByName(...)`, which was removed in Frida 17.0.0 (May 2025), so export | |
| > lookup now needs to be resolved through the loaded module (for example, | |
| > `monoModule.findExportByName(...)`). Submitted as a small contribution to the GoSecure | |
| > tooling that powers [frida-xamarin-unpin](https://github.com/GoSecure/frida-xamarin-unpin). | |
| > See the upstream [Frida 17.0.0 release notes](https://frida.re/news/2025/05/17/frida-17-0-0-released/) | |
| > for the full migration guide. |
| else { | ||
| const addr = Module.findExportByName(monoModule.name, exportName) | ||
| const addr = monoModule.findExportByName(exportName) | ||
| MonoApi[exportName] = !addr |
There was a problem hiding this comment.
The loop uses Object.keys(MonoApi).map(...) for side-effects (initializing MonoApi[exportName]), which allocates an unused array. Prefer forEach or a for...of loop over Object.keys(...) to avoid the extra allocation and make the intent explicit.
| const addr = monoModule.findExportByName(exportName) | ||
| MonoApi[exportName] = !addr | ||
| ? () => { throw new Error('Export not found: ' + exportName) } | ||
| : MonoApi[exportName] = new ExNativeFunction(addr, ...MonoApi[exportName]) |
There was a problem hiding this comment.
The ternary assigns to MonoApi[exportName] twice in the : branch (MonoApi[exportName] = ... : MonoApi[exportName] = new ExNativeFunction(...)). This is redundant and makes the control flow harder to read; simplify to a single assignment (compute the value, then assign once).
| : MonoApi[exportName] = new ExNativeFunction(addr, ...MonoApi[exportName]) | |
| : new ExNativeFunction(addr, ...MonoApi[exportName]) |
Replace the small blockquote banner with a proper top-level header that names this as a Frida 17 compatibility fork, links the Frida 17 release notes, and credits @freehuntx (original author) and GoSecure (extra branch additions).
Summary
Frida 17.0.0 (release notes, May 2025) removed the static
Module.*helper family, includingModule.findExportByName. The currentextrabranch calls it in two places, so any agent that importsfrida-mono-apiunder Frida 17 crashes at module-load time withTypeError: not a function.This PR migrates both call sites to the Frida-17-supported forms:
src/mono-module.js—Module.findExportByName(null, 'mono_thread_attach')→Module.findGlobalExportByName('mono_thread_attach')(the dedicated replacement for thenull-as-first-arg form, used here because the lookup is intentionally module-agnostic).src/mono-api.js—Module.findExportByName(monoModule.name, exportName)→monoModule.findExportByName(exportName). TheModuleobject is already in hand as a local, so the instance method (which has existed since Frida 16) is the natural and most efficient replacement, and is forward+backward compatible across Frida 16 and 17.The existing
!addrcheck on the next line already handles both the Frida 16 NULL-NativePointerand the Frida 17nullreturns, so no change to the not-found path was needed.Why these specific replacements
Process.getModuleByName(name).findExportByName(...)— the module is already cached inmonoModule; re-resolving it on every iteration would be wasteful, andProcess.getModuleByNamethrows on miss whereas the existing logic relies on a non-throwing path.findGlobalExportByNameovergetGlobalExportByName— call sites already test the result (if (monoThreadAttach) ...), so the non-throwingfind*form is the right one.get*would force adding a try/catch.Companion PR
The bundled script consumer needs a parallel rebuild — see GoSecure/frida-xamarin-unpin#19, which regenerates
dist/xamarin-unpin.jsagainst this branch. The two PRs should be considered together.Test plan
frida-xamarin-unpinrebuilt against this branch loads cleanly under Frida 17.9.1 against a real Xamarin Android target.mono_thread_attach,mono_compile_method,mono_class_get_method_from_name, etc.) continues to work in attach mode.Module.findExportByName(in the diff.🤖 Generated with Claude Code