phantom-frida builds Android Frida Server and Gadget from source while
changing a targeted set of observable runtime identifiers. It is a builder and
verification harness, not a promise that every application-specific detection
method is defeated.
The current compatibility target is Frida 17.16.3 on Android. Other Frida versions are intentionally treated as unverified until their source contracts, full build, and rooted-device acceptance have been repeated.
Use this project only on applications and devices you own or are authorized to test.
The repository separates three kinds of evidence:
- Unit and fixture tests validate input handling, exact Frida 17.16.3 source patch contracts, DEX rebuilding, artifact promotion, metadata, workflows, and failure behavior.
build.py --verifyrequires both Server and Gadget, then rejects known forbidden runtime markers before publishing either artifact.scripts/android_smoke.pyexercises a built artifact on one rooted device: stock-client enumeration, spawn, attach, Java bridge assertions,/procscans, and a separately loaded Gadget.
A passing source test or byte scan is not equivalent to runtime stealth. Claims about Android behavior should include the generated, redacted smoke-test report.
Run Build Custom Frida from the Actions tab. The reusable build workflow:
- validates every user-controlled build input;
- downloads Android NDK r29 from Google and checks its published checksum;
- clones a fresh upstream source tree instead of caching patched source;
- uploads only after the hard artifact and marker gates pass;
- includes
build-info.jsonandSHA256SUMSin one build artifact.
The weekly workflow resolves the latest release through the authenticated GitHub API, calls the same read-only build workflow, verifies the downloaded artifact, attests it, and grants release write permission only to the final job.
Requirements:
- Ubuntu 22.04 or newer (WSL is supported);
- Python 3.10 or newer;
- Git, curl, unzip, a C/C++ toolchain, JDK 17, and Node.js 18 or newer (CI uses Node.js 24.13.1);
- Android SDK platform and build-tools containing
android.jarand D8; - about 20 GB of free disk space.
If --ndk-path is omitted, the builder downloads Android NDK r29 under
build/. A verified pinned-input arm64 build is:
export ANDROID_SDK_ROOT=/path/to/Android/Sdk
python3 build.py \
--version 17.16.3 \
--name oemcodec \
--arch android-arm64 \
--port 27142 \
--extended \
--verifyUseful options:
--version, -v Exact Frida semantic version (required)
--name, -n Lowercase replacement name, 3-20 characters
--arch, -a One or more supported Android architectures
--port, -p Listening port; omitted keeps 27042
--extended, -e Apply the optional extended identifier transformations
--temp-fixes Apply opt-in, device-specific stability changes
--verify Reject known forbidden markers in final artifacts
--skip-build Patch source without compiling
--skip-clone Use an existing source tree in the work directory
--ndk-path Use an existing Android NDK r29 directory
For the example above, output/ contains:
oemcodec-server-17.16.3-android-arm64
oemcodec-server-17.16.3-android-arm64.gz
oemcodec-gadget-17.16.3-android-arm64.so
oemcodec-gadget-17.16.3-android-arm64.so.gz
build-info.json
SHA256SUMS
build-info.json records the exact builder, Frida, and frida-core commits, NDK
version, UTC build time, architectures, name, port, and workflow URL when built
in Actions. Verify downloaded binary files before use:
cd output
sha256sum --check SHA256SUMS
python3 -m json.tool build-info.json >/dev/nullPublic weekly releases also receive a GitHub build-provenance attestation.
SHA256SUMS identifies one output set; binary hashes are not expected to match
across different build hosts.
The builder preserves the D-Bus protocol interfaces under re.frida.*, the
/re/frida/GadgetSession path, public capital Frida JavaScript API strings,
and generated C ABI symbols required by stock clients. Renaming those values
would break the normal Frida client/server contract.
The D-Bus service identifier, helper JNI package, zymbiote socket prefix, selected process/library/path identifiers, selected thread names, and an optional custom port are separate implementation details that the builder can transform. The output verifier rejects this explicit marker set:
frida\0
frida-zymbiote
re/frida/HelperBackend
frida-server
frida-helper
Capital Frida and allowlisted protocol strings are not verifier failures.
Install the exact Python binding recorded in build-info.json, install the
pinned Java bridge dependency, and connect exactly one rooted Android device:
python3 -m pip install "frida==17.16.3" frida-tools
npm ci --ignore-scripts
python3 scripts/android_smoke.py \
--server output/oemcodec-server-17.16.3-android-arm64 \
--gadget output/oemcodec-gadget-17.16.3-android-arm64.so \
--name oemcodec \
--port 27142 \
--package com.example.app \
--ndk build/android-ndk-r29 \
--report android-smoke-report.jsonThe package must be an installed Java application you are authorized to test.
The harness compiles test_comprehensive.js with the explicit
frida-java-bridge required by Frida 17, starts Server through a forwarded TCP
port, then compiles a minimal native loader and exercises Gadget on a separate
port. It cleans up its processes and forwards on exit.
Frida Gadget configuration must be named next to the library as
lib<name>-gadget.config.so; the harness generates and deploys this file.
python -m pip install --requirement requirements-dev.txt
npm ci --ignore-scripts
python -m pytest
ruff check .
ruff format --check .
mypy build.py patches.py namegen.py scripts
node --check test_comprehensive.js
bash -n build-wsl.sh
go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.12See CONTRIBUTING.md for the full evidence requirements.
build.py Clone, patch, compile, verify, and collect artifacts
patches.py Source and same-length binary transformations
namegen.py Seeded build-name and port generation
scripts/android_smoke.py Rooted Android Server/Gadget acceptance harness
test_comprehensive.js Structured Frida 17 Java bridge assertions
tests/ Unit, contract, fixture, and workflow tests
.github/workflows/ CI, CodeQL, reusable build, and release isolation
- Only Frida 17.16.3 is the current verification target; support is not inferred for all 17.x or 16.x releases.
--temp-fixeschanges runtime behavior and remains opt-in.- Marker absence does not prove resistance to behavioral, integrity, timing, or application-specific detection.
- Frida 17 raw agents need explicit bridge imports or bundling. The harness uses
frida.Compiler; the Frida REPL and tracer provide their own bundled bridges.
The builder code is MIT licensed. Generated binaries retain upstream licensing; see THIRD_PARTY_NOTICES.md.