diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
deleted file mode 100644
index ea23ea2..0000000
--- a/.github/FUNDING.yml
+++ /dev/null
@@ -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 ]
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..c997646
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -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
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..3ba13e0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@
+blank_issues_enabled: false
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 0000000..62883a5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -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
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000..45b2389
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -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.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..ac98147
--- /dev/null
+++ b/.github/dependabot.yml
@@ -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
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
new file mode 100644
index 0000000..b63b43e
--- /dev/null
+++ b/.github/workflows/android.yml
@@ -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
diff --git a/.github/workflows/build_and_telegram.yml b/.github/workflows/build_and_telegram.yml
deleted file mode 100644
index 18ed8a2..0000000
--- a/.github/workflows/build_and_telegram.yml
+++ /dev/null
@@ -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
-
diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md
index 609c379..9a63ad1 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -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. |
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..a1fda31
--- /dev/null
+++ b/CHANGELOG.md
@@ -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).
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..d496f49
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -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.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..2ed4b2d
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -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.
diff --git a/README.md b/README.md
index aabfbbf..e198aad 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,295 @@
+
+
# 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`.
+[](docs/TEST_RESULTS.md)
+[](docs/BUILDING.md)
+[](THIRD_PARTY_NOTICES.md)
+[](CHANGELOG.md)
+[](LICENSE)
+[](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).
+
-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).
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000..03a445c
--- /dev/null
+++ b/SECURITY.md
@@ -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.
diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index fb3cf91..2893e82 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -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
diff --git a/assets/usage.gif b/assets/usage.gif
deleted file mode 100644
index ef2bbb7..0000000
Binary files a/assets/usage.gif and /dev/null differ
diff --git a/docs/ENGINEERING_JOURNEY.md b/docs/ENGINEERING_JOURNEY.md
new file mode 100644
index 0000000..d4e4d64
--- /dev/null
+++ b/docs/ENGINEERING_JOURNEY.md
@@ -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).
diff --git a/docs/FRIDA_CONNECTION.md b/docs/FRIDA_CONNECTION.md
index 3d2cfba..c907f26 100644
--- a/docs/FRIDA_CONNECTION.md
+++ b/docs/FRIDA_CONNECTION.md
@@ -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`.
diff --git a/docs/GITHUB_PUBLISHING.md b/docs/GITHUB_PUBLISHING.md
new file mode 100644
index 0000000..ccd1c48
--- /dev/null
+++ b/docs/GITHUB_PUBLISHING.md
@@ -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.