diff --git a/.gitignore b/.gitignore index 286cd3a..1fe3280 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ __pycache__/ *.pyc node_modules/ .npm-cache/ +/release-secrets/ +/.release-work/ diff --git a/Bcore/build.gradle b/Bcore/build.gradle index 832b12b..8afb3da 100644 --- a/Bcore/build.gradle +++ b/Bcore/build.gradle @@ -26,7 +26,7 @@ android { consumerProguardFiles "consumer-rules.pro" ndk { - abiFilters 'arm64-v8a' + abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } diff --git a/Bcore/src/main/cpp/Application.mk b/Bcore/src/main/cpp/Application.mk index e9cabc3..9843b1b 100644 --- a/Bcore/src/main/cpp/Application.mk +++ b/Bcore/src/main/cpp/Application.mk @@ -1,4 +1,4 @@ -APP_ABI := armeabi-v7a arm64-v8a +APP_ABI := armeabi-v7a arm64-v8a x86 x86_64 APP_PLATFORM := android-24 APP_STL := c++_static APP_OPTIM := release diff --git a/Bcore/src/main/cpp/Dobby/x86/libdobby.a b/Bcore/src/main/cpp/Dobby/x86/libdobby.a new file mode 100644 index 0000000..83ceeb9 Binary files /dev/null and b/Bcore/src/main/cpp/Dobby/x86/libdobby.a differ diff --git a/Bcore/src/main/cpp/Dobby/x86_64/libdobby.a b/Bcore/src/main/cpp/Dobby/x86_64/libdobby.a new file mode 100644 index 0000000..f723af3 Binary files /dev/null and b/Bcore/src/main/cpp/Dobby/x86_64/libdobby.a differ diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/utils/AbiUtils.java b/Bcore/src/main/java/top/niunaijun/blackbox/utils/AbiUtils.java index 4758283..7a85863 100644 --- a/Bcore/src/main/java/top/niunaijun/blackbox/utils/AbiUtils.java +++ b/Bcore/src/main/java/top/niunaijun/blackbox/utils/AbiUtils.java @@ -43,10 +43,14 @@ public class AbiUtils { String name = zipEntry.getName(); if (name.startsWith("lib/arm64-v8a")) { mLibs.add("arm64-v8a"); - } else if (name.startsWith("lib/armeabi")) { - mLibs.add("armeabi"); } else if (name.startsWith("lib/armeabi-v7a")) { mLibs.add("armeabi-v7a"); + } else if (name.startsWith("lib/armeabi")) { + mLibs.add("armeabi"); + } else if (name.startsWith("lib/x86_64")) { + mLibs.add("x86_64"); + } else if (name.startsWith("lib/x86")) { + mLibs.add("x86"); } } } catch (Exception e) { @@ -57,11 +61,11 @@ public class AbiUtils { } public boolean is64Bit() { - return mLibs.contains("arm64-v8a"); + return mLibs.contains("arm64-v8a") || mLibs.contains("x86_64"); } public boolean is32Bit() { - return mLibs.contains("armeabi") || mLibs.contains("armeabi-v7a"); + return mLibs.contains("armeabi") || mLibs.contains("armeabi-v7a") || mLibs.contains("x86"); } public boolean isEmptyAib() { diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/utils/NativeUtils.java b/Bcore/src/main/java/top/niunaijun/blackbox/utils/NativeUtils.java index f21b8fd..170b150 100644 --- a/Bcore/src/main/java/top/niunaijun/blackbox/utils/NativeUtils.java +++ b/Bcore/src/main/java/top/niunaijun/blackbox/utils/NativeUtils.java @@ -25,8 +25,10 @@ public class NativeUtils { nativeLibDir.mkdirs(); } try (ZipFile zipfile = new ZipFile(apk.getAbsolutePath())) { - if (findAndCopyNativeLib(zipfile, Build.CPU_ABI, nativeLibDir)) { - return; + for (String abi : Build.SUPPORTED_ABIS) { + if (findAndCopyNativeLib(zipfile, abi, nativeLibDir)) { + return; + } } findAndCopyNativeLib(zipfile, "armeabi", nativeLibDir); diff --git a/CHANGELOG.md b/CHANGELOG.md index b751610..abff1d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ versioning for its public releases. ## [Unreleased] +## [4.1.0] - 2026-07-28 + +### Added + +- Separate release APKs for `armeabi-v7a`, `arm64-v8a`, `x86`, and `x86_64`. +- In-app APK inspection now accepts supported 32-bit ARM and x86 guest ABIs. +- Downloadable official Frida Gadget management, including ABI validation and + on-device or computer-controlled runtime selection. +- A liquid-glass launcher, downloadable Gadget screen, and guest log overlay. + +### Changed + +- Updated application iconography, navigation, runtime visibility, and release + dependency set. + ### Documentation - Added the public research roadmap for Frida visibility, `/proc`/maps diff --git a/app/build.gradle b/app/build.gradle index 45b0369..a1ed126 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -32,7 +32,7 @@ android { enable true reset() - include "arm64-v8a" + include "armeabi-v7a", "arm64-v8a", "x86", "x86_64" universalApk false } } @@ -106,12 +106,17 @@ tasks.matching { it.name.toLowerCase().contains("debug") && it.name.toLowerCase( tasks.register("verifyDebugApkHasNoGadget") { dependsOn("assembleDebug") doLast { - def apk = fileTree("$buildDir/outputs/apk/debug").matching { include("*.apk") }.singleFile - def entries = zipTree(apk).files.findAll { - it.name.toLowerCase().contains("gadget") && it.name.toLowerCase().endsWith(".so") + def apks = fileTree("$buildDir/outputs/apk/debug").matching { include("*.apk") }.files + if (apks.isEmpty()) { + throw new GradleException("No debug APKs were produced") } - if (!entries.isEmpty()) { - throw new GradleException("APK must not bundle Frida Gadget: ${entries*.name}") + apks.each { apk -> + def entries = zipTree(apk).files.findAll { + it.name.toLowerCase().contains("gadget") && it.name.toLowerCase().endsWith(".so") + } + if (!entries.isEmpty()) { + throw new GradleException("${apk.name} must not bundle Frida Gadget: ${entries*.name}") + } } } } diff --git a/app/src/main/java/com/qm4rs/fridabox/ApkInspector.java b/app/src/main/java/com/qm4rs/fridabox/ApkInspector.java index aab920d..31a5e9c 100644 --- a/app/src/main/java/com/qm4rs/fridabox/ApkInspector.java +++ b/app/src/main/java/com/qm4rs/fridabox/ApkInspector.java @@ -44,7 +44,7 @@ public final class ApkInspector { } } if (!inspectedAny) throw new IOException("No APK files were provided"); - boolean supported = !hasNativeLibraries || abis.contains("arm64-v8a"); + boolean supported = !hasNativeLibraries || !Collections.disjoint(abis, SUPPORTED_ABIS); return new Result(hasNativeLibraries, supported, abis); } @@ -61,7 +61,11 @@ public final class ApkInspector { public String description() { if (!hasNativeLibraries) return "Pure Java/Kotlin (accepted)"; - return supported ? "ARM64 supported: " + abis : "Rejected; no arm64-v8a: " + abis; + return supported ? "Supported ABI: " + abis : "Rejected; unsupported ABI: " + abis; } } + + private static final Set SUPPORTED_ABIS = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList( + "armeabi-v7a", "arm64-v8a", "x86", "x86_64" + ))); } diff --git a/app/src/test/java/com/qm4rs/fridabox/ApkInspectorTest.java b/app/src/test/java/com/qm4rs/fridabox/ApkInspectorTest.java index c0d7a94..72f8c76 100644 --- a/app/src/test/java/com/qm4rs/fridabox/ApkInspectorTest.java +++ b/app/src/test/java/com/qm4rs/fridabox/ApkInspectorTest.java @@ -31,10 +31,17 @@ public class ApkInspectorTest { } @Test - public void thirtyTwoBitOnlyApkIsRejected() throws Exception { + public void thirtyTwoBitOnlyApkIsAccepted() throws Exception { ApkInspector.Result result = ApkInspector.inspect(apkWith("lib/armeabi-v7a/libsample.so")); assertTrue(result.hasNativeLibraries); - assertFalse(result.supported); + assertTrue(result.supported); + } + + @Test + public void x86ApkIsAccepted() throws Exception { + ApkInspector.Result result = ApkInspector.inspect(apkWith("lib/x86/libsample.so")); + assertTrue(result.hasNativeLibraries); + assertTrue(result.supported); } @Test diff --git a/build.gradle b/build.gradle index 52651d7..fd3bd07 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,8 @@ ext { targetSdkVersion = 28 minSdk = 21 - versionCode = 400 - versionName = "4.0.0" + versionCode = 401 + versionName = "4.1.0" xVersion = '1.1.0' hiddenApiBypass = '4.3' } diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 1603f6d..473353c 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -51,7 +51,8 @@ Build and test: The debug host build depends on the sample build and copies its byte-identical APK into generated debug assets. Generated sample APKs are not source-controlled. -The final host output is under `app/build/outputs/apk/debug/` and is ARM64-only. +The final host outputs are under `app/build/outputs/apk/debug/` for `armeabi-v7a`, +`arm64-v8a`, `x86`, and `x86_64`. `verifyDebugApkHasNoGadget` inspects the assembled APK and fails if a Gadget library or configuration is accidentally bundled again. @@ -82,5 +83,5 @@ If only some signing variables are present, configuration fails instead of producing an ambiguously signed artifact. Keep the keystore and credentials outside the repository and CI logs. -The ARM64 release output is written to -`app/build/outputs/apk/release/FridaBox_4.0.0_arm64-v8a-release.apk`. +Release outputs are written to `app/build/outputs/apk/release/`, one APK each for +`armeabi-v7a`, `arm64-v8a`, `x86`, and `x86_64`.