phantom-frida
Build anti-detection Frida server from source. Covers 16 detection vectors with ~90 patches.
Extended beyond ajeossida with additional stealth techniques: custom port, binary string sweep, internal symbol renaming, temp path obfuscation, and more.
How it works
Phantom-frida clones Frida source, applies patches in 4 phases (source, targeted, post-build, binary), and compiles a custom server where all identifiable "frida" strings, symbols, thread names, and file paths are replaced with a custom name.
Standard Frida client (pip install frida-tools) connects to the patched server normally — the client-server protocol is preserved.
Quick Start
GitHub Actions (recommended)
- Fork this repo
- Actions > Build Custom Frida > Run workflow
- Choose version, name, architecture, options
- Download artifacts (~8 min with cache, ~35 min cold build)
Weekly auto-builds
The Weekly Stealth Build workflow runs every Sunday:
- Detects latest Frida version automatically
- Generates a random name and port via
namegen.py - Builds with
--extendedfor maximum stealth - Creates a GitHub Release with binary +
build-info.json
Local build (WSL Ubuntu)
python3 build.py --version 17.7.2
# Full options:
python3 build.py --version 17.7.2 --name myserver --port 27142 --extended --verify
# Patch only (inspect changes without compiling):
python3 build.py --version 17.7.2 --skip-build
WSL helper script
wsl -d Ubuntu bash build-wsl.sh
# With options:
FRIDA_VERSION=17.7.2 CUSTOM_NAME=myserver CUSTOM_PORT=27142 EXTENDED=1 \
wsl -d Ubuntu bash build-wsl.sh
Detection Vectors
| # | Vector | Detection method | Base | Extended |
|---|---|---|---|---|
| 1 | Process name frida-server |
/proc/*/cmdline, ps |
Renamed | Renamed |
| 2 | libfrida-agent.so in maps |
/proc/self/maps scan |
Renamed | Renamed |
| 3 | Thread names gum-js-loop, gmain, gdbus |
/proc/self/task/*/comm |
Renamed | Renamed |
| 4 | memfd name frida-agent-64.so |
/proc/self/fd/ readlink |
jit-cache |
jit-cache |
| 5 | frida_agent_main symbol |
dlsym / memory scan |
Renamed | Renamed |
| 6 | SELinux labels frida_file |
SELinux context check | Renamed | Renamed |
| 7 | libc hooks (exit, signal) | Hook detection | Disabled | Disabled |
| 8 | D-Bus service re.frida.server |
D-Bus introspection | Renamed | Renamed |
| 9 | Default port 27042 | connect() scan |
- | --port N |
| 10 | D-Bus interfaces | Protocol inspection | - | Renamed |
| 11 | Internal C symbols | Memory string scan | - | Renamed |
| 12 | GType names FridaServer |
GObject introspection | - | Renamed |
| 13 | Temp paths .frida, frida- |
Filesystem scan | - | Renamed |
| 14 | Binary string residuals | Binary strings scan |
- | Swept |
| 15 | Build config defines | Memory scan | - | Renamed |
| 16 | Asset directory libdir/frida |
Path inspection | - | Renamed |
Options
--version, -v Frida version to build (required)
--name, -n Custom name replacing 'frida' (default: ajeossida; use random for stealth)
--arch, -a Target arch (default: android-arm64)
--port, -p Custom listening port (default: 27042)
--extended, -e Enable extended anti-detection (vectors 9-16)
--temp-fixes Stability fixes (perfetto skip, cloak detach)
--verify Scan output for residual 'frida' strings
--skip-build Apply patches only, don't compile
--skip-clone Use existing source in work-dir
--ndk-path Path to existing Android NDK r25
Deploy
# Push to device
adb push output/myserver-server-17.7.2-android-arm64 /data/local/tmp/myserver-server
adb shell chmod 755 /data/local/tmp/myserver-server
# Start (default port 27042)
adb shell /data/local/tmp/myserver-server -D &
frida -U -f com.example.app
# Start (custom port)
adb shell /data/local/tmp/myserver-server -D &
adb forward tcp:27142 tcp:27142
frida -H 127.0.0.1:27142 -f com.example.app
Each weekly release includes a build-info.json with the name, port, version, and architecture.
Build Phases
Source patches: Global string replacement across the entire Frida source tree. Renames all
frida-agent,frida-helper,frida-server,re.frida.*references. Rebuilds Android helper DEX with renamed Java package.Targeted patches: Specific fixes for build system files (meson.build), memfd names, libc hook disabling, SELinux labels.
Post-build patches: After first compilation, renames
frida_agent_mainsymbol (generated by Vala compiler, only exists in build output). Requires a second incremental build.Binary patches: Hex-level replacements in compiled binaries — thread names (
gmain,gdbus,pool-spawner), and optional binary string sweep for residualfrida/Fridastrings.
Architecture
build.py Main build script (clone, patch, compile, collect)
patches.py All patch definitions (87 patches + 17 rollbacks)
namegen.py Random name/port generator for stealth builds
build-wsl.sh WSL helper script
test_comprehensive.js Anti-detection + Java bridge verification script
.github/workflows/
build.yml Manual build workflow
scheduled-build.yml Weekly auto-build with releases
Requirements
- Ubuntu 22.04+ (WSL works)
- Python 3.10+
- Git, curl, unzip, make
- ~20 GB free disk space
- Android NDK r25c (auto-downloaded)
Version Support
| Frida | Status |
|---|---|
| 17.x | Fully verified against source |
| 16.x | Compatible (auto-detects API differences) |
Tested Apps
Verified on arm64 Android 14 device with --extended:
| App | Java bridge | Hooks | Anti-detection |
|---|---|---|---|
| Telegram | 28,772 classes | SSL+crypto | All clean |
| Google Play Store | 47,305 classes | Activity hooks | All clean |
| 54,064 classes | Basic hooks | All clean | |
| Magisk | 27,737 classes | Activity hooks | All clean |
Known Limitations
- arm32 apps (Chrome): Frida upstream bug #2878 —
invalid instructionin_patchCode. Not a phantom-frida issue. - D-Bus interface names (
re.frida.HostSession17etc.): Intentionally NOT renamed in base mode. These are the client-server protocol — renaming server-side would break standardfridaclient. Not a detection vector (only visible over USB/TCP channel).
Credits
- Frida by Ole Andre Ravnas
- ajeossida by hackcatml — original stealth Frida concept
- Detection vector research from the Android security community
License
MIT
