One‑Click Root‑Free Persistence for Frida Scripts
This article details a step‑by‑step method to embed Frida scripts directly into Android binaries, creating a root‑free, self‑contained Xposed module by compiling a custom Frida‑gadget, editing ELF/PE files, adding magic markers, and automating packaging with Rust and apktool.
Compiling Frida‑GumJS
Frida‑GumJS normally includes V8 and QuickJS engines. To minimise binary size, V8 and the built‑in database were disabled and QuickJS was kept as the sole engine. The source was compiled via a GitHub Actions workflow ( https://github.com/FriRebuild/fripack-inject).
Embedding the script
An xmake project was created that links against the compiled GumJS library and executes a script. A custom C struct containing a unique magic marker was defined. During .so generation the binary is scanned for this marker; the fields data_size and data_offset are then set to describe the location of the embedded script data.
ELF file editing
To embed the script in an ELF binary a new PT_LOAD segment was added. The segment holds the script data and must be mapped into memory. The virtual address ( vaddr) of the segment is aligned to 4 KB or 16 KB; otherwise the dynamic loader ( dl) may silently fail to map it.
After adding the segment the ELF header size was increased. This caused an error .note sh_offset at 0x270, must be larger than 0x28a because the new segment overlapped existing sections. The overlapping sections and their p_offset values were moved to the end of the file, eliminating the overlap.
A subsequent error PT_PHDR segment is not covered by a PT_LOAD segment appeared. The fix was to extend the covering PT_LOAD segment so that the PT_PHDR segment lies within its range.
Using the magic marker, the tool locates the marker’s segment, reads its vaddr, computes the offset to g_embedded_config, and writes the calculated offset into the binary.
PE file editing
The same principle was applied to PE files. The implementation required only about ten minutes because PE’s layout avoids the segment‑overlap pitfalls encountered with ELF. The resulting PE binary also contains the embedded script and loads it automatically.
Loading the binary in the target process
Several injection methods are possible:
Repackage the APK and use patchelf to add the custom .so as a dependency.
Add static initialization code in an app class and call System.loadLibrary.
Write an Xposed module that loads the .so at runtime.
Use DLL injection techniques on Windows.
Employ LD_PRELOAD or similar mechanisms on Linux.
Create a Zygisk module.
The article focuses on the Xposed approach.
Xposed module construction
The Xposed module implements IXposedHookZygoteInit and IXposedHookLoadPackage in Smali. Required metadata is placed in AndroidManifest.xml, and the assets directory contains xposed_init and native_init. In the xposed_init class the path to the embedded .so is obtained and loaded with System.load.
Instead of using Gradle, the APK is built directly with apktool:
Create a minimal apktool project structure.
Add the Smali code and asset files.
Run apktool b to produce the final Xposed APK.
The resulting APK is self‑contained: it embeds the Frida script, loads the custom .so at startup, and executes the script without any external files.
For users who only need the packaging step, a ready‑made tool is available at https://github.com/std-microblock/fripack/.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Black & White Path
We are the beacon of the cyber world, a stepping stone on the road to security.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
