docs: prepare FridaBox for public release

This commit is contained in:
Mahdi Karzari
2026-07-20 04:25:09 +03:30
parent bf5f73e07a
commit 89e476c145
19 changed files with 1173 additions and 246 deletions
-3
View File
@@ -1,3 +0,0 @@
github: alex5402
buy_me_a_coffee: alex5402
custom: ["https://www.binance.com/en-IN/my/wallet/account/main/withdrawal/crypto/USDT", Binance__749326513 ]
+52
View File
@@ -0,0 +1,52 @@
name: Bug report
description: Report a reproducible FridaBox failure on an authorized test target.
title: "[Bug]: "
labels: [bug]
body:
- type: markdown
attributes:
value: |
Do not upload proprietary APKs, private agents, credentials, or unsanitized device logs.
Security vulnerabilities belong in a private GitHub security advisory.
- type: checkboxes
attributes:
label: Authorization and scope
options:
- label: I am authorized to test the device and application involved.
required: true
- label: I checked the documented limitations and existing issues.
required: true
- type: input
attributes:
label: FridaBox version or commit
placeholder: 4.0.0 / commit SHA
validations:
required: true
- type: input
attributes:
label: Device and Android build
placeholder: Model, Android/API version, vendor ROM
validations:
required: true
- type: dropdown
attributes:
label: Launch mode
options: [On-device, Computer, Clean, Import/build, Not mode-specific]
validations:
required: true
- type: textarea
attributes:
label: Reproduction steps
description: Provide the smallest deterministic sequence.
validations:
required: true
- type: textarea
attributes:
label: Expected and actual behavior
validations:
required: true
- type: textarea
attributes:
label: Sanitized evidence
description: Relevant logcat, stack trace, controller output, ABI, and process state.
render: text
+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: false
@@ -0,0 +1,34 @@
name: Research or feature proposal
description: Propose a scoped capability or research direction.
title: "[Proposal]: "
labels: [enhancement]
body:
- type: checkboxes
attributes:
label: Scope
options:
- label: This proposal is for authorized research and defensive testing.
required: true
- label: I reviewed the architecture and current limitations.
required: true
- type: textarea
attributes:
label: Problem
description: What concrete limitation or workflow gap should be addressed?
validations:
required: true
- type: textarea
attributes:
label: Proposed boundary
description: Which host, virtual runtime, Gadget, controller, or UI component changes?
validations:
required: true
- type: textarea
attributes:
label: Acceptance evidence
description: Describe the tests and device proof that would demonstrate success.
validations:
required: true
- type: textarea
attributes:
label: Alternatives and risks
+30
View File
@@ -0,0 +1,30 @@
## Summary
Describe the problem and the narrow change that solves it.
## Affected boundary
- [ ] Host UI/import/policy
- [ ] Virtual package or process runtime
- [ ] Gadget lifecycle or agent configuration
- [ ] Controller or Frida scripts
- [ ] Build/release/tooling
- [ ] Documentation only
## Validation
- [ ] Relevant unit tests pass
- [ ] `:app:check` passes
- [ ] Debug build passes
- [ ] Release build passes
- [ ] Device validation attached when runtime behavior changed
- [ ] Original guest APK remains unmodified
- [ ] No credentials, private agents, proprietary APKs, or sensitive logs included
## Evidence
List exact commands, Android/device details, and sanitized output.
## Risks and limitations
Describe compatibility impact, process-lifecycle assumptions, and remaining gaps.
+18
View File
@@ -0,0 +1,18 @@
version: 2
updates:
- package-ecosystem: gradle
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
+87
View File
@@ -0,0 +1,87 @@
name: Android CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
permissions:
contents: read
concurrency:
group: android-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
verify:
name: Build, test, and verify
runs-on: ubuntu-latest
timeout-minutes: 45
steps:
- name: Check out source
uses: actions/checkout@v6
- name: Set up JDK 21
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: '21'
cache: gradle
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: pip
cache-dependency-path: tools/requirements.txt
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: '22'
cache: npm
- name: Install Android SDK components
run: |
yes | sdkmanager --licenses >/dev/null || true
sdkmanager \
'platforms;android-35' \
'build-tools;35.0.0' \
'ndk;29.0.14206865'
- name: Install controller and agent dependencies
run: |
python -m pip install --requirement tools/requirements.txt
npm ci
- name: Verify reproducible Frida agents
run: |
python tools/build_frida_agents.py
git diff --exit-code -- scripts/dist
- name: Build and test
run: |
chmod +x gradlew
./gradlew \
:app:assembleDebug \
:app:assembleRelease \
:Bcore:testDebugUnitTest \
:app:testDebugUnitTest \
:app:check \
--stacktrace \
--console=plain
- name: Upload APKs and reports
if: always()
uses: actions/upload-artifact@v6
with:
name: fridabox-${{ github.sha }}
if-no-files-found: warn
retention-days: 14
path: |
app/build/outputs/apk/**/*.apk
app/build/reports/lint-results-*.html
app/build/test-results/**/*.xml
Bcore/build/test-results/**/*.xml
-167
View File
@@ -1,167 +0,0 @@
name: Build and Send APK to Telegram
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build-and-send:
runs-on: ubuntu-latest
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: 'gradle'
- name: Set up Android SDK
uses: android-actions/setup-android@v3
- name: Accept Android SDK licenses
run: yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses || yes | $ANDROID_HOME/tools/bin/sdkmanager --licenses || true
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
- name: Build APKs and AARs
run: ./gradlew assembleDebug assembleRelease :Bcore:assembleDebug :Bcore:assembleRelease :black-reflection:assemble :compiler:assemble
- name: Find Bcore AAR paths
id: aar_paths
run: |
DEBUG_AAR=$(find ./Bcore/build/outputs/aar -name "*debug.aar" | head -n 1)
RELEASE_AAR=$(find ./Bcore/build/outputs/aar -name "*release.aar" | head -n 1)
echo "debug_aar_path=$DEBUG_AAR" >> $GITHUB_OUTPUT
echo "release_aar_path=$RELEASE_AAR" >> $GITHUB_OUTPUT
- name: Find black-reflection and compiler artifact paths
id: additional_artifacts
run: |
BLACK_REFLECTION_ART=$(find ./black-reflection/build/libs ./black-reflection/build/outputs -name "*.jar" -o -name "*.aar" 2>/dev/null | head -n 1)
COMPILER_ART=$(find ./compiler/build/libs ./compiler/build/outputs -name "*.jar" -o -name "*.aar" 2>/dev/null | head -n 1)
echo "black_reflection_path=$BLACK_REFLECTION_ART" >> $GITHUB_OUTPUT
echo "compiler_path=$COMPILER_ART" >> $GITHUB_OUTPUT
- name: Send Bcore Debug AAR to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
AAR_PATH="${{ steps.aar_paths.outputs.debug_aar_path }}"
if [ -n "$AAR_PATH" ] && [ -f "$AAR_PATH" ]; then
RESPONSE=$(curl -s -F document=@"$AAR_PATH" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[Bcore DEBUG AAR] $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
else
echo "Debug AAR not found at $AAR_PATH"
fi
- name: Send Bcore Release AAR to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
AAR_PATH="${{ steps.aar_paths.outputs.release_aar_path }}"
if [ -n "$AAR_PATH" ] && [ -f "$AAR_PATH" ]; then
RESPONSE=$(curl -s -F document=@"$AAR_PATH" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[Bcore RELEASE AAR] $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
else
echo "Release AAR not found at $AAR_PATH"
fi
- name: Send black-reflection Artifact to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
ART_PATH="${{ steps.additional_artifacts.outputs.black_reflection_path }}"
if [ -n "$ART_PATH" ] && [ -f "$ART_PATH" ]; then
FILENAME=$(basename "$ART_PATH")
RESPONSE=$(curl -s -F document=@"$ART_PATH" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[black-reflection] $FILENAME - $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
else
echo "black-reflection artifact not found at $ART_PATH"
fi
- name: Send compiler Artifact to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
ART_PATH="${{ steps.additional_artifacts.outputs.compiler_path }}"
if [ -n "$ART_PATH" ] && [ -f "$ART_PATH" ]; then
FILENAME=$(basename "$ART_PATH")
RESPONSE=$(curl -s -F document=@"$ART_PATH" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[compiler] $FILENAME - $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
else
echo "compiler artifact not found at $ART_PATH"
fi
- name: Send ALL Debug APKs to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
for APK in ./app/build/outputs/apk/debug/*.apk; do
if [ -f "$APK" ]; then
RESPONSE=$(curl -s -F document=@"$APK" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[DEBUG] $(basename $APK) $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
fi
done
- name: Send ALL Release APKs to Telegram and Pin
run: |
COMMIT_MSG=$(git log -1 --pretty=%s)
for APK in ./app/build/outputs/apk/release/*.apk; do
if [ -f "$APK" ]; then
RESPONSE=$(curl -s -F document=@"$APK" \
-F chat_id="$TELEGRAM_CHAT_ID" \
-F caption="[RELEASE] $(basename $APK) $COMMIT_MSG" \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendDocument)
MESSAGE_ID=$(echo $RESPONSE | jq '.result.message_id')
if [ "$MESSAGE_ID" != "null" ] && [ -n "$MESSAGE_ID" ]; then
curl -s -X POST "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/pinChatMessage" \
-d chat_id="$TELEGRAM_CHAT_ID" \
-d message_id="$MESSAGE_ID"
fi
fi
done
+126 -50
View File
@@ -1,57 +1,133 @@
# Architecture
# FridaBox architecture
FridaBox extends the existing BlackBox virtual package, process, Binder, file,
identity, signature, and lifecycle implementation. It does not introduce a
second plugin framework and never creates a replacement `DexClassLoader` for a
guest.
FridaBox has two deliberate layers:
1. an independent host product under `com.qm4rs.fridabox`, responsible for APK
import, integrity, launch policy, agent storage, runtime presentation, and
the user experience;
2. a retained virtual Android runtime responsible for package, process, Binder,
filesystem, identity, signature, component, and lifecycle virtualization.
The runtime descends from the NewBlackbox/BlackBox lineage. Its internal package
names are compatibility API and are not the FridaBox product namespace. They are
kept stable because manifests, AIDL, reflection, native code, persisted paths,
and virtual process dispatch all depend on that contract.
## End-to-end lifecycle
```text
Host launcher process
|
| import original APK
v
BlackBox virtual package manager
|
| allocate :pN virtual process
v
BActivityThread.handleBindApplication()
|
| create guest Context / LoadedApk / ClassLoader
| initialize virtual runtime and IO redirection
| populate GuestRuntimeRegistry
| load Frida Gadget and wait
v
Frida controller attaches
|
| select guest ClassLoader
| install Java/native hooks
v
Guest makeApplication()
|
v
Guest Application.onCreate()
|
v
Guest Activity
FridaBoxActivity
│
├── SAF document stream
├── private immutable APK copy
├── SHA-256 + ZIP ABI inspection
└── virtual installation for user 0
│
▼
virtual package manager
│
▼
allocate :pN process and dispatch ProxyActivity
│
▼
BActivityThread.handleBindApplication()
│
├── establish virtual identity and runtime
├── initialize native IO redirection
├── create guest Context / LoadedApk / PathClassLoader
├── populate GuestRuntimeRegistry
└── apply per-package InstrumentationPreferences
│
├── disabled: continue
├── listen: load loopback Gadget and wait for attach
└── script: load private Gadget + agent.js
│
▼
guest makeApplication()
│
▼
guest Application.onCreate()
│
▼
guest Activity
```
## Runtime boundary
`GuestRuntimeRegistry` is volatile, process-local state. Each normal BlackBox
virtual process populates it after `VirtualRuntime.setupRuntime`, `NativeCore.init`,
and IO redirection, using the `LoadedApk` ClassLoader. `FridaGadgetLoader` then
performs one synchronized `System.loadLibrary("frida-gadget")` attempt in that
Linux process. The static Gadget configuration pauses that call until a
controller connects. Only afterward does BlackBox call `makeApplication`.
The host status screen uses a small SharedPreferences snapshot because the host
launcher cannot directly read another process's static registry. The Frida
controller reads the authoritative process-local registry through Java.
## Import boundary
The host copies a document-provider stream once into `files/imported-apks`,
computes SHA-256 while copying, inspects the ZIP ABI entries, parses package
metadata, verifies the stored hash, marks the file read-only, and passes the path
only to BlackBox's virtual package manager. No real package installer Intent or
PackageInstaller session is used.
The host copies a document-provider stream once into `files/imported-apks` and
computes SHA-256 while copying. It inspects native ZIP entries, parses package
metadata, verifies the stored hash, marks the private file read-only, and passes
that path only to the virtual package manager.
There is no package-installer Intent, PackageInstaller session, APK mutation,
repack, or resign. The original guest package is therefore absent from Android's
real PackageManager.
## Instrumentation boundary
`GuestRuntimeRegistry` is authoritative, volatile, process-local state. It is
populated only after `VirtualRuntime.setupRuntime`, `NativeCore.init`, IO
redirection, and guest `LoadedApk` creation have succeeded. This gives Frida a
real guest ClassLoader while still preceding `makeApplication()`.
`FridaGadgetLoader` makes one synchronized Gadget-load attempt per Linux process.
The loader reads per-package policy from private host storage:
- **disabled** emits an explicit clean-launch state and never loads Gadget;
- **listen** loads the pinned loopback configuration with `on_load=wait`;
- **script** creates a private per-guest Gadget copy and adjacent Script
interaction config referencing a read-only `agent.js`.
The build task `verifyInstrumentationOrdering` statically verifies that the
loader remains before guest `makeApplication()`.
## Controller boundary
Gadget always listens on device loopback. ADB forwarding is a controller concern,
not a guest concern. `tools/attach_guest.py` forwards a bounded port range,
probes candidates using a compiled registry agent, rejects unrelated endpoints,
and maps each endpoint to package/process metadata from `GuestRuntimeRegistry`.
Before loading a user agent, `guest-bootstrap.js` assigns the registry's guest
ClassLoader to `Java.classFactory.loader` and reports native module enumeration.
This prevents host-first class resolution from producing false negatives.
## Cross-process state
The registry itself is never treated as cross-process storage. A minimal private
SharedPreferences snapshot lets the host UI display the latest package, process,
virtual user, process slot, source APK, ClassLoader, state, and error. Reads use
multi-process reload semantics because host and guest processes maintain
independent in-memory preference caches.
## Process recycling
Instrumentation policy is process-scoped in effect even though it is persisted
per package. Changing mode stops the guest before relaunch. This is essential:
a native library cannot be unloaded safely from a living Android process, so a
Clean launch must receive a fresh virtual process rather than attempting to undo
Gadget initialization.
## Trust and security boundaries
- The imported APK and selected JavaScript agent are untrusted inputs.
- Imported files are size-bounded, hashed, privately stored, and made read-only.
- On-device agents require an explicit trust confirmation and execute with the
guest process's access.
- Gadget binds only to `127.0.0.1`; remote reachability requires an explicit ADB
forwarding action.
- Release builds never silently use the debug signing key.
- FridaBox does not claim to defeat kernel, SELinux, Frida, virtualization, or
hardware-attestation detection.
## Source layout
| Module | Responsibility |
| --- | --- |
| `app` | FridaBox application, UI, import pipeline, modes and management. |
| `Bcore` | Virtual Android runtime, Gadget load point, registry and native integration. |
| `black-reflection` | Generated/reflected access to hidden Android framework APIs. |
| `compiler` | Annotation processing used by the reflection layer. |
| `sample-guest` | Deterministic early-start and hook validation target. |
| `scripts` | Source and reproducibly bundled Frida 17 agents. |
| `tools` | Fetch, build, forward, discover and attach utilities. |
+48
View File
@@ -0,0 +1,48 @@
# Changelog
All notable FridaBox changes are documented here. The project follows semantic
versioning for its public releases.
## [4.0.0] - 2026-07-20
### Added
- Independent FridaBox application, Android namespace, brand, icon, responsive
workspace, runtime dashboard, settings, and per-guest management.
- Per-app **On-device**, **Computer**, and **Clean** launch modes.
- Trusted JavaScript selection through SAF with private byte-identical storage,
SHA-256 recording, size bounds, and read-only execution permissions.
- Autonomous Gadget Script interaction requiring no ADB or computer after agent
selection.
- Loopback Gadget endpoint discovery and guest mapping through
`GuestRuntimeRegistry`.
- Guest ClassLoader bootstrap and native module enumeration.
- ARM64 APK inspection and clear rejection of incompatible/split inputs.
- Generated sample guest and deterministic `Target.add(2, 3) -> 1337` hook.
- Reproducible Frida 17 agent bundles with pinned npm dependencies.
- Explicit production signing configuration, R8, and resource shrinking.
- Android 16 device-validation transcript and engineering documentation.
### Changed
- Gadget now loads after virtual runtime/IO/ClassLoader setup and before guest
`makeApplication()`.
- Launch-mode changes recycle the virtual process to prevent instrumentation
state from leaking into Clean launches.
- Runtime snapshots reload safely across host/guest process boundaries.
- Private Gadget and agent permissions comply with modern Android executable
file constraints.
- Guest-visible inherited product strings were replaced with FridaBox identity.
### Removed
- The inherited launcher and unrelated GMS, Xposed, fake-location, floating
overlay, cloning-list, and legacy settings surfaces.
- Obsolete launcher resources, translations, UI AARs, and product documents.
- Debug-key fallback for release artifacts.
## Foundation
FridaBox began from NewBlackbox commit
`89b59836c66f173756a4ae258cf379a957649820`. Upstream provenance and bundled
Frida licensing are documented in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
+25
View File
@@ -0,0 +1,25 @@
# Community code of conduct
FridaBox is a technical research project. Participation must remain respectful,
evidence-driven, and safe.
## Expected behavior
- Treat contributors, maintainers, upstream projects, and users with respect.
- Critique technical claims with reproducible evidence rather than personal
attacks.
- Respect authorization boundaries, privacy, licenses, and coordinated security
disclosure.
- Make room for different experience levels while maintaining engineering rigor.
- Clearly distinguish measured results from assumptions or speculation.
## Unacceptable behavior
Harassment, discrimination, threats, doxxing, publication of secrets or private
data, knowingly false claims, and requests for unauthorized exploitation are not
welcome. Maintainers may edit, hide, reject, or remove contributions that violate
these expectations and may restrict participation when necessary.
Report conduct concerns privately through the repository owner's available
GitHub contact or security-advisory channel. Good-faith reports will be handled
with discretion.
+75
View File
@@ -0,0 +1,75 @@
# Contributing to FridaBox
FridaBox welcomes focused contributions that improve correctness,
compatibility, observability, documentation, or responsible research workflows.
## Before opening an issue
- Confirm the target and device are authorized for your testing.
- Read [docs/LIMITATIONS.md](docs/LIMITATIONS.md) and
[docs/DETECTION_SURFACES.md](docs/DETECTION_SURFACES.md).
- Search existing issues for the Android version, vendor ROM, package type, and
failure signature.
- Remove credentials, personal data, proprietary APKs, private agents, tokens,
and device identifiers from logs.
Security vulnerabilities should follow [SECURITY.md](SECURITY.md), not a public
issue.
## Development setup
Use JDK 21, Android SDK 35, NDK 29.0.14206865, Python 3.10+, and Node.js 20+.
Follow [docs/BUILDING.md](docs/BUILDING.md) for Gadget verification and the
Windows no-space native-build workaround.
```text
npm ci
python tools/build_frida_agents.py
./gradlew :app:assembleDebug :Bcore:testDebugUnitTest :app:testDebugUnitTest :app:check
```
## Pull requests
Keep changes narrow and explain the runtime boundary they affect. A useful pull
request includes:
- the problem and why the current behavior is incorrect;
- the smallest viable implementation;
- affected Android versions, ABIs, and process types;
- host-side test results;
- device evidence for lifecycle, native, Binder, or virtualization changes;
- explicit confirmation that imported APK bytes were not modified;
- documentation updates for new behavior or limitations.
Do not combine unrelated reformatting, package renames, or generated-file churn
with a runtime fix.
## Runtime changes
Changes around `BActivityThread`, `NativeCore`, IO redirection, Binder proxies,
Gadget loading, process allocation, or package persistence require device
validation. At minimum, test:
1. import of an original ARM64 base APK;
2. absence of the guest from the real PackageManager;
3. Computer-mode pause and attach;
4. Java hook execution with the guest ClassLoader;
5. native module enumeration;
6. process recycling into Clean mode;
7. a second instrumented launch after Clean mode.
Add exact commands and relevant log lines to a dedicated validation note. Never
commit proprietary APKs or third-party scripts without redistribution rights.
## Style
- Preserve existing source encoding and line endings where practical.
- Keep user-facing language precise; do not promise stealth or universal app
compatibility.
- Prefer explicit failure states over silent fallbacks.
- Keep network listeners loopback-only by default.
- Pin and verify externally fetched runtime artifacts.
- Add tests for parsers, integrity rules, state transitions, and regressions.
By contributing, you agree that your contribution is licensed under the
repository's Apache License 2.0.
+286 -25
View File
@@ -1,34 +1,295 @@
<div align="center">
# FridaBox
FridaBox is an authorized mobile-security research workspace that runs an original,
unmodified APK inside private virtual processes and loads Frida Gadget before
the guest `Application` is created. It requires no root, frida-server, Magisk,
Zygisk, system-image changes, real PackageManager installation, APK patching,
repacking, or resigning.
### On-device Android instrumentation, inside a private virtual workspace
The host application ID and Android namespace are both `com.qm4rs.fridabox`.
Third-party engine provenance is isolated in `THIRD_PARTY_NOTICES.md`.
[![Android](https://img.shields.io/badge/Android-12--16-3DDC84?logo=android&logoColor=white)](docs/TEST_RESULTS.md)
[![ABI](https://img.shields.io/badge/ABI-arm64--v8a-5C6BC0)](docs/BUILDING.md)
[![Frida](https://img.shields.io/badge/Frida_Gadget-17.16.0-FF6B35)](THIRD_PARTY_NOTICES.md)
[![Release](https://img.shields.io/badge/release-4.0.0-00BFA5)](CHANGELOG.md)
[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE)
[![Status](https://img.shields.io/badge/status-device--validated-success)](docs/device-validation.log)
## MVP capabilities
**Import an original APK. Choose a per-app mode. Run trusted Frida JavaScript
directly on the phone, attach from a computer, or launch clean.**
- SAF import of one base APK into app-private, read-only storage.
- SHA-256 verification before and after private virtual installation.
- ARM64 native-library inspection; pure Java/Kotlin guests are accepted and
native guests without `arm64-v8a` are rejected.
- Per-guest instrumented or non-instrumented launches with virtual process stop
before mode changes.
- Frida Gadget 17.16.0 bound to loopback, default port 27042, with conflict
fallback and `on_load=wait` for pre-`Application.onCreate()` hooks.
- Process-local guest registry and controller-side ClassLoader selection.
- Debug sample guest proving `Target.add(2, 3)` can be replaced with `1337`.
- Reproducibly bundled Frida 17 Java agents using pinned `frida-java-bridge`
7.0.13 and `frida-compile` 19.0.5.
[Features](#what-fridabox-does) · [How it works](#how-it-works) ·
[Quick start](#quick-start) · [Research](#engineering-and-research) ·
[Limitations](#scope-and-limitations) · [Acknowledgements](#acknowledgements)
Start with [docs/BUILDING.md](docs/BUILDING.md), [docs/USAGE.md](docs/USAGE.md),
and [docs/FRIDA_CONNECTION.md](docs/FRIDA_CONNECTION.md).
</div>
FridaBox is not undetectable. See [docs/DETECTION_SURFACES.md](docs/DETECTION_SURFACES.md)
and [docs/LIMITATIONS.md](docs/LIMITATIONS.md).
---
The complete Android 16 device transcript is in
FridaBox is an Android mobile-security research workspace built for authorized
dynamic analysis. It runs an original, unmodified APK inside app-private virtual
processes and can load Frida Gadget before the guest `Application` is created.
It does **not** require root, Magisk, Zygisk, frida-server, a modified system
image, real PackageManager installation, APK patching, repacking, or resigning.
The host application ID and Android namespace are both
`com.qm4rs.fridabox`.
> [!IMPORTANT]
> FridaBox is intended for applications and devices you own or are explicitly
> authorized to test. It is a research tool, not an invisibility product. Read
> [SECURITY.md](SECURITY.md) and [the documented detection surfaces](docs/DETECTION_SURFACES.md)
> before using it in an assessment.
## Why FridaBox exists
Traditional Gadget workflows patch a target APK, add a native library, rebuild
it, and sign the modified package. That changes the artifact under test and can
invalidate signatures, integrity assumptions, update paths, and experimental
results. A frida-server workflow avoids repacking but normally requires a rooted
or specially prepared device.
FridaBox explores a different boundary:
- preserve the imported APK byte-for-byte;
- install it only into a private virtual package manager;
- create the guest's real Android `LoadedApk` and `ClassLoader`;
- load a pinned Gadget inside the assigned virtual process;
- pause before guest `Application.onCreate()` when interactive attachment is
requested;
- keep instrumentation policy per guest instead of globally.
The result is a repeatable laboratory for early Java/native hooks while the
original package remains absent from Android's real PackageManager.
## What FridaBox does
| Capability | What it provides |
| --- | --- |
| Original APK import | SAF-based import into private storage with SHA-256 verification before and after virtual installation. |
| Three launch modes | **On-device**, **Computer**, and **Clean**, remembered independently for every guest. |
| Earliest practical Gadget load | Gadget is loaded after guest runtime/IO setup but before `makeApplication()` and guest `Application.onCreate()`. |
| No-computer instrumentation | A trusted JavaScript agent can be selected once and automatically loaded on every On-device launch. |
| Familiar desktop workflow | Computer mode supports the normal `frida -U gadget -l agent.js` flow and pauses startup until attachment. |
| Deterministic clean launch | The virtual process is recycled before starting without Gadget, preventing mode leakage from a previous process. |
| Correct Java context | The controller selects the guest `PathClassLoader`, not the host loader, before user hooks execute. |
| Runtime observability | Package, process, virtual user, process slot, source APK, ClassLoader, mode, state, and latest error are exposed. |
| Endpoint discovery | The controller probes a bounded forwarded range and identifies the correct Gadget endpoint for a guest. |
| Native visibility | Loaded native modules can be enumerated before a user agent is installed. |
| ARM64 validation | Native guests are inspected before import; incompatible native APKs and split containers are rejected clearly. |
| Production-oriented host | Independent FridaBox identity, responsive Material UI, R8/resource shrinking, and explicit release signing. |
## Launch modes
### On-device
Choose a trusted `.js` file through Android's document picker. FridaBox stores a
private byte-identical copy, records its hash, creates a per-guest Script
interaction configuration, and loads it on future launches—without ADB, a USB
cable, port forwarding, or a computer-side Frida client.
### Computer
FridaBox loads its loopback-only Gadget listener and pauses guest startup. Attach
using the familiar workflow:
```text
frida -U gadget -l path/to/agent.js
```
For deterministic multi-guest discovery and automatic ClassLoader selection:
```text
python tools/attach_guest.py --list
python tools/attach_guest.py --package com.example.app --script scripts/example.js
```
### Clean
FridaBox stops the existing virtual process, disables instrumentation for the
next process, and launches the guest normally. The saved on-device agent remains
available for later use.
## How it works
```text
Original APK selected with SAF
│
▼
Private copy + SHA-256 + ABI inspection
│
▼
Virtual package installation (not Android PackageManager)
│
▼
Virtual process allocation and guest runtime setup
│
├── Clean ───────────────► guest makeApplication()
│
├── On-device ───────────► Gadget + private agent.js
│ │
│ ▼
│ guest makeApplication()
│
└── Computer ────────────► Gadget listens + startup waits
│
controller attaches
│
▼
guest makeApplication()
```
The instrumentation hook lives in `BActivityThread.handleBindApplication()`.
At that point the virtual identity, filesystem redirection, guest context, and
guest ClassLoader exist, but the guest `Application` has not yet been created.
That ordering is enforced by a build verification task.
See [ARCHITECTURE.md](ARCHITECTURE.md) for component boundaries and
[docs/ENGINEERING_JOURNEY.md](docs/ENGINEERING_JOURNEY.md) for the failures,
constraints, and fixes that shaped the implementation.
## Demonstrated result
The repository includes a generated sample guest and a small hook:
```javascript
Java.perform(function () {
const Target = Java.use('com.qm4rs.fridabox.sample.Target');
Target.add.implementation = function (a, b) {
return 1337;
};
});
```
The complete Android 16 device validation proved that:
- the sample package was absent from the real Android PackageManager;
- startup paused before `SampleApplication.onCreate()`;
- the correct Gadget endpoint and guest ClassLoader were discovered;
- native module enumeration returned hundreds of modules;
- `Target.add(2, 3)` changed from `5` to `1337`;
- recycling into Clean mode removed the listener and restored the result to `5`.
The commercial workspace flow was also validated with a real ARM64 Unity guest
in On-device, Computer, and Clean modes. Evidence and exact commands are in
[docs/TEST_RESULTS.md](docs/TEST_RESULTS.md) and
[docs/device-validation.log](docs/device-validation.log).
## Quick start
### Requirements
- an ARM64 Android 12–16 device;
- JDK 21;
- Android SDK 35 and NDK 29.0.14206865;
- Python 3.10+;
- Node.js 20+ and npm when rebuilding the bundled Frida 17 agents.
### Build
```text
python tools/fetch_frida_gadget.py
npm ci
python tools/build_frida_agents.py
./gradlew :app:assembleDebug :Bcore:testDebugUnitTest :app:testDebugUnitTest :app:check
```
Windows paths containing spaces need the scoped native-build workaround
documented in [docs/BUILDING.md](docs/BUILDING.md). The output is written under
`app/build/outputs/apk/debug/`.
### Use
1. Install and open FridaBox.
2. Tap **Import APK** and select an ARM64 base APK.
3. Choose **On-device**, **Computer**, or **Clean** on that guest's card.
4. Select an agent for On-device mode, or attach normally in Computer mode.
5. Inspect live state in the **Runtime** tab.
See [docs/USAGE.md](docs/USAGE.md) and
[docs/FRIDA_CONNECTION.md](docs/FRIDA_CONNECTION.md) for the complete workflow.
## Engineering and research
FridaBox is the outcome of runtime investigation rather than a wrapper around a
single `System.loadLibrary()` call. The project had to solve:
- ordering Gadget before guest `Application` creation without loading it in the
host process;
- preserving the guest's genuine `LoadedApk` ClassLoader for Java hooks;
- discovering the right loopback Gadget among colliding virtual processes;
- bundling `frida-java-bridge` explicitly for Frida 17 agents;
- making autonomous Script interaction work with private, read-only artifacts;
- maintaining reliable cross-process runtime state on Android;
- recycling virtual processes so instrumentation mode never leaks;
- satisfying Android 16 executable-file restrictions;
- keeping the imported APK byte-identical and outside the real PackageManager;
- producing reproducible debug/release builds across Windows path and NDK
constraints;
- replacing the inherited application shell with an independent FridaBox
product while preserving the mature runtime engine boundary.
Each problem, failed assumption, narrow fix, and verification method is recorded
in [the engineering journey](docs/ENGINEERING_JOURNEY.md).
## Repository map
```text
app/ FridaBox Android product, UI, import and per-app policy
Bcore/ Virtual Android runtime and instrumentation integration
black-reflection/ Hidden-framework reflection layer used by the runtime
compiler/ Compile-time reflection helpers
sample-guest/ Deterministic hook demonstration target
scripts/ Frida probe, bootstrap, sample and native agents
tools/ Gadget fetch, agent build, forwarding and attach tools
docs/ Build, usage, limitations and device evidence
```
## Scope and limitations
FridaBox currently targets single-file ARM64 APKs. Split APK sets, privileged or
system applications, full Google Play Services, Play Integrity, hardware-backed
attestation, and perfect anti-instrumentation resistance are outside the current
scope. Vendor behavior and hidden Android APIs can still affect compatibility.
FridaBox deliberately does not claim stealth. Frida mappings, sockets and
threads; virtual stub processes; the shared host UID; Binder synthesis; and
ClassLoader topology may all be observable. Read
[docs/LIMITATIONS.md](docs/LIMITATIONS.md) and
[docs/DETECTION_SURFACES.md](docs/DETECTION_SURFACES.md).
## Project status
FridaBox 4.0.0 is a device-validated research release. The full sample hook and
three-mode guest flow have passed on a Samsung SM-S928B running ARM64 Android
16/API 36. Compatibility reports for other devices and ROMs are welcome when
they include reproducible logs and authorized test targets.
See [CHANGELOG.md](CHANGELOG.md), [CONTRIBUTING.md](CONTRIBUTING.md), and
[SECURITY.md](SECURITY.md). Repository owners can use the
[GitHub publishing checklist](docs/GITHUB_PUBLISHING.md) for the first public
push, branch protection, topics, and release setup.
## Acknowledgements
FridaBox stands on years of work by the Android instrumentation and
virtualization communities.
- **[Frida](https://github.com/frida/frida)** provides the dynamic
instrumentation engine, Frida Gadget, GumJS, the Java bridge, and the tooling
model that makes this research possible. FridaBox pins and verifies Gadget
17.16.0 and uses the official Frida 17 Java-agent toolchain.
- **[NewBlackbox](https://github.com/ALEX5402/NewBlackbox)** and the broader
**BlackBox** project lineage provided the virtual package/process/Binder/IO
runtime foundation. FridaBox began from NewBlackbox commit
`89b59836c66f173756a4ae258cf379a957649820`, then added its instrumentation
lifecycle, controller protocol, per-app modes, integrity pipeline, research
tooling, validation suite, and independent product surface.
- The Android Open Source Project and its contributors provide the platform
interfaces and runtime behavior this project studies.
Thank you to every upstream maintainer and researcher who published the work
that made FridaBox possible. Ownership and license details are preserved in
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
## License
FridaBox is distributed under the [Apache License 2.0](LICENSE). Bundled Frida
components retain their own license terms; see
[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md).
+45
View File
@@ -0,0 +1,45 @@
# Security policy
## Supported version
FridaBox 4.x is the actively maintained research line. Older inherited launcher
versions are not supported.
## Reporting a vulnerability
Please use GitHub's private **Report a vulnerability** security-advisory flow for
this repository when it is available. Do not open a public issue for a flaw that
could expose imported APKs, JavaScript agents, device data, signing material, or
an unintended network listener.
Include:
- affected commit/version and Android build;
- device model, ABI, and ROM/vendor information;
- a minimal reproduction using an APK you are allowed to share;
- impact and the crossed trust boundary;
- sanitized logs or a small proof of concept;
- whether the issue reproduces in On-device, Computer, Clean, or all modes.
Please allow reasonable time for validation and a coordinated fix before public
disclosure.
## Security model
- FridaBox processes APKs and JavaScript selected explicitly by the user.
- Imported APKs and on-device agents are untrusted code and execute inside the
host application's Android security boundary.
- On-device agents have the same effective access as their virtual guest process.
- Gadget is configured for device loopback. ADB forwarding is an explicit
computer-side action.
- Private files reduce accidental exposure but do not create a hardware-backed
isolation boundary between the host, guest, and agent.
- FridaBox is not designed to hide from a hostile guest, kernel inspection,
SELinux inspection, Play Integrity, hardware attestation, or advanced RASP.
## Responsible use
Use FridaBox only on software and devices you own or are explicitly authorized
to assess. The maintainers do not support credential theft, unauthorized access,
surveillance, malware deployment, piracy, or bypassing protections outside a
lawful research or defensive-testing scope.
+16
View File
@@ -6,6 +6,18 @@ FridaBox is based on `ALEX5402/NewBlackbox` commit
`89b59836c66f173756a4ae258cf379a957649820`. The foundation repository includes
an Apache License 2.0 notice; see the repository root `LICENSE` file.
FridaBox gratefully acknowledges NewBlackbox and the wider BlackBox project
lineage for the virtual package, process, Binder, filesystem, identity,
signature, component, and lifecycle foundation. FridaBox's own work builds a
separate instrumentation product on that foundation: early Gadget integration,
guest runtime discovery, controller tooling, per-app launch modes, integrity and
ABI validation, on-device agent execution, the FridaBox UI, and the associated
test and research documentation.
- NewBlackbox source: `https://github.com/ALEX5402/NewBlackbox`
- Pinned foundation revision:
`https://github.com/ALEX5402/NewBlackbox/commit/89b59836c66f173756a4ae258cf379a957649820`
## Frida Gadget 17.16.0
- Origin: `https://github.com/frida/frida/releases/tag/17.16.0`
@@ -26,6 +38,10 @@ authoritative text is available at
Frida is copyright its respective contributors. FridaBox makes no claim of
ownership over Frida Gadget.
FridaBox gratefully acknowledges the Frida maintainers and contributors for the
instrumentation engine, GumJS runtime, Java bridge, Gadget deployment model, and
controller APIs that make this research possible.
## Frida Java bridge and agent compiler
The compiled JavaScript agents under `scripts/dist/` include
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 MiB

+256
View File
@@ -0,0 +1,256 @@
# Engineering journey
This document records the engineering problems that turned FridaBox from a
virtual-app proof of concept into a repeatable instrumentation workspace. It is
not a claim that every Android application will run; it is a map of the concrete
failure modes investigated, the narrow fixes selected, and the evidence used to
accept those fixes.
## 1. Establishing a buildable baseline
### Problem
The inherited project did not build reproducibly on the available Windows host.
AGP marker resolution differed from direct module resolution, the requested NDK
revision was unavailable, and `ndk-build` could not parse an `APP_BUILD_SCRIPT`
path containing spaces.
### Resolution
- Map Android plugin IDs to the official AGP module.
- Use the installed complete NDK 29.0.14206865 revision explicitly.
- Add a Bcore-scoped `FRIDABOX_NDK_PROJECT_DIR` override so only the native
build sees a no-space junction path.
- Record the exact deviation instead of silently changing toolchains.
### Evidence
The baseline investigation and commands are preserved in
[`BASELINE.md`](BASELINE.md). Both Java/Kotlin and native ARM64 builds now run
from the workspace path.
## 2. Finding the only useful early-load point
### Problem
Loading Gadget in the host `Application` instruments the wrong process. Loading
after guest `Application.onCreate()` is too late for early hooks. Loading before
virtual identity, IO redirection, and `LoadedApk` creation leaves Frida without
the correct guest environment.
### Resolution
Insert `FridaGadgetLoader.loadIfEnabled()` inside
`BActivityThread.handleBindApplication()` after runtime/native/ClassLoader setup
and before `makeApplication()`.
### Evidence
The sample guest logs `attachBaseContext` and `onCreate`. During Computer mode,
neither appeared until the Gadget client attached. A build verification task
also rejects source ordering regressions.
## 3. Preserving the original APK
### Problem
The common Gadget workflow mutates and resigns an APK, which changes the object
under study. Importing through Android's PackageInstaller would also place the
guest in the real system package database.
### Resolution
Stream the selected base APK through SAF into private storage, hash while
copying, inspect the archive, verify the private copy again, make it read-only,
and install only through the virtual package manager.
### Evidence
The generated sample asset and imported copy were byte-identical. `adb shell pm
list packages` did not contain the sample package while FridaBox could launch it.
## 4. Selecting the guest ClassLoader
### Problem
Frida's default Java factory can observe the host loader first in a virtual
process. A valid guest class then appears missing even though the application is
running.
### Resolution
Store the actual `LoadedApk` ClassLoader in `GuestRuntimeRegistry`. Load a
bootstrap agent before the user's script and assign that loader to
`Java.classFactory.loader`, with bounded retries during transient startup.
### Evidence
The controller reported `dalvik.system.PathClassLoader` and the sample hook
resolved `com.qm4rs.fridabox.sample.Target` before `Application.onCreate()`.
## 5. Discovering the correct Gadget endpoint
### Problem
Every virtual guest process begins with the same preferred Gadget port. Multiple
processes may move to fallback ports, while another unrelated Frida endpoint may
already exist on the device. A fixed `adb forward tcp:27042 tcp:27042` cannot
identify which guest it reached.
### Resolution
Use Gadget's bounded `pick-next` range, forward each candidate, probe it with a
FridaBox registry agent, reject endpoints without the expected registry, and map
valid endpoints to package and process.
### Evidence
`tools/attach_guest.py --list` discovered the correct sample endpoint and printed
package, process, user ID, virtual process ID, source APK, and ClassLoader.
## 6. Adapting agents to Frida 17
### Problem
Frida 17 API-loaded agents no longer receive the Java bridge implicitly. Plain
source scripts could load yet fail when calling `Java.perform()`.
### Resolution
Pin `frida-java-bridge` 7.0.13 and `frida-compile` 19.0.5, import the bridge
explicitly, commit reproducible bundles under `scripts/dist`, and teach the
controller to choose a compiled counterpart automatically.
### Evidence
Clean `npm ci` agent builds succeeded and the bundled sample hook changed
`Target.add(2, 3)` to `1337`.
## 7. Running an agent without a computer
### Problem
Interactive Gadget listen mode requires a host to attach and resume execution.
It cannot deliver the requested cable-free, persistent per-app behavior.
### Resolution
Add a per-package Script interaction mode. FridaBox copies the selected agent
byte-for-byte into private storage, records its SHA-256, generates an adjacent
relative-path config, and loads a private Gadget copy on every On-device launch.
### Evidence
A 198,960-byte real-world agent was imported with an identical SHA-256, marked
0400, loaded without a controller, and reached `local_script_active` before the
Unity guest became interactive.
## 8. Preventing launch-mode leakage
### Problem
Gadget is a native library. Once loaded, switching a living process to Clean
mode cannot reliably reverse its threads, mappings, hooks, or listener.
### Resolution
Treat mode changes as process-boundary changes. Stop the virtual package before
every relaunch and make each new process read the current per-package policy.
### Evidence
The validated clean launch used a different PID, emitted an explicit disabled
state, opened no Gadget listener, and restored the sample result from `1337` to
`5`.
## 9. Making runtime state honest across processes
### Problem
The guest registry is process-local. A host-screen read of cached
SharedPreferences could display stale `Waiting for computer` state even after an
On-device agent was active in another process.
### Resolution
Keep the registry authoritative inside the guest and use a deliberately small
controller snapshot with cross-process reload semantics for presentation.
### Evidence
The persisted state was correct during the failure. Reloading eliminated the
stale host display and subsequent On-device launches reported
`local_script_active` consistently.
## 10. Android 16 executable-file constraints
### Problem
Copying a writable native executable into app-private storage triggered modern
Android warnings and created an avoidable writable/executable overlap.
### Resolution
Finish copying and configuration first, then set the private Gadget executable
to mode 0555 and the agent to 0400 before loading.
### Evidence
The final Android 16 run reported the expected permissions and no longer emitted
the writable-executable warning for the private Gadget copy.
## 11. Building a real product boundary
### Problem
The inherited launcher mixed unrelated cloning, GMS, Xposed, fake-location, and
floating-overlay features with the instrumentation research. Its namespace,
resources, dependencies, and branding obscured the actual FridaBox workflow.
### Resolution
- Replace the launcher with a FridaBox-owned workspace and runtime UI.
- Move all host source and tests to `com.qm4rs.fridabox`.
- Replace the inherited `Application` shell with a minimal FridaBox runtime
bootstrap.
- Remove 7,000+ lines of unused UI code, obsolete resources, legacy AARs, and
stale product documentation.
- Keep the mature runtime engine as an internal compatibility boundary and
preserve its required attribution.
### Evidence
Debug/release assembly, app/Bcore tests, lint/check, reinstall, launcher resume,
guest restoration, and a real Clean-mode Unity launch all passed after removal.
## 12. Release safety and reproducibility
### Problem
Research APKs often accidentally ship with a debug key or depend on locally
generated assets whose provenance cannot be reproduced.
### Resolution
- Release signing is configured only when all four explicit keystore variables
are present; partial configuration fails and no debug fallback exists.
- R8 and resource shrinking are enabled for release.
- Gadget version and SHA-256 are pinned and verified before every app build.
- The debug sample is generated and embedded byte-identically.
- Frida 17 agents are reproducible from lockfile-pinned npm dependencies.
### Evidence
The debug signature verified, the unsigned release contained no debug signature,
and all custom integrity/order/packaging tasks passed. Current artifact hashes
are recorded in [`TEST_RESULTS.md`](TEST_RESULTS.md).
## Current research boundary
FridaBox demonstrates a robust architecture for ordinary single-file ARM64 APKs,
not universal Android virtualization. Split delivery, privileged/system apps,
Play Integrity, hardware-backed attestation, isolated services, WebView renderer
processes, and adversarial commercial RASP remain distinct research problems.
The project documents these boundaries rather than hiding them; see
[`LIMITATIONS.md`](LIMITATIONS.md) and
[`DETECTION_SURFACES.md`](DETECTION_SURFACES.md).
+1 -1
View File
@@ -9,7 +9,7 @@ python tools/build_frida_agents.py
```
The Gadget listens only on device loopback. The controller verifies ADB, selects
an authorized device, forwards TCP 27042–27073, probes each endpoint, rejects
an authorized device, forwards TCP 27042-27073, probes each endpoint, rejects
non-Gadget/non-FridaBox endpoints, and maps endpoints through
`GuestRuntimeRegistry`.
+73
View File
@@ -0,0 +1,73 @@
# GitHub publishing checklist
This repository is prepared to publish under the project name **FridaBox**.
## Suggested About description
> Android research workspace for per-app Frida Gadget instrumentation: on-device
> JavaScript, desktop attach, and clean launches without root or APK patching.
## Suggested topics
```text
android
android-security
arm64
dynamic-analysis
frida
frida-gadget
instrumentation
mobile-security
reverse-engineering
virtualization
kotlin
research
```
## Repository settings
- Set the default branch to `main`.
- Enable Issues and private vulnerability reporting.
- Enable Actions with read-only default workflow permissions.
- Add branch protection requiring the **Build, test, and verify** check.
- Require pull requests and dismiss stale approvals after new commits.
- Prevent force pushes and branch deletion on `main`.
- Enable Dependabot alerts and security updates.
- Add a social preview image only when it reflects the current FridaBox UI.
Do not reuse the removed legacy BlackBox64 GIF as the social preview.
## First push
Review the destination remote before pushing:
```text
git remote -v
git status
git log --oneline -5
```
Then push the intended branch explicitly:
```text
git push -u origin feature/fridabox-mvp
```
If this branch is intended to become the public default, create/review a pull
request into `main` and let Android CI finish before merging.
## Release checklist
1. Update `versionCode`, `versionName`, and `CHANGELOG.md`.
2. Run the host test and verification commands from `docs/BUILDING.md`.
3. Complete the device flow in `docs/TEST_RESULTS.md` on at least one supported
ARM64 Android version.
4. Build with all four `FRIDABOX_RELEASE_*` signing variables set.
5. Verify the release signature, packaged ABIs, Gadget hash, and absence of a
debug certificate.
6. Publish checksums with the APK and identify the tested device/Android build.
7. State known limitations and never describe FridaBox as undetectable.
The CI-produced release APK is intentionally unsigned unless a separate secure
release process provides signing credentials. Never store a keystore or signing
secret in the repository or workflow file.