diff --git a/.gitignore b/.gitignore index 0d8cd69..286cd3a 100644 --- a/.gitignore +++ b/.gitignore @@ -17,8 +17,13 @@ *.logcat .vscode /build +**/build/ /captures .externalNativeBuild .cxx local.properties /app/release/ +__pycache__/ +*.pyc +node_modules/ +.npm-cache/ diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..609c379 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,57 @@ +# 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. + +```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 +``` + +## 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. diff --git a/Bcore/build.gradle b/Bcore/build.gradle index 857d57e..7eb4117 100644 --- a/Bcore/build.gradle +++ b/Bcore/build.gradle @@ -1,9 +1,15 @@ apply plugin: 'com.android.library' +def fridaBoxNdkProjectDir = System.getenv('FRIDABOX_NDK_PROJECT_DIR') ?: project.projectDir.absolutePath +if (System.getenv('FRIDABOX_NDK_PROJECT_DIR')) { + layout.buildDirectory.set(file("${fridaBoxNdkProjectDir}/build")) +} + android { namespace 'top.niunaijun.blackbox' compileSdk rootProject.ext.compileSdkVersion + ndkVersion = "29.0.14206865" aidlPackagedList "android/app/IServiceConnection.aidl" @@ -19,8 +25,7 @@ android { consumerProguardFiles "consumer-rules.pro" ndk { - - abiFilters 'arm64-v8a' , 'armeabi-v7a' + abiFilters 'arm64-v8a' } } @@ -33,9 +38,8 @@ android { externalNativeBuild { ndkBuild { - path 'src/main/cpp/Android.mk' + path file("${fridaBoxNdkProjectDir}/src/main/cpp/Android.mk") } - ndkVersion = "29.0.13846066" } compileOptions { @@ -106,6 +110,7 @@ dependencies { implementation 'com.moandjiezana.toml:toml4j:0.7.2' implementation 'com.github.tiann:FreeReflection:3.2.2' + testImplementation libs.junit diff --git a/Bcore/consumer-rules.pro b/Bcore/consumer-rules.pro index 0d7cb9b..c3aba30 100644 --- a/Bcore/consumer-rules.pro +++ b/Bcore/consumer-rules.pro @@ -26,3 +26,5 @@ -keep class android.** {*; } -keep class com.android.** {*; } +-keep class top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry { public static *; } +-keep class top.niunaijun.blackbox.instrumentation.FridaGadgetLoader { public static *; } diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/app/BActivityThread.java b/Bcore/src/main/java/top/niunaijun/blackbox/app/BActivityThread.java index 61b9d7f..13d7a2b 100644 --- a/Bcore/src/main/java/top/niunaijun/blackbox/app/BActivityThread.java +++ b/Bcore/src/main/java/top/niunaijun/blackbox/app/BActivityThread.java @@ -85,6 +85,10 @@ import top.niunaijun.blackbox.utils.compat.BuildCompat; import top.niunaijun.blackbox.utils.compat.ContextCompat; import top.niunaijun.blackbox.utils.compat.StrictModeCompat; import top.niunaijun.blackbox.core.system.JarManager; +import top.niunaijun.blackbox.instrumentation.FridaGadgetLoader; +import top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry; +import top.niunaijun.blackbox.instrumentation.InstrumentationSettings; +import top.niunaijun.blackbox.instrumentation.InstrumentationStatusStore; public class BActivityThread extends IBActivityThread.Stub { @@ -403,6 +407,21 @@ public class BActivityThread extends IBActivityThread.Stub { assert packageContext != null; IOCore.get().enableRedirect(packageContext); + ClassLoader guestClassLoader = BRLoadedApk.get(loadedApk).getClassLoader(); + boolean instrumentationEnabled = InstrumentationSettings.isEnabledForPackage(packageName); + GuestRuntimeRegistry.initialize(packageName, processName, getUserId(), getAppPid(), + applicationInfo, guestClassLoader, instrumentationEnabled); + InstrumentationStatusStore.recordBinding(); + if (guestClassLoader != null) { + try { + Thread.currentThread().setContextClassLoader(guestClassLoader); + } catch (SecurityException error) { + GuestRuntimeRegistry.setLastError(error); + Slog.w(TAG, "Unable to set guest context ClassLoader: " + error.getMessage()); + } + } + FridaGadgetLoader.loadIfEnabled(); + AppBindData bindData = new AppBindData(); bindData.appInfo = applicationInfo; bindData.processName = processName; diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/FridaGadgetLoader.java b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/FridaGadgetLoader.java new file mode 100644 index 0000000..68cb9f7 --- /dev/null +++ b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/FridaGadgetLoader.java @@ -0,0 +1,50 @@ +package top.niunaijun.blackbox.instrumentation; + +import android.util.Log; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** Loads Frida Gadget at most once in the current Linux process. */ +public final class FridaGadgetLoader { + private static final String TAG = "FridaBox.Gadget"; + private static final AtomicBoolean ATTEMPTED = new AtomicBoolean(false); + private static final Object LOAD_LOCK = new Object(); + private static volatile boolean loaded; + + private FridaGadgetLoader() { + } + + public static boolean loadIfEnabled() { + if (!GuestRuntimeRegistry.isInstrumentationEnabled()) { + Log.i(TAG, "Instrumentation disabled for this guest process"); + return false; + } + if (loaded) return true; + synchronized (LOAD_LOCK) { + if (loaded) return true; + if (!ATTEMPTED.compareAndSet(false, true)) return false; + try { + InstrumentationStatusStore.recordBinding(); + Log.i(TAG, "Loading Frida Gadget for " + GuestRuntimeRegistry.getGuestProcessName()); + System.loadLibrary("frida-gadget"); + loaded = true; + InstrumentationStatusStore.recordLoaded(); + Log.i(TAG, "Frida Gadget loaded"); + return true; + } catch (UnsatisfiedLinkError | SecurityException error) { + GuestRuntimeRegistry.setLastError(error); + InstrumentationStatusStore.recordError(GuestRuntimeRegistry.getLastError()); + Log.e(TAG, "Frida Gadget load failed; guest will continue", error); + } catch (Throwable error) { + GuestRuntimeRegistry.setLastError(error); + InstrumentationStatusStore.recordError(GuestRuntimeRegistry.getLastError()); + Log.e(TAG, "Unexpected Frida Gadget initialization failure; guest will continue", error); + } + return false; + } + } + + public static boolean isLoaded() { + return loaded; + } +} diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistry.java b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistry.java new file mode 100644 index 0000000..ae78306 --- /dev/null +++ b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistry.java @@ -0,0 +1,88 @@ +package top.niunaijun.blackbox.instrumentation; + +import android.content.pm.ApplicationInfo; + +/** Process-local guest metadata exposed to Frida scripts. */ +public final class GuestRuntimeRegistry { + private static volatile String guestPackageName; + private static volatile String guestProcessName; + private static volatile int guestUserId = -1; + private static volatile int virtualProcessId = -1; + private static volatile ApplicationInfo guestApplicationInfo; + private static volatile ClassLoader guestClassLoader; + private static volatile String guestSourceDir; + private static volatile boolean instrumentationEnabled; + private static volatile String lastError; + private static volatile long initializationTimestamp; + + private GuestRuntimeRegistry() { + } + + public static synchronized void initialize(String packageName, String processName, + int userId, int processId, + ApplicationInfo applicationInfo, + ClassLoader classLoader, + boolean enabled) { + guestPackageName = packageName; + guestProcessName = processName; + guestUserId = userId; + virtualProcessId = processId; + guestApplicationInfo = applicationInfo; + guestClassLoader = classLoader; + guestSourceDir = applicationInfo == null ? null : applicationInfo.sourceDir; + instrumentationEnabled = enabled; + lastError = null; + initializationTimestamp = System.currentTimeMillis(); + } + + public static synchronized void clear() { + guestPackageName = null; + guestProcessName = null; + guestUserId = -1; + virtualProcessId = -1; + guestApplicationInfo = null; + guestClassLoader = null; + guestSourceDir = null; + instrumentationEnabled = false; + lastError = null; + initializationTimestamp = 0L; + } + + public static String getGuestPackageName() { return guestPackageName; } + public static String getGuestProcessName() { return guestProcessName; } + public static int getGuestUserId() { return guestUserId; } + public static int getVirtualProcessId() { return virtualProcessId; } + public static ApplicationInfo getGuestApplicationInfo() { return guestApplicationInfo; } + public static ClassLoader getGuestClassLoader() { return guestClassLoader; } + public static String getGuestSourceDir() { return guestSourceDir; } + public static boolean isInstrumentationEnabled() { return instrumentationEnabled; } + public static String getLastError() { return lastError; } + public static long getInitializationTimestamp() { return initializationTimestamp; } + + public static void setLastError(Throwable error) { + lastError = error == null ? null : error.getClass().getSimpleName() + ": " + error.getMessage(); + } + + public static void setLastError(String error) { + lastError = error; + } + + private static String quote(String value) { + if (value == null) return "null"; + return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + .replace("\n", "\\n").replace("\r", "\\r") + "\""; + } + + public static String describe() { + return "{" + + "\"package\":" + quote(guestPackageName) + ',' + + "\"process\":" + quote(guestProcessName) + ',' + + "\"userId\":" + guestUserId + ',' + + "\"virtualProcessId\":" + virtualProcessId + ',' + + "\"sourceDir\":" + quote(guestSourceDir) + ',' + + "\"instrumentationEnabled\":" + instrumentationEnabled + ',' + + "\"lastError\":" + quote(lastError) + ',' + + "\"initializedAt\":" + initializationTimestamp + + '}'; + } +} diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationSettings.java b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationSettings.java new file mode 100644 index 0000000..be9ae63 --- /dev/null +++ b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationSettings.java @@ -0,0 +1,54 @@ +package top.niunaijun.blackbox.instrumentation; + +import android.content.Context; +import android.content.SharedPreferences; + +import top.niunaijun.blackbox.BlackBoxCore; + +/** Shared host preferences read independently by each virtual process. */ +public final class InstrumentationSettings { + public static final String PREFERENCES = "fridabox_instrumentation"; + public static final String KEY_ENABLED = "instrumentation_enabled"; + public static final String KEY_BASE_PORT = "frida_base_port"; + public static final String KEY_SCAN_COUNT = "frida_port_scan_count"; + public static final String KEY_ADVANCED_LOGS = "show_advanced_logs"; + private static final String PACKAGE_PREFIX = "package_enabled_"; + + private InstrumentationSettings() { + } + + private static SharedPreferences preferences() { + Context context = BlackBoxCore.getContext(); + return context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); + } + + public static boolean isGloballyEnabled() { + return preferences().getBoolean(KEY_ENABLED, true); + } + + public static boolean isEnabledForPackage(String packageName) { + SharedPreferences preferences = preferences(); + return preferences.getBoolean(KEY_ENABLED, true) + && preferences.getBoolean(PACKAGE_PREFIX + packageName, true); + } + + public static void setEnabledForPackage(String packageName, boolean enabled) { + preferences().edit().putBoolean(PACKAGE_PREFIX + packageName, enabled).commit(); + } + + public static int getBasePort() { + return clamp(preferences().getInt(KEY_BASE_PORT, 27042), 1024, 65535, 27042); + } + + public static int getPortScanCount() { + return clamp(preferences().getInt(KEY_SCAN_COUNT, 32), 1, 128, 32); + } + + public static boolean showAdvancedLogs() { + return preferences().getBoolean(KEY_ADVANCED_LOGS, false); + } + + static int clamp(int value, int minimum, int maximum, int fallback) { + return value < minimum || value > maximum ? fallback : value; + } +} diff --git a/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationStatusStore.java b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationStatusStore.java new file mode 100644 index 0000000..1ae046e --- /dev/null +++ b/Bcore/src/main/java/top/niunaijun/blackbox/instrumentation/InstrumentationStatusStore.java @@ -0,0 +1,40 @@ +package top.niunaijun.blackbox.instrumentation; + +import android.content.Context; +import android.content.SharedPreferences; + +import top.niunaijun.blackbox.BlackBoxCore; + +/** Small cross-process status snapshot for the host runtime screen. */ +public final class InstrumentationStatusStore { + private InstrumentationStatusStore() { + } + + private static SharedPreferences preferences() { + return BlackBoxCore.getContext().getSharedPreferences( + InstrumentationSettings.PREFERENCES, Context.MODE_PRIVATE); + } + + public static void recordBinding() { + String packageName = GuestRuntimeRegistry.getGuestPackageName(); + preferences().edit() + .putString("runtime_package", packageName) + .putString("runtime_process", GuestRuntimeRegistry.getGuestProcessName()) + .putInt("runtime_vpid", GuestRuntimeRegistry.getVirtualProcessId()) + .putString("runtime_source", GuestRuntimeRegistry.getGuestSourceDir()) + .putBoolean("runtime_enabled", GuestRuntimeRegistry.isInstrumentationEnabled()) + .putString("runtime_state", GuestRuntimeRegistry.isInstrumentationEnabled() + ? "waiting_for_attach" : "disabled") + .putString("runtime_error", null) + .putLong("runtime_timestamp", GuestRuntimeRegistry.getInitializationTimestamp()) + .commit(); + } + + public static void recordLoaded() { + preferences().edit().putString("runtime_state", "loaded").putString("runtime_error", null).commit(); + } + + public static void recordError(String error) { + preferences().edit().putString("runtime_state", "failed").putString("runtime_error", error).commit(); + } +} diff --git a/Bcore/src/test/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistryTest.java b/Bcore/src/test/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistryTest.java new file mode 100644 index 0000000..63d950d --- /dev/null +++ b/Bcore/src/test/java/top/niunaijun/blackbox/instrumentation/GuestRuntimeRegistryTest.java @@ -0,0 +1,44 @@ +package top.niunaijun.blackbox.instrumentation; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import android.content.pm.ApplicationInfo; + +import org.junit.After; +import org.junit.Test; + +public class GuestRuntimeRegistryTest { + @After + public void clearRegistry() { + GuestRuntimeRegistry.clear(); + } + + @Test + public void initializeReplacesProcessLocalSnapshot() { + ApplicationInfo info = new ApplicationInfo(); + info.sourceDir = "/private/original.apk"; + ClassLoader loader = getClass().getClassLoader(); + GuestRuntimeRegistry.initialize("sample.one", "sample.one:remote", 3, 7, info, loader, true); + + assertEquals("sample.one", GuestRuntimeRegistry.getGuestPackageName()); + assertEquals("sample.one:remote", GuestRuntimeRegistry.getGuestProcessName()); + assertEquals(3, GuestRuntimeRegistry.getGuestUserId()); + assertEquals(7, GuestRuntimeRegistry.getVirtualProcessId()); + assertSame(loader, GuestRuntimeRegistry.getGuestClassLoader()); + assertEquals("/private/original.apk", GuestRuntimeRegistry.getGuestSourceDir()); + assertTrue(GuestRuntimeRegistry.isInstrumentationEnabled()); + assertTrue(GuestRuntimeRegistry.describe().contains("\"package\":\"sample.one\"")); + } + + @Test + public void clearRemovesPriorGuest() { + GuestRuntimeRegistry.initialize("sample", "sample", 0, 1, null, null, true); + GuestRuntimeRegistry.clear(); + assertEquals(null, GuestRuntimeRegistry.getGuestPackageName()); + assertEquals(-1, GuestRuntimeRegistry.getGuestUserId()); + assertFalse(GuestRuntimeRegistry.isInstrumentationEnabled()); + } +} diff --git a/README.md b/README.md index 72cbedd..d4ac61d 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,35 @@ -# BlackBox - Virtual Engine +# FridaBox -

- BlackBox Banner -

+FridaBox is an authorized mobile-security research MVP that runs an original, +unmodified APK inside BlackBox 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. -BlackBox is a virtual engine that allows you to clone and run virtual applications on Android devices without installing APKs. This project works on Android 5.0 to 14.0+ and supports multiple architectures (ARM64, ARMv7, x86). +The foundation is `ALEX5402/NewBlackbox` commit +`89b59836c66f173756a4ae258cf379a957649820`. The host application ID is +`com.qm4rs.fridabox`; existing engine namespaces remain unchanged. -## Overview +## MVP capabilities -This enhanced edition includes bug fixes, stability improvements, and Android 14+ compatibility tailored for modern devices. +- SAF import of one base APK into app-private, read-only storage. +- SHA-256 verification before and after BlackBox 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. -### Key Features +Start with [docs/BUILDING.md](docs/BUILDING.md), [docs/USAGE.md](docs/USAGE.md), +and [docs/FRIDA_CONNECTION.md](docs/FRIDA_CONNECTION.md). -* **Virtual App Cloning**: Run multiple instances of applications. -* **Sandboxed Environment**: Isolated process execution. -* **No Root Required**: Runs entirely in userspace. -* **Multi-Architecture**: Support for 32-bit and 64-bit apps. -* **Device Spoofing**: Modify device information for virtual apps. -* **Fake Location**: Spoof GPS coordinates. +FridaBox is not undetectable. See [docs/DETECTION_SURFACES.md](docs/DETECTION_SURFACES.md) +and [docs/LIMITATIONS.md](docs/LIMITATIONS.md). -## Requirements - -* **Android Version**: Android 5.0 (API 21) or higher. -* **RAM**: 2GB minimum recommended. -* **Architecture**: ARMv7a, ARM64-v8a, x86. - -## Build Instructions - -### Prerequisites -* Android Studio (Arctic Fox or newer) -* JDK 17 -* Android SDK 34+ -* NDK (Version 29.0.13846066) - -### Building from Source - -```bash -# Clone the repository -git clone https://github.com/your-repo/NewBlackbox.git -cd NewBlackbox - -# Build Debug APK -./gradlew assembleDebug - -# Build Release APK -./gradlew assembleRelease -``` - -## Integration - -To use BlackBox Core in your own project, add the AAR dependency: - -```gradle -dependencies { - implementation fileTree(dir: "libs", include: ["*.aar"]) -} -``` - -Refer to `Docs.md` for detailed API documentation. - -## Troubleshooting - -* **App Crashes**: Check logcat for UID mismatches or permission errors. -* **Installation Failures**: Verify potential architecture mismatches or storage permissions. -* **Android 15**: Ensure you are using the latest build which handles stricter security policies. - -## Credits - -* **Main Developer**: ALEX502 -* **Original Framework**: VirtualApp, VirtualAPK -* **Native Hooks**: Dobby, xDL -* **Reflection**: BlackReflection, FreeReflection - -## License - -Copyright 2022 BlackBox - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. +The complete Android 16 device transcript is in +[docs/device-validation.log](docs/device-validation.log). diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..fb3cf91 --- /dev/null +++ b/THIRD_PARTY_NOTICES.md @@ -0,0 +1,41 @@ +# Third-party notices + +## NewBlackbox / BlackBox + +FridaBox is based on `ALEX5402/NewBlackbox` commit +`89b59836c66f173756a4ae258cf379a957649820`. The foundation repository includes +an Apache License 2.0 notice; see the repository root `LICENSE` file. + +## Frida Gadget 17.16.0 + +- Origin: `https://github.com/frida/frida/releases/tag/17.16.0` +- Asset: `frida-gadget-17.16.0-android-arm64.so.xz` +- Installed filename: `libfrida-gadget.so` +- SHA-256 after XZ decompression: + `6bf149e5d1c5ec701e7b822cab57bb243f1c2a03318fa974fe373ee711a9ed9e` +- License: wxWindows Library Licence, Version 3.1, as stated by the official + Frida 17.16.0 `COPYING` file. + +The wxWindows licence permits redistribution/modification under GNU Library +General Public Licence version 2 or later and includes an exception permitting +binary object code versions of works based on the library to be used, copied, +linked, modified, and distributed under the distributor's own terms. The full +authoritative text is available at +`https://github.com/frida/frida/blob/17.16.0/COPYING`. + +Frida is copyright its respective contributors. FridaBox makes no claim of +ownership over Frida Gadget. + +## Frida Java bridge and agent compiler + +The compiled JavaScript agents under `scripts/dist/` include +`frida-java-bridge` 7.0.13. They are built with `frida-compile` 19.0.5. + +- Java bridge origin: `https://github.com/frida/frida-java-bridge` +- Compiler origin: `https://github.com/frida/frida-compile` +- License: LGPL-2.0 with the wxWindows Library Licence 3.1 exception, as + declared by the respective official packages. + +The authoritative licence text and exception are the same wxWindows Library +Licence described above. Exact package versions and dependency integrity hashes +are preserved in `package-lock.json`. diff --git a/app/build.gradle b/app/build.gradle index a5ce1ad..fb8fb77 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,9 +7,9 @@ android { namespace 'top.niunaijun.blackboxa' compileSdk rootProject.ext.compileSdkVersion - ndkVersion = "29.0.13846066" + ndkVersion = "29.0.14206865" defaultConfig { - applicationId "top.niunaijun.blackbox" + applicationId "com.qm4rs.fridabox" minSdk rootProject.ext.minSdk targetSdk rootProject.ext.targetSdkVersion versionCode rootProject.ext.versionCode @@ -22,8 +22,8 @@ android { enable true reset() - include 'armeabi-v7a', "arm64-v8a" - universalApk true + include "arm64-v8a" + universalApk false } } } @@ -41,6 +41,10 @@ android { } buildFeatures { viewBinding true + buildConfig true + } + sourceSets { + debug.assets.srcDir("$buildDir/generated/demoGuestAssets") } kotlinOptions { jvmTarget = '21' @@ -48,6 +52,8 @@ android { packaging { jniLibs { excludes.add("**/libandroidx.graphics.path.so") + useLegacyPackaging true + keepDebugSymbols.add("**/libfrida-gadget.config.so") } resources { excludes.add("**/libandroidx.graphics.path.so") @@ -55,9 +61,88 @@ android { } applicationVariants.configureEach { variant -> variant.outputs.configureEach { output -> - output.outputFileName = "BlackBox_${variant.versionName}_${output.baseName}.apk" + output.outputFileName = "FridaBox_${variant.versionName}_${output.baseName}.apk" } } + lint { + abortOnError false + checkReleaseBuilds false + } +} + +tasks.register("copyDemoGuestDebug", Copy) { + dependsOn(":sample-guest:assembleDebug") + from(project(":sample-guest").layout.buildDirectory.file("outputs/apk/debug/sample-guest-debug.apk")) + into(layout.buildDirectory.dir("generated/demoGuestAssets/demo")) + rename { "sample-guest.apk" } +} +tasks.matching { it.name == "mergeDebugAssets" }.configureEach { dependsOn("copyDemoGuestDebug") } +tasks.matching { it.name.toLowerCase().contains("debug") && it.name.toLowerCase().contains("lint") } + .configureEach { dependsOn("copyDemoGuestDebug") } + +def fridaGadget = file("src/main/jniLibs/arm64-v8a/libfrida-gadget.so") +def fridaGadgetConfig = file("src/main/jniLibs/arm64-v8a/libfrida-gadget.config.so") +tasks.register("verifyFridaGadget") { + inputs.files(fridaGadget, fridaGadgetConfig) + doLast { + if (!fridaGadget.isFile()) { + throw new GradleException("Frida Gadget 17.16.0 is missing. Run: python tools/fetch_frida_gadget.py") + } + if (!fridaGadgetConfig.isFile()) { + throw new GradleException("Frida Gadget configuration is missing: ${fridaGadgetConfig}") + } + def digest = java.security.MessageDigest.getInstance("SHA-256") + .digest(fridaGadget.bytes).collect { String.format("%02x", it & 0xff) }.join() + if (digest != "6bf149e5d1c5ec701e7b822cab57bb243f1c2a03318fa974fe373ee711a9ed9e") { + throw new GradleException("Frida Gadget 17.16.0 SHA-256 mismatch: ${digest}") + } + def config = new groovy.json.JsonSlurper().parse(fridaGadgetConfig) + if (config.interaction?.address != "127.0.0.1" || config.interaction?.on_load != "wait") { + throw new GradleException("Unsafe or invalid Frida Gadget configuration") + } + } +} +tasks.matching { it.name == "preBuild" }.configureEach { dependsOn("verifyFridaGadget") } + +tasks.register("verifyDebugApkFridaPackaging") { + dependsOn("assembleDebug") + doLast { + def apk = fileTree("$buildDir/outputs/apk/debug").matching { include("*.apk") }.singleFile + def entries = zipTree(apk).matching { + include("lib/arm64-v8a/libfrida-gadget.so") + include("lib/arm64-v8a/libfrida-gadget.config.so") + }.files.collect { it.name }.toSet() + if (!entries.contains("libfrida-gadget.so") || !entries.contains("libfrida-gadget.config.so")) { + throw new GradleException("Debug APK does not contain both Frida Gadget files") + } + } +} + +tasks.register("verifyInstrumentationOrdering") { + doLast { + def source = project(":Bcore").file("src/main/java/top/niunaijun/blackbox/app/BActivityThread.java").text + def loader = source.indexOf("FridaGadgetLoader.loadIfEnabled()") + def makeApplication = source.indexOf("makeApplication(", loader) + if (loader < 0 || makeApplication < 0 || loader >= makeApplication) { + throw new GradleException("Frida Gadget loader must execute before guest makeApplication") + } + } +} + +tasks.register("verifyDemoGuestUnmodified") { + dependsOn("copyDemoGuestDebug") + doLast { + def source = project(":sample-guest").layout.buildDirectory.file("outputs/apk/debug/sample-guest-debug.apk").get().asFile + def embedded = layout.buildDirectory.file("generated/demoGuestAssets/demo/sample-guest.apk").get().asFile + if (!java.util.Arrays.equals(java.security.MessageDigest.getInstance("SHA-256").digest(source.bytes), + java.security.MessageDigest.getInstance("SHA-256").digest(embedded.bytes))) { + throw new GradleException("Embedded sample APK differs from generated sample APK") + } + } +} + +tasks.named("check").configure { + dependsOn("verifyDebugApkFridaPackaging", "verifyInstrumentationOrdering", "verifyDemoGuestUnmodified") } dependencies { diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index f4e5465..98441e5 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -41,4 +41,6 @@ @top.niunaijun.blackreflection.annotation.BMethodCheckNotProcess.* ; @top.niunaijun.blackreflection.annotation.BConstructor.* ; @top.niunaijun.blackreflection.annotation.BConstructorNotProcess.* ; -} \ No newline at end of file +} +-keep class top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry { public static *; } +-keep class top.niunaijun.blackbox.instrumentation.FridaGadgetLoader { public static *; } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 66ec39f..477102b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,9 @@ + @@ -53,4 +59,4 @@ - \ No newline at end of file + diff --git a/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkInspector.java b/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkInspector.java new file mode 100644 index 0000000..472afb2 --- /dev/null +++ b/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkInspector.java @@ -0,0 +1,53 @@ +package top.niunaijun.blackboxa.fridabox; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +public final class ApkInspector { + private ApkInspector() { + } + + public static Result inspect(File apk) throws IOException { + Set abis = new LinkedHashSet<>(); + boolean hasNativeLibraries = false; + try (ZipFile archive = new ZipFile(apk)) { + if (archive.getEntry("AndroidManifest.xml") == null) { + throw new IOException("The selected file has no AndroidManifest.xml"); + } + for (ZipEntry entry : Collections.list(archive.entries())) { + String name = entry.getName(); + if (!entry.isDirectory() && name.startsWith("lib/") && name.endsWith(".so")) { + String[] parts = name.split("/", 3); + if (parts.length == 3) { + hasNativeLibraries = true; + abis.add(parts[1]); + } + } + } + } + boolean supported = !hasNativeLibraries || abis.contains("arm64-v8a"); + return new Result(hasNativeLibraries, supported, abis); + } + + public static final class Result { + public final boolean hasNativeLibraries; + public final boolean supported; + public final Set abis; + + Result(boolean hasNativeLibraries, boolean supported, Set abis) { + this.hasNativeLibraries = hasNativeLibraries; + this.supported = supported; + this.abis = Collections.unmodifiableSet(new LinkedHashSet<>(abis)); + } + + public String description() { + if (!hasNativeLibraries) return "Pure Java/Kotlin (accepted)"; + return supported ? "ARM64 supported: " + abis : "Rejected; no arm64-v8a: " + abis; + } + } +} diff --git a/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkIntegrity.java b/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkIntegrity.java new file mode 100644 index 0000000..7152c57 --- /dev/null +++ b/app/src/main/java/top/niunaijun/blackboxa/fridabox/ApkIntegrity.java @@ -0,0 +1,33 @@ +package top.niunaijun.blackboxa.fridabox; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public final class ApkIntegrity { + private ApkIntegrity() { + } + + public static String sha256(File file) throws IOException { + try (InputStream stream = new FileInputStream(file)) { + return sha256(stream); + } + } + + public static String sha256(InputStream stream) throws IOException { + try { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] buffer = new byte[64 * 1024]; + int count; + while ((count = stream.read(buffer)) != -1) digest.update(buffer, 0, count); + StringBuilder result = new StringBuilder(64); + for (byte value : digest.digest()) result.append(String.format("%02x", value & 0xff)); + return result.toString(); + } catch (NoSuchAlgorithmException impossible) { + throw new AssertionError(impossible); + } + } +} diff --git a/app/src/main/java/top/niunaijun/blackboxa/fridabox/FridaBoxActivity.kt b/app/src/main/java/top/niunaijun/blackboxa/fridabox/FridaBoxActivity.kt new file mode 100644 index 0000000..9315288 --- /dev/null +++ b/app/src/main/java/top/niunaijun/blackboxa/fridabox/FridaBoxActivity.kt @@ -0,0 +1,423 @@ +package top.niunaijun.blackboxa.fridabox + +import android.app.AlertDialog +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.content.SharedPreferences +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.graphics.Typeface +import android.net.Uri +import android.os.Bundle +import android.provider.OpenableColumns +import android.text.InputType +import android.view.Gravity +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.CheckBox +import android.widget.EditText +import android.widget.HorizontalScrollView +import android.widget.ImageView +import android.widget.LinearLayout +import android.widget.ScrollView +import android.widget.Switch +import android.widget.TextView +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AppCompatActivity +import top.niunaijun.blackbox.BlackBoxCore +import top.niunaijun.blackbox.instrumentation.InstrumentationSettings +import top.niunaijun.blackboxa.BuildConfig +import java.io.File +import java.io.FileOutputStream +import java.security.MessageDigest +import java.util.Locale +import java.util.concurrent.Executors + +/** Minimal host UI for APK import, virtual launch, runtime status, and settings. */ +class FridaBoxActivity : AppCompatActivity() { + private val worker = Executors.newSingleThreadExecutor() + private lateinit var content: LinearLayout + private val settings: SharedPreferences by lazy { + getSharedPreferences(InstrumentationSettings.PREFERENCES, Context.MODE_PRIVATE) + } + private val metadata: SharedPreferences by lazy { + getSharedPreferences("fridabox_imports", Context.MODE_PRIVATE) + } + + private val apkPicker = registerForActivityResult(ActivityResultContracts.OpenDocument()) { uri -> + if (uri != null) importApk(uri) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + showHome() + } + + override fun onDestroy() { + worker.shutdown() + super.onDestroy() + } + + private fun baseScreen(title: String): LinearLayout { + val root = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setPadding(dp(16), dp(12), dp(16), dp(12)) + setBackgroundColor(0xfff7f8fa.toInt()) + } + val header = LinearLayout(this).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + } + header.addView(TextView(this).apply { + text = title + textSize = 24f + setTypeface(typeface, Typeface.BOLD) + }, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) + header.addView(Button(this).apply { + text = "Home" + setOnClickListener { showHome() } + }) + header.addView(Button(this).apply { + text = "Runtime" + setOnClickListener { showRuntime() } + }) + header.addView(Button(this).apply { + text = "Settings" + setOnClickListener { showSettings() } + }) + root.addView(header) + content = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setPadding(0, dp(12), 0, dp(24)) + } + root.addView(ScrollView(this).apply { addView(content) }, LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, 0, 1f)) + setContentView(root) + return content + } + + private fun showHome() { + baseScreen("FridaBox") + content.addView(TextView(this).apply { + text = "Non-root Android application virtualization with per-guest Frida Gadget instrumentation." + textSize = 16f + }) + content.addView(Button(this).apply { + text = "Import APK" + setOnClickListener { apkPicker.launch(arrayOf("application/vnd.android.package-archive", "application/octet-stream")) } + }) + if (BuildConfig.DEBUG) { + content.addView(Button(this).apply { + text = "Install demo guest" + setOnClickListener { installDemoGuest() } + }) + } + content.addView(sectionTitle("Virtual applications")) + refreshApps() + } + + private fun refreshApps() { + val marker = TextView(this).apply { text = "Loading…" } + content.addView(marker) + worker.execute { + val packages = try { + BlackBoxCore.get().getInstalledPackages(PackageManager.GET_META_DATA, 0) + } catch (error: Throwable) { + runOnUiThread { marker.text = "Unable to read virtual packages: ${error.message}" } + return@execute + } + runOnUiThread { + content.removeView(marker) + if (packages.isEmpty()) { + content.addView(TextView(this).apply { text = "No APKs imported yet." }) + } else { + packages.sortedBy { it.packageName }.forEach { addAppCard(it) } + } + } + } + } + + private fun addAppCard(info: PackageInfo) { + val card = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + setPadding(dp(12), dp(12), dp(12), dp(12)) + setBackgroundColor(0xffffffff.toInt()) + } + val heading = LinearLayout(this).apply { orientation = LinearLayout.HORIZONTAL } + heading.addView(ImageView(this).apply { + try { setImageDrawable(info.applicationInfo?.loadIcon(BlackBoxCore.getPackageManager())) } catch (_: Throwable) { } + }, LinearLayout.LayoutParams(dp(56), dp(56))) + heading.addView(TextView(this).apply { + text = buildString { + append(info.packageName) + append("\nVersion: ").append(info.versionName ?: "unknown") + append("\nInstrumentation: ") + append(if (settings.getBoolean("package_enabled_${info.packageName}", true)) "enabled" else "disabled") + } + setPadding(dp(12), 0, 0, 0) + }, LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)) + card.addView(heading) + val actions = LinearLayout(this).apply { orientation = LinearLayout.HORIZONTAL } + actions.addView(actionButton("Launch instrumented") { confirmInstrumentedLaunch(info.packageName) }) + actions.addView(actionButton("Launch without instrumentation") { launch(info.packageName, false) }) + actions.addView(actionButton("Clear virtual app data") { clearApp(info.packageName) }) + actions.addView(actionButton("Remove from virtual space") { removeApp(info.packageName) }) + actions.addView(actionButton("View runtime details") { showRuntime(info.packageName) }) + card.addView(HorizontalScrollView(this).apply { addView(actions) }) + val sha = metadata.getString("${info.packageName}.sha256", null) + if (sha != null) { + card.addView(TextView(this).apply { + text = "SHA-256: $sha\nSource: ${metadata.getString("${info.packageName}.source", "unknown")}\n" + + "ABI: ${metadata.getString("${info.packageName}.abi", "unknown")}\n" + + "Target SDK: ${metadata.getInt("${info.packageName}.targetSdk", info.applicationInfo?.targetSdkVersion ?: -1)}" + textSize = 12f + setTextIsSelectable(true) + }) + } + content.addView(card, LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { topMargin = dp(10) }) + } + + private fun confirmInstrumentedLaunch(packageName: String) { + AlertDialog.Builder(this) + .setTitle("Early instrumentation") + .setMessage("Guest startup is paused until Frida attaches. Run the generated attach command or disable instrumentation.") + .setPositiveButton("Launch") { _, _ -> launch(packageName, true) } + .setNegativeButton("Cancel", null) + .show() + } + + private fun launch(packageName: String, instrumented: Boolean) { + worker.execute { + try { + InstrumentationSettings.setEnabledForPackage(packageName, instrumented) + BlackBoxCore.get().stopPackage(packageName, 0) + Thread.sleep(150) + val launched = BlackBoxCore.get().launchApk(packageName, 0) + runOnUiThread { + toast(if (launched) "Guest launch requested" else "Guest has no launchable activity") + if (instrumented) showRuntime(packageName) + } + } catch (error: Throwable) { + runOnUiThread { toast("Launch failed: ${error.message}") } + } + } + } + + private fun clearApp(packageName: String) { + worker.execute { + try { + BlackBoxCore.get().stopPackage(packageName, 0) + BlackBoxCore.get().clearPackage(packageName, 0) + runOnUiThread { toast("Virtual app data cleared") } + } catch (error: Throwable) { + runOnUiThread { toast("Clear failed: ${error.message}") } + } + } + } + + private fun removeApp(packageName: String) { + AlertDialog.Builder(this).setTitle("Remove $packageName?") + .setMessage("This removes the app and its data only from BlackBox virtual space.") + .setPositiveButton("Remove") { _, _ -> + worker.execute { + try { + BlackBoxCore.get().stopPackage(packageName, 0) + BlackBoxCore.get().uninstallPackageAsUser(packageName, 0) + runOnUiThread { showHome() } + } catch (error: Throwable) { + runOnUiThread { toast("Remove failed: ${error.message}") } + } + } + }.setNegativeButton("Cancel", null).show() + } + + private fun importApk(uri: Uri) { + val name = displayName(uri) + val lowerName = name.lowercase(Locale.ROOT) + if (!lowerName.endsWith(".apk") || lowerName.endsWith(".apks") || + lowerName.endsWith(".xapk") || lowerName.endsWith(".apkm")) { + toast("Select one base .apk file; bundles and split sets are not supported") + return + } + toast("Importing $name…") + worker.execute { + val directory = File(filesDir, "imported-apks").apply { mkdirs() } + val temporary = File.createTempFile("import-", ".partial", directory) + try { + val digest = MessageDigest.getInstance("SHA-256") + contentResolver.openInputStream(uri).use { input -> + requireNotNull(input) { "Unable to open the selected document" } + FileOutputStream(temporary).use { output -> + val buffer = ByteArray(64 * 1024) + while (true) { + val count = input.read(buffer) + if (count < 0) break + digest.update(buffer, 0, count) + output.write(buffer, 0, count) + } + output.fd.sync() + } + } + val originalHash = digest.digest().joinToString("") { "%02x".format(it) } + val archiveInfo = packageManager.getPackageArchiveInfo(temporary.absolutePath, PackageManager.GET_META_DATA) + ?: error("Android could not parse this APK") + if (!archiveInfo.splitNames.isNullOrEmpty()) error("Split-only APKs are not supported in this MVP") + val abi = ApkInspector.inspect(temporary) + if (!abi.supported) error("32-bit-only/native APK rejected: ${abi.description()}") + val safePackage = archiveInfo.packageName.replace(Regex("[^A-Za-z0-9._-]"), "_") + val stored = File(directory, "$safePackage-${originalHash.take(12)}.apk") + if (stored.exists()) stored.delete() + if (!temporary.renameTo(stored)) error("Unable to move APK into private storage") + if (ApkIntegrity.sha256(stored) != originalHash) error("SHA-256 changed while importing") + stored.setReadable(true, true) + stored.setWritable(false, false) + val installResult = BlackBoxCore.get().installPackageAsUser(stored, 0) + if (!installResult.success) error(installResult.msg ?: "Virtual installation failed") + if (ApkIntegrity.sha256(stored) != originalHash) error("Stored APK was modified during virtual installation") + metadata.edit() + .putString("${archiveInfo.packageName}.sha256", originalHash) + .putString("${archiveInfo.packageName}.source", stored.absolutePath) + .putString("${archiveInfo.packageName}.abi", abi.description()) + .putString("${archiveInfo.packageName}.version", archiveInfo.versionName) + .putInt("${archiveInfo.packageName}.targetSdk", archiveInfo.applicationInfo?.targetSdkVersion ?: -1) + .apply() + InstrumentationSettings.setEnabledForPackage(archiveInfo.packageName, true) + runOnUiThread { + toast("Imported ${archiveInfo.packageName}; SHA-256 verified") + showHome() + } + } catch (error: Throwable) { + temporary.delete() + runOnUiThread { toast("Import rejected: ${error.message}") } + } + } + } + + private fun installDemoGuest() { + worker.execute { + try { + val directory = File(filesDir, "imported-apks").apply { mkdirs() } + val output = File(directory, "sample-guest.apk") + if (output.exists() && !output.delete()) error("Unable to replace the prior demo APK") + assets.open("demo/sample-guest.apk").use { input -> + FileOutputStream(output).use { input.copyTo(it) } + } + val sha = ApkIntegrity.sha256(output) + output.setWritable(false, false) + val result = BlackBoxCore.get().installPackageAsUser(output, 0) + if (!result.success) error(result.msg ?: "Demo virtual installation failed") + metadata.edit().putString("${result.packageName}.sha256", sha) + .putString("${result.packageName}.source", output.absolutePath) + .putString("${result.packageName}.abi", ApkInspector.inspect(output).description()).apply() + runOnUiThread { toast("Demo guest installed into virtual space"); showHome() } + } catch (error: Throwable) { + runOnUiThread { toast("Demo install failed: ${error.message}") } + } + } + } + + private fun showRuntime(packageHint: String? = null) { + baseScreen("Runtime status") + val packageName = settings.getString("runtime_package", packageHint) ?: packageHint ?: "No guest bound" + val state = settings.getString("runtime_state", "idle") + val basePort = settings.getInt(InstrumentationSettings.KEY_BASE_PORT, 27042) + val count = settings.getInt(InstrumentationSettings.KEY_SCAN_COUNT, 32) + val command = "python tools/attach_guest.py --package $packageName --keep-alive" + content.addView(detail("Guest package", packageName)) + content.addView(detail("Guest process", settings.getString("runtime_process", "unknown") ?: "unknown")) + content.addView(detail("Virtual process slot", settings.getInt("runtime_vpid", -1).toString())) + content.addView(detail("Guest source path", settings.getString("runtime_source", "unknown") ?: "unknown")) + content.addView(detail("Instrumentation enabled", settings.getBoolean("runtime_enabled", false).toString())) + content.addView(detail("Gadget load status", state ?: "idle")) + content.addView(detail("Expected port range", "$basePort..${basePort + count - 1}")) + content.addView(detail("Latest error", settings.getString("runtime_error", "none") ?: "none")) + content.addView(TextView(this).apply { + text = "Attach command\n$command" + setTextIsSelectable(true) + setPadding(0, dp(12), 0, dp(8)) + }) + content.addView(Button(this).apply { + text = "Copy attach command" + setOnClickListener { + (getSystemService(CLIPBOARD_SERVICE) as ClipboardManager) + .setPrimaryClip(ClipData.newPlainText("FridaBox attach", command)) + toast("Attach command copied") + } + }) + content.addView(Button(this).apply { text = "Refresh"; setOnClickListener { showRuntime(packageHint) } }) + } + + private fun showSettings() { + baseScreen("Instrumentation settings") + val enabled = Switch(this).apply { + text = "Instrumentation enabled" + isChecked = settings.getBoolean(InstrumentationSettings.KEY_ENABLED, true) + } + val pause = CheckBox(this).apply { + text = "Pause guest until attach (required for this MVP)" + isChecked = true + isEnabled = false + } + val port = numericSetting("Frida base port", settings.getInt(InstrumentationSettings.KEY_BASE_PORT, 27042)) + val count = numericSetting("Port scan count", settings.getInt(InstrumentationSettings.KEY_SCAN_COUNT, 32)) + val logs = Switch(this).apply { + text = "Show advanced logs" + isChecked = settings.getBoolean(InstrumentationSettings.KEY_ADVANCED_LOGS, false) + } + content.addView(enabled); content.addView(pause); content.addView(port.first); content.addView(count.first); content.addView(logs) + content.addView(Button(this).apply { + text = "Save settings" + setOnClickListener { + settings.edit() + .putBoolean(InstrumentationSettings.KEY_ENABLED, enabled.isChecked) + .putInt(InstrumentationSettings.KEY_BASE_PORT, InstrumentationPreferenceParser.parsePort(port.second.text.toString(), 27042)) + .putInt(InstrumentationSettings.KEY_SCAN_COUNT, InstrumentationPreferenceParser.parseScanCount(count.second.text.toString(), 32)) + .putBoolean(InstrumentationSettings.KEY_ADVANCED_LOGS, logs.isChecked) + .apply() + toast("Settings saved") + } + }) + content.addView(TextView(this).apply { + text = "Limitations: FridaBox is not undetectable. The host UID/SELinux domain, virtual stub process, host classes, ClassLoader topology, synthesized Binder responses, Gadget module/threads/socket, and /proc/self/maps remain observable. Play Integrity and hardware-backed attestation are not virtualized." + setPadding(0, dp(20), 0, 0) + }) + } + + private fun numericSetting(label: String, value: Int): Pair { + val input = EditText(this).apply { + setText(value.toString()); inputType = InputType.TYPE_CLASS_NUMBER + } + return LinearLayout(this).apply { + orientation = LinearLayout.HORIZONTAL; gravity = Gravity.CENTER_VERTICAL + addView(TextView(this@FridaBoxActivity).apply { text = label }, LinearLayout.LayoutParams(0, dp(56), 1f)) + addView(input, LinearLayout.LayoutParams(dp(140), dp(56))) + } to input + } + + private fun detail(label: String, value: String) = TextView(this).apply { + text = "$label: $value"; setTextIsSelectable(true); setPadding(0, dp(5), 0, dp(5)) + } + + private fun sectionTitle(text: String) = TextView(this).apply { + this.text = text; textSize = 19f; setTypeface(typeface, Typeface.BOLD); setPadding(0, dp(18), 0, dp(4)) + } + + private fun actionButton(label: String, action: () -> Unit) = Button(this).apply { + text = label; setOnClickListener { action() } + } + + private fun displayName(uri: Uri): String { + contentResolver.query(uri, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null)?.use { + if (it.moveToFirst()) return it.getString(0) ?: "selected.apk" + } + return uri.lastPathSegment ?: "selected.apk" + } + + private fun toast(message: String) = Toast.makeText(this, message, Toast.LENGTH_LONG).show() + private fun dp(value: Int) = (value * resources.displayMetrics.density).toInt() +} diff --git a/app/src/main/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParser.java b/app/src/main/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParser.java new file mode 100644 index 0000000..526ff44 --- /dev/null +++ b/app/src/main/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParser.java @@ -0,0 +1,23 @@ +package top.niunaijun.blackboxa.fridabox; + +public final class InstrumentationPreferenceParser { + private InstrumentationPreferenceParser() { + } + + public static int parsePort(String text, int fallback) { + return parseRange(text, 1024, 65535, fallback); + } + + public static int parseScanCount(String text, int fallback) { + return parseRange(text, 1, 128, fallback); + } + + private static int parseRange(String text, int minimum, int maximum, int fallback) { + try { + int value = Integer.parseInt(text == null ? "" : text.trim()); + return value >= minimum && value <= maximum ? value : fallback; + } catch (NumberFormatException ignored) { + return fallback; + } + } +} diff --git a/app/src/main/java/top/niunaijun/blackboxa/view/main/BlackBoxLoader.kt b/app/src/main/java/top/niunaijun/blackboxa/view/main/BlackBoxLoader.kt index 0a2030a..31a0fa2 100644 --- a/app/src/main/java/top/niunaijun/blackboxa/view/main/BlackBoxLoader.kt +++ b/app/src/main/java/top/niunaijun/blackboxa/view/main/BlackBoxLoader.kt @@ -17,7 +17,7 @@ class BlackBoxLoader { private var mHideRoot by AppSharedPreferenceDelegate(App.getContext(), false) - private var mDaemonEnable by AppSharedPreferenceDelegate(App.getContext(), false) + private var mDaemonEnable by AppSharedPreferenceDelegate(App.getContext(), true) private var mShowShortcutPermissionDialog by AppSharedPreferenceDelegate(App.getContext(), true) @@ -245,12 +245,7 @@ class BlackBoxLoader { } override fun isEnableDaemonService(): Boolean { - return try { - mDaemonEnable - } catch (e: Exception) { - Log.e(TAG, "Error checking daemonEnable: ${e.message}") - false - } + return true } override fun isUseVpnNetwork(): Boolean { diff --git a/app/src/main/java/top/niunaijun/blackboxa/view/main/WelcomeActivity.kt b/app/src/main/java/top/niunaijun/blackboxa/view/main/WelcomeActivity.kt index 9c07fbd..3f3586d 100644 --- a/app/src/main/java/top/niunaijun/blackboxa/view/main/WelcomeActivity.kt +++ b/app/src/main/java/top/niunaijun/blackboxa/view/main/WelcomeActivity.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModelProvider import top.niunaijun.blackbox.BlackBoxCore import top.niunaijun.blackboxa.util.InjectionUtil import top.niunaijun.blackboxa.view.list.ListViewModel +import top.niunaijun.blackboxa.fridabox.FridaBoxActivity class WelcomeActivity : AppCompatActivity() { @@ -22,7 +23,7 @@ class WelcomeActivity : AppCompatActivity() { } private fun jump() { - MainActivity.start(this) + startActivity(Intent(this, FridaBoxActivity::class.java)) finish() } @@ -30,4 +31,4 @@ class WelcomeActivity : AppCompatActivity() { val viewModel = ViewModelProvider(this,InjectionUtil.getListFactory()).get(ListViewModel::class.java) viewModel.previewInstalledList() } -} \ No newline at end of file +} diff --git a/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.config.so b/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.config.so new file mode 100644 index 0000000..6b8b54f --- /dev/null +++ b/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.config.so @@ -0,0 +1,11 @@ +{ + "interaction": { + "type": "listen", + "address": "127.0.0.1", + "port": 27042, + "on_port_conflict": "pick-next", + "on_load": "wait" + }, + "runtime": "qjs", + "teardown": "minimal" +} diff --git a/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.so b/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.so new file mode 100644 index 0000000..b7829a8 Binary files /dev/null and b/app/src/main/jniLibs/arm64-v8a/libfrida-gadget.so differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7dc6d8a..d4aa8b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,6 @@ - BlackBox + FridaBox Choose Choose App Installed App diff --git a/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkInspectorTest.java b/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkInspectorTest.java new file mode 100644 index 0000000..9fbcb2c --- /dev/null +++ b/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkInspectorTest.java @@ -0,0 +1,48 @@ +package top.niunaijun.blackboxa.fridabox; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class ApkInspectorTest { + @Rule public final TemporaryFolder temporary = new TemporaryFolder(); + + @Test + public void pureJavaApkIsAccepted() throws Exception { + File apk = apkWith("classes.dex"); + ApkInspector.Result result = ApkInspector.inspect(apk); + assertFalse(result.hasNativeLibraries); + assertTrue(result.supported); + } + + @Test + public void arm64ApkIsAccepted() throws Exception { + ApkInspector.Result result = ApkInspector.inspect(apkWith("lib/arm64-v8a/libsample.so")); + assertTrue(result.hasNativeLibraries); + assertTrue(result.supported); + } + + @Test + public void thirtyTwoBitOnlyApkIsRejected() throws Exception { + ApkInspector.Result result = ApkInspector.inspect(apkWith("lib/armeabi-v7a/libsample.so")); + assertTrue(result.hasNativeLibraries); + assertFalse(result.supported); + } + + private File apkWith(String entry) throws Exception { + File file = temporary.newFile("test-" + System.nanoTime() + ".apk"); + try (ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file))) { + output.putNextEntry(new ZipEntry("AndroidManifest.xml")); output.write(1); output.closeEntry(); + output.putNextEntry(new ZipEntry(entry)); output.write(2); output.closeEntry(); + } + return file; + } +} diff --git a/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkIntegrityTest.java b/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkIntegrityTest.java new file mode 100644 index 0000000..5119993 --- /dev/null +++ b/app/src/test/java/top/niunaijun/blackboxa/fridabox/ApkIntegrityTest.java @@ -0,0 +1,15 @@ +package top.niunaijun.blackboxa.fridabox; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import java.io.ByteArrayInputStream; + +public class ApkIntegrityTest { + @Test + public void computesKnownSha256() throws Exception { + assertEquals("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + ApkIntegrity.sha256(new ByteArrayInputStream("abc".getBytes("UTF-8")))); + } +} diff --git a/app/src/test/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParserTest.java b/app/src/test/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParserTest.java new file mode 100644 index 0000000..bf0bce5 --- /dev/null +++ b/app/src/test/java/top/niunaijun/blackboxa/fridabox/InstrumentationPreferenceParserTest.java @@ -0,0 +1,20 @@ +package top.niunaijun.blackboxa.fridabox; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class InstrumentationPreferenceParserTest { + @Test + public void acceptsValidValues() { + assertEquals(27043, InstrumentationPreferenceParser.parsePort("27043", 27042)); + assertEquals(32, InstrumentationPreferenceParser.parseScanCount("32", 16)); + } + + @Test + public void rejectsMalformedAndOutOfRangeValues() { + assertEquals(27042, InstrumentationPreferenceParser.parsePort("nope", 27042)); + assertEquals(27042, InstrumentationPreferenceParser.parsePort("80", 27042)); + assertEquals(32, InstrumentationPreferenceParser.parseScanCount("999", 32)); + } +} diff --git a/docs/BASELINE.md b/docs/BASELINE.md new file mode 100644 index 0000000..397d060 --- /dev/null +++ b/docs/BASELINE.md @@ -0,0 +1,40 @@ +# NewBlackbox baseline + +- Foundation: `ALEX5402/NewBlackbox`, branch `main` +- Required commit: `89b59836c66f173756a4ae258cf379a957649820` +- Working branch: `feature/fridabox-mvp` +- Baseline date: 2026-07-19 +- Host OS: Windows 11 amd64 +- Available JVM used: Oracle JDK 24.0.1 (JDK 21 was not installed on the build host) + +## Exact pinned-source result + +`gradlew clean --stacktrace --console=plain` failed during configuration because +`com.android.application:com.android.application.gradle.plugin:8.13.2` could not +be resolved. A direct request to the official Google Maven artifact URL returned +HTTP 404. No source code had been changed when this result was recorded. + +## Narrow baseline compatibility adjustments + +The official Google Maven endpoint returned HTTP 404 for AGP and AndroidX +artifacts in this build environment. The Google repository mirror at +`https://maven.aliyun.com/repository/google` is configured ahead of `google()`; +the requested AGP 8.13.2 is retained. Plugin IDs are mapped directly to the +official `com.android.tools.build:gradle` module to avoid marker resolution. + +The requested NDK +29.0.13846066 was not installed; the nearest complete installed NDK, +29.0.14206865, is used. Bcore's `ndkVersion` was also moved from the +`externalNativeBuild` block to the Android block where AGP recognizes it. + +On Windows, upstream `ndk-build` cannot parse an `APP_BUILD_SCRIPT` path that +contains spaces. Bcore accepts `FRIDABOX_NDK_PROJECT_DIR` as an optional alias +for the Bcore module directory; this build used `D:\FridaBoxBuild\Bcore`, a +directory junction to the real workspace. + +## Post-adjustment result + +With the repository mirror, installed NDK 29 revision, and scoped Windows +space-path workaround, `:app:assembleDebug` completed successfully. The baseline +build compiled Java/Kotlin resources and both native ABIs present in the original +foundation before FridaBox changed the final target to ARM64-only. diff --git a/docs/BUILDING.md b/docs/BUILDING.md new file mode 100644 index 0000000..8581d93 --- /dev/null +++ b/docs/BUILDING.md @@ -0,0 +1,54 @@ +# Building + +## Prerequisites + +- JDK 21 (the requested/recommended toolchain). +- Android SDK 35 and build tools. +- Android NDK 29.0.13846066 when available. This build host only had the closely + related complete NDK 29.0.14206865, which is recorded in `docs/BASELINE.md`. +- Python 3.10 or newer. +- Node.js 20 or newer and npm for reproducibly building Frida 17 Java agents. + +Create `local.properties` with the SDK path, then fetch the pinned official +Gadget: + +```powershell +python tools\fetch_frida_gadget.py +``` + +The script uses the GitHub Releases API and Python's standard `lzma` module. The +build fails with a direct instruction if the binary is absent. No XZ archive is +kept. + +Install the pinned Java bridge/compiler and build the controller agents: + +```powershell +npm ci +python tools\build_frida_agents.py +``` + +Frida 17 no longer bundles runtime bridges into API-loaded GumJS agents. The +compiled files under `scripts/dist/` are reproducible from the source scripts, +`package.json`, and `package-lock.json`. + +On Windows, if the repository path contains spaces, create a no-space junction +and set the Bcore-only native path override: + +```powershell +New-Item -ItemType Junction -Path D:\FridaBoxBuild -Target 'D:\path with spaces\FridaBox' +$env:FRIDABOX_NDK_PROJECT_DIR='D:\FridaBoxBuild\Bcore' +``` + +Build and test: + +```powershell +.\gradlew.bat clean +.\gradlew.bat :sample-guest:assembleDebug +.\gradlew.bat :app:assembleDebug +.\gradlew.bat test +.\gradlew.bat :app:check +``` + +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. diff --git a/docs/DETECTION_SURFACES.md b/docs/DETECTION_SURFACES.md new file mode 100644 index 0000000..4a2ee4d --- /dev/null +++ b/docs/DETECTION_SURFACES.md @@ -0,0 +1,20 @@ +# Detection surfaces + +FridaBox is not undetectable. Virtualization reduces accidental identity and API +leakage but cannot reproduce a normal kernel/system installation. + +- The host Linux UID remains the real UID at kernel level. +- The host SELinux domain remains visible. +- BlackBox virtual stub process names may be observed. +- Host and BlackBox classes coexist with guest classes in the ART process. +- Frida threads, mappings, sockets, and modules are observable. +- `/proc/self/maps` can reveal Frida Gadget. +- The default Frida protocol endpoint can be probed even though it is loopback-only. +- ClassLoader topology differs from a normally installed application. +- Some PackageManager, ActivityManager, and other Binder responses are synthesized. +- The system-side PackageManager does not know the guest package. +- The guest shares the host UID and process sandbox rather than receiving a + system-assigned package UID. +- Play Integrity and hardware-backed attestation cannot be faithfully virtualized. + +No app-specific anti-Frida or anti-virtualization bypasses are included. diff --git a/docs/FRIDA_CONNECTION.md b/docs/FRIDA_CONNECTION.md new file mode 100644 index 0000000..fe70274 --- /dev/null +++ b/docs/FRIDA_CONNECTION.md @@ -0,0 +1,38 @@ +# Frida connection + +Install the pinned controller binding: + +```text +python -m pip install -r tools/requirements.txt +npm ci +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 +non-Gadget/non-FridaBox endpoints, and maps endpoints through +`GuestRuntimeRegistry`. + +Frida 17 Java agents explicitly import `frida-java-bridge`. The controller +loads the compiled probe/bootstrap from `scripts/dist/`; when a source path such +as `scripts/sample-hook.js` has a compiled counterpart, that bundle is selected +automatically. + +```text +python tools/attach_guest.py --list +python tools/attach_guest.py --package PACKAGE +python tools/attach_guest.py --package PACKAGE --process PROCESS +python tools/attach_guest.py --package PACKAGE --script scripts/example.js +python tools/attach_guest.py --package PACKAGE --script scripts/example.js --keep-alive +``` + +`guest-bootstrap.js` loads before the user script and assigns the registry's +guest ClassLoader to `Java.classFactory.loader`. Its RPC exports are `info`, +`useclass`, `enumerateloadedclasses`, and `enumeratemodules`. It retries for a +bounded ten seconds when the ClassLoader is temporarily unavailable. +The controller prints the registry JSON, selected ClassLoader, and native-module +enumeration before loading the user script. + +Use `tools/forward_frida_ports.py` when only port forwarding is needed. A client +major-version mismatch prints the exact `pip install frida==17.16.0` repair +command. diff --git a/docs/LIMITATIONS.md b/docs/LIMITATIONS.md new file mode 100644 index 0000000..551b827 --- /dev/null +++ b/docs/LIMITATIONS.md @@ -0,0 +1,25 @@ +# Limitations + +The MVP targets ordinary single-file APKs on ARM64 Android 12 through Android 16. +Compatibility varies because Android hidden APIs and vendor framework behavior +change, and virtualization is observable. + +Explicitly unsupported or excluded: + +- split APK sets and App Bundles (`.apks`, `.xapk`, `.apkm`); +- 32-bit-only native APKs and x86 guests; +- system apps, privileged permissions, or Play Store inside the container; +- full Google Play Services compatibility and Play Integrity; +- hardware-backed keystore identity or attestation emulation; +- reliable `isolatedProcess=true`, WebView renderer sandbox, app zygote, or + external-service instrumentation outside the host UID; +- reliable operation for all banking/RASP applications; +- perfect anti-virtualization or anti-instrumentation resistance. + +Normal guest `android:process=":remote"` components routed through BlackBox's +`BActivityThread` receive a best-effort independent Gadget load. Each process +starts at 27042 and relies on `pick-next` for conflicts. + +The static config always uses `on_load=wait`; changing the displayed base port +does not rewrite the packaged Gadget configuration in this MVP. The controller's +base/count options must match the port range used for discovery. diff --git a/docs/TEST_RESULTS.md b/docs/TEST_RESULTS.md new file mode 100644 index 0000000..aebe89b --- /dev/null +++ b/docs/TEST_RESULTS.md @@ -0,0 +1,70 @@ +# Test results + +Validation date: 2026-07-19 + +## Host validation + +The following commands completed successfully on the build host: + +```powershell +.\gradlew.bat clean +.\gradlew.bat :sample-guest:assembleDebug +.\gradlew.bat :app:assembleDebug +.\gradlew.bat test +.\gradlew.bat :app:check +.\gradlew.bat :app:verifyDebugApkFridaPackaging :app:verifyInstrumentationOrdering :app:verifyDemoGuestUnmodified +npm ci +python tools\build_frida_agents.py +python -m py_compile tools\attach_guest.py tools\forward_frida_ports.py tools\fetch_frida_gadget.py tools\build_frida_agents.py +``` + +For this workspace path, native builds used: + +```powershell +$env:FRIDABOX_NDK_PROJECT_DIR='D:\FridaBoxBuild\Bcore' +``` + +Unit-test results: 16 executions passed, with zero failures, errors, or skips. +This is eight test methods run for both debug and release variants: + +- `ApkInspectorTest`: 3 per variant; +- `ApkIntegrityTest`: 1 per variant; +- `InstrumentationPreferenceParserTest`: 2 per variant; +- `GuestRuntimeRegistryTest`: 2 per variant. + +The final APK and custom verification tasks passed: + +- output: `app/build/outputs/apk/debug/FridaBox_4.0.0_arm64-v8a-debug.apk`; +- size: 19,977,904 bytes; +- SHA-256: `a87af38ff7f4a54d2cdc0207ac68319a1a05ab8067b7acdeb057c6c967ed2573`; +- packaged ABIs: ARM64 only; +- packaged native files: `libblackbox.so`, `libfrida-gadget.so`, and + `libfrida-gadget.config.so` under `lib/arm64-v8a/`; +- Frida Gadget 17.16.0 SHA-256: + `6bf149e5d1c5ec701e7b822cab57bb243f1c2a03318fa974fe373ee711a9ed9e`; +- early-load ordering and byte-identical demo-asset checks passed. +- pinned Frida 17 registry/bootstrap/sample agents rebuilt successfully, and + controller help plus empty-range discovery completed successfully. + +The build host provided JDK 24.0.1 and complete NDK 29.0.14206865 rather than +the requested JDK 21 and NDK 29.0.13846066. These substitutions and the +baseline build investigation are recorded in `docs/BASELINE.md`. + +## Device validation + +Runtime validation passed on a Samsung SM-S928B running ARM64 Android 16/API 36: + +- latest host APK installed successfully; +- the sample installed only in BlackBox and was absent from Android user 0's + real PackageManager; +- Gadget paused startup before `SampleApplication.attachBaseContext` and + `onCreate`; +- the controller mapped port 27042 to the sample package/process and reported + user ID 0, virtual process ID 0, source APK, and guest `PathClassLoader`; +- native enumeration returned 419 modules; +- `sample-hook.js` changed `Target.add(2, 3)` from 5 to 1337; +- launching without instrumentation recycled the process, opened no Gadget + listener, and restored the visible result to 5. + +The command and log transcript, including two device-discovered fixes, is in +`docs/device-validation.log`. diff --git a/docs/USAGE.md b/docs/USAGE.md new file mode 100644 index 0000000..04fa267 --- /dev/null +++ b/docs/USAGE.md @@ -0,0 +1,27 @@ +# Usage + +1. Install and open the FridaBox host on an ARM64 Android 12–16 research device. +2. Tap **Import APK** and select one base `.apk` through the system document + picker. `.apks`, `.xapk`, `.apkm`, split-only packages, and 32-bit-only native + APKs are rejected. +3. Review package, version, SHA-256, private source path, and ABI status. +4. Tap **Launch instrumented**. Startup intentionally pauses before the guest + `Application` is created. +5. Run the attach command shown on **Runtime status**. Attach and load hooks. +6. Use **Launch without instrumentation** for a clean virtual process where the + Gadget is not loaded. FridaBox stops the package before switching modes. + +Debug builds expose **Install demo guest**. The action installs the generated +`com.qm4rs.fridabox.sample` APK only into BlackBox. Then run: + +```text +npm ci +python tools/build_frida_agents.py +python tools/attach_guest.py --package com.qm4rs.fridabox.sample --script scripts/sample-hook.js --keep-alive +``` + +After startup resumes, press the sample button. The visible result should be +`1337`, demonstrating that the guest ClassLoader was selected. + +**Clear virtual app data** and **Remove from virtual space** affect only the +BlackBox virtual environment. They do not invoke Android's real package manager. diff --git a/docs/device-validation.log b/docs/device-validation.log new file mode 100644 index 0000000..4c9efae --- /dev/null +++ b/docs/device-validation.log @@ -0,0 +1,163 @@ +FridaBox device validation transcript +Date: 2026-07-19 (Asia/Tehran) +Device: Samsung SM-S928B, serial R5CY149SZEX + +1. Device and host installation + +> adb devices -l +R5CY149SZEX device product:e3qxxx model:SM_S928B device:e3q transport_id:3 + +> adb shell getprop ro.product.cpu.abilist +arm64-v8a + +> adb shell getprop ro.build.version.release +16 + +> adb shell getprop ro.build.version.sdk +36 + +> $env:FRIDABOX_NDK_PROJECT_DIR='D:\FridaBoxBuild\Bcore'; .\gradlew.bat :app:assembleDebug --console=plain +BUILD SUCCESSFUL + +> adb install -r app\build\outputs\apk\debug\FridaBox_4.0.0_arm64-v8a-debug.apk +Performing Streamed Install +Success + +> adb shell am start --user 0 -n com.qm4rs.fridabox/top.niunaijun.blackboxa.view.main.WelcomeActivity +Starting: Intent { cmp=com.qm4rs.fridabox/top.niunaijun.blackboxa.view.main.WelcomeActivity } + +The debug UI action "Install demo guest" installed the generated asset into +BlackBox. The UI reported: + + package: com.qm4rs.fridabox.sample + version: 1.0 + SHA-256: 35fa3a6d679ae0b0a18635756e1d1a23b5340d12e480eb8600768ab60af0e95e + source: /data/user/0/com.qm4rs.fridabox/files/imported-apks/sample-guest.apk + ABI: Pure Java/Kotlin (accepted) + target SDK: 28 + +> adb shell pm list packages --user 0 com.qm4rs.fridabox +package:com.qm4rs.fridabox + +> adb shell pm list packages --user 0 com.qm4rs.fridabox.sample + + +Result: the sample guest is absent from Android user 0's real PackageManager. +Samsung has an inaccessible user 150, so all PackageManager proof commands +explicitly use --user 0. + +2. Pre-attach pause + +The UI selected "Launch instrumented" and confirmed the early-instrumentation +warning. Before running the controller: + +> adb shell ps -A | Select-String fridabox.sample +u0_a524 31797 1675 ... S com.qm4rs.fridabox.sample + +> adb shell ss -ltn | Select-String 27042 +LISTEN 0 0 127.0.0.1:27042 0.0.0.0:* + +> adb logcat -d -v threadtime -s FridaBox.Gadget:I FridaBox.Sample:I *:S +07-19 23:11:00.878 31797 31797 I FridaBox.Gadget: Loading Frida Gadget for com.qm4rs.fridabox.sample + +There was no FridaBox.Sample attachBaseContext or onCreate line. The guest main +thread was paused inside System.loadLibrary before makeApplication. + +3. Controller discovery, registry, ClassLoader and native modules + +> python -m pip install -r tools\requirements.txt +Successfully installed frida-17.16.0 + +> npm ci +Pinned packages installed from package-lock.json. + +> python tools\build_frida_agents.py +Built Frida agents: scripts/dist/registry-probe.js, +scripts/dist/guest-bootstrap.js, scripts/dist/sample-hook.js + +> python -u tools\attach_guest.py --package com.qm4rs.fridabox.sample --script scripts\sample-hook.js --keep-alive + +PORT GUEST PACKAGE GUEST PROCESS VPID SOURCE APK +27042 com.qm4rs.fridabox.sample com.qm4rs.fridabox.sample 0 /data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/base.apk + +[FridaBox] package=com.qm4rs.fridabox.sample +[FridaBox] process=com.qm4rs.fridabox.sample +[FridaBox] userId=0 +[FridaBox] virtualProcessId=0 +[FridaBox] source=/data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/base.apk +[FridaBox] ClassLoader=dalvik.system.PathClassLoader[DexPathList[[zip file "/data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/base.apk"],nativeLibraryDirectories=[/data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/lib, /data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/base.apk!/lib/arm64-v8a, /system/lib64, /system_ext/lib64]]] +GuestRuntimeRegistry: {"initializedAt": 1784490060872, "instrumentationEnabled": true, "lastError": null, "package": "com.qm4rs.fridabox.sample", "process": "com.qm4rs.fridabox.sample", "sourceDir": "/data/user/0/com.qm4rs.fridabox/blackbox/data/app/com.qm4rs.fridabox.sample/base.apk", "userId": 0, "virtualProcessId": 0} +Native modules: 419 + app_process64 @ 0x5e4d8a8000 /system/bin/app_process64 + linker64 @ 0x7d37dc1000 /apex/com.android.runtime/bin/linker64 + libandroid_runtime.so @ 0x7cf688b000 /system/lib64/libandroid_runtime.so + libbinder.so @ 0x7d0ae9a000 /system/lib64/libbinder.so + libnativeloader.so @ 0x7d2fbc1000 /apex/com.android.art/lib64/libnativeloader.so +[sample-hook] installed for com.qm4rs.fridabox.sample +Attached on port 27042 to com.qm4rs.fridabox.sample / com.qm4rs.fridabox.sample + +Post-attach lifecycle evidence: + +07-19 23:11:44.774 31797 31797 I FridaBox.Gadget: Frida Gadget loaded +07-19 23:11:44.782 31797 31797 I FridaBox.Sample: Application.attachBaseContext package=com.qm4rs.fridabox.sample +07-19 23:11:44.787 31797 31797 I FridaBox.Sample: Application.onCreate package=com.qm4rs.fridabox.sample + +This ordering proves the Application lifecycle resumed only after controller +attachment. + +4. Java hook proof + +The validation tapped the visible "CALL TARGET.ADD(2, 3)" button while the +controller session remained attached. + +Controller output: +[sample-hook] Target.add(2, 3) => 1337 + +UI hierarchy output: + + +5. Recycled launch without instrumentation + +The previous instrumented process was PID 31797. The controller detached, the +UI returned Home, and "Launch without instrumentation" stopped/recycled the +virtual process before launch. + +> adb shell ps -A | Select-String fridabox.sample +u0_a524 32298 1675 ... S com.qm4rs.fridabox.sample + +> adb shell ss -ltn | Select-String 27042 + + +07-19 23:12:47.821 32298 32298 I FridaBox.Gadget: Instrumentation disabled for this guest process +07-19 23:12:47.826 32298 32298 I FridaBox.Sample: Application.attachBaseContext package=com.qm4rs.fridabox.sample +07-19 23:12:47.828 32298 32298 I FridaBox.Sample: Application.onCreate package=com.qm4rs.fridabox.sample + +The same button then produced: + + +6. Device-specific failures found and fixed + +Samsung Android 16 initially froze the BlackBox :black system-service process: + + libbinder.IPCThreadState: Transaction failed because process frozen. + Binder transaction failure: BR_FROZEN_REPLY + android.os.DeadObjectException at + IBPackageManagerService$Stub$Proxy.installPackageAsUser(...) + +Fix: enable the existing internal DaemonService for FridaBox. Verification: + + DaemonService: Foreground service started successfully + DaemonService: DaemonService started successfully + +No subsequent BR_FROZEN_REPLY occurred and the virtual package remained +available across host/activity restarts. + +The first Frida 17 API-loaded probe failed with: + + Port 27042 rejected: ReferenceError: 'Java' is not defined + +Fix: explicitly import frida-java-bridge 7.0.13 and reproducibly compile all +Java agents with frida-compile 19.0.5. The early registry probe also uses +Java.performNow(), avoiding a deadlock with Gadget's on_load=wait main thread. + +Final result: all required sample runtime checks passed on ARM64 Android 16. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4407c35 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,589 @@ +{ + "name": "fridabox-agents", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fridabox-agents", + "dependencies": { + "frida-java-bridge": "7.0.13" + }, + "devDependencies": { + "frida-compile": "19.0.5" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/commander": { + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/frida": { + "version": "17.16.1", + "resolved": "https://registry.npmjs.org/frida/-/frida-17.16.1.tgz", + "integrity": "sha512-bIjJGZy3q8anS2l81eond/qHP2oCsCv3iWck6MgcXzbwx6LWFLunnI9E7we/iEy0bHEsi4gX5ja6Wz76k+LEGQ==", + "dev": true, + "hasInstallScript": true, + "license": "LGPL-2.0 WITH WxWindows-exception-3.1", + "dependencies": { + "bindings": "^1.5.0", + "minimatch": "^10.0.1", + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/frida-compile": { + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/frida-compile/-/frida-compile-19.0.5.tgz", + "integrity": "sha512-dHkZBswL6zzF63bcqK2AaXOrZTYIk4ZynJhcI1EP+dFRtmCx1nhMQH/dFZfkgcS5yoP6nabA/Ra2IUji3j3GOg==", + "dev": true, + "dependencies": { + "chalk": "^5.4.1", + "commander": "^14.0.0", + "frida": "^17.8.0" + }, + "bin": { + "frida-compile": "dist/cli.js" + } + }, + "node_modules/frida-java-bridge": { + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/frida-java-bridge/-/frida-java-bridge-7.0.13.tgz", + "integrity": "sha512-YSyKjxbxKnSi3KSUy9vciOvTOuq0RRh9dkxzkQVEdfIIZlw20zE8D3Cq9eL2FDqUVj4YKas6Wf09kCjL5zbffg==", + "license": "LGPL-2.0 WITH WxWindows-exception-3.1" + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.94.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", + "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8b5b8e4 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "fridabox-agents", + "private": true, + "dependencies": { + "frida-java-bridge": "7.0.13" + }, + "devDependencies": { + "frida-compile": "19.0.5" + } +} diff --git a/sample-guest/build.gradle b/sample-guest/build.gradle new file mode 100644 index 0000000..625e135 --- /dev/null +++ b/sample-guest/build.gradle @@ -0,0 +1,21 @@ +plugins { + alias(libs.plugins.android.application) +} + +android { + namespace "com.qm4rs.fridabox.sample" + compileSdk rootProject.ext.compileSdkVersion + + defaultConfig { + applicationId "com.qm4rs.fridabox.sample" + minSdk rootProject.ext.minSdk + targetSdk rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_21 + targetCompatibility JavaVersion.VERSION_21 + } +} diff --git a/sample-guest/src/main/AndroidManifest.xml b/sample-guest/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a5aa316 --- /dev/null +++ b/sample-guest/src/main/AndroidManifest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/sample-guest/src/main/java/com/qm4rs/fridabox/sample/MainActivity.java b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/MainActivity.java new file mode 100644 index 0000000..b4d1f59 --- /dev/null +++ b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/MainActivity.java @@ -0,0 +1,28 @@ +package com.qm4rs.fridabox.sample; + +import android.app.Activity; +import android.os.Bundle; +import android.view.Gravity; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +public final class MainActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + TextView output = new TextView(this); + output.setTextSize(22f); + output.setText("Press the button to call Target.add(2, 3)"); + Button button = new Button(this); + button.setText("Call Target.add(2, 3)"); + button.setOnClickListener(view -> output.setText("Result: " + Target.add(2, 3))); + LinearLayout root = new LinearLayout(this); + root.setOrientation(LinearLayout.VERTICAL); + root.setGravity(Gravity.CENTER); + root.setPadding(32, 32, 32, 32); + root.addView(output); + root.addView(button); + setContentView(root); + } +} diff --git a/sample-guest/src/main/java/com/qm4rs/fridabox/sample/SampleApplication.java b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/SampleApplication.java new file mode 100644 index 0000000..1e27076 --- /dev/null +++ b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/SampleApplication.java @@ -0,0 +1,21 @@ +package com.qm4rs.fridabox.sample; + +import android.app.Application; +import android.content.Context; +import android.util.Log; + +public final class SampleApplication extends Application { + private static final String TAG = "FridaBox.Sample"; + + @Override + protected void attachBaseContext(Context base) { + Log.i(TAG, "Application.attachBaseContext package=" + base.getPackageName()); + super.attachBaseContext(base); + } + + @Override + public void onCreate() { + super.onCreate(); + Log.i(TAG, "Application.onCreate package=" + getPackageName()); + } +} diff --git a/sample-guest/src/main/java/com/qm4rs/fridabox/sample/Target.java b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/Target.java new file mode 100644 index 0000000..3f35357 --- /dev/null +++ b/sample-guest/src/main/java/com/qm4rs/fridabox/sample/Target.java @@ -0,0 +1,10 @@ +package com.qm4rs.fridabox.sample; + +public final class Target { + private Target() { + } + + public static int add(int a, int b) { + return a + b; + } +} diff --git a/scripts/dist/guest-bootstrap.js b/scripts/dist/guest-bootstrap.js new file mode 100644 index 0000000..721853b --- /dev/null +++ b/scripts/dist/guest-bootstrap.js @@ -0,0 +1,1887 @@ +📦 +237003 /scripts/guest-bootstrap.js +✄ +var vs=Object.defineProperty;var Ss=(t,e)=>{for(var n in e)vs(t,n,{get:e[n],enumerable:!0})};var Ie=[],be=[],Ht="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(let t=0,e=Ht.length;t0)throw new Error("Invalid string. Length must be a multiple of 4");let n=t.indexOf("=");n===-1&&(n=e);let r=n===e?0:4-n%4;return[n,r]}function Is(t,e,n){return(e+n)*3/4-n}function Lr(t){let e=ws(t),n=e[0],r=e[1],o=new Uint8Array(Is(t,n,r)),s=0,i=r>0?n-4:n,l;for(l=0;l>16&255,o[s++]=a>>8&255,o[s++]=a&255}if(r===2){let a=be[t.charCodeAt(l)]<<2|be[t.charCodeAt(l+1)]>>4;o[s++]=a&255}if(r===1){let a=be[t.charCodeAt(l)]<<10|be[t.charCodeAt(l+1)]<<4|be[t.charCodeAt(l+2)]>>2;o[s++]=a>>8&255,o[s++]=a&255}return o}function Cs(t){return Ie[t>>18&63]+Ie[t>>12&63]+Ie[t>>6&63]+Ie[t&63]}function Ts(t,e,n){let r=[];for(let o=e;oi?i:s+o));if(n===1){let s=t[e-1];r.push(Ie[s>>2]+Ie[s<<4&63]+"==")}else if(n===2){let s=(t[e-2]<<8)+t[e-1];r.push(Ie[s>>10]+Ie[s>>4&63]+Ie[s<<2&63]+"=")}return r.join("")}function rt(t,e,n,r,o){let s,i,l=o*8-r-1,a=(1<>1,d=-7,p=n?o-1:0,f=n?-1:1,u=t[e+p];for(p+=f,s=u&(1<<-d)-1,u>>=-d,d+=l;d>0;)s=s*256+t[e+p],p+=f,d-=8;for(i=s&(1<<-d)-1,s>>=-d,d+=r;d>0;)i=i*256+t[e+p],p+=f,d-=8;if(s===0)s=1-c;else{if(s===a)return i?NaN:(u?-1:1)*(1/0);i=i+Math.pow(2,r),s=s-c}return(u?-1:1)*i*Math.pow(2,s-r)}function qt(t,e,n,r,o,s){let i,l,a,c=s*8-o-1,d=(1<>1,f=o===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=r?0:s-1,_=r?1:-1,h=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(l=isNaN(e)?1:0,i=d):(i=Math.floor(Math.log(e)/Math.LN2),e*(a=Math.pow(2,-i))<1&&(i--,a*=2),i+p>=1?e+=f/a:e+=f*Math.pow(2,1-p),e*a>=2&&(i++,a/=2),i+p>=d?(l=0,i=d):i+p>=1?(l=(e*a-1)*Math.pow(2,o),i=i+p):(l=e*Math.pow(2,p-1)*Math.pow(2,o),i=0));o>=8;)t[n+u]=l&255,u+=_,l/=256,o-=8;for(i=i<0;)t[n+u]=i&255,u+=_,i/=256,c-=8;t[n+u-_]|=h*128}var xs={INSPECT_MAX_BYTES:50},Wt=2147483647;m.TYPED_ARRAY_SUPPORT=!0;Object.defineProperty(m.prototype,"parent",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.buffer}});Object.defineProperty(m.prototype,"offset",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.byteOffset}});function xe(t){if(t>Wt)throw new RangeError('The value "'+t+'" is invalid for option "size"');let e=new Uint8Array(t);return Object.setPrototypeOf(e,m.prototype),e}function m(t,e,n){if(typeof t=="number"){if(typeof e=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return Xt(t)}return Mr(t,e,n)}m.poolSize=8192;function Mr(t,e,n){if(typeof t=="string")return ks(t,e);if(ArrayBuffer.isView(t))return Ms(t);if(t==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(t instanceof ArrayBuffer||t&&t.buffer instanceof ArrayBuffer||t instanceof SharedArrayBuffer||t&&t.buffer instanceof SharedArrayBuffer)return Qt(t,e,n);if(typeof t=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');let r=t.valueOf&&t.valueOf();if(r!=null&&r!==t)return m.from(r,e,n);let o=js(t);if(o)return o;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof t[Symbol.toPrimitive]=="function")return m.from(t[Symbol.toPrimitive]("string"),e,n);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t)}m.from=function(t,e,n){return Mr(t,e,n)};Object.setPrototypeOf(m.prototype,Uint8Array.prototype);Object.setPrototypeOf(m,Uint8Array);function jr(t){if(typeof t!="number")throw new TypeError('"size" argument must be of type number');if(t<0)throw new RangeError('The value "'+t+'" is invalid for option "size"')}function Ns(t,e,n){return jr(t),t<=0?xe(t):e!==void 0?typeof n=="string"?xe(t).fill(e,n):xe(t).fill(e):xe(t)}m.alloc=function(t,e,n){return Ns(t,e,n)};function Xt(t){return jr(t),xe(t<0?0:en(t)|0)}m.allocUnsafe=function(t){return Xt(t)};m.allocUnsafeSlow=function(t){return Xt(t)};function ks(t,e){if((typeof e!="string"||e==="")&&(e="utf8"),!m.isEncoding(e))throw new TypeError("Unknown encoding: "+e);let n=Or(t,e)|0,r=xe(n),o=r.write(t,e);return o!==n&&(r=r.slice(0,o)),r}function Kt(t){let e=t.length<0?0:en(t.length)|0,n=xe(e);for(let r=0;r=Wt)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+Wt.toString(16)+" bytes");return t|0}m.isBuffer=function(e){return e!=null&&e._isBuffer===!0&&e!==m.prototype};m.compare=function(e,n){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),n instanceof Uint8Array&&(n=m.from(n,n.offset,n.byteLength)),!m.isBuffer(e)||!m.isBuffer(n))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(e===n)return 0;let r=e.length,o=n.length;for(let s=0,i=Math.min(r,o);so.length?(m.isBuffer(i)||(i=m.from(i.buffer,i.byteOffset,i.byteLength)),i.copy(o,s)):Uint8Array.prototype.set.call(o,i,s);else if(m.isBuffer(i))i.copy(o,s);else throw new TypeError('"list" argument must be an Array of Buffers');s+=i.length}return o};function Or(t,e){if(m.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t.byteLength;if(typeof t!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);let n=t.length,r=arguments.length>2&&arguments[2]===!0;if(!r&&n===0)return 0;let o=!1;for(;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return Yt(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return n*2;case"hex":return n>>>1;case"base64":return Jr(t).length;default:if(o)return r?-1:Yt(t).length;e=(""+e).toLowerCase(),o=!0}}m.byteLength=Or;function Os(t,e,n){let r=!1;if((e===void 0||e<0)&&(e=0),e>this.length||((n===void 0||n>this.length)&&(n=this.length),n<=0)||(n>>>=0,e>>>=0,n<=e))return"";for(t||(t="utf8");;)switch(t){case"hex":return Gs(this,e,n);case"utf8":case"utf-8":return Pr(this,e,n);case"ascii":return Vs(this,e,n);case"latin1":case"binary":return Js(this,e,n);case"base64":return Bs(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return $s(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}m.prototype._isBuffer=!0;function Fe(t,e,n){let r=t[e];t[e]=t[n],t[n]=r}m.prototype.swap16=function(){let e=this.length;if(e%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let n=0;nn&&(e+=" ... "),""};m.prototype[Symbol.for("nodejs.util.inspect.custom")]=m.prototype.inspect;m.prototype.compare=function(e,n,r,o,s){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),!m.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(n===void 0&&(n=0),r===void 0&&(r=e?e.length:0),o===void 0&&(o=0),s===void 0&&(s=this.length),n<0||r>e.length||o<0||s>this.length)throw new RangeError("out of range index");if(o>=s&&n>=r)return 0;if(o>=s)return-1;if(n>=r)return 1;if(n>>>=0,r>>>=0,o>>>=0,s>>>=0,this===e)return 0;let i=s-o,l=r-n,a=Math.min(i,l),c=this.slice(o,s),d=e.slice(n,r);for(let p=0;p2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,Number.isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0)if(o)n=0;else return-1;if(typeof e=="string"&&(e=m.from(e,r)),m.isBuffer(e))return e.length===0?-1:xr(t,e,n,r,o);if(typeof e=="number")return e=e&255,typeof Uint8Array.prototype.indexOf=="function"?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):xr(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function xr(t,e,n,r,o){let s=1,i=t.length,l=e.length;if(r!==void 0&&(r=String(r).toLowerCase(),r==="ucs2"||r==="ucs-2"||r==="utf16le"||r==="utf-16le")){if(t.length<2||e.length<2)return-1;s=2,i/=2,l/=2,n/=2}function a(d,p){return s===1?d[p]:d.readUInt16BE(p*s)}let c;if(o){let d=-1;for(c=n;ci&&(n=i-l),c=n;c>=0;c--){let d=!0;for(let p=0;po&&(r=o)):r=o;let s=e.length;r>s/2&&(r=s/2);let i;for(i=0;i>>0,isFinite(r)?(r=r>>>0,o===void 0&&(o="utf8")):(o=r,r=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let s=this.length-n;if((r===void 0||r>s)&&(r=s),e.length>0&&(r<0||n<0)||n>this.length)throw new RangeError("Attempt to write outside buffer bounds");o||(o="utf8");let i=!1;for(;;)switch(o){case"hex":return Rs(this,e,n,r);case"utf8":case"utf-8":return Ps(this,e,n,r);case"ascii":case"latin1":case"binary":return Fs(this,e,n,r);case"base64":return Ds(this,e,n,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Us(this,e,n,r);default:if(i)throw new TypeError("Unknown encoding: "+o);o=(""+o).toLowerCase(),i=!0}};m.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Bs(t,e,n){return e===0&&n===t.length?Zt(t):Zt(t.slice(e,n))}function Pr(t,e,n){n=Math.min(t.length,n);let r=[],o=e;for(;o239?4:s>223?3:s>191?2:1;if(o+l<=n){let a,c,d,p;switch(l){case 1:s<128&&(i=s);break;case 2:a=t[o+1],(a&192)===128&&(p=(s&31)<<6|a&63,p>127&&(i=p));break;case 3:a=t[o+1],c=t[o+2],(a&192)===128&&(c&192)===128&&(p=(s&15)<<12|(a&63)<<6|c&63,p>2047&&(p<55296||p>57343)&&(i=p));break;case 4:a=t[o+1],c=t[o+2],d=t[o+3],(a&192)===128&&(c&192)===128&&(d&192)===128&&(p=(s&15)<<18|(a&63)<<12|(c&63)<<6|d&63,p>65535&&p<1114112&&(i=p))}}i===null?(i=65533,l=1):i>65535&&(i-=65536,r.push(i>>>10&1023|55296),i=56320|i&1023),r.push(i),o+=l}return zs(r)}var Nr=4096;function zs(t){let e=t.length;if(e<=Nr)return String.fromCharCode.apply(String,t);let n="",r=0;for(;rr)&&(n=r);let o="";for(let s=e;sr&&(e=r),n<0?(n+=r,n<0&&(n=0)):n>r&&(n=r),nn)throw new RangeError("Trying to access beyond buffer length")}m.prototype.readUintLE=m.prototype.readUIntLE=function(e,n,r){e=e>>>0,n=n>>>0,r||ie(e,n,this.length);let o=this[e],s=1,i=0;for(;++i>>0,n=n>>>0,r||ie(e,n,this.length);let o=this[e+--n],s=1;for(;n>0&&(s*=256);)o+=this[e+--n]*s;return o};m.prototype.readUint8=m.prototype.readUInt8=function(e,n){return e=e>>>0,n||ie(e,1,this.length),this[e]};m.prototype.readUint16LE=m.prototype.readUInt16LE=function(e,n){return e=e>>>0,n||ie(e,2,this.length),this[e]|this[e+1]<<8};m.prototype.readUint16BE=m.prototype.readUInt16BE=function(e,n){return e=e>>>0,n||ie(e,2,this.length),this[e]<<8|this[e+1]};m.prototype.readUint32LE=m.prototype.readUInt32LE=function(e,n){return e=e>>>0,n||ie(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+this[e+3]*16777216};m.prototype.readUint32BE=m.prototype.readUInt32BE=function(e,n){return e=e>>>0,n||ie(e,4,this.length),this[e]*16777216+(this[e+1]<<16|this[e+2]<<8|this[e+3])};m.prototype.readBigUInt64LE=function(e){e=e>>>0,He(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&ot(e,this.length-8);let o=n+this[++e]*2**8+this[++e]*2**16+this[++e]*2**24,s=this[++e]+this[++e]*2**8+this[++e]*2**16+r*2**24;return BigInt(o)+(BigInt(s)<>>0,He(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&ot(e,this.length-8);let o=n*2**24+this[++e]*2**16+this[++e]*2**8+this[++e],s=this[++e]*2**24+this[++e]*2**16+this[++e]*2**8+r;return(BigInt(o)<>>0,n=n>>>0,r||ie(e,n,this.length);let o=this[e],s=1,i=0;for(;++i=s&&(o-=Math.pow(2,8*n)),o};m.prototype.readIntBE=function(e,n,r){e=e>>>0,n=n>>>0,r||ie(e,n,this.length);let o=n,s=1,i=this[e+--o];for(;o>0&&(s*=256);)i+=this[e+--o]*s;return s*=128,i>=s&&(i-=Math.pow(2,8*n)),i};m.prototype.readInt8=function(e,n){return e=e>>>0,n||ie(e,1,this.length),this[e]&128?(255-this[e]+1)*-1:this[e]};m.prototype.readInt16LE=function(e,n){e=e>>>0,n||ie(e,2,this.length);let r=this[e]|this[e+1]<<8;return r&32768?r|4294901760:r};m.prototype.readInt16BE=function(e,n){e=e>>>0,n||ie(e,2,this.length);let r=this[e+1]|this[e]<<8;return r&32768?r|4294901760:r};m.prototype.readInt32LE=function(e,n){return e=e>>>0,n||ie(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24};m.prototype.readInt32BE=function(e,n){return e=e>>>0,n||ie(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]};m.prototype.readBigInt64LE=function(e){e=e>>>0,He(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&ot(e,this.length-8);let o=this[e+4]+this[e+5]*2**8+this[e+6]*2**16+(r<<24);return(BigInt(o)<>>0,He(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&ot(e,this.length-8);let o=(n<<24)+this[++e]*2**16+this[++e]*2**8+this[++e];return(BigInt(o)<>>0,n||ie(e,4,this.length),rt(this,e,!0,23,4)};m.prototype.readFloatBE=function(e,n){return e=e>>>0,n||ie(e,4,this.length),rt(this,e,!1,23,4)};m.prototype.readDoubleLE=function(e,n){return e=e>>>0,n||ie(e,8,this.length),rt(this,e,!0,52,8)};m.prototype.readDoubleBE=function(e,n){return e=e>>>0,n||ie(e,8,this.length),rt(this,e,!1,52,8)};function pe(t,e,n,r,o,s){if(!m.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||et.length)throw new RangeError("Index out of range")}m.prototype.writeUintLE=m.prototype.writeUIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,r=r>>>0,!o){let l=Math.pow(2,8*r)-1;pe(this,e,n,r,l,0)}let s=1,i=0;for(this[n]=e&255;++i>>0,r=r>>>0,!o){let l=Math.pow(2,8*r)-1;pe(this,e,n,r,l,0)}let s=r-1,i=1;for(this[n+s]=e&255;--s>=0&&(i*=256);)this[n+s]=e/i&255;return n+r};m.prototype.writeUint8=m.prototype.writeUInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,255,0),this[n]=e&255,n+1};m.prototype.writeUint16LE=m.prototype.writeUInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeUint16BE=m.prototype.writeUInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeUint32LE=m.prototype.writeUInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n+3]=e>>>24,this[n+2]=e>>>16,this[n+1]=e>>>8,this[n]=e&255,n+4};m.prototype.writeUint32BE=m.prototype.writeUInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};function Fr(t,e,n,r,o){Vr(e,r,o,t,n,7);let s=Number(e&BigInt(4294967295));t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s;let i=Number(e>>BigInt(32)&BigInt(4294967295));return t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i,n}function Dr(t,e,n,r,o){Vr(e,r,o,t,n,7);let s=Number(e&BigInt(4294967295));t[n+7]=s,s=s>>8,t[n+6]=s,s=s>>8,t[n+5]=s,s=s>>8,t[n+4]=s;let i=Number(e>>BigInt(32)&BigInt(4294967295));return t[n+3]=i,i=i>>8,t[n+2]=i,i=i>>8,t[n+1]=i,i=i>>8,t[n]=i,n+8}m.prototype.writeBigUInt64LE=function(e,n=0){return Fr(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeBigUInt64BE=function(e,n=0){return Dr(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let s=0,i=1,l=0;for(this[n]=e&255;++s>0)-l&255;return n+r};m.prototype.writeIntBE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let s=r-1,i=1,l=0;for(this[n+s]=e&255;--s>=0&&(i*=256);)e<0&&l===0&&this[n+s+1]!==0&&(l=1),this[n+s]=(e/i>>0)-l&255;return n+r};m.prototype.writeInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,127,-128),e<0&&(e=255+e+1),this[n]=e&255,n+1};m.prototype.writeInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),this[n]=e&255,this[n+1]=e>>>8,this[n+2]=e>>>16,this[n+3]=e>>>24,n+4};m.prototype.writeInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};m.prototype.writeBigInt64LE=function(e,n=0){return Fr(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};m.prototype.writeBigInt64BE=function(e,n=0){return Dr(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};function Ur(t,e,n,r,o,s){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function Br(t,e,n,r,o){return e=+e,n=n>>>0,o||Ur(t,e,n,4,34028234663852886e22,-34028234663852886e22),qt(t,e,n,r,23,4),n+4}m.prototype.writeFloatLE=function(e,n,r){return Br(this,e,n,!0,r)};m.prototype.writeFloatBE=function(e,n,r){return Br(this,e,n,!1,r)};function zr(t,e,n,r,o){return e=+e,n=n>>>0,o||Ur(t,e,n,8,17976931348623157e292,-17976931348623157e292),qt(t,e,n,r,52,8),n+8}m.prototype.writeDoubleLE=function(e,n,r){return zr(this,e,n,!0,r)};m.prototype.writeDoubleBE=function(e,n,r){return zr(this,e,n,!1,r)};m.prototype.copy=function(e,n,r,o){if(!m.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r||(r=0),!o&&o!==0&&(o=this.length),n>=e.length&&(n=e.length),n||(n=0),o>0&&o=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-n>>0,r=r===void 0?this.length:r>>>0,e||(e=0);let s;if(typeof e=="number")for(s=n;s2**32?o=kr(String(n)):typeof n=="bigint"&&(o=String(n),(n>BigInt(2)**BigInt(32)||n<-(BigInt(2)**BigInt(32)))&&(o=kr(o)),o+="n"),r+=` It must be ${e}. Received ${o}`,r},RangeError);function kr(t){let e="",n=t.length,r=t[0]==="-"?1:0;for(;n>=r+4;n-=3)e=`_${t.slice(n-3,n)}${e}`;return`${t.slice(0,n)}${e}`}function Hs(t,e,n){He(e,"offset"),(t[e]===void 0||t[e+n]===void 0)&&ot(e,t.length-(n+1))}function Vr(t,e,n,r,o,s){if(t>n||t3?e===0||e===BigInt(0)?l=`>= 0${i} and < 2${i} ** ${(s+1)*8}${i}`:l=`>= -(2${i} ** ${(s+1)*8-1}${i}) and < 2 ** ${(s+1)*8-1}${i}`:l=`>= ${e}${i} and <= ${n}${i}`,new $e.ERR_OUT_OF_RANGE("value",l,t)}Hs(r,o,s)}function He(t,e){if(typeof t!="number")throw new $e.ERR_INVALID_ARG_TYPE(e,"number",t)}function ot(t,e,n){throw Math.floor(t)!==t?(He(t,n),new $e.ERR_OUT_OF_RANGE(n||"offset","an integer",t)):e<0?new $e.ERR_BUFFER_OUT_OF_BOUNDS:new $e.ERR_OUT_OF_RANGE(n||"offset",`>= ${n?1:0} and <= ${e}`,t)}var Zs=/[^+/0-9A-Za-z-_]/g;function qs(t){if(t=t.split("=")[0],t=t.trim().replace(Zs,""),t.length<2)return"";for(;t.length%4!==0;)t=t+"=";return t}function Yt(t,e){e=e||1/0;let n,r=t.length,o=null,s=[];for(let i=0;i55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&s.push(239,191,189);continue}else if(i+1===r){(e-=3)>-1&&s.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&s.push(239,191,189),o=n;continue}n=(o-55296<<10|n-56320)+65536}else o&&(e-=3)>-1&&s.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;s.push(n)}else if(n<2048){if((e-=2)<0)break;s.push(n>>6|192,n&63|128)}else if(n<65536){if((e-=3)<0)break;s.push(n>>12|224,n>>6&63|128,n&63|128)}else if(n<1114112){if((e-=4)<0)break;s.push(n>>18|240,n>>12&63|128,n>>6&63|128,n&63|128)}else throw new Error("Invalid code point")}return s}function Ws(t){let e=[];for(let n=0;n>8,o=n%256,s.push(o),s.push(r);return s}function Jr(t){return Lr(qs(t))}function vt(t,e,n,r){let o;for(o=0;o=e.length||o>=t.length);++o)e[o+n]=t[o];return o}var Qs=function(){let t="0123456789abcdef",e=new Array(256);for(let n=0;n<16;++n){let r=n*16;for(let o=0;o<16;++o)e[r+o]=t[n]+t[o]}return e}();var Bt={};Ss(Bt,{ArtMethod:()=>Mt,ArtStackVisitor:()=>Rn,DVM_JNI_ENV_OFFSET_SELF:()=>po,HandleVector:()=>ut,VariableSizedHandleScope:()=>pt,backtrace:()=>Kn,deoptimizeBootImage:()=>tr,deoptimizeEverything:()=>er,deoptimizeMethod:()=>Xn,ensureClassInitialized:()=>El,getAndroidApiLevel:()=>ee,getAndroidVersion:()=>ft,getApi:()=>J,getArtApexVersion:()=>Jn,getArtClassSpec:()=>$n,getArtFieldSpec:()=>Dt,getArtMethodSpec:()=>_e,getArtThreadFromEnv:()=>Ut,getArtThreadSpec:()=>We,makeArtClassLoaderVisitor:()=>Wn,makeArtClassVisitor:()=>qn,makeMethodMangler:()=>fc,makeObjectVisitorPredicate:()=>rr,revertGlobalPatches:()=>Qn,translateMethod:()=>hc,withAllArtThreadsSuspended:()=>Zn,withRunnableArtThread:()=>ye});var{pageSize:nn,pointerSize:Ys}=Process,rn=class{constructor(e){this.sliceSize=e,this.slicesPerPage=nn/e,this.pages=[],this.free=[]}allocateSlice(e,n){let r=e.near===void 0,o=n===1;if(r&&o){let s=this.free.pop();if(s!==void 0)return s}else if(n{n.deleteGlobalRef(e)})}}y.prototype.fromReflectedMethod=x(7,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.fromReflectedField=x(8,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.toReflectedMethod=x(9,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getSuperclass=x(10,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isAssignableFrom=x(11,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.toReflectedField=x(12,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.throw=x(13,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.exceptionOccurred=x(15,"pointer",["pointer"],function(t){return t(this.handle)});y.prototype.exceptionDescribe=x(16,"void",["pointer"],function(t){t(this.handle)});y.prototype.exceptionClear=x(17,"void",["pointer"],function(t){t(this.handle)});y.prototype.pushLocalFrame=x(19,"int32",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.popLocalFrame=x(20,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newGlobalRef=x(21,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.deleteGlobalRef=x(22,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.deleteLocalRef=x(23,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.isSameObject=x(24,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.newLocalRef=x(25,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.allocObject=x(27,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectClass=x(31,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isInstanceOf=x(32,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.getMethodId=x(33,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getFieldId=x(94,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getIntField=x(100,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStaticMethodId=x(113,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticFieldId=x(144,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticIntField=x(150,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStringLength=x(164,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getStringChars=x(165,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringChars=x(166,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.newStringUtf=x(167,"pointer",["pointer","pointer"],function(t,e){let n=Memory.allocUtf8String(e);return t(this.handle,n)});y.prototype.getStringUtfChars=x(169,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringUtfChars=x(170,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.getArrayLength=x(171,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newObjectArray=x(172,"pointer",["pointer","int32","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getObjectArrayElement=x(173,"pointer",["pointer","pointer","int32"],function(t,e,n){return t(this.handle,e,n)});y.prototype.setObjectArrayElement=x(174,"void",["pointer","pointer","int32","pointer"],function(t,e,n,r){t(this.handle,e,n,r)});y.prototype.newBooleanArray=x(175,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newByteArray=x(176,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newCharArray=x(177,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newShortArray=x(178,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newIntArray=x(179,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newLongArray=x(180,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newFloatArray=x(181,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newDoubleArray=x(182,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.getBooleanArrayElements=x(183,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getByteArrayElements=x(184,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getCharArrayElements=x(185,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getShortArrayElements=x(186,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getIntArrayElements=x(187,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getLongArrayElements=x(188,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getFloatArrayElements=x(189,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getDoubleArrayElements=x(190,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseBooleanArrayElements=x(191,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseByteArrayElements=x(192,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseCharArrayElements=x(193,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseShortArrayElements=x(194,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseIntArrayElements=x(195,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseLongArrayElements=x(196,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseFloatArrayElements=x(197,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.releaseDoubleArrayElements=x(198,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Oe)});y.prototype.getByteArrayRegion=x(200,"void",["pointer","pointer","int","int","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setBooleanArrayRegion=x(207,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setByteArrayRegion=x(208,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setCharArrayRegion=x(209,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setShortArrayRegion=x(210,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setIntArrayRegion=x(211,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setLongArrayRegion=x(212,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setFloatArrayRegion=x(213,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setDoubleArrayRegion=x(214,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.registerNatives=x(215,"int32",["pointer","pointer","pointer","int32"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.monitorEnter=x(217,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.monitorExit=x(218,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getDirectBufferAddress=x(230,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectRefType=x(232,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});var $r=new Map;function Tt(t,e,n,r){return yn(this,"p",wa,t,e,n,r)}function bn(t,e,n,r){return yn(this,"v",Ia,t,e,n,r)}function Sa(t,e,n,r){return yn(this,"n",Ca,t,e,n,r)}function yn(t,e,n,r,o,s,i){if(i!==void 0)return n(t,r,o,s,i);let l=[r,e,o].concat(s).join("|"),a=$r.get(l);return a===void 0&&(a=n(t,r,o,s,Hr),$r.set(l,a)),a}function wa(t,e,n,r,o){return new NativeFunction(Ct(t).add(e*It).readPointer(),n,["pointer","pointer","pointer"].concat(r),o)}function Ia(t,e,n,r,o){return new NativeFunction(Ct(t).add(e*It).readPointer(),n,["pointer","pointer","pointer","..."].concat(r),o)}function Ca(t,e,n,r,o){return new NativeFunction(Ct(t).add(e*It).readPointer(),n,["pointer","pointer","pointer","pointer","..."].concat(r),o)}y.prototype.constructor=function(t,e){return bn.call(this,ti,"pointer",t,e)};y.prototype.vaMethod=function(t,e,n){let r=ha[t];if(r===void 0)throw new Error("Unsupported type: "+t);return bn.call(this,r,t,e,n)};y.prototype.nonvirtualVaMethod=function(t,e,n){let r=_a[t];if(r===void 0)throw new Error("Unsupported type: "+t);return Sa.call(this,r,t,e,n)};y.prototype.staticVaMethod=function(t,e,n){let r=ma[t];if(r===void 0)throw new Error("Unsupported type: "+t);return bn.call(this,r,t,e,n)};y.prototype.getField=function(t){let e=ga[t];if(e===void 0)throw new Error("Unsupported type: "+t);return Tt.call(this,e,t,[])};y.prototype.getStaticField=function(t){let e=ya[t];if(e===void 0)throw new Error("Unsupported type: "+t);return Tt.call(this,e,t,[])};y.prototype.setField=function(t){let e=ba[t];if(e===void 0)throw new Error("Unsupported type: "+t);return Tt.call(this,e,"void",[t])};y.prototype.setStaticField=function(t){let e=Ea[t];if(e===void 0)throw new Error("Unsupported type: "+t);return Tt.call(this,e,"void",[t])};var an=null;y.prototype.javaLangClass=function(){if(an===null){let t=this.findClass("java/lang/Class");try{let e=this.getMethodId.bind(this,t);an={handle:De(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getSimpleName:e("getSimpleName","()Ljava/lang/String;"),getGenericSuperclass:e("getGenericSuperclass","()Ljava/lang/reflect/Type;"),getDeclaredConstructors:e("getDeclaredConstructors","()[Ljava/lang/reflect/Constructor;"),getDeclaredMethods:e("getDeclaredMethods","()[Ljava/lang/reflect/Method;"),getDeclaredFields:e("getDeclaredFields","()[Ljava/lang/reflect/Field;"),isArray:e("isArray","()Z"),isPrimitive:e("isPrimitive","()Z"),isInterface:e("isInterface","()Z"),getComponentType:e("getComponentType","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return an};var ln=null;y.prototype.javaLangObject=function(){if(ln===null){let t=this.findClass("java/lang/Object");try{let e=this.getMethodId.bind(this,t);ln={handle:De(this.newGlobalRef(t)),toString:e("toString","()Ljava/lang/String;"),getClass:e("getClass","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return ln};var cn=null;y.prototype.javaLangReflectConstructor=function(){if(cn===null){let t=this.findClass("java/lang/reflect/Constructor");try{cn={getGenericParameterTypes:this.getMethodId(t,"getGenericParameterTypes","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return cn};var dn=null;y.prototype.javaLangReflectMethod=function(){if(dn===null){let t=this.findClass("java/lang/reflect/Method");try{let e=this.getMethodId.bind(this,t);dn={getName:e("getName","()Ljava/lang/String;"),getGenericParameterTypes:e("getGenericParameterTypes","()[Ljava/lang/reflect/Type;"),getParameterTypes:e("getParameterTypes","()[Ljava/lang/Class;"),getGenericReturnType:e("getGenericReturnType","()Ljava/lang/reflect/Type;"),getGenericExceptionTypes:e("getGenericExceptionTypes","()[Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),isVarArgs:e("isVarArgs","()Z")}}finally{this.deleteLocalRef(t)}}return dn};var un=null;y.prototype.javaLangReflectField=function(){if(un===null){let t=this.findClass("java/lang/reflect/Field");try{let e=this.getMethodId.bind(this,t);un={getName:e("getName","()Ljava/lang/String;"),getType:e("getType","()Ljava/lang/Class;"),getGenericType:e("getGenericType","()Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),toString:e("toString","()Ljava/lang/String;")}}finally{this.deleteLocalRef(t)}}return un};var pn=null;y.prototype.javaLangReflectTypeVariable=function(){if(pn===null){let t=this.findClass("java/lang/reflect/TypeVariable");try{let e=this.getMethodId.bind(this,t);pn={handle:De(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getBounds:e("getBounds","()[Ljava/lang/reflect/Type;"),getGenericDeclaration:e("getGenericDeclaration","()Ljava/lang/reflect/GenericDeclaration;")}}finally{this.deleteLocalRef(t)}}return pn};var fn=null;y.prototype.javaLangReflectWildcardType=function(){if(fn===null){let t=this.findClass("java/lang/reflect/WildcardType");try{let e=this.getMethodId.bind(this,t);fn={handle:De(this.newGlobalRef(t)),getLowerBounds:e("getLowerBounds","()[Ljava/lang/reflect/Type;"),getUpperBounds:e("getUpperBounds","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return fn};var hn=null;y.prototype.javaLangReflectGenericArrayType=function(){if(hn===null){let t=this.findClass("java/lang/reflect/GenericArrayType");try{hn={handle:De(this.newGlobalRef(t)),getGenericComponentType:this.getMethodId(t,"getGenericComponentType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return hn};var _n=null;y.prototype.javaLangReflectParameterizedType=function(){if(_n===null){let t=this.findClass("java/lang/reflect/ParameterizedType");try{let e=this.getMethodId.bind(this,t);_n={handle:De(this.newGlobalRef(t)),getActualTypeArguments:e("getActualTypeArguments","()[Ljava/lang/reflect/Type;"),getRawType:e("getRawType","()Ljava/lang/reflect/Type;"),getOwnerType:e("getOwnerType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return _n};var mn=null;y.prototype.javaLangString=function(){if(mn===null){let t=this.findClass("java/lang/String");try{mn={handle:De(this.newGlobalRef(t))}}finally{this.deleteLocalRef(t)}}return mn};y.prototype.getClassName=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangClass().getName);try{return this.stringFromJni(e)}finally{this.deleteLocalRef(e)}};y.prototype.getObjectClassName=function(t){let e=this.getObjectClass(t);try{return this.getClassName(e)}finally{this.deleteLocalRef(e)}};y.prototype.getActualTypeArgument=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangReflectParameterizedType().getActualTypeArguments);if(this.throwIfExceptionPending(),!e.isNull())try{return this.getTypeNameFromFirstTypeElement(e)}finally{this.deleteLocalRef(e)}};y.prototype.getTypeNameFromFirstTypeElement=function(t){if(this.getArrayLength(t)>0){let n=this.getObjectArrayElement(t,0);try{return this.getTypeName(n)}finally{this.deleteLocalRef(n)}}else return"java.lang.Object"};y.prototype.getTypeName=function(t,e){let n=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle))return this.getArrayTypeName(t);if(this.isInstanceOf(t,this.javaLangReflectParameterizedType().handle)){let r=n(this.handle,t,this.javaLangReflectParameterizedType().getRawType);this.throwIfExceptionPending();let o;try{o=this.getTypeName(r)}finally{this.deleteLocalRef(r)}return e&&(o+="<"+this.getActualTypeArgument(t)+">"),o}else return this.isInstanceOf(t,this.javaLangReflectTypeVariable().handle)||this.isInstanceOf(t,this.javaLangReflectWildcardType().handle),"java.lang.Object"};y.prototype.getArrayTypeName=function(t){let e=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle)){let n=e(this.handle,t,this.javaLangReflectGenericArrayType().getGenericComponentType);this.throwIfExceptionPending();try{return"[L"+this.getTypeName(n)+";"}finally{this.deleteLocalRef(n)}}else return"[Ljava.lang.Object;"};y.prototype.stringFromJni=function(t){let e=this.getStringChars(t);if(e.isNull())throw new Error("Unable to access string");try{let n=this.getStringLength(t);return e.readUtf16String(n)}finally{this.releaseStringChars(t,e)}};var Zr=65542,Ze=Process.pointerSize,En=Process.getCurrentThreadId(),Ue=new Map,it=new Map;function Ce(t){let e=t.vm,n=null,r=null,o=null;function s(){let l=e.readPointer(),a={exceptions:"propagate"};n=new NativeFunction(l.add(4*Ze).readPointer(),"int32",["pointer","pointer","pointer"],a),r=new NativeFunction(l.add(5*Ze).readPointer(),"int32",["pointer"],a),o=new NativeFunction(l.add(6*Ze).readPointer(),"int32",["pointer","pointer","int32"],a)}this.handle=e,this.perform=function(l){let a=Process.getCurrentThreadId(),c=i(a);if(c!==null)return l(c);let d=this._tryGetEnv(),p=d!==null;p||(d=this.attachCurrentThread(),Ue.set(a,!0)),this.link(a,d);try{return l(d)}finally{let f=a===En;if(f||this.unlink(a),!p&&!f){let u=Ue.get(a);Ue.delete(a),u&&this.detachCurrentThread()}}},this.attachCurrentThread=function(){let l=Memory.alloc(Ze);return de("VM::AttachCurrentThread",n(e,l,NULL)),new y(l.readPointer(),this)},this.detachCurrentThread=function(){de("VM::DetachCurrentThread",r(e))},this.preventDetachDueToClassLoader=function(){let l=Process.getCurrentThreadId();Ue.has(l)&&Ue.set(l,!1)},this.getEnv=function(){let l=i(Process.getCurrentThreadId());if(l!==null)return l;let a=Memory.alloc(Ze),c=o(e,a,Zr);if(c===-2)throw new Error("Current thread is not attached to the Java VM; please move this code inside a Java.perform() callback");return de("VM::GetEnv",c),new y(a.readPointer(),this)},this.tryGetEnv=function(){let l=i(Process.getCurrentThreadId());return l!==null?l:this._tryGetEnv()},this._tryGetEnv=function(){let l=this.tryGetEnvHandle(Zr);return l===null?null:new y(l,this)},this.tryGetEnvHandle=function(l){let a=Memory.alloc(Ze);return o(e,a,l)!==0?null:a.readPointer()},this.makeHandleDestructor=function(l){return()=>{this.perform(a=>{a.deleteGlobalRef(l)})}},this.link=function(l,a){let c=it.get(l);c===void 0?it.set(l,[a,1]):c[1]++},this.unlink=function(l){let a=it.get(l);a[1]===1?it.delete(l):a[1]--};function i(l){let a=it.get(l);return a===void 0?null:a[0]}s.call(this)}Ce.dispose=function(t){Ue.get(En)===!0&&(Ue.delete(En),t.detachCurrentThread())};var Ta=4,v=Process.pointerSize,{readU32:Aa,readPointer:La,writeU32:xa,writePointer:Na}=NativePointer.prototype,ka=1,Ma=8,ja=16,Nt=256,Oa=524288,Ra=2097152,uo=1073741824,Pa=524288,Fa=134217728,qr=1048576,Da=2097152,Ua=268435456,Ba=268435456,za=0,kn=3,Mn=5,Vn=ptr(1).not(),Va=2147467263,Ja=4294963200,Ft=17*v,Ga=18*v,po=12,$a=112,Ha=116,Za=0,Sn=56,Wr=4,qa=8,Wa=10,Ka=12,Qa=14,Ya=28,Xa=36,el=0,tl=1,nl=2,rl=3,ol=4,sl=5,il=6,al=7,Kr=2147483648,ll=28,dt=3*v,cl=3*v,dl=1,ul=1,fo=ce(Sl),pl=ce(Rl),_e=ce(Fl),We=ce(Dl),fl=ce(Ul),hl=ce(ql),ft=ce(Jl),ho=ce(Gl),ee=ce($l),Jn=ce(Hl),_l=ce(Yl),ml=Process.arch==="ia32"?Dc:Fc,W={exceptions:"propagate"},at={},wn=null,In=null,_o=null,oe=null,Gn=[],kt=new Map,mo=[],Cn=null,Qr=0,Yr=!1,Xr=!1,lt=null,gl=[],Tn=null,At=null;function J(){return wn===null&&(wn=bl()),wn}function bl(){let t=Process.enumerateModules().filter(u=>/^lib(art|dvm).so$/.test(u.name)).filter(u=>!/\/system\/fake-libs/.test(u.path));if(t.length===0)return null;let e=t[0],n=e.name.indexOf("art")!==-1?"art":"dalvik",r=n==="art",o={module:e,find(u){let{module:_}=this,h=_.findExportByName(u);return h===null&&(h=_.findSymbolByName(u)),h},flavor:n,addLocalReference:null};o.isApiLevel34OrApexEquivalent=r&&(o.find("_ZN3art7AppInfo29GetPrimaryApkReferenceProfileEv")!==null||o.find("_ZN3art6Thread15RunFlipFunctionEPS0_")!==null);let s=r?{functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],artInterpreterToCompiledCodeBridge:function(u){this.artInterpreterToCompiledCodeBridge=u},_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art17ReaderWriterMutex13ExclusiveLockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveLock","void",["pointer","pointer"]],_ZN3art17ReaderWriterMutex15ExclusiveUnlockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveUnlock","void",["pointer","pointer"]],_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art9JavaVMExt12DecodeGlobalEPv:function(u){let _;ee()>=26?_=ml(u,["pointer","pointer"]):_=new NativeFunction(u,"pointer",["pointer","pointer"],W),this["art::JavaVMExt::DecodeGlobal"]=function(h,g,b){return _(h,b)}},_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv:["art::JavaVMExt::DecodeGlobal","pointer",["pointer","pointer","pointer"]],_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZNK3art6Thread13DecodeJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZN3art10ThreadList10SuspendAllEPKcb:["art::ThreadList::SuspendAll","void",["pointer","pointer","bool"]],_ZN3art10ThreadList10SuspendAllEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::ThreadList::SuspendAll"]=function(h,g,b){return _(h)}},_ZN3art10ThreadList9ResumeAllEv:["art::ThreadList::ResumeAll","void",["pointer"]],_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE:["art::ClassLinker::VisitClasses","void",["pointer","pointer"]],_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer"],W);this["art::ClassLinker::VisitClasses"]=function(h,g){_(h,g,NULL)}},_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE:["art::ClassLinker::VisitClassLoaders","void",["pointer","pointer"]],_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_:["art::gc::Heap::VisitObjects","void",["pointer","pointer","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:["art::gc::Heap::GetInstances","void",["pointer","pointer","pointer","int","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer","bool","int","pointer"],W);this["art::gc::Heap::GetInstances"]=function(h,g,b,E,C){_(h,g,b,0,E,C)}},_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","uint","bool"]],_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","size_t","bool"]],_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb:["art::StackVisitor::WalkStack","void",["pointer","bool"]],_ZNK3art12StackVisitor9GetMethodEv:["art::StackVisitor::GetMethod","pointer",["pointer"]],_ZNK3art12StackVisitor16DescribeLocationEv:function(u){this["art::StackVisitor::DescribeLocation"]=xt(u,["pointer"])},_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv:function(u){this["art::StackVisitor::GetCurrentQuickFrameInfo"]=Ql(u)},_ZN3art7Context6CreateEv:["art::Context::Create","pointer",[]],_ZN3art6Thread18GetLongJumpContextEv:["art::Thread::GetLongJumpContext","pointer",["pointer"]],_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:function(u){this["art::mirror::Class::GetDescriptor"]=u},_ZN3art6mirror5Class11GetLocationEv:function(u){this["art::mirror::Class::GetLocation"]=xt(u,["pointer"])},_ZN3art9ArtMethod12PrettyMethodEb:function(u){this["art::ArtMethod::PrettyMethod"]=xt(u,["pointer","bool"])},_ZN3art12PrettyMethodEPNS_9ArtMethodEb:function(u){this["art::ArtMethod::PrettyMethodNullSafe"]=xt(u,["pointer","bool"])},_ZN3art6Thread14CurrentFromGdbEv:["art::Thread::CurrentFromGdb","pointer",[]],_ZN3art6mirror6Object5CloneEPNS_6ThreadE:function(u){this["art::mirror::Object::Clone"]=new NativeFunction(u,"pointer",["pointer","pointer"],W)},_ZN3art6mirror6Object5CloneEPNS_6ThreadEm:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","pointer"],W);this["art::mirror::Object::Clone"]=function(h,g){let b=NULL;return _(h,g,b)}},_ZN3art6mirror6Object5CloneEPNS_6ThreadEj:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","uint"],W);this["art::mirror::Object::Clone"]=function(h,g){return _(h,g,0)}},_ZN3art3Dbg14SetJdwpAllowedEb:["art::Dbg::SetJdwpAllowed","void",["bool"]],_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE:["art::Dbg::ConfigureJdwp","void",["pointer"]],_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv:["art::InternalDebuggerControlCallback::StartDebugger","void",["pointer"]],_ZN3art3Dbg9StartJdwpEv:["art::Dbg::StartJdwp","void",[]],_ZN3art3Dbg8GoActiveEv:["art::Dbg::GoActive","void",[]],_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE:["art::Dbg::RequestDeoptimization","void",["pointer"]],_ZN3art3Dbg20ManageDeoptimizationEv:["art::Dbg::ManageDeoptimization","void",[]],_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv:["art::Instrumentation::EnableDeoptimization","void",["pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc:["art::Instrumentation::DeoptimizeEverything","void",["pointer","pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::Instrumentation::DeoptimizeEverything"]=function(h,g){_(h)}},_ZN3art7Runtime19DeoptimizeBootImageEv:["art::Runtime::DeoptimizeBootImage","void",["pointer"]],_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE:["art::Instrumentation::Deoptimize","void",["pointer","pointer"]],_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID:["art::jni::JniIdManager::DecodeMethodId","pointer",["pointer","pointer"]],_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID:["art::jni::JniIdManager::DecodeFieldId","pointer",["pointer","pointer"]],_ZN3art11interpreter18GetNterpEntryPointEv:["art::interpreter::GetNterpEntryPoint","pointer",[]],_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi:["art::Monitor::TranslateLocation","void",["pointer","uint32","pointer","pointer"]]},variables:{_ZN3art3Dbg9gRegistryE:function(u){this.isJdwpStarted=()=>!u.readPointer().isNull()},_ZN3art3Dbg15gDebuggerActiveE:function(u){this.isDebuggerActive=()=>!!u.readU8()}},optionals:new Set(["artInterpreterToCompiledCodeBridge","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE","_ZN3art9JavaVMExt12DecodeGlobalEPv","_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv","_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject","_ZNK3art6Thread13DecodeJObjectEP8_jobject","_ZN3art10ThreadList10SuspendAllEPKcb","_ZN3art10ThreadList10SuspendAllEv","_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE","_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_","_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE","_ZN3art6mirror6Object5CloneEPNS_6ThreadE","_ZN3art6mirror6Object5CloneEPNS_6ThreadEm","_ZN3art6mirror6Object5CloneEPNS_6ThreadEj","_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE","_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb","_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb","_ZNK3art12StackVisitor9GetMethodEv","_ZNK3art12StackVisitor16DescribeLocationEv","_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv","_ZN3art7Context6CreateEv","_ZN3art6Thread18GetLongJumpContextEv","_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE","_ZN3art6mirror5Class11GetLocationEv","_ZN3art9ArtMethod12PrettyMethodEb","_ZN3art12PrettyMethodEPNS_9ArtMethodEb","_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE","_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv","_ZN3art3Dbg15gDebuggerActiveE","_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv","_ZN3art7Runtime19DeoptimizeBootImageEv","_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE","_ZN3art3Dbg9StartJdwpEv","_ZN3art3Dbg8GoActiveEv","_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE","_ZN3art3Dbg20ManageDeoptimizationEv","_ZN3art3Dbg9gRegistryE","_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID","_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID","_ZN3art11interpreter18GetNterpEntryPointEv","_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi"])}:{functions:{_Z20dvmDecodeIndirectRefP6ThreadP8_jobject:["dvmDecodeIndirectRef","pointer",["pointer","pointer"]],_Z15dvmUseJNIBridgeP6MethodPv:["dvmUseJNIBridge","void",["pointer","pointer"]],_Z20dvmHeapSourceGetBasev:["dvmHeapSourceGetBase","pointer",[]],_Z21dvmHeapSourceGetLimitv:["dvmHeapSourceGetLimit","pointer",[]],_Z16dvmIsValidObjectPK6Object:["dvmIsValidObject","uint8",["pointer"]],JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]]},variables:{gDvmJni:function(u){this.gDvmJni=u},gDvm:function(u){this.gDvm=u}}},{functions:i={},variables:l={},optionals:a=new Set}=s,c=[];for(let[u,_]of Object.entries(i)){let h=o.find(u);h!==null?typeof _=="function"?_.call(o,h):o[_[0]]=new NativeFunction(h,_[1],_[2],W):a.has(u)||c.push(u)}for(let[u,_]of Object.entries(l)){let h=o.find(u);h!==null?_.call(o,h):a.has(u)||c.push(u)}if(c.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+c.join(", "));let d=Memory.alloc(v),p=Memory.alloc(Ta);if(de("JNI_GetCreatedJavaVMs",o.JNI_GetCreatedJavaVMs(d,1,p)),p.readInt()===0)return null;if(o.vm=d.readPointer(),r){let u=ee(),_;u>=27?_=33554432:u>=24?_=16777216:_=0,o.kAccCompileDontBother=_;let h=o.vm.add(v).readPointer();o.artRuntime=h;let g=fo(o),b=g.offset,E=b.instrumentation;o.artInstrumentation=E!==null?h.add(E):null,Jn()>=36e7&&o.artInstrumentation!=null&&(o.artInstrumentation=o.artInstrumentation.readPointer()),o.artHeap=h.add(b.heap).readPointer(),o.artThreadList=h.add(b.threadList).readPointer();let A=h.add(b.classLinker).readPointer(),M=Pl(h,g).offset,O=A.add(M.quickResolutionTrampoline).readPointer(),k=A.add(M.quickImtConflictTrampoline).readPointer(),N=A.add(M.quickGenericJniTrampoline).readPointer(),S=A.add(M.quickToInterpreterBridgeTrampoline).readPointer();o.artClassLinker={address:A,quickResolutionTrampoline:O,quickImtConflictTrampoline:k,quickGenericJniTrampoline:N,quickToInterpreterBridgeTrampoline:S};let L=new Ce(o);o.artQuickGenericJniTrampoline=An(N,L),o.artQuickToInterpreterBridge=An(S,L),o.artQuickResolutionTrampoline=An(O,L),o["art::JavaVMExt::AddGlobalRef"]===void 0&&(o["art::JavaVMExt::AddGlobalRef"]=kc(o)),o["art::JavaVMExt::DecodeGlobal"]===void 0&&(o["art::JavaVMExt::DecodeGlobal"]=Mc(o)),o["art::ArtMethod::PrettyMethod"]===void 0&&(o["art::ArtMethod::PrettyMethod"]=o["art::ArtMethod::PrettyMethodNullSafe"]),o["art::interpreter::GetNterpEntryPoint"]!==void 0?o.artNterpEntryPoint=o["art::interpreter::GetNterpEntryPoint"]():o.artNterpEntryPoint=o.find("ExecuteNterpImpl"),oe=tc(o,L),Pc(o);let j=null;Object.defineProperty(o,"jvmti",{get(){return j===null&&(j=[yl(L,this.artRuntime)]),j[0]}})}let f=e.enumerateImports().filter(u=>u.name.indexOf("_Z")===0).reduce((u,_)=>(u[_.name]=_.address,u),{});return o.$new=new NativeFunction(f._Znwm||f._Znwj,"pointer",["ulong"],W),o.$delete=new NativeFunction(f._ZdlPv,"void",["pointer"],W),_o=r?Dn:Un,o}function yl(t,e){let n=null;return t.perform(()=>{let r=J().find("_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE");if(r===null)return;let o=new NativeFunction(r,"bool",["pointer","pointer","pointer"]),s=Memory.alloc(v);if(!o(e,Memory.allocUtf8String("libopenjdkjvmti.so"),s))return;let l=St.v1_2|1073741824,a=t.tryGetEnvHandle(l);if(a===null)return;n=new Ne(a,t);let c=Memory.alloc(8);c.writeU64(wt.canTagObjects),n.addCapabilities(c)!==0&&(n=null)}),n}function El(t,e){J().flavor==="art"&&t.getClassName(e)}function vl(t){return{offset:v===4?{globalsLock:32,globals:72}:{globalsLock:64,globals:112}}}function Sl(t){let e=t.vm,n=t.artRuntime,r=v===4?200:384,o=r+100*v,s=ee(),i=ho(),{isApiLevel34OrApexEquivalent:l}=t,a=null;for(let d=r;d!==o;d+=v)if(n.add(d).readPointer().equals(e)){let f,u=null;s>=33||i==="Tiramisu"||l?(f=[d-4*v],u=d-v):s>=30||i==="R"?(f=[d-3*v,d-4*v],u=d-v):s>=29?f=[d-2*v]:s>=27?f=[d-dt-3*v]:f=[d-dt-2*v];for(let _ of f){let h=_-v,g=h-v,b;l?b=g-9*v:s>=24?b=g-8*v:s>=23?b=g-7*v:b=g-4*v;let E={offset:{heap:b,threadList:g,internTable:h,classLinker:_,jniIdManager:u}};if(go(n,E)!==null){a=E;break}}break}if(a===null)throw new Error("Unable to determine Runtime field offsets");let c=Jn()>=36e7;return a.offset.instrumentation=c?Ll(t):Il(t),a.offset.jniIdsIndirection=Ml(t),a}var wl={ia32:eo,x64:eo,arm:Cl,arm64:Tl};function Il(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:ke(e,wl[Process.arch],{limit:30})}function eo(t){if(t.mnemonic!=="lea")return null;let e=t.operands[1].value.disp;return e<256||e>1024?null:e}function Cl(t){if(t.mnemonic!=="add.w")return null;let e=t.operands;if(e.length!==3)return null;let n=e[2];return n.type!=="imm"?null:n.value}function Tl(t){if(t.mnemonic!=="add")return null;let e=t.operands;if(e.length!==3||e[0].value==="sp"||e[1].value==="sp")return null;let n=e[2];if(n.type!=="imm")return null;let r=n.value.valueOf();return r<256||r>1024?null:r}var Al={ia32:to,x64:to,arm:xl,arm64:Nl};function Ll(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:ke(e,Al[Process.arch],{limit:30})}function to(t){if(t.mnemonic!=="mov")return null;let e=t.operands;if(e[0].value!=="rax")return null;let r=e[1];if(r.type!=="mem")return null;let o=r.value;if(o.base!=="rdi")return null;let s=o.disp;return s<256||s>1024?null:s}function xl(t){return null}function Nl(t){if(t.mnemonic!=="ldr")return null;let e=t.operands;if(e[0].value==="x0")return null;let n=e[1].value;if(n.base!=="x0")return null;let r=n.disp;return r<256||r>1024?null:r}var kl={ia32:no,x64:no,arm:jl,arm64:Ol};function Ml(t){let e=t.find("_ZN3art7Runtime12SetJniIdTypeENS_9JniIdTypeE");if(e===null)return null;let n=ke(e,kl[Process.arch],{limit:20});if(n===null)throw new Error("Unable to determine Runtime.jni_ids_indirection_ offset");return n}function no(t){return t.mnemonic==="cmp"?t.operands[0].value.disp:null}function jl(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Ol(t,e){if(e===null)return null;let{mnemonic:n}=t,{mnemonic:r}=e;return n==="cmp"&&r==="ldr"||n==="bl"&&r==="str"?e.operands[1].value.disp:null}function Rl(){let e={"4-21":136,"4-22":136,"4-23":172,"4-24":196,"4-25":196,"4-26":196,"4-27":196,"4-28":212,"4-29":172,"4-30":180,"4-31":180,"8-21":224,"8-22":224,"8-23":296,"8-24":344,"8-25":344,"8-26":352,"8-27":352,"8-28":392,"8-29":328,"8-30":336,"8-31":336}[`${v}-${ee()}`];if(e===void 0)throw new Error("Unable to determine Instrumentation field offsets");return{offset:{forcedInterpretOnly:4,deoptimizationEnabled:e}}}function Pl(t,e){let n=go(t,e);if(n===null)throw new Error("Unable to determine ClassLinker field offsets");return n}function go(t,e){if(In!==null)return In;let{classLinker:n,internTable:r}=e.offset,o=t.add(n).readPointer(),s=t.add(r).readPointer(),i=v===4?100:200,l=i+100*v,a=ee(),c=null;for(let d=i;d!==l;d+=v)if(o.add(d).readPointer().equals(s)){let f;a>=30||ho()==="R"?f=6:a>=29?f=4:a>=23?f=3:f=5;let u=d+f*v,_;a>=23?_=u-2*v:_=u-3*v,c={offset:{quickResolutionTrampoline:_,quickImtConflictTrampoline:u-v,quickGenericJniTrampoline:u,quickToInterpreterBridgeTrampoline:u+v}};break}return c!==null&&(In=c),c}function $n(t){let n=null;return t.perform(r=>{let o=Dt(t),s=_e(t),i={artArrayLengthSize:4,artArrayEntrySize:o.size,artArrayMax:50},l={artArrayLengthSize:v,artArrayEntrySize:s.size,artArrayMax:100},a=(f,u,_)=>{let h=f.add(u).readPointer();if(h.isNull())return null;let g=_===4?h.readU32():h.readU64().valueOf();return g<=0?null:{length:g,data:h.add(_)}},c=(f,u,_,h)=>{try{let g=a(f,u,h.artArrayLengthSize);if(g===null)return!1;let b=Math.min(g.length,h.artArrayMax);for(let E=0;E!==b;E++)if(g.data.add(E*h.artArrayEntrySize).equals(_))return!0}catch{}return!1},d=r.findClass("java/lang/Thread"),p=r.newGlobalRef(d);try{let f;ye(t,r,N=>{f=J()["art::JavaVMExt::DecodeGlobal"](t,N,p)});let u=so(r.getFieldId(p,"name","Ljava/lang/String;")),_=so(r.getStaticFieldId(p,"MAX_PRIORITY","I")),h=-1,g=-1;for(let N=0;N!==256;N+=4)h===-1&&c(f,N,_,i)&&(h=N),g===-1&&c(f,N,u,i)&&(g=N);if(g===-1||h===-1)throw new Error("Unable to find fields in java/lang/Thread; please file a bug");let b=g!==h?h:0,E=g,C=-1,A=Yn(r.getMethodId(p,"getName","()Ljava/lang/String;"));for(let N=0;N!==256;N+=4)C===-1&&c(f,N,A,l)&&(C=N);if(C===-1)throw new Error("Unable to find methods in java/lang/Thread; please file a bug");let M=-1,k=a(f,C,l.artArrayLengthSize).length;for(let N=C;N!==256;N+=4)if(f.add(N).readU16()===k){M=N;break}if(M===-1)throw new Error("Unable to find copied methods in java/lang/Thread; please file a bug");n={offset:{ifields:E,methods:C,sfields:b,copiedMethodsOffset:M}}}finally{r.deleteLocalRef(d),r.deleteGlobalRef(p)}}),n}function Fl(t){let e=J(),n;return t.perform(r=>{let o=r.findClass("android/os/Process"),s=Yn(r.getStaticMethodId(o,"getElapsedCpuTime","()J"));r.deleteLocalRef(o);let i=Process.getModuleByName("libandroid_runtime.so"),l=i.base,a=l.add(i.size),c=ee(),d=c<=21?8:v,p=ka|Ma|ja|Nt,f=~(uo|Ua|Da)>>>0,u=null,_=null,h=2;for(let E=0;E!==64&&h!==0;E+=4){let C=s.add(E);if(u===null){let A=C.readPointer();A.compare(l)>=0&&A.compare(a)<0&&(u=E,h--)}_===null&&(C.readU32()&f)===p&&(_=E,h--)}if(h!==0)throw new Error("Unable to determine ArtMethod field offsets");let g=u+d;n={size:c<=21?g+32:g+v,offset:{jniCode:u,quickCode:g,accessFlags:_}},"artInterpreterToCompiledCodeBridge"in e&&(n.offset.interpreterCode=u-d)}),n}function Dt(t){let e=ee();return e>=23?{size:16,offset:{accessFlags:4}}:e>=21?{size:24,offset:{accessFlags:12}}:null}function Dl(t){let e=ee(),n;return t.perform(r=>{let o=Ut(r),s=r.handle,i=null,l=null,a=null,c=null,d=null,p=null;for(let f=144;f!==256;f+=v)if(o.add(f).readPointer().equals(s)){l=f-6*v,d=f-4*v,p=f+2*v,e<=22&&(l-=v,i=l-v-9*8-3*4,a=f+6*v,d-=v,p-=v),c=f+9*v,e<=22&&(c+=2*v+4,v===8&&(c+=4)),e>=23&&(c+=v);break}if(c===null)throw new Error("Unable to determine ArtThread field offsets");n={offset:{isExceptionReportedToInstrumentation:i,exception:l,throwLocation:a,topHandleScope:c,managedStack:d,self:p}}}),n}function Ul(){return ee()>=23?{offset:{topQuickFrame:0,link:v}}:{offset:{topQuickFrame:2*v,link:0}}}var Bl={ia32:ro,x64:ro,arm:zl,arm64:Vl};function An(t,e){let n;return e.perform(r=>{let o=Ut(r),s=Bl[Process.arch],i=Instruction.parse(t),l=s(i);l!==null?n=o.add(l).readPointer():n=t}),n}function ro(t){return t.mnemonic==="jmp"?t.operands[0].value.disp:null}function zl(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Vl(t){return t.mnemonic==="ldr"?t.operands[1].value.disp:null}function Ut(t){return t.handle.add(v).readPointer()}function Jl(){return Hn("ro.build.version.release")}function Gl(){return Hn("ro.build.version.codename")}function $l(){return parseInt(Hn("ro.build.version.sdk"),10)}function Hl(){try{let t=File.readAllText("/proc/self/mountinfo"),e=null,n=new Map;for(let o of t.trimEnd().split(` +`)){let s=o.split(" "),i=s[4];if(!i.startsWith("/apex/com.android.art"))continue;let l=s[10];i.includes("@")?n.set(l,i.split("@")[1]):e=l}let r=n.get(e);return r!==void 0?parseInt(r):oo()}catch{return oo()}}function oo(){return ee()*1e7}var Ln=null,Zl=92;function Hn(t){Ln===null&&(Ln=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("__system_property_get"),"int",["pointer","pointer"],W));let e=Memory.alloc(Zl);return Ln(Memory.allocUtf8String(t),e),e.readUtf8String()}function ye(t,e,n){let r=hl(t,e),o=Ut(e).toString();if(at[o]=n,r(e.handle),at[o]!==void 0)throw delete at[o],new Error("Unable to perform state transition; please file a bug")}function ql(t,e){let n=new NativeCallback(Wl,"void",["pointer"]);return Eo(t,e,n)}function Wl(t){let e=t.toString(),n=at[e];delete at[e],n(t)}function Zn(t){let e=J(),n=e.artThreadList;e["art::ThreadList::SuspendAll"](n,Memory.allocUtf8String("frida"),!1?1:0);try{t()}finally{e["art::ThreadList::ResumeAll"](n)}}var jn=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((s,i)=>e(i)===!0?1:0,"bool",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function qn(t){return J()["art::ClassLinker::VisitClasses"]instanceof NativeFunction?new jn(t):new NativeCallback(n=>t(n)===!0?1:0,"bool",["pointer","pointer"])}var On=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((s,i)=>{e(i)},"void",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function Wn(t){return new On(t)}var Kl={"include-inlined-frames":0,"skip-inlined-frames":1},Rn=class{constructor(e,n,r,o=0,s=!0){let i=J(),l=512,a=3*v,c=Memory.alloc(l+a);i["art::StackVisitor::StackVisitor"](c,e,n,Kl[r],o,s?1:0);let d=c.add(l);c.writePointer(d);let p=new NativeCallback(this._visitFrame.bind(this),"bool",["pointer"]);d.add(2*v).writePointer(p),this.handle=c,this._onVisitFrame=p;let f=c.add(v===4?12:24);this._curShadowFrame=f,this._curQuickFrame=f.add(v),this._curQuickFramePc=f.add(2*v),this._curOatQuickMethodHeader=f.add(3*v),this._getMethodImpl=i["art::StackVisitor::GetMethod"],this._descLocImpl=i["art::StackVisitor::DescribeLocation"],this._getCQFIImpl=i["art::StackVisitor::GetCurrentQuickFrameInfo"]}walkStack(e=!1){J()["art::StackVisitor::WalkStack"](this.handle,e?1:0)}_visitFrame(){return this.visitFrame()?1:0}visitFrame(){throw new Error("Subclass must implement visitFrame")}getMethod(){let e=this._getMethodImpl(this.handle);return e.isNull()?null:new Mt(e)}getCurrentQuickFramePc(){return this._curQuickFramePc.readPointer()}getCurrentQuickFrame(){return this._curQuickFrame.readPointer()}getCurrentShadowFrame(){return this._curShadowFrame.readPointer()}describeLocation(){let e=new Rt;return this._descLocImpl(e,this.handle),e.disposeToString()}getCurrentOatQuickMethodHeader(){return this._curOatQuickMethodHeader.readPointer()}getCurrentQuickFrameInfo(){return this._getCQFIImpl(this.handle)}},Mt=class{constructor(e){this.handle=e}prettyMethod(e=!0){let n=new Rt;return J()["art::ArtMethod::PrettyMethod"](n,this.handle,e?1:0),n.disposeToString()}toString(){return`ArtMethod(handle=${this.handle})`}};function Ql(t){return function(e){let n=Memory.alloc(12);return _l(t)(n,e),{frameSizeInBytes:n.readU32(),coreSpillMask:n.add(4).readU32(),fpSpillMask:n.add(8).readU32()}}}function Yl(t){let e=NULL;switch(Process.arch){case"ia32":e=qe(32,n=>{n.putMovRegRegOffsetPtr("ecx","esp",4),n.putMovRegRegOffsetPtr("edx","esp",8),n.putCallAddressWithArguments(t,["ecx","edx"]),n.putMovRegReg("esp","ebp"),n.putPopReg("ebp"),n.putRet()});break;case"x64":e=qe(32,n=>{n.putPushReg("rdi"),n.putCallAddressWithArguments(t,["rsi"]),n.putPopReg("rdi"),n.putMovRegPtrReg("rdi","rax"),n.putMovRegOffsetPtrReg("rdi",8,"edx"),n.putRet()});break;case"arm":e=qe(16,n=>{n.putCallAddressWithArguments(t,["r0","r1"]),n.putPopRegs(["r0","lr"]),n.putMovRegReg("pc","lr")});break;case"arm64":e=qe(64,n=>{n.putPushRegReg("x0","lr"),n.putCallAddressWithArguments(t,["x1"]),n.putPopRegReg("x2","lr"),n.putStrRegRegOffset("x0","x2",0),n.putStrRegRegOffset("w1","x2",8),n.putRet()});break}return new NativeFunction(e,"void",["pointer","pointer"],W)}var Xl={ia32:globalThis.X86Relocator,x64:globalThis.X86Relocator,arm:globalThis.ThumbRelocator,arm64:globalThis.Arm64Relocator},Pn={ia32:globalThis.X86Writer,x64:globalThis.X86Writer,arm:globalThis.ThumbWriter,arm64:globalThis.Arm64Writer};function qe(t,e){Cn===null&&(Cn=Memory.alloc(Process.pageSize));let n=Cn.add(Qr),r=Process.arch,o=Pn[r];return Memory.patchCode(n,t,s=>{let i=new o(s,{pc:n});if(e(i),i.flush(),i.offset>t)throw new Error(`Wrote ${i.offset}, exceeding maximum of ${t}`)}),Qr+=t,r==="arm"?n.or(1):n}function ec(t,e){nc(e),ac(e)}function tc(t,e){let n=We(e).offset,r=fl().offset,o=` +#include + +extern GMutex lock; +extern GHashTable * methods; +extern GHashTable * replacements; +extern gpointer last_seen_art_method; + +extern gpointer get_oat_quick_method_header_impl (gpointer method, gpointer pc); + +void +init (void) +{ + g_mutex_init (&lock); + methods = g_hash_table_new_full (NULL, NULL, NULL, NULL); + replacements = g_hash_table_new_full (NULL, NULL, NULL, NULL); +} + +void +finalize (void) +{ + g_hash_table_unref (replacements); + g_hash_table_unref (methods); + g_mutex_clear (&lock); +} + +gboolean +is_replacement_method (gpointer method) +{ + gboolean is_replacement; + + g_mutex_lock (&lock); + + is_replacement = g_hash_table_contains (replacements, method); + + g_mutex_unlock (&lock); + + return is_replacement; +} + +gpointer +get_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + + g_mutex_unlock (&lock); + + return replacement_method; +} + +void +set_replacement_method (gpointer original_method, + gpointer replacement_method) +{ + g_mutex_lock (&lock); + + g_hash_table_insert (methods, original_method, replacement_method); + g_hash_table_insert (replacements, replacement_method, original_method); + + g_mutex_unlock (&lock); +} + +void +synchronize_replacement_methods (guint quick_code_offset, + void * nterp_entrypoint, + void * quick_to_interpreter_bridge) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + { + void ** quick_code; + + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + quick_code = hooked_method + quick_code_offset; + if (*quick_code == nterp_entrypoint) + *quick_code = quick_to_interpreter_bridge; + } + + g_mutex_unlock (&lock); +} + +void +delete_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + if (replacement_method != NULL) + { + g_hash_table_remove (methods, original_method); + g_hash_table_remove (replacements, replacement_method); + } + + g_mutex_unlock (&lock); +} + +gpointer +translate_method (gpointer method) +{ + gpointer translated_method; + + g_mutex_lock (&lock); + + translated_method = g_hash_table_lookup (replacements, method); + + g_mutex_unlock (&lock); + + return (translated_method != NULL) ? translated_method : method; +} + +gpointer +find_replacement_method_from_quick_code (gpointer method, + gpointer thread) +{ + gpointer replacement_method; + gpointer managed_stack; + gpointer top_quick_frame; + gpointer link_managed_stack; + gpointer * link_top_quick_frame; + + replacement_method = get_replacement_method (method); + if (replacement_method == NULL) + return NULL; + + /* + * Stack check. + * + * Return NULL to indicate that the original method should be invoked, otherwise + * return a pointer to the replacement ArtMethod. + * + * If the caller is our own JNI replacement stub, then a stack transition must + * have been pushed onto the current thread's linked list. + * + * Therefore, we invoke the original method if the following conditions are met: + * 1- The current managed stack is empty. + * 2- The ArtMethod * inside the linked managed stack's top quick frame is the + * same as our replacement. + */ + managed_stack = thread + ${n.managedStack}; + top_quick_frame = *((gpointer *) (managed_stack + ${r.topQuickFrame})); + if (top_quick_frame != NULL) + return replacement_method; + + link_managed_stack = *((gpointer *) (managed_stack + ${r.link})); + if (link_managed_stack == NULL) + return replacement_method; + + link_top_quick_frame = GSIZE_TO_POINTER (*((gsize *) (link_managed_stack + ${r.topQuickFrame})) & ~((gsize) 1)); + if (link_top_quick_frame == NULL || *link_top_quick_frame != replacement_method) + return replacement_method; + + return NULL; +} + +void +on_interpreter_do_call (GumInvocationContext * ic) +{ + gpointer method, replacement_method; + + method = gum_invocation_context_get_nth_argument (ic, 0); + + replacement_method = get_replacement_method (method); + if (replacement_method != NULL) + gum_invocation_context_replace_nth_argument (ic, 0, replacement_method); +} + +gpointer +on_art_method_get_oat_quick_method_header (gpointer method, + gpointer pc) +{ + if (is_replacement_method (method)) + return NULL; + + return get_oat_quick_method_header_impl (method, pc); +} + +void +on_art_method_pretty_method (GumInvocationContext * ic) +{ + const guint this_arg_index = ${Process.arch==="arm64"?0:1}; + gpointer method; + + method = gum_invocation_context_get_nth_argument (ic, this_arg_index); + if (method == NULL) + gum_invocation_context_replace_nth_argument (ic, this_arg_index, last_seen_art_method); + else + last_seen_art_method = method; +} + +void +on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + g_mutex_unlock (&lock); +} +`,s=8,i=v,l=v,a=v,d=Memory.alloc(s+i+l+a),p=d.add(s),f=p.add(i),u=f.add(l),_=t.find(v===4?"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj":"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"),h=new CModule(o,{lock:d,methods:p,replacements:f,last_seen_art_method:u,get_oat_quick_method_header_impl:_??ptr("0xdeadbeef")}),g={exceptions:"propagate",scheduling:"exclusive"};return{handle:h,replacedMethods:{isReplacement:new NativeFunction(h.is_replacement_method,"bool",["pointer"],g),get:new NativeFunction(h.get_replacement_method,"pointer",["pointer"],g),set:new NativeFunction(h.set_replacement_method,"void",["pointer","pointer"],g),synchronize:new NativeFunction(h.synchronize_replacement_methods,"void",["uint","pointer","pointer"],g),delete:new NativeFunction(h.delete_replacement_method,"void",["pointer"],g),translate:new NativeFunction(h.translate_method,"pointer",["pointer"],g),findReplacementFromQuickCode:h.find_replacement_method_from_quick_code},getOatQuickMethodHeaderImpl:_,hooks:{Interpreter:{doCall:h.on_interpreter_do_call},ArtMethod:{getOatQuickMethodHeader:h.on_art_method_get_oat_quick_method_header,prettyMethod:h.on_art_method_pretty_method},Gc:{copyingPhase:{onLeave:h.on_leave_gc_concurrent_copying_copying_phase},runFlip:{onEnter:h.on_leave_gc_concurrent_copying_copying_phase}}}}}function nc(t){Xr||(Xr=!0,rc(t),oc(),sc(),ic())}function rc(t){let e=J();[e.artQuickGenericJniTrampoline,e.artQuickToInterpreterBridge,e.artQuickResolutionTrampoline].forEach(r=>{Memory.protect(r,32,"rwx");let o=new Ot(r);o.activate(t),mo.push(o)})}function oc(){let t=J(),e=ee(),{isApiLevel34OrApexEquivalent:n}=t,r;if(e<=22)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_6mirror9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(e<=33&&!n)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(n)r=/^_ZN3art11interpreter6DoCallILb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtbPNS_6JValueE$/;else throw new Error("Unable to find method invocation in ART; please file a bug");let o=t.module,s=[...o.enumerateExports(),...o.enumerateSymbols()].filter(i=>r.test(i.name));if(s.length===0)throw new Error("Unable to find method invocation in ART; please file a bug");for(let i of s)Interceptor.attach(i.address,oe.hooks.Interpreter.doCall)}function sc(){let t=J(),n=t.module.findSymbolByName("_ZN3art2gc4Heap22CollectGarbageInternalENS0_9collector6GcTypeENS0_7GcCauseEbj");if(n===null)return;let{artNterpEntryPoint:r,artQuickToInterpreterBridge:o}=t,s=_e(t.vm).offset.quickCode;Interceptor.attach(n,{onLeave(){oe.replacedMethods.synchronize(s,r,o)}})}function ic(){let t=[["_ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE","e90340f8 : ff0ff0ff"],["_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEl","7f0f00f9 : 1ffcffff"]],e=J(),n=e.module;for(let[r,o]of t){let s=n.findSymbolByName(r);if(s===null)continue;let i=Memory.scanSync(s,8192,o);if(i.length===0)return;let{artNterpEntryPoint:l,artQuickToInterpreterBridge:a}=e,c=_e(e.vm).offset.quickCode;Interceptor.attach(i[0].address,function(){oe.replacedMethods.synchronize(c,l,a)});return}}function ac(t){if(Yr)return;if(Yr=!0,!cc()){let{getOatQuickMethodHeaderImpl:s}=oe;if(s===null)return;try{Interceptor.replace(s,oe.hooks.ArtMethod.getOatQuickMethodHeader)}catch{}}let e=ee(),n=null,r=J();e>28?n=r.find("_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv"):e>22&&(n=r.find("_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv")),n!==null&&Interceptor.attach(n,oe.hooks.Gc.copyingPhase);let o=null;o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_"),o===null&&(o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_b")),o!==null&&Interceptor.attach(o,oe.hooks.Gc.runFlip)}var lc={arm:{signatures:[{pattern:["b0 68","01 30","0c d0","1b 98",":","c0 ff","c0 ff","00 ff","00 2f"],validateMatch:xn},{pattern:["d8 f8 08 00","01 30","0c d0","1b 98",":","f0 ff ff 0f","ff ff","00 ff","00 2f"],validateMatch:xn},{pattern:["b0 68","01 30","40 f0 c3 80","00 25",":","c0 ff","c0 ff","c0 fb 00 d0","ff f8"],validateMatch:xn}],instrument:uc},arm64:{signatures:[{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","88 39 00 f0",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 00 00 9f"],offset:1,validateMatch:Nn},{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","00 0e 40 f9",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 fc ff ff"],offset:1,validateMatch:Nn},{pattern:["0a 40 b9","1f 05 00 31","01 34 00 54","e0 03 1f aa",":","fc ff ff","1f fc ff ff","1f 00 00 ff","e0 ff ff ff"],offset:1,validateMatch:Nn}],instrument:pc}};function xn({address:t,size:e}){let n=Instruction.parse(t.or(1)),[r,o]=n.operands,s=o.value.base,i=r.value,l=Instruction.parse(n.next.add(2)),a=ptr(l.operands[0].value),c=l.address.add(l.size),d,p;return l.mnemonic==="beq"?(d=c,p=a):(d=a,p=c),ke(d.or(1),f,{limit:3});function f(u){let{mnemonic:_}=u;if(!(_==="ldr"||_==="ldr.w"))return null;let{base:h,disp:g}=u.operands[1].value;return h===s&&g===20?{methodReg:s,scratchReg:i,target:{whenTrue:a,whenRegularMethod:d,whenRuntimeMethod:p}}:null}}function Nn({address:t,size:e}){let[n,r]=Instruction.parse(t).operands,o=r.value.base,s="x"+n.value.substring(1),i=Instruction.parse(t.add(8)),l=ptr(i.operands[0].value),a=t.add(12),c,d;return i.mnemonic==="b.eq"?(c=a,d=l):(c=l,d=a),ke(c,p,{limit:3});function p(f){if(f.mnemonic!=="ldr")return null;let{base:u,disp:_}=f.operands[1].value;return u===o&&_===24?{methodReg:o,scratchReg:s,target:{whenTrue:l,whenRegularMethod:c,whenRuntimeMethod:d}}:null}}function cc(){if(ee()<31)return!1;let t=lc[Process.arch];if(t===void 0)return!1;let e=t.signatures.map(({pattern:r,offset:o=0,validateMatch:s=dc})=>({pattern:new MatchPattern(r.join("")),offset:o,validateMatch:s})),n=[];for(let{base:r,size:o}of J().module.enumerateRanges("--x"))for(let{pattern:s,offset:i,validateMatch:l}of e){let a=Memory.scanSync(r,o,s).map(({address:c,size:d})=>({address:c.sub(i),size:d+i})).filter(c=>{let d=l(c);return d===null?!1:(c.validationResult=d,!0)});n.push(...a)}return n.length===0?!1:(n.forEach(t.instrument),!0)}function dc(){return{}}var jt=class{constructor(e,n,r){this.address=e,this.size=n,this.originalCode=e.readByteArray(n),this.trampoline=r}revert(){Memory.patchCode(this.address,this.size,e=>{e.writeByteArray(this.originalCode)})}};function uc({address:t,size:e,validationResult:n}){let{methodReg:r,target:o}=n,s=Memory.alloc(Process.pageSize),i=e;Memory.patchCode(s,256,l=>{let a=new ThumbWriter(l,{pc:s}),c=new ThumbRelocator(t,a);for(let _=0;_!==2;_++)c.readOne();c.writeAll(),c.readOne(),c.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=[45,237,16,10];a.putBytes(d);let p=["r0","r1","r2","r3"];a.putPushRegs(p),a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegImm("r0",0),a.putPopRegs(p);let f=[189,236,16,10];a.putBytes(f),a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),c.readOne();let u=c.input.address.equals(o.whenRegularMethod);for(a.putLabel(u?"regular_method":"runtime_or_replacement_method"),c.writeOne();i<10;){let _=c.readOne();if(_===0){i=10;break}i=_}c.writeAll(),a.putBranchAddress(t.add(i+1)),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(o.whenTrue),a.flush()}),Gn.push(new jt(t,i,s)),Memory.patchCode(t,i,l=>{let a=new ThumbWriter(l,{pc:t});a.putLdrRegAddress("pc",s.or(1)),a.flush()})}function pc({address:t,size:e,validationResult:n}){let{methodReg:r,scratchReg:o,target:s}=n,i=Memory.alloc(Process.pageSize);Memory.patchCode(i,256,l=>{let a=new Arm64Writer(l,{pc:i}),c=new Arm64Relocator(t,a);for(let _=0;_!==2;_++)c.readOne();c.writeAll(),c.readOne(),c.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=["d0","d1","d2","d3","d4","d5","d6","d7","x0","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10","x11","x12","x13","x14","x15","x16","x17"],p=d.length;for(let _=0;_!==p;_+=2)a.putPushRegReg(d[_],d[_+1]);a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegReg("x0","xzr");for(let _=p-2;_>=0;_-=2)a.putPopRegReg(d[_],d[_+1]);a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),c.readOne();let f=c.input,u=f.address.equals(s.whenRegularMethod);a.putLabel(u?"regular_method":"runtime_or_replacement_method"),c.writeOne(),a.putBranchAddress(f.next),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(s.whenTrue),a.flush()}),Gn.push(new jt(t,e,i)),Memory.patchCode(t,e,l=>{let a=new Arm64Writer(l,{pc:t});a.putLdrRegAddress(o,i),a.putBrReg(o),a.flush()})}function fc(t){return new _o(t)}function hc(t){return oe.replacedMethods.translate(t)}function Kn(t,e={}){let{limit:n=16}=e,r=t.getEnv();return lt===null&&(lt=_c(t,r)),lt.backtrace(r,n)}function _c(t,e){let n=J(),r=Memory.alloc(Process.pointerSize),o=new CModule(` +#include +#include +#include +#include +#include + +typedef struct _ArtBacktrace ArtBacktrace; +typedef struct _ArtStackFrame ArtStackFrame; + +typedef struct _ArtStackVisitor ArtStackVisitor; +typedef struct _ArtStackVisitorVTable ArtStackVisitorVTable; + +typedef struct _ArtClass ArtClass; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtThread ArtThread; +typedef struct _ArtContext ArtContext; + +typedef struct _JNIEnv JNIEnv; + +typedef struct _StdString StdString; +typedef struct _StdTinyString StdTinyString; +typedef struct _StdLargeString StdLargeString; + +typedef enum { + STACK_WALK_INCLUDE_INLINED_FRAMES, + STACK_WALK_SKIP_INLINED_FRAMES, +} StackWalkKind; + +struct _StdTinyString +{ + guint8 unused; + gchar data[(3 * sizeof (gpointer)) - 1]; +}; + +struct _StdLargeString +{ + gsize capacity; + gsize size; + gchar * data; +}; + +struct _StdString +{ + union + { + guint8 flags; + StdTinyString tiny; + StdLargeString large; + }; +}; + +struct _ArtBacktrace +{ + GChecksum * id; + GArray * frames; + gchar * frames_json; +}; + +struct _ArtStackFrame +{ + ArtMethod * method; + gsize dexpc; + StdString description; +}; + +struct _ArtStackVisitorVTable +{ + void (* unused1) (void); + void (* unused2) (void); + bool (* visit) (ArtStackVisitor * visitor); +}; + +struct _ArtStackVisitor +{ + ArtStackVisitorVTable * vtable; + + guint8 padding[512]; + + ArtStackVisitorVTable vtable_storage; + + ArtBacktrace * backtrace; +}; + +struct _ArtMethod +{ + guint32 declaring_class; + guint32 access_flags; +}; + +extern GumTlsKey current_backtrace; + +extern void (* perform_art_thread_state_transition) (JNIEnv * env); + +extern ArtContext * art_make_context (ArtThread * thread); + +extern void art_stack_visitor_init (ArtStackVisitor * visitor, ArtThread * thread, void * context, StackWalkKind walk_kind, + size_t num_frames, bool check_suspended); +extern void art_stack_visitor_walk_stack (ArtStackVisitor * visitor, bool include_transitions); +extern ArtMethod * art_stack_visitor_get_method (ArtStackVisitor * visitor); +extern void art_stack_visitor_describe_location (StdString * description, ArtStackVisitor * visitor); +extern ArtMethod * translate_method (ArtMethod * method); +extern void translate_location (ArtMethod * method, guint32 pc, const gchar ** source_file, gint32 * line_number); +extern void get_class_location (StdString * result, ArtClass * klass); +extern void cxx_delete (void * mem); +extern unsigned long strtoul (const char * str, char ** endptr, int base); + +static bool visit_frame (ArtStackVisitor * visitor); +static void art_stack_frame_destroy (ArtStackFrame * frame); + +static void append_jni_type_name (GString * s, const gchar * name, gsize length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_get_data (StdString * str); + +void +init (void) +{ + current_backtrace = gum_tls_key_new (); +} + +void +finalize (void) +{ + gum_tls_key_free (current_backtrace); +} + +ArtBacktrace * +_create (JNIEnv * env, + guint limit) +{ + ArtBacktrace * bt; + + bt = g_new (ArtBacktrace, 1); + bt->id = g_checksum_new (G_CHECKSUM_SHA1); + bt->frames = (limit != 0) + ? g_array_sized_new (FALSE, FALSE, sizeof (ArtStackFrame), limit) + : g_array_new (FALSE, FALSE, sizeof (ArtStackFrame)); + g_array_set_clear_func (bt->frames, (GDestroyNotify) art_stack_frame_destroy); + bt->frames_json = NULL; + + gum_tls_key_set_value (current_backtrace, bt); + + perform_art_thread_state_transition (env); + + gum_tls_key_set_value (current_backtrace, NULL); + + return bt; +} + +void +_on_thread_state_transition_complete (ArtThread * thread) +{ + ArtContext * context; + ArtStackVisitor visitor = { + .vtable_storage = { + .visit = visit_frame, + }, + }; + + context = art_make_context (thread); + + art_stack_visitor_init (&visitor, thread, context, STACK_WALK_SKIP_INLINED_FRAMES, 0, true); + visitor.vtable = &visitor.vtable_storage; + visitor.backtrace = gum_tls_key_get_value (current_backtrace); + + art_stack_visitor_walk_stack (&visitor, false); + + cxx_delete (context); +} + +static bool +visit_frame (ArtStackVisitor * visitor) +{ + ArtBacktrace * bt = visitor->backtrace; + ArtStackFrame frame; + const gchar * description, * dexpc_part; + + frame.method = art_stack_visitor_get_method (visitor); + + art_stack_visitor_describe_location (&frame.description, visitor); + + description = std_string_get_data (&frame.description); + if (strstr (description, " '<") != NULL) + goto skip; + + dexpc_part = strstr (description, " at dex PC 0x"); + if (dexpc_part == NULL) + goto skip; + frame.dexpc = strtoul (dexpc_part + 13, NULL, 16); + + g_array_append_val (bt->frames, frame); + + g_checksum_update (bt->id, (guchar *) &frame.method, sizeof (frame.method)); + g_checksum_update (bt->id, (guchar *) &frame.dexpc, sizeof (frame.dexpc)); + + return true; + +skip: + std_string_destroy (&frame.description); + return true; +} + +static void +art_stack_frame_destroy (ArtStackFrame * frame) +{ + std_string_destroy (&frame->description); +} + +void +_destroy (ArtBacktrace * backtrace) +{ + g_free (backtrace->frames_json); + g_array_free (backtrace->frames, TRUE); + g_checksum_free (backtrace->id); + g_free (backtrace); +} + +const gchar * +_get_id (ArtBacktrace * backtrace) +{ + return g_checksum_get_string (backtrace->id); +} + +const gchar * +_get_frames (ArtBacktrace * backtrace) +{ + GArray * frames = backtrace->frames; + JsonBuilder * b; + guint i; + JsonNode * root; + + if (backtrace->frames_json != NULL) + return backtrace->frames_json; + + b = json_builder_new_immutable (); + + json_builder_begin_array (b); + + for (i = 0; i != frames->len; i++) + { + ArtStackFrame * frame = &g_array_index (frames, ArtStackFrame, i); + gchar * description, * ret_type, * paren_open, * paren_close, * arg_types, * token, * method_name, * class_name; + GString * signature; + gchar * cursor; + ArtMethod * translated_method; + StdString location; + gsize dexpc; + const gchar * source_file; + gint32 line_number; + + description = std_string_get_data (&frame->description); + + ret_type = strchr (description, '\\'') + 1; + + paren_open = strchr (ret_type, '('); + paren_close = strchr (paren_open, ')'); + *paren_open = '\\0'; + *paren_close = '\\0'; + + arg_types = paren_open + 1; + + token = strrchr (ret_type, '.'); + *token = '\\0'; + + method_name = token + 1; + + token = strrchr (ret_type, ' '); + *token = '\\0'; + + class_name = token + 1; + + signature = g_string_sized_new (128); + + append_jni_type_name (signature, class_name, method_name - class_name - 1); + g_string_append_c (signature, ','); + g_string_append (signature, method_name); + g_string_append (signature, ",("); + + if (arg_types != paren_close) + { + for (cursor = arg_types; cursor != NULL;) + { + gsize length; + gchar * next; + + token = strstr (cursor, ", "); + if (token != NULL) + { + length = token - cursor; + next = token + 2; + } + else + { + length = paren_close - cursor; + next = NULL; + } + + append_jni_type_name (signature, cursor, length); + + cursor = next; + } + } + + g_string_append_c (signature, ')'); + + append_jni_type_name (signature, ret_type, class_name - ret_type - 1); + + translated_method = translate_method (frame->method); + dexpc = (translated_method == frame->method) ? frame->dexpc : 0; + + get_class_location (&location, GSIZE_TO_POINTER (translated_method->declaring_class)); + + translate_location (translated_method, dexpc, &source_file, &line_number); + + json_builder_begin_object (b); + + json_builder_set_member_name (b, "signature"); + json_builder_add_string_value (b, signature->str); + + json_builder_set_member_name (b, "origin"); + json_builder_add_string_value (b, std_string_get_data (&location)); + + json_builder_set_member_name (b, "className"); + json_builder_add_string_value (b, class_name); + + json_builder_set_member_name (b, "methodName"); + json_builder_add_string_value (b, method_name); + + json_builder_set_member_name (b, "methodFlags"); + json_builder_add_int_value (b, translated_method->access_flags); + + json_builder_set_member_name (b, "fileName"); + json_builder_add_string_value (b, source_file); + + json_builder_set_member_name (b, "lineNumber"); + json_builder_add_int_value (b, line_number); + + json_builder_end_object (b); + + std_string_destroy (&location); + g_string_free (signature, TRUE); + } + + json_builder_end_array (b); + + root = json_builder_get_root (b); + backtrace->frames_json = json_to_string (root, FALSE); + json_node_unref (root); + + return backtrace->frames_json; +} + +static void +append_jni_type_name (GString * s, + const gchar * name, + gsize length) +{ + gchar shorty = '\\0'; + gsize i; + + switch (name[0]) + { + case 'b': + if (strncmp (name, "boolean", length) == 0) + shorty = 'Z'; + else if (strncmp (name, "byte", length) == 0) + shorty = 'B'; + break; + case 'c': + if (strncmp (name, "char", length) == 0) + shorty = 'C'; + break; + case 'd': + if (strncmp (name, "double", length) == 0) + shorty = 'D'; + break; + case 'f': + if (strncmp (name, "float", length) == 0) + shorty = 'F'; + break; + case 'i': + if (strncmp (name, "int", length) == 0) + shorty = 'I'; + break; + case 'l': + if (strncmp (name, "long", length) == 0) + shorty = 'J'; + break; + case 's': + if (strncmp (name, "short", length) == 0) + shorty = 'S'; + break; + case 'v': + if (strncmp (name, "void", length) == 0) + shorty = 'V'; + break; + } + + if (shorty != '\\0') + { + g_string_append_c (s, shorty); + + return; + } + + if (length > 2 && name[length - 2] == '[' && name[length - 1] == ']') + { + g_string_append_c (s, '['); + append_jni_type_name (s, name, length - 2); + + return; + } + + g_string_append_c (s, 'L'); + + for (i = 0; i != length; i++) + { + gchar ch = name[i]; + if (ch != '.') + g_string_append_c (s, ch); + else + g_string_append_c (s, '/'); + } + + g_string_append_c (s, ';'); +} + +static void +std_string_destroy (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + if (is_large) + cxx_delete (str->large.data); +} + +static gchar * +std_string_get_data (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + return is_large ? str->large.data : str->tiny.data; +} +`,{current_backtrace:Memory.alloc(Process.pointerSize),perform_art_thread_state_transition:r,art_make_context:n["art::Thread::GetLongJumpContext"]??n["art::Context::Create"],art_stack_visitor_init:n["art::StackVisitor::StackVisitor"],art_stack_visitor_walk_stack:n["art::StackVisitor::WalkStack"],art_stack_visitor_get_method:n["art::StackVisitor::GetMethod"],art_stack_visitor_describe_location:n["art::StackVisitor::DescribeLocation"],translate_method:oe.replacedMethods.translate,translate_location:n["art::Monitor::TranslateLocation"],get_class_location:n["art::mirror::Class::GetLocation"],cxx_delete:n.$delete,strtoul:Process.getModuleByName("libc.so").getExportByName("strtoul")}),s=new NativeFunction(o._create,"pointer",["pointer","uint"],W),i=new NativeFunction(o._destroy,"void",["pointer"],W),l={exceptions:"propagate",scheduling:"exclusive"},a=new NativeFunction(o._get_id,"pointer",["pointer"],l),c=new NativeFunction(o._get_frames,"pointer",["pointer"],l),d=Eo(t,e,o._on_thread_state_transition_complete);o._performData=d,r.writePointer(d),o.backtrace=(f,u)=>{let _=s(f,u),h=new Fn(_);return Script.bindWeak(h,p.bind(null,_)),h};function p(f){i(f)}return o.getId=f=>a(f).readUtf8String(),o.getFrames=f=>JSON.parse(c(f).readUtf8String()),o}var Fn=class{constructor(e){this.handle=e}get id(){return lt.getId(this.handle)}get frames(){return lt.getFrames(this.handle)}};function Qn(){kt.forEach(t=>{t.vtablePtr.writePointer(t.vtable),t.vtableCountPtr.writeS32(t.vtableCount)}),kt.clear();for(let t of mo.splice(0))t.deactivate();for(let t of Gn.splice(0))t.revert()}function Yn(t){return bo(t,"art::jni::JniIdManager::DecodeMethodId")}function so(t){return bo(t,"art::jni::JniIdManager::DecodeFieldId")}function bo(t,e){let n=J(),r=fo(n).offset,o=r.jniIdManager,s=r.jniIdsIndirection;if(o!==null&&s!==null){let i=n.artRuntime;if(i.add(s).readInt()!==za){let a=i.add(o).readPointer();return n[e](a,t)}}return t}var mc={ia32:gc,x64:bc,arm:yc,arm64:Ec};function gc(t,e,n,r,o){let s=We(o).offset,i=_e(o).offset,l;return Memory.patchCode(t,128,a=>{let c=new X86Writer(a,{pc:t}),d=new X86Relocator(e,c),p=[15,174,4,36],f=[15,174,12,36];c.putPushax(),c.putMovRegReg("ebp","esp"),c.putAndRegU32("esp",4294967280),c.putSubRegImm("esp",512),c.putBytes(p),c.putMovRegFsU32Ptr("ebx",s.self),c.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["eax","ebx"]),c.putTestRegReg("eax","eax"),c.putJccShortLabel("je","restore_registers","no-hint"),c.putMovRegOffsetPtrReg("ebp",7*4,"eax"),c.putLabel("restore_registers"),c.putBytes(f),c.putMovRegReg("esp","ebp"),c.putPopax(),c.putJccShortLabel("jne","invoke_replacement","no-hint");do l=d.readOne();while(l{let c=new X86Writer(a,{pc:t}),d=new X86Relocator(e,c),p=[15,174,4,36],f=[15,174,12,36];c.putPushax(),c.putMovRegReg("rbp","rsp"),c.putAndRegU32("rsp",4294967280),c.putSubRegImm("rsp",512),c.putBytes(p),c.putMovRegGsU32Ptr("rbx",s.self),c.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["rdi","rbx"]),c.putTestRegReg("rax","rax"),c.putJccShortLabel("je","restore_registers","no-hint"),c.putMovRegOffsetPtrReg("rbp",8*8,"rax"),c.putLabel("restore_registers"),c.putBytes(f),c.putMovRegReg("rsp","rbp"),c.putPopax(),c.putJccShortLabel("jne","invoke_replacement","no-hint");do l=d.readOne();while(l{let c=new ThumbWriter(a,{pc:t}),d=new ThumbRelocator(i,c),p=[45,237,16,10],f=[189,236,16,10];c.putPushRegs(["r1","r2","r3","r5","r6","r7","r8","r10","r11","lr"]),c.putBytes(p),c.putSubRegRegImm("sp","sp",8),c.putStrRegRegOffset("r0","sp",0),c.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["r0","r9"]),c.putCmpRegImm("r0",0),c.putBCondLabel("eq","restore_registers"),c.putStrRegRegOffset("r0","sp",0),c.putLabel("restore_registers"),c.putLdrRegRegOffset("r0","sp",0),c.putAddRegRegImm("sp","sp",8),c.putBytes(f),c.putPopRegs(["lr","r11","r10","r8","r7","r6","r5","r3","r2","r1"]),c.putBCondLabel("ne","invoke_replacement");do l=d.readOne();while(l{let a=new Arm64Writer(l,{pc:t}),c=new Arm64Relocator(e,a);a.putPushRegReg("d0","d1"),a.putPushRegReg("d2","d3"),a.putPushRegReg("d4","d5"),a.putPushRegReg("d6","d7"),a.putPushRegReg("x1","x2"),a.putPushRegReg("x3","x4"),a.putPushRegReg("x5","x6"),a.putPushRegReg("x7","x20"),a.putPushRegReg("x21","x22"),a.putPushRegReg("x23","x24"),a.putPushRegReg("x25","x26"),a.putPushRegReg("x27","x28"),a.putPushRegReg("x29","lr"),a.putSubRegRegImm("sp","sp",16),a.putStrRegRegOffset("x0","sp",0),a.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["x0","x19"]),a.putCmpRegReg("x0","xzr"),a.putBCondLabel("eq","restore_registers"),a.putStrRegRegOffset("x0","sp",0),a.putLabel("restore_registers"),a.putLdrRegRegOffset("x0","sp",0),a.putAddRegRegImm("sp","sp",16),a.putPopRegReg("x29","lr"),a.putPopRegReg("x27","x28"),a.putPopRegReg("x25","x26"),a.putPopRegReg("x23","x24"),a.putPopRegReg("x21","x22"),a.putPopRegReg("x7","x20"),a.putPopRegReg("x5","x6"),a.putPopRegReg("x3","x4"),a.putPopRegReg("x1","x2"),a.putPopRegReg("d6","d7"),a.putPopRegReg("d4","d5"),a.putPopRegReg("d2","d3"),a.putPopRegReg("d0","d1"),a.putBCondLabel("ne","invoke_replacement");do i=c.readOne();while(i{let o=new X86Writer(r,{pc:t});o.putJmpAddress(e),o.flush()})}function Sc(t,e,n){let r=t.and(Vn);Memory.patchCode(r,16,o=>{let s=new ThumbWriter(o,{pc:r});s.putLdrRegAddress("pc",e.or(1)),s.flush()})}function wc(t,e,n){Memory.patchCode(t,16,r=>{let o=new Arm64Writer(r,{pc:t});n===16?o.putLdrRegAddress("x16",e):o.putAdrpRegAddress("x16",e),o.putBrReg("x16"),o.flush()})}var Ic={ia32:5,x64:16,arm:8,arm64:16},Ot=class{constructor(e){this.quickCode=e,this.quickCodeAddress=Process.arch==="arm"?e.and(Vn):e,this.redirectSize=0,this.trampoline=null,this.overwrittenPrologue=null,this.overwrittenPrologueLength=0}_canRelocateCode(e,n){let r=Pn[Process.arch],o=Xl[Process.arch],{quickCodeAddress:s}=this,i=new r(s),l=new o(s,i),a;if(Process.arch==="arm64"){let c=new Set(["x16","x17"]);do{let d=l.readOne(),p=new Set(c),{read:f,written:u}=l.input.regsAccessed;for(let _ of[f,u])for(let h of _){let g;h.startsWith("w")?g="x"+h.substring(1):g=h,p.delete(g)}if(p.size===0)break;a=d,c=p}while(a=e}_allocateTrampoline(){At===null&&(At=on(v===4?128:256));let e=Ic[Process.arch],n,r,o=1,s={};if(v===4||this._canRelocateCode(e,s))n=e,r={};else{let i;Process.arch==="x64"?(n=5,i=Va):Process.arch==="arm64"&&(n=8,i=Ja,o=4096),r={near:this.quickCodeAddress,maxDistance:i}}return this.redirectSize=n,this.trampoline=At.allocateSlice(r,o),s}_destroyTrampoline(){At.freeSlice(this.trampoline)}activate(e){let n=this._allocateTrampoline(),{trampoline:r,quickCode:o,redirectSize:s}=this,i=mc[Process.arch],l=i(r,o,s,n,e);this.overwrittenPrologueLength=l,this.overwrittenPrologue=Memory.dup(this.quickCodeAddress,l);let a=vc[Process.arch];a(o,r,s)}deactivate(){let{quickCodeAddress:e,overwrittenPrologueLength:n}=this,r=Pn[Process.arch];Memory.patchCode(e,n,o=>{let s=new r(o,{pc:e}),{overwrittenPrologue:i}=this;s.putBytes(i.readByteArray(n)),s.flush()}),this._destroyTrampoline()}};function Cc(t){let e=J(),{module:n,artClassLinker:r}=e;return t.equals(r.quickGenericJniTrampoline)||t.equals(r.quickToInterpreterBridgeTrampoline)||t.equals(r.quickResolutionTrampoline)||t.equals(r.quickImtConflictTrampoline)||t.compare(n.base)>=0&&t.compare(n.base.add(n.size))<0}var Dn=class{constructor(e){let n=Yn(e);this.methodId=n,this.originalMethod=null,this.hookedMethodId=n,this.replacementMethodId=null,this.interceptor=null}replace(e,n,r,o,s){let{kAccCompileDontBother:i,artNterpEntryPoint:l}=s;this.originalMethod=ao(this.methodId,o);let a=this.originalMethod.accessFlags;if((a&Ba)!==0&&Tc()){let u=this.originalMethod.jniCode;this.hookedMethodId=u.add(2*v).readPointer(),this.originalMethod=ao(this.hookedMethodId,o)}let{hookedMethodId:c}=this,d=Lc(c,o);this.replacementMethodId=d,Lt(d,{jniCode:e,accessFlags:(a&~(Ra|Oa|qr)|Nt|i)>>>0,quickCode:s.artClassLinker.quickGenericJniTrampoline,interpreterCode:s.artInterpreterToCompiledCodeBridge},o);let p=uo|Fa|qr;(a&Nt)===0&&(p|=Pa),Lt(c,{accessFlags:(a&~p|i)>>>0},o);let f=this.originalMethod.quickCode;if(l!==null&&f.equals(l)&&Lt(c,{quickCode:s.artQuickToInterpreterBridge},o),!Cc(f)){let u=new Ot(f);u.activate(o),this.interceptor=u}oe.replacedMethods.set(c,d),ec(c,o)}revert(e){let{hookedMethodId:n,interceptor:r}=this;Lt(n,this.originalMethod,e),oe.replacedMethods.delete(n),r!==null&&(r.deactivate(),this.interceptor=null)}resolveTarget(e,n,r,o){return this.hookedMethodId}};function Tc(){return ee()<28}function ao(t,e){let r=_e(e).offset;return["jniCode","accessFlags","quickCode","interpreterCode"].reduce((o,s)=>{let i=r[s];if(i===void 0)return o;let l=t.add(i),a=s==="accessFlags"?Aa:La;return o[s]=a.call(l),o},{})}function Lt(t,e,n){let o=_e(n).offset;Object.keys(e).forEach(s=>{let i=o[s];if(i===void 0)return;let l=t.add(i);(s==="accessFlags"?xa:Na).call(l,e[s])})}var Un=class{constructor(e){this.methodId=e,this.originalMethod=null}replace(e,n,r,o,s){let{methodId:i}=this;this.originalMethod=Memory.dup(i,Sn);let l=r.reduce((f,u)=>f+u.size,0);n&&l++;let a=(i.add(Wr).readU32()|Nt)>>>0,c=l,d=0,p=l;i.add(Wr).writeU32(a),i.add(Wa).writeU16(c),i.add(Ka).writeU16(d),i.add(Qa).writeU16(p),i.add(Xa).writeU32(Ac(i)),s.dvmUseJNIBridge(i,e)}revert(e){Memory.copy(this.methodId,this.originalMethod,Sn)}resolveTarget(e,n,r,o){let s=r.handle.add(po).readPointer(),i;if(n)i=o.dvmDecodeIndirectRef(s,e.$h);else{let f=e.$borrowClassHandle(r);i=o.dvmDecodeIndirectRef(s,f.value),f.unref(r)}let l;n?l=i.add(Za).readPointer():l=i;let a=l.toString(16),c=kt.get(a);if(c===void 0){let f=l.add(Ha),u=l.add($a),_=f.readPointer(),h=u.readS32(),g=h*v,b=Memory.alloc(2*g);Memory.copy(b,_,g),f.writePointer(b),c={classObject:l,vtablePtr:f,vtableCountPtr:u,vtable:_,vtableCount:h,shadowVtable:b,shadowVtableCount:h,targetMethods:new Map},kt.set(a,c)}let d=this.methodId.toString(16),p=c.targetMethods.get(d);if(p===void 0){p=Memory.dup(this.originalMethod,Sn);let f=c.shadowVtableCount++;c.shadowVtable.add(f*v).writePointer(p),p.add(qa).writeU16(f),c.vtableCountPtr.writeS32(c.shadowVtableCount),c.targetMethods.set(d,p)}return p}};function Ac(t){if(Process.arch!=="ia32")return Kr;let e=t.add(Ya).readPointer().readCString();if(e===null||e.length===0||e.length>65535)return Kr;let n;switch(e[0]){case"V":n=el;break;case"F":n=tl;break;case"D":n=nl;break;case"J":n=rl;break;case"Z":case"B":n=al;break;case"C":n=il;break;case"S":n=sl;break;default:n=ol;break}let r=0;for(let o=e.length-1;o>0;o--){let s=e[o];r+=s==="D"||s==="J"?2:1}return n<= 8.0");ye(t,e,r=>{n["art::Runtime::DeoptimizeBootImage"](n.artRuntime)})}function yo(t,e,n,r){let o=J();if(ee()<24)throw new Error("This API is only available on Android >= 7.0");ye(t,e,s=>{if(ee()<30){if(!o.isJdwpStarted()){let l=xc(o);gl.push(l)}o.isDebuggerActive()||o["art::Dbg::GoActive"]();let i=Memory.alloc(8+v);switch(i.writeU32(n),n){case kn:break;case Mn:i.add(8).writePointer(r);break;default:throw new Error("Unsupported deoptimization kind")}o["art::Dbg::RequestDeoptimization"](i),o["art::Dbg::ManageDeoptimization"]()}else{let i=o.artInstrumentation;if(i===null)throw new Error("Unable to find Instrumentation class in ART; please file a bug");let l=o["art::Instrumentation::EnableDeoptimization"];switch(l!==void 0&&(i.add(pl().offset.deoptimizationEnabled).readU8()||l(i)),n){case kn:o["art::Instrumentation::DeoptimizeEverything"](i,Memory.allocUtf8String("frida"));break;case Mn:o["art::Instrumentation::Deoptimize"](i,r);break;default:throw new Error("Unsupported deoptimization kind")}}})}var Bn=class{constructor(){let e=Process.getModuleByName("libart.so"),n=e.getExportByName("_ZN3art4JDWP12JdwpAdbState6AcceptEv"),r=e.getExportByName("_ZN3art4JDWP12JdwpAdbState15ReceiveClientFdEv"),o=lo(),s=lo();this._controlFd=o[0],this._clientFd=s[0];let i=null;i=Interceptor.attach(n,function(l){let a=l[0];Memory.scanSync(a.add(8252),256,"00 ff ff ff ff 00")[0].address.add(1).writeS32(o[1]),i.detach()}),Interceptor.replace(r,new NativeCallback(function(l){return Interceptor.revert(r),s[1]},"int",["pointer"])),Interceptor.flush(),this._handshakeRequest=this._performHandshake()}async _performHandshake(){let e=new UnixInputStream(this._clientFd,{autoClose:!1}),n=new UnixOutputStream(this._clientFd,{autoClose:!1}),r=[74,68,87,80,45,72,97,110,100,115,104,97,107,101];try{await n.writeAll(r),await e.readAll(r.length)}catch{}}};function xc(t){let e=new Bn;t["art::Dbg::SetJdwpAllowed"](1);let n=Nc();t["art::Dbg::ConfigureJdwp"](n);let r=t["art::InternalDebuggerControlCallback::StartDebugger"];return r!==void 0?r(NULL):t["art::Dbg::StartJdwp"](),e}function Nc(){let t=ee()<28?2:3,e=0,n=t,r=!0,o=!1,s=e,i=8+dt+2,l=Memory.alloc(i);return l.writeU32(n).add(4).writeU8(r?1:0).add(1).writeU8(o?1:0).add(1).add(dt).writeU16(s),l}function lo(){Tn===null&&(Tn=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("socketpair"),"int",["int","int","int","pointer"]));let t=Memory.alloc(8);if(Tn(dl,ul,0,t)===-1)throw new Error("Unable to create socketpair for JDWP");return[t.readS32(),t.add(4).readS32()]}function kc(t){let e=vl().offset,n=t.vm.add(e.globalsLock),r=t.vm.add(e.globals),o=t["art::IndirectReferenceTable::Add"],s=t["art::ReaderWriterMutex::ExclusiveLock"],i=t["art::ReaderWriterMutex::ExclusiveUnlock"],l=0;return function(a,c,d){s(n,c);try{return o(r,l,d)}finally{i(n,c)}}}function Mc(t){let e=t["art::Thread::DecodeJObject"];if(e===void 0)throw new Error("art::Thread::DecodeJObject is not available; please file a bug");return function(n,r,o){return e(r,o)}}var jc={ia32:co,x64:co,arm:Oc,arm64:Rc};function Eo(t,e,n){let r=J(),o=e.handle.readPointer(),s,i=r.find("_ZN3art3JNIILb1EE14ExceptionClearEP7_JNIEnv");i!==null?s=i:s=o.add(Ft).readPointer();let l,a=r.find("_ZN3art3JNIILb1EE10FatalErrorEP7_JNIEnvPKc");a!==null?l=a:l=o.add(Ga).readPointer();let c=jc[Process.arch];if(c===void 0)throw new Error("Not yet implemented for "+Process.arch);let d=null,p=We(t).offset,f=p.exception,u=new Set,_=p.isExceptionReportedToInstrumentation;_!==null&&u.add(_);let h=p.throwLocation;h!==null&&(u.add(h),u.add(h+v),u.add(h+2*v));let g=65536,b=Memory.alloc(g);return Memory.patchCode(b,g,E=>{d=c(E,b,s,l,f,u,n)}),d._code=b,d._callback=n,d}function co(t,e,n,r,o,s,i){let l={},a=new Set,c=[n];for(;c.length>0;){let h=c.shift();if(Object.values(l).some(({begin:M,end:O})=>h.compare(M)>=0&&h.compare(O)<0))continue;let b=h.toString(),E={begin:h},C=null,A=!1;do{if(h.equals(r)){A=!0;break}let M=Instruction.parse(h);C=M;let O=l[M.address.toString()];if(O!==void 0){delete l[O.begin.toString()],l[b]=O,O.begin=E.begin,E=null;break}let k=null;switch(M.mnemonic){case"jmp":k=ptr(M.operands[0].value),A=!0;break;case"je":case"jg":case"jle":case"jne":case"js":k=ptr(M.operands[0].value);break;case"ret":A=!0;break}k!==null&&(a.add(k.toString()),c.push(k),c.sort((N,S)=>N.compare(S))),h=M.next}while(!A);E!==null&&(E.end=C.address.add(C.size),l[b]=E)}let d=Object.keys(l).map(h=>l[h]);d.sort((h,g)=>h.begin.compare(g.begin));let p=l[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new X86Writer(t,{pc:e}),u=!1,_=null;return d.forEach(h=>{let g=h.end.sub(h.begin).toInt32(),b=new X86Relocator(h.begin,f),E;for(;(E=b.readOne())!==0;){let C=b.input,{mnemonic:A}=C,M=C.address.toString();a.has(M)&&f.putLabel(M);let O=!0;switch(A){case"jmp":f.putJmpNearLabel(fe(C.operands[0])),O=!1;break;case"je":case"jg":case"jle":case"jne":case"js":f.putJccNearLabel(A,fe(C.operands[0]),"no-hint"),O=!1;break;case"mov":{let[k,N]=C.operands;if(k.type==="mem"&&N.type==="imm"){let S=k.value,L=S.disp;if(L===o&&N.value.valueOf()===0){if(_=S.base,f.putPushfx(),f.putPushax(),f.putMovRegReg("xbp","xsp"),v===4)f.putAndRegU32("esp",4294967280);else{let j=_!=="rdi"?"rdi":"rsi";f.putMovRegU64(j,uint64("0xfffffffffffffff0")),f.putAndRegReg("rsp",j)}f.putCallAddressWithAlignedArguments(i,[_]),f.putMovRegReg("xsp","xbp"),f.putPopax(),f.putPopfx(),u=!0,O=!1}else s.has(L)&&S.base===_&&(O=!1)}break}case"call":{let k=C.operands[0];k.type==="mem"&&k.value.disp===Ft&&(v===4?(f.putPopReg("eax"),f.putMovRegRegOffsetPtr("eax","eax",4),f.putPushReg("eax")):f.putMovRegRegOffsetPtr("rdi","rdi",8),f.putCallAddressWithArguments(i,[]),u=!0,O=!1);break}}if(O?b.writeAll():b.skipOne(),E===g)break}b.dispose()}),f.dispose(),u||nr(),new NativeFunction(e,"void",["pointer"],W)}function Oc(t,e,n,r,o,s,i){let l={},a=new Set,c=ptr(1).not(),d=[n];for(;d.length>0;){let b=d.shift();if(Object.values(l).some(({begin:L,end:j})=>b.compare(L)>=0&&b.compare(j)<0))continue;let C=b.and(c),A=C.toString(),M=b.and(1),O={begin:C},k=null,N=!1,S=0;do{if(b.equals(r)){N=!0;break}let L=Instruction.parse(b),{mnemonic:j}=L;k=L;let R=b.and(c).toString(),D=l[R];if(D!==void 0){delete l[D.begin.toString()],l[A]=D,D.begin=O.begin,O=null;break}let U=S===0,F=null;switch(j){case"b":F=ptr(L.operands[0].value),N=U;break;case"beq.w":case"beq":case"bne":case"bne.w":case"bgt":F=ptr(L.operands[0].value);break;case"cbz":case"cbnz":F=ptr(L.operands[1].value);break;case"pop.w":U&&(N=L.operands.filter(z=>z.value==="pc").length===1);break}switch(j){case"it":S=1;break;case"itt":S=2;break;case"ittt":S=3;break;case"itttt":S=4;break;default:S>0&&S--;break}F!==null&&(a.add(F.toString()),d.push(F.or(M)),d.sort((z,X)=>z.compare(X))),b=L.next}while(!N);O!==null&&(O.end=k.address.add(k.size),l[A]=O)}let p=Object.keys(l).map(b=>l[b]);p.sort((b,E)=>b.begin.compare(E.begin));let f=l[n.and(c).toString()];p.splice(p.indexOf(f),1),p.unshift(f);let u=new ThumbWriter(t,{pc:e}),_=!1,h=null,g=null;return p.forEach(b=>{let E=new ThumbRelocator(b.begin,u),C=b.begin,A=b.end,M=0;do{if(E.readOne()===0)throw new Error("Unexpected end of block");let k=E.input;C=k.address,M=k.size;let{mnemonic:N}=k,S=C.toString();a.has(S)&&u.putLabel(S);let L=!0;switch(N){case"b":u.putBLabel(fe(k.operands[0])),L=!1;break;case"beq.w":u.putBCondLabelWide("eq",fe(k.operands[0])),L=!1;break;case"bne.w":u.putBCondLabelWide("ne",fe(k.operands[0])),L=!1;break;case"beq":case"bne":case"bgt":u.putBCondLabelWide(N.substr(1),fe(k.operands[0])),L=!1;break;case"cbz":{let j=k.operands;u.putCbzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"cbnz":{let j=k.operands;u.putCbnzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"str":case"str.w":{let j=k.operands[1].value,w=j.disp;if(w===o){h=j.base;let R=h!=="r4"?"r4":"r5",D=["r0","r1","r2","r3",R,"r9","r12","lr"];u.putPushRegs(D),u.putMrsRegReg(R,"apsr-nzcvq"),u.putCallAddressWithArguments(i,[h]),u.putMsrRegReg("apsr-nzcvq",R),u.putPopRegs(D),_=!0,L=!1}else s.has(w)&&j.base===h&&(L=!1);break}case"ldr":{let[j,w]=k.operands;if(w.type==="mem"){let R=w.value;R.base[0]==="r"&&R.disp===Ft&&(g=j.value)}break}case"blx":k.operands[0].value===g&&(u.putLdrRegRegOffset("r0","r0",4),u.putCallAddressWithArguments(i,["r0"]),_=!0,g=null,L=!1);break}L?E.writeAll():E.skipOne()}while(!C.add(M).equals(A));E.dispose()}),u.dispose(),_||nr(),new NativeFunction(e.or(1),"void",["pointer"],W)}function Rc(t,e,n,r,o,s,i){let l={},a=new Set,c=[n];for(;c.length>0;){let b=c.shift();if(Object.values(l).some(({begin:k,end:N})=>b.compare(k)>=0&&b.compare(N)<0))continue;let C=b.toString(),A={begin:b},M=null,O=!1;do{if(b.equals(r)){O=!0;break}let k;try{k=Instruction.parse(b)}catch(L){if(b.readU32()===0){O=!0;break}else throw L}M=k;let N=l[k.address.toString()];if(N!==void 0){delete l[N.begin.toString()],l[C]=N,N.begin=A.begin,A=null;break}let S=null;switch(k.mnemonic){case"b":S=ptr(k.operands[0].value),O=!0;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":S=ptr(k.operands[0].value);break;case"cbz":case"cbnz":S=ptr(k.operands[1].value);break;case"tbz":case"tbnz":S=ptr(k.operands[2].value);break;case"ret":O=!0;break}S!==null&&(a.add(S.toString()),c.push(S),c.sort((L,j)=>L.compare(j))),b=k.next}while(!O);A!==null&&(A.end=M.address.add(M.size),l[C]=A)}let d=Object.keys(l).map(b=>l[b]);d.sort((b,E)=>b.begin.compare(E.begin));let p=l[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new Arm64Writer(t,{pc:e});f.putBLabel("performTransition");let u=e.add(f.offset);f.putPushAllXRegisters(),f.putCallAddressWithArguments(i,["x0"]),f.putPopAllXRegisters(),f.putRet(),f.putLabel("performTransition");let _=!1,h=null,g=null;return d.forEach(b=>{let E=b.end.sub(b.begin).toInt32(),C=new Arm64Relocator(b.begin,f),A;for(;(A=C.readOne())!==0;){let M=C.input,{mnemonic:O}=M,k=M.address.toString();a.has(k)&&f.putLabel(k);let N=!0;switch(O){case"b":f.putBLabel(fe(M.operands[0])),N=!1;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":f.putBCondLabel(O.substr(2),fe(M.operands[0])),N=!1;break;case"cbz":{let S=M.operands;f.putCbzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"cbnz":{let S=M.operands;f.putCbnzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"tbz":{let S=M.operands;f.putTbzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"tbnz":{let S=M.operands;f.putTbnzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"str":{let S=M.operands,L=S[0].value,j=S[1].value,w=j.disp;L==="xzr"&&w===o?(h=j.base,f.putPushRegReg("x0","lr"),f.putMovRegReg("x0",h),f.putBlImm(u),f.putPopRegReg("x0","lr"),_=!0,N=!1):s.has(w)&&j.base===h&&(N=!1);break}case"ldr":{let S=M.operands,L=S[1].value;L.base[0]==="x"&&L.disp===Ft&&(g=S[0].value);break}case"blr":M.operands[0].value===g&&(f.putLdrRegRegOffset("x0","x0",8),f.putCallAddressWithArguments(i,["x0"]),_=!0,g=null,N=!1);break}if(N?C.writeAll():C.skipOne(),A===E)break}C.dispose()}),f.dispose(),_||nr(),new NativeFunction(e,"void",["pointer"],W)}function nr(){throw new Error("Unable to parse ART internals; please file a bug")}function Pc(t){let e=t["art::ArtMethod::PrettyMethod"];e!==void 0&&(Interceptor.attach(e.impl,oe.hooks.ArtMethod.prettyMethod),Interceptor.flush())}function fe(t){return ptr(t.value).toString()}function Fc(t,e){return new NativeFunction(t,"pointer",e,W)}function Dc(t,e){let n=new NativeFunction(t,"void",["pointer"].concat(e),W);return function(){let r=Memory.alloc(v);return n(r,...arguments),r.readPointer()}}function xt(t,e){let{arch:n}=Process;switch(n){case"ia32":case"arm64":{let r;n==="ia32"?r=qe(64,i=>{let l=1+e.length,a=l*4;i.putSubRegImm("esp",a);for(let c=0;c!==l;c++){let d=c*4;i.putMovRegRegOffsetPtr("eax","esp",a+4+d),i.putMovRegOffsetPtrReg("esp",d,"eax")}i.putCallAddress(t),i.putAddRegImm("esp",a-4),i.putRet()}):r=qe(32,i=>{i.putMovRegReg("x8","x0"),e.forEach((l,a)=>{i.putMovRegReg("x"+a,"x"+(a+1))}),i.putLdrRegAddress("x7",t),i.putBrReg("x7")});let o=new NativeFunction(r,"void",["pointer"].concat(e),W),s=function(...i){o(...i)};return s.handle=r,s.impl=t,s}default:{let r=new NativeFunction(t,"void",["pointer"].concat(e),W);return r.impl=t,r}}}var Rt=class{constructor(){this.handle=Memory.alloc(dt)}dispose(){let[e,n]=this._getData();n||J().$delete(e)}disposeToString(){let e=this.toString();return this.dispose(),e}toString(){let[e]=this._getData();return e.readUtf8String()}_getData(){let e=this.handle,n=(e.readU8()&1)===0;return[n?e.add(1):e.add(2*v).readPointer(),n]}},zn=class{$delete(){this.dispose(),J().$delete(this)}constructor(e,n){this.handle=e,this._begin=e,this._end=e.add(v),this._storage=e.add(2*v),this._elementSize=n}init(){this.begin=NULL,this.end=NULL,this.storage=NULL}dispose(){J().$delete(this.begin)}get begin(){return this._begin.readPointer()}set begin(e){this._begin.writePointer(e)}get end(){return this._end.readPointer()}set end(e){this._end.writePointer(e)}get storage(){return this._storage.readPointer()}set storage(e){this._storage.writePointer(e)}get size(){return this.end.sub(this.begin).toInt32()/this._elementSize}},ut=class t extends zn{static $new(){let e=new t(J().$new(cl));return e.init(),e}constructor(e){super(e,v)}get handles(){let e=[],n=this.begin,r=this.end;for(;!n.equals(r);)e.push(n.readPointer()),n=n.add(v);return e}},Uc=0,vo=v,So=vo+4,Bc=-1,Pt=class t{$delete(){this.dispose(),J().$delete(this)}constructor(e){this.handle=e,this._link=e.add(Uc),this._numberOfReferences=e.add(vo)}init(e,n){this.link=e,this.numberOfReferences=n}dispose(){}get link(){return new t(this._link.readPointer())}set link(e){this._link.writePointer(e)}get numberOfReferences(){return this._numberOfReferences.readS32()}set numberOfReferences(e){this._numberOfReferences.writeS32(e)}},wo=Gc(So),Io=wo+v,zc=Io+v,pt=class t extends Pt{static $new(e,n){let r=new t(J().$new(zc));return r.init(e,n),r}constructor(e){super(e),this._self=e.add(wo),this._currentScope=e.add(Io);let o=(64-v-4-4)/4;this._scopeLayout=ct.layoutForCapacity(o),this._topHandleScopePtr=null}init(e,n){let r=e.add(We(n).offset.topHandleScope);this._topHandleScopePtr=r,super.init(r.readPointer(),Bc),this.self=e,this.currentScope=ct.$new(this._scopeLayout),r.writePointer(this)}dispose(){this._topHandleScopePtr.writePointer(this.link);let e;for(;(e=this.currentScope)!==null;){let n=e.link;e.$delete(),this.currentScope=n}}get self(){return this._self.readPointer()}set self(e){this._self.writePointer(e)}get currentScope(){let e=this._currentScope.readPointer();return e.isNull()?null:new ct(e,this._scopeLayout)}set currentScope(e){this._currentScope.writePointer(e)}newHandle(e){return this.currentScope.newHandle(e)}},ct=class t extends Pt{static $new(e){let n=new t(J().$new(e.size),e);return n.init(),n}constructor(e,n){super(e);let{offset:r}=n;this._refsStorage=e.add(r.refsStorage),this._pos=e.add(r.pos),this._layout=n}init(){super.init(NULL,this._layout.numberOfReferences),this.pos=0}get pos(){return this._pos.readU32()}set pos(e){this._pos.writeU32(e)}newHandle(e){let n=this.pos,r=this._refsStorage.add(n*4);return r.writeS32(e.toInt32()),this.pos=n+1,r}static layoutForCapacity(e){let n=So,r=n+e*4;return{size:r+4,numberOfReferences:e,offset:{refsStorage:n,pos:r}}}},Vc={arm:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let s=[26625,18947,17041,53505,19202,18200,18288,48896],i=s.length*2,l=i+4,a=l+4;return Memory.patchCode(r,a,function(c){s.forEach((d,p)=>{c.add(p*2).writeU16(d)}),c.add(i).writeS32(t),c.add(l).writePointer(o)}),r.or(1)},arm64:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let s=[3107979265,402653378,1795293247,1409286241,1476395139,3592355936,3596551104],i=s.length*4,l=i+4,a=l+8;return Memory.patchCode(r,a,function(c){s.forEach((d,p)=>{c.add(p*4).writeU32(d)}),c.add(i).writeS32(t),c.add(l).writePointer(o)}),r}};function rr(t,e){return(Vc[Process.arch]||Jc)(t,e)}function Jc(t,e){return new NativeCallback(n=>{n.readS32()===t&&e(n)},"void",["pointer","pointer"])}function Gc(t){let e=t%v;return e!==0?t+v-e:t}var $c=4,{pointerSize:V}=Process,Hc=256,Zc=65536,qc=131072,Wc=33554432,Kc=67108864,Qc=134217728,Be={exceptions:"propagate"},Lo=ce(dd),Yc=ce(pd),Xc=ce(ad),or=null,sr=!1,zt=new Map,ht=new Map;function Te(){return or===null&&(or=ed()),or}function ed(){let t=Process.enumerateModules().filter(a=>/jvm.(dll|dylib|so)$/.test(a.name));if(t.length===0)return null;let e=t[0],n={flavor:"jvm"},r=Process.platform==="windows"?[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]],"VMThread::execute":["VMThread::execute","void",["pointer"]],"Method::size":["Method::size","int",["int"]],"Method::set_native_function":["Method::set_native_function","void",["pointer","pointer","int"]],"Method::clear_native_function":["Method::clear_native_function","void",["pointer"]],"Method::jmethod_id":["Method::jmethod_id","pointer",["pointer"]],"ClassLoaderDataGraph::classes_do":["ClassLoaderDataGraph::classes_do","void",["pointer"]],"NMethodSweeper::sweep_code_cache":["NMethodSweeper::sweep_code_cache","void",[]],"OopMapCache::flush_obsolete_entries":["OopMapCache::flush_obsolete_entries","void",["pointer"]]},variables:{"VM_RedefineClasses::`vftable'":function(a){this.vtableRedefineClasses=a},"VM_RedefineClasses::doit":function(a){this.redefineClassesDoIt=a},"VM_RedefineClasses::doit_prologue":function(a){this.redefineClassesDoItPrologue=a},"VM_RedefineClasses::doit_epilogue":function(a){this.redefineClassesDoItEpilogue=a},"VM_RedefineClasses::allow_nested_vm_operations":function(a){this.redefineClassesAllow=a},"NMethodSweeper::_traversals":function(a){this.traversals=a},"NMethodSweeper::_should_sweep":function(a){this.shouldSweep=a}},optionals:[]}]:[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],_ZN6Method4sizeEb:["Method::size","int",["int"]],_ZN6Method19set_native_functionEPhb:["Method::set_native_function","void",["pointer","pointer","int"]],_ZN6Method21clear_native_functionEv:["Method::clear_native_function","void",["pointer"]],_ZN6Method24restore_unshareable_infoEP10JavaThread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method24restore_unshareable_infoEP6Thread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method11link_methodERK12methodHandleP10JavaThread:["Method::link_method","void",["pointer","pointer","pointer"]],_ZN6Method10jmethod_idEv:["Method::jmethod_id","pointer",["pointer"]],_ZN6Method10clear_codeEv:function(a){let c=new NativeFunction(a,"void",["pointer"],Be);this["Method::clear_code"]=function(d){c(d)}},_ZN6Method10clear_codeEb:function(a){let c=new NativeFunction(a,"void",["pointer","int"],Be),d=0;this["Method::clear_code"]=function(p){c(p,d)}},_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass:["VM_RedefineClasses::mark_dependent_code","void",["pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeEv:["VM_RedefineClasses::flush_dependent_code","void",[]],_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN19ResolvedMethodTable21adjust_method_entriesEPb:["ResolvedMethodTable::adjust_method_entries","void",["pointer"]],_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb:["MemberNameTable::adjust_method_entries","void",["pointer","pointer","pointer"]],_ZN17ConstantPoolCache21adjust_method_entriesEPb:function(a){let c=new NativeFunction(a,"void",["pointer","pointer"],Be);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){c(d,f)}},_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb:function(a){let c=new NativeFunction(a,"void",["pointer","pointer","pointer"],Be);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){c(d,p,f)}},_ZN20ClassLoaderDataGraph10classes_doEP12KlassClosure:["ClassLoaderDataGraph::classes_do","void",["pointer"]],_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb:["ClassLoaderDataGraph::clean_deallocate_lists","void",["int"]],_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_:["JavaThread::thread_from_jni_environment","pointer",["pointer"]],_ZN8VMThread7executeEP12VM_Operation:["VMThread::execute","void",["pointer"]],_ZN11OopMapCache22flush_obsolete_entriesEv:["OopMapCache::flush_obsolete_entries","void",["pointer"]],_ZN14NMethodSweeper11force_sweepEv:["NMethodSweeper::force_sweep","void",[]],_ZN14NMethodSweeper16sweep_code_cacheEv:["NMethodSweeper::sweep_code_cache","void",[]],_ZN14NMethodSweeper17sweep_in_progressEv:["NMethodSweeper::sweep_in_progress","bool",[]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]]},variables:{_ZN18VM_RedefineClasses14_the_class_oopE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses10_the_classE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass:function(a){this.doKlass=a},_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass:function(a){this.doKlass=a},_ZTV18VM_RedefineClasses:function(a){this.vtableRedefineClasses=a},_ZN18VM_RedefineClasses4doitEv:function(a){this.redefineClassesDoIt=a},_ZN18VM_RedefineClasses13doit_prologueEv:function(a){this.redefineClassesDoItPrologue=a},_ZN18VM_RedefineClasses13doit_epilogueEv:function(a){this.redefineClassesDoItEpilogue=a},_ZN18VM_RedefineClassesD0Ev:function(a){this.redefineClassesDispose0=a},_ZN18VM_RedefineClassesD1Ev:function(a){this.redefineClassesDispose1=a},_ZNK18VM_RedefineClasses26allow_nested_vm_operationsEv:function(a){this.redefineClassesAllow=a},_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream:function(a){this.redefineClassesOnError=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread:function(a){this.createNewDefaultVtableIndices=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread:function(a){this.createNewDefaultVtableIndices=a},_ZN19Abstract_VM_Version19jre_release_versionEv:function(a){let d=new NativeFunction(a,"pointer",[],Be)().readCString();this.version=d.startsWith("1.8")?8:d.startsWith("9.")?9:parseInt(d.slice(0,2),10),this.versionS=d},_ZN14NMethodSweeper11_traversalsE:function(a){this.traversals=a},_ZN14NMethodSweeper21_sweep_fractions_leftE:function(a){this.fractions=a},_ZN14NMethodSweeper13_should_sweepE:function(a){this.shouldSweep=a}},optionals:["_ZN6Method24restore_unshareable_infoEP10JavaThread","_ZN6Method24restore_unshareable_infoEP6Thread","_ZN6Method11link_methodERK12methodHandleP10JavaThread","_ZN6Method10clear_codeEv","_ZN6Method10clear_codeEb","_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass","_ZN18VM_RedefineClasses20flush_dependent_codeEv","_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread","_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread","_ZN19ResolvedMethodTable21adjust_method_entriesEPb","_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb","_ZN17ConstantPoolCache21adjust_method_entriesEPb","_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb","_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb","_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_","_ZN14NMethodSweeper11force_sweepEv","_ZN14NMethodSweeper17sweep_in_progressEv","_ZN18VM_RedefineClasses14_the_class_oopE","_ZN18VM_RedefineClasses10_the_classE","_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass","_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass","_ZN18VM_RedefineClassesD0Ev","_ZN18VM_RedefineClassesD1Ev","_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread","_ZN14NMethodSweeper21_sweep_fractions_leftE"]}],o=[];if(r.forEach(function(a){let c=a.module,d=a.functions||{},p=a.variables||{},f=new Set(a.optionals||[]),u=c.enumerateExports().reduce(function(h,g){return h[g.name]=g,h},{}),_=c.enumerateSymbols().reduce(function(h,g){return h[g.name]=g,h},u);Object.keys(d).forEach(function(h){let g=_[h];if(g!==void 0){let b=d[h];typeof b=="function"?b.call(n,g.address):n[b[0]]=new NativeFunction(g.address,b[1],b[2],Be)}else f.has(h)||o.push(h)}),Object.keys(p).forEach(function(h){let g=_[h];g!==void 0?p[h].call(n,g.address):f.has(h)||o.push(h)})}),o.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+o.join(", "));let s=Memory.alloc(V),i=Memory.alloc($c);if(de("JNI_GetCreatedJavaVMs",n.JNI_GetCreatedJavaVMs(s,1,i)),i.readInt()===0)return null;n.vm=s.readPointer();let l=Process.platform==="windows"?{$new:["??2@YAPEAX_K@Z","pointer",["ulong"]],$delete:["??3@YAXPEAX@Z","void",["pointer"]]}:{$new:["_Znwm","pointer",["ulong"]],$delete:["_ZdlPv","void",["pointer"]]};for(let[a,[c,d,p]]of Object.entries(l)){let f=Module.findGlobalExportByName(c);if(f===null&&(f=DebugSymbol.fromName(c).address,f.isNull()))throw new Error(`unable to find C++ allocator API, missing: '${c}'`);n[a]=new NativeFunction(f,d,p,Be)}return n.jvmti=td(n),n["JavaThread::thread_from_jni_environment"]===void 0&&(n["JavaThread::thread_from_jni_environment"]=rd(n)),n}function td(t){let e=new Ce(t),n;return e.perform(()=>{let r=e.tryGetEnvHandle(St.v1_0);if(r===null)throw new Error("JVMTI not available");n=new Ne(r,e);let o=Memory.alloc(8);o.writeU64(wt.canTagObjects);let s=n.addCapabilities(o);de("getEnvJvmti::AddCapabilities",s)}),n}var nd={x64:od};function rd(t){let e=null,n=nd[Process.arch];if(n!==void 0){let o=new Ce(t).perform(s=>s.handle.readPointer().add(6*V).readPointer());e=ke(o,n,{limit:11})}return e===null?()=>{throw new Error("Unable to make thread_from_jni_environment() helper for the current architecture")}:r=>r.add(e)}function od(t){if(t.mnemonic!=="lea")return null;let{base:e,disp:n}=t.operands[1].value;return e==="rdi"&&n<0?n:null}function xo(t,e){}var ir=class{constructor(e){this.methodId=e,this.method=e.readPointer(),this.originalMethod=null,this.newMethod=null,this.resolved=null,this.impl=null,this.key=e.toString(16)}replace(e,n,r,o,s){let{key:i}=this,l=ht.get(i);l!==void 0&&(ht.delete(i),this.method=l.method,this.originalMethod=l.originalMethod,this.newMethod=l.newMethod,this.resolved=l.resolved),this.impl=e,zt.set(i,this),Co(o)}revert(e){let{key:n}=this;zt.delete(n),ht.set(n,this),Co(e)}resolveTarget(e,n,r,o){let{resolved:s,originalMethod:i,methodId:l}=this;if(s!==null)return s;if(i===null)return l;i.oldMethod.vtableIndexPtr.writeS32(-2);let c=Memory.alloc(V);return c.writePointer(this.method),this.resolved=c,c}};function Co(t){sr||(sr=!0,Script.nextTick(sd,t))}function sd(t){let e=new Map(zt),n=new Map(ht);zt.clear(),ht.clear(),sr=!1,t.perform(r=>{let o=Te(),s=o["JavaThread::thread_from_jni_environment"](r.handle),i=!1;No(()=>{e.forEach(l=>{let{method:a,originalMethod:c,impl:d,methodId:p,newMethod:f}=l;c===null?(l.originalMethod=Mo(a),l.newMethod=ld(a,d,s),To(l.newMethod,p,s)):o["Method::set_native_function"](f.method,d,0)}),n.forEach(l=>{let{originalMethod:a,methodId:c,newMethod:d}=l;if(a!==null){cd(a);let p=a.oldMethod;p.oldMethod=d,To(p,c,s),i=!0}})}),i&&id(r.handle)})}function id(t){let{fractions:e,shouldSweep:n,traversals:r,"NMethodSweeper::sweep_code_cache":o,"NMethodSweeper::sweep_in_progress":s,"NMethodSweeper::force_sweep":i,JVM_Sleep:l}=Te();if(i!==void 0)Thread.sleep(.05),i(),Thread.sleep(.05),i();else{let a=r.readS64(),c=a+2;for(;c>a;)e.writeS32(1),l(t,NULL,50),s()||No(()=>{Thread.sleep(.05)}),n.readU8()===0&&(e.writeS32(1),o()),a=r.readS64()}}function No(t,e,n){let{execute:r,vtable:o,vtableSize:s,doItOffset:i,prologueOffset:l,epilogueOffset:a}=Xc(),c=Memory.dup(o,s),d=Memory.alloc(V*25);d.writePointer(c);let p=new NativeCallback(t,"void",["pointer"]);c.add(i).writePointer(p);let f=null;e!==void 0&&(f=new NativeCallback(e,"int",["pointer"]),c.add(l).writePointer(f));let u=null;n!==void 0&&(u=new NativeCallback(n,"void",["pointer"]),c.add(a).writePointer(u)),r(d)}function ad(){let{vtableRedefineClasses:t,redefineClassesDoIt:e,redefineClassesDoItPrologue:n,redefineClassesDoItEpilogue:r,redefineClassesOnError:o,redefineClassesAllow:s,redefineClassesDispose0:i,redefineClassesDispose1:l,"VMThread::execute":a}=Te(),c=t.add(2*V),d=15*V,p=Memory.dup(c,d),f=new NativeCallback(()=>{},"void",["pointer"]),u,_,h;for(let g=0;g!==d;g+=V){let b=p.add(g),E=b.readPointer();o!==void 0&&E.equals(o)||i!==void 0&&E.equals(i)||l!==void 0&&E.equals(l)?b.writePointer(f):E.equals(e)?u=g:E.equals(n)?(_=g,b.writePointer(s)):E.equals(r)&&(h=g,b.writePointer(f))}return{execute:a,emptyCallback:f,vtable:p,vtableSize:d,doItOffset:u,prologueOffset:_,epilogueOffset:h}}function ko(t){return new ir(t)}function To(t,e,n){let{method:r,oldMethod:o}=t,s=Te();t.methodsArray.add(t.methodIndex*V).writePointer(r),t.vtableIndex>=0&&t.vtable.add(t.vtableIndex*V).writePointer(r),e.writePointer(r),o.accessFlagsPtr.writeU32((o.accessFlags|Zc|qc)>>>0);let i=s["OopMapCache::flush_obsolete_entries"];if(i!==void 0){let{oopMapCache:_}=t;_.isNull()||i(_)}let l=s["VM_RedefineClasses::mark_dependent_code"],a=s["VM_RedefineClasses::flush_dependent_code"];l!==void 0?(l(NULL,t.instanceKlass),a()):a(NULL,t.instanceKlass,n);let c=Memory.alloc(1);c.writeU8(1),s["ConstantPoolCache::adjust_method_entries"](t.cache,t.instanceKlass,c);let d=Memory.alloc(3*V),p=Memory.alloc(V);p.writePointer(s.doKlass),d.writePointer(p),d.add(V).writePointer(n),d.add(2*V).writePointer(n),s.redefineClass!==void 0&&s.redefineClass.writePointer(t.instanceKlass),s["ClassLoaderDataGraph::classes_do"](d);let f=s["ResolvedMethodTable::adjust_method_entries"];if(f!==void 0)f(c);else{let{memberNames:_}=t;if(!_.isNull()){let h=s["MemberNameTable::adjust_method_entries"];h!==void 0&&h(_,t.instanceKlass,c)}}let u=s["ClassLoaderDataGraph::clean_deallocate_lists"];u!==void 0&&u(0)}function ld(t,e,n){let r=Te(),o=Mo(t);o.constPtr.writePointer(o.const);let s=(o.accessFlags|Hc|Wc|Kc|Qc)>>>0;if(o.accessFlagsPtr.writeU32(s),o.signatureHandler.writePointer(NULL),o.adapter.writePointer(NULL),o.i2iEntry.writePointer(NULL),r["Method::clear_code"](o.method),o.dataPtr.writePointer(NULL),o.countersPtr.writePointer(NULL),o.stackmapPtr.writePointer(NULL),r["Method::clear_native_function"](o.method),r["Method::set_native_function"](o.method,e,0),r["Method::restore_unshareable_info"](o.method,n),r.version>=17){let i=Memory.alloc(2*V);i.writePointer(o.method),i.add(V).writePointer(n),r["Method::link_method"](o.method,i,n)}return o}function Mo(t){let e=Lo(),n=t.add(e.method.constMethodOffset).readPointer(),r=n.add(e.constMethod.sizeOffset).readS32()*V,o=Memory.alloc(r+e.method.size);Memory.copy(o,n,r);let s=o.add(r);Memory.copy(s,t,e.method.size);let i=Ao(s,o,r),l=Ao(t,n,r);return i.oldMethod=l,i}function Ao(t,e,n){let r=Te(),o=Lo(),s=t.add(o.method.constMethodOffset),i=t.add(o.method.methodDataOffset),l=t.add(o.method.methodCountersOffset),a=t.add(o.method.accessFlagsOffset),c=a.readU32(),d=o.getAdapterPointer(t,e),p=t.add(o.method.i2iEntryOffset),f=t.add(o.method.signatureHandlerOffset),u=e.add(o.constMethod.constantPoolOffset).readPointer(),_=e.add(o.constMethod.stackmapDataOffset),h=u.add(o.constantPool.instanceKlassOffset).readPointer(),g=u.add(o.constantPool.cacheOffset).readPointer(),b=Yc(),E=h.add(b.methodsOffset).readPointer(),C=E.readS32(),A=E.add(V),M=e.add(o.constMethod.methodIdnumOffset).readU16(),O=t.add(o.method.vtableIndexOffset),k=O.readS32(),N=h.add(b.vtableOffset),S=h.add(b.oopMapCacheOffset).readPointer(),L=r.version>=10?h.add(b.memberNamesOffset).readPointer():NULL;return{method:t,methodSize:o.method.size,const:e,constSize:n,constPtr:s,dataPtr:i,countersPtr:l,stackmapPtr:_,instanceKlass:h,methodsArray:A,methodsCount:C,methodIndex:M,vtableIndex:k,vtableIndexPtr:O,vtable:N,accessFlags:c,accessFlagsPtr:a,adapter:d,i2iEntry:p,signatureHandler:f,memberNames:L,cache:g,oopMapCache:S}}function cd(t){let{oldMethod:e}=t;e.accessFlagsPtr.writeU32(e.accessFlags),e.vtableIndexPtr.writeS32(e.vtableIndex)}function dd(){let t=Te(),{version:e}=t,n;e>=17?n="method:early":e>=9&&e<=16?n="const-method":n="method:late";let o=t["Method::size"](1)*V,s=V,i=2*V,l=3*V,a=4*V,c=n==="method:early"?V:0,d=a+c,p=d+4,f=p+4+8,u=f+V,_=c!==0?a:u,h=o-2*V,g=o-V,b=8,E=b+V,C=E+V,A=n==="const-method"?V:0,M=C+A,O=M+14,k=2*V,N=3*V;return{getAdapterPointer:A!==0?function(L,j){return j.add(C)}:function(L,j){return L.add(_)},method:{size:o,constMethodOffset:s,methodDataOffset:i,methodCountersOffset:l,accessFlagsOffset:d,vtableIndexOffset:p,i2iEntryOffset:f,nativeFunctionOffset:h,signatureHandlerOffset:g},constMethod:{constantPoolOffset:b,stackmapDataOffset:E,sizeOffset:M,methodIdnumOffset:O},constantPool:{cacheOffset:k,instanceKlassOffset:N}}}var ud={x64:fd};function pd(){let{version:t,createNewDefaultVtableIndices:e}=Te(),n=ud[Process.arch];if(n===void 0)throw new Error(`Missing vtable offset parser for ${Process.arch}`);let r=ke(e,n,{limit:32});if(r===null)throw new Error("Unable to deduce vtable offset");let o=t>=10&&t<=11||t>=15?17:18,s=r-7*V,i=r-17*V,l=r-o*V;return{vtableOffset:r,methodsOffset:s,memberNamesOffset:i,oopMapCacheOffset:l}}function fd(t){if(t.mnemonic!=="mov")return null;let e=t.operands[0];if(e.type!=="mem")return null;let{value:n}=e;if(n.scale!==1)return null;let{disp:r}=n;return r<256?null:r+16}var jo=J;try{ft()}catch{jo=Te}var _t=jo;var hd=`#include +#include + +#define kAccStatic 0x0008 +#define kAccConstructor 0x00010000 + +typedef struct _Model Model; +typedef struct _EnumerateMethodsContext EnumerateMethodsContext; + +typedef struct _JavaApi JavaApi; +typedef struct _JavaClassApi JavaClassApi; +typedef struct _JavaMethodApi JavaMethodApi; +typedef struct _JavaFieldApi JavaFieldApi; + +typedef struct _JNIEnv JNIEnv; +typedef guint8 jboolean; +typedef gint32 jint; +typedef jint jsize; +typedef gpointer jobject; +typedef jobject jclass; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jobjectArray; +typedef gpointer jfieldID; +typedef gpointer jmethodID; + +typedef struct _jvmtiEnv jvmtiEnv; +typedef enum +{ + JVMTI_ERROR_NONE = 0 +} jvmtiError; + +typedef struct _ArtApi ArtApi; +typedef guint32 ArtHeapReference; +typedef struct _ArtObject ArtObject; +typedef struct _ArtClass ArtClass; +typedef struct _ArtClassLinker ArtClassLinker; +typedef struct _ArtClassVisitor ArtClassVisitor; +typedef struct _ArtClassVisitorVTable ArtClassVisitorVTable; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtString ArtString; + +typedef union _StdString StdString; +typedef struct _StdStringShort StdStringShort; +typedef struct _StdStringLong StdStringLong; + +typedef void (* ArtVisitClassesFunc) (ArtClassLinker * linker, ArtClassVisitor * visitor); +typedef const char * (* ArtGetClassDescriptorFunc) (ArtClass * klass, StdString * storage); +typedef void (* ArtPrettyMethodFunc) (StdString * result, ArtMethod * method, jboolean with_signature); + +struct _Model +{ + GHashTable * members; +}; + +struct _EnumerateMethodsContext +{ + GPatternSpec * class_query; + GPatternSpec * method_query; + jboolean include_signature; + jboolean ignore_case; + jboolean skip_system_classes; + GHashTable * groups; +}; + +struct _JavaClassApi +{ + jmethodID get_declared_methods; + jmethodID get_declared_fields; +}; + +struct _JavaMethodApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaFieldApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaApi +{ + jvmtiEnv * jvmti; + JavaClassApi clazz; + JavaMethodApi method; + JavaFieldApi field; +}; + +struct _JNIEnv +{ + gpointer * functions; +}; + +struct _jvmtiEnv +{ + gpointer * functions; +}; + +struct _ArtApi +{ + gboolean available; + + guint class_offset_ifields; + guint class_offset_methods; + guint class_offset_sfields; + guint class_offset_copied_methods_offset; + + guint method_size; + guint method_offset_access_flags; + + guint field_size; + guint field_offset_access_flags; + + guint alignment_padding; + + ArtClassLinker * linker; + ArtVisitClassesFunc visit_classes; + ArtGetClassDescriptorFunc get_class_descriptor; + ArtPrettyMethodFunc pretty_method; + + void (* free) (gpointer mem); +}; + +struct _ArtObject +{ + ArtHeapReference klass; + ArtHeapReference monitor; +}; + +struct _ArtClass +{ + ArtObject parent; + + ArtHeapReference class_loader; +}; + +struct _ArtClassVisitor +{ + ArtClassVisitorVTable * vtable; + gpointer user_data; +}; + +struct _ArtClassVisitorVTable +{ + void (* reserved1) (ArtClassVisitor * self); + void (* reserved2) (ArtClassVisitor * self); + jboolean (* visit) (ArtClassVisitor * self, ArtClass * klass); +}; + +struct _ArtString +{ + ArtObject parent; + + gint32 count; + guint32 hash_code; + + union + { + guint16 value[0]; + guint8 value_compressed[0]; + }; +}; + +struct _StdStringShort +{ + guint8 size; + gchar data[(3 * sizeof (gpointer)) - sizeof (guint8)]; +}; + +struct _StdStringLong +{ + gsize capacity; + gsize size; + gchar * data; +}; + +union _StdString +{ + StdStringShort s; + StdStringLong l; +}; + +static void model_add_method (Model * self, const gchar * name, jmethodID id, jint modifiers); +static void model_add_field (Model * self, const gchar * name, jfieldID id, jint modifiers); +static void model_free (Model * model); + +static jboolean collect_matching_class_methods (ArtClassVisitor * self, ArtClass * klass); +static gchar * finalize_method_groups_to_json (GHashTable * groups); +static GPatternSpec * make_pattern_spec (const gchar * pattern, jboolean ignore_case); +static gchar * class_name_from_signature (const gchar * signature); +static gchar * format_method_signature (const gchar * name, const gchar * signature); +static void append_type (GString * output, const gchar ** type); + +static gpointer read_art_array (gpointer object_base, guint field_offset, guint length_size, guint * length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_c_str (StdString * self); + +extern GMutex lock; +extern GArray * models; +extern JavaApi java_api; +extern ArtApi art_api; + +void +init (void) +{ + g_mutex_init (&lock); + models = g_array_new (FALSE, FALSE, sizeof (Model *)); +} + +void +finalize (void) +{ + guint n, i; + + n = models->len; + for (i = 0; i != n; i++) + { + Model * model = g_array_index (models, Model *, i); + model_free (model); + } + + g_array_unref (models); + g_mutex_clear (&lock); +} + +Model * +model_new (jclass class_handle, + gpointer class_object, + JNIEnv * env) +{ + Model * model; + GHashTable * members; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * funcs = env->functions; + jmethodID (* from_reflected_method) (JNIEnv *, jobject) = funcs[7]; + jfieldID (* from_reflected_field) (JNIEnv *, jobject) = funcs[8]; + jobject (* to_reflected_method) (JNIEnv *, jclass, jmethodID, jboolean) = funcs[9]; + jobject (* to_reflected_field) (JNIEnv *, jclass, jfieldID, jboolean) = funcs[12]; + void (* delete_local_ref) (JNIEnv *, jobject) = funcs[23]; + jobject (* call_object_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[34]; + jint (* call_int_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[49]; + const char * (* get_string_utf_chars) (JNIEnv *, jstring, jboolean *) = funcs[169]; + void (* release_string_utf_chars) (JNIEnv *, jstring, const char *) = funcs[170]; + jsize (* get_array_length) (JNIEnv *, jarray) = funcs[171]; + jobject (* get_object_array_element) (JNIEnv *, jobjectArray, jsize) = funcs[173]; + jsize n, i; + + model = g_new (Model, 1); + + members = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + model->members = members; + + if (jvmti != NULL) + { + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_fields) (jvmtiEnv *, jclass, jint *, jfieldID **) = jf[53]; + jvmtiError (* get_field_name) (jvmtiEnv *, jclass, jfieldID, char **, char **, char **) = jf[60]; + jvmtiError (* get_field_modifiers) (jvmtiEnv *, jclass, jfieldID, jint *) = jf[62]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_method_modifiers) (jvmtiEnv *, jmethodID, jint *) = jf[66]; + jint method_count; + jmethodID * methods; + jint field_count; + jfieldID * fields; + char * name; + jint modifiers; + + get_class_methods (jvmti, class_handle, &method_count, &methods); + for (i = 0; i != method_count; i++) + { + jmethodID method = methods[i]; + + get_method_name (jvmti, method, &name, NULL, NULL); + get_method_modifiers (jvmti, method, &modifiers); + + model_add_method (model, name, method, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, methods); + + get_class_fields (jvmti, class_handle, &field_count, &fields); + for (i = 0; i != field_count; i++) + { + jfieldID field = fields[i]; + + get_field_name (jvmti, class_handle, field, &name, NULL, NULL); + get_field_modifiers (jvmti, class_handle, field, &modifiers); + + model_add_field (model, name, field, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, fields); + } + else if (art_api.available) + { + gpointer elements; + guint n, i; + const guint field_arrays[] = { + art_api.class_offset_ifields, + art_api.class_offset_sfields + }; + guint field_array_cursor; + gboolean merged_fields = art_api.class_offset_sfields == 0; + + elements = read_art_array (class_object, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) (class_object + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + jmethodID id; + guint32 access_flags; + jboolean is_static; + jobject method, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) (id + art_api.method_offset_access_flags); + if ((access_flags & kAccConstructor) != 0) + continue; + is_static = (access_flags & kAccStatic) != 0; + method = to_reflected_method (env, class_handle, id, is_static); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + + for (field_array_cursor = 0; field_array_cursor != G_N_ELEMENTS (field_arrays); field_array_cursor++) + { + jboolean is_static; + + if (field_arrays[field_array_cursor] == 0) + continue; + + if (!merged_fields) + is_static = field_array_cursor == 1; + + elements = read_art_array (class_object, field_arrays[field_array_cursor], sizeof (guint32), &n); + for (i = 0; i != n; i++) + { + jfieldID id; + guint32 access_flags; + jobject field, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.field_size); + + access_flags = *(guint32 *) (id + art_api.field_offset_access_flags); + if (merged_fields) + is_static = (access_flags & kAccStatic) != 0; + field = to_reflected_field (env, class_handle, id, is_static); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + } + } + else + { + jobject elements; + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_methods); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject method, name; + const char * name_str; + jmethodID id; + jint modifiers; + + method = get_object_array_element (env, elements, i); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_method (env, method); + modifiers = call_int_method (env, method, java_api.method.get_modifiers); + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + delete_local_ref (env, elements); + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_fields); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject field, name; + const char * name_str; + jfieldID id; + jint modifiers; + + field = get_object_array_element (env, elements, i); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_field (env, field); + modifiers = call_int_method (env, field, java_api.field.get_modifiers); + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + delete_local_ref (env, elements); + } + + g_mutex_lock (&lock); + g_array_append_val (models, model); + g_mutex_unlock (&lock); + + return model; +} + +static void +model_add_method (Model * self, + const gchar * name, + jmethodID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + const gchar * value; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + value = g_hash_table_lookup (members, key); + if (value == NULL) + g_hash_table_insert (members, key, g_strdup_printf ("m:%c0x%zx", type, id)); + else + g_hash_table_insert (members, key, g_strdup_printf ("%s:%c0x%zx", value, type, id)); +} + +static void +model_add_field (Model * self, + const gchar * name, + jfieldID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + while (g_hash_table_contains (members, key)) + { + gchar * new_key = g_strdup_printf ("_%s", key); + g_free (key); + key = new_key; + } + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + g_hash_table_insert (members, key, g_strdup_printf ("f:%c0x%zx", type, id)); +} + +static void +model_free (Model * model) +{ + g_hash_table_unref (model->members); + + g_free (model); +} + +gboolean +model_has (Model * self, + const gchar * member) +{ + return g_hash_table_contains (self->members, member); +} + +const gchar * +model_find (Model * self, + const gchar * member) +{ + return g_hash_table_lookup (self->members, member); +} + +gchar * +model_list (Model * self) +{ + GString * result; + GHashTableIter iter; + guint i; + const gchar * name; + + result = g_string_sized_new (128); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, self->members); + for (i = 0; g_hash_table_iter_next (&iter, (gpointer *) &name, NULL); i++) + { + if (i > 0) + g_string_append_c (result, ','); + + g_string_append_c (result, '"'); + g_string_append (result, name); + g_string_append_c (result, '"'); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +gchar * +enumerate_methods_art (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes) +{ + gchar * result; + EnumerateMethodsContext ctx; + ArtClassVisitor visitor; + ArtClassVisitorVTable visitor_vtable = { NULL, }; + + ctx.class_query = make_pattern_spec (class_query, ignore_case); + ctx.method_query = make_pattern_spec (method_query, ignore_case); + ctx.include_signature = include_signature; + ctx.ignore_case = ignore_case; + ctx.skip_system_classes = skip_system_classes; + ctx.groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + visitor.vtable = &visitor_vtable; + visitor.user_data = &ctx; + + visitor_vtable.visit = collect_matching_class_methods; + + art_api.visit_classes (art_api.linker, &visitor); + + result = finalize_method_groups_to_json (ctx.groups); + + g_hash_table_unref (ctx.groups); + g_pattern_spec_free (ctx.method_query); + g_pattern_spec_free (ctx.class_query); + + return result; +} + +static jboolean +collect_matching_class_methods (ArtClassVisitor * self, + ArtClass * klass) +{ + EnumerateMethodsContext * ctx = self->user_data; + const char * descriptor; + StdString descriptor_storage = { 0, }; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + JsonBuilder * group; + size_t class_name_length; + GHashTable * seen_method_names; + gpointer elements; + guint n, i; + + if (ctx->skip_system_classes && klass->class_loader == 0) + goto skip_class; + + descriptor = art_api.get_class_descriptor (klass, &descriptor_storage); + if (descriptor[0] != 'L') + goto skip_class; + + class_name = class_name_from_signature (descriptor); + + if (ctx->ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (ctx->class_query, normalized_class_name)) + goto skip_class; + + group = NULL; + class_name_length = strlen (class_name); + seen_method_names = ctx->include_signature ? NULL : g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + elements = read_art_array (klass, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) ((gpointer) klass + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + ArtMethod * method; + guint32 access_flags; + jboolean is_constructor; + StdString method_name = { 0, }; + const gchar * bare_method_name; + gchar * bare_method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + method = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) ((gpointer) method + art_api.method_offset_access_flags); + is_constructor = (access_flags & kAccConstructor) != 0; + + art_api.pretty_method (&method_name, method, ctx->include_signature); + bare_method_name = std_string_c_str (&method_name); + if (ctx->include_signature) + { + const gchar * return_type_end, * name_begin; + GString * name; + + return_type_end = strchr (bare_method_name, ' '); + name_begin = return_type_end + 1 + class_name_length + 1; + if (is_constructor && g_str_has_prefix (name_begin, "")) + goto skip_method; + + name = g_string_sized_new (64); + + if (is_constructor) + { + g_string_append (name, "$init"); + g_string_append (name, strchr (name_begin, '>') + 1); + } + else + { + g_string_append (name, name_begin); + } + g_string_append (name, ": "); + g_string_append_len (name, bare_method_name, return_type_end - bare_method_name); + + bare_method_name_copy = g_string_free (name, FALSE); + bare_method_name = bare_method_name_copy; + } + else + { + const gchar * name_begin; + + name_begin = bare_method_name + class_name_length + 1; + if (is_constructor && strcmp (name_begin, "") == 0) + goto skip_method; + + if (is_constructor) + bare_method_name = "$init"; + else + bare_method_name += class_name_length + 1; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, bare_method_name)) + goto skip_method; + + if (ctx->ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (bare_method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = bare_method_name; + } + + if (!g_pattern_match_string (ctx->method_query, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + group = g_hash_table_lookup (ctx->groups, GUINT_TO_POINTER (klass->class_loader)); + if (group == NULL) + { + group = json_builder_new_immutable (); + g_hash_table_insert (ctx->groups, GUINT_TO_POINTER (klass->class_loader), group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + json_builder_add_int_value (group, klass->class_loader); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, bare_method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (bare_method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (bare_method_name_copy); + std_string_destroy (&method_name); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + if (group == NULL) + goto skip_class; + + json_builder_end_array (group); + json_builder_end_object (group); + +skip_class: + g_free (class_name_copy); + g_free (class_name); + std_string_destroy (&descriptor_storage); + + return TRUE; +} + +gchar * +enumerate_methods_jvm (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes, + JNIEnv * env) +{ + gchar * result; + GPatternSpec * class_pattern, * method_pattern; + GHashTable * groups; + gpointer * ef = env->functions; + jobject (* new_global_ref) (JNIEnv *, jobject) = ef[21]; + void (* delete_local_ref) (JNIEnv *, jobject) = ef[23]; + jboolean (* is_same_object) (JNIEnv *, jobject, jobject) = ef[24]; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_signature) (jvmtiEnv *, jclass, char **, char **) = jf[48]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_loader) (jvmtiEnv *, jclass, jobject *) = jf[57]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_loaded_classes) (jvmtiEnv *, jint *, jclass **) = jf[78]; + jint class_count, class_index; + jclass * classes; + + class_pattern = make_pattern_spec (class_query, ignore_case); + method_pattern = make_pattern_spec (method_query, ignore_case); + groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + if (get_loaded_classes (jvmti, &class_count, &classes) != JVMTI_ERROR_NONE) + goto emit_results; + + for (class_index = 0; class_index != class_count; class_index++) + { + jclass klass = classes[class_index]; + jobject loader = NULL; + gboolean have_loader = FALSE; + char * signature = NULL; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + jint method_count, method_index; + jmethodID * methods = NULL; + JsonBuilder * group = NULL; + GHashTable * seen_method_names = NULL; + + if (skip_system_classes) + { + if (get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_class; + have_loader = TRUE; + + if (loader == NULL) + goto skip_class; + } + + if (get_class_signature (jvmti, klass, &signature, NULL) != JVMTI_ERROR_NONE) + goto skip_class; + + class_name = class_name_from_signature (signature); + + if (ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (class_pattern, normalized_class_name)) + goto skip_class; + + if (get_class_methods (jvmti, klass, &method_count, &methods) != JVMTI_ERROR_NONE) + goto skip_class; + + if (!include_signature) + seen_method_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + for (method_index = 0; method_index != method_count; method_index++) + { + jmethodID method = methods[method_index]; + const gchar * method_name; + char * method_name_value = NULL; + char * method_signature_value = NULL; + gchar * method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + if (get_method_name (jvmti, method, &method_name_value, include_signature ? &method_signature_value : NULL, NULL) != JVMTI_ERROR_NONE) + goto skip_method; + method_name = method_name_value; + + if (method_name[0] == '<') + { + if (strcmp (method_name, "") == 0) + method_name = "$init"; + else if (strcmp (method_name, "") == 0) + goto skip_method; + } + + if (include_signature) + { + method_name_copy = format_method_signature (method_name, method_signature_value); + method_name = method_name_copy; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, method_name)) + goto skip_method; + + if (ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = method_name; + } + + if (!g_pattern_match_string (method_pattern, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + if (!have_loader && get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_method; + + if (loader == NULL) + { + group = g_hash_table_lookup (groups, NULL); + } + else + { + GHashTableIter iter; + jobject cur_loader; + JsonBuilder * cur_group; + + g_hash_table_iter_init (&iter, groups); + while (g_hash_table_iter_next (&iter, (gpointer *) &cur_loader, (gpointer *) &cur_group)) + { + if (cur_loader != NULL && is_same_object (env, cur_loader, loader)) + { + group = cur_group; + break; + } + } + } + + if (group == NULL) + { + jobject l; + gchar * str; + + l = (loader != NULL) ? new_global_ref (env, loader) : NULL; + + group = json_builder_new_immutable (); + g_hash_table_insert (groups, l, group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + str = g_strdup_printf ("0x%" G_GSIZE_MODIFIER "x", GPOINTER_TO_SIZE (l)); + json_builder_add_string_value (group, str); + g_free (str); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (method_name_copy); + deallocate (jvmti, method_signature_value); + deallocate (jvmti, method_name_value); + } + +skip_class: + if (group != NULL) + { + json_builder_end_array (group); + json_builder_end_object (group); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + deallocate (jvmti, methods); + + g_free (class_name_copy); + g_free (class_name); + deallocate (jvmti, signature); + + if (loader != NULL) + delete_local_ref (env, loader); + + delete_local_ref (env, klass); + } + + deallocate (jvmti, classes); + +emit_results: + result = finalize_method_groups_to_json (groups); + + g_hash_table_unref (groups); + g_pattern_spec_free (method_pattern); + g_pattern_spec_free (class_pattern); + + return result; +} + +static gchar * +finalize_method_groups_to_json (GHashTable * groups) +{ + GString * result; + GHashTableIter iter; + guint i; + JsonBuilder * group; + + result = g_string_sized_new (1024); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, groups); + for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &group); i++) + { + JsonNode * root; + gchar * json; + + if (i > 0) + g_string_append_c (result, ','); + + json_builder_end_array (group); + json_builder_end_object (group); + + root = json_builder_get_root (group); + json = json_to_string (root, FALSE); + g_string_append (result, json); + g_free (json); + json_node_unref (root); + + g_object_unref (group); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +static GPatternSpec * +make_pattern_spec (const gchar * pattern, + jboolean ignore_case) +{ + GPatternSpec * spec; + + if (ignore_case) + { + gchar * str = g_utf8_strdown (pattern, -1); + spec = g_pattern_spec_new (str); + g_free (str); + } + else + { + spec = g_pattern_spec_new (pattern); + } + + return spec; +} + +static gchar * +class_name_from_signature (const gchar * descriptor) +{ + gchar * result, * c; + + result = g_strdup (descriptor + 1); + + for (c = result; *c != '\\0'; c++) + { + if (*c == '/') + *c = '.'; + } + + c[-1] = '\\0'; + + return result; +} + +static gchar * +format_method_signature (const gchar * name, + const gchar * signature) +{ + GString * sig; + const gchar * cursor; + gint arg_index; + + sig = g_string_sized_new (128); + + g_string_append (sig, name); + + cursor = signature; + arg_index = -1; + while (TRUE) + { + const gchar c = *cursor; + + if (c == '(') + { + g_string_append_c (sig, c); + cursor++; + arg_index = 0; + } + else if (c == ')') + { + g_string_append_c (sig, c); + cursor++; + break; + } + else + { + if (arg_index >= 1) + g_string_append (sig, ", "); + + append_type (sig, &cursor); + + if (arg_index != -1) + arg_index++; + } + } + + g_string_append (sig, ": "); + append_type (sig, &cursor); + + return g_string_free (sig, FALSE); +} + +static void +append_type (GString * output, + const gchar ** type) +{ + const gchar * cursor = *type; + + switch (*cursor) + { + case 'Z': + g_string_append (output, "boolean"); + cursor++; + break; + case 'B': + g_string_append (output, "byte"); + cursor++; + break; + case 'C': + g_string_append (output, "char"); + cursor++; + break; + case 'S': + g_string_append (output, "short"); + cursor++; + break; + case 'I': + g_string_append (output, "int"); + cursor++; + break; + case 'J': + g_string_append (output, "long"); + cursor++; + break; + case 'F': + g_string_append (output, "float"); + cursor++; + break; + case 'D': + g_string_append (output, "double"); + cursor++; + break; + case 'V': + g_string_append (output, "void"); + cursor++; + break; + case 'L': + { + gchar ch; + + cursor++; + for (; (ch = *cursor) != ';'; cursor++) + { + g_string_append_c (output, (ch != '/') ? ch : '.'); + } + cursor++; + + break; + } + case '[': + *type = cursor + 1; + append_type (output, type); + g_string_append (output, "[]"); + return; + default: + g_string_append (output, "BUG"); + cursor++; + } + + *type = cursor; +} + +void +dealloc (gpointer mem) +{ + g_free (mem); +} + +static gpointer +read_art_array (gpointer object_base, + guint field_offset, + guint length_size, + guint * length) +{ + gpointer result, header; + guint n; + + header = GSIZE_TO_POINTER (*(guint64 *) (object_base + field_offset)); + if (header != NULL) + { + result = header + length_size; + if (length_size == sizeof (guint32)) + n = *(guint32 *) header; + else + n = *(guint64 *) header; + } + else + { + result = NULL; + n = 0; + } + + if (length != NULL) + *length = n; + + return result; +} + +static void +std_string_destroy (StdString * str) +{ + if ((str->l.capacity & 1) != 0) + art_api.free (str->l.data); +} + +static gchar * +std_string_c_str (StdString * self) +{ + if ((self->l.capacity & 1) != 0) + return self->l.data; + + return self->s.data; +} +`,_d=/(.+)!([^/]+)\/?([isu]+)?/,Ee=null,Ro=null,ze=class t{static build(e,n){return Oo(n),Ro(e,n,r=>new t(Ee.new(e,r,n)))}static enumerateMethods(e,n,r){Oo(r);let o=e.match(_d);if(o===null)throw new Error("Invalid query; format is: class!method -- see documentation of Java.enumerateMethods(query) for details");let s=Memory.allocUtf8String(o[1]),i=Memory.allocUtf8String(o[2]),l=!1,a=!1,c=!1,d=o[3];d!==void 0&&(l=d.indexOf("s")!==-1,a=d.indexOf("i")!==-1,c=d.indexOf("u")!==-1);let p;if(n.jvmti!==null){let f=Ee.enumerateMethodsJvm(s,i,Ke(l),Ke(a),Ke(c),r);try{p=JSON.parse(f.readUtf8String()).map(u=>{let _=ptr(u.loader);return u.loader=_.isNull()?null:_,u})}finally{Ee.dealloc(f)}}else ye(r.vm,r,f=>{let u=Ee.enumerateMethodsArt(s,i,Ke(l),Ke(a),Ke(c));try{let _=n["art::JavaVMExt::AddGlobalRef"],{vm:h}=n;p=JSON.parse(u.readUtf8String()).map(g=>{let b=g.loader;return g.loader=b!==0?_(h,f,ptr(b)):null,g})}finally{Ee.dealloc(u)}});return p}constructor(e){this.handle=e}has(e){return Ee.has(this.handle,Memory.allocUtf8String(e))!==0}find(e){return Ee.find(this.handle,Memory.allocUtf8String(e)).readUtf8String()}list(){let e=Ee.list(this.handle);try{return JSON.parse(e.readUtf8String())}finally{Ee.dealloc(e)}}};function Oo(t){Ee===null&&(Ee=md(t),Ro=gd(Ee,t.vm))}function md(t){let e=_t(),{jvmti:n=null}=e,{pointerSize:r}=Process,o=8,s=r,i=7*r,l=10*4+5*r,a=o+s+i+l,d=Memory.alloc(a),p=d.add(o),f=p.add(s),{getDeclaredMethods:u,getDeclaredFields:_}=t.javaLangClass(),h=t.javaLangReflectMethod(),g=t.javaLangReflectField(),b=f;[n!==null?n:NULL,u,_,h.getName,h.getModifiers,g.getName,g.getModifiers].forEach(k=>{b=b.writePointer(k).add(r)});let E=f.add(i),{vm:C}=t;if(e.flavor==="art"){let k;if(n!==null)k=[0,0,0,0];else{let j=$n(C).offset;k=[j.ifields,j.methods,j.sfields,j.copiedMethodsOffset]}let N=_e(C),S=Dt(C),L=E;[1,...k,N.size,N.offset.accessFlags,S.size,S.offset.accessFlags,4294967295].forEach(j=>{L=L.writeUInt(j).add(4)}),[e.artClassLinker.address,e["art::ClassLinker::VisitClasses"],e["art::mirror::Class::GetDescriptor"],e["art::ArtMethod::PrettyMethod"],Process.getModuleByName("libc.so").getExportByName("free")].forEach((j,w)=>{j===void 0&&(j=NULL),L=L.writePointer(j).add(r)})}let A=new CModule(hd,{lock:d,models:p,java_api:f,art_api:E}),M={exceptions:"propagate"},O={exceptions:"propagate",scheduling:"exclusive"};return{handle:A,new:new NativeFunction(A.model_new,"pointer",["pointer","pointer","pointer"],M),has:new NativeFunction(A.model_has,"bool",["pointer","pointer"],O),find:new NativeFunction(A.model_find,"pointer",["pointer","pointer"],O),list:new NativeFunction(A.model_list,"pointer",["pointer"],O),enumerateMethodsArt:new NativeFunction(A.enumerate_methods_art,"pointer",["pointer","pointer","bool","bool","bool"],M),enumerateMethodsJvm:new NativeFunction(A.enumerate_methods_jvm,"pointer",["pointer","pointer","bool","bool","bool","pointer"],M),dealloc:new NativeFunction(A.dealloc,"void",["pointer"],O)}}function gd(t,e){let n=_t();if(n.flavor!=="art")return bd;let r=n["art::JavaVMExt::DecodeGlobal"];return function(o,s,i){let l;return ye(e,s,a=>{let c=r(e,a,o);l=i(c)}),l}}function bd(t,e,n){return n(NULL)}function Ke(t){return t?1:0}var mt=class{constructor(e,n){this.items=new Map,this.capacity=e,this.destroy=n}dispose(e){let{items:n,destroy:r}=this;n.forEach(o=>{r(o,e)}),n.clear()}get(e){let{items:n}=this,r=n.get(e);return r!==void 0&&(n.delete(e),n.set(e,r)),r}set(e,n,r){let{items:o}=this,s=o.get(e);if(s!==void 0)o.delete(e),this.destroy(s,r);else if(o.size===this.capacity){let i=o.keys().next().value,l=o.get(i);o.delete(i),this.destroy(l,r)}o.set(e,n)}};var gt=1,cr=256,Po=65536,yd=305419896,Fo=32,Do=12,Uo=8,Bo=8,zo=4,Vo=4,Jo=12,Ed=0,vd=1,Sd=2,wd=3,Id=4,Cd=5,Td=6,Ad=4096,Ld=4097,xd=4099,Nd=8192,kd=8193,Md=8194,jd=8195,Od=8196,Rd=8198,Pd=24,Fd=28,Dd=2,Ud=24,Go=m.from([3,0,7,14,0]),ar="Ldalvik/annotation/Throws;",Bd=m.from([0]);function zd(t){let e=new dr,n=Object.assign({},t);return e.addClass(n),e.build()}var dr=class{constructor(){this.classes=[]}addClass(e){this.classes.push(e)}build(){let e=Gd(this.classes),{classes:n,interfaces:r,fields:o,methods:s,protos:i,parameters:l,annotationDirectories:a,annotationSets:c,throwsAnnotations:d,types:p,strings:f}=e,u=0,_=0,h=8,g=12,b=20,E=112;u+=E;let C=u,A=f.length*Vo;u+=A;let M=u,O=p.length*zo;u+=O;let k=u,N=i.length*Do;u+=N;let S=u,L=o.length*Uo;u+=L;let j=u,w=s.length*Bo;u+=w;let R=u,D=n.length*Fo;u+=D;let U=u,F=c.map(T=>{let P=u;return T.offset=P,u+=4+T.items.length*4,P}),z=n.reduce((T,P)=>(P.classData.constructorMethods.forEach(H=>{let[,q,Z]=H;(q&cr)===0&&Z>=0&&(H.push(u),T.push({offset:u,superConstructor:Z}),u+=Ud)}),T),[]);a.forEach(T=>{T.offset=u,u+=16+T.methods.length*8});let X=r.map(T=>{u=lr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),te=l.map(T=>{u=lr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),ae=[],Q=f.map(T=>{let P=u,B=m.from(me(T.length)),H=m.from(T,"utf8"),q=m.concat([B,H,Bd]);return ae.push(q),u+=q.length,P}),se=z.map(T=>{let P=u;return u+=Go.length,P}),Y=d.map(T=>{let P=Jd(T);return T.offset=u,u+=P.length,P}),ne=n.map((T,P)=>{T.classData.offset=u;let B=Vd(T);return u+=B.length,B}),we=0,tt=0;u=lr(u,4);let $=u,he=r.length+l.length,Le=4+(o.length>0?1:0)+2+c.length+z.length+a.length+(he>0?1:0)+1+se.length+d.length+n.length+1,Pe=4+Le*Jo;u+=Pe;let je=u-U,Ge=u,I=m.alloc(Ge);I.write(`dex +035`),I.writeUInt32LE(Ge,32),I.writeUInt32LE(E,36),I.writeUInt32LE(yd,40),I.writeUInt32LE(we,44),I.writeUInt32LE(tt,48),I.writeUInt32LE($,52),I.writeUInt32LE(f.length,56),I.writeUInt32LE(C,60),I.writeUInt32LE(p.length,64),I.writeUInt32LE(M,68),I.writeUInt32LE(i.length,72),I.writeUInt32LE(k,76),I.writeUInt32LE(o.length,80),I.writeUInt32LE(o.length>0?S:0,84),I.writeUInt32LE(s.length,88),I.writeUInt32LE(j,92),I.writeUInt32LE(n.length,96),I.writeUInt32LE(R,100),I.writeUInt32LE(je,104),I.writeUInt32LE(U,108),Q.forEach((T,P)=>{I.writeUInt32LE(T,C+P*Vo)}),p.forEach((T,P)=>{I.writeUInt32LE(T,M+P*zo)}),i.forEach((T,P)=>{let[B,H,q]=T,Z=k+P*Do;I.writeUInt32LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q!==null?q.offset:0,Z+8)}),o.forEach((T,P)=>{let[B,H,q]=T,Z=S+P*Uo;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),s.forEach((T,P)=>{let[B,H,q]=T,Z=j+P*Bo;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),n.forEach((T,P)=>{let{interfaces:B,annotationsDirectory:H}=T,q=B!==null?B.offset:0,Z=H!==null?H.offset:0,nt=0,ge=R+P*Fo;I.writeUInt32LE(T.index,ge),I.writeUInt32LE(T.accessFlags,ge+4),I.writeUInt32LE(T.superClassIndex,ge+8),I.writeUInt32LE(q,ge+12),I.writeUInt32LE(T.sourceFileIndex,ge+16),I.writeUInt32LE(Z,ge+20),I.writeUInt32LE(T.classData.offset,ge+24),I.writeUInt32LE(nt,ge+28)}),c.forEach((T,P)=>{let{items:B}=T,H=F[P];I.writeUInt32LE(B.length,H),B.forEach((q,Z)=>{I.writeUInt32LE(q.offset,H+4+Z*4)})}),z.forEach((T,P)=>{let{offset:B,superConstructor:H}=T,q=1,Z=1,nt=1,ge=0,Et=4;I.writeUInt16LE(q,B),I.writeUInt16LE(Z,B+2),I.writeUInt16LE(nt,B+4),I.writeUInt16LE(ge,B+6),I.writeUInt32LE(se[P],B+8),I.writeUInt32LE(Et,B+12),I.writeUInt16LE(4208,B+16),I.writeUInt16LE(H,B+18),I.writeUInt16LE(0,B+20),I.writeUInt16LE(14,B+22)}),a.forEach(T=>{let P=T.offset,B=0,H=0,q=T.methods.length,Z=0;I.writeUInt32LE(B,P),I.writeUInt32LE(H,P+4),I.writeUInt32LE(q,P+8),I.writeUInt32LE(Z,P+12),T.methods.forEach((nt,ge)=>{let Et=P+16+ge*8,[ys,Es]=nt;I.writeUInt32LE(ys,Et),I.writeUInt32LE(Es.offset,Et+4)})}),r.forEach((T,P)=>{let B=X[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),l.forEach((T,P)=>{let B=te[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),ae.forEach((T,P)=>{T.copy(I,Q[P])}),se.forEach(T=>{Go.copy(I,T)}),Y.forEach((T,P)=>{T.copy(I,d[P].offset)}),ne.forEach((T,P)=>{T.copy(I,n[P].classData.offset)}),I.writeUInt32LE(Le,$);let le=[[Ed,1,_],[vd,f.length,C],[Sd,p.length,M],[wd,i.length,k]];o.length>0&&le.push([Id,o.length,S]),le.push([Cd,s.length,j]),le.push([Td,n.length,R]),c.forEach((T,P)=>{le.push([xd,T.items.length,F[P]])}),z.forEach(T=>{le.push([kd,1,T.offset])}),a.forEach(T=>{le.push([Rd,1,T.offset])}),he>0&&le.push([Ld,he,X.concat(te)[0]]),le.push([Md,f.length,Q[0]]),se.forEach(T=>{le.push([jd,1,T])}),d.forEach(T=>{le.push([Od,1,T.offset])}),n.forEach(T=>{le.push([Nd,1,T.classData.offset])}),le.push([Ad,1,$]),le.forEach((T,P)=>{let[B,H,q]=T,Z=$+4+P*Jo;I.writeUInt16LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q,Z+8)});let Ar=new Checksum("sha1");return Ar.update(I.slice(g+b)),m.from(Ar.getDigest()).copy(I,g),I.writeUInt32LE(Kd(I,g),h),I}};function Vd(t){let{instanceFields:e,constructorMethods:n,virtualMethods:r}=t.classData;return m.from([0].concat(me(e.length)).concat(me(n.length)).concat(me(r.length)).concat(e.reduce((s,[i,l])=>s.concat(me(i)).concat(me(l)),[])).concat(n.reduce((s,[i,l,,a])=>s.concat(me(i)).concat(me(l)).concat(me(a||0)),[])).concat(r.reduce((s,[i,l])=>s.concat(me(i)).concat(me(l)).concat([0]),[])))}function Jd(t){let{thrownTypes:e}=t;return m.from([Dd].concat(me(t.type)).concat([1]).concat(me(t.value)).concat([Fd,e.length]).concat(e.reduce((n,r)=>(n.push(Pd,r),n),[])))}function Gd(t){let e=new Set,n=new Set,r={},o=[],s=[],i={},l=new Set,a=new Set;t.forEach(w=>{let{name:R,superClass:D,sourceFileName:U}=w;e.add("this"),e.add(R),n.add(R),e.add(D),n.add(D),e.add(U),w.interfaces.forEach(F=>{e.add(F),n.add(F)}),w.fields.forEach(F=>{let[z,X]=F;e.add(z),e.add(X),n.add(X),o.push([w.name,X,z])}),w.methods.some(([F])=>F==="")||(w.methods.unshift(["","V",[]]),l.add(R)),w.methods.forEach(F=>{let[z,X,te,ae=[],Q]=F;e.add(z);let se=c(X,te),Y=null;if(ae.length>0){let ne=ae.slice();ne.sort(),Y=ne.join("|");let we=i[Y];we===void 0&&(we={id:Y,types:ne},i[Y]=we),e.add(ar),n.add(ar),ae.forEach(tt=>{e.add(tt),n.add(tt)}),e.add("value")}if(s.push([w.name,se,z,Y,Q]),z===""){a.add(R+"|"+se);let ne=D+"|"+se;l.has(R)&&!a.has(ne)&&(s.push([D,se,z,null,0]),a.add(ne))}})});function c(w,R){let D=[w].concat(R),U=D.join("|");if(r[U]!==void 0)return U;e.add(w),n.add(w),R.forEach(z=>{e.add(z),n.add(z)});let F=D.map(Wd).join("");return e.add(F),r[U]=[U,F,w,R],U}let d=Array.from(e);d.sort();let p=d.reduce((w,R,D)=>(w[R]=D,w),{}),f=Array.from(n).map(w=>p[w]);f.sort($o);let u=f.reduce((w,R,D)=>(w[d[R]]=D,w),{}),_=Object.keys(r).map(w=>r[w]);_.sort(Hd);let h={},g=_.map(w=>{let[,R,D,U]=w,F;if(U.length>0){let z=U.join("|");F=h[z],F===void 0&&(F={types:U.map(X=>u[X]),offset:-1},h[z]=F)}else F=null;return[p[R],u[D],F]}),b=_.reduce((w,R,D)=>{let[U]=R;return w[U]=D,w},{}),E=Object.keys(h).map(w=>h[w]),C=o.map(w=>{let[R,D,U]=w;return[u[R],u[D],p[U]]});C.sort(Zd);let A=s.map(w=>{let[R,D,U,F,z]=w;return[u[R],b[D],p[U],F,z]});A.sort(qd);let M=Object.keys(i).map(w=>i[w]).map(w=>({id:w.id,type:u[ar],value:p.value,thrownTypes:w.types.map(R=>u[R]),offset:-1})),O=M.map(w=>({id:w.id,items:[w],offset:-1})),k=O.reduce((w,R,D)=>(w[R.id]=D,w),{}),N={},S=[],L=t.map(w=>{let R=u[w.name],D=gt,U=u[w.superClass],F,z=w.interfaces.map($=>u[$]);if(z.length>0){z.sort($o);let $=z.join("|");F=N[$],F===void 0&&(F={types:z,offset:-1},N[$]=F)}else F=null;let X=p[w.sourceFileName],te=A.reduce(($,he,Le)=>{let[Pe,je,Ge,I,le]=he;return Pe===R&&$.push([Le,Ge,I,je,le]),$},[]),ae=null,Q=te.filter(([,,$])=>$!==null).map(([$,,he])=>[$,O[k[he]]]);Q.length>0&&(ae={methods:Q,offset:-1},S.push(ae));let se=C.reduce(($,he,Le)=>{let[Pe]=he;return Pe===R&&$.push([Le>0?1:0,gt]),$},[]),Y=p[""],ne=te.filter(([,$])=>$===Y).map(([$,,,he])=>{if(l.has(w.name)){let Le=-1,Pe=A.length;for(let je=0;je!==Pe;je++){let[Ge,I,le]=A[je];if(Ge===U&&le===Y&&I===he){Le=je;break}}return[$,gt|Po,Le]}else return[$,gt|Po|cr,-1]}),we=$d(te.filter(([,$])=>$!==Y).map(([$,,,,he])=>[$,he|gt|cr]));return{index:R,accessFlags:D,superClassIndex:U,interfaces:F,sourceFileIndex:X,annotationsDirectory:ae,classData:{instanceFields:se,constructorMethods:ne,virtualMethods:we,offset:-1}}}),j=Object.keys(N).map(w=>N[w]);return{classes:L,interfaces:j,fields:C,methods:A,protos:g,parameters:E,annotationDirectories:S,annotationSets:O,throwsAnnotations:M,types:f,strings:d}}function $d(t){let e=0;return t.map(([n,r],o)=>{let s;return o===0?s=[n,r]:s=[n-e,r],e=n,s})}function $o(t,e){return t-e}function Hd(t,e){let[,,n,r]=t,[,,o,s]=e;if(no)return 1;let i=r.join("|"),l=s.join("|");return il?1:0}function Zd(t,e){let[n,r,o]=t,[s,i,l]=e;return n!==s?n-s:o!==l?o-l:r-i}function qd(t,e){let[n,r,o]=t,[s,i,l]=e;return n!==s?n-s:o!==l?o-l:r-i}function Wd(t){let e=t[0];return e==="L"||e==="["?"L":t}function me(t){if(t<=127)return[t];let e=[],n=!1;do{let r=t&127;t>>=7,n=t!==0,n&&(r|=128),e.push(r)}while(n);return e}function lr(t,e){let n=t%e;return n===0?t:t+e-n}function Kd(t,e){let n=1,r=0,o=t.length;for(let s=e;s>>0}var Ho=zd;var Qd=1,ur=null,Zo=null;function qo(t){ur=t}function pr(t,e,n){let r=Qe(t);return r===null&&(t.indexOf("[")===0?r=fr(t,e,n):(t[0]==="L"&&t[t.length-1]===";"&&(t=t.substring(1,t.length-1)),r=Xd(t,e,n))),Object.assign({className:t},r)}var Wo={boolean:{name:"Z",type:"uint8",size:1,byteSize:1,defaultValue:!1,isCompatible(t){return typeof t=="boolean"},fromJni(t){return!!t},toJni(t){return t?1:0},read(t){return t.readU8()},write(t,e){t.writeU8(e)},toString(){return this.name}},byte:{name:"B",type:"int8",size:1,byteSize:1,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-128&&t<=127},fromJni:ve,toJni:ve,read(t){return t.readS8()},write(t,e){t.writeS8(e)},toString(){return this.name}},char:{name:"C",type:"uint16",size:1,byteSize:2,defaultValue:0,isCompatible(t){if(typeof t!="string"||t.length!==1)return!1;let e=t.charCodeAt(0);return e>=0&&e<=65535},fromJni(t){return String.fromCharCode(t)},toJni(t){return t.charCodeAt(0)},read(t){return t.readU16()},write(t,e){t.writeU16(e)},toString(){return this.name}},short:{name:"S",type:"int16",size:1,byteSize:2,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-32768&&t<=32767},fromJni:ve,toJni:ve,read(t){return t.readS16()},write(t,e){t.writeS16(e)},toString(){return this.name}},int:{name:"I",type:"int32",size:1,byteSize:4,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-2147483648&&t<=2147483647},fromJni:ve,toJni:ve,read(t){return t.readS32()},write(t,e){t.writeS32(e)},toString(){return this.name}},long:{name:"J",type:"int64",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"||t instanceof Int64},fromJni:ve,toJni:ve,read(t){return t.readS64()},write(t,e){t.writeS64(e)},toString(){return this.name}},float:{name:"F",type:"float",size:1,byteSize:4,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readFloat()},write(t,e){t.writeFloat(e)},toString(){return this.name}},double:{name:"D",type:"double",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readDouble()},write(t,e){t.writeDouble(e)},toString(){return this.name}},void:{name:"V",type:"void",size:0,byteSize:0,defaultValue:void 0,isCompatible(t){return t===void 0},fromJni(){},toJni(){return NULL},toString(){return this.name}}},Yd=new Set(Object.values(Wo).map(t=>t.name));function Qe(t){let e=Wo[t];return e!==void 0?e:null}function Xd(t,e,n){let r=n._types[e?1:0],o=r[t];return o!==void 0||(t==="java.lang.Object"?o=eu(n):o=tu(t,e,n),r[t]=o),o}function eu(t){return{name:"Ljava/lang/Object;",type:"pointer",size:1,defaultValue:NULL,isCompatible(e){return e===null?!0:e===void 0?!1:e.$h instanceof NativePointer?!0:typeof e=="string"},fromJni(e,n,r){return e.isNull()?null:t.cast(e,t.use("java.lang.Object"),r)},toJni(e,n){return e===null?NULL:typeof e=="string"?n.newStringUtf(e):e.$h}}}function tu(t,e,n){let r=null,o=null,s=null;function i(){return r===null&&(r=n.use(t).class),r}function l(c){let d=i();return o===null&&(o=d.isInstance.overload("java.lang.Object")),o.call(d,c)}function a(){if(s===null){let c=i();s=n.use("java.lang.String").class.isAssignableFrom(c)}return s}return{name:Ve(t),type:"pointer",size:1,defaultValue:NULL,isCompatible(c){return c===null?!0:c===void 0?!1:c.$h instanceof NativePointer?l(c):typeof c=="string"&&a()},fromJni(c,d,p){return c.isNull()?null:a()&&e?d.stringFromJni(c):n.cast(c,n.use(t),p)},toJni(c,d){return c===null?NULL:typeof c=="string"?d.newStringUtf(c):c.$h},toString(){return this.name}}}var nu=[["Z","boolean"],["B","byte"],["C","char"],["D","double"],["F","float"],["I","int"],["J","long"],["S","short"]].reduce((t,[e,n])=>(t["["+e]=ru("["+e,n),t),{});function ru(t,e){let n=y.prototype,r=lu(e),o={typeName:e,newArray:n["new"+r+"Array"],setRegion:n["set"+r+"ArrayRegion"],getElements:n["get"+r+"ArrayElements"],releaseElements:n["release"+r+"ArrayElements"]};return{name:t,type:"pointer",size:1,defaultValue:NULL,isCompatible(s){return au(s,e)},fromJni(s,i,l){return su(s,o,i,l)},toJni(s,i){return iu(s,o,i)}}}function fr(t,e,n){let r=nu[t];if(r!==void 0)return r;if(t.indexOf("[")!==0)throw new Error("Unsupported type: "+t);let o=t.substring(1),s=pr(o,e,n),i=0,l=o.length;for(;i!==l&&o[i]==="[";)i++;o=o.substring(i),o[0]==="L"&&o[o.length-1]===";"&&(o=o.substring(1,o.length-1));let a=o.replace(/\./g,"/");Yd.has(a)?a="[".repeat(i)+a:a="[".repeat(i)+"L"+a+";";let c="["+a;return o="[".repeat(i)+o,{name:t.replace(/\./g,"/"),type:"pointer",size:1,defaultValue:NULL,isCompatible(d){return d===null?!0:typeof d!="object"||d.length===void 0?!1:d.every(function(p){return s.isCompatible(p)})},fromJni(d,p,f){if(d.isNull())return null;let u=[],_=p.getArrayLength(d);for(let h=0;h!==_;h++){let g=p.getObjectArrayElement(d,h);try{u.push(s.fromJni(g,p))}finally{p.deleteLocalRef(g)}}try{u.$w=n.cast(d,n.use(c),f)}catch{n.use("java.lang.reflect.Array").newInstance(n.use(o).class,0),u.$w=n.cast(d,n.use(c),f)}return u.$dispose=ou,u},toJni(d,p){if(d===null)return NULL;if(!(d instanceof Array))throw new Error("Expected an array");let f=d.$w;if(f!==void 0)return f.$h;let u=d.length,h=n.use(o).$borrowClassHandle(p);try{let g=p.newObjectArray(u,h.value,NULL);p.throwIfExceptionPending();for(let b=0;b!==u;b++){let E=s.toJni(d[b],p);try{p.setObjectArrayElement(g,b,E)}finally{s.type==="pointer"&&p.getObjectRefType(E)===Qd&&p.deleteLocalRef(E)}p.throwIfExceptionPending()}return g}finally{h.unref(p)}}}}function ou(){let t=this.length;for(let e=0;e!==t;e++){let n=this[e];if(n===null)continue;let r=n.$dispose;if(r===void 0)break;r.call(n)}this.$w.$dispose()}function su(t,e,n,r){if(t.isNull())return null;let o=Qe(e.typeName),s=n.getArrayLength(t);return new Vt(t,e,o,s,n,r)}function iu(t,e,n){if(t===null)return NULL;let r=t.$h;if(r!==void 0)return r;let o=t.length,s=Qe(e.typeName),i=e.newArray.call(n,o);if(i.isNull())throw new Error("Unable to construct array");if(o>0){let l=s.byteSize,a=s.write,c=s.toJni,d=Memory.alloc(o*s.byteSize);for(let p=0;p!==o;p++)a(d.add(p*l),c(t[p]));e.setRegion.call(n,i,0,o,d),n.throwIfExceptionPending()}return i}function au(t,e){if(t===null)return!0;if(t instanceof Vt)return t.$s.typeName===e;if(!(typeof t=="object"&&t.length!==void 0))return!1;let r=Qe(e);return Array.prototype.every.call(t,o=>r.isCompatible(o))}function Vt(t,e,n,r,o,s=!0){if(s){let i=o.newGlobalRef(t);this.$h=i,this.$r=Script.bindWeak(this,o.vm.makeHandleDestructor(i))}else this.$h=t,this.$r=null;return this.$s=e,this.$t=n,this.length=r,new Proxy(this,Zo)}Zo={has(t,e){return e in t?!0:t.tryParseIndex(e)!==null},get(t,e,n){let r=t.tryParseIndex(e);return r===null?t[e]:t.readElement(r)},set(t,e,n,r){let o=t.tryParseIndex(e);return o===null?(t[e]=n,!0):(t.writeElement(o,n),!0)},ownKeys(t){let e=[],{length:n}=t;for(let r=0;r!==n;r++){let o=r.toString();e.push(o)}return e.push("length"),e},getOwnPropertyDescriptor(t,e){return t.tryParseIndex(e)!==null?{writable:!0,configurable:!0,enumerable:!0}:Object.getOwnPropertyDescriptor(t,e)}};Object.defineProperties(Vt.prototype,{$dispose:{enumerable:!0,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t))}},$clone:{value(t){return new Vt(this.$h,this.$s,this.$t,this.length,t)}},tryParseIndex:{value(t){if(typeof t=="symbol")return null;let e=parseInt(t);return isNaN(e)||e<0||e>=this.length?null:e}},readElement:{value(t){return this.withElements(e=>{let n=this.$t;return n.fromJni(n.read(e.add(t*n.byteSize)))})}},writeElement:{value(t,e){let{$h:n,$s:r,$t:o}=this,s=ur.getEnv(),i=Memory.alloc(o.byteSize);o.write(i,o.toJni(e)),r.setRegion.call(s,n,t,1,i)}},withElements:{value(t){let{$h:e,$s:n}=this,r=ur.getEnv(),o=n.getElements.call(r,e);if(o.isNull())throw new Error("Unable to get array elements");try{return t(o)}finally{n.releaseElements.call(r,e,o)}}},toJSON:{value(){let{length:t,$t:e}=this,{byteSize:n,fromJni:r,read:o}=e;return this.withElements(s=>{let i=[];for(let l=0;l!==t;l++){let a=r(o(s.add(l*n)));i.push(a)}return i})}},toString:{value(){return this.toJSON().toString()}}});function Ve(t){return"L"+t.replace(/\./g,"/")+";"}function lu(t){return t.charAt(0).toUpperCase()+t.slice(1)}function ve(t){return t}var cu=4,{ensureClassInitialized:Ko,makeMethodMangler:ns}=Bt,du=8,mr=1,yt=2,Me=3,hr=1,gr=2,Jt=1,rs=2,Qo=Symbol("PENDING_USE"),Yo="/data/local/tmp",{getCurrentThreadId:$t,pointerSize:bt}=Process,ue={state:"empty",factories:[],loaders:null,Integer:null},G=null,K=null,os=null,ss=null,is=null,as=null,ls=null,Xo=null,_r=null,Xe=new Map,Re=class t{static _initialize(e,n){G=e,K=n,os=n.flavor==="art",n.flavor==="jvm"&&(Ko=xo,ns=ko)}static _disposeAll(e){ue.factories.forEach(n=>{n._dispose(e)})}static get(e){let n=Nu(),r=n.factories[0];if(e===null)return r;let o=n.loaders.get(e);if(o!==null){let i=r.cast(o,n.Integer);return n.factories[i.intValue()]}let s=new t;return s.loader=e,s.cacheDir=r.cacheDir,Er(s,e),s}constructor(){this.cacheDir=Yo,this.codeCacheDir=Yo+"/dalvik-cache",this.tempFileNaming={prefix:"frida",suffix:""},this._classes={},this._classHandles=new mt(10,pu),this._patchedMethods=new Set,this._loader=null,this._types=[{},{}],ue.factories.push(this)}_dispose(e){Array.from(this._patchedMethods).forEach(n=>{n.implementation=null}),this._patchedMethods.clear(),Qn(),this._classHandles.dispose(e),this._classes={}}get loader(){return this._loader}set loader(e){let n=this._loader===null&&e!==null;this._loader=e,n&&ue.state==="ready"&&this===ue.factories[0]&&Er(this,e)}use(e,n={}){let r=n.cache!=="skip",o=r?this._getUsedClass(e):void 0;if(o===void 0)try{let s=G.getEnv(),{_loader:i}=this,l=i!==null?hu(e,i,s):fu(e);o=this._make(e,l,s)}finally{r&&this._setUsedClass(e,o)}return o}_getUsedClass(e){let n;for(;(n=this._classes[e])===Qo;)Thread.sleep(.05);return n===void 0&&(this._classes[e]=Qo),n}_setUsedClass(e,n){n!==void 0?this._classes[e]=n:delete this._classes[e]}_make(e,n,r){let o=uu(),s=Object.create(Sr.prototype,{[Symbol.for("n")]:{value:e},$n:{get(){return this[Symbol.for("n")]}},[Symbol.for("C")]:{value:o},$C:{get(){return this[Symbol.for("C")]}},[Symbol.for("w")]:{value:null,writable:!0},$w:{get(){return this[Symbol.for("w")]},set(a){this[Symbol.for("w")]=a}},[Symbol.for("_s")]:{writable:!0},$_s:{get(){return this[Symbol.for("_s")]},set(a){this[Symbol.for("_s")]=a}},[Symbol.for("c")]:{value:[null]},$c:{get(){return this[Symbol.for("c")]}},[Symbol.for("m")]:{value:new Map},$m:{get(){return this[Symbol.for("m")]}},[Symbol.for("l")]:{value:null,writable:!0},$l:{get(){return this[Symbol.for("l")]},set(a){this[Symbol.for("l")]=a}},[Symbol.for("gch")]:{value:n},$gch:{get(){return this[Symbol.for("gch")]}},[Symbol.for("f")]:{value:this},$f:{get(){return this[Symbol.for("f")]}}});o.prototype=s;let i=new o(null);s[Symbol.for("w")]=i,s.$w=i;let l=i.$borrowClassHandle(r);try{let a=l.value;Ko(r,a),s.$l=ze.build(a,r)}finally{l.unref(r)}return i}retain(e){let n=G.getEnv();return e.$clone(n)}cast(e,n,r){let o=G.getEnv(),s=e.$h;s===void 0&&(s=e);let i=n.$borrowClassHandle(o);try{if(!o.isInstanceOf(s,i.value))throw new Error(`Cast from '${o.getObjectClassName(s)}' to '${n.$n}' isn't possible`)}finally{i.unref(o)}let l=n.$C;return new l(s,Jt,o,r)}wrap(e,n,r){let o=n.$C,s=new o(e,Jt,r,!1);return s.$r=Script.bindWeak(s,G.makeHandleDestructor(e)),s}array(e,n){let r=G.getEnv(),o=Qe(e);o!==null&&(e=o.name);let s=fr("["+e,!1,this),i=s.toJni(n,r);return s.fromJni(i,r,!0)}registerClass(e){let n=G.getEnv(),r=[];try{let o=this.use("java.lang.Class"),s=n.javaLangReflectMethod(),i=n.vaMethod("pointer",[]),l=e.name,a=e.implements||[],c=e.superClass||this.use("java.lang.Object"),d=[],p=[],f={name:Ve(l),sourceFileName:Mu(l),superClass:Ve(c.$n),interfaces:a.map(S=>Ve(S.$n)),fields:d,methods:p},u=a.slice();a.forEach(S=>{Array.prototype.slice.call(S.class.getInterfaces()).forEach(L=>{let j=this.cast(L,o).getCanonicalName();u.push(this.use(j))})});let _=e.fields||{};Object.getOwnPropertyNames(_).forEach(S=>{let L=this._getType(_[S]);d.push([S,L.name])});let h={},g={};u.forEach(S=>{let L=S.$borrowClassHandle(n);r.push(L);let j=L.value;S.$ownMembers.filter(w=>S[w].overloads!==void 0).forEach(w=>{let R=S[w],D=R.overloads,U=D.map(F=>es(w,F.returnType,F.argumentTypes));h[w]=[R,U,j],D.forEach((F,z)=>{let X=U[z];g[X]=[F,j]})})});let b=e.methods||{},C=Object.keys(b).reduce((S,L)=>{let j=b[L],w=L==="$init"?"":L;return j instanceof Array?S.push(...j.map(R=>[w,R])):S.push([w,j]),S},[]),A=[];C.forEach(([S,L])=>{let j=Me,w,R,D=[],U;if(typeof L=="function"){let te=h[S];if(te!==void 0&&Array.isArray(te)){let[ae,Q,se]=te;if(Q.length>1)throw new Error(`More than one overload matching '${S}': signature must be specified`);delete g[Q[0]];let Y=ae.overloads[0];j=Y.type,w=Y.returnType,R=Y.argumentTypes,U=L;let ne=n.toReflectedMethod(se,Y.handle,0),we=i(n.handle,ne,s.getGenericExceptionTypes);D=vr(n,we).map(Ve),n.deleteLocalRef(we),n.deleteLocalRef(ne)}else w=this._getType("void"),R=[],U=L}else{if(L.isStatic&&(j=yt),w=this._getType(L.returnType||"void"),R=(L.argumentTypes||[]).map(Q=>this._getType(Q)),U=L.implementation,typeof U!="function")throw new Error("Expected a function implementation for method: "+S);let te=es(S,w,R),ae=g[te];if(ae!==void 0){let[Q,se]=ae;delete g[te],j=Q.type,w=Q.returnType,R=Q.argumentTypes;let Y=n.toReflectedMethod(se,Q.handle,0),ne=i(n.handle,Y,s.getGenericExceptionTypes);D=vr(n,ne).map(Ve),n.deleteLocalRef(ne),n.deleteLocalRef(Y)}}let F=w.name,z=R.map(te=>te.name),X="("+z.join("")+")"+F;p.push([S,F,z,D,j===yt?du:0]),A.push([S,X,j,w,R,U])});let M=Object.keys(g);if(M.length>0)throw new Error("Missing implementation for: "+M.join(", "));let O=Gt.fromBuffer(Ho(f),this);try{O.load()}finally{O.file.delete()}let k=this.use(e.name),N=C.length;if(N>0){let S=3*bt,L=Memory.alloc(N*S),j=[],w=[];A.forEach(([U,F,z,X,te,ae],Q)=>{let se=Memory.allocUtf8String(U),Y=Memory.allocUtf8String(F),ne=cs(U,k,z,X,te,ae);L.add(Q*S).writePointer(se),L.add(Q*S+bt).writePointer(Y),L.add(Q*S+2*bt).writePointer(ne),w.push(se,Y),j.push(ne)});let R=k.$borrowClassHandle(n);r.push(R);let D=R.value;n.registerNatives(D,L,N),n.throwIfExceptionPending(),k.$nativeMethods=j}return k}finally{r.forEach(o=>{o.unref(n)})}}choose(e,n){let r=G.getEnv(),{flavor:o}=K;if(o==="jvm")this._chooseObjectsJvm(e,r,n);else if(o==="art"){let s=K["art::gc::Heap::VisitObjects"]===void 0;if(s&&K["art::gc::Heap::GetInstances"]===void 0)return this._chooseObjectsJvm(e,r,n);ye(G,r,i=>{s?this._chooseObjectsArtPreA12(e,r,i,n):this._chooseObjectsArtLegacy(e,r,i,n)})}else this._chooseObjectsDalvik(e,r,n)}_chooseObjectsJvm(e,n,r){let o=this.use(e),{jvmti:s}=K,i=1,l=3,a=o.$borrowClassHandle(n),c=int64(a.value.toString());try{let d=new NativeCallback((b,E,C,A)=>(C.writeS64(c),i),"int",["int64","int64","pointer","pointer"]);s.iterateOverInstancesOfClass(a.value,l,d,a.value);let p=Memory.alloc(8);p.writeS64(c);let f=Memory.alloc(cu),u=Memory.alloc(bt);s.getObjectsWithTags(1,p,f,u,NULL);let _=f.readS32(),h=u.readPointer(),g=[];for(let b=0;b!==_;b++)g.push(h.add(b*bt).readPointer());s.deallocate(h);try{for(let b of g){let E=this.cast(b,o);if(r.onMatch(E)==="stop")break}r.onComplete()}finally{g.forEach(b=>{n.deleteLocalRef(b)})}}finally{a.unref(n)}}_chooseObjectsArtPreA12(e,n,r,o){let s=this.use(e),i=pt.$new(r,G),l,a=s.$borrowClassHandle(n);try{let f=K["art::JavaVMExt::DecodeGlobal"](K.vm,r,a.value);l=i.newHandle(f)}finally{a.unref(n)}let c=0,d=ut.$new();K["art::gc::Heap::GetInstances"](K.artHeap,i,l,c,d);let p=d.handles.map(f=>n.newGlobalRef(f));d.$delete(),i.$delete();try{for(let f of p){let u=this.cast(f,s);if(o.onMatch(u)==="stop")break}o.onComplete()}finally{p.forEach(f=>{n.deleteGlobalRef(f)})}}_chooseObjectsArtLegacy(e,n,r,o){let s=this.use(e),i=[],l=K["art::JavaVMExt::AddGlobalRef"],a=K.vm,c,d=s.$borrowClassHandle(n);try{c=K["art::JavaVMExt::DecodeGlobal"](a,r,d.value).toInt32()}finally{d.unref(n)}let p=rr(c,f=>{i.push(l(a,r,f))});K["art::gc::Heap::VisitObjects"](K.artHeap,p,NULL);try{for(let f of i){let u=this.cast(f,s);if(o.onMatch(u)==="stop")break}}finally{i.forEach(f=>{n.deleteGlobalRef(f)})}o.onComplete()}_chooseObjectsDalvik(e,n,r){let o=this.use(e);if(K.addLocalReference===null){let i=Process.getModuleByName("libdvm.so"),l;switch(Process.arch){case"arm":l="2d e9 f0 41 05 46 15 4e 0c 46 7e 44 11 b3 43 68";break;case"ia32":l="8d 64 24 d4 89 5c 24 1c 89 74 24 20 e8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 85 d2";break}Memory.scan(i.base,i.size,l,{onMatch:(a,c)=>{let d;if(Process.arch==="arm")a=a.or(1),d=new NativeFunction(a,"pointer",["pointer","pointer"]);else{let p=Memory.alloc(Process.pageSize);Memory.patchCode(p,16,f=>{let u=new X86Writer(f,{pc:p});u.putMovRegRegOffsetPtr("eax","esp",4),u.putMovRegRegOffsetPtr("edx","esp",8),u.putJmpAddress(a),u.flush()}),d=new NativeFunction(p,"pointer",["pointer","pointer"]),d._thunk=p}return K.addLocalReference=d,G.perform(p=>{s(this,p)}),"stop"},onError(a){},onComplete(){K.addLocalReference===null&&r.onComplete()}})}else s(this,n);function s(i,l){let{DVM_JNI_ENV_OFFSET_SELF:a}=Bt,c=l.handle.add(a).readPointer(),d,p=o.$borrowClassHandle(l);try{d=K.dvmDecodeIndirectRef(c,p.value)}finally{p.unref(l)}let f=d.toMatchPattern(),u=K.dvmHeapSourceGetBase(),h=K.dvmHeapSourceGetLimit().sub(u).toInt32();Memory.scan(u,h,f,{onMatch:(g,b)=>{K.dvmIsValidObject(g)&&G.perform(E=>{let C=E.handle.add(a).readPointer(),A,M=K.addLocalReference(C,g);try{A=i.cast(M,o)}finally{E.deleteLocalRef(M)}if(r.onMatch(A)==="stop")return"stop"})},onError(g){},onComplete(){r.onComplete()}})}}openClassFile(e){return new Gt(e,null,this)}_getType(e,n=!0){return pr(e,n,this)}};function uu(){return function(t,e,n,r){return Sr.call(this,t,e,n,r)}}function Sr(t,e,n,r=!0){if(t!==null)if(r){let o=n.newGlobalRef(t);this.$h=o,this.$r=Script.bindWeak(this,G.makeHandleDestructor(o))}else this.$h=t,this.$r=null;else this.$h=null,this.$r=null;return this.$t=e,new Proxy(this,ss)}ss={has(t,e){return e in t?!0:t.$has(e)},get(t,e,n){if(typeof e!="string"||e.startsWith("$")||e==="class")return t[e];let r=t.$find(e);return r!==null?r(n):t[e]},set(t,e,n,r){return t[e]=n,!0},ownKeys(t){return t.$list()},getOwnPropertyDescriptor(t,e){return Object.prototype.hasOwnProperty.call(t,e)?Object.getOwnPropertyDescriptor(t,e):{writable:!1,configurable:!0,enumerable:!0}}};Object.defineProperties(Sr.prototype,{[Symbol.for("new")]:{enumerable:!1,get(){return this.$getCtor("allocAndInit")}},$new:{enumerable:!0,get(){return this[Symbol.for("new")]}},[Symbol.for("alloc")]:{enumerable:!1,value(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=t.allocObject(e.value);return this.$f.cast(n,this)}finally{e.unref(t)}}},$alloc:{enumerable:!0,get(){return this[Symbol.for("alloc")]}},[Symbol.for("init")]:{enumerable:!1,get(){return this.$getCtor("initOnly")}},$init:{enumerable:!0,get(){return this[Symbol.for("init")]}},[Symbol.for("dispose")]:{enumerable:!1,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t)),this.$h!==null&&(this.$h=void 0)}},$dispose:{enumerable:!0,get(){return this[Symbol.for("dispose")]}},[Symbol.for("clone")]:{enumerable:!1,value(t){let e=this.$C;return new e(this.$h,this.$t,t)}},$clone:{value(t){return this[Symbol.for("clone")](t)}},[Symbol.for("class")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=this.$f;return n.cast(e.value,n.use("java.lang.Class"))}finally{e.unref(t)}}},class:{enumerable:!0,get(){return this[Symbol.for("class")]}},[Symbol.for("className")]:{enumerable:!1,get(){let t=this.$h;return t===null?this.$n:G.getEnv().getObjectClassName(t)}},$className:{enumerable:!0,get(){return this[Symbol.for("className")]}},[Symbol.for("ownMembers")]:{enumerable:!1,get(){return this.$l.list()}},$ownMembers:{enumerable:!0,get(){return this[Symbol.for("ownMembers")]}},[Symbol.for("super")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$s.$C;return new e(this.$h,rs,t)}},$super:{enumerable:!0,get(){return this[Symbol.for("super")]}},[Symbol.for("s")]:{enumerable:!1,get(){let t=Object.getPrototypeOf(this),e=t.$_s;if(e===void 0){let n=G.getEnv(),r=this.$borrowClassHandle(n);try{let o=n.getSuperclass(r.value);if(o.isNull())e=null;else try{let s=n.getClassName(o),i=t.$f;if(e=i._getUsedClass(s),e===void 0)try{let l=_u(this);e=i._make(s,l,n)}finally{i._setUsedClass(s,e)}}finally{n.deleteLocalRef(o)}}finally{r.unref(n)}t.$_s=e}return e}},$s:{get(){return this[Symbol.for("s")]}},[Symbol.for("isSameObject")]:{enumerable:!1,value(t){return G.getEnv().isSameObject(t.$h,this.$h)}},$isSameObject:{value(t){return this[Symbol.for("isSameObject")](t)}},[Symbol.for("getCtor")]:{enumerable:!1,value(t){let e=this.$c,n=e[0];if(n===null){let r=G.getEnv(),o=this.$borrowClassHandle(r);try{n=mu(o.value,this.$w,r),e[0]=n}finally{o.unref(r)}}return n[t]}},$getCtor:{value(t){return this[Symbol.for("getCtor")](t)}},[Symbol.for("borrowClassHandle")]:{enumerable:!1,value(t){let e=this.$n,n=this.$f._classHandles,r=n.get(e);return r===void 0&&(r=new wr(this.$gch(t),t),n.set(e,r,t)),r.ref()}},$borrowClassHandle:{value(t){return this[Symbol.for("borrowClassHandle")](t)}},[Symbol.for("copyClassHandle")]:{enumerable:!1,value(t){let e=this.$borrowClassHandle(t);try{return t.newLocalRef(e.value)}finally{e.unref(t)}}},$copyClassHandle:{value(t){return this[Symbol.for("copyClassHandle")](t)}},[Symbol.for("getHandle")]:{enumerable:!1,value(t){let e=this.$h;if(e===void 0)throw new Error("Wrapper is disposed; perhaps it was borrowed from a hook instead of calling Java.retain() to make a long-lived wrapper?");return e}},$getHandle:{value(t){return this[Symbol.for("getHandle")](t)}},[Symbol.for("list")]:{enumerable:!1,value(){let t=this.$s,e=t!==null?t.$list():[],n=this.$l;return Array.from(new Set(e.concat(n.list())))}},$list:{get(){return this[Symbol.for("list")]}},[Symbol.for("has")]:{enumerable:!1,value(t){if(this.$m.has(t)||this.$l.has(t))return!0;let r=this.$s;return!!(r!==null&&r.$has(t))}},$has:{value(t){return this[Symbol.for("has")](t)}},[Symbol.for("find")]:{enumerable:!1,value(t){let e=this.$m,n=e.get(t);if(n!==void 0)return n;let o=this.$l.find(t);if(o!==null){let i=G.getEnv(),l=this.$borrowClassHandle(i);try{n=gu(t,o,l.value,this.$w,i)}finally{l.unref(i)}return e.set(t,n),n}let s=this.$s;return s!==null?s.$find(t):null}},$find:{value(t){return this[Symbol.for("find")](t)}},[Symbol.for("toJSON")]:{enumerable:!1,value(){let t=this.$n;if(this.$h===null)return``;let n=this.$className;return t===n?``:``}},toJSON:{get(){return this[Symbol.for("toJSON")]}}});function wr(t,e){this.value=e.newGlobalRef(t),e.deleteLocalRef(t),this.refs=1}wr.prototype.ref=function(){return this.refs++,this};wr.prototype.unref=function(t){--this.refs===0&&t.deleteGlobalRef(this.value)};function pu(t,e){t.unref(e)}function fu(t){let e=t.replace(/\./g,"/");return function(n){let r=$t();us(r);try{return n.findClass(e)}finally{ps(r)}}}function hu(t,e,n){return _r===null&&(Xo=n.vaMethod("pointer",["pointer"]),_r=e.loadClass.overload("java.lang.String").handle),n=null,function(r){let o=r.newStringUtf(t),s=$t();us(s);try{let i=Xo(r.handle,e.$h,_r,o);return r.throwIfExceptionPending(),i}finally{ps(s),r.deleteLocalRef(o)}}}function _u(t){return function(e){let n=t.$borrowClassHandle(e);try{return e.getSuperclass(n.value)}finally{n.unref(e)}}}function mu(t,e,n){let{$n:r,$f:o}=e,s=ku(r),i=n.javaLangClass(),l=n.javaLangReflectConstructor(),a=n.vaMethod("pointer",[]),c=n.vaMethod("uint8",[]),d=[],p=[],f=o._getType(r,!1),u=o._getType("void",!1),_=a(n.handle,t,i.getDeclaredConstructors);try{let h=n.getArrayLength(_);if(h!==0)for(let g=0;g!==h;g++){let b,E,C=n.getObjectArrayElement(_,g);try{b=n.fromReflectedMethod(C),E=a(n.handle,C,l.getGenericParameterTypes)}finally{n.deleteLocalRef(C)}let A;try{A=vr(n,E).map(M=>o._getType(M))}finally{n.deleteLocalRef(E)}d.push(Ye(s,e,mr,b,f,A,n)),p.push(Ye(s,e,Me,b,u,A,n))}else{if(c(n.handle,t,i.isInterface))throw new Error("cannot instantiate an interface");let b=n.javaLangObject(),E=n.getMethodId(b,"","()V");d.push(Ye(s,e,mr,E,f,[],n)),p.push(Ye(s,e,Me,E,u,[],n))}}finally{n.deleteLocalRef(_)}if(p.length===0)throw new Error("no supported overloads");return{allocAndInit:br(d),initOnly:br(p)}}function gu(t,e,n,r,o){return e.startsWith("m")?bu(t,e,n,r,o):Au(t,e,n,r,o)}function bu(t,e,n,r,o){let{$f:s}=r,i=e.split(":").slice(1),l=o.javaLangReflectMethod(),a=o.vaMethod("pointer",[]),c=o.vaMethod("uint8",[]),d=i.map(f=>{let u=f[0]==="s"?yt:Me,_=ptr(f.substr(1)),h,g=[],b=o.toReflectedMethod(n,_,u===yt?1:0);try{let E=!!c(o.handle,b,l.isVarArgs),C=a(o.handle,b,l.getGenericReturnType);o.throwIfExceptionPending();try{h=s._getType(o.getTypeName(C))}finally{o.deleteLocalRef(C)}let A=a(o.handle,b,l.getParameterTypes);try{let M=o.getArrayLength(A);for(let O=0;O!==M;O++){let k=o.getObjectArrayElement(A,O),N;try{N=E&&O===M-1?o.getArrayTypeName(k):o.getTypeName(k)}finally{o.deleteLocalRef(k)}let S=s._getType(N);g.push(S)}}finally{o.deleteLocalRef(A)}}catch{return null}finally{o.deleteLocalRef(b)}return Ye(t,r,u,_,h,g,o)}).filter(f=>f!==null);if(d.length===0)throw new Error("No supported overloads");t==="valueOf"&&Iu(d);let p=br(d);return function(f){return p}}function br(t){let e=yu();return Object.setPrototypeOf(e,is),e._o=t,e}function yu(){let t=function(){return t.invoke(this,arguments)};return t}is=Object.create(Function.prototype,{overloads:{enumerable:!0,get(){return this._o}},overload:{value(...t){let e=this._o,n=t.length,r=t.join(":");for(let o=0;o!==e.length;o++){let s=e[o],{argumentTypes:i}=s;if(i.length!==n)continue;if(i.map(a=>a.className).join(":")===r)return s}yr(this.methodName,this.overloads,"specified argument types do not match any of:")}},methodName:{enumerable:!0,get(){return this._o[0].methodName}},holder:{enumerable:!0,get(){return this._o[0].holder}},type:{enumerable:!0,get(){return this._o[0].type}},handle:{enumerable:!0,get(){return Je(this),this._o[0].handle}},implementation:{enumerable:!0,get(){return Je(this),this._o[0].implementation},set(t){Je(this),this._o[0].implementation=t}},returnType:{enumerable:!0,get(){return Je(this),this._o[0].returnType}},argumentTypes:{enumerable:!0,get(){return Je(this),this._o[0].argumentTypes}},canInvokeWith:{enumerable:!0,get(t){return Je(this),this._o[0].canInvokeWith}},clone:{enumerable:!0,value(t){return Je(this),this._o[0].clone(t)}},invoke:{value(t,e){let n=this._o,r=t.$h!==null;for(let o=0;o!==n.length;o++){let s=n[o];if(s.canInvokeWith(e)){if(s.type===Me&&!r){let i=this.methodName;if(i==="toString")return``;throw new Error(i+": cannot call instance method without an instance")}return s.apply(t,e)}}if(this.methodName==="toString")return``;yr(this.methodName,this.overloads,"argument types do not match any of:")}}});function es(t,e,n){return`${e.className} ${t}(${n.map(r=>r.className).join(", ")})`}function Je(t){let e=t._o;e.length>1&&yr(e[0].methodName,e,"has more than one overload, use .overload() to choose from:")}function yr(t,e,n){let o=e.slice().sort((s,i)=>s.argumentTypes.length-i.argumentTypes.length).map(s=>s.argumentTypes.length>0?".overload('"+s.argumentTypes.map(l=>l.className).join("', '")+"')":".overload()");throw new Error(`${t}(): ${n} + ${o.join(` + `)}`)}function Ye(t,e,n,r,o,s,i,l){let a=o.type,c=s.map(f=>f.type);i===null&&(i=G.getEnv());let d,p;return n===Me?(d=i.vaMethod(a,c,l),p=i.nonvirtualVaMethod(a,c,l)):n===yt?(d=i.staticVaMethod(a,c,l),p=d):(d=i.constructor(c,l),p=d),Eu([t,e,n,r,o,s,d,p])}function Eu(t){let e=vu();return Object.setPrototypeOf(e,as),e._p=t,e}function vu(){let t=function(){return t.invoke(this,arguments)};return t}as=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return this._p[0]}},holder:{enumerable:!0,get(){return this._p[1]}},type:{enumerable:!0,get(){return this._p[2]}},handle:{enumerable:!0,get(){return this._p[3]}},implementation:{enumerable:!0,get(){let t=this._r;return t!==void 0?t:null},set(t){let e=this._p,n=e[1];if(e[2]===mr)throw new Error("Reimplementing $new is not possible; replace implementation of $init instead");let o=this._r;if(o!==void 0&&(n.$f._patchedMethods.delete(this),o._m.revert(G),this._r=void 0),t!==null){let[s,i,l,a,c,d]=e,p=cs(s,i,l,c,d,t,this),f=ns(a);p._m=f,this._r=p,f.replace(p,l===Me,d,G,K),n.$f._patchedMethods.add(this)}}},returnType:{enumerable:!0,get(){return this._p[4]}},argumentTypes:{enumerable:!0,get(){return this._p[5]}},canInvokeWith:{enumerable:!0,value(t){let e=this._p[5];return t.length!==e.length?!1:e.every((n,r)=>n.isCompatible(t[r]))}},clone:{enumerable:!0,value(t){let e=this._p.slice(0,6);return Ye(...e,null,t)}},invoke:{value(t,e){let n=G.getEnv(),r=this._p,o=r[2],s=r[4],i=r[5],l=this._r,a=o===Me,c=e.length,d=2+c;n.pushLocalFrame(d);let p=null;try{let f;a?f=t.$getHandle():(p=t.$borrowClassHandle(n),f=p.value);let u,_=t.$t;l===void 0?u=r[3]:(u=l._m.resolveTarget(t,a,n,K),os&&l._c.has($t())&&(_=rs));let h=[n.handle,f,u];for(let E=0;E!==c;E++)h.push(i[E].toJni(e[E],n));let g;_===Jt?g=r[6]:(g=r[7],a&&h.splice(2,0,t.$copyClassHandle(n)));let b=g.apply(null,h);return n.throwIfExceptionPending(),s.fromJni(b,n,!0)}finally{p!==null&&p.unref(n),n.popLocalFrame(NULL)}}},toString:{enumerable:!0,value(){return`function ${this.methodName}(${this.argumentTypes.map(t=>t.className).join(", ")}): ${this.returnType.className}`}}});function cs(t,e,n,r,o,s,i=null){let l=new Set,a=Su([t,e,n,r,o,s,i,l]),c=new NativeCallback(a,r.type,["pointer","pointer"].concat(o.map(d=>d.type)));return c._c=l,c}function Su(t){return function(){return wu(arguments,t)}}function wu(t,e){let n=new y(t[0],G),[r,o,s,i,l,a,c,d]=e,p=[],f;if(s===Me){let h=o.$C;f=new h(t[1],Jt,n,!1)}else f=o;let u=$t();n.pushLocalFrame(3);let _=!0;G.link(u,n);try{d.add(u);let h;c===null||!Xe.has(u)?h=a:h=c;let g=[],b=t.length-2;for(let A=0;A!==b;A++){let O=l[A].fromJni(t[2+A],n,!1);g.push(O),p.push(O)}let E=h.apply(f,g);if(!i.isCompatible(E))throw new Error(`Implementation for ${r} expected return value compatible with ${i.className}`);let C=i.toJni(E,n);return i.type==="pointer"&&(C=n.popLocalFrame(C),_=!1,p.push(E)),C}catch(h){let g=h.$h;return g!==void 0?n.throw(g):Script.nextTick(()=>{throw h}),i.defaultValue}finally{G.unlink(u),_&&n.popLocalFrame(NULL),d.delete(u),p.forEach(h=>{if(h===null)return;let g=h.$dispose;g!==void 0&&g.call(h)})}}function Iu(t){let{holder:e,type:n}=t[0];t.some(o=>o.type===n&&o.argumentTypes.length===0)||t.push(Cu([e,n]))}function Cu(t){let e=Tu();return Object.setPrototypeOf(e,ls),e._p=t,e}function Tu(){return function(){return this}}ls=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return"valueOf"}},holder:{enumerable:!0,get(){return this._p[0]}},type:{enumerable:!0,get(){return this._p[1]}},handle:{enumerable:!0,get(){return NULL}},implementation:{enumerable:!0,get(){return null},set(t){}},returnType:{enumerable:!0,get(){let t=this.holder;return t.$f.use(t.$n)}},argumentTypes:{enumerable:!0,get(){return[]}},canInvokeWith:{enumerable:!0,value(t){return t.length===0}},clone:{enumerable:!0,value(t){throw new Error("Invalid operation")}}});function Au(t,e,n,r,o){let s=e[2]==="s"?hr:gr,i=ptr(e.substr(3)),{$f:l}=r,a,c=o.toReflectedField(n,i,s===hr?1:0);try{a=o.vaMethod("pointer",[])(o.handle,c,o.javaLangReflectField().getGenericType),o.throwIfExceptionPending()}finally{o.deleteLocalRef(c)}let d;try{d=l._getType(o.getTypeName(a))}finally{o.deleteLocalRef(a)}let p,f,u=d.type;return s===hr?(p=o.getStaticField(u),f=o.setStaticField(u)):(p=o.getField(u),f=o.setField(u)),Lu([s,d,i,p,f])}function Lu(t){return function(e){return new ds([e].concat(t))}}function ds(t){this._p=t}Object.defineProperties(ds.prototype,{value:{enumerable:!0,get(){let[t,e,n,r,o]=this._p,s=G.getEnv();s.pushLocalFrame(4);let i=null;try{let l;if(e===gr){if(l=t.$getHandle(),l===null)throw new Error("Cannot access an instance field without an instance")}else i=t.$borrowClassHandle(s),l=i.value;let a=o(s.handle,l,r);return s.throwIfExceptionPending(),n.fromJni(a,s,!0)}finally{i!==null&&i.unref(s),s.popLocalFrame(NULL)}},set(t){let[e,n,r,o,,s]=this._p,i=G.getEnv();i.pushLocalFrame(4);let l=null;try{let a;if(n===gr){if(a=e.$getHandle(),a===null)throw new Error("Cannot access an instance field without an instance")}else l=e.$borrowClassHandle(i),a=l.value;if(!r.isCompatible(t))throw new Error(`Expected value compatible with ${r.className}`);let c=r.toJni(t,i);s(i.handle,a,o,c),i.throwIfExceptionPending()}finally{l!==null&&l.unref(i),i.popLocalFrame(NULL)}}},holder:{enumerable:!0,get(){return this._p[0]}},fieldType:{enumerable:!0,get(){return this._p[1]}},fieldReturnType:{enumerable:!0,get(){return this._p[2]}},toString:{enumerable:!0,value(){let t=`Java.Field{holder: ${this.holder}, fieldType: ${this.fieldType}, fieldReturnType: ${this.fieldReturnType}, value: ${this.value}}`;return t.length<200?t:`Java.Field{ + holder: ${this.holder}, + fieldType: ${this.fieldType}, + fieldReturnType: ${this.fieldReturnType}, + value: ${this.value}, +}`.split(` +`).map(n=>n.length>200?n.slice(0,n.indexOf(" ")+1)+"...,":n).join(` +`)}}});var Gt=class t{static fromBuffer(e,n){let r=ts(n),o=r.getCanonicalPath().toString(),s=new File(o,"w");return s.write(e.buffer),s.close(),xu(o,n),new t(o,r,n)}constructor(e,n,r){this.path=e,this.file=n,this._factory=r}load(){let{_factory:e}=this,{codeCacheDir:n}=e,r=e.use("dalvik.system.DexClassLoader"),o=e.use("java.io.File"),s=this.file;if(s===null&&(s=e.use("java.io.File").$new(this.path)),!s.exists())throw new Error("File not found");o.$new(n).mkdirs(),e.loader=r.$new(s.getCanonicalPath(),n,null,e.loader),G.preventDetachDueToClassLoader()}getClassNames(){let{_factory:e}=this,n=e.use("dalvik.system.DexFile"),r=ts(e),o=n.loadDex(this.path,r.getCanonicalPath(),0),s=[],i=o.entries();for(;i.hasMoreElements();)s.push(i.nextElement().toString());return s}};function ts(t){let{cacheDir:e,tempFileNaming:n}=t,r=t.use("java.io.File"),o=r.$new(e);return o.mkdirs(),r.createTempFile(n.prefix,n.suffix+".dex",o)}function xu(t,e){e.use("java.io.File").$new(t).setWritable(!1,!1)}function Nu(){switch(ue.state){case"empty":{ue.state="pending";let t=ue.factories[0],e=t.use("java.util.HashMap"),n=t.use("java.lang.Integer");ue.loaders=e.$new(),ue.Integer=n;let r=t.loader;return r!==null&&Er(t,r),ue.state="ready",ue}case"pending":do Thread.sleep(.05);while(ue.state==="pending");return ue;case"ready":return ue}}function Er(t,e){let{factories:n,loaders:r,Integer:o}=ue,s=o.$new(n.indexOf(t));r.put(e,s);for(let i=e.getParent();i!==null&&!r.containsKey(i);i=i.getParent())r.put(i,s)}function us(t){let e=Xe.get(t);e===void 0&&(e=0),e++,Xe.set(t,e)}function ps(t){let e=Xe.get(t);if(e===void 0)throw new Error(`Thread ${t} is not ignored`);e--,e===0?Xe.delete(t):Xe.set(t,e)}function ku(t){return t.slice(t.lastIndexOf(".")+1)}function vr(t,e){let n=[],r=t.getArrayLength(e);for(let o=0;o!==r;o++){let s=t.getObjectArrayElement(e,o);try{n.push(t.getTypeName(s))}finally{t.deleteLocalRef(s)}}return n}function Mu(t){let e=t.split(".");return e[e.length-1]+".java"}var ju=4,fs=Process.pointerSize,Ir=class{ACC_PUBLIC=1;ACC_PRIVATE=2;ACC_PROTECTED=4;ACC_STATIC=8;ACC_FINAL=16;ACC_SYNCHRONIZED=32;ACC_BRIDGE=64;ACC_VARARGS=128;ACC_NATIVE=256;ACC_ABSTRACT=1024;ACC_STRICT=2048;ACC_SYNTHETIC=4096;constructor(){this.classFactory=null,this.ClassFactory=Re,this.vm=null,this.api=null,this._initialized=!1,this._apiError=null,this._wakeupHandler=null,this._pollListener=null,this._pendingMainOps=[],this._pendingVmOps=[],this._cachedIsAppProcess=null;try{this._tryInitialize()}catch{}}_tryInitialize(){if(this._initialized)return!0;if(this._apiError!==null)throw this._apiError;let e;try{e=_t(),this.api=e}catch(r){throw this._apiError=r,r}if(e===null)return!1;let n=new Ce(e);return this.vm=n,qo(n),Re._initialize(n,e),this.classFactory=new Re,this._initialized=!0,!0}_dispose(){if(this.api===null)return;let{vm:e}=this;e.perform(n=>{Re._disposeAll(n),y.dispose(n)}),Script.nextTick(()=>{Ce.dispose(e)})}get available(){return this._tryInitialize()}get androidVersion(){return ft()}synchronized(e,n){let{$h:r=e}=e;if(!(r instanceof NativePointer))throw new Error("Java.synchronized: the first argument `obj` must be either a pointer or a Java instance");let o=this.vm.getEnv();de("VM::MonitorEnter",o.monitorEnter(r));try{n()}finally{o.monitorExit(r)}}enumerateLoadedClasses(e){this._checkAvailable();let{flavor:n}=this.api;n==="jvm"?this._enumerateLoadedClassesJvm(e):n==="art"?this._enumerateLoadedClassesArt(e):this._enumerateLoadedClassesDalvik(e)}enumerateLoadedClassesSync(){let e=[];return this.enumerateLoadedClasses({onMatch(n){e.push(n)},onComplete(){}}),e}enumerateClassLoaders(e){this._checkAvailable();let{flavor:n}=this.api;if(n==="jvm")this._enumerateClassLoadersJvm(e);else if(n==="art")this._enumerateClassLoadersArt(e);else throw new Error("Enumerating class loaders is not supported on Dalvik")}enumerateClassLoadersSync(){let e=[];return this.enumerateClassLoaders({onMatch(n){e.push(n)},onComplete(){}}),e}_enumerateLoadedClassesJvm(e){let{api:n,vm:r}=this,{jvmti:o}=n,s=r.getEnv(),i=Memory.alloc(ju),l=Memory.alloc(fs);o.getLoadedClasses(i,l);let a=i.readS32(),c=l.readPointer(),d=[];for(let p=0;p!==a;p++)d.push(c.add(p*fs).readPointer());o.deallocate(c);try{for(let p of d){let f=s.getClassName(p);e.onMatch(f,p)}e.onComplete()}finally{d.forEach(p=>{s.deleteLocalRef(p)})}}_enumerateClassLoadersJvm(e){this.choose("java.lang.ClassLoader",e)}_enumerateLoadedClassesArt(e){let{vm:n,api:r}=this,o=n.getEnv(),s=r["art::JavaVMExt::AddGlobalRef"],{vm:i}=r;ye(n,o,l=>{let a=qn(c=>{let d=s(i,l,c);try{let p=o.getClassName(d);e.onMatch(p,d)}finally{o.deleteGlobalRef(d)}return!0});r["art::ClassLinker::VisitClasses"](r.artClassLinker.address,a)}),e.onComplete()}_enumerateClassLoadersArt(e){let{classFactory:n,vm:r,api:o}=this,s=r.getEnv(),i=o["art::ClassLinker::VisitClassLoaders"];if(i===void 0)throw new Error("This API is only available on Android >= 7.0");let l=n.use("java.lang.ClassLoader"),a=[],c=o["art::JavaVMExt::AddGlobalRef"],{vm:d}=o;ye(r,s,p=>{let f=Wn(u=>(a.push(c(d,p,u)),!0));Zn(()=>{i(o.artClassLinker.address,f)})});try{a.forEach(p=>{let f=n.cast(p,l);e.onMatch(f)})}finally{a.forEach(p=>{s.deleteGlobalRef(p)})}e.onComplete()}_enumerateLoadedClassesDalvik(e){let{api:n}=this,r=ptr("0xcbcacccd"),o=172,s=8,l=n.gDvm.add(o).readPointer(),a=l.readS32(),d=l.add(12).readPointer(),p=a*s;for(let f=0;f{let i=s.loader;return s.loader=i!==null?n.wrap(i,o,r):null,s})}scheduleOnMainThread(e){this.performNow(()=>{this._pendingMainOps.push(e);let{_wakeupHandler:n}=this;if(n===null){let{classFactory:r}=this,o=r.use("android.os.Handler"),s=r.use("android.os.Looper");n=o.$new(s.getMainLooper()),this._wakeupHandler=n}this._pollListener===null&&(this._pollListener=Interceptor.attach(Process.getModuleByName("libc.so").getExportByName("epoll_wait"),this._makePollHook()),Interceptor.flush()),n.sendEmptyMessage(1)})}_makePollHook(){let e=Process.id,{_pendingMainOps:n}=this;return function(){if(this.threadId!==e)return;let r;for(;(r=n.shift())!==void 0;)try{r()}catch(o){Script.nextTick(()=>{throw o})}}}perform(e){if(this._checkAvailable(),!this._isAppProcess()||this.classFactory.loader!==null)try{this.vm.perform(e)}catch(n){Script.nextTick(()=>{throw n})}else this._pendingVmOps.push(e),this._pendingVmOps.length===1&&this._performPendingVmOpsWhenReady()}performNow(e){return this._checkAvailable(),this.vm.perform(()=>{let{classFactory:n}=this;if(this._isAppProcess()&&n.loader===null){let o=n.use("android.app.ActivityThread").currentApplication();o!==null&&hs(n,o)}return e()})}_performPendingVmOpsWhenReady(){this.vm.perform(()=>{let{classFactory:e}=this,n=e.use("android.app.ActivityThread"),r=n.currentApplication();if(r!==null){hs(e,r),this._performPendingVmOps();return}let o=this,s=!1,i="early",l=n.handleBindApplication;l.implementation=function(d){if(d.instrumentationName.value!==null){i="late";let f=e.use("android.app.LoadedApk").makeApplication;f.implementation=function(u,_){return s||(s=!0,_s(e,this),o._performPendingVmOps()),f.apply(this,arguments)}}l.apply(this,arguments)};let c=n.getPackageInfo.overloads.map(d=>[d.argumentTypes.length,d]).sort(([d],[p])=>p-d).map(([d,p])=>p)[0];c.implementation=function(...d){let p=c.call(this,...d);return!s&&i==="early"&&(s=!0,_s(e,p),o._performPendingVmOps()),p}})}_performPendingVmOps(){let{vm:e,_pendingVmOps:n}=this,r;for(;(r=n.shift())!==void 0;)try{e.perform(r)}catch(o){Script.nextTick(()=>{throw o})}}use(e,n){return this.classFactory.use(e,n)}openClassFile(e){return this.classFactory.openClassFile(e)}choose(e,n){this.classFactory.choose(e,n)}retain(e){return this.classFactory.retain(e)}cast(e,n){return this.classFactory.cast(e,n)}array(e,n){return this.classFactory.array(e,n)}backtrace(e){return Kn(this.vm,e)}isMainThread(){let e=this.classFactory.use("android.os.Looper"),n=e.getMainLooper(),r=e.myLooper();return r===null?!1:n.$isSameObject(r)}registerClass(e){return this.classFactory.registerClass(e)}deoptimizeEverything(){let{vm:e}=this;return er(e,e.getEnv())}deoptimizeBootImage(){let{vm:e}=this;return tr(e,e.getEnv())}deoptimizeMethod(e){let{vm:n}=this;return Xn(n,n.getEnv(),e)}_checkAvailable(){if(!this.available)throw new Error("Java API not available")}_isAppProcess(){let e=this._cachedIsAppProcess;if(e===null){if(this.api.flavor==="jvm")return e=!1,this._cachedIsAppProcess=e,e;let n=new NativeFunction(Module.getGlobalExportByName("readlink"),"pointer",["pointer","pointer","pointer"],{exceptions:"propagate"}),r=Memory.allocUtf8String("/proc/self/exe"),o=1024,s=Memory.alloc(o),i=n(r,s,ptr(o)).toInt32();if(i!==-1){let l=s.readUtf8String(i);e=/^\/system\/bin\/app_process/.test(l)}else e=!0;this._cachedIsAppProcess=e}return e}};function hs(t,e){let n=t.use("android.os.Process");t.loader=e.getClassLoader(),n.myUid()===n.SYSTEM_UID.value?(t.cacheDir="/data/system",t.codeCacheDir="/data/dalvik-cache"):"getCodeCacheDir"in e?(t.cacheDir=e.getCacheDir().getCanonicalPath(),t.codeCacheDir=e.getCodeCacheDir().getCanonicalPath()):(t.cacheDir=e.getFilesDir().getCanonicalPath(),t.codeCacheDir=e.getCacheDir().getCanonicalPath())}function _s(t,e){let n=t.use("java.io.File");t.loader=e.getClassLoader();let r=n.$new(e.getDataDir()).getCanonicalPath();t.cacheDir=r,t.codeCacheDir=r+"/cache"}var Cr=new Ir;Script.bindWeak(Cr,()=>{Cr._dispose()});var Se=Cr;var Tr="top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry",ms=40,gs=250,Ae=null,et=null;function Ou(){try{return Se.use(Tr)}catch{let e=null;return Se.enumerateClassLoaders({onMatch(n){if(e===null)try{n.loadClass(Tr),e=Se.ClassFactory.get(n).use(Tr)}catch{}},onComplete(){}}),e}}function bs(t){Se.perform(()=>{if(Ae=Ou(),Ae!==null&&(et=Ae.getGuestClassLoader(),et!==null)){Se.classFactory.loader=et,console.log("[FridaBox] package="+Ae.getGuestPackageName()),console.log("[FridaBox] process="+Ae.getGuestProcessName()),console.log("[FridaBox] userId="+Ae.getGuestUserId()),console.log("[FridaBox] virtualProcessId="+Ae.getVirtualProcessId()),console.log("[FridaBox] source="+Ae.getGuestSourceDir()),console.log("[FridaBox] ClassLoader="+et.toString());return}t+1bs(t+1),gs):console.error("[FridaBox] guest ClassLoader unavailable after "+ms*gs+" ms")})}bs(0);rpc.exports={info(){return Se.performNow(()=>Ae===null?{error:"registry unavailable"}:JSON.parse(Ae.describe()))},useclass(t){return Se.performNow(()=>{if(et===null)throw new Error("guest ClassLoader is not ready");return Se.classFactory.loader=et,Se.use(t).$className})},enumerateloadedclasses(t){let e=t||"";return Se.performNow(()=>Se.enumerateLoadedClassesSync().filter(n=>n.indexOf(e)===0))},enumeratemodules(){return Process.enumerateModules().map(t=>({name:t.name,base:t.base.toString(),path:t.path}))}}; diff --git a/scripts/dist/registry-probe.js b/scripts/dist/registry-probe.js new file mode 100644 index 0000000..95e8877 --- /dev/null +++ b/scripts/dist/registry-probe.js @@ -0,0 +1,1887 @@ +📦 +236053 /scripts/registry-probe.js +✄ +var _i=Object.defineProperty;var mi=(t,e)=>{for(var n in e)_i(t,n,{get:e[n],enumerable:!0})};var we=[],be=[],Gt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(let t=0,e=Gt.length;t0)throw new Error("Invalid string. Length must be a multiple of 4");let n=t.indexOf("=");n===-1&&(n=e);let r=n===e?0:4-n%4;return[n,r]}function bi(t,e,n){return(e+n)*3/4-n}function Cr(t){let e=gi(t),n=e[0],r=e[1],o=new Uint8Array(bi(t,n,r)),i=0,s=r>0?n-4:n,c;for(c=0;c>16&255,o[i++]=a>>8&255,o[i++]=a&255}if(r===2){let a=be[t.charCodeAt(c)]<<2|be[t.charCodeAt(c+1)]>>4;o[i++]=a&255}if(r===1){let a=be[t.charCodeAt(c)]<<10|be[t.charCodeAt(c+1)]<<4|be[t.charCodeAt(c+2)]>>2;o[i++]=a>>8&255,o[i++]=a&255}return o}function yi(t){return we[t>>18&63]+we[t>>12&63]+we[t>>6&63]+we[t&63]}function Ei(t,e,n){let r=[];for(let o=e;os?s:i+o));if(n===1){let i=t[e-1];r.push(we[i>>2]+we[i<<4&63]+"==")}else if(n===2){let i=(t[e-2]<<8)+t[e-1];r.push(we[i>>10]+we[i>>4&63]+we[i<<2&63]+"=")}return r.join("")}function et(t,e,n,r,o){let i,s,c=o*8-r-1,a=(1<>1,d=-7,p=n?o-1:0,f=n?-1:1,u=t[e+p];for(p+=f,i=u&(1<<-d)-1,u>>=-d,d+=c;d>0;)i=i*256+t[e+p],p+=f,d-=8;for(s=i&(1<<-d)-1,i>>=-d,d+=r;d>0;)s=s*256+t[e+p],p+=f,d-=8;if(i===0)i=1-l;else{if(i===a)return s?NaN:(u?-1:1)*(1/0);s=s+Math.pow(2,r),i=i-l}return(u?-1:1)*s*Math.pow(2,i-r)}function Ht(t,e,n,r,o,i){let s,c,a,l=i*8-o-1,d=(1<>1,f=o===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=r?0:i-1,_=r?1:-1,h=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(c=isNaN(e)?1:0,s=d):(s=Math.floor(Math.log(e)/Math.LN2),e*(a=Math.pow(2,-s))<1&&(s--,a*=2),s+p>=1?e+=f/a:e+=f*Math.pow(2,1-p),e*a>=2&&(s++,a/=2),s+p>=d?(c=0,s=d):s+p>=1?(c=(e*a-1)*Math.pow(2,o),s=s+p):(c=e*Math.pow(2,p-1)*Math.pow(2,o),s=0));o>=8;)t[n+u]=c&255,u+=_,c/=256,o-=8;for(s=s<0;)t[n+u]=s&255,u+=_,s/=256,l-=8;t[n+u-_]|=h*128}var wi={INSPECT_MAX_BYTES:50},Zt=2147483647;m.TYPED_ARRAY_SUPPORT=!0;Object.defineProperty(m.prototype,"parent",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.buffer}});Object.defineProperty(m.prototype,"offset",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.byteOffset}});function Ae(t){if(t>Zt)throw new RangeError('The value "'+t+'" is invalid for option "size"');let e=new Uint8Array(t);return Object.setPrototypeOf(e,m.prototype),e}function m(t,e,n){if(typeof t=="number"){if(typeof e=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return Qt(t)}return xr(t,e,n)}m.poolSize=8192;function xr(t,e,n){if(typeof t=="string")return Ci(t,e);if(ArrayBuffer.isView(t))return Ti(t);if(t==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(t instanceof ArrayBuffer||t&&t.buffer instanceof ArrayBuffer||t instanceof SharedArrayBuffer||t&&t.buffer instanceof SharedArrayBuffer)return Wt(t,e,n);if(typeof t=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');let r=t.valueOf&&t.valueOf();if(r!=null&&r!==t)return m.from(r,e,n);let o=Ai(t);if(o)return o;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof t[Symbol.toPrimitive]=="function")return m.from(t[Symbol.toPrimitive]("string"),e,n);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t)}m.from=function(t,e,n){return xr(t,e,n)};Object.setPrototypeOf(m.prototype,Uint8Array.prototype);Object.setPrototypeOf(m,Uint8Array);function Nr(t){if(typeof t!="number")throw new TypeError('"size" argument must be of type number');if(t<0)throw new RangeError('The value "'+t+'" is invalid for option "size"')}function Ii(t,e,n){return Nr(t),t<=0?Ae(t):e!==void 0?typeof n=="string"?Ae(t).fill(e,n):Ae(t).fill(e):Ae(t)}m.alloc=function(t,e,n){return Ii(t,e,n)};function Qt(t){return Nr(t),Ae(t<0?0:Yt(t)|0)}m.allocUnsafe=function(t){return Qt(t)};m.allocUnsafeSlow=function(t){return Qt(t)};function Ci(t,e){if((typeof e!="string"||e==="")&&(e="utf8"),!m.isEncoding(e))throw new TypeError("Unknown encoding: "+e);let n=kr(t,e)|0,r=Ae(n),o=r.write(t,e);return o!==n&&(r=r.slice(0,o)),r}function qt(t){let e=t.length<0?0:Yt(t.length)|0,n=Ae(e);for(let r=0;r=Zt)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+Zt.toString(16)+" bytes");return t|0}m.isBuffer=function(e){return e!=null&&e._isBuffer===!0&&e!==m.prototype};m.compare=function(e,n){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),n instanceof Uint8Array&&(n=m.from(n,n.offset,n.byteLength)),!m.isBuffer(e)||!m.isBuffer(n))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(e===n)return 0;let r=e.length,o=n.length;for(let i=0,s=Math.min(r,o);io.length?(m.isBuffer(s)||(s=m.from(s.buffer,s.byteOffset,s.byteLength)),s.copy(o,i)):Uint8Array.prototype.set.call(o,s,i);else if(m.isBuffer(s))s.copy(o,i);else throw new TypeError('"list" argument must be an Array of Buffers');i+=s.length}return o};function kr(t,e){if(m.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t.byteLength;if(typeof t!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);let n=t.length,r=arguments.length>2&&arguments[2]===!0;if(!r&&n===0)return 0;let o=!1;for(;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return Kt(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return n*2;case"hex":return n>>>1;case"base64":return Br(t).length;default:if(o)return r?-1:Kt(t).length;e=(""+e).toLowerCase(),o=!0}}m.byteLength=kr;function Li(t,e,n){let r=!1;if((e===void 0||e<0)&&(e=0),e>this.length||((n===void 0||n>this.length)&&(n=this.length),n<=0)||(n>>>=0,e>>>=0,n<=e))return"";for(t||(t="utf8");;)switch(t){case"hex":return Di(this,e,n);case"utf8":case"utf-8":return jr(this,e,n);case"ascii":return Pi(this,e,n);case"latin1":case"binary":return Fi(this,e,n);case"base64":return Oi(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ui(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}m.prototype._isBuffer=!0;function Re(t,e,n){let r=t[e];t[e]=t[n],t[n]=r}m.prototype.swap16=function(){let e=this.length;if(e%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let n=0;nn&&(e+=" ... "),""};m.prototype[Symbol.for("nodejs.util.inspect.custom")]=m.prototype.inspect;m.prototype.compare=function(e,n,r,o,i){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),!m.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(n===void 0&&(n=0),r===void 0&&(r=e?e.length:0),o===void 0&&(o=0),i===void 0&&(i=this.length),n<0||r>e.length||o<0||i>this.length)throw new RangeError("out of range index");if(o>=i&&n>=r)return 0;if(o>=i)return-1;if(n>=r)return 1;if(n>>>=0,r>>>=0,o>>>=0,i>>>=0,this===e)return 0;let s=i-o,c=r-n,a=Math.min(s,c),l=this.slice(o,i),d=e.slice(n,r);for(let p=0;p2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,Number.isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0)if(o)n=0;else return-1;if(typeof e=="string"&&(e=m.from(e,r)),m.isBuffer(e))return e.length===0?-1:Tr(t,e,n,r,o);if(typeof e=="number")return e=e&255,typeof Uint8Array.prototype.indexOf=="function"?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):Tr(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function Tr(t,e,n,r,o){let i=1,s=t.length,c=e.length;if(r!==void 0&&(r=String(r).toLowerCase(),r==="ucs2"||r==="ucs-2"||r==="utf16le"||r==="utf-16le")){if(t.length<2||e.length<2)return-1;i=2,s/=2,c/=2,n/=2}function a(d,p){return i===1?d[p]:d.readUInt16BE(p*i)}let l;if(o){let d=-1;for(l=n;ls&&(n=s-c),l=n;l>=0;l--){let d=!0;for(let p=0;po&&(r=o)):r=o;let i=e.length;r>i/2&&(r=i/2);let s;for(s=0;s>>0,isFinite(r)?(r=r>>>0,o===void 0&&(o="utf8")):(o=r,r=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let i=this.length-n;if((r===void 0||r>i)&&(r=i),e.length>0&&(r<0||n<0)||n>this.length)throw new RangeError("Attempt to write outside buffer bounds");o||(o="utf8");let s=!1;for(;;)switch(o){case"hex":return xi(this,e,n,r);case"utf8":case"utf-8":return Ni(this,e,n,r);case"ascii":case"latin1":case"binary":return ki(this,e,n,r);case"base64":return Mi(this,e,n,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ji(this,e,n,r);default:if(s)throw new TypeError("Unknown encoding: "+o);o=(""+o).toLowerCase(),s=!0}};m.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Oi(t,e,n){return e===0&&n===t.length?$t(t):$t(t.slice(e,n))}function jr(t,e,n){n=Math.min(t.length,n);let r=[],o=e;for(;o239?4:i>223?3:i>191?2:1;if(o+c<=n){let a,l,d,p;switch(c){case 1:i<128&&(s=i);break;case 2:a=t[o+1],(a&192)===128&&(p=(i&31)<<6|a&63,p>127&&(s=p));break;case 3:a=t[o+1],l=t[o+2],(a&192)===128&&(l&192)===128&&(p=(i&15)<<12|(a&63)<<6|l&63,p>2047&&(p<55296||p>57343)&&(s=p));break;case 4:a=t[o+1],l=t[o+2],d=t[o+3],(a&192)===128&&(l&192)===128&&(d&192)===128&&(p=(i&15)<<18|(a&63)<<12|(l&63)<<6|d&63,p>65535&&p<1114112&&(s=p))}}s===null?(s=65533,c=1):s>65535&&(s-=65536,r.push(s>>>10&1023|55296),s=56320|s&1023),r.push(s),o+=c}return Ri(r)}var Ar=4096;function Ri(t){let e=t.length;if(e<=Ar)return String.fromCharCode.apply(String,t);let n="",r=0;for(;rr)&&(n=r);let o="";for(let i=e;ir&&(e=r),n<0?(n+=r,n<0&&(n=0)):n>r&&(n=r),nn)throw new RangeError("Trying to access beyond buffer length")}m.prototype.readUintLE=m.prototype.readUIntLE=function(e,n,r){e=e>>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e],i=1,s=0;for(;++s>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e+--n],i=1;for(;n>0&&(i*=256);)o+=this[e+--n]*i;return o};m.prototype.readUint8=m.prototype.readUInt8=function(e,n){return e=e>>>0,n||se(e,1,this.length),this[e]};m.prototype.readUint16LE=m.prototype.readUInt16LE=function(e,n){return e=e>>>0,n||se(e,2,this.length),this[e]|this[e+1]<<8};m.prototype.readUint16BE=m.prototype.readUInt16BE=function(e,n){return e=e>>>0,n||se(e,2,this.length),this[e]<<8|this[e+1]};m.prototype.readUint32LE=m.prototype.readUInt32LE=function(e,n){return e=e>>>0,n||se(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+this[e+3]*16777216};m.prototype.readUint32BE=m.prototype.readUInt32BE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]*16777216+(this[e+1]<<16|this[e+2]<<8|this[e+3])};m.prototype.readBigUInt64LE=function(e){e=e>>>0,Ge(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&tt(e,this.length-8);let o=n+this[++e]*2**8+this[++e]*2**16+this[++e]*2**24,i=this[++e]+this[++e]*2**8+this[++e]*2**16+r*2**24;return BigInt(o)+(BigInt(i)<>>0,Ge(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&tt(e,this.length-8);let o=n*2**24+this[++e]*2**16+this[++e]*2**8+this[++e],i=this[++e]*2**24+this[++e]*2**16+this[++e]*2**8+r;return(BigInt(o)<>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e],i=1,s=0;for(;++s=i&&(o-=Math.pow(2,8*n)),o};m.prototype.readIntBE=function(e,n,r){e=e>>>0,n=n>>>0,r||se(e,n,this.length);let o=n,i=1,s=this[e+--o];for(;o>0&&(i*=256);)s+=this[e+--o]*i;return i*=128,s>=i&&(s-=Math.pow(2,8*n)),s};m.prototype.readInt8=function(e,n){return e=e>>>0,n||se(e,1,this.length),this[e]&128?(255-this[e]+1)*-1:this[e]};m.prototype.readInt16LE=function(e,n){e=e>>>0,n||se(e,2,this.length);let r=this[e]|this[e+1]<<8;return r&32768?r|4294901760:r};m.prototype.readInt16BE=function(e,n){e=e>>>0,n||se(e,2,this.length);let r=this[e+1]|this[e]<<8;return r&32768?r|4294901760:r};m.prototype.readInt32LE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24};m.prototype.readInt32BE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]};m.prototype.readBigInt64LE=function(e){e=e>>>0,Ge(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&tt(e,this.length-8);let o=this[e+4]+this[e+5]*2**8+this[e+6]*2**16+(r<<24);return(BigInt(o)<>>0,Ge(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&tt(e,this.length-8);let o=(n<<24)+this[++e]*2**16+this[++e]*2**8+this[++e];return(BigInt(o)<>>0,n||se(e,4,this.length),et(this,e,!0,23,4)};m.prototype.readFloatBE=function(e,n){return e=e>>>0,n||se(e,4,this.length),et(this,e,!1,23,4)};m.prototype.readDoubleLE=function(e,n){return e=e>>>0,n||se(e,8,this.length),et(this,e,!0,52,8)};m.prototype.readDoubleBE=function(e,n){return e=e>>>0,n||se(e,8,this.length),et(this,e,!1,52,8)};function pe(t,e,n,r,o,i){if(!m.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||et.length)throw new RangeError("Index out of range")}m.prototype.writeUintLE=m.prototype.writeUIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,r=r>>>0,!o){let c=Math.pow(2,8*r)-1;pe(this,e,n,r,c,0)}let i=1,s=0;for(this[n]=e&255;++s>>0,r=r>>>0,!o){let c=Math.pow(2,8*r)-1;pe(this,e,n,r,c,0)}let i=r-1,s=1;for(this[n+i]=e&255;--i>=0&&(s*=256);)this[n+i]=e/s&255;return n+r};m.prototype.writeUint8=m.prototype.writeUInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,255,0),this[n]=e&255,n+1};m.prototype.writeUint16LE=m.prototype.writeUInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeUint16BE=m.prototype.writeUInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeUint32LE=m.prototype.writeUInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n+3]=e>>>24,this[n+2]=e>>>16,this[n+1]=e>>>8,this[n]=e&255,n+4};m.prototype.writeUint32BE=m.prototype.writeUInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};function Or(t,e,n,r,o){Ur(e,r,o,t,n,7);let i=Number(e&BigInt(4294967295));t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i;let s=Number(e>>BigInt(32)&BigInt(4294967295));return t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s,n}function Rr(t,e,n,r,o){Ur(e,r,o,t,n,7);let i=Number(e&BigInt(4294967295));t[n+7]=i,i=i>>8,t[n+6]=i,i=i>>8,t[n+5]=i,i=i>>8,t[n+4]=i;let s=Number(e>>BigInt(32)&BigInt(4294967295));return t[n+3]=s,s=s>>8,t[n+2]=s,s=s>>8,t[n+1]=s,s=s>>8,t[n]=s,n+8}m.prototype.writeBigUInt64LE=function(e,n=0){return Or(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeBigUInt64BE=function(e,n=0){return Rr(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let i=0,s=1,c=0;for(this[n]=e&255;++i>0)-c&255;return n+r};m.prototype.writeIntBE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let i=r-1,s=1,c=0;for(this[n+i]=e&255;--i>=0&&(s*=256);)e<0&&c===0&&this[n+i+1]!==0&&(c=1),this[n+i]=(e/s>>0)-c&255;return n+r};m.prototype.writeInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,127,-128),e<0&&(e=255+e+1),this[n]=e&255,n+1};m.prototype.writeInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),this[n]=e&255,this[n+1]=e>>>8,this[n+2]=e>>>16,this[n+3]=e>>>24,n+4};m.prototype.writeInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};m.prototype.writeBigInt64LE=function(e,n=0){return Or(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};m.prototype.writeBigInt64BE=function(e,n=0){return Rr(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};function Pr(t,e,n,r,o,i){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function Fr(t,e,n,r,o){return e=+e,n=n>>>0,o||Pr(t,e,n,4,34028234663852886e22,-34028234663852886e22),Ht(t,e,n,r,23,4),n+4}m.prototype.writeFloatLE=function(e,n,r){return Fr(this,e,n,!0,r)};m.prototype.writeFloatBE=function(e,n,r){return Fr(this,e,n,!1,r)};function Dr(t,e,n,r,o){return e=+e,n=n>>>0,o||Pr(t,e,n,8,17976931348623157e292,-17976931348623157e292),Ht(t,e,n,r,52,8),n+8}m.prototype.writeDoubleLE=function(e,n,r){return Dr(this,e,n,!0,r)};m.prototype.writeDoubleBE=function(e,n,r){return Dr(this,e,n,!1,r)};m.prototype.copy=function(e,n,r,o){if(!m.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r||(r=0),!o&&o!==0&&(o=this.length),n>=e.length&&(n=e.length),n||(n=0),o>0&&o=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-n>>0,r=r===void 0?this.length:r>>>0,e||(e=0);let i;if(typeof e=="number")for(i=n;i2**32?o=Lr(String(n)):typeof n=="bigint"&&(o=String(n),(n>BigInt(2)**BigInt(32)||n<-(BigInt(2)**BigInt(32)))&&(o=Lr(o)),o+="n"),r+=` It must be ${e}. Received ${o}`,r},RangeError);function Lr(t){let e="",n=t.length,r=t[0]==="-"?1:0;for(;n>=r+4;n-=3)e=`_${t.slice(n-3,n)}${e}`;return`${t.slice(0,n)}${e}`}function Bi(t,e,n){Ge(e,"offset"),(t[e]===void 0||t[e+n]===void 0)&&tt(e,t.length-(n+1))}function Ur(t,e,n,r,o,i){if(t>n||t3?e===0||e===BigInt(0)?c=`>= 0${s} and < 2${s} ** ${(i+1)*8}${s}`:c=`>= -(2${s} ** ${(i+1)*8-1}${s}) and < 2 ** ${(i+1)*8-1}${s}`:c=`>= ${e}${s} and <= ${n}${s}`,new Je.ERR_OUT_OF_RANGE("value",c,t)}Bi(r,o,i)}function Ge(t,e){if(typeof t!="number")throw new Je.ERR_INVALID_ARG_TYPE(e,"number",t)}function tt(t,e,n){throw Math.floor(t)!==t?(Ge(t,n),new Je.ERR_OUT_OF_RANGE(n||"offset","an integer",t)):e<0?new Je.ERR_BUFFER_OUT_OF_BOUNDS:new Je.ERR_OUT_OF_RANGE(n||"offset",`>= ${n?1:0} and <= ${e}`,t)}var zi=/[^+/0-9A-Za-z-_]/g;function Vi(t){if(t=t.split("=")[0],t=t.trim().replace(zi,""),t.length<2)return"";for(;t.length%4!==0;)t=t+"=";return t}function Kt(t,e){e=e||1/0;let n,r=t.length,o=null,i=[];for(let s=0;s55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&i.push(239,191,189);continue}else if(s+1===r){(e-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&i.push(239,191,189),o=n;continue}n=(o-55296<<10|n-56320)+65536}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;i.push(n)}else if(n<2048){if((e-=2)<0)break;i.push(n>>6|192,n&63|128)}else if(n<65536){if((e-=3)<0)break;i.push(n>>12|224,n>>6&63|128,n&63|128)}else if(n<1114112){if((e-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,n&63|128)}else throw new Error("Invalid code point")}return i}function Ji(t){let e=[];for(let n=0;n>8,o=n%256,i.push(o),i.push(r);return i}function Br(t){return Cr(Vi(t))}function yt(t,e,n,r){let o;for(o=0;o=e.length||o>=t.length);++o)e[o+n]=t[o];return o}var $i=function(){let t="0123456789abcdef",e=new Array(256);for(let n=0;n<16;++n){let r=n*16;for(let o=0;o<16;++o)e[r+o]=t[n]+t[o]}return e}();var Dt={};mi(Dt,{ArtMethod:()=>Nt,ArtStackVisitor:()=>jn,DVM_JNI_ENV_OFFSET_SELF:()=>co,HandleVector:()=>ct,VariableSizedHandleScope:()=>lt,backtrace:()=>qn,deoptimizeBootImage:()=>Xn,deoptimizeEverything:()=>Yn,deoptimizeMethod:()=>Qn,ensureClassInitialized:()=>hc,getAndroidApiLevel:()=>ee,getAndroidVersion:()=>dt,getApi:()=>J,getArtApexVersion:()=>zn,getArtClassSpec:()=>Jn,getArtFieldSpec:()=>Pt,getArtMethodSpec:()=>_e,getArtThreadFromEnv:()=>Ft,getArtThreadSpec:()=>Ze,makeArtClassLoaderVisitor:()=>Zn,makeArtClassVisitor:()=>Hn,makeMethodMangler:()=>al,makeObjectVisitorPredicate:()=>tr,revertGlobalPatches:()=>Wn,translateMethod:()=>cl,withAllArtThreadsSuspended:()=>$n,withRunnableArtThread:()=>ye});var{pageSize:en,pointerSize:Hi}=Process,tn=class{constructor(e){this.sliceSize=e,this.slicesPerPage=en/e,this.pages=[],this.free=[]}allocateSlice(e,n){let r=e.near===void 0,o=n===1;if(r&&o){let i=this.free.pop();if(i!==void 0)return i}else if(n{n.deleteGlobalRef(e)})}}y.prototype.fromReflectedMethod=x(7,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.fromReflectedField=x(8,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.toReflectedMethod=x(9,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getSuperclass=x(10,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isAssignableFrom=x(11,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.toReflectedField=x(12,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.throw=x(13,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.exceptionOccurred=x(15,"pointer",["pointer"],function(t){return t(this.handle)});y.prototype.exceptionDescribe=x(16,"void",["pointer"],function(t){t(this.handle)});y.prototype.exceptionClear=x(17,"void",["pointer"],function(t){t(this.handle)});y.prototype.pushLocalFrame=x(19,"int32",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.popLocalFrame=x(20,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newGlobalRef=x(21,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.deleteGlobalRef=x(22,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.deleteLocalRef=x(23,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.isSameObject=x(24,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.newLocalRef=x(25,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.allocObject=x(27,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectClass=x(31,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isInstanceOf=x(32,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.getMethodId=x(33,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getFieldId=x(94,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getIntField=x(100,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStaticMethodId=x(113,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticFieldId=x(144,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticIntField=x(150,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStringLength=x(164,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getStringChars=x(165,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringChars=x(166,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.newStringUtf=x(167,"pointer",["pointer","pointer"],function(t,e){let n=Memory.allocUtf8String(e);return t(this.handle,n)});y.prototype.getStringUtfChars=x(169,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringUtfChars=x(170,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.getArrayLength=x(171,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newObjectArray=x(172,"pointer",["pointer","int32","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getObjectArrayElement=x(173,"pointer",["pointer","pointer","int32"],function(t,e,n){return t(this.handle,e,n)});y.prototype.setObjectArrayElement=x(174,"void",["pointer","pointer","int32","pointer"],function(t,e,n,r){t(this.handle,e,n,r)});y.prototype.newBooleanArray=x(175,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newByteArray=x(176,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newCharArray=x(177,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newShortArray=x(178,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newIntArray=x(179,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newLongArray=x(180,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newFloatArray=x(181,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newDoubleArray=x(182,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.getBooleanArrayElements=x(183,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getByteArrayElements=x(184,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getCharArrayElements=x(185,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getShortArrayElements=x(186,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getIntArrayElements=x(187,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getLongArrayElements=x(188,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getFloatArrayElements=x(189,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getDoubleArrayElements=x(190,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseBooleanArrayElements=x(191,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseByteArrayElements=x(192,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseCharArrayElements=x(193,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseShortArrayElements=x(194,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseIntArrayElements=x(195,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseLongArrayElements=x(196,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseFloatArrayElements=x(197,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseDoubleArrayElements=x(198,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.getByteArrayRegion=x(200,"void",["pointer","pointer","int","int","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setBooleanArrayRegion=x(207,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setByteArrayRegion=x(208,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setCharArrayRegion=x(209,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setShortArrayRegion=x(210,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setIntArrayRegion=x(211,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setLongArrayRegion=x(212,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setFloatArrayRegion=x(213,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setDoubleArrayRegion=x(214,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.registerNatives=x(215,"int32",["pointer","pointer","pointer","int32"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.monitorEnter=x(217,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.monitorExit=x(218,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getDirectBufferAddress=x(230,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectRefType=x(232,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});var Vr=new Map;function It(t,e,n,r){return gn(this,"p",ga,t,e,n,r)}function mn(t,e,n,r){return gn(this,"v",ba,t,e,n,r)}function ma(t,e,n,r){return gn(this,"n",ya,t,e,n,r)}function gn(t,e,n,r,o,i,s){if(s!==void 0)return n(t,r,o,i,s);let c=[r,e,o].concat(i).join("|"),a=Vr.get(c);return a===void 0&&(a=n(t,r,o,i,Jr),Vr.set(c,a)),a}function ga(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer"].concat(r),o)}function ba(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer","..."].concat(r),o)}function ya(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer","pointer","..."].concat(r),o)}y.prototype.constructor=function(t,e){return mn.call(this,Wi,"pointer",t,e)};y.prototype.vaMethod=function(t,e,n){let r=ca[t];if(r===void 0)throw new Error("Unsupported type: "+t);return mn.call(this,r,t,e,n)};y.prototype.nonvirtualVaMethod=function(t,e,n){let r=la[t];if(r===void 0)throw new Error("Unsupported type: "+t);return ma.call(this,r,t,e,n)};y.prototype.staticVaMethod=function(t,e,n){let r=da[t];if(r===void 0)throw new Error("Unsupported type: "+t);return mn.call(this,r,t,e,n)};y.prototype.getField=function(t){let e=ua[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,t,[])};y.prototype.getStaticField=function(t){let e=fa[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,t,[])};y.prototype.setField=function(t){let e=pa[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,"void",[t])};y.prototype.setStaticField=function(t){let e=ha[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,"void",[t])};var on=null;y.prototype.javaLangClass=function(){if(on===null){let t=this.findClass("java/lang/Class");try{let e=this.getMethodId.bind(this,t);on={handle:Pe(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getSimpleName:e("getSimpleName","()Ljava/lang/String;"),getGenericSuperclass:e("getGenericSuperclass","()Ljava/lang/reflect/Type;"),getDeclaredConstructors:e("getDeclaredConstructors","()[Ljava/lang/reflect/Constructor;"),getDeclaredMethods:e("getDeclaredMethods","()[Ljava/lang/reflect/Method;"),getDeclaredFields:e("getDeclaredFields","()[Ljava/lang/reflect/Field;"),isArray:e("isArray","()Z"),isPrimitive:e("isPrimitive","()Z"),isInterface:e("isInterface","()Z"),getComponentType:e("getComponentType","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return on};var sn=null;y.prototype.javaLangObject=function(){if(sn===null){let t=this.findClass("java/lang/Object");try{let e=this.getMethodId.bind(this,t);sn={handle:Pe(this.newGlobalRef(t)),toString:e("toString","()Ljava/lang/String;"),getClass:e("getClass","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return sn};var an=null;y.prototype.javaLangReflectConstructor=function(){if(an===null){let t=this.findClass("java/lang/reflect/Constructor");try{an={getGenericParameterTypes:this.getMethodId(t,"getGenericParameterTypes","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return an};var cn=null;y.prototype.javaLangReflectMethod=function(){if(cn===null){let t=this.findClass("java/lang/reflect/Method");try{let e=this.getMethodId.bind(this,t);cn={getName:e("getName","()Ljava/lang/String;"),getGenericParameterTypes:e("getGenericParameterTypes","()[Ljava/lang/reflect/Type;"),getParameterTypes:e("getParameterTypes","()[Ljava/lang/Class;"),getGenericReturnType:e("getGenericReturnType","()Ljava/lang/reflect/Type;"),getGenericExceptionTypes:e("getGenericExceptionTypes","()[Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),isVarArgs:e("isVarArgs","()Z")}}finally{this.deleteLocalRef(t)}}return cn};var ln=null;y.prototype.javaLangReflectField=function(){if(ln===null){let t=this.findClass("java/lang/reflect/Field");try{let e=this.getMethodId.bind(this,t);ln={getName:e("getName","()Ljava/lang/String;"),getType:e("getType","()Ljava/lang/Class;"),getGenericType:e("getGenericType","()Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),toString:e("toString","()Ljava/lang/String;")}}finally{this.deleteLocalRef(t)}}return ln};var dn=null;y.prototype.javaLangReflectTypeVariable=function(){if(dn===null){let t=this.findClass("java/lang/reflect/TypeVariable");try{let e=this.getMethodId.bind(this,t);dn={handle:Pe(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getBounds:e("getBounds","()[Ljava/lang/reflect/Type;"),getGenericDeclaration:e("getGenericDeclaration","()Ljava/lang/reflect/GenericDeclaration;")}}finally{this.deleteLocalRef(t)}}return dn};var un=null;y.prototype.javaLangReflectWildcardType=function(){if(un===null){let t=this.findClass("java/lang/reflect/WildcardType");try{let e=this.getMethodId.bind(this,t);un={handle:Pe(this.newGlobalRef(t)),getLowerBounds:e("getLowerBounds","()[Ljava/lang/reflect/Type;"),getUpperBounds:e("getUpperBounds","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return un};var pn=null;y.prototype.javaLangReflectGenericArrayType=function(){if(pn===null){let t=this.findClass("java/lang/reflect/GenericArrayType");try{pn={handle:Pe(this.newGlobalRef(t)),getGenericComponentType:this.getMethodId(t,"getGenericComponentType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return pn};var fn=null;y.prototype.javaLangReflectParameterizedType=function(){if(fn===null){let t=this.findClass("java/lang/reflect/ParameterizedType");try{let e=this.getMethodId.bind(this,t);fn={handle:Pe(this.newGlobalRef(t)),getActualTypeArguments:e("getActualTypeArguments","()[Ljava/lang/reflect/Type;"),getRawType:e("getRawType","()Ljava/lang/reflect/Type;"),getOwnerType:e("getOwnerType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return fn};var hn=null;y.prototype.javaLangString=function(){if(hn===null){let t=this.findClass("java/lang/String");try{hn={handle:Pe(this.newGlobalRef(t))}}finally{this.deleteLocalRef(t)}}return hn};y.prototype.getClassName=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangClass().getName);try{return this.stringFromJni(e)}finally{this.deleteLocalRef(e)}};y.prototype.getObjectClassName=function(t){let e=this.getObjectClass(t);try{return this.getClassName(e)}finally{this.deleteLocalRef(e)}};y.prototype.getActualTypeArgument=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangReflectParameterizedType().getActualTypeArguments);if(this.throwIfExceptionPending(),!e.isNull())try{return this.getTypeNameFromFirstTypeElement(e)}finally{this.deleteLocalRef(e)}};y.prototype.getTypeNameFromFirstTypeElement=function(t){if(this.getArrayLength(t)>0){let n=this.getObjectArrayElement(t,0);try{return this.getTypeName(n)}finally{this.deleteLocalRef(n)}}else return"java.lang.Object"};y.prototype.getTypeName=function(t,e){let n=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle))return this.getArrayTypeName(t);if(this.isInstanceOf(t,this.javaLangReflectParameterizedType().handle)){let r=n(this.handle,t,this.javaLangReflectParameterizedType().getRawType);this.throwIfExceptionPending();let o;try{o=this.getTypeName(r)}finally{this.deleteLocalRef(r)}return e&&(o+="<"+this.getActualTypeArgument(t)+">"),o}else return this.isInstanceOf(t,this.javaLangReflectTypeVariable().handle)||this.isInstanceOf(t,this.javaLangReflectWildcardType().handle),"java.lang.Object"};y.prototype.getArrayTypeName=function(t){let e=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle)){let n=e(this.handle,t,this.javaLangReflectGenericArrayType().getGenericComponentType);this.throwIfExceptionPending();try{return"[L"+this.getTypeName(n)+";"}finally{this.deleteLocalRef(n)}}else return"[Ljava.lang.Object;"};y.prototype.stringFromJni=function(t){let e=this.getStringChars(t);if(e.isNull())throw new Error("Unable to access string");try{let n=this.getStringLength(t);return e.readUtf16String(n)}finally{this.releaseStringChars(t,e)}};var Gr=65542,$e=Process.pointerSize,bn=Process.getCurrentThreadId(),Fe=new Map,rt=new Map;function Ie(t){let e=t.vm,n=null,r=null,o=null;function i(){let c=e.readPointer(),a={exceptions:"propagate"};n=new NativeFunction(c.add(4*$e).readPointer(),"int32",["pointer","pointer","pointer"],a),r=new NativeFunction(c.add(5*$e).readPointer(),"int32",["pointer"],a),o=new NativeFunction(c.add(6*$e).readPointer(),"int32",["pointer","pointer","int32"],a)}this.handle=e,this.perform=function(c){let a=Process.getCurrentThreadId(),l=s(a);if(l!==null)return c(l);let d=this._tryGetEnv(),p=d!==null;p||(d=this.attachCurrentThread(),Fe.set(a,!0)),this.link(a,d);try{return c(d)}finally{let f=a===bn;if(f||this.unlink(a),!p&&!f){let u=Fe.get(a);Fe.delete(a),u&&this.detachCurrentThread()}}},this.attachCurrentThread=function(){let c=Memory.alloc($e);return de("VM::AttachCurrentThread",n(e,c,NULL)),new y(c.readPointer(),this)},this.detachCurrentThread=function(){de("VM::DetachCurrentThread",r(e))},this.preventDetachDueToClassLoader=function(){let c=Process.getCurrentThreadId();Fe.has(c)&&Fe.set(c,!1)},this.getEnv=function(){let c=s(Process.getCurrentThreadId());if(c!==null)return c;let a=Memory.alloc($e),l=o(e,a,Gr);if(l===-2)throw new Error("Current thread is not attached to the Java VM; please move this code inside a Java.perform() callback");return de("VM::GetEnv",l),new y(a.readPointer(),this)},this.tryGetEnv=function(){let c=s(Process.getCurrentThreadId());return c!==null?c:this._tryGetEnv()},this._tryGetEnv=function(){let c=this.tryGetEnvHandle(Gr);return c===null?null:new y(c,this)},this.tryGetEnvHandle=function(c){let a=Memory.alloc($e);return o(e,a,c)!==0?null:a.readPointer()},this.makeHandleDestructor=function(c){return()=>{this.perform(a=>{a.deleteGlobalRef(c)})}},this.link=function(c,a){let l=rt.get(c);l===void 0?rt.set(c,[a,1]):l[1]++},this.unlink=function(c){let a=rt.get(c);a[1]===1?rt.delete(c):a[1]--};function s(c){let a=rt.get(c);return a===void 0?null:a[0]}i.call(this)}Ie.dispose=function(t){Fe.get(bn)===!0&&(Fe.delete(bn),t.detachCurrentThread())};var Ea=4,v=Process.pointerSize,{readU32:va,readPointer:Sa,writeU32:wa,writePointer:Ia}=NativePointer.prototype,Ca=1,Ta=8,Aa=16,Lt=256,La=524288,xa=2097152,ao=1073741824,Na=524288,ka=134217728,$r=1048576,Ma=2097152,ja=268435456,Oa=268435456,Ra=0,xn=3,Nn=5,Bn=ptr(1).not(),Pa=2147467263,Fa=4294963200,Rt=17*v,Da=18*v,co=12,Ua=112,Ba=116,za=0,En=56,Hr=4,Va=8,Ja=10,Ga=12,$a=14,Ha=28,Za=36,qa=0,Wa=1,Ka=2,Qa=3,Ya=4,Xa=5,ec=6,tc=7,Zr=2147483648,nc=28,at=3*v,rc=3*v,oc=1,ic=1,lo=le(mc),sc=le(xc),_e=le(kc),Ze=le(Mc),ac=le(jc),cc=le(Vc),dt=le(Fc),uo=le(Dc),ee=le(Uc),zn=le(Bc),lc=le(Hc),dc=Process.arch==="ia32"?Ml:kl,W={exceptions:"propagate"},ot={},vn=null,Sn=null,po=null,oe=null,Vn=[],xt=new Map,fo=[],wn=null,qr=0,Wr=!1,Kr=!1,it=null,uc=[],In=null,Ct=null;function J(){return vn===null&&(vn=pc()),vn}function pc(){let t=Process.enumerateModules().filter(u=>/^lib(art|dvm).so$/.test(u.name)).filter(u=>!/\/system\/fake-libs/.test(u.path));if(t.length===0)return null;let e=t[0],n=e.name.indexOf("art")!==-1?"art":"dalvik",r=n==="art",o={module:e,find(u){let{module:_}=this,h=_.findExportByName(u);return h===null&&(h=_.findSymbolByName(u)),h},flavor:n,addLocalReference:null};o.isApiLevel34OrApexEquivalent=r&&(o.find("_ZN3art7AppInfo29GetPrimaryApkReferenceProfileEv")!==null||o.find("_ZN3art6Thread15RunFlipFunctionEPS0_")!==null);let i=r?{functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],artInterpreterToCompiledCodeBridge:function(u){this.artInterpreterToCompiledCodeBridge=u},_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art17ReaderWriterMutex13ExclusiveLockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveLock","void",["pointer","pointer"]],_ZN3art17ReaderWriterMutex15ExclusiveUnlockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveUnlock","void",["pointer","pointer"]],_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art9JavaVMExt12DecodeGlobalEPv:function(u){let _;ee()>=26?_=dc(u,["pointer","pointer"]):_=new NativeFunction(u,"pointer",["pointer","pointer"],W),this["art::JavaVMExt::DecodeGlobal"]=function(h,g,b){return _(h,b)}},_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv:["art::JavaVMExt::DecodeGlobal","pointer",["pointer","pointer","pointer"]],_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZNK3art6Thread13DecodeJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZN3art10ThreadList10SuspendAllEPKcb:["art::ThreadList::SuspendAll","void",["pointer","pointer","bool"]],_ZN3art10ThreadList10SuspendAllEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::ThreadList::SuspendAll"]=function(h,g,b){return _(h)}},_ZN3art10ThreadList9ResumeAllEv:["art::ThreadList::ResumeAll","void",["pointer"]],_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE:["art::ClassLinker::VisitClasses","void",["pointer","pointer"]],_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer"],W);this["art::ClassLinker::VisitClasses"]=function(h,g){_(h,g,NULL)}},_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE:["art::ClassLinker::VisitClassLoaders","void",["pointer","pointer"]],_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_:["art::gc::Heap::VisitObjects","void",["pointer","pointer","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:["art::gc::Heap::GetInstances","void",["pointer","pointer","pointer","int","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer","bool","int","pointer"],W);this["art::gc::Heap::GetInstances"]=function(h,g,b,E,C){_(h,g,b,0,E,C)}},_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","uint","bool"]],_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","size_t","bool"]],_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb:["art::StackVisitor::WalkStack","void",["pointer","bool"]],_ZNK3art12StackVisitor9GetMethodEv:["art::StackVisitor::GetMethod","pointer",["pointer"]],_ZNK3art12StackVisitor16DescribeLocationEv:function(u){this["art::StackVisitor::DescribeLocation"]=At(u,["pointer"])},_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv:function(u){this["art::StackVisitor::GetCurrentQuickFrameInfo"]=$c(u)},_ZN3art7Context6CreateEv:["art::Context::Create","pointer",[]],_ZN3art6Thread18GetLongJumpContextEv:["art::Thread::GetLongJumpContext","pointer",["pointer"]],_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:function(u){this["art::mirror::Class::GetDescriptor"]=u},_ZN3art6mirror5Class11GetLocationEv:function(u){this["art::mirror::Class::GetLocation"]=At(u,["pointer"])},_ZN3art9ArtMethod12PrettyMethodEb:function(u){this["art::ArtMethod::PrettyMethod"]=At(u,["pointer","bool"])},_ZN3art12PrettyMethodEPNS_9ArtMethodEb:function(u){this["art::ArtMethod::PrettyMethodNullSafe"]=At(u,["pointer","bool"])},_ZN3art6Thread14CurrentFromGdbEv:["art::Thread::CurrentFromGdb","pointer",[]],_ZN3art6mirror6Object5CloneEPNS_6ThreadE:function(u){this["art::mirror::Object::Clone"]=new NativeFunction(u,"pointer",["pointer","pointer"],W)},_ZN3art6mirror6Object5CloneEPNS_6ThreadEm:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","pointer"],W);this["art::mirror::Object::Clone"]=function(h,g){let b=NULL;return _(h,g,b)}},_ZN3art6mirror6Object5CloneEPNS_6ThreadEj:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","uint"],W);this["art::mirror::Object::Clone"]=function(h,g){return _(h,g,0)}},_ZN3art3Dbg14SetJdwpAllowedEb:["art::Dbg::SetJdwpAllowed","void",["bool"]],_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE:["art::Dbg::ConfigureJdwp","void",["pointer"]],_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv:["art::InternalDebuggerControlCallback::StartDebugger","void",["pointer"]],_ZN3art3Dbg9StartJdwpEv:["art::Dbg::StartJdwp","void",[]],_ZN3art3Dbg8GoActiveEv:["art::Dbg::GoActive","void",[]],_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE:["art::Dbg::RequestDeoptimization","void",["pointer"]],_ZN3art3Dbg20ManageDeoptimizationEv:["art::Dbg::ManageDeoptimization","void",[]],_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv:["art::Instrumentation::EnableDeoptimization","void",["pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc:["art::Instrumentation::DeoptimizeEverything","void",["pointer","pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::Instrumentation::DeoptimizeEverything"]=function(h,g){_(h)}},_ZN3art7Runtime19DeoptimizeBootImageEv:["art::Runtime::DeoptimizeBootImage","void",["pointer"]],_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE:["art::Instrumentation::Deoptimize","void",["pointer","pointer"]],_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID:["art::jni::JniIdManager::DecodeMethodId","pointer",["pointer","pointer"]],_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID:["art::jni::JniIdManager::DecodeFieldId","pointer",["pointer","pointer"]],_ZN3art11interpreter18GetNterpEntryPointEv:["art::interpreter::GetNterpEntryPoint","pointer",[]],_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi:["art::Monitor::TranslateLocation","void",["pointer","uint32","pointer","pointer"]]},variables:{_ZN3art3Dbg9gRegistryE:function(u){this.isJdwpStarted=()=>!u.readPointer().isNull()},_ZN3art3Dbg15gDebuggerActiveE:function(u){this.isDebuggerActive=()=>!!u.readU8()}},optionals:new Set(["artInterpreterToCompiledCodeBridge","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE","_ZN3art9JavaVMExt12DecodeGlobalEPv","_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv","_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject","_ZNK3art6Thread13DecodeJObjectEP8_jobject","_ZN3art10ThreadList10SuspendAllEPKcb","_ZN3art10ThreadList10SuspendAllEv","_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE","_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_","_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE","_ZN3art6mirror6Object5CloneEPNS_6ThreadE","_ZN3art6mirror6Object5CloneEPNS_6ThreadEm","_ZN3art6mirror6Object5CloneEPNS_6ThreadEj","_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE","_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb","_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb","_ZNK3art12StackVisitor9GetMethodEv","_ZNK3art12StackVisitor16DescribeLocationEv","_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv","_ZN3art7Context6CreateEv","_ZN3art6Thread18GetLongJumpContextEv","_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE","_ZN3art6mirror5Class11GetLocationEv","_ZN3art9ArtMethod12PrettyMethodEb","_ZN3art12PrettyMethodEPNS_9ArtMethodEb","_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE","_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv","_ZN3art3Dbg15gDebuggerActiveE","_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv","_ZN3art7Runtime19DeoptimizeBootImageEv","_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE","_ZN3art3Dbg9StartJdwpEv","_ZN3art3Dbg8GoActiveEv","_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE","_ZN3art3Dbg20ManageDeoptimizationEv","_ZN3art3Dbg9gRegistryE","_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID","_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID","_ZN3art11interpreter18GetNterpEntryPointEv","_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi"])}:{functions:{_Z20dvmDecodeIndirectRefP6ThreadP8_jobject:["dvmDecodeIndirectRef","pointer",["pointer","pointer"]],_Z15dvmUseJNIBridgeP6MethodPv:["dvmUseJNIBridge","void",["pointer","pointer"]],_Z20dvmHeapSourceGetBasev:["dvmHeapSourceGetBase","pointer",[]],_Z21dvmHeapSourceGetLimitv:["dvmHeapSourceGetLimit","pointer",[]],_Z16dvmIsValidObjectPK6Object:["dvmIsValidObject","uint8",["pointer"]],JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]]},variables:{gDvmJni:function(u){this.gDvmJni=u},gDvm:function(u){this.gDvm=u}}},{functions:s={},variables:c={},optionals:a=new Set}=i,l=[];for(let[u,_]of Object.entries(s)){let h=o.find(u);h!==null?typeof _=="function"?_.call(o,h):o[_[0]]=new NativeFunction(h,_[1],_[2],W):a.has(u)||l.push(u)}for(let[u,_]of Object.entries(c)){let h=o.find(u);h!==null?_.call(o,h):a.has(u)||l.push(u)}if(l.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+l.join(", "));let d=Memory.alloc(v),p=Memory.alloc(Ea);if(de("JNI_GetCreatedJavaVMs",o.JNI_GetCreatedJavaVMs(d,1,p)),p.readInt()===0)return null;if(o.vm=d.readPointer(),r){let u=ee(),_;u>=27?_=33554432:u>=24?_=16777216:_=0,o.kAccCompileDontBother=_;let h=o.vm.add(v).readPointer();o.artRuntime=h;let g=lo(o),b=g.offset,E=b.instrumentation;o.artInstrumentation=E!==null?h.add(E):null,zn()>=36e7&&o.artInstrumentation!=null&&(o.artInstrumentation=o.artInstrumentation.readPointer()),o.artHeap=h.add(b.heap).readPointer(),o.artThreadList=h.add(b.threadList).readPointer();let A=h.add(b.classLinker).readPointer(),M=Nc(h,g).offset,O=A.add(M.quickResolutionTrampoline).readPointer(),k=A.add(M.quickImtConflictTrampoline).readPointer(),N=A.add(M.quickGenericJniTrampoline).readPointer(),S=A.add(M.quickToInterpreterBridgeTrampoline).readPointer();o.artClassLinker={address:A,quickResolutionTrampoline:O,quickImtConflictTrampoline:k,quickGenericJniTrampoline:N,quickToInterpreterBridgeTrampoline:S};let L=new Ie(o);o.artQuickGenericJniTrampoline=Cn(N,L),o.artQuickToInterpreterBridge=Cn(S,L),o.artQuickResolutionTrampoline=Cn(O,L),o["art::JavaVMExt::AddGlobalRef"]===void 0&&(o["art::JavaVMExt::AddGlobalRef"]=Cl(o)),o["art::JavaVMExt::DecodeGlobal"]===void 0&&(o["art::JavaVMExt::DecodeGlobal"]=Tl(o)),o["art::ArtMethod::PrettyMethod"]===void 0&&(o["art::ArtMethod::PrettyMethod"]=o["art::ArtMethod::PrettyMethodNullSafe"]),o["art::interpreter::GetNterpEntryPoint"]!==void 0?o.artNterpEntryPoint=o["art::interpreter::GetNterpEntryPoint"]():o.artNterpEntryPoint=o.find("ExecuteNterpImpl"),oe=Wc(o,L),Nl(o);let j=null;Object.defineProperty(o,"jvmti",{get(){return j===null&&(j=[fc(L,this.artRuntime)]),j[0]}})}let f=e.enumerateImports().filter(u=>u.name.indexOf("_Z")===0).reduce((u,_)=>(u[_.name]=_.address,u),{});return o.$new=new NativeFunction(f._Znwm||f._Znwj,"pointer",["ulong"],W),o.$delete=new NativeFunction(f._ZdlPv,"void",["pointer"],W),po=r?Pn:Fn,o}function fc(t,e){let n=null;return t.perform(()=>{let r=J().find("_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE");if(r===null)return;let o=new NativeFunction(r,"bool",["pointer","pointer","pointer"]),i=Memory.alloc(v);if(!o(e,Memory.allocUtf8String("libopenjdkjvmti.so"),i))return;let c=Et.v1_2|1073741824,a=t.tryGetEnvHandle(c);if(a===null)return;n=new Le(a,t);let l=Memory.alloc(8);l.writeU64(vt.canTagObjects),n.addCapabilities(l)!==0&&(n=null)}),n}function hc(t,e){J().flavor==="art"&&t.getClassName(e)}function _c(t){return{offset:v===4?{globalsLock:32,globals:72}:{globalsLock:64,globals:112}}}function mc(t){let e=t.vm,n=t.artRuntime,r=v===4?200:384,o=r+100*v,i=ee(),s=uo(),{isApiLevel34OrApexEquivalent:c}=t,a=null;for(let d=r;d!==o;d+=v)if(n.add(d).readPointer().equals(e)){let f,u=null;i>=33||s==="Tiramisu"||c?(f=[d-4*v],u=d-v):i>=30||s==="R"?(f=[d-3*v,d-4*v],u=d-v):i>=29?f=[d-2*v]:i>=27?f=[d-at-3*v]:f=[d-at-2*v];for(let _ of f){let h=_-v,g=h-v,b;c?b=g-9*v:i>=24?b=g-8*v:i>=23?b=g-7*v:b=g-4*v;let E={offset:{heap:b,threadList:g,internTable:h,classLinker:_,jniIdManager:u}};if(ho(n,E)!==null){a=E;break}}break}if(a===null)throw new Error("Unable to determine Runtime field offsets");let l=zn()>=36e7;return a.offset.instrumentation=l?Sc(t):bc(t),a.offset.jniIdsIndirection=Tc(t),a}var gc={ia32:Qr,x64:Qr,arm:yc,arm64:Ec};function bc(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:xe(e,gc[Process.arch],{limit:30})}function Qr(t){if(t.mnemonic!=="lea")return null;let e=t.operands[1].value.disp;return e<256||e>1024?null:e}function yc(t){if(t.mnemonic!=="add.w")return null;let e=t.operands;if(e.length!==3)return null;let n=e[2];return n.type!=="imm"?null:n.value}function Ec(t){if(t.mnemonic!=="add")return null;let e=t.operands;if(e.length!==3||e[0].value==="sp"||e[1].value==="sp")return null;let n=e[2];if(n.type!=="imm")return null;let r=n.value.valueOf();return r<256||r>1024?null:r}var vc={ia32:Yr,x64:Yr,arm:wc,arm64:Ic};function Sc(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:xe(e,vc[Process.arch],{limit:30})}function Yr(t){if(t.mnemonic!=="mov")return null;let e=t.operands;if(e[0].value!=="rax")return null;let r=e[1];if(r.type!=="mem")return null;let o=r.value;if(o.base!=="rdi")return null;let i=o.disp;return i<256||i>1024?null:i}function wc(t){return null}function Ic(t){if(t.mnemonic!=="ldr")return null;let e=t.operands;if(e[0].value==="x0")return null;let n=e[1].value;if(n.base!=="x0")return null;let r=n.disp;return r<256||r>1024?null:r}var Cc={ia32:Xr,x64:Xr,arm:Ac,arm64:Lc};function Tc(t){let e=t.find("_ZN3art7Runtime12SetJniIdTypeENS_9JniIdTypeE");if(e===null)return null;let n=xe(e,Cc[Process.arch],{limit:20});if(n===null)throw new Error("Unable to determine Runtime.jni_ids_indirection_ offset");return n}function Xr(t){return t.mnemonic==="cmp"?t.operands[0].value.disp:null}function Ac(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Lc(t,e){if(e===null)return null;let{mnemonic:n}=t,{mnemonic:r}=e;return n==="cmp"&&r==="ldr"||n==="bl"&&r==="str"?e.operands[1].value.disp:null}function xc(){let e={"4-21":136,"4-22":136,"4-23":172,"4-24":196,"4-25":196,"4-26":196,"4-27":196,"4-28":212,"4-29":172,"4-30":180,"4-31":180,"8-21":224,"8-22":224,"8-23":296,"8-24":344,"8-25":344,"8-26":352,"8-27":352,"8-28":392,"8-29":328,"8-30":336,"8-31":336}[`${v}-${ee()}`];if(e===void 0)throw new Error("Unable to determine Instrumentation field offsets");return{offset:{forcedInterpretOnly:4,deoptimizationEnabled:e}}}function Nc(t,e){let n=ho(t,e);if(n===null)throw new Error("Unable to determine ClassLinker field offsets");return n}function ho(t,e){if(Sn!==null)return Sn;let{classLinker:n,internTable:r}=e.offset,o=t.add(n).readPointer(),i=t.add(r).readPointer(),s=v===4?100:200,c=s+100*v,a=ee(),l=null;for(let d=s;d!==c;d+=v)if(o.add(d).readPointer().equals(i)){let f;a>=30||uo()==="R"?f=6:a>=29?f=4:a>=23?f=3:f=5;let u=d+f*v,_;a>=23?_=u-2*v:_=u-3*v,l={offset:{quickResolutionTrampoline:_,quickImtConflictTrampoline:u-v,quickGenericJniTrampoline:u,quickToInterpreterBridgeTrampoline:u+v}};break}return l!==null&&(Sn=l),l}function Jn(t){let n=null;return t.perform(r=>{let o=Pt(t),i=_e(t),s={artArrayLengthSize:4,artArrayEntrySize:o.size,artArrayMax:50},c={artArrayLengthSize:v,artArrayEntrySize:i.size,artArrayMax:100},a=(f,u,_)=>{let h=f.add(u).readPointer();if(h.isNull())return null;let g=_===4?h.readU32():h.readU64().valueOf();return g<=0?null:{length:g,data:h.add(_)}},l=(f,u,_,h)=>{try{let g=a(f,u,h.artArrayLengthSize);if(g===null)return!1;let b=Math.min(g.length,h.artArrayMax);for(let E=0;E!==b;E++)if(g.data.add(E*h.artArrayEntrySize).equals(_))return!0}catch{}return!1},d=r.findClass("java/lang/Thread"),p=r.newGlobalRef(d);try{let f;ye(t,r,N=>{f=J()["art::JavaVMExt::DecodeGlobal"](t,N,p)});let u=no(r.getFieldId(p,"name","Ljava/lang/String;")),_=no(r.getStaticFieldId(p,"MAX_PRIORITY","I")),h=-1,g=-1;for(let N=0;N!==256;N+=4)h===-1&&l(f,N,_,s)&&(h=N),g===-1&&l(f,N,u,s)&&(g=N);if(g===-1||h===-1)throw new Error("Unable to find fields in java/lang/Thread; please file a bug");let b=g!==h?h:0,E=g,C=-1,A=Kn(r.getMethodId(p,"getName","()Ljava/lang/String;"));for(let N=0;N!==256;N+=4)C===-1&&l(f,N,A,c)&&(C=N);if(C===-1)throw new Error("Unable to find methods in java/lang/Thread; please file a bug");let M=-1,k=a(f,C,c.artArrayLengthSize).length;for(let N=C;N!==256;N+=4)if(f.add(N).readU16()===k){M=N;break}if(M===-1)throw new Error("Unable to find copied methods in java/lang/Thread; please file a bug");n={offset:{ifields:E,methods:C,sfields:b,copiedMethodsOffset:M}}}finally{r.deleteLocalRef(d),r.deleteGlobalRef(p)}}),n}function kc(t){let e=J(),n;return t.perform(r=>{let o=r.findClass("android/os/Process"),i=Kn(r.getStaticMethodId(o,"getElapsedCpuTime","()J"));r.deleteLocalRef(o);let s=Process.getModuleByName("libandroid_runtime.so"),c=s.base,a=c.add(s.size),l=ee(),d=l<=21?8:v,p=Ca|Ta|Aa|Lt,f=~(ao|ja|Ma)>>>0,u=null,_=null,h=2;for(let E=0;E!==64&&h!==0;E+=4){let C=i.add(E);if(u===null){let A=C.readPointer();A.compare(c)>=0&&A.compare(a)<0&&(u=E,h--)}_===null&&(C.readU32()&f)===p&&(_=E,h--)}if(h!==0)throw new Error("Unable to determine ArtMethod field offsets");let g=u+d;n={size:l<=21?g+32:g+v,offset:{jniCode:u,quickCode:g,accessFlags:_}},"artInterpreterToCompiledCodeBridge"in e&&(n.offset.interpreterCode=u-d)}),n}function Pt(t){let e=ee();return e>=23?{size:16,offset:{accessFlags:4}}:e>=21?{size:24,offset:{accessFlags:12}}:null}function Mc(t){let e=ee(),n;return t.perform(r=>{let o=Ft(r),i=r.handle,s=null,c=null,a=null,l=null,d=null,p=null;for(let f=144;f!==256;f+=v)if(o.add(f).readPointer().equals(i)){c=f-6*v,d=f-4*v,p=f+2*v,e<=22&&(c-=v,s=c-v-9*8-3*4,a=f+6*v,d-=v,p-=v),l=f+9*v,e<=22&&(l+=2*v+4,v===8&&(l+=4)),e>=23&&(l+=v);break}if(l===null)throw new Error("Unable to determine ArtThread field offsets");n={offset:{isExceptionReportedToInstrumentation:s,exception:c,throwLocation:a,topHandleScope:l,managedStack:d,self:p}}}),n}function jc(){return ee()>=23?{offset:{topQuickFrame:0,link:v}}:{offset:{topQuickFrame:2*v,link:0}}}var Oc={ia32:eo,x64:eo,arm:Rc,arm64:Pc};function Cn(t,e){let n;return e.perform(r=>{let o=Ft(r),i=Oc[Process.arch],s=Instruction.parse(t),c=i(s);c!==null?n=o.add(c).readPointer():n=t}),n}function eo(t){return t.mnemonic==="jmp"?t.operands[0].value.disp:null}function Rc(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Pc(t){return t.mnemonic==="ldr"?t.operands[1].value.disp:null}function Ft(t){return t.handle.add(v).readPointer()}function Fc(){return Gn("ro.build.version.release")}function Dc(){return Gn("ro.build.version.codename")}function Uc(){return parseInt(Gn("ro.build.version.sdk"),10)}function Bc(){try{let t=File.readAllText("/proc/self/mountinfo"),e=null,n=new Map;for(let o of t.trimEnd().split(` +`)){let i=o.split(" "),s=i[4];if(!s.startsWith("/apex/com.android.art"))continue;let c=i[10];s.includes("@")?n.set(c,s.split("@")[1]):e=c}let r=n.get(e);return r!==void 0?parseInt(r):to()}catch{return to()}}function to(){return ee()*1e7}var Tn=null,zc=92;function Gn(t){Tn===null&&(Tn=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("__system_property_get"),"int",["pointer","pointer"],W));let e=Memory.alloc(zc);return Tn(Memory.allocUtf8String(t),e),e.readUtf8String()}function ye(t,e,n){let r=cc(t,e),o=Ft(e).toString();if(ot[o]=n,r(e.handle),ot[o]!==void 0)throw delete ot[o],new Error("Unable to perform state transition; please file a bug")}function Vc(t,e){let n=new NativeCallback(Jc,"void",["pointer"]);return go(t,e,n)}function Jc(t){let e=t.toString(),n=ot[e];delete ot[e],n(t)}function $n(t){let e=J(),n=e.artThreadList;e["art::ThreadList::SuspendAll"](n,Memory.allocUtf8String("frida"),!1?1:0);try{t()}finally{e["art::ThreadList::ResumeAll"](n)}}var kn=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((i,s)=>e(s)===!0?1:0,"bool",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function Hn(t){return J()["art::ClassLinker::VisitClasses"]instanceof NativeFunction?new kn(t):new NativeCallback(n=>t(n)===!0?1:0,"bool",["pointer","pointer"])}var Mn=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((i,s)=>{e(s)},"void",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function Zn(t){return new Mn(t)}var Gc={"include-inlined-frames":0,"skip-inlined-frames":1},jn=class{constructor(e,n,r,o=0,i=!0){let s=J(),c=512,a=3*v,l=Memory.alloc(c+a);s["art::StackVisitor::StackVisitor"](l,e,n,Gc[r],o,i?1:0);let d=l.add(c);l.writePointer(d);let p=new NativeCallback(this._visitFrame.bind(this),"bool",["pointer"]);d.add(2*v).writePointer(p),this.handle=l,this._onVisitFrame=p;let f=l.add(v===4?12:24);this._curShadowFrame=f,this._curQuickFrame=f.add(v),this._curQuickFramePc=f.add(2*v),this._curOatQuickMethodHeader=f.add(3*v),this._getMethodImpl=s["art::StackVisitor::GetMethod"],this._descLocImpl=s["art::StackVisitor::DescribeLocation"],this._getCQFIImpl=s["art::StackVisitor::GetCurrentQuickFrameInfo"]}walkStack(e=!1){J()["art::StackVisitor::WalkStack"](this.handle,e?1:0)}_visitFrame(){return this.visitFrame()?1:0}visitFrame(){throw new Error("Subclass must implement visitFrame")}getMethod(){let e=this._getMethodImpl(this.handle);return e.isNull()?null:new Nt(e)}getCurrentQuickFramePc(){return this._curQuickFramePc.readPointer()}getCurrentQuickFrame(){return this._curQuickFrame.readPointer()}getCurrentShadowFrame(){return this._curShadowFrame.readPointer()}describeLocation(){let e=new jt;return this._descLocImpl(e,this.handle),e.disposeToString()}getCurrentOatQuickMethodHeader(){return this._curOatQuickMethodHeader.readPointer()}getCurrentQuickFrameInfo(){return this._getCQFIImpl(this.handle)}},Nt=class{constructor(e){this.handle=e}prettyMethod(e=!0){let n=new jt;return J()["art::ArtMethod::PrettyMethod"](n,this.handle,e?1:0),n.disposeToString()}toString(){return`ArtMethod(handle=${this.handle})`}};function $c(t){return function(e){let n=Memory.alloc(12);return lc(t)(n,e),{frameSizeInBytes:n.readU32(),coreSpillMask:n.add(4).readU32(),fpSpillMask:n.add(8).readU32()}}}function Hc(t){let e=NULL;switch(Process.arch){case"ia32":e=He(32,n=>{n.putMovRegRegOffsetPtr("ecx","esp",4),n.putMovRegRegOffsetPtr("edx","esp",8),n.putCallAddressWithArguments(t,["ecx","edx"]),n.putMovRegReg("esp","ebp"),n.putPopReg("ebp"),n.putRet()});break;case"x64":e=He(32,n=>{n.putPushReg("rdi"),n.putCallAddressWithArguments(t,["rsi"]),n.putPopReg("rdi"),n.putMovRegPtrReg("rdi","rax"),n.putMovRegOffsetPtrReg("rdi",8,"edx"),n.putRet()});break;case"arm":e=He(16,n=>{n.putCallAddressWithArguments(t,["r0","r1"]),n.putPopRegs(["r0","lr"]),n.putMovRegReg("pc","lr")});break;case"arm64":e=He(64,n=>{n.putPushRegReg("x0","lr"),n.putCallAddressWithArguments(t,["x1"]),n.putPopRegReg("x2","lr"),n.putStrRegRegOffset("x0","x2",0),n.putStrRegRegOffset("w1","x2",8),n.putRet()});break}return new NativeFunction(e,"void",["pointer","pointer"],W)}var Zc={ia32:globalThis.X86Relocator,x64:globalThis.X86Relocator,arm:globalThis.ThumbRelocator,arm64:globalThis.Arm64Relocator},On={ia32:globalThis.X86Writer,x64:globalThis.X86Writer,arm:globalThis.ThumbWriter,arm64:globalThis.Arm64Writer};function He(t,e){wn===null&&(wn=Memory.alloc(Process.pageSize));let n=wn.add(qr),r=Process.arch,o=On[r];return Memory.patchCode(n,t,i=>{let s=new o(i,{pc:n});if(e(s),s.flush(),s.offset>t)throw new Error(`Wrote ${s.offset}, exceeding maximum of ${t}`)}),qr+=t,r==="arm"?n.or(1):n}function qc(t,e){Kc(e),tl(e)}function Wc(t,e){let n=Ze(e).offset,r=ac().offset,o=` +#include + +extern GMutex lock; +extern GHashTable * methods; +extern GHashTable * replacements; +extern gpointer last_seen_art_method; + +extern gpointer get_oat_quick_method_header_impl (gpointer method, gpointer pc); + +void +init (void) +{ + g_mutex_init (&lock); + methods = g_hash_table_new_full (NULL, NULL, NULL, NULL); + replacements = g_hash_table_new_full (NULL, NULL, NULL, NULL); +} + +void +finalize (void) +{ + g_hash_table_unref (replacements); + g_hash_table_unref (methods); + g_mutex_clear (&lock); +} + +gboolean +is_replacement_method (gpointer method) +{ + gboolean is_replacement; + + g_mutex_lock (&lock); + + is_replacement = g_hash_table_contains (replacements, method); + + g_mutex_unlock (&lock); + + return is_replacement; +} + +gpointer +get_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + + g_mutex_unlock (&lock); + + return replacement_method; +} + +void +set_replacement_method (gpointer original_method, + gpointer replacement_method) +{ + g_mutex_lock (&lock); + + g_hash_table_insert (methods, original_method, replacement_method); + g_hash_table_insert (replacements, replacement_method, original_method); + + g_mutex_unlock (&lock); +} + +void +synchronize_replacement_methods (guint quick_code_offset, + void * nterp_entrypoint, + void * quick_to_interpreter_bridge) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + { + void ** quick_code; + + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + quick_code = hooked_method + quick_code_offset; + if (*quick_code == nterp_entrypoint) + *quick_code = quick_to_interpreter_bridge; + } + + g_mutex_unlock (&lock); +} + +void +delete_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + if (replacement_method != NULL) + { + g_hash_table_remove (methods, original_method); + g_hash_table_remove (replacements, replacement_method); + } + + g_mutex_unlock (&lock); +} + +gpointer +translate_method (gpointer method) +{ + gpointer translated_method; + + g_mutex_lock (&lock); + + translated_method = g_hash_table_lookup (replacements, method); + + g_mutex_unlock (&lock); + + return (translated_method != NULL) ? translated_method : method; +} + +gpointer +find_replacement_method_from_quick_code (gpointer method, + gpointer thread) +{ + gpointer replacement_method; + gpointer managed_stack; + gpointer top_quick_frame; + gpointer link_managed_stack; + gpointer * link_top_quick_frame; + + replacement_method = get_replacement_method (method); + if (replacement_method == NULL) + return NULL; + + /* + * Stack check. + * + * Return NULL to indicate that the original method should be invoked, otherwise + * return a pointer to the replacement ArtMethod. + * + * If the caller is our own JNI replacement stub, then a stack transition must + * have been pushed onto the current thread's linked list. + * + * Therefore, we invoke the original method if the following conditions are met: + * 1- The current managed stack is empty. + * 2- The ArtMethod * inside the linked managed stack's top quick frame is the + * same as our replacement. + */ + managed_stack = thread + ${n.managedStack}; + top_quick_frame = *((gpointer *) (managed_stack + ${r.topQuickFrame})); + if (top_quick_frame != NULL) + return replacement_method; + + link_managed_stack = *((gpointer *) (managed_stack + ${r.link})); + if (link_managed_stack == NULL) + return replacement_method; + + link_top_quick_frame = GSIZE_TO_POINTER (*((gsize *) (link_managed_stack + ${r.topQuickFrame})) & ~((gsize) 1)); + if (link_top_quick_frame == NULL || *link_top_quick_frame != replacement_method) + return replacement_method; + + return NULL; +} + +void +on_interpreter_do_call (GumInvocationContext * ic) +{ + gpointer method, replacement_method; + + method = gum_invocation_context_get_nth_argument (ic, 0); + + replacement_method = get_replacement_method (method); + if (replacement_method != NULL) + gum_invocation_context_replace_nth_argument (ic, 0, replacement_method); +} + +gpointer +on_art_method_get_oat_quick_method_header (gpointer method, + gpointer pc) +{ + if (is_replacement_method (method)) + return NULL; + + return get_oat_quick_method_header_impl (method, pc); +} + +void +on_art_method_pretty_method (GumInvocationContext * ic) +{ + const guint this_arg_index = ${Process.arch==="arm64"?0:1}; + gpointer method; + + method = gum_invocation_context_get_nth_argument (ic, this_arg_index); + if (method == NULL) + gum_invocation_context_replace_nth_argument (ic, this_arg_index, last_seen_art_method); + else + last_seen_art_method = method; +} + +void +on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + g_mutex_unlock (&lock); +} +`,i=8,s=v,c=v,a=v,d=Memory.alloc(i+s+c+a),p=d.add(i),f=p.add(s),u=f.add(c),_=t.find(v===4?"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj":"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"),h=new CModule(o,{lock:d,methods:p,replacements:f,last_seen_art_method:u,get_oat_quick_method_header_impl:_??ptr("0xdeadbeef")}),g={exceptions:"propagate",scheduling:"exclusive"};return{handle:h,replacedMethods:{isReplacement:new NativeFunction(h.is_replacement_method,"bool",["pointer"],g),get:new NativeFunction(h.get_replacement_method,"pointer",["pointer"],g),set:new NativeFunction(h.set_replacement_method,"void",["pointer","pointer"],g),synchronize:new NativeFunction(h.synchronize_replacement_methods,"void",["uint","pointer","pointer"],g),delete:new NativeFunction(h.delete_replacement_method,"void",["pointer"],g),translate:new NativeFunction(h.translate_method,"pointer",["pointer"],g),findReplacementFromQuickCode:h.find_replacement_method_from_quick_code},getOatQuickMethodHeaderImpl:_,hooks:{Interpreter:{doCall:h.on_interpreter_do_call},ArtMethod:{getOatQuickMethodHeader:h.on_art_method_get_oat_quick_method_header,prettyMethod:h.on_art_method_pretty_method},Gc:{copyingPhase:{onLeave:h.on_leave_gc_concurrent_copying_copying_phase},runFlip:{onEnter:h.on_leave_gc_concurrent_copying_copying_phase}}}}}function Kc(t){Kr||(Kr=!0,Qc(t),Yc(),Xc(),el())}function Qc(t){let e=J();[e.artQuickGenericJniTrampoline,e.artQuickToInterpreterBridge,e.artQuickResolutionTrampoline].forEach(r=>{Memory.protect(r,32,"rwx");let o=new Mt(r);o.activate(t),fo.push(o)})}function Yc(){let t=J(),e=ee(),{isApiLevel34OrApexEquivalent:n}=t,r;if(e<=22)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_6mirror9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(e<=33&&!n)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(n)r=/^_ZN3art11interpreter6DoCallILb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtbPNS_6JValueE$/;else throw new Error("Unable to find method invocation in ART; please file a bug");let o=t.module,i=[...o.enumerateExports(),...o.enumerateSymbols()].filter(s=>r.test(s.name));if(i.length===0)throw new Error("Unable to find method invocation in ART; please file a bug");for(let s of i)Interceptor.attach(s.address,oe.hooks.Interpreter.doCall)}function Xc(){let t=J(),n=t.module.findSymbolByName("_ZN3art2gc4Heap22CollectGarbageInternalENS0_9collector6GcTypeENS0_7GcCauseEbj");if(n===null)return;let{artNterpEntryPoint:r,artQuickToInterpreterBridge:o}=t,i=_e(t.vm).offset.quickCode;Interceptor.attach(n,{onLeave(){oe.replacedMethods.synchronize(i,r,o)}})}function el(){let t=[["_ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE","e90340f8 : ff0ff0ff"],["_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEl","7f0f00f9 : 1ffcffff"]],e=J(),n=e.module;for(let[r,o]of t){let i=n.findSymbolByName(r);if(i===null)continue;let s=Memory.scanSync(i,8192,o);if(s.length===0)return;let{artNterpEntryPoint:c,artQuickToInterpreterBridge:a}=e,l=_e(e.vm).offset.quickCode;Interceptor.attach(s[0].address,function(){oe.replacedMethods.synchronize(l,c,a)});return}}function tl(t){if(Wr)return;if(Wr=!0,!rl()){let{getOatQuickMethodHeaderImpl:i}=oe;if(i===null)return;try{Interceptor.replace(i,oe.hooks.ArtMethod.getOatQuickMethodHeader)}catch{}}let e=ee(),n=null,r=J();e>28?n=r.find("_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv"):e>22&&(n=r.find("_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv")),n!==null&&Interceptor.attach(n,oe.hooks.Gc.copyingPhase);let o=null;o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_"),o===null&&(o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_b")),o!==null&&Interceptor.attach(o,oe.hooks.Gc.runFlip)}var nl={arm:{signatures:[{pattern:["b0 68","01 30","0c d0","1b 98",":","c0 ff","c0 ff","00 ff","00 2f"],validateMatch:An},{pattern:["d8 f8 08 00","01 30","0c d0","1b 98",":","f0 ff ff 0f","ff ff","00 ff","00 2f"],validateMatch:An},{pattern:["b0 68","01 30","40 f0 c3 80","00 25",":","c0 ff","c0 ff","c0 fb 00 d0","ff f8"],validateMatch:An}],instrument:il},arm64:{signatures:[{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","88 39 00 f0",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 00 00 9f"],offset:1,validateMatch:Ln},{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","00 0e 40 f9",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 fc ff ff"],offset:1,validateMatch:Ln},{pattern:["0a 40 b9","1f 05 00 31","01 34 00 54","e0 03 1f aa",":","fc ff ff","1f fc ff ff","1f 00 00 ff","e0 ff ff ff"],offset:1,validateMatch:Ln}],instrument:sl}};function An({address:t,size:e}){let n=Instruction.parse(t.or(1)),[r,o]=n.operands,i=o.value.base,s=r.value,c=Instruction.parse(n.next.add(2)),a=ptr(c.operands[0].value),l=c.address.add(c.size),d,p;return c.mnemonic==="beq"?(d=l,p=a):(d=a,p=l),xe(d.or(1),f,{limit:3});function f(u){let{mnemonic:_}=u;if(!(_==="ldr"||_==="ldr.w"))return null;let{base:h,disp:g}=u.operands[1].value;return h===i&&g===20?{methodReg:i,scratchReg:s,target:{whenTrue:a,whenRegularMethod:d,whenRuntimeMethod:p}}:null}}function Ln({address:t,size:e}){let[n,r]=Instruction.parse(t).operands,o=r.value.base,i="x"+n.value.substring(1),s=Instruction.parse(t.add(8)),c=ptr(s.operands[0].value),a=t.add(12),l,d;return s.mnemonic==="b.eq"?(l=a,d=c):(l=c,d=a),xe(l,p,{limit:3});function p(f){if(f.mnemonic!=="ldr")return null;let{base:u,disp:_}=f.operands[1].value;return u===o&&_===24?{methodReg:o,scratchReg:i,target:{whenTrue:c,whenRegularMethod:l,whenRuntimeMethod:d}}:null}}function rl(){if(ee()<31)return!1;let t=nl[Process.arch];if(t===void 0)return!1;let e=t.signatures.map(({pattern:r,offset:o=0,validateMatch:i=ol})=>({pattern:new MatchPattern(r.join("")),offset:o,validateMatch:i})),n=[];for(let{base:r,size:o}of J().module.enumerateRanges("--x"))for(let{pattern:i,offset:s,validateMatch:c}of e){let a=Memory.scanSync(r,o,i).map(({address:l,size:d})=>({address:l.sub(s),size:d+s})).filter(l=>{let d=c(l);return d===null?!1:(l.validationResult=d,!0)});n.push(...a)}return n.length===0?!1:(n.forEach(t.instrument),!0)}function ol(){return{}}var kt=class{constructor(e,n,r){this.address=e,this.size=n,this.originalCode=e.readByteArray(n),this.trampoline=r}revert(){Memory.patchCode(this.address,this.size,e=>{e.writeByteArray(this.originalCode)})}};function il({address:t,size:e,validationResult:n}){let{methodReg:r,target:o}=n,i=Memory.alloc(Process.pageSize),s=e;Memory.patchCode(i,256,c=>{let a=new ThumbWriter(c,{pc:i}),l=new ThumbRelocator(t,a);for(let _=0;_!==2;_++)l.readOne();l.writeAll(),l.readOne(),l.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=[45,237,16,10];a.putBytes(d);let p=["r0","r1","r2","r3"];a.putPushRegs(p),a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegImm("r0",0),a.putPopRegs(p);let f=[189,236,16,10];a.putBytes(f),a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),l.readOne();let u=l.input.address.equals(o.whenRegularMethod);for(a.putLabel(u?"regular_method":"runtime_or_replacement_method"),l.writeOne();s<10;){let _=l.readOne();if(_===0){s=10;break}s=_}l.writeAll(),a.putBranchAddress(t.add(s+1)),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(o.whenTrue),a.flush()}),Vn.push(new kt(t,s,i)),Memory.patchCode(t,s,c=>{let a=new ThumbWriter(c,{pc:t});a.putLdrRegAddress("pc",i.or(1)),a.flush()})}function sl({address:t,size:e,validationResult:n}){let{methodReg:r,scratchReg:o,target:i}=n,s=Memory.alloc(Process.pageSize);Memory.patchCode(s,256,c=>{let a=new Arm64Writer(c,{pc:s}),l=new Arm64Relocator(t,a);for(let _=0;_!==2;_++)l.readOne();l.writeAll(),l.readOne(),l.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=["d0","d1","d2","d3","d4","d5","d6","d7","x0","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10","x11","x12","x13","x14","x15","x16","x17"],p=d.length;for(let _=0;_!==p;_+=2)a.putPushRegReg(d[_],d[_+1]);a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegReg("x0","xzr");for(let _=p-2;_>=0;_-=2)a.putPopRegReg(d[_],d[_+1]);a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),l.readOne();let f=l.input,u=f.address.equals(i.whenRegularMethod);a.putLabel(u?"regular_method":"runtime_or_replacement_method"),l.writeOne(),a.putBranchAddress(f.next),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(i.whenTrue),a.flush()}),Vn.push(new kt(t,e,s)),Memory.patchCode(t,e,c=>{let a=new Arm64Writer(c,{pc:t});a.putLdrRegAddress(o,s),a.putBrReg(o),a.flush()})}function al(t){return new po(t)}function cl(t){return oe.replacedMethods.translate(t)}function qn(t,e={}){let{limit:n=16}=e,r=t.getEnv();return it===null&&(it=ll(t,r)),it.backtrace(r,n)}function ll(t,e){let n=J(),r=Memory.alloc(Process.pointerSize),o=new CModule(` +#include +#include +#include +#include +#include + +typedef struct _ArtBacktrace ArtBacktrace; +typedef struct _ArtStackFrame ArtStackFrame; + +typedef struct _ArtStackVisitor ArtStackVisitor; +typedef struct _ArtStackVisitorVTable ArtStackVisitorVTable; + +typedef struct _ArtClass ArtClass; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtThread ArtThread; +typedef struct _ArtContext ArtContext; + +typedef struct _JNIEnv JNIEnv; + +typedef struct _StdString StdString; +typedef struct _StdTinyString StdTinyString; +typedef struct _StdLargeString StdLargeString; + +typedef enum { + STACK_WALK_INCLUDE_INLINED_FRAMES, + STACK_WALK_SKIP_INLINED_FRAMES, +} StackWalkKind; + +struct _StdTinyString +{ + guint8 unused; + gchar data[(3 * sizeof (gpointer)) - 1]; +}; + +struct _StdLargeString +{ + gsize capacity; + gsize size; + gchar * data; +}; + +struct _StdString +{ + union + { + guint8 flags; + StdTinyString tiny; + StdLargeString large; + }; +}; + +struct _ArtBacktrace +{ + GChecksum * id; + GArray * frames; + gchar * frames_json; +}; + +struct _ArtStackFrame +{ + ArtMethod * method; + gsize dexpc; + StdString description; +}; + +struct _ArtStackVisitorVTable +{ + void (* unused1) (void); + void (* unused2) (void); + bool (* visit) (ArtStackVisitor * visitor); +}; + +struct _ArtStackVisitor +{ + ArtStackVisitorVTable * vtable; + + guint8 padding[512]; + + ArtStackVisitorVTable vtable_storage; + + ArtBacktrace * backtrace; +}; + +struct _ArtMethod +{ + guint32 declaring_class; + guint32 access_flags; +}; + +extern GumTlsKey current_backtrace; + +extern void (* perform_art_thread_state_transition) (JNIEnv * env); + +extern ArtContext * art_make_context (ArtThread * thread); + +extern void art_stack_visitor_init (ArtStackVisitor * visitor, ArtThread * thread, void * context, StackWalkKind walk_kind, + size_t num_frames, bool check_suspended); +extern void art_stack_visitor_walk_stack (ArtStackVisitor * visitor, bool include_transitions); +extern ArtMethod * art_stack_visitor_get_method (ArtStackVisitor * visitor); +extern void art_stack_visitor_describe_location (StdString * description, ArtStackVisitor * visitor); +extern ArtMethod * translate_method (ArtMethod * method); +extern void translate_location (ArtMethod * method, guint32 pc, const gchar ** source_file, gint32 * line_number); +extern void get_class_location (StdString * result, ArtClass * klass); +extern void cxx_delete (void * mem); +extern unsigned long strtoul (const char * str, char ** endptr, int base); + +static bool visit_frame (ArtStackVisitor * visitor); +static void art_stack_frame_destroy (ArtStackFrame * frame); + +static void append_jni_type_name (GString * s, const gchar * name, gsize length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_get_data (StdString * str); + +void +init (void) +{ + current_backtrace = gum_tls_key_new (); +} + +void +finalize (void) +{ + gum_tls_key_free (current_backtrace); +} + +ArtBacktrace * +_create (JNIEnv * env, + guint limit) +{ + ArtBacktrace * bt; + + bt = g_new (ArtBacktrace, 1); + bt->id = g_checksum_new (G_CHECKSUM_SHA1); + bt->frames = (limit != 0) + ? g_array_sized_new (FALSE, FALSE, sizeof (ArtStackFrame), limit) + : g_array_new (FALSE, FALSE, sizeof (ArtStackFrame)); + g_array_set_clear_func (bt->frames, (GDestroyNotify) art_stack_frame_destroy); + bt->frames_json = NULL; + + gum_tls_key_set_value (current_backtrace, bt); + + perform_art_thread_state_transition (env); + + gum_tls_key_set_value (current_backtrace, NULL); + + return bt; +} + +void +_on_thread_state_transition_complete (ArtThread * thread) +{ + ArtContext * context; + ArtStackVisitor visitor = { + .vtable_storage = { + .visit = visit_frame, + }, + }; + + context = art_make_context (thread); + + art_stack_visitor_init (&visitor, thread, context, STACK_WALK_SKIP_INLINED_FRAMES, 0, true); + visitor.vtable = &visitor.vtable_storage; + visitor.backtrace = gum_tls_key_get_value (current_backtrace); + + art_stack_visitor_walk_stack (&visitor, false); + + cxx_delete (context); +} + +static bool +visit_frame (ArtStackVisitor * visitor) +{ + ArtBacktrace * bt = visitor->backtrace; + ArtStackFrame frame; + const gchar * description, * dexpc_part; + + frame.method = art_stack_visitor_get_method (visitor); + + art_stack_visitor_describe_location (&frame.description, visitor); + + description = std_string_get_data (&frame.description); + if (strstr (description, " '<") != NULL) + goto skip; + + dexpc_part = strstr (description, " at dex PC 0x"); + if (dexpc_part == NULL) + goto skip; + frame.dexpc = strtoul (dexpc_part + 13, NULL, 16); + + g_array_append_val (bt->frames, frame); + + g_checksum_update (bt->id, (guchar *) &frame.method, sizeof (frame.method)); + g_checksum_update (bt->id, (guchar *) &frame.dexpc, sizeof (frame.dexpc)); + + return true; + +skip: + std_string_destroy (&frame.description); + return true; +} + +static void +art_stack_frame_destroy (ArtStackFrame * frame) +{ + std_string_destroy (&frame->description); +} + +void +_destroy (ArtBacktrace * backtrace) +{ + g_free (backtrace->frames_json); + g_array_free (backtrace->frames, TRUE); + g_checksum_free (backtrace->id); + g_free (backtrace); +} + +const gchar * +_get_id (ArtBacktrace * backtrace) +{ + return g_checksum_get_string (backtrace->id); +} + +const gchar * +_get_frames (ArtBacktrace * backtrace) +{ + GArray * frames = backtrace->frames; + JsonBuilder * b; + guint i; + JsonNode * root; + + if (backtrace->frames_json != NULL) + return backtrace->frames_json; + + b = json_builder_new_immutable (); + + json_builder_begin_array (b); + + for (i = 0; i != frames->len; i++) + { + ArtStackFrame * frame = &g_array_index (frames, ArtStackFrame, i); + gchar * description, * ret_type, * paren_open, * paren_close, * arg_types, * token, * method_name, * class_name; + GString * signature; + gchar * cursor; + ArtMethod * translated_method; + StdString location; + gsize dexpc; + const gchar * source_file; + gint32 line_number; + + description = std_string_get_data (&frame->description); + + ret_type = strchr (description, '\\'') + 1; + + paren_open = strchr (ret_type, '('); + paren_close = strchr (paren_open, ')'); + *paren_open = '\\0'; + *paren_close = '\\0'; + + arg_types = paren_open + 1; + + token = strrchr (ret_type, '.'); + *token = '\\0'; + + method_name = token + 1; + + token = strrchr (ret_type, ' '); + *token = '\\0'; + + class_name = token + 1; + + signature = g_string_sized_new (128); + + append_jni_type_name (signature, class_name, method_name - class_name - 1); + g_string_append_c (signature, ','); + g_string_append (signature, method_name); + g_string_append (signature, ",("); + + if (arg_types != paren_close) + { + for (cursor = arg_types; cursor != NULL;) + { + gsize length; + gchar * next; + + token = strstr (cursor, ", "); + if (token != NULL) + { + length = token - cursor; + next = token + 2; + } + else + { + length = paren_close - cursor; + next = NULL; + } + + append_jni_type_name (signature, cursor, length); + + cursor = next; + } + } + + g_string_append_c (signature, ')'); + + append_jni_type_name (signature, ret_type, class_name - ret_type - 1); + + translated_method = translate_method (frame->method); + dexpc = (translated_method == frame->method) ? frame->dexpc : 0; + + get_class_location (&location, GSIZE_TO_POINTER (translated_method->declaring_class)); + + translate_location (translated_method, dexpc, &source_file, &line_number); + + json_builder_begin_object (b); + + json_builder_set_member_name (b, "signature"); + json_builder_add_string_value (b, signature->str); + + json_builder_set_member_name (b, "origin"); + json_builder_add_string_value (b, std_string_get_data (&location)); + + json_builder_set_member_name (b, "className"); + json_builder_add_string_value (b, class_name); + + json_builder_set_member_name (b, "methodName"); + json_builder_add_string_value (b, method_name); + + json_builder_set_member_name (b, "methodFlags"); + json_builder_add_int_value (b, translated_method->access_flags); + + json_builder_set_member_name (b, "fileName"); + json_builder_add_string_value (b, source_file); + + json_builder_set_member_name (b, "lineNumber"); + json_builder_add_int_value (b, line_number); + + json_builder_end_object (b); + + std_string_destroy (&location); + g_string_free (signature, TRUE); + } + + json_builder_end_array (b); + + root = json_builder_get_root (b); + backtrace->frames_json = json_to_string (root, FALSE); + json_node_unref (root); + + return backtrace->frames_json; +} + +static void +append_jni_type_name (GString * s, + const gchar * name, + gsize length) +{ + gchar shorty = '\\0'; + gsize i; + + switch (name[0]) + { + case 'b': + if (strncmp (name, "boolean", length) == 0) + shorty = 'Z'; + else if (strncmp (name, "byte", length) == 0) + shorty = 'B'; + break; + case 'c': + if (strncmp (name, "char", length) == 0) + shorty = 'C'; + break; + case 'd': + if (strncmp (name, "double", length) == 0) + shorty = 'D'; + break; + case 'f': + if (strncmp (name, "float", length) == 0) + shorty = 'F'; + break; + case 'i': + if (strncmp (name, "int", length) == 0) + shorty = 'I'; + break; + case 'l': + if (strncmp (name, "long", length) == 0) + shorty = 'J'; + break; + case 's': + if (strncmp (name, "short", length) == 0) + shorty = 'S'; + break; + case 'v': + if (strncmp (name, "void", length) == 0) + shorty = 'V'; + break; + } + + if (shorty != '\\0') + { + g_string_append_c (s, shorty); + + return; + } + + if (length > 2 && name[length - 2] == '[' && name[length - 1] == ']') + { + g_string_append_c (s, '['); + append_jni_type_name (s, name, length - 2); + + return; + } + + g_string_append_c (s, 'L'); + + for (i = 0; i != length; i++) + { + gchar ch = name[i]; + if (ch != '.') + g_string_append_c (s, ch); + else + g_string_append_c (s, '/'); + } + + g_string_append_c (s, ';'); +} + +static void +std_string_destroy (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + if (is_large) + cxx_delete (str->large.data); +} + +static gchar * +std_string_get_data (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + return is_large ? str->large.data : str->tiny.data; +} +`,{current_backtrace:Memory.alloc(Process.pointerSize),perform_art_thread_state_transition:r,art_make_context:n["art::Thread::GetLongJumpContext"]??n["art::Context::Create"],art_stack_visitor_init:n["art::StackVisitor::StackVisitor"],art_stack_visitor_walk_stack:n["art::StackVisitor::WalkStack"],art_stack_visitor_get_method:n["art::StackVisitor::GetMethod"],art_stack_visitor_describe_location:n["art::StackVisitor::DescribeLocation"],translate_method:oe.replacedMethods.translate,translate_location:n["art::Monitor::TranslateLocation"],get_class_location:n["art::mirror::Class::GetLocation"],cxx_delete:n.$delete,strtoul:Process.getModuleByName("libc.so").getExportByName("strtoul")}),i=new NativeFunction(o._create,"pointer",["pointer","uint"],W),s=new NativeFunction(o._destroy,"void",["pointer"],W),c={exceptions:"propagate",scheduling:"exclusive"},a=new NativeFunction(o._get_id,"pointer",["pointer"],c),l=new NativeFunction(o._get_frames,"pointer",["pointer"],c),d=go(t,e,o._on_thread_state_transition_complete);o._performData=d,r.writePointer(d),o.backtrace=(f,u)=>{let _=i(f,u),h=new Rn(_);return Script.bindWeak(h,p.bind(null,_)),h};function p(f){s(f)}return o.getId=f=>a(f).readUtf8String(),o.getFrames=f=>JSON.parse(l(f).readUtf8String()),o}var Rn=class{constructor(e){this.handle=e}get id(){return it.getId(this.handle)}get frames(){return it.getFrames(this.handle)}};function Wn(){xt.forEach(t=>{t.vtablePtr.writePointer(t.vtable),t.vtableCountPtr.writeS32(t.vtableCount)}),xt.clear();for(let t of fo.splice(0))t.deactivate();for(let t of Vn.splice(0))t.revert()}function Kn(t){return _o(t,"art::jni::JniIdManager::DecodeMethodId")}function no(t){return _o(t,"art::jni::JniIdManager::DecodeFieldId")}function _o(t,e){let n=J(),r=lo(n).offset,o=r.jniIdManager,i=r.jniIdsIndirection;if(o!==null&&i!==null){let s=n.artRuntime;if(s.add(i).readInt()!==Ra){let a=s.add(o).readPointer();return n[e](a,t)}}return t}var dl={ia32:ul,x64:pl,arm:fl,arm64:hl};function ul(t,e,n,r,o){let i=Ze(o).offset,s=_e(o).offset,c;return Memory.patchCode(t,128,a=>{let l=new X86Writer(a,{pc:t}),d=new X86Relocator(e,l),p=[15,174,4,36],f=[15,174,12,36];l.putPushax(),l.putMovRegReg("ebp","esp"),l.putAndRegU32("esp",4294967280),l.putSubRegImm("esp",512),l.putBytes(p),l.putMovRegFsU32Ptr("ebx",i.self),l.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["eax","ebx"]),l.putTestRegReg("eax","eax"),l.putJccShortLabel("je","restore_registers","no-hint"),l.putMovRegOffsetPtrReg("ebp",7*4,"eax"),l.putLabel("restore_registers"),l.putBytes(f),l.putMovRegReg("esp","ebp"),l.putPopax(),l.putJccShortLabel("jne","invoke_replacement","no-hint");do c=d.readOne();while(c{let l=new X86Writer(a,{pc:t}),d=new X86Relocator(e,l),p=[15,174,4,36],f=[15,174,12,36];l.putPushax(),l.putMovRegReg("rbp","rsp"),l.putAndRegU32("rsp",4294967280),l.putSubRegImm("rsp",512),l.putBytes(p),l.putMovRegGsU32Ptr("rbx",i.self),l.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["rdi","rbx"]),l.putTestRegReg("rax","rax"),l.putJccShortLabel("je","restore_registers","no-hint"),l.putMovRegOffsetPtrReg("rbp",8*8,"rax"),l.putLabel("restore_registers"),l.putBytes(f),l.putMovRegReg("rsp","rbp"),l.putPopax(),l.putJccShortLabel("jne","invoke_replacement","no-hint");do c=d.readOne();while(c{let l=new ThumbWriter(a,{pc:t}),d=new ThumbRelocator(s,l),p=[45,237,16,10],f=[189,236,16,10];l.putPushRegs(["r1","r2","r3","r5","r6","r7","r8","r10","r11","lr"]),l.putBytes(p),l.putSubRegRegImm("sp","sp",8),l.putStrRegRegOffset("r0","sp",0),l.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["r0","r9"]),l.putCmpRegImm("r0",0),l.putBCondLabel("eq","restore_registers"),l.putStrRegRegOffset("r0","sp",0),l.putLabel("restore_registers"),l.putLdrRegRegOffset("r0","sp",0),l.putAddRegRegImm("sp","sp",8),l.putBytes(f),l.putPopRegs(["lr","r11","r10","r8","r7","r6","r5","r3","r2","r1"]),l.putBCondLabel("ne","invoke_replacement");do c=d.readOne();while(c{let a=new Arm64Writer(c,{pc:t}),l=new Arm64Relocator(e,a);a.putPushRegReg("d0","d1"),a.putPushRegReg("d2","d3"),a.putPushRegReg("d4","d5"),a.putPushRegReg("d6","d7"),a.putPushRegReg("x1","x2"),a.putPushRegReg("x3","x4"),a.putPushRegReg("x5","x6"),a.putPushRegReg("x7","x20"),a.putPushRegReg("x21","x22"),a.putPushRegReg("x23","x24"),a.putPushRegReg("x25","x26"),a.putPushRegReg("x27","x28"),a.putPushRegReg("x29","lr"),a.putSubRegRegImm("sp","sp",16),a.putStrRegRegOffset("x0","sp",0),a.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["x0","x19"]),a.putCmpRegReg("x0","xzr"),a.putBCondLabel("eq","restore_registers"),a.putStrRegRegOffset("x0","sp",0),a.putLabel("restore_registers"),a.putLdrRegRegOffset("x0","sp",0),a.putAddRegRegImm("sp","sp",16),a.putPopRegReg("x29","lr"),a.putPopRegReg("x27","x28"),a.putPopRegReg("x25","x26"),a.putPopRegReg("x23","x24"),a.putPopRegReg("x21","x22"),a.putPopRegReg("x7","x20"),a.putPopRegReg("x5","x6"),a.putPopRegReg("x3","x4"),a.putPopRegReg("x1","x2"),a.putPopRegReg("d6","d7"),a.putPopRegReg("d4","d5"),a.putPopRegReg("d2","d3"),a.putPopRegReg("d0","d1"),a.putBCondLabel("ne","invoke_replacement");do s=l.readOne();while(s{let o=new X86Writer(r,{pc:t});o.putJmpAddress(e),o.flush()})}function ml(t,e,n){let r=t.and(Bn);Memory.patchCode(r,16,o=>{let i=new ThumbWriter(o,{pc:r});i.putLdrRegAddress("pc",e.or(1)),i.flush()})}function gl(t,e,n){Memory.patchCode(t,16,r=>{let o=new Arm64Writer(r,{pc:t});n===16?o.putLdrRegAddress("x16",e):o.putAdrpRegAddress("x16",e),o.putBrReg("x16"),o.flush()})}var bl={ia32:5,x64:16,arm:8,arm64:16},Mt=class{constructor(e){this.quickCode=e,this.quickCodeAddress=Process.arch==="arm"?e.and(Bn):e,this.redirectSize=0,this.trampoline=null,this.overwrittenPrologue=null,this.overwrittenPrologueLength=0}_canRelocateCode(e,n){let r=On[Process.arch],o=Zc[Process.arch],{quickCodeAddress:i}=this,s=new r(i),c=new o(i,s),a;if(Process.arch==="arm64"){let l=new Set(["x16","x17"]);do{let d=c.readOne(),p=new Set(l),{read:f,written:u}=c.input.regsAccessed;for(let _ of[f,u])for(let h of _){let g;h.startsWith("w")?g="x"+h.substring(1):g=h,p.delete(g)}if(p.size===0)break;a=d,l=p}while(a=e}_allocateTrampoline(){Ct===null&&(Ct=nn(v===4?128:256));let e=bl[Process.arch],n,r,o=1,i={};if(v===4||this._canRelocateCode(e,i))n=e,r={};else{let s;Process.arch==="x64"?(n=5,s=Pa):Process.arch==="arm64"&&(n=8,s=Fa,o=4096),r={near:this.quickCodeAddress,maxDistance:s}}return this.redirectSize=n,this.trampoline=Ct.allocateSlice(r,o),i}_destroyTrampoline(){Ct.freeSlice(this.trampoline)}activate(e){let n=this._allocateTrampoline(),{trampoline:r,quickCode:o,redirectSize:i}=this,s=dl[Process.arch],c=s(r,o,i,n,e);this.overwrittenPrologueLength=c,this.overwrittenPrologue=Memory.dup(this.quickCodeAddress,c);let a=_l[Process.arch];a(o,r,i)}deactivate(){let{quickCodeAddress:e,overwrittenPrologueLength:n}=this,r=On[Process.arch];Memory.patchCode(e,n,o=>{let i=new r(o,{pc:e}),{overwrittenPrologue:s}=this;i.putBytes(s.readByteArray(n)),i.flush()}),this._destroyTrampoline()}};function yl(t){let e=J(),{module:n,artClassLinker:r}=e;return t.equals(r.quickGenericJniTrampoline)||t.equals(r.quickToInterpreterBridgeTrampoline)||t.equals(r.quickResolutionTrampoline)||t.equals(r.quickImtConflictTrampoline)||t.compare(n.base)>=0&&t.compare(n.base.add(n.size))<0}var Pn=class{constructor(e){let n=Kn(e);this.methodId=n,this.originalMethod=null,this.hookedMethodId=n,this.replacementMethodId=null,this.interceptor=null}replace(e,n,r,o,i){let{kAccCompileDontBother:s,artNterpEntryPoint:c}=i;this.originalMethod=oo(this.methodId,o);let a=this.originalMethod.accessFlags;if((a&Oa)!==0&&El()){let u=this.originalMethod.jniCode;this.hookedMethodId=u.add(2*v).readPointer(),this.originalMethod=oo(this.hookedMethodId,o)}let{hookedMethodId:l}=this,d=Sl(l,o);this.replacementMethodId=d,Tt(d,{jniCode:e,accessFlags:(a&~(xa|La|$r)|Lt|s)>>>0,quickCode:i.artClassLinker.quickGenericJniTrampoline,interpreterCode:i.artInterpreterToCompiledCodeBridge},o);let p=ao|ka|$r;(a&Lt)===0&&(p|=Na),Tt(l,{accessFlags:(a&~p|s)>>>0},o);let f=this.originalMethod.quickCode;if(c!==null&&f.equals(c)&&Tt(l,{quickCode:i.artQuickToInterpreterBridge},o),!yl(f)){let u=new Mt(f);u.activate(o),this.interceptor=u}oe.replacedMethods.set(l,d),qc(l,o)}revert(e){let{hookedMethodId:n,interceptor:r}=this;Tt(n,this.originalMethod,e),oe.replacedMethods.delete(n),r!==null&&(r.deactivate(),this.interceptor=null)}resolveTarget(e,n,r,o){return this.hookedMethodId}};function El(){return ee()<28}function oo(t,e){let r=_e(e).offset;return["jniCode","accessFlags","quickCode","interpreterCode"].reduce((o,i)=>{let s=r[i];if(s===void 0)return o;let c=t.add(s),a=i==="accessFlags"?va:Sa;return o[i]=a.call(c),o},{})}function Tt(t,e,n){let o=_e(n).offset;Object.keys(e).forEach(i=>{let s=o[i];if(s===void 0)return;let c=t.add(s);(i==="accessFlags"?wa:Ia).call(c,e[i])})}var Fn=class{constructor(e){this.methodId=e,this.originalMethod=null}replace(e,n,r,o,i){let{methodId:s}=this;this.originalMethod=Memory.dup(s,En);let c=r.reduce((f,u)=>f+u.size,0);n&&c++;let a=(s.add(Hr).readU32()|Lt)>>>0,l=c,d=0,p=c;s.add(Hr).writeU32(a),s.add(Ja).writeU16(l),s.add(Ga).writeU16(d),s.add($a).writeU16(p),s.add(Za).writeU32(vl(s)),i.dvmUseJNIBridge(s,e)}revert(e){Memory.copy(this.methodId,this.originalMethod,En)}resolveTarget(e,n,r,o){let i=r.handle.add(co).readPointer(),s;if(n)s=o.dvmDecodeIndirectRef(i,e.$h);else{let f=e.$borrowClassHandle(r);s=o.dvmDecodeIndirectRef(i,f.value),f.unref(r)}let c;n?c=s.add(za).readPointer():c=s;let a=c.toString(16),l=xt.get(a);if(l===void 0){let f=c.add(Ba),u=c.add(Ua),_=f.readPointer(),h=u.readS32(),g=h*v,b=Memory.alloc(2*g);Memory.copy(b,_,g),f.writePointer(b),l={classObject:c,vtablePtr:f,vtableCountPtr:u,vtable:_,vtableCount:h,shadowVtable:b,shadowVtableCount:h,targetMethods:new Map},xt.set(a,l)}let d=this.methodId.toString(16),p=l.targetMethods.get(d);if(p===void 0){p=Memory.dup(this.originalMethod,En);let f=l.shadowVtableCount++;l.shadowVtable.add(f*v).writePointer(p),p.add(Va).writeU16(f),l.vtableCountPtr.writeS32(l.shadowVtableCount),l.targetMethods.set(d,p)}return p}};function vl(t){if(Process.arch!=="ia32")return Zr;let e=t.add(Ha).readPointer().readCString();if(e===null||e.length===0||e.length>65535)return Zr;let n;switch(e[0]){case"V":n=qa;break;case"F":n=Wa;break;case"D":n=Ka;break;case"J":n=Qa;break;case"Z":case"B":n=tc;break;case"C":n=ec;break;case"S":n=Xa;break;default:n=Ya;break}let r=0;for(let o=e.length-1;o>0;o--){let i=e[o];r+=i==="D"||i==="J"?2:1}return n<= 8.0");ye(t,e,r=>{n["art::Runtime::DeoptimizeBootImage"](n.artRuntime)})}function mo(t,e,n,r){let o=J();if(ee()<24)throw new Error("This API is only available on Android >= 7.0");ye(t,e,i=>{if(ee()<30){if(!o.isJdwpStarted()){let c=wl(o);uc.push(c)}o.isDebuggerActive()||o["art::Dbg::GoActive"]();let s=Memory.alloc(8+v);switch(s.writeU32(n),n){case xn:break;case Nn:s.add(8).writePointer(r);break;default:throw new Error("Unsupported deoptimization kind")}o["art::Dbg::RequestDeoptimization"](s),o["art::Dbg::ManageDeoptimization"]()}else{let s=o.artInstrumentation;if(s===null)throw new Error("Unable to find Instrumentation class in ART; please file a bug");let c=o["art::Instrumentation::EnableDeoptimization"];switch(c!==void 0&&(s.add(sc().offset.deoptimizationEnabled).readU8()||c(s)),n){case xn:o["art::Instrumentation::DeoptimizeEverything"](s,Memory.allocUtf8String("frida"));break;case Nn:o["art::Instrumentation::Deoptimize"](s,r);break;default:throw new Error("Unsupported deoptimization kind")}}})}var Dn=class{constructor(){let e=Process.getModuleByName("libart.so"),n=e.getExportByName("_ZN3art4JDWP12JdwpAdbState6AcceptEv"),r=e.getExportByName("_ZN3art4JDWP12JdwpAdbState15ReceiveClientFdEv"),o=io(),i=io();this._controlFd=o[0],this._clientFd=i[0];let s=null;s=Interceptor.attach(n,function(c){let a=c[0];Memory.scanSync(a.add(8252),256,"00 ff ff ff ff 00")[0].address.add(1).writeS32(o[1]),s.detach()}),Interceptor.replace(r,new NativeCallback(function(c){return Interceptor.revert(r),i[1]},"int",["pointer"])),Interceptor.flush(),this._handshakeRequest=this._performHandshake()}async _performHandshake(){let e=new UnixInputStream(this._clientFd,{autoClose:!1}),n=new UnixOutputStream(this._clientFd,{autoClose:!1}),r=[74,68,87,80,45,72,97,110,100,115,104,97,107,101];try{await n.writeAll(r),await e.readAll(r.length)}catch{}}};function wl(t){let e=new Dn;t["art::Dbg::SetJdwpAllowed"](1);let n=Il();t["art::Dbg::ConfigureJdwp"](n);let r=t["art::InternalDebuggerControlCallback::StartDebugger"];return r!==void 0?r(NULL):t["art::Dbg::StartJdwp"](),e}function Il(){let t=ee()<28?2:3,e=0,n=t,r=!0,o=!1,i=e,s=8+at+2,c=Memory.alloc(s);return c.writeU32(n).add(4).writeU8(r?1:0).add(1).writeU8(o?1:0).add(1).add(at).writeU16(i),c}function io(){In===null&&(In=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("socketpair"),"int",["int","int","int","pointer"]));let t=Memory.alloc(8);if(In(oc,ic,0,t)===-1)throw new Error("Unable to create socketpair for JDWP");return[t.readS32(),t.add(4).readS32()]}function Cl(t){let e=_c().offset,n=t.vm.add(e.globalsLock),r=t.vm.add(e.globals),o=t["art::IndirectReferenceTable::Add"],i=t["art::ReaderWriterMutex::ExclusiveLock"],s=t["art::ReaderWriterMutex::ExclusiveUnlock"],c=0;return function(a,l,d){i(n,l);try{return o(r,c,d)}finally{s(n,l)}}}function Tl(t){let e=t["art::Thread::DecodeJObject"];if(e===void 0)throw new Error("art::Thread::DecodeJObject is not available; please file a bug");return function(n,r,o){return e(r,o)}}var Al={ia32:so,x64:so,arm:Ll,arm64:xl};function go(t,e,n){let r=J(),o=e.handle.readPointer(),i,s=r.find("_ZN3art3JNIILb1EE14ExceptionClearEP7_JNIEnv");s!==null?i=s:i=o.add(Rt).readPointer();let c,a=r.find("_ZN3art3JNIILb1EE10FatalErrorEP7_JNIEnvPKc");a!==null?c=a:c=o.add(Da).readPointer();let l=Al[Process.arch];if(l===void 0)throw new Error("Not yet implemented for "+Process.arch);let d=null,p=Ze(t).offset,f=p.exception,u=new Set,_=p.isExceptionReportedToInstrumentation;_!==null&&u.add(_);let h=p.throwLocation;h!==null&&(u.add(h),u.add(h+v),u.add(h+2*v));let g=65536,b=Memory.alloc(g);return Memory.patchCode(b,g,E=>{d=l(E,b,i,c,f,u,n)}),d._code=b,d._callback=n,d}function so(t,e,n,r,o,i,s){let c={},a=new Set,l=[n];for(;l.length>0;){let h=l.shift();if(Object.values(c).some(({begin:M,end:O})=>h.compare(M)>=0&&h.compare(O)<0))continue;let b=h.toString(),E={begin:h},C=null,A=!1;do{if(h.equals(r)){A=!0;break}let M=Instruction.parse(h);C=M;let O=c[M.address.toString()];if(O!==void 0){delete c[O.begin.toString()],c[b]=O,O.begin=E.begin,E=null;break}let k=null;switch(M.mnemonic){case"jmp":k=ptr(M.operands[0].value),A=!0;break;case"je":case"jg":case"jle":case"jne":case"js":k=ptr(M.operands[0].value);break;case"ret":A=!0;break}k!==null&&(a.add(k.toString()),l.push(k),l.sort((N,S)=>N.compare(S))),h=M.next}while(!A);E!==null&&(E.end=C.address.add(C.size),c[b]=E)}let d=Object.keys(c).map(h=>c[h]);d.sort((h,g)=>h.begin.compare(g.begin));let p=c[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new X86Writer(t,{pc:e}),u=!1,_=null;return d.forEach(h=>{let g=h.end.sub(h.begin).toInt32(),b=new X86Relocator(h.begin,f),E;for(;(E=b.readOne())!==0;){let C=b.input,{mnemonic:A}=C,M=C.address.toString();a.has(M)&&f.putLabel(M);let O=!0;switch(A){case"jmp":f.putJmpNearLabel(fe(C.operands[0])),O=!1;break;case"je":case"jg":case"jle":case"jne":case"js":f.putJccNearLabel(A,fe(C.operands[0]),"no-hint"),O=!1;break;case"mov":{let[k,N]=C.operands;if(k.type==="mem"&&N.type==="imm"){let S=k.value,L=S.disp;if(L===o&&N.value.valueOf()===0){if(_=S.base,f.putPushfx(),f.putPushax(),f.putMovRegReg("xbp","xsp"),v===4)f.putAndRegU32("esp",4294967280);else{let j=_!=="rdi"?"rdi":"rsi";f.putMovRegU64(j,uint64("0xfffffffffffffff0")),f.putAndRegReg("rsp",j)}f.putCallAddressWithAlignedArguments(s,[_]),f.putMovRegReg("xsp","xbp"),f.putPopax(),f.putPopfx(),u=!0,O=!1}else i.has(L)&&S.base===_&&(O=!1)}break}case"call":{let k=C.operands[0];k.type==="mem"&&k.value.disp===Rt&&(v===4?(f.putPopReg("eax"),f.putMovRegRegOffsetPtr("eax","eax",4),f.putPushReg("eax")):f.putMovRegRegOffsetPtr("rdi","rdi",8),f.putCallAddressWithArguments(s,[]),u=!0,O=!1);break}}if(O?b.writeAll():b.skipOne(),E===g)break}b.dispose()}),f.dispose(),u||er(),new NativeFunction(e,"void",["pointer"],W)}function Ll(t,e,n,r,o,i,s){let c={},a=new Set,l=ptr(1).not(),d=[n];for(;d.length>0;){let b=d.shift();if(Object.values(c).some(({begin:L,end:j})=>b.compare(L)>=0&&b.compare(j)<0))continue;let C=b.and(l),A=C.toString(),M=b.and(1),O={begin:C},k=null,N=!1,S=0;do{if(b.equals(r)){N=!0;break}let L=Instruction.parse(b),{mnemonic:j}=L;k=L;let R=b.and(l).toString(),D=c[R];if(D!==void 0){delete c[D.begin.toString()],c[A]=D,D.begin=O.begin,O=null;break}let U=S===0,F=null;switch(j){case"b":F=ptr(L.operands[0].value),N=U;break;case"beq.w":case"beq":case"bne":case"bne.w":case"bgt":F=ptr(L.operands[0].value);break;case"cbz":case"cbnz":F=ptr(L.operands[1].value);break;case"pop.w":U&&(N=L.operands.filter(z=>z.value==="pc").length===1);break}switch(j){case"it":S=1;break;case"itt":S=2;break;case"ittt":S=3;break;case"itttt":S=4;break;default:S>0&&S--;break}F!==null&&(a.add(F.toString()),d.push(F.or(M)),d.sort((z,X)=>z.compare(X))),b=L.next}while(!N);O!==null&&(O.end=k.address.add(k.size),c[A]=O)}let p=Object.keys(c).map(b=>c[b]);p.sort((b,E)=>b.begin.compare(E.begin));let f=c[n.and(l).toString()];p.splice(p.indexOf(f),1),p.unshift(f);let u=new ThumbWriter(t,{pc:e}),_=!1,h=null,g=null;return p.forEach(b=>{let E=new ThumbRelocator(b.begin,u),C=b.begin,A=b.end,M=0;do{if(E.readOne()===0)throw new Error("Unexpected end of block");let k=E.input;C=k.address,M=k.size;let{mnemonic:N}=k,S=C.toString();a.has(S)&&u.putLabel(S);let L=!0;switch(N){case"b":u.putBLabel(fe(k.operands[0])),L=!1;break;case"beq.w":u.putBCondLabelWide("eq",fe(k.operands[0])),L=!1;break;case"bne.w":u.putBCondLabelWide("ne",fe(k.operands[0])),L=!1;break;case"beq":case"bne":case"bgt":u.putBCondLabelWide(N.substr(1),fe(k.operands[0])),L=!1;break;case"cbz":{let j=k.operands;u.putCbzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"cbnz":{let j=k.operands;u.putCbnzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"str":case"str.w":{let j=k.operands[1].value,w=j.disp;if(w===o){h=j.base;let R=h!=="r4"?"r4":"r5",D=["r0","r1","r2","r3",R,"r9","r12","lr"];u.putPushRegs(D),u.putMrsRegReg(R,"apsr-nzcvq"),u.putCallAddressWithArguments(s,[h]),u.putMsrRegReg("apsr-nzcvq",R),u.putPopRegs(D),_=!0,L=!1}else i.has(w)&&j.base===h&&(L=!1);break}case"ldr":{let[j,w]=k.operands;if(w.type==="mem"){let R=w.value;R.base[0]==="r"&&R.disp===Rt&&(g=j.value)}break}case"blx":k.operands[0].value===g&&(u.putLdrRegRegOffset("r0","r0",4),u.putCallAddressWithArguments(s,["r0"]),_=!0,g=null,L=!1);break}L?E.writeAll():E.skipOne()}while(!C.add(M).equals(A));E.dispose()}),u.dispose(),_||er(),new NativeFunction(e.or(1),"void",["pointer"],W)}function xl(t,e,n,r,o,i,s){let c={},a=new Set,l=[n];for(;l.length>0;){let b=l.shift();if(Object.values(c).some(({begin:k,end:N})=>b.compare(k)>=0&&b.compare(N)<0))continue;let C=b.toString(),A={begin:b},M=null,O=!1;do{if(b.equals(r)){O=!0;break}let k;try{k=Instruction.parse(b)}catch(L){if(b.readU32()===0){O=!0;break}else throw L}M=k;let N=c[k.address.toString()];if(N!==void 0){delete c[N.begin.toString()],c[C]=N,N.begin=A.begin,A=null;break}let S=null;switch(k.mnemonic){case"b":S=ptr(k.operands[0].value),O=!0;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":S=ptr(k.operands[0].value);break;case"cbz":case"cbnz":S=ptr(k.operands[1].value);break;case"tbz":case"tbnz":S=ptr(k.operands[2].value);break;case"ret":O=!0;break}S!==null&&(a.add(S.toString()),l.push(S),l.sort((L,j)=>L.compare(j))),b=k.next}while(!O);A!==null&&(A.end=M.address.add(M.size),c[C]=A)}let d=Object.keys(c).map(b=>c[b]);d.sort((b,E)=>b.begin.compare(E.begin));let p=c[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new Arm64Writer(t,{pc:e});f.putBLabel("performTransition");let u=e.add(f.offset);f.putPushAllXRegisters(),f.putCallAddressWithArguments(s,["x0"]),f.putPopAllXRegisters(),f.putRet(),f.putLabel("performTransition");let _=!1,h=null,g=null;return d.forEach(b=>{let E=b.end.sub(b.begin).toInt32(),C=new Arm64Relocator(b.begin,f),A;for(;(A=C.readOne())!==0;){let M=C.input,{mnemonic:O}=M,k=M.address.toString();a.has(k)&&f.putLabel(k);let N=!0;switch(O){case"b":f.putBLabel(fe(M.operands[0])),N=!1;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":f.putBCondLabel(O.substr(2),fe(M.operands[0])),N=!1;break;case"cbz":{let S=M.operands;f.putCbzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"cbnz":{let S=M.operands;f.putCbnzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"tbz":{let S=M.operands;f.putTbzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"tbnz":{let S=M.operands;f.putTbnzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"str":{let S=M.operands,L=S[0].value,j=S[1].value,w=j.disp;L==="xzr"&&w===o?(h=j.base,f.putPushRegReg("x0","lr"),f.putMovRegReg("x0",h),f.putBlImm(u),f.putPopRegReg("x0","lr"),_=!0,N=!1):i.has(w)&&j.base===h&&(N=!1);break}case"ldr":{let S=M.operands,L=S[1].value;L.base[0]==="x"&&L.disp===Rt&&(g=S[0].value);break}case"blr":M.operands[0].value===g&&(f.putLdrRegRegOffset("x0","x0",8),f.putCallAddressWithArguments(s,["x0"]),_=!0,g=null,N=!1);break}if(N?C.writeAll():C.skipOne(),A===E)break}C.dispose()}),f.dispose(),_||er(),new NativeFunction(e,"void",["pointer"],W)}function er(){throw new Error("Unable to parse ART internals; please file a bug")}function Nl(t){let e=t["art::ArtMethod::PrettyMethod"];e!==void 0&&(Interceptor.attach(e.impl,oe.hooks.ArtMethod.prettyMethod),Interceptor.flush())}function fe(t){return ptr(t.value).toString()}function kl(t,e){return new NativeFunction(t,"pointer",e,W)}function Ml(t,e){let n=new NativeFunction(t,"void",["pointer"].concat(e),W);return function(){let r=Memory.alloc(v);return n(r,...arguments),r.readPointer()}}function At(t,e){let{arch:n}=Process;switch(n){case"ia32":case"arm64":{let r;n==="ia32"?r=He(64,s=>{let c=1+e.length,a=c*4;s.putSubRegImm("esp",a);for(let l=0;l!==c;l++){let d=l*4;s.putMovRegRegOffsetPtr("eax","esp",a+4+d),s.putMovRegOffsetPtrReg("esp",d,"eax")}s.putCallAddress(t),s.putAddRegImm("esp",a-4),s.putRet()}):r=He(32,s=>{s.putMovRegReg("x8","x0"),e.forEach((c,a)=>{s.putMovRegReg("x"+a,"x"+(a+1))}),s.putLdrRegAddress("x7",t),s.putBrReg("x7")});let o=new NativeFunction(r,"void",["pointer"].concat(e),W),i=function(...s){o(...s)};return i.handle=r,i.impl=t,i}default:{let r=new NativeFunction(t,"void",["pointer"].concat(e),W);return r.impl=t,r}}}var jt=class{constructor(){this.handle=Memory.alloc(at)}dispose(){let[e,n]=this._getData();n||J().$delete(e)}disposeToString(){let e=this.toString();return this.dispose(),e}toString(){let[e]=this._getData();return e.readUtf8String()}_getData(){let e=this.handle,n=(e.readU8()&1)===0;return[n?e.add(1):e.add(2*v).readPointer(),n]}},Un=class{$delete(){this.dispose(),J().$delete(this)}constructor(e,n){this.handle=e,this._begin=e,this._end=e.add(v),this._storage=e.add(2*v),this._elementSize=n}init(){this.begin=NULL,this.end=NULL,this.storage=NULL}dispose(){J().$delete(this.begin)}get begin(){return this._begin.readPointer()}set begin(e){this._begin.writePointer(e)}get end(){return this._end.readPointer()}set end(e){this._end.writePointer(e)}get storage(){return this._storage.readPointer()}set storage(e){this._storage.writePointer(e)}get size(){return this.end.sub(this.begin).toInt32()/this._elementSize}},ct=class t extends Un{static $new(){let e=new t(J().$new(rc));return e.init(),e}constructor(e){super(e,v)}get handles(){let e=[],n=this.begin,r=this.end;for(;!n.equals(r);)e.push(n.readPointer()),n=n.add(v);return e}},jl=0,bo=v,yo=bo+4,Ol=-1,Ot=class t{$delete(){this.dispose(),J().$delete(this)}constructor(e){this.handle=e,this._link=e.add(jl),this._numberOfReferences=e.add(bo)}init(e,n){this.link=e,this.numberOfReferences=n}dispose(){}get link(){return new t(this._link.readPointer())}set link(e){this._link.writePointer(e)}get numberOfReferences(){return this._numberOfReferences.readS32()}set numberOfReferences(e){this._numberOfReferences.writeS32(e)}},Eo=Dl(yo),vo=Eo+v,Rl=vo+v,lt=class t extends Ot{static $new(e,n){let r=new t(J().$new(Rl));return r.init(e,n),r}constructor(e){super(e),this._self=e.add(Eo),this._currentScope=e.add(vo);let o=(64-v-4-4)/4;this._scopeLayout=st.layoutForCapacity(o),this._topHandleScopePtr=null}init(e,n){let r=e.add(Ze(n).offset.topHandleScope);this._topHandleScopePtr=r,super.init(r.readPointer(),Ol),this.self=e,this.currentScope=st.$new(this._scopeLayout),r.writePointer(this)}dispose(){this._topHandleScopePtr.writePointer(this.link);let e;for(;(e=this.currentScope)!==null;){let n=e.link;e.$delete(),this.currentScope=n}}get self(){return this._self.readPointer()}set self(e){this._self.writePointer(e)}get currentScope(){let e=this._currentScope.readPointer();return e.isNull()?null:new st(e,this._scopeLayout)}set currentScope(e){this._currentScope.writePointer(e)}newHandle(e){return this.currentScope.newHandle(e)}},st=class t extends Ot{static $new(e){let n=new t(J().$new(e.size),e);return n.init(),n}constructor(e,n){super(e);let{offset:r}=n;this._refsStorage=e.add(r.refsStorage),this._pos=e.add(r.pos),this._layout=n}init(){super.init(NULL,this._layout.numberOfReferences),this.pos=0}get pos(){return this._pos.readU32()}set pos(e){this._pos.writeU32(e)}newHandle(e){let n=this.pos,r=this._refsStorage.add(n*4);return r.writeS32(e.toInt32()),this.pos=n+1,r}static layoutForCapacity(e){let n=yo,r=n+e*4;return{size:r+4,numberOfReferences:e,offset:{refsStorage:n,pos:r}}}},Pl={arm:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let i=[26625,18947,17041,53505,19202,18200,18288,48896],s=i.length*2,c=s+4,a=c+4;return Memory.patchCode(r,a,function(l){i.forEach((d,p)=>{l.add(p*2).writeU16(d)}),l.add(s).writeS32(t),l.add(c).writePointer(o)}),r.or(1)},arm64:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let i=[3107979265,402653378,1795293247,1409286241,1476395139,3592355936,3596551104],s=i.length*4,c=s+4,a=c+8;return Memory.patchCode(r,a,function(l){i.forEach((d,p)=>{l.add(p*4).writeU32(d)}),l.add(s).writeS32(t),l.add(c).writePointer(o)}),r}};function tr(t,e){return(Pl[Process.arch]||Fl)(t,e)}function Fl(t,e){return new NativeCallback(n=>{n.readS32()===t&&e(n)},"void",["pointer","pointer"])}function Dl(t){let e=t%v;return e!==0?t+v-e:t}var Ul=4,{pointerSize:V}=Process,Bl=256,zl=65536,Vl=131072,Jl=33554432,Gl=67108864,$l=134217728,De={exceptions:"propagate"},Co=le(od),Hl=le(sd),Zl=le(td),nr=null,rr=!1,Ut=new Map,ut=new Map;function Ce(){return nr===null&&(nr=ql()),nr}function ql(){let t=Process.enumerateModules().filter(a=>/jvm.(dll|dylib|so)$/.test(a.name));if(t.length===0)return null;let e=t[0],n={flavor:"jvm"},r=Process.platform==="windows"?[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]],"VMThread::execute":["VMThread::execute","void",["pointer"]],"Method::size":["Method::size","int",["int"]],"Method::set_native_function":["Method::set_native_function","void",["pointer","pointer","int"]],"Method::clear_native_function":["Method::clear_native_function","void",["pointer"]],"Method::jmethod_id":["Method::jmethod_id","pointer",["pointer"]],"ClassLoaderDataGraph::classes_do":["ClassLoaderDataGraph::classes_do","void",["pointer"]],"NMethodSweeper::sweep_code_cache":["NMethodSweeper::sweep_code_cache","void",[]],"OopMapCache::flush_obsolete_entries":["OopMapCache::flush_obsolete_entries","void",["pointer"]]},variables:{"VM_RedefineClasses::`vftable'":function(a){this.vtableRedefineClasses=a},"VM_RedefineClasses::doit":function(a){this.redefineClassesDoIt=a},"VM_RedefineClasses::doit_prologue":function(a){this.redefineClassesDoItPrologue=a},"VM_RedefineClasses::doit_epilogue":function(a){this.redefineClassesDoItEpilogue=a},"VM_RedefineClasses::allow_nested_vm_operations":function(a){this.redefineClassesAllow=a},"NMethodSweeper::_traversals":function(a){this.traversals=a},"NMethodSweeper::_should_sweep":function(a){this.shouldSweep=a}},optionals:[]}]:[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],_ZN6Method4sizeEb:["Method::size","int",["int"]],_ZN6Method19set_native_functionEPhb:["Method::set_native_function","void",["pointer","pointer","int"]],_ZN6Method21clear_native_functionEv:["Method::clear_native_function","void",["pointer"]],_ZN6Method24restore_unshareable_infoEP10JavaThread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method24restore_unshareable_infoEP6Thread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method11link_methodERK12methodHandleP10JavaThread:["Method::link_method","void",["pointer","pointer","pointer"]],_ZN6Method10jmethod_idEv:["Method::jmethod_id","pointer",["pointer"]],_ZN6Method10clear_codeEv:function(a){let l=new NativeFunction(a,"void",["pointer"],De);this["Method::clear_code"]=function(d){l(d)}},_ZN6Method10clear_codeEb:function(a){let l=new NativeFunction(a,"void",["pointer","int"],De),d=0;this["Method::clear_code"]=function(p){l(p,d)}},_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass:["VM_RedefineClasses::mark_dependent_code","void",["pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeEv:["VM_RedefineClasses::flush_dependent_code","void",[]],_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN19ResolvedMethodTable21adjust_method_entriesEPb:["ResolvedMethodTable::adjust_method_entries","void",["pointer"]],_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb:["MemberNameTable::adjust_method_entries","void",["pointer","pointer","pointer"]],_ZN17ConstantPoolCache21adjust_method_entriesEPb:function(a){let l=new NativeFunction(a,"void",["pointer","pointer"],De);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){l(d,f)}},_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb:function(a){let l=new NativeFunction(a,"void",["pointer","pointer","pointer"],De);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){l(d,p,f)}},_ZN20ClassLoaderDataGraph10classes_doEP12KlassClosure:["ClassLoaderDataGraph::classes_do","void",["pointer"]],_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb:["ClassLoaderDataGraph::clean_deallocate_lists","void",["int"]],_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_:["JavaThread::thread_from_jni_environment","pointer",["pointer"]],_ZN8VMThread7executeEP12VM_Operation:["VMThread::execute","void",["pointer"]],_ZN11OopMapCache22flush_obsolete_entriesEv:["OopMapCache::flush_obsolete_entries","void",["pointer"]],_ZN14NMethodSweeper11force_sweepEv:["NMethodSweeper::force_sweep","void",[]],_ZN14NMethodSweeper16sweep_code_cacheEv:["NMethodSweeper::sweep_code_cache","void",[]],_ZN14NMethodSweeper17sweep_in_progressEv:["NMethodSweeper::sweep_in_progress","bool",[]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]]},variables:{_ZN18VM_RedefineClasses14_the_class_oopE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses10_the_classE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass:function(a){this.doKlass=a},_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass:function(a){this.doKlass=a},_ZTV18VM_RedefineClasses:function(a){this.vtableRedefineClasses=a},_ZN18VM_RedefineClasses4doitEv:function(a){this.redefineClassesDoIt=a},_ZN18VM_RedefineClasses13doit_prologueEv:function(a){this.redefineClassesDoItPrologue=a},_ZN18VM_RedefineClasses13doit_epilogueEv:function(a){this.redefineClassesDoItEpilogue=a},_ZN18VM_RedefineClassesD0Ev:function(a){this.redefineClassesDispose0=a},_ZN18VM_RedefineClassesD1Ev:function(a){this.redefineClassesDispose1=a},_ZNK18VM_RedefineClasses26allow_nested_vm_operationsEv:function(a){this.redefineClassesAllow=a},_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream:function(a){this.redefineClassesOnError=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread:function(a){this.createNewDefaultVtableIndices=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread:function(a){this.createNewDefaultVtableIndices=a},_ZN19Abstract_VM_Version19jre_release_versionEv:function(a){let d=new NativeFunction(a,"pointer",[],De)().readCString();this.version=d.startsWith("1.8")?8:d.startsWith("9.")?9:parseInt(d.slice(0,2),10),this.versionS=d},_ZN14NMethodSweeper11_traversalsE:function(a){this.traversals=a},_ZN14NMethodSweeper21_sweep_fractions_leftE:function(a){this.fractions=a},_ZN14NMethodSweeper13_should_sweepE:function(a){this.shouldSweep=a}},optionals:["_ZN6Method24restore_unshareable_infoEP10JavaThread","_ZN6Method24restore_unshareable_infoEP6Thread","_ZN6Method11link_methodERK12methodHandleP10JavaThread","_ZN6Method10clear_codeEv","_ZN6Method10clear_codeEb","_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass","_ZN18VM_RedefineClasses20flush_dependent_codeEv","_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread","_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread","_ZN19ResolvedMethodTable21adjust_method_entriesEPb","_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb","_ZN17ConstantPoolCache21adjust_method_entriesEPb","_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb","_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb","_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_","_ZN14NMethodSweeper11force_sweepEv","_ZN14NMethodSweeper17sweep_in_progressEv","_ZN18VM_RedefineClasses14_the_class_oopE","_ZN18VM_RedefineClasses10_the_classE","_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass","_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass","_ZN18VM_RedefineClassesD0Ev","_ZN18VM_RedefineClassesD1Ev","_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread","_ZN14NMethodSweeper21_sweep_fractions_leftE"]}],o=[];if(r.forEach(function(a){let l=a.module,d=a.functions||{},p=a.variables||{},f=new Set(a.optionals||[]),u=l.enumerateExports().reduce(function(h,g){return h[g.name]=g,h},{}),_=l.enumerateSymbols().reduce(function(h,g){return h[g.name]=g,h},u);Object.keys(d).forEach(function(h){let g=_[h];if(g!==void 0){let b=d[h];typeof b=="function"?b.call(n,g.address):n[b[0]]=new NativeFunction(g.address,b[1],b[2],De)}else f.has(h)||o.push(h)}),Object.keys(p).forEach(function(h){let g=_[h];g!==void 0?p[h].call(n,g.address):f.has(h)||o.push(h)})}),o.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+o.join(", "));let i=Memory.alloc(V),s=Memory.alloc(Ul);if(de("JNI_GetCreatedJavaVMs",n.JNI_GetCreatedJavaVMs(i,1,s)),s.readInt()===0)return null;n.vm=i.readPointer();let c=Process.platform==="windows"?{$new:["??2@YAPEAX_K@Z","pointer",["ulong"]],$delete:["??3@YAXPEAX@Z","void",["pointer"]]}:{$new:["_Znwm","pointer",["ulong"]],$delete:["_ZdlPv","void",["pointer"]]};for(let[a,[l,d,p]]of Object.entries(c)){let f=Module.findGlobalExportByName(l);if(f===null&&(f=DebugSymbol.fromName(l).address,f.isNull()))throw new Error(`unable to find C++ allocator API, missing: '${l}'`);n[a]=new NativeFunction(f,d,p,De)}return n.jvmti=Wl(n),n["JavaThread::thread_from_jni_environment"]===void 0&&(n["JavaThread::thread_from_jni_environment"]=Ql(n)),n}function Wl(t){let e=new Ie(t),n;return e.perform(()=>{let r=e.tryGetEnvHandle(Et.v1_0);if(r===null)throw new Error("JVMTI not available");n=new Le(r,e);let o=Memory.alloc(8);o.writeU64(vt.canTagObjects);let i=n.addCapabilities(o);de("getEnvJvmti::AddCapabilities",i)}),n}var Kl={x64:Yl};function Ql(t){let e=null,n=Kl[Process.arch];if(n!==void 0){let o=new Ie(t).perform(i=>i.handle.readPointer().add(6*V).readPointer());e=xe(o,n,{limit:11})}return e===null?()=>{throw new Error("Unable to make thread_from_jni_environment() helper for the current architecture")}:r=>r.add(e)}function Yl(t){if(t.mnemonic!=="lea")return null;let{base:e,disp:n}=t.operands[1].value;return e==="rdi"&&n<0?n:null}function To(t,e){}var or=class{constructor(e){this.methodId=e,this.method=e.readPointer(),this.originalMethod=null,this.newMethod=null,this.resolved=null,this.impl=null,this.key=e.toString(16)}replace(e,n,r,o,i){let{key:s}=this,c=ut.get(s);c!==void 0&&(ut.delete(s),this.method=c.method,this.originalMethod=c.originalMethod,this.newMethod=c.newMethod,this.resolved=c.resolved),this.impl=e,Ut.set(s,this),So(o)}revert(e){let{key:n}=this;Ut.delete(n),ut.set(n,this),So(e)}resolveTarget(e,n,r,o){let{resolved:i,originalMethod:s,methodId:c}=this;if(i!==null)return i;if(s===null)return c;s.oldMethod.vtableIndexPtr.writeS32(-2);let l=Memory.alloc(V);return l.writePointer(this.method),this.resolved=l,l}};function So(t){rr||(rr=!0,Script.nextTick(Xl,t))}function Xl(t){let e=new Map(Ut),n=new Map(ut);Ut.clear(),ut.clear(),rr=!1,t.perform(r=>{let o=Ce(),i=o["JavaThread::thread_from_jni_environment"](r.handle),s=!1;Ao(()=>{e.forEach(c=>{let{method:a,originalMethod:l,impl:d,methodId:p,newMethod:f}=c;l===null?(c.originalMethod=xo(a),c.newMethod=nd(a,d,i),wo(c.newMethod,p,i)):o["Method::set_native_function"](f.method,d,0)}),n.forEach(c=>{let{originalMethod:a,methodId:l,newMethod:d}=c;if(a!==null){rd(a);let p=a.oldMethod;p.oldMethod=d,wo(p,l,i),s=!0}})}),s&&ed(r.handle)})}function ed(t){let{fractions:e,shouldSweep:n,traversals:r,"NMethodSweeper::sweep_code_cache":o,"NMethodSweeper::sweep_in_progress":i,"NMethodSweeper::force_sweep":s,JVM_Sleep:c}=Ce();if(s!==void 0)Thread.sleep(.05),s(),Thread.sleep(.05),s();else{let a=r.readS64(),l=a+2;for(;l>a;)e.writeS32(1),c(t,NULL,50),i()||Ao(()=>{Thread.sleep(.05)}),n.readU8()===0&&(e.writeS32(1),o()),a=r.readS64()}}function Ao(t,e,n){let{execute:r,vtable:o,vtableSize:i,doItOffset:s,prologueOffset:c,epilogueOffset:a}=Zl(),l=Memory.dup(o,i),d=Memory.alloc(V*25);d.writePointer(l);let p=new NativeCallback(t,"void",["pointer"]);l.add(s).writePointer(p);let f=null;e!==void 0&&(f=new NativeCallback(e,"int",["pointer"]),l.add(c).writePointer(f));let u=null;n!==void 0&&(u=new NativeCallback(n,"void",["pointer"]),l.add(a).writePointer(u)),r(d)}function td(){let{vtableRedefineClasses:t,redefineClassesDoIt:e,redefineClassesDoItPrologue:n,redefineClassesDoItEpilogue:r,redefineClassesOnError:o,redefineClassesAllow:i,redefineClassesDispose0:s,redefineClassesDispose1:c,"VMThread::execute":a}=Ce(),l=t.add(2*V),d=15*V,p=Memory.dup(l,d),f=new NativeCallback(()=>{},"void",["pointer"]),u,_,h;for(let g=0;g!==d;g+=V){let b=p.add(g),E=b.readPointer();o!==void 0&&E.equals(o)||s!==void 0&&E.equals(s)||c!==void 0&&E.equals(c)?b.writePointer(f):E.equals(e)?u=g:E.equals(n)?(_=g,b.writePointer(i)):E.equals(r)&&(h=g,b.writePointer(f))}return{execute:a,emptyCallback:f,vtable:p,vtableSize:d,doItOffset:u,prologueOffset:_,epilogueOffset:h}}function Lo(t){return new or(t)}function wo(t,e,n){let{method:r,oldMethod:o}=t,i=Ce();t.methodsArray.add(t.methodIndex*V).writePointer(r),t.vtableIndex>=0&&t.vtable.add(t.vtableIndex*V).writePointer(r),e.writePointer(r),o.accessFlagsPtr.writeU32((o.accessFlags|zl|Vl)>>>0);let s=i["OopMapCache::flush_obsolete_entries"];if(s!==void 0){let{oopMapCache:_}=t;_.isNull()||s(_)}let c=i["VM_RedefineClasses::mark_dependent_code"],a=i["VM_RedefineClasses::flush_dependent_code"];c!==void 0?(c(NULL,t.instanceKlass),a()):a(NULL,t.instanceKlass,n);let l=Memory.alloc(1);l.writeU8(1),i["ConstantPoolCache::adjust_method_entries"](t.cache,t.instanceKlass,l);let d=Memory.alloc(3*V),p=Memory.alloc(V);p.writePointer(i.doKlass),d.writePointer(p),d.add(V).writePointer(n),d.add(2*V).writePointer(n),i.redefineClass!==void 0&&i.redefineClass.writePointer(t.instanceKlass),i["ClassLoaderDataGraph::classes_do"](d);let f=i["ResolvedMethodTable::adjust_method_entries"];if(f!==void 0)f(l);else{let{memberNames:_}=t;if(!_.isNull()){let h=i["MemberNameTable::adjust_method_entries"];h!==void 0&&h(_,t.instanceKlass,l)}}let u=i["ClassLoaderDataGraph::clean_deallocate_lists"];u!==void 0&&u(0)}function nd(t,e,n){let r=Ce(),o=xo(t);o.constPtr.writePointer(o.const);let i=(o.accessFlags|Bl|Jl|Gl|$l)>>>0;if(o.accessFlagsPtr.writeU32(i),o.signatureHandler.writePointer(NULL),o.adapter.writePointer(NULL),o.i2iEntry.writePointer(NULL),r["Method::clear_code"](o.method),o.dataPtr.writePointer(NULL),o.countersPtr.writePointer(NULL),o.stackmapPtr.writePointer(NULL),r["Method::clear_native_function"](o.method),r["Method::set_native_function"](o.method,e,0),r["Method::restore_unshareable_info"](o.method,n),r.version>=17){let s=Memory.alloc(2*V);s.writePointer(o.method),s.add(V).writePointer(n),r["Method::link_method"](o.method,s,n)}return o}function xo(t){let e=Co(),n=t.add(e.method.constMethodOffset).readPointer(),r=n.add(e.constMethod.sizeOffset).readS32()*V,o=Memory.alloc(r+e.method.size);Memory.copy(o,n,r);let i=o.add(r);Memory.copy(i,t,e.method.size);let s=Io(i,o,r),c=Io(t,n,r);return s.oldMethod=c,s}function Io(t,e,n){let r=Ce(),o=Co(),i=t.add(o.method.constMethodOffset),s=t.add(o.method.methodDataOffset),c=t.add(o.method.methodCountersOffset),a=t.add(o.method.accessFlagsOffset),l=a.readU32(),d=o.getAdapterPointer(t,e),p=t.add(o.method.i2iEntryOffset),f=t.add(o.method.signatureHandlerOffset),u=e.add(o.constMethod.constantPoolOffset).readPointer(),_=e.add(o.constMethod.stackmapDataOffset),h=u.add(o.constantPool.instanceKlassOffset).readPointer(),g=u.add(o.constantPool.cacheOffset).readPointer(),b=Hl(),E=h.add(b.methodsOffset).readPointer(),C=E.readS32(),A=E.add(V),M=e.add(o.constMethod.methodIdnumOffset).readU16(),O=t.add(o.method.vtableIndexOffset),k=O.readS32(),N=h.add(b.vtableOffset),S=h.add(b.oopMapCacheOffset).readPointer(),L=r.version>=10?h.add(b.memberNamesOffset).readPointer():NULL;return{method:t,methodSize:o.method.size,const:e,constSize:n,constPtr:i,dataPtr:s,countersPtr:c,stackmapPtr:_,instanceKlass:h,methodsArray:A,methodsCount:C,methodIndex:M,vtableIndex:k,vtableIndexPtr:O,vtable:N,accessFlags:l,accessFlagsPtr:a,adapter:d,i2iEntry:p,signatureHandler:f,memberNames:L,cache:g,oopMapCache:S}}function rd(t){let{oldMethod:e}=t;e.accessFlagsPtr.writeU32(e.accessFlags),e.vtableIndexPtr.writeS32(e.vtableIndex)}function od(){let t=Ce(),{version:e}=t,n;e>=17?n="method:early":e>=9&&e<=16?n="const-method":n="method:late";let o=t["Method::size"](1)*V,i=V,s=2*V,c=3*V,a=4*V,l=n==="method:early"?V:0,d=a+l,p=d+4,f=p+4+8,u=f+V,_=l!==0?a:u,h=o-2*V,g=o-V,b=8,E=b+V,C=E+V,A=n==="const-method"?V:0,M=C+A,O=M+14,k=2*V,N=3*V;return{getAdapterPointer:A!==0?function(L,j){return j.add(C)}:function(L,j){return L.add(_)},method:{size:o,constMethodOffset:i,methodDataOffset:s,methodCountersOffset:c,accessFlagsOffset:d,vtableIndexOffset:p,i2iEntryOffset:f,nativeFunctionOffset:h,signatureHandlerOffset:g},constMethod:{constantPoolOffset:b,stackmapDataOffset:E,sizeOffset:M,methodIdnumOffset:O},constantPool:{cacheOffset:k,instanceKlassOffset:N}}}var id={x64:ad};function sd(){let{version:t,createNewDefaultVtableIndices:e}=Ce(),n=id[Process.arch];if(n===void 0)throw new Error(`Missing vtable offset parser for ${Process.arch}`);let r=xe(e,n,{limit:32});if(r===null)throw new Error("Unable to deduce vtable offset");let o=t>=10&&t<=11||t>=15?17:18,i=r-7*V,s=r-17*V,c=r-o*V;return{vtableOffset:r,methodsOffset:i,memberNamesOffset:s,oopMapCacheOffset:c}}function ad(t){if(t.mnemonic!=="mov")return null;let e=t.operands[0];if(e.type!=="mem")return null;let{value:n}=e;if(n.scale!==1)return null;let{disp:r}=n;return r<256?null:r+16}var No=J;try{dt()}catch{No=Ce}var pt=No;var cd=`#include +#include + +#define kAccStatic 0x0008 +#define kAccConstructor 0x00010000 + +typedef struct _Model Model; +typedef struct _EnumerateMethodsContext EnumerateMethodsContext; + +typedef struct _JavaApi JavaApi; +typedef struct _JavaClassApi JavaClassApi; +typedef struct _JavaMethodApi JavaMethodApi; +typedef struct _JavaFieldApi JavaFieldApi; + +typedef struct _JNIEnv JNIEnv; +typedef guint8 jboolean; +typedef gint32 jint; +typedef jint jsize; +typedef gpointer jobject; +typedef jobject jclass; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jobjectArray; +typedef gpointer jfieldID; +typedef gpointer jmethodID; + +typedef struct _jvmtiEnv jvmtiEnv; +typedef enum +{ + JVMTI_ERROR_NONE = 0 +} jvmtiError; + +typedef struct _ArtApi ArtApi; +typedef guint32 ArtHeapReference; +typedef struct _ArtObject ArtObject; +typedef struct _ArtClass ArtClass; +typedef struct _ArtClassLinker ArtClassLinker; +typedef struct _ArtClassVisitor ArtClassVisitor; +typedef struct _ArtClassVisitorVTable ArtClassVisitorVTable; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtString ArtString; + +typedef union _StdString StdString; +typedef struct _StdStringShort StdStringShort; +typedef struct _StdStringLong StdStringLong; + +typedef void (* ArtVisitClassesFunc) (ArtClassLinker * linker, ArtClassVisitor * visitor); +typedef const char * (* ArtGetClassDescriptorFunc) (ArtClass * klass, StdString * storage); +typedef void (* ArtPrettyMethodFunc) (StdString * result, ArtMethod * method, jboolean with_signature); + +struct _Model +{ + GHashTable * members; +}; + +struct _EnumerateMethodsContext +{ + GPatternSpec * class_query; + GPatternSpec * method_query; + jboolean include_signature; + jboolean ignore_case; + jboolean skip_system_classes; + GHashTable * groups; +}; + +struct _JavaClassApi +{ + jmethodID get_declared_methods; + jmethodID get_declared_fields; +}; + +struct _JavaMethodApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaFieldApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaApi +{ + jvmtiEnv * jvmti; + JavaClassApi clazz; + JavaMethodApi method; + JavaFieldApi field; +}; + +struct _JNIEnv +{ + gpointer * functions; +}; + +struct _jvmtiEnv +{ + gpointer * functions; +}; + +struct _ArtApi +{ + gboolean available; + + guint class_offset_ifields; + guint class_offset_methods; + guint class_offset_sfields; + guint class_offset_copied_methods_offset; + + guint method_size; + guint method_offset_access_flags; + + guint field_size; + guint field_offset_access_flags; + + guint alignment_padding; + + ArtClassLinker * linker; + ArtVisitClassesFunc visit_classes; + ArtGetClassDescriptorFunc get_class_descriptor; + ArtPrettyMethodFunc pretty_method; + + void (* free) (gpointer mem); +}; + +struct _ArtObject +{ + ArtHeapReference klass; + ArtHeapReference monitor; +}; + +struct _ArtClass +{ + ArtObject parent; + + ArtHeapReference class_loader; +}; + +struct _ArtClassVisitor +{ + ArtClassVisitorVTable * vtable; + gpointer user_data; +}; + +struct _ArtClassVisitorVTable +{ + void (* reserved1) (ArtClassVisitor * self); + void (* reserved2) (ArtClassVisitor * self); + jboolean (* visit) (ArtClassVisitor * self, ArtClass * klass); +}; + +struct _ArtString +{ + ArtObject parent; + + gint32 count; + guint32 hash_code; + + union + { + guint16 value[0]; + guint8 value_compressed[0]; + }; +}; + +struct _StdStringShort +{ + guint8 size; + gchar data[(3 * sizeof (gpointer)) - sizeof (guint8)]; +}; + +struct _StdStringLong +{ + gsize capacity; + gsize size; + gchar * data; +}; + +union _StdString +{ + StdStringShort s; + StdStringLong l; +}; + +static void model_add_method (Model * self, const gchar * name, jmethodID id, jint modifiers); +static void model_add_field (Model * self, const gchar * name, jfieldID id, jint modifiers); +static void model_free (Model * model); + +static jboolean collect_matching_class_methods (ArtClassVisitor * self, ArtClass * klass); +static gchar * finalize_method_groups_to_json (GHashTable * groups); +static GPatternSpec * make_pattern_spec (const gchar * pattern, jboolean ignore_case); +static gchar * class_name_from_signature (const gchar * signature); +static gchar * format_method_signature (const gchar * name, const gchar * signature); +static void append_type (GString * output, const gchar ** type); + +static gpointer read_art_array (gpointer object_base, guint field_offset, guint length_size, guint * length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_c_str (StdString * self); + +extern GMutex lock; +extern GArray * models; +extern JavaApi java_api; +extern ArtApi art_api; + +void +init (void) +{ + g_mutex_init (&lock); + models = g_array_new (FALSE, FALSE, sizeof (Model *)); +} + +void +finalize (void) +{ + guint n, i; + + n = models->len; + for (i = 0; i != n; i++) + { + Model * model = g_array_index (models, Model *, i); + model_free (model); + } + + g_array_unref (models); + g_mutex_clear (&lock); +} + +Model * +model_new (jclass class_handle, + gpointer class_object, + JNIEnv * env) +{ + Model * model; + GHashTable * members; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * funcs = env->functions; + jmethodID (* from_reflected_method) (JNIEnv *, jobject) = funcs[7]; + jfieldID (* from_reflected_field) (JNIEnv *, jobject) = funcs[8]; + jobject (* to_reflected_method) (JNIEnv *, jclass, jmethodID, jboolean) = funcs[9]; + jobject (* to_reflected_field) (JNIEnv *, jclass, jfieldID, jboolean) = funcs[12]; + void (* delete_local_ref) (JNIEnv *, jobject) = funcs[23]; + jobject (* call_object_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[34]; + jint (* call_int_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[49]; + const char * (* get_string_utf_chars) (JNIEnv *, jstring, jboolean *) = funcs[169]; + void (* release_string_utf_chars) (JNIEnv *, jstring, const char *) = funcs[170]; + jsize (* get_array_length) (JNIEnv *, jarray) = funcs[171]; + jobject (* get_object_array_element) (JNIEnv *, jobjectArray, jsize) = funcs[173]; + jsize n, i; + + model = g_new (Model, 1); + + members = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + model->members = members; + + if (jvmti != NULL) + { + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_fields) (jvmtiEnv *, jclass, jint *, jfieldID **) = jf[53]; + jvmtiError (* get_field_name) (jvmtiEnv *, jclass, jfieldID, char **, char **, char **) = jf[60]; + jvmtiError (* get_field_modifiers) (jvmtiEnv *, jclass, jfieldID, jint *) = jf[62]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_method_modifiers) (jvmtiEnv *, jmethodID, jint *) = jf[66]; + jint method_count; + jmethodID * methods; + jint field_count; + jfieldID * fields; + char * name; + jint modifiers; + + get_class_methods (jvmti, class_handle, &method_count, &methods); + for (i = 0; i != method_count; i++) + { + jmethodID method = methods[i]; + + get_method_name (jvmti, method, &name, NULL, NULL); + get_method_modifiers (jvmti, method, &modifiers); + + model_add_method (model, name, method, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, methods); + + get_class_fields (jvmti, class_handle, &field_count, &fields); + for (i = 0; i != field_count; i++) + { + jfieldID field = fields[i]; + + get_field_name (jvmti, class_handle, field, &name, NULL, NULL); + get_field_modifiers (jvmti, class_handle, field, &modifiers); + + model_add_field (model, name, field, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, fields); + } + else if (art_api.available) + { + gpointer elements; + guint n, i; + const guint field_arrays[] = { + art_api.class_offset_ifields, + art_api.class_offset_sfields + }; + guint field_array_cursor; + gboolean merged_fields = art_api.class_offset_sfields == 0; + + elements = read_art_array (class_object, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) (class_object + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + jmethodID id; + guint32 access_flags; + jboolean is_static; + jobject method, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) (id + art_api.method_offset_access_flags); + if ((access_flags & kAccConstructor) != 0) + continue; + is_static = (access_flags & kAccStatic) != 0; + method = to_reflected_method (env, class_handle, id, is_static); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + + for (field_array_cursor = 0; field_array_cursor != G_N_ELEMENTS (field_arrays); field_array_cursor++) + { + jboolean is_static; + + if (field_arrays[field_array_cursor] == 0) + continue; + + if (!merged_fields) + is_static = field_array_cursor == 1; + + elements = read_art_array (class_object, field_arrays[field_array_cursor], sizeof (guint32), &n); + for (i = 0; i != n; i++) + { + jfieldID id; + guint32 access_flags; + jobject field, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.field_size); + + access_flags = *(guint32 *) (id + art_api.field_offset_access_flags); + if (merged_fields) + is_static = (access_flags & kAccStatic) != 0; + field = to_reflected_field (env, class_handle, id, is_static); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + } + } + else + { + jobject elements; + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_methods); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject method, name; + const char * name_str; + jmethodID id; + jint modifiers; + + method = get_object_array_element (env, elements, i); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_method (env, method); + modifiers = call_int_method (env, method, java_api.method.get_modifiers); + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + delete_local_ref (env, elements); + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_fields); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject field, name; + const char * name_str; + jfieldID id; + jint modifiers; + + field = get_object_array_element (env, elements, i); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_field (env, field); + modifiers = call_int_method (env, field, java_api.field.get_modifiers); + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + delete_local_ref (env, elements); + } + + g_mutex_lock (&lock); + g_array_append_val (models, model); + g_mutex_unlock (&lock); + + return model; +} + +static void +model_add_method (Model * self, + const gchar * name, + jmethodID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + const gchar * value; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + value = g_hash_table_lookup (members, key); + if (value == NULL) + g_hash_table_insert (members, key, g_strdup_printf ("m:%c0x%zx", type, id)); + else + g_hash_table_insert (members, key, g_strdup_printf ("%s:%c0x%zx", value, type, id)); +} + +static void +model_add_field (Model * self, + const gchar * name, + jfieldID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + while (g_hash_table_contains (members, key)) + { + gchar * new_key = g_strdup_printf ("_%s", key); + g_free (key); + key = new_key; + } + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + g_hash_table_insert (members, key, g_strdup_printf ("f:%c0x%zx", type, id)); +} + +static void +model_free (Model * model) +{ + g_hash_table_unref (model->members); + + g_free (model); +} + +gboolean +model_has (Model * self, + const gchar * member) +{ + return g_hash_table_contains (self->members, member); +} + +const gchar * +model_find (Model * self, + const gchar * member) +{ + return g_hash_table_lookup (self->members, member); +} + +gchar * +model_list (Model * self) +{ + GString * result; + GHashTableIter iter; + guint i; + const gchar * name; + + result = g_string_sized_new (128); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, self->members); + for (i = 0; g_hash_table_iter_next (&iter, (gpointer *) &name, NULL); i++) + { + if (i > 0) + g_string_append_c (result, ','); + + g_string_append_c (result, '"'); + g_string_append (result, name); + g_string_append_c (result, '"'); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +gchar * +enumerate_methods_art (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes) +{ + gchar * result; + EnumerateMethodsContext ctx; + ArtClassVisitor visitor; + ArtClassVisitorVTable visitor_vtable = { NULL, }; + + ctx.class_query = make_pattern_spec (class_query, ignore_case); + ctx.method_query = make_pattern_spec (method_query, ignore_case); + ctx.include_signature = include_signature; + ctx.ignore_case = ignore_case; + ctx.skip_system_classes = skip_system_classes; + ctx.groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + visitor.vtable = &visitor_vtable; + visitor.user_data = &ctx; + + visitor_vtable.visit = collect_matching_class_methods; + + art_api.visit_classes (art_api.linker, &visitor); + + result = finalize_method_groups_to_json (ctx.groups); + + g_hash_table_unref (ctx.groups); + g_pattern_spec_free (ctx.method_query); + g_pattern_spec_free (ctx.class_query); + + return result; +} + +static jboolean +collect_matching_class_methods (ArtClassVisitor * self, + ArtClass * klass) +{ + EnumerateMethodsContext * ctx = self->user_data; + const char * descriptor; + StdString descriptor_storage = { 0, }; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + JsonBuilder * group; + size_t class_name_length; + GHashTable * seen_method_names; + gpointer elements; + guint n, i; + + if (ctx->skip_system_classes && klass->class_loader == 0) + goto skip_class; + + descriptor = art_api.get_class_descriptor (klass, &descriptor_storage); + if (descriptor[0] != 'L') + goto skip_class; + + class_name = class_name_from_signature (descriptor); + + if (ctx->ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (ctx->class_query, normalized_class_name)) + goto skip_class; + + group = NULL; + class_name_length = strlen (class_name); + seen_method_names = ctx->include_signature ? NULL : g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + elements = read_art_array (klass, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) ((gpointer) klass + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + ArtMethod * method; + guint32 access_flags; + jboolean is_constructor; + StdString method_name = { 0, }; + const gchar * bare_method_name; + gchar * bare_method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + method = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) ((gpointer) method + art_api.method_offset_access_flags); + is_constructor = (access_flags & kAccConstructor) != 0; + + art_api.pretty_method (&method_name, method, ctx->include_signature); + bare_method_name = std_string_c_str (&method_name); + if (ctx->include_signature) + { + const gchar * return_type_end, * name_begin; + GString * name; + + return_type_end = strchr (bare_method_name, ' '); + name_begin = return_type_end + 1 + class_name_length + 1; + if (is_constructor && g_str_has_prefix (name_begin, "")) + goto skip_method; + + name = g_string_sized_new (64); + + if (is_constructor) + { + g_string_append (name, "$init"); + g_string_append (name, strchr (name_begin, '>') + 1); + } + else + { + g_string_append (name, name_begin); + } + g_string_append (name, ": "); + g_string_append_len (name, bare_method_name, return_type_end - bare_method_name); + + bare_method_name_copy = g_string_free (name, FALSE); + bare_method_name = bare_method_name_copy; + } + else + { + const gchar * name_begin; + + name_begin = bare_method_name + class_name_length + 1; + if (is_constructor && strcmp (name_begin, "") == 0) + goto skip_method; + + if (is_constructor) + bare_method_name = "$init"; + else + bare_method_name += class_name_length + 1; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, bare_method_name)) + goto skip_method; + + if (ctx->ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (bare_method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = bare_method_name; + } + + if (!g_pattern_match_string (ctx->method_query, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + group = g_hash_table_lookup (ctx->groups, GUINT_TO_POINTER (klass->class_loader)); + if (group == NULL) + { + group = json_builder_new_immutable (); + g_hash_table_insert (ctx->groups, GUINT_TO_POINTER (klass->class_loader), group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + json_builder_add_int_value (group, klass->class_loader); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, bare_method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (bare_method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (bare_method_name_copy); + std_string_destroy (&method_name); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + if (group == NULL) + goto skip_class; + + json_builder_end_array (group); + json_builder_end_object (group); + +skip_class: + g_free (class_name_copy); + g_free (class_name); + std_string_destroy (&descriptor_storage); + + return TRUE; +} + +gchar * +enumerate_methods_jvm (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes, + JNIEnv * env) +{ + gchar * result; + GPatternSpec * class_pattern, * method_pattern; + GHashTable * groups; + gpointer * ef = env->functions; + jobject (* new_global_ref) (JNIEnv *, jobject) = ef[21]; + void (* delete_local_ref) (JNIEnv *, jobject) = ef[23]; + jboolean (* is_same_object) (JNIEnv *, jobject, jobject) = ef[24]; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_signature) (jvmtiEnv *, jclass, char **, char **) = jf[48]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_loader) (jvmtiEnv *, jclass, jobject *) = jf[57]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_loaded_classes) (jvmtiEnv *, jint *, jclass **) = jf[78]; + jint class_count, class_index; + jclass * classes; + + class_pattern = make_pattern_spec (class_query, ignore_case); + method_pattern = make_pattern_spec (method_query, ignore_case); + groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + if (get_loaded_classes (jvmti, &class_count, &classes) != JVMTI_ERROR_NONE) + goto emit_results; + + for (class_index = 0; class_index != class_count; class_index++) + { + jclass klass = classes[class_index]; + jobject loader = NULL; + gboolean have_loader = FALSE; + char * signature = NULL; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + jint method_count, method_index; + jmethodID * methods = NULL; + JsonBuilder * group = NULL; + GHashTable * seen_method_names = NULL; + + if (skip_system_classes) + { + if (get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_class; + have_loader = TRUE; + + if (loader == NULL) + goto skip_class; + } + + if (get_class_signature (jvmti, klass, &signature, NULL) != JVMTI_ERROR_NONE) + goto skip_class; + + class_name = class_name_from_signature (signature); + + if (ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (class_pattern, normalized_class_name)) + goto skip_class; + + if (get_class_methods (jvmti, klass, &method_count, &methods) != JVMTI_ERROR_NONE) + goto skip_class; + + if (!include_signature) + seen_method_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + for (method_index = 0; method_index != method_count; method_index++) + { + jmethodID method = methods[method_index]; + const gchar * method_name; + char * method_name_value = NULL; + char * method_signature_value = NULL; + gchar * method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + if (get_method_name (jvmti, method, &method_name_value, include_signature ? &method_signature_value : NULL, NULL) != JVMTI_ERROR_NONE) + goto skip_method; + method_name = method_name_value; + + if (method_name[0] == '<') + { + if (strcmp (method_name, "") == 0) + method_name = "$init"; + else if (strcmp (method_name, "") == 0) + goto skip_method; + } + + if (include_signature) + { + method_name_copy = format_method_signature (method_name, method_signature_value); + method_name = method_name_copy; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, method_name)) + goto skip_method; + + if (ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = method_name; + } + + if (!g_pattern_match_string (method_pattern, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + if (!have_loader && get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_method; + + if (loader == NULL) + { + group = g_hash_table_lookup (groups, NULL); + } + else + { + GHashTableIter iter; + jobject cur_loader; + JsonBuilder * cur_group; + + g_hash_table_iter_init (&iter, groups); + while (g_hash_table_iter_next (&iter, (gpointer *) &cur_loader, (gpointer *) &cur_group)) + { + if (cur_loader != NULL && is_same_object (env, cur_loader, loader)) + { + group = cur_group; + break; + } + } + } + + if (group == NULL) + { + jobject l; + gchar * str; + + l = (loader != NULL) ? new_global_ref (env, loader) : NULL; + + group = json_builder_new_immutable (); + g_hash_table_insert (groups, l, group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + str = g_strdup_printf ("0x%" G_GSIZE_MODIFIER "x", GPOINTER_TO_SIZE (l)); + json_builder_add_string_value (group, str); + g_free (str); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (method_name_copy); + deallocate (jvmti, method_signature_value); + deallocate (jvmti, method_name_value); + } + +skip_class: + if (group != NULL) + { + json_builder_end_array (group); + json_builder_end_object (group); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + deallocate (jvmti, methods); + + g_free (class_name_copy); + g_free (class_name); + deallocate (jvmti, signature); + + if (loader != NULL) + delete_local_ref (env, loader); + + delete_local_ref (env, klass); + } + + deallocate (jvmti, classes); + +emit_results: + result = finalize_method_groups_to_json (groups); + + g_hash_table_unref (groups); + g_pattern_spec_free (method_pattern); + g_pattern_spec_free (class_pattern); + + return result; +} + +static gchar * +finalize_method_groups_to_json (GHashTable * groups) +{ + GString * result; + GHashTableIter iter; + guint i; + JsonBuilder * group; + + result = g_string_sized_new (1024); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, groups); + for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &group); i++) + { + JsonNode * root; + gchar * json; + + if (i > 0) + g_string_append_c (result, ','); + + json_builder_end_array (group); + json_builder_end_object (group); + + root = json_builder_get_root (group); + json = json_to_string (root, FALSE); + g_string_append (result, json); + g_free (json); + json_node_unref (root); + + g_object_unref (group); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +static GPatternSpec * +make_pattern_spec (const gchar * pattern, + jboolean ignore_case) +{ + GPatternSpec * spec; + + if (ignore_case) + { + gchar * str = g_utf8_strdown (pattern, -1); + spec = g_pattern_spec_new (str); + g_free (str); + } + else + { + spec = g_pattern_spec_new (pattern); + } + + return spec; +} + +static gchar * +class_name_from_signature (const gchar * descriptor) +{ + gchar * result, * c; + + result = g_strdup (descriptor + 1); + + for (c = result; *c != '\\0'; c++) + { + if (*c == '/') + *c = '.'; + } + + c[-1] = '\\0'; + + return result; +} + +static gchar * +format_method_signature (const gchar * name, + const gchar * signature) +{ + GString * sig; + const gchar * cursor; + gint arg_index; + + sig = g_string_sized_new (128); + + g_string_append (sig, name); + + cursor = signature; + arg_index = -1; + while (TRUE) + { + const gchar c = *cursor; + + if (c == '(') + { + g_string_append_c (sig, c); + cursor++; + arg_index = 0; + } + else if (c == ')') + { + g_string_append_c (sig, c); + cursor++; + break; + } + else + { + if (arg_index >= 1) + g_string_append (sig, ", "); + + append_type (sig, &cursor); + + if (arg_index != -1) + arg_index++; + } + } + + g_string_append (sig, ": "); + append_type (sig, &cursor); + + return g_string_free (sig, FALSE); +} + +static void +append_type (GString * output, + const gchar ** type) +{ + const gchar * cursor = *type; + + switch (*cursor) + { + case 'Z': + g_string_append (output, "boolean"); + cursor++; + break; + case 'B': + g_string_append (output, "byte"); + cursor++; + break; + case 'C': + g_string_append (output, "char"); + cursor++; + break; + case 'S': + g_string_append (output, "short"); + cursor++; + break; + case 'I': + g_string_append (output, "int"); + cursor++; + break; + case 'J': + g_string_append (output, "long"); + cursor++; + break; + case 'F': + g_string_append (output, "float"); + cursor++; + break; + case 'D': + g_string_append (output, "double"); + cursor++; + break; + case 'V': + g_string_append (output, "void"); + cursor++; + break; + case 'L': + { + gchar ch; + + cursor++; + for (; (ch = *cursor) != ';'; cursor++) + { + g_string_append_c (output, (ch != '/') ? ch : '.'); + } + cursor++; + + break; + } + case '[': + *type = cursor + 1; + append_type (output, type); + g_string_append (output, "[]"); + return; + default: + g_string_append (output, "BUG"); + cursor++; + } + + *type = cursor; +} + +void +dealloc (gpointer mem) +{ + g_free (mem); +} + +static gpointer +read_art_array (gpointer object_base, + guint field_offset, + guint length_size, + guint * length) +{ + gpointer result, header; + guint n; + + header = GSIZE_TO_POINTER (*(guint64 *) (object_base + field_offset)); + if (header != NULL) + { + result = header + length_size; + if (length_size == sizeof (guint32)) + n = *(guint32 *) header; + else + n = *(guint64 *) header; + } + else + { + result = NULL; + n = 0; + } + + if (length != NULL) + *length = n; + + return result; +} + +static void +std_string_destroy (StdString * str) +{ + if ((str->l.capacity & 1) != 0) + art_api.free (str->l.data); +} + +static gchar * +std_string_c_str (StdString * self) +{ + if ((self->l.capacity & 1) != 0) + return self->l.data; + + return self->s.data; +} +`,ld=/(.+)!([^/]+)\/?([isu]+)?/,Ee=null,Mo=null,Ue=class t{static build(e,n){return ko(n),Mo(e,n,r=>new t(Ee.new(e,r,n)))}static enumerateMethods(e,n,r){ko(r);let o=e.match(ld);if(o===null)throw new Error("Invalid query; format is: class!method -- see documentation of Java.enumerateMethods(query) for details");let i=Memory.allocUtf8String(o[1]),s=Memory.allocUtf8String(o[2]),c=!1,a=!1,l=!1,d=o[3];d!==void 0&&(c=d.indexOf("s")!==-1,a=d.indexOf("i")!==-1,l=d.indexOf("u")!==-1);let p;if(n.jvmti!==null){let f=Ee.enumerateMethodsJvm(i,s,qe(c),qe(a),qe(l),r);try{p=JSON.parse(f.readUtf8String()).map(u=>{let _=ptr(u.loader);return u.loader=_.isNull()?null:_,u})}finally{Ee.dealloc(f)}}else ye(r.vm,r,f=>{let u=Ee.enumerateMethodsArt(i,s,qe(c),qe(a),qe(l));try{let _=n["art::JavaVMExt::AddGlobalRef"],{vm:h}=n;p=JSON.parse(u.readUtf8String()).map(g=>{let b=g.loader;return g.loader=b!==0?_(h,f,ptr(b)):null,g})}finally{Ee.dealloc(u)}});return p}constructor(e){this.handle=e}has(e){return Ee.has(this.handle,Memory.allocUtf8String(e))!==0}find(e){return Ee.find(this.handle,Memory.allocUtf8String(e)).readUtf8String()}list(){let e=Ee.list(this.handle);try{return JSON.parse(e.readUtf8String())}finally{Ee.dealloc(e)}}};function ko(t){Ee===null&&(Ee=dd(t),Mo=ud(Ee,t.vm))}function dd(t){let e=pt(),{jvmti:n=null}=e,{pointerSize:r}=Process,o=8,i=r,s=7*r,c=10*4+5*r,a=o+i+s+c,d=Memory.alloc(a),p=d.add(o),f=p.add(i),{getDeclaredMethods:u,getDeclaredFields:_}=t.javaLangClass(),h=t.javaLangReflectMethod(),g=t.javaLangReflectField(),b=f;[n!==null?n:NULL,u,_,h.getName,h.getModifiers,g.getName,g.getModifiers].forEach(k=>{b=b.writePointer(k).add(r)});let E=f.add(s),{vm:C}=t;if(e.flavor==="art"){let k;if(n!==null)k=[0,0,0,0];else{let j=Jn(C).offset;k=[j.ifields,j.methods,j.sfields,j.copiedMethodsOffset]}let N=_e(C),S=Pt(C),L=E;[1,...k,N.size,N.offset.accessFlags,S.size,S.offset.accessFlags,4294967295].forEach(j=>{L=L.writeUInt(j).add(4)}),[e.artClassLinker.address,e["art::ClassLinker::VisitClasses"],e["art::mirror::Class::GetDescriptor"],e["art::ArtMethod::PrettyMethod"],Process.getModuleByName("libc.so").getExportByName("free")].forEach((j,w)=>{j===void 0&&(j=NULL),L=L.writePointer(j).add(r)})}let A=new CModule(cd,{lock:d,models:p,java_api:f,art_api:E}),M={exceptions:"propagate"},O={exceptions:"propagate",scheduling:"exclusive"};return{handle:A,new:new NativeFunction(A.model_new,"pointer",["pointer","pointer","pointer"],M),has:new NativeFunction(A.model_has,"bool",["pointer","pointer"],O),find:new NativeFunction(A.model_find,"pointer",["pointer","pointer"],O),list:new NativeFunction(A.model_list,"pointer",["pointer"],O),enumerateMethodsArt:new NativeFunction(A.enumerate_methods_art,"pointer",["pointer","pointer","bool","bool","bool"],M),enumerateMethodsJvm:new NativeFunction(A.enumerate_methods_jvm,"pointer",["pointer","pointer","bool","bool","bool","pointer"],M),dealloc:new NativeFunction(A.dealloc,"void",["pointer"],O)}}function ud(t,e){let n=pt();if(n.flavor!=="art")return pd;let r=n["art::JavaVMExt::DecodeGlobal"];return function(o,i,s){let c;return ye(e,i,a=>{let l=r(e,a,o);c=s(l)}),c}}function pd(t,e,n){return n(NULL)}function qe(t){return t?1:0}var ft=class{constructor(e,n){this.items=new Map,this.capacity=e,this.destroy=n}dispose(e){let{items:n,destroy:r}=this;n.forEach(o=>{r(o,e)}),n.clear()}get(e){let{items:n}=this,r=n.get(e);return r!==void 0&&(n.delete(e),n.set(e,r)),r}set(e,n,r){let{items:o}=this,i=o.get(e);if(i!==void 0)o.delete(e),this.destroy(i,r);else if(o.size===this.capacity){let s=o.keys().next().value,c=o.get(s);o.delete(s),this.destroy(c,r)}o.set(e,n)}};var ht=1,ar=256,jo=65536,fd=305419896,Oo=32,Ro=12,Po=8,Fo=8,Do=4,Uo=4,Bo=12,hd=0,_d=1,md=2,gd=3,bd=4,yd=5,Ed=6,vd=4096,Sd=4097,wd=4099,Id=8192,Cd=8193,Td=8194,Ad=8195,Ld=8196,xd=8198,Nd=24,kd=28,Md=2,jd=24,zo=m.from([3,0,7,14,0]),ir="Ldalvik/annotation/Throws;",Od=m.from([0]);function Rd(t){let e=new cr,n=Object.assign({},t);return e.addClass(n),e.build()}var cr=class{constructor(){this.classes=[]}addClass(e){this.classes.push(e)}build(){let e=Dd(this.classes),{classes:n,interfaces:r,fields:o,methods:i,protos:s,parameters:c,annotationDirectories:a,annotationSets:l,throwsAnnotations:d,types:p,strings:f}=e,u=0,_=0,h=8,g=12,b=20,E=112;u+=E;let C=u,A=f.length*Uo;u+=A;let M=u,O=p.length*Do;u+=O;let k=u,N=s.length*Ro;u+=N;let S=u,L=o.length*Po;u+=L;let j=u,w=i.length*Fo;u+=w;let R=u,D=n.length*Oo;u+=D;let U=u,F=l.map(T=>{let P=u;return T.offset=P,u+=4+T.items.length*4,P}),z=n.reduce((T,P)=>(P.classData.constructorMethods.forEach(H=>{let[,q,Z]=H;(q&ar)===0&&Z>=0&&(H.push(u),T.push({offset:u,superConstructor:Z}),u+=jd)}),T),[]);a.forEach(T=>{T.offset=u,u+=16+T.methods.length*8});let X=r.map(T=>{u=sr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),te=c.map(T=>{u=sr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),ae=[],Q=f.map(T=>{let P=u,B=m.from(me(T.length)),H=m.from(T,"utf8"),q=m.concat([B,H,Od]);return ae.push(q),u+=q.length,P}),ie=z.map(T=>{let P=u;return u+=zo.length,P}),Y=d.map(T=>{let P=Fd(T);return T.offset=u,u+=P.length,P}),ne=n.map((T,P)=>{T.classData.offset=u;let B=Pd(T);return u+=B.length,B}),Se=0,Ye=0;u=sr(u,4);let $=u,he=r.length+c.length,Te=4+(o.length>0?1:0)+2+l.length+z.length+a.length+(he>0?1:0)+1+ie.length+d.length+n.length+1,Oe=4+Te*Bo;u+=Oe;let ke=u-U,Ve=u,I=m.alloc(Ve);I.write(`dex +035`),I.writeUInt32LE(Ve,32),I.writeUInt32LE(E,36),I.writeUInt32LE(fd,40),I.writeUInt32LE(Se,44),I.writeUInt32LE(Ye,48),I.writeUInt32LE($,52),I.writeUInt32LE(f.length,56),I.writeUInt32LE(C,60),I.writeUInt32LE(p.length,64),I.writeUInt32LE(M,68),I.writeUInt32LE(s.length,72),I.writeUInt32LE(k,76),I.writeUInt32LE(o.length,80),I.writeUInt32LE(o.length>0?S:0,84),I.writeUInt32LE(i.length,88),I.writeUInt32LE(j,92),I.writeUInt32LE(n.length,96),I.writeUInt32LE(R,100),I.writeUInt32LE(ke,104),I.writeUInt32LE(U,108),Q.forEach((T,P)=>{I.writeUInt32LE(T,C+P*Uo)}),p.forEach((T,P)=>{I.writeUInt32LE(T,M+P*Do)}),s.forEach((T,P)=>{let[B,H,q]=T,Z=k+P*Ro;I.writeUInt32LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q!==null?q.offset:0,Z+8)}),o.forEach((T,P)=>{let[B,H,q]=T,Z=S+P*Po;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),i.forEach((T,P)=>{let[B,H,q]=T,Z=j+P*Fo;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),n.forEach((T,P)=>{let{interfaces:B,annotationsDirectory:H}=T,q=B!==null?B.offset:0,Z=H!==null?H.offset:0,Xe=0,ge=R+P*Oo;I.writeUInt32LE(T.index,ge),I.writeUInt32LE(T.accessFlags,ge+4),I.writeUInt32LE(T.superClassIndex,ge+8),I.writeUInt32LE(q,ge+12),I.writeUInt32LE(T.sourceFileIndex,ge+16),I.writeUInt32LE(Z,ge+20),I.writeUInt32LE(T.classData.offset,ge+24),I.writeUInt32LE(Xe,ge+28)}),l.forEach((T,P)=>{let{items:B}=T,H=F[P];I.writeUInt32LE(B.length,H),B.forEach((q,Z)=>{I.writeUInt32LE(q.offset,H+4+Z*4)})}),z.forEach((T,P)=>{let{offset:B,superConstructor:H}=T,q=1,Z=1,Xe=1,ge=0,bt=4;I.writeUInt16LE(q,B),I.writeUInt16LE(Z,B+2),I.writeUInt16LE(Xe,B+4),I.writeUInt16LE(ge,B+6),I.writeUInt32LE(ie[P],B+8),I.writeUInt32LE(bt,B+12),I.writeUInt16LE(4208,B+16),I.writeUInt16LE(H,B+18),I.writeUInt16LE(0,B+20),I.writeUInt16LE(14,B+22)}),a.forEach(T=>{let P=T.offset,B=0,H=0,q=T.methods.length,Z=0;I.writeUInt32LE(B,P),I.writeUInt32LE(H,P+4),I.writeUInt32LE(q,P+8),I.writeUInt32LE(Z,P+12),T.methods.forEach((Xe,ge)=>{let bt=P+16+ge*8,[fi,hi]=Xe;I.writeUInt32LE(fi,bt),I.writeUInt32LE(hi.offset,bt+4)})}),r.forEach((T,P)=>{let B=X[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),c.forEach((T,P)=>{let B=te[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),ae.forEach((T,P)=>{T.copy(I,Q[P])}),ie.forEach(T=>{zo.copy(I,T)}),Y.forEach((T,P)=>{T.copy(I,d[P].offset)}),ne.forEach((T,P)=>{T.copy(I,n[P].classData.offset)}),I.writeUInt32LE(Te,$);let ce=[[hd,1,_],[_d,f.length,C],[md,p.length,M],[gd,s.length,k]];o.length>0&&ce.push([bd,o.length,S]),ce.push([yd,i.length,j]),ce.push([Ed,n.length,R]),l.forEach((T,P)=>{ce.push([wd,T.items.length,F[P]])}),z.forEach(T=>{ce.push([Cd,1,T.offset])}),a.forEach(T=>{ce.push([xd,1,T.offset])}),he>0&&ce.push([Sd,he,X.concat(te)[0]]),ce.push([Td,f.length,Q[0]]),ie.forEach(T=>{ce.push([Ad,1,T])}),d.forEach(T=>{ce.push([Ld,1,T.offset])}),n.forEach(T=>{ce.push([Id,1,T.classData.offset])}),ce.push([vd,1,$]),ce.forEach((T,P)=>{let[B,H,q]=T,Z=$+4+P*Bo;I.writeUInt16LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q,Z+8)});let Ir=new Checksum("sha1");return Ir.update(I.slice(g+b)),m.from(Ir.getDigest()).copy(I,g),I.writeUInt32LE(Gd(I,g),h),I}};function Pd(t){let{instanceFields:e,constructorMethods:n,virtualMethods:r}=t.classData;return m.from([0].concat(me(e.length)).concat(me(n.length)).concat(me(r.length)).concat(e.reduce((i,[s,c])=>i.concat(me(s)).concat(me(c)),[])).concat(n.reduce((i,[s,c,,a])=>i.concat(me(s)).concat(me(c)).concat(me(a||0)),[])).concat(r.reduce((i,[s,c])=>i.concat(me(s)).concat(me(c)).concat([0]),[])))}function Fd(t){let{thrownTypes:e}=t;return m.from([Md].concat(me(t.type)).concat([1]).concat(me(t.value)).concat([kd,e.length]).concat(e.reduce((n,r)=>(n.push(Nd,r),n),[])))}function Dd(t){let e=new Set,n=new Set,r={},o=[],i=[],s={},c=new Set,a=new Set;t.forEach(w=>{let{name:R,superClass:D,sourceFileName:U}=w;e.add("this"),e.add(R),n.add(R),e.add(D),n.add(D),e.add(U),w.interfaces.forEach(F=>{e.add(F),n.add(F)}),w.fields.forEach(F=>{let[z,X]=F;e.add(z),e.add(X),n.add(X),o.push([w.name,X,z])}),w.methods.some(([F])=>F==="")||(w.methods.unshift(["","V",[]]),c.add(R)),w.methods.forEach(F=>{let[z,X,te,ae=[],Q]=F;e.add(z);let ie=l(X,te),Y=null;if(ae.length>0){let ne=ae.slice();ne.sort(),Y=ne.join("|");let Se=s[Y];Se===void 0&&(Se={id:Y,types:ne},s[Y]=Se),e.add(ir),n.add(ir),ae.forEach(Ye=>{e.add(Ye),n.add(Ye)}),e.add("value")}if(i.push([w.name,ie,z,Y,Q]),z===""){a.add(R+"|"+ie);let ne=D+"|"+ie;c.has(R)&&!a.has(ne)&&(i.push([D,ie,z,null,0]),a.add(ne))}})});function l(w,R){let D=[w].concat(R),U=D.join("|");if(r[U]!==void 0)return U;e.add(w),n.add(w),R.forEach(z=>{e.add(z),n.add(z)});let F=D.map(Jd).join("");return e.add(F),r[U]=[U,F,w,R],U}let d=Array.from(e);d.sort();let p=d.reduce((w,R,D)=>(w[R]=D,w),{}),f=Array.from(n).map(w=>p[w]);f.sort(Vo);let u=f.reduce((w,R,D)=>(w[d[R]]=D,w),{}),_=Object.keys(r).map(w=>r[w]);_.sort(Bd);let h={},g=_.map(w=>{let[,R,D,U]=w,F;if(U.length>0){let z=U.join("|");F=h[z],F===void 0&&(F={types:U.map(X=>u[X]),offset:-1},h[z]=F)}else F=null;return[p[R],u[D],F]}),b=_.reduce((w,R,D)=>{let[U]=R;return w[U]=D,w},{}),E=Object.keys(h).map(w=>h[w]),C=o.map(w=>{let[R,D,U]=w;return[u[R],u[D],p[U]]});C.sort(zd);let A=i.map(w=>{let[R,D,U,F,z]=w;return[u[R],b[D],p[U],F,z]});A.sort(Vd);let M=Object.keys(s).map(w=>s[w]).map(w=>({id:w.id,type:u[ir],value:p.value,thrownTypes:w.types.map(R=>u[R]),offset:-1})),O=M.map(w=>({id:w.id,items:[w],offset:-1})),k=O.reduce((w,R,D)=>(w[R.id]=D,w),{}),N={},S=[],L=t.map(w=>{let R=u[w.name],D=ht,U=u[w.superClass],F,z=w.interfaces.map($=>u[$]);if(z.length>0){z.sort(Vo);let $=z.join("|");F=N[$],F===void 0&&(F={types:z,offset:-1},N[$]=F)}else F=null;let X=p[w.sourceFileName],te=A.reduce(($,he,Te)=>{let[Oe,ke,Ve,I,ce]=he;return Oe===R&&$.push([Te,Ve,I,ke,ce]),$},[]),ae=null,Q=te.filter(([,,$])=>$!==null).map(([$,,he])=>[$,O[k[he]]]);Q.length>0&&(ae={methods:Q,offset:-1},S.push(ae));let ie=C.reduce(($,he,Te)=>{let[Oe]=he;return Oe===R&&$.push([Te>0?1:0,ht]),$},[]),Y=p[""],ne=te.filter(([,$])=>$===Y).map(([$,,,he])=>{if(c.has(w.name)){let Te=-1,Oe=A.length;for(let ke=0;ke!==Oe;ke++){let[Ve,I,ce]=A[ke];if(Ve===U&&ce===Y&&I===he){Te=ke;break}}return[$,ht|jo,Te]}else return[$,ht|jo|ar,-1]}),Se=Ud(te.filter(([,$])=>$!==Y).map(([$,,,,he])=>[$,he|ht|ar]));return{index:R,accessFlags:D,superClassIndex:U,interfaces:F,sourceFileIndex:X,annotationsDirectory:ae,classData:{instanceFields:ie,constructorMethods:ne,virtualMethods:Se,offset:-1}}}),j=Object.keys(N).map(w=>N[w]);return{classes:L,interfaces:j,fields:C,methods:A,protos:g,parameters:E,annotationDirectories:S,annotationSets:O,throwsAnnotations:M,types:f,strings:d}}function Ud(t){let e=0;return t.map(([n,r],o)=>{let i;return o===0?i=[n,r]:i=[n-e,r],e=n,i})}function Vo(t,e){return t-e}function Bd(t,e){let[,,n,r]=t,[,,o,i]=e;if(no)return 1;let s=r.join("|"),c=i.join("|");return sc?1:0}function zd(t,e){let[n,r,o]=t,[i,s,c]=e;return n!==i?n-i:o!==c?o-c:r-s}function Vd(t,e){let[n,r,o]=t,[i,s,c]=e;return n!==i?n-i:o!==c?o-c:r-s}function Jd(t){let e=t[0];return e==="L"||e==="["?"L":t}function me(t){if(t<=127)return[t];let e=[],n=!1;do{let r=t&127;t>>=7,n=t!==0,n&&(r|=128),e.push(r)}while(n);return e}function sr(t,e){let n=t%e;return n===0?t:t+e-n}function Gd(t,e){let n=1,r=0,o=t.length;for(let i=e;i>>0}var Jo=Rd;var $d=1,lr=null,Go=null;function $o(t){lr=t}function dr(t,e,n){let r=We(t);return r===null&&(t.indexOf("[")===0?r=ur(t,e,n):(t[0]==="L"&&t[t.length-1]===";"&&(t=t.substring(1,t.length-1)),r=Zd(t,e,n))),Object.assign({className:t},r)}var Ho={boolean:{name:"Z",type:"uint8",size:1,byteSize:1,defaultValue:!1,isCompatible(t){return typeof t=="boolean"},fromJni(t){return!!t},toJni(t){return t?1:0},read(t){return t.readU8()},write(t,e){t.writeU8(e)},toString(){return this.name}},byte:{name:"B",type:"int8",size:1,byteSize:1,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-128&&t<=127},fromJni:ve,toJni:ve,read(t){return t.readS8()},write(t,e){t.writeS8(e)},toString(){return this.name}},char:{name:"C",type:"uint16",size:1,byteSize:2,defaultValue:0,isCompatible(t){if(typeof t!="string"||t.length!==1)return!1;let e=t.charCodeAt(0);return e>=0&&e<=65535},fromJni(t){return String.fromCharCode(t)},toJni(t){return t.charCodeAt(0)},read(t){return t.readU16()},write(t,e){t.writeU16(e)},toString(){return this.name}},short:{name:"S",type:"int16",size:1,byteSize:2,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-32768&&t<=32767},fromJni:ve,toJni:ve,read(t){return t.readS16()},write(t,e){t.writeS16(e)},toString(){return this.name}},int:{name:"I",type:"int32",size:1,byteSize:4,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-2147483648&&t<=2147483647},fromJni:ve,toJni:ve,read(t){return t.readS32()},write(t,e){t.writeS32(e)},toString(){return this.name}},long:{name:"J",type:"int64",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"||t instanceof Int64},fromJni:ve,toJni:ve,read(t){return t.readS64()},write(t,e){t.writeS64(e)},toString(){return this.name}},float:{name:"F",type:"float",size:1,byteSize:4,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readFloat()},write(t,e){t.writeFloat(e)},toString(){return this.name}},double:{name:"D",type:"double",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readDouble()},write(t,e){t.writeDouble(e)},toString(){return this.name}},void:{name:"V",type:"void",size:0,byteSize:0,defaultValue:void 0,isCompatible(t){return t===void 0},fromJni(){},toJni(){return NULL},toString(){return this.name}}},Hd=new Set(Object.values(Ho).map(t=>t.name));function We(t){let e=Ho[t];return e!==void 0?e:null}function Zd(t,e,n){let r=n._types[e?1:0],o=r[t];return o!==void 0||(t==="java.lang.Object"?o=qd(n):o=Wd(t,e,n),r[t]=o),o}function qd(t){return{name:"Ljava/lang/Object;",type:"pointer",size:1,defaultValue:NULL,isCompatible(e){return e===null?!0:e===void 0?!1:e.$h instanceof NativePointer?!0:typeof e=="string"},fromJni(e,n,r){return e.isNull()?null:t.cast(e,t.use("java.lang.Object"),r)},toJni(e,n){return e===null?NULL:typeof e=="string"?n.newStringUtf(e):e.$h}}}function Wd(t,e,n){let r=null,o=null,i=null;function s(){return r===null&&(r=n.use(t).class),r}function c(l){let d=s();return o===null&&(o=d.isInstance.overload("java.lang.Object")),o.call(d,l)}function a(){if(i===null){let l=s();i=n.use("java.lang.String").class.isAssignableFrom(l)}return i}return{name:Be(t),type:"pointer",size:1,defaultValue:NULL,isCompatible(l){return l===null?!0:l===void 0?!1:l.$h instanceof NativePointer?c(l):typeof l=="string"&&a()},fromJni(l,d,p){return l.isNull()?null:a()&&e?d.stringFromJni(l):n.cast(l,n.use(t),p)},toJni(l,d){return l===null?NULL:typeof l=="string"?d.newStringUtf(l):l.$h},toString(){return this.name}}}var Kd=[["Z","boolean"],["B","byte"],["C","char"],["D","double"],["F","float"],["I","int"],["J","long"],["S","short"]].reduce((t,[e,n])=>(t["["+e]=Qd("["+e,n),t),{});function Qd(t,e){let n=y.prototype,r=nu(e),o={typeName:e,newArray:n["new"+r+"Array"],setRegion:n["set"+r+"ArrayRegion"],getElements:n["get"+r+"ArrayElements"],releaseElements:n["release"+r+"ArrayElements"]};return{name:t,type:"pointer",size:1,defaultValue:NULL,isCompatible(i){return tu(i,e)},fromJni(i,s,c){return Xd(i,o,s,c)},toJni(i,s){return eu(i,o,s)}}}function ur(t,e,n){let r=Kd[t];if(r!==void 0)return r;if(t.indexOf("[")!==0)throw new Error("Unsupported type: "+t);let o=t.substring(1),i=dr(o,e,n),s=0,c=o.length;for(;s!==c&&o[s]==="[";)s++;o=o.substring(s),o[0]==="L"&&o[o.length-1]===";"&&(o=o.substring(1,o.length-1));let a=o.replace(/\./g,"/");Hd.has(a)?a="[".repeat(s)+a:a="[".repeat(s)+"L"+a+";";let l="["+a;return o="[".repeat(s)+o,{name:t.replace(/\./g,"/"),type:"pointer",size:1,defaultValue:NULL,isCompatible(d){return d===null?!0:typeof d!="object"||d.length===void 0?!1:d.every(function(p){return i.isCompatible(p)})},fromJni(d,p,f){if(d.isNull())return null;let u=[],_=p.getArrayLength(d);for(let h=0;h!==_;h++){let g=p.getObjectArrayElement(d,h);try{u.push(i.fromJni(g,p))}finally{p.deleteLocalRef(g)}}try{u.$w=n.cast(d,n.use(l),f)}catch{n.use("java.lang.reflect.Array").newInstance(n.use(o).class,0),u.$w=n.cast(d,n.use(l),f)}return u.$dispose=Yd,u},toJni(d,p){if(d===null)return NULL;if(!(d instanceof Array))throw new Error("Expected an array");let f=d.$w;if(f!==void 0)return f.$h;let u=d.length,h=n.use(o).$borrowClassHandle(p);try{let g=p.newObjectArray(u,h.value,NULL);p.throwIfExceptionPending();for(let b=0;b!==u;b++){let E=i.toJni(d[b],p);try{p.setObjectArrayElement(g,b,E)}finally{i.type==="pointer"&&p.getObjectRefType(E)===$d&&p.deleteLocalRef(E)}p.throwIfExceptionPending()}return g}finally{h.unref(p)}}}}function Yd(){let t=this.length;for(let e=0;e!==t;e++){let n=this[e];if(n===null)continue;let r=n.$dispose;if(r===void 0)break;r.call(n)}this.$w.$dispose()}function Xd(t,e,n,r){if(t.isNull())return null;let o=We(e.typeName),i=n.getArrayLength(t);return new Bt(t,e,o,i,n,r)}function eu(t,e,n){if(t===null)return NULL;let r=t.$h;if(r!==void 0)return r;let o=t.length,i=We(e.typeName),s=e.newArray.call(n,o);if(s.isNull())throw new Error("Unable to construct array");if(o>0){let c=i.byteSize,a=i.write,l=i.toJni,d=Memory.alloc(o*i.byteSize);for(let p=0;p!==o;p++)a(d.add(p*c),l(t[p]));e.setRegion.call(n,s,0,o,d),n.throwIfExceptionPending()}return s}function tu(t,e){if(t===null)return!0;if(t instanceof Bt)return t.$s.typeName===e;if(!(typeof t=="object"&&t.length!==void 0))return!1;let r=We(e);return Array.prototype.every.call(t,o=>r.isCompatible(o))}function Bt(t,e,n,r,o,i=!0){if(i){let s=o.newGlobalRef(t);this.$h=s,this.$r=Script.bindWeak(this,o.vm.makeHandleDestructor(s))}else this.$h=t,this.$r=null;return this.$s=e,this.$t=n,this.length=r,new Proxy(this,Go)}Go={has(t,e){return e in t?!0:t.tryParseIndex(e)!==null},get(t,e,n){let r=t.tryParseIndex(e);return r===null?t[e]:t.readElement(r)},set(t,e,n,r){let o=t.tryParseIndex(e);return o===null?(t[e]=n,!0):(t.writeElement(o,n),!0)},ownKeys(t){let e=[],{length:n}=t;for(let r=0;r!==n;r++){let o=r.toString();e.push(o)}return e.push("length"),e},getOwnPropertyDescriptor(t,e){return t.tryParseIndex(e)!==null?{writable:!0,configurable:!0,enumerable:!0}:Object.getOwnPropertyDescriptor(t,e)}};Object.defineProperties(Bt.prototype,{$dispose:{enumerable:!0,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t))}},$clone:{value(t){return new Bt(this.$h,this.$s,this.$t,this.length,t)}},tryParseIndex:{value(t){if(typeof t=="symbol")return null;let e=parseInt(t);return isNaN(e)||e<0||e>=this.length?null:e}},readElement:{value(t){return this.withElements(e=>{let n=this.$t;return n.fromJni(n.read(e.add(t*n.byteSize)))})}},writeElement:{value(t,e){let{$h:n,$s:r,$t:o}=this,i=lr.getEnv(),s=Memory.alloc(o.byteSize);o.write(s,o.toJni(e)),r.setRegion.call(i,n,t,1,s)}},withElements:{value(t){let{$h:e,$s:n}=this,r=lr.getEnv(),o=n.getElements.call(r,e);if(o.isNull())throw new Error("Unable to get array elements");try{return t(o)}finally{n.releaseElements.call(r,e,o)}}},toJSON:{value(){let{length:t,$t:e}=this,{byteSize:n,fromJni:r,read:o}=e;return this.withElements(i=>{let s=[];for(let c=0;c!==t;c++){let a=r(o(i.add(c*n)));s.push(a)}return s})}},toString:{value(){return this.toJSON().toString()}}});function Be(t){return"L"+t.replace(/\./g,"/")+";"}function nu(t){return t.charAt(0).toUpperCase()+t.slice(1)}function ve(t){return t}var ru=4,{ensureClassInitialized:Zo,makeMethodMangler:Xo}=Dt,ou=8,hr=1,mt=2,Ne=3,pr=1,_r=2,zt=1,ei=2,qo=Symbol("PENDING_USE"),Wo="/data/local/tmp",{getCurrentThreadId:Jt,pointerSize:_t}=Process,ue={state:"empty",factories:[],loaders:null,Integer:null},G=null,K=null,ti=null,ni=null,ri=null,oi=null,ii=null,Ko=null,fr=null,Qe=new Map,je=class t{static _initialize(e,n){G=e,K=n,ti=n.flavor==="art",n.flavor==="jvm"&&(Zo=To,Xo=Lo)}static _disposeAll(e){ue.factories.forEach(n=>{n._dispose(e)})}static get(e){let n=Iu(),r=n.factories[0];if(e===null)return r;let o=n.loaders.get(e);if(o!==null){let s=r.cast(o,n.Integer);return n.factories[s.intValue()]}let i=new t;return i.loader=e,i.cacheDir=r.cacheDir,br(i,e),i}constructor(){this.cacheDir=Wo,this.codeCacheDir=Wo+"/dalvik-cache",this.tempFileNaming={prefix:"frida",suffix:""},this._classes={},this._classHandles=new ft(10,su),this._patchedMethods=new Set,this._loader=null,this._types=[{},{}],ue.factories.push(this)}_dispose(e){Array.from(this._patchedMethods).forEach(n=>{n.implementation=null}),this._patchedMethods.clear(),Wn(),this._classHandles.dispose(e),this._classes={}}get loader(){return this._loader}set loader(e){let n=this._loader===null&&e!==null;this._loader=e,n&&ue.state==="ready"&&this===ue.factories[0]&&br(this,e)}use(e,n={}){let r=n.cache!=="skip",o=r?this._getUsedClass(e):void 0;if(o===void 0)try{let i=G.getEnv(),{_loader:s}=this,c=s!==null?cu(e,s,i):au(e);o=this._make(e,c,i)}finally{r&&this._setUsedClass(e,o)}return o}_getUsedClass(e){let n;for(;(n=this._classes[e])===qo;)Thread.sleep(.05);return n===void 0&&(this._classes[e]=qo),n}_setUsedClass(e,n){n!==void 0?this._classes[e]=n:delete this._classes[e]}_make(e,n,r){let o=iu(),i=Object.create(Er.prototype,{[Symbol.for("n")]:{value:e},$n:{get(){return this[Symbol.for("n")]}},[Symbol.for("C")]:{value:o},$C:{get(){return this[Symbol.for("C")]}},[Symbol.for("w")]:{value:null,writable:!0},$w:{get(){return this[Symbol.for("w")]},set(a){this[Symbol.for("w")]=a}},[Symbol.for("_s")]:{writable:!0},$_s:{get(){return this[Symbol.for("_s")]},set(a){this[Symbol.for("_s")]=a}},[Symbol.for("c")]:{value:[null]},$c:{get(){return this[Symbol.for("c")]}},[Symbol.for("m")]:{value:new Map},$m:{get(){return this[Symbol.for("m")]}},[Symbol.for("l")]:{value:null,writable:!0},$l:{get(){return this[Symbol.for("l")]},set(a){this[Symbol.for("l")]=a}},[Symbol.for("gch")]:{value:n},$gch:{get(){return this[Symbol.for("gch")]}},[Symbol.for("f")]:{value:this},$f:{get(){return this[Symbol.for("f")]}}});o.prototype=i;let s=new o(null);i[Symbol.for("w")]=s,i.$w=s;let c=s.$borrowClassHandle(r);try{let a=c.value;Zo(r,a),i.$l=Ue.build(a,r)}finally{c.unref(r)}return s}retain(e){let n=G.getEnv();return e.$clone(n)}cast(e,n,r){let o=G.getEnv(),i=e.$h;i===void 0&&(i=e);let s=n.$borrowClassHandle(o);try{if(!o.isInstanceOf(i,s.value))throw new Error(`Cast from '${o.getObjectClassName(i)}' to '${n.$n}' isn't possible`)}finally{s.unref(o)}let c=n.$C;return new c(i,zt,o,r)}wrap(e,n,r){let o=n.$C,i=new o(e,zt,r,!1);return i.$r=Script.bindWeak(i,G.makeHandleDestructor(e)),i}array(e,n){let r=G.getEnv(),o=We(e);o!==null&&(e=o.name);let i=ur("["+e,!1,this),s=i.toJni(n,r);return i.fromJni(s,r,!0)}registerClass(e){let n=G.getEnv(),r=[];try{let o=this.use("java.lang.Class"),i=n.javaLangReflectMethod(),s=n.vaMethod("pointer",[]),c=e.name,a=e.implements||[],l=e.superClass||this.use("java.lang.Object"),d=[],p=[],f={name:Be(c),sourceFileName:Tu(c),superClass:Be(l.$n),interfaces:a.map(S=>Be(S.$n)),fields:d,methods:p},u=a.slice();a.forEach(S=>{Array.prototype.slice.call(S.class.getInterfaces()).forEach(L=>{let j=this.cast(L,o).getCanonicalName();u.push(this.use(j))})});let _=e.fields||{};Object.getOwnPropertyNames(_).forEach(S=>{let L=this._getType(_[S]);d.push([S,L.name])});let h={},g={};u.forEach(S=>{let L=S.$borrowClassHandle(n);r.push(L);let j=L.value;S.$ownMembers.filter(w=>S[w].overloads!==void 0).forEach(w=>{let R=S[w],D=R.overloads,U=D.map(F=>Qo(w,F.returnType,F.argumentTypes));h[w]=[R,U,j],D.forEach((F,z)=>{let X=U[z];g[X]=[F,j]})})});let b=e.methods||{},C=Object.keys(b).reduce((S,L)=>{let j=b[L],w=L==="$init"?"":L;return j instanceof Array?S.push(...j.map(R=>[w,R])):S.push([w,j]),S},[]),A=[];C.forEach(([S,L])=>{let j=Ne,w,R,D=[],U;if(typeof L=="function"){let te=h[S];if(te!==void 0&&Array.isArray(te)){let[ae,Q,ie]=te;if(Q.length>1)throw new Error(`More than one overload matching '${S}': signature must be specified`);delete g[Q[0]];let Y=ae.overloads[0];j=Y.type,w=Y.returnType,R=Y.argumentTypes,U=L;let ne=n.toReflectedMethod(ie,Y.handle,0),Se=s(n.handle,ne,i.getGenericExceptionTypes);D=yr(n,Se).map(Be),n.deleteLocalRef(Se),n.deleteLocalRef(ne)}else w=this._getType("void"),R=[],U=L}else{if(L.isStatic&&(j=mt),w=this._getType(L.returnType||"void"),R=(L.argumentTypes||[]).map(Q=>this._getType(Q)),U=L.implementation,typeof U!="function")throw new Error("Expected a function implementation for method: "+S);let te=Qo(S,w,R),ae=g[te];if(ae!==void 0){let[Q,ie]=ae;delete g[te],j=Q.type,w=Q.returnType,R=Q.argumentTypes;let Y=n.toReflectedMethod(ie,Q.handle,0),ne=s(n.handle,Y,i.getGenericExceptionTypes);D=yr(n,ne).map(Be),n.deleteLocalRef(ne),n.deleteLocalRef(Y)}}let F=w.name,z=R.map(te=>te.name),X="("+z.join("")+")"+F;p.push([S,F,z,D,j===mt?ou:0]),A.push([S,X,j,w,R,U])});let M=Object.keys(g);if(M.length>0)throw new Error("Missing implementation for: "+M.join(", "));let O=Vt.fromBuffer(Jo(f),this);try{O.load()}finally{O.file.delete()}let k=this.use(e.name),N=C.length;if(N>0){let S=3*_t,L=Memory.alloc(N*S),j=[],w=[];A.forEach(([U,F,z,X,te,ae],Q)=>{let ie=Memory.allocUtf8String(U),Y=Memory.allocUtf8String(F),ne=si(U,k,z,X,te,ae);L.add(Q*S).writePointer(ie),L.add(Q*S+_t).writePointer(Y),L.add(Q*S+2*_t).writePointer(ne),w.push(ie,Y),j.push(ne)});let R=k.$borrowClassHandle(n);r.push(R);let D=R.value;n.registerNatives(D,L,N),n.throwIfExceptionPending(),k.$nativeMethods=j}return k}finally{r.forEach(o=>{o.unref(n)})}}choose(e,n){let r=G.getEnv(),{flavor:o}=K;if(o==="jvm")this._chooseObjectsJvm(e,r,n);else if(o==="art"){let i=K["art::gc::Heap::VisitObjects"]===void 0;if(i&&K["art::gc::Heap::GetInstances"]===void 0)return this._chooseObjectsJvm(e,r,n);ye(G,r,s=>{i?this._chooseObjectsArtPreA12(e,r,s,n):this._chooseObjectsArtLegacy(e,r,s,n)})}else this._chooseObjectsDalvik(e,r,n)}_chooseObjectsJvm(e,n,r){let o=this.use(e),{jvmti:i}=K,s=1,c=3,a=o.$borrowClassHandle(n),l=int64(a.value.toString());try{let d=new NativeCallback((b,E,C,A)=>(C.writeS64(l),s),"int",["int64","int64","pointer","pointer"]);i.iterateOverInstancesOfClass(a.value,c,d,a.value);let p=Memory.alloc(8);p.writeS64(l);let f=Memory.alloc(ru),u=Memory.alloc(_t);i.getObjectsWithTags(1,p,f,u,NULL);let _=f.readS32(),h=u.readPointer(),g=[];for(let b=0;b!==_;b++)g.push(h.add(b*_t).readPointer());i.deallocate(h);try{for(let b of g){let E=this.cast(b,o);if(r.onMatch(E)==="stop")break}r.onComplete()}finally{g.forEach(b=>{n.deleteLocalRef(b)})}}finally{a.unref(n)}}_chooseObjectsArtPreA12(e,n,r,o){let i=this.use(e),s=lt.$new(r,G),c,a=i.$borrowClassHandle(n);try{let f=K["art::JavaVMExt::DecodeGlobal"](K.vm,r,a.value);c=s.newHandle(f)}finally{a.unref(n)}let l=0,d=ct.$new();K["art::gc::Heap::GetInstances"](K.artHeap,s,c,l,d);let p=d.handles.map(f=>n.newGlobalRef(f));d.$delete(),s.$delete();try{for(let f of p){let u=this.cast(f,i);if(o.onMatch(u)==="stop")break}o.onComplete()}finally{p.forEach(f=>{n.deleteGlobalRef(f)})}}_chooseObjectsArtLegacy(e,n,r,o){let i=this.use(e),s=[],c=K["art::JavaVMExt::AddGlobalRef"],a=K.vm,l,d=i.$borrowClassHandle(n);try{l=K["art::JavaVMExt::DecodeGlobal"](a,r,d.value).toInt32()}finally{d.unref(n)}let p=tr(l,f=>{s.push(c(a,r,f))});K["art::gc::Heap::VisitObjects"](K.artHeap,p,NULL);try{for(let f of s){let u=this.cast(f,i);if(o.onMatch(u)==="stop")break}}finally{s.forEach(f=>{n.deleteGlobalRef(f)})}o.onComplete()}_chooseObjectsDalvik(e,n,r){let o=this.use(e);if(K.addLocalReference===null){let s=Process.getModuleByName("libdvm.so"),c;switch(Process.arch){case"arm":c="2d e9 f0 41 05 46 15 4e 0c 46 7e 44 11 b3 43 68";break;case"ia32":c="8d 64 24 d4 89 5c 24 1c 89 74 24 20 e8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 85 d2";break}Memory.scan(s.base,s.size,c,{onMatch:(a,l)=>{let d;if(Process.arch==="arm")a=a.or(1),d=new NativeFunction(a,"pointer",["pointer","pointer"]);else{let p=Memory.alloc(Process.pageSize);Memory.patchCode(p,16,f=>{let u=new X86Writer(f,{pc:p});u.putMovRegRegOffsetPtr("eax","esp",4),u.putMovRegRegOffsetPtr("edx","esp",8),u.putJmpAddress(a),u.flush()}),d=new NativeFunction(p,"pointer",["pointer","pointer"]),d._thunk=p}return K.addLocalReference=d,G.perform(p=>{i(this,p)}),"stop"},onError(a){},onComplete(){K.addLocalReference===null&&r.onComplete()}})}else i(this,n);function i(s,c){let{DVM_JNI_ENV_OFFSET_SELF:a}=Dt,l=c.handle.add(a).readPointer(),d,p=o.$borrowClassHandle(c);try{d=K.dvmDecodeIndirectRef(l,p.value)}finally{p.unref(c)}let f=d.toMatchPattern(),u=K.dvmHeapSourceGetBase(),h=K.dvmHeapSourceGetLimit().sub(u).toInt32();Memory.scan(u,h,f,{onMatch:(g,b)=>{K.dvmIsValidObject(g)&&G.perform(E=>{let C=E.handle.add(a).readPointer(),A,M=K.addLocalReference(C,g);try{A=s.cast(M,o)}finally{E.deleteLocalRef(M)}if(r.onMatch(A)==="stop")return"stop"})},onError(g){},onComplete(){r.onComplete()}})}}openClassFile(e){return new Vt(e,null,this)}_getType(e,n=!0){return dr(e,n,this)}};function iu(){return function(t,e,n,r){return Er.call(this,t,e,n,r)}}function Er(t,e,n,r=!0){if(t!==null)if(r){let o=n.newGlobalRef(t);this.$h=o,this.$r=Script.bindWeak(this,G.makeHandleDestructor(o))}else this.$h=t,this.$r=null;else this.$h=null,this.$r=null;return this.$t=e,new Proxy(this,ni)}ni={has(t,e){return e in t?!0:t.$has(e)},get(t,e,n){if(typeof e!="string"||e.startsWith("$")||e==="class")return t[e];let r=t.$find(e);return r!==null?r(n):t[e]},set(t,e,n,r){return t[e]=n,!0},ownKeys(t){return t.$list()},getOwnPropertyDescriptor(t,e){return Object.prototype.hasOwnProperty.call(t,e)?Object.getOwnPropertyDescriptor(t,e):{writable:!1,configurable:!0,enumerable:!0}}};Object.defineProperties(Er.prototype,{[Symbol.for("new")]:{enumerable:!1,get(){return this.$getCtor("allocAndInit")}},$new:{enumerable:!0,get(){return this[Symbol.for("new")]}},[Symbol.for("alloc")]:{enumerable:!1,value(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=t.allocObject(e.value);return this.$f.cast(n,this)}finally{e.unref(t)}}},$alloc:{enumerable:!0,get(){return this[Symbol.for("alloc")]}},[Symbol.for("init")]:{enumerable:!1,get(){return this.$getCtor("initOnly")}},$init:{enumerable:!0,get(){return this[Symbol.for("init")]}},[Symbol.for("dispose")]:{enumerable:!1,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t)),this.$h!==null&&(this.$h=void 0)}},$dispose:{enumerable:!0,get(){return this[Symbol.for("dispose")]}},[Symbol.for("clone")]:{enumerable:!1,value(t){let e=this.$C;return new e(this.$h,this.$t,t)}},$clone:{value(t){return this[Symbol.for("clone")](t)}},[Symbol.for("class")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=this.$f;return n.cast(e.value,n.use("java.lang.Class"))}finally{e.unref(t)}}},class:{enumerable:!0,get(){return this[Symbol.for("class")]}},[Symbol.for("className")]:{enumerable:!1,get(){let t=this.$h;return t===null?this.$n:G.getEnv().getObjectClassName(t)}},$className:{enumerable:!0,get(){return this[Symbol.for("className")]}},[Symbol.for("ownMembers")]:{enumerable:!1,get(){return this.$l.list()}},$ownMembers:{enumerable:!0,get(){return this[Symbol.for("ownMembers")]}},[Symbol.for("super")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$s.$C;return new e(this.$h,ei,t)}},$super:{enumerable:!0,get(){return this[Symbol.for("super")]}},[Symbol.for("s")]:{enumerable:!1,get(){let t=Object.getPrototypeOf(this),e=t.$_s;if(e===void 0){let n=G.getEnv(),r=this.$borrowClassHandle(n);try{let o=n.getSuperclass(r.value);if(o.isNull())e=null;else try{let i=n.getClassName(o),s=t.$f;if(e=s._getUsedClass(i),e===void 0)try{let c=lu(this);e=s._make(i,c,n)}finally{s._setUsedClass(i,e)}}finally{n.deleteLocalRef(o)}}finally{r.unref(n)}t.$_s=e}return e}},$s:{get(){return this[Symbol.for("s")]}},[Symbol.for("isSameObject")]:{enumerable:!1,value(t){return G.getEnv().isSameObject(t.$h,this.$h)}},$isSameObject:{value(t){return this[Symbol.for("isSameObject")](t)}},[Symbol.for("getCtor")]:{enumerable:!1,value(t){let e=this.$c,n=e[0];if(n===null){let r=G.getEnv(),o=this.$borrowClassHandle(r);try{n=du(o.value,this.$w,r),e[0]=n}finally{o.unref(r)}}return n[t]}},$getCtor:{value(t){return this[Symbol.for("getCtor")](t)}},[Symbol.for("borrowClassHandle")]:{enumerable:!1,value(t){let e=this.$n,n=this.$f._classHandles,r=n.get(e);return r===void 0&&(r=new vr(this.$gch(t),t),n.set(e,r,t)),r.ref()}},$borrowClassHandle:{value(t){return this[Symbol.for("borrowClassHandle")](t)}},[Symbol.for("copyClassHandle")]:{enumerable:!1,value(t){let e=this.$borrowClassHandle(t);try{return t.newLocalRef(e.value)}finally{e.unref(t)}}},$copyClassHandle:{value(t){return this[Symbol.for("copyClassHandle")](t)}},[Symbol.for("getHandle")]:{enumerable:!1,value(t){let e=this.$h;if(e===void 0)throw new Error("Wrapper is disposed; perhaps it was borrowed from a hook instead of calling Java.retain() to make a long-lived wrapper?");return e}},$getHandle:{value(t){return this[Symbol.for("getHandle")](t)}},[Symbol.for("list")]:{enumerable:!1,value(){let t=this.$s,e=t!==null?t.$list():[],n=this.$l;return Array.from(new Set(e.concat(n.list())))}},$list:{get(){return this[Symbol.for("list")]}},[Symbol.for("has")]:{enumerable:!1,value(t){if(this.$m.has(t)||this.$l.has(t))return!0;let r=this.$s;return!!(r!==null&&r.$has(t))}},$has:{value(t){return this[Symbol.for("has")](t)}},[Symbol.for("find")]:{enumerable:!1,value(t){let e=this.$m,n=e.get(t);if(n!==void 0)return n;let o=this.$l.find(t);if(o!==null){let s=G.getEnv(),c=this.$borrowClassHandle(s);try{n=uu(t,o,c.value,this.$w,s)}finally{c.unref(s)}return e.set(t,n),n}let i=this.$s;return i!==null?i.$find(t):null}},$find:{value(t){return this[Symbol.for("find")](t)}},[Symbol.for("toJSON")]:{enumerable:!1,value(){let t=this.$n;if(this.$h===null)return``;let n=this.$className;return t===n?``:``}},toJSON:{get(){return this[Symbol.for("toJSON")]}}});function vr(t,e){this.value=e.newGlobalRef(t),e.deleteLocalRef(t),this.refs=1}vr.prototype.ref=function(){return this.refs++,this};vr.prototype.unref=function(t){--this.refs===0&&t.deleteGlobalRef(this.value)};function su(t,e){t.unref(e)}function au(t){let e=t.replace(/\./g,"/");return function(n){let r=Jt();ci(r);try{return n.findClass(e)}finally{li(r)}}}function cu(t,e,n){return fr===null&&(Ko=n.vaMethod("pointer",["pointer"]),fr=e.loadClass.overload("java.lang.String").handle),n=null,function(r){let o=r.newStringUtf(t),i=Jt();ci(i);try{let s=Ko(r.handle,e.$h,fr,o);return r.throwIfExceptionPending(),s}finally{li(i),r.deleteLocalRef(o)}}}function lu(t){return function(e){let n=t.$borrowClassHandle(e);try{return e.getSuperclass(n.value)}finally{n.unref(e)}}}function du(t,e,n){let{$n:r,$f:o}=e,i=Cu(r),s=n.javaLangClass(),c=n.javaLangReflectConstructor(),a=n.vaMethod("pointer",[]),l=n.vaMethod("uint8",[]),d=[],p=[],f=o._getType(r,!1),u=o._getType("void",!1),_=a(n.handle,t,s.getDeclaredConstructors);try{let h=n.getArrayLength(_);if(h!==0)for(let g=0;g!==h;g++){let b,E,C=n.getObjectArrayElement(_,g);try{b=n.fromReflectedMethod(C),E=a(n.handle,C,c.getGenericParameterTypes)}finally{n.deleteLocalRef(C)}let A;try{A=yr(n,E).map(M=>o._getType(M))}finally{n.deleteLocalRef(E)}d.push(Ke(i,e,hr,b,f,A,n)),p.push(Ke(i,e,Ne,b,u,A,n))}else{if(l(n.handle,t,s.isInterface))throw new Error("cannot instantiate an interface");let b=n.javaLangObject(),E=n.getMethodId(b,"","()V");d.push(Ke(i,e,hr,E,f,[],n)),p.push(Ke(i,e,Ne,E,u,[],n))}}finally{n.deleteLocalRef(_)}if(p.length===0)throw new Error("no supported overloads");return{allocAndInit:mr(d),initOnly:mr(p)}}function uu(t,e,n,r,o){return e.startsWith("m")?pu(t,e,n,r,o):vu(t,e,n,r,o)}function pu(t,e,n,r,o){let{$f:i}=r,s=e.split(":").slice(1),c=o.javaLangReflectMethod(),a=o.vaMethod("pointer",[]),l=o.vaMethod("uint8",[]),d=s.map(f=>{let u=f[0]==="s"?mt:Ne,_=ptr(f.substr(1)),h,g=[],b=o.toReflectedMethod(n,_,u===mt?1:0);try{let E=!!l(o.handle,b,c.isVarArgs),C=a(o.handle,b,c.getGenericReturnType);o.throwIfExceptionPending();try{h=i._getType(o.getTypeName(C))}finally{o.deleteLocalRef(C)}let A=a(o.handle,b,c.getParameterTypes);try{let M=o.getArrayLength(A);for(let O=0;O!==M;O++){let k=o.getObjectArrayElement(A,O),N;try{N=E&&O===M-1?o.getArrayTypeName(k):o.getTypeName(k)}finally{o.deleteLocalRef(k)}let S=i._getType(N);g.push(S)}}finally{o.deleteLocalRef(A)}}catch{return null}finally{o.deleteLocalRef(b)}return Ke(t,r,u,_,h,g,o)}).filter(f=>f!==null);if(d.length===0)throw new Error("No supported overloads");t==="valueOf"&&bu(d);let p=mr(d);return function(f){return p}}function mr(t){let e=fu();return Object.setPrototypeOf(e,ri),e._o=t,e}function fu(){let t=function(){return t.invoke(this,arguments)};return t}ri=Object.create(Function.prototype,{overloads:{enumerable:!0,get(){return this._o}},overload:{value(...t){let e=this._o,n=t.length,r=t.join(":");for(let o=0;o!==e.length;o++){let i=e[o],{argumentTypes:s}=i;if(s.length!==n)continue;if(s.map(a=>a.className).join(":")===r)return i}gr(this.methodName,this.overloads,"specified argument types do not match any of:")}},methodName:{enumerable:!0,get(){return this._o[0].methodName}},holder:{enumerable:!0,get(){return this._o[0].holder}},type:{enumerable:!0,get(){return this._o[0].type}},handle:{enumerable:!0,get(){return ze(this),this._o[0].handle}},implementation:{enumerable:!0,get(){return ze(this),this._o[0].implementation},set(t){ze(this),this._o[0].implementation=t}},returnType:{enumerable:!0,get(){return ze(this),this._o[0].returnType}},argumentTypes:{enumerable:!0,get(){return ze(this),this._o[0].argumentTypes}},canInvokeWith:{enumerable:!0,get(t){return ze(this),this._o[0].canInvokeWith}},clone:{enumerable:!0,value(t){return ze(this),this._o[0].clone(t)}},invoke:{value(t,e){let n=this._o,r=t.$h!==null;for(let o=0;o!==n.length;o++){let i=n[o];if(i.canInvokeWith(e)){if(i.type===Ne&&!r){let s=this.methodName;if(s==="toString")return``;throw new Error(s+": cannot call instance method without an instance")}return i.apply(t,e)}}if(this.methodName==="toString")return``;gr(this.methodName,this.overloads,"argument types do not match any of:")}}});function Qo(t,e,n){return`${e.className} ${t}(${n.map(r=>r.className).join(", ")})`}function ze(t){let e=t._o;e.length>1&&gr(e[0].methodName,e,"has more than one overload, use .overload() to choose from:")}function gr(t,e,n){let o=e.slice().sort((i,s)=>i.argumentTypes.length-s.argumentTypes.length).map(i=>i.argumentTypes.length>0?".overload('"+i.argumentTypes.map(c=>c.className).join("', '")+"')":".overload()");throw new Error(`${t}(): ${n} + ${o.join(` + `)}`)}function Ke(t,e,n,r,o,i,s,c){let a=o.type,l=i.map(f=>f.type);s===null&&(s=G.getEnv());let d,p;return n===Ne?(d=s.vaMethod(a,l,c),p=s.nonvirtualVaMethod(a,l,c)):n===mt?(d=s.staticVaMethod(a,l,c),p=d):(d=s.constructor(l,c),p=d),hu([t,e,n,r,o,i,d,p])}function hu(t){let e=_u();return Object.setPrototypeOf(e,oi),e._p=t,e}function _u(){let t=function(){return t.invoke(this,arguments)};return t}oi=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return this._p[0]}},holder:{enumerable:!0,get(){return this._p[1]}},type:{enumerable:!0,get(){return this._p[2]}},handle:{enumerable:!0,get(){return this._p[3]}},implementation:{enumerable:!0,get(){let t=this._r;return t!==void 0?t:null},set(t){let e=this._p,n=e[1];if(e[2]===hr)throw new Error("Reimplementing $new is not possible; replace implementation of $init instead");let o=this._r;if(o!==void 0&&(n.$f._patchedMethods.delete(this),o._m.revert(G),this._r=void 0),t!==null){let[i,s,c,a,l,d]=e,p=si(i,s,c,l,d,t,this),f=Xo(a);p._m=f,this._r=p,f.replace(p,c===Ne,d,G,K),n.$f._patchedMethods.add(this)}}},returnType:{enumerable:!0,get(){return this._p[4]}},argumentTypes:{enumerable:!0,get(){return this._p[5]}},canInvokeWith:{enumerable:!0,value(t){let e=this._p[5];return t.length!==e.length?!1:e.every((n,r)=>n.isCompatible(t[r]))}},clone:{enumerable:!0,value(t){let e=this._p.slice(0,6);return Ke(...e,null,t)}},invoke:{value(t,e){let n=G.getEnv(),r=this._p,o=r[2],i=r[4],s=r[5],c=this._r,a=o===Ne,l=e.length,d=2+l;n.pushLocalFrame(d);let p=null;try{let f;a?f=t.$getHandle():(p=t.$borrowClassHandle(n),f=p.value);let u,_=t.$t;c===void 0?u=r[3]:(u=c._m.resolveTarget(t,a,n,K),ti&&c._c.has(Jt())&&(_=ei));let h=[n.handle,f,u];for(let E=0;E!==l;E++)h.push(s[E].toJni(e[E],n));let g;_===zt?g=r[6]:(g=r[7],a&&h.splice(2,0,t.$copyClassHandle(n)));let b=g.apply(null,h);return n.throwIfExceptionPending(),i.fromJni(b,n,!0)}finally{p!==null&&p.unref(n),n.popLocalFrame(NULL)}}},toString:{enumerable:!0,value(){return`function ${this.methodName}(${this.argumentTypes.map(t=>t.className).join(", ")}): ${this.returnType.className}`}}});function si(t,e,n,r,o,i,s=null){let c=new Set,a=mu([t,e,n,r,o,i,s,c]),l=new NativeCallback(a,r.type,["pointer","pointer"].concat(o.map(d=>d.type)));return l._c=c,l}function mu(t){return function(){return gu(arguments,t)}}function gu(t,e){let n=new y(t[0],G),[r,o,i,s,c,a,l,d]=e,p=[],f;if(i===Ne){let h=o.$C;f=new h(t[1],zt,n,!1)}else f=o;let u=Jt();n.pushLocalFrame(3);let _=!0;G.link(u,n);try{d.add(u);let h;l===null||!Qe.has(u)?h=a:h=l;let g=[],b=t.length-2;for(let A=0;A!==b;A++){let O=c[A].fromJni(t[2+A],n,!1);g.push(O),p.push(O)}let E=h.apply(f,g);if(!s.isCompatible(E))throw new Error(`Implementation for ${r} expected return value compatible with ${s.className}`);let C=s.toJni(E,n);return s.type==="pointer"&&(C=n.popLocalFrame(C),_=!1,p.push(E)),C}catch(h){let g=h.$h;return g!==void 0?n.throw(g):Script.nextTick(()=>{throw h}),s.defaultValue}finally{G.unlink(u),_&&n.popLocalFrame(NULL),d.delete(u),p.forEach(h=>{if(h===null)return;let g=h.$dispose;g!==void 0&&g.call(h)})}}function bu(t){let{holder:e,type:n}=t[0];t.some(o=>o.type===n&&o.argumentTypes.length===0)||t.push(yu([e,n]))}function yu(t){let e=Eu();return Object.setPrototypeOf(e,ii),e._p=t,e}function Eu(){return function(){return this}}ii=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return"valueOf"}},holder:{enumerable:!0,get(){return this._p[0]}},type:{enumerable:!0,get(){return this._p[1]}},handle:{enumerable:!0,get(){return NULL}},implementation:{enumerable:!0,get(){return null},set(t){}},returnType:{enumerable:!0,get(){let t=this.holder;return t.$f.use(t.$n)}},argumentTypes:{enumerable:!0,get(){return[]}},canInvokeWith:{enumerable:!0,value(t){return t.length===0}},clone:{enumerable:!0,value(t){throw new Error("Invalid operation")}}});function vu(t,e,n,r,o){let i=e[2]==="s"?pr:_r,s=ptr(e.substr(3)),{$f:c}=r,a,l=o.toReflectedField(n,s,i===pr?1:0);try{a=o.vaMethod("pointer",[])(o.handle,l,o.javaLangReflectField().getGenericType),o.throwIfExceptionPending()}finally{o.deleteLocalRef(l)}let d;try{d=c._getType(o.getTypeName(a))}finally{o.deleteLocalRef(a)}let p,f,u=d.type;return i===pr?(p=o.getStaticField(u),f=o.setStaticField(u)):(p=o.getField(u),f=o.setField(u)),Su([i,d,s,p,f])}function Su(t){return function(e){return new ai([e].concat(t))}}function ai(t){this._p=t}Object.defineProperties(ai.prototype,{value:{enumerable:!0,get(){let[t,e,n,r,o]=this._p,i=G.getEnv();i.pushLocalFrame(4);let s=null;try{let c;if(e===_r){if(c=t.$getHandle(),c===null)throw new Error("Cannot access an instance field without an instance")}else s=t.$borrowClassHandle(i),c=s.value;let a=o(i.handle,c,r);return i.throwIfExceptionPending(),n.fromJni(a,i,!0)}finally{s!==null&&s.unref(i),i.popLocalFrame(NULL)}},set(t){let[e,n,r,o,,i]=this._p,s=G.getEnv();s.pushLocalFrame(4);let c=null;try{let a;if(n===_r){if(a=e.$getHandle(),a===null)throw new Error("Cannot access an instance field without an instance")}else c=e.$borrowClassHandle(s),a=c.value;if(!r.isCompatible(t))throw new Error(`Expected value compatible with ${r.className}`);let l=r.toJni(t,s);i(s.handle,a,o,l),s.throwIfExceptionPending()}finally{c!==null&&c.unref(s),s.popLocalFrame(NULL)}}},holder:{enumerable:!0,get(){return this._p[0]}},fieldType:{enumerable:!0,get(){return this._p[1]}},fieldReturnType:{enumerable:!0,get(){return this._p[2]}},toString:{enumerable:!0,value(){let t=`Java.Field{holder: ${this.holder}, fieldType: ${this.fieldType}, fieldReturnType: ${this.fieldReturnType}, value: ${this.value}}`;return t.length<200?t:`Java.Field{ + holder: ${this.holder}, + fieldType: ${this.fieldType}, + fieldReturnType: ${this.fieldReturnType}, + value: ${this.value}, +}`.split(` +`).map(n=>n.length>200?n.slice(0,n.indexOf(" ")+1)+"...,":n).join(` +`)}}});var Vt=class t{static fromBuffer(e,n){let r=Yo(n),o=r.getCanonicalPath().toString(),i=new File(o,"w");return i.write(e.buffer),i.close(),wu(o,n),new t(o,r,n)}constructor(e,n,r){this.path=e,this.file=n,this._factory=r}load(){let{_factory:e}=this,{codeCacheDir:n}=e,r=e.use("dalvik.system.DexClassLoader"),o=e.use("java.io.File"),i=this.file;if(i===null&&(i=e.use("java.io.File").$new(this.path)),!i.exists())throw new Error("File not found");o.$new(n).mkdirs(),e.loader=r.$new(i.getCanonicalPath(),n,null,e.loader),G.preventDetachDueToClassLoader()}getClassNames(){let{_factory:e}=this,n=e.use("dalvik.system.DexFile"),r=Yo(e),o=n.loadDex(this.path,r.getCanonicalPath(),0),i=[],s=o.entries();for(;s.hasMoreElements();)i.push(s.nextElement().toString());return i}};function Yo(t){let{cacheDir:e,tempFileNaming:n}=t,r=t.use("java.io.File"),o=r.$new(e);return o.mkdirs(),r.createTempFile(n.prefix,n.suffix+".dex",o)}function wu(t,e){e.use("java.io.File").$new(t).setWritable(!1,!1)}function Iu(){switch(ue.state){case"empty":{ue.state="pending";let t=ue.factories[0],e=t.use("java.util.HashMap"),n=t.use("java.lang.Integer");ue.loaders=e.$new(),ue.Integer=n;let r=t.loader;return r!==null&&br(t,r),ue.state="ready",ue}case"pending":do Thread.sleep(.05);while(ue.state==="pending");return ue;case"ready":return ue}}function br(t,e){let{factories:n,loaders:r,Integer:o}=ue,i=o.$new(n.indexOf(t));r.put(e,i);for(let s=e.getParent();s!==null&&!r.containsKey(s);s=s.getParent())r.put(s,i)}function ci(t){let e=Qe.get(t);e===void 0&&(e=0),e++,Qe.set(t,e)}function li(t){let e=Qe.get(t);if(e===void 0)throw new Error(`Thread ${t} is not ignored`);e--,e===0?Qe.delete(t):Qe.set(t,e)}function Cu(t){return t.slice(t.lastIndexOf(".")+1)}function yr(t,e){let n=[],r=t.getArrayLength(e);for(let o=0;o!==r;o++){let i=t.getObjectArrayElement(e,o);try{n.push(t.getTypeName(i))}finally{t.deleteLocalRef(i)}}return n}function Tu(t){let e=t.split(".");return e[e.length-1]+".java"}var Au=4,di=Process.pointerSize,Sr=class{ACC_PUBLIC=1;ACC_PRIVATE=2;ACC_PROTECTED=4;ACC_STATIC=8;ACC_FINAL=16;ACC_SYNCHRONIZED=32;ACC_BRIDGE=64;ACC_VARARGS=128;ACC_NATIVE=256;ACC_ABSTRACT=1024;ACC_STRICT=2048;ACC_SYNTHETIC=4096;constructor(){this.classFactory=null,this.ClassFactory=je,this.vm=null,this.api=null,this._initialized=!1,this._apiError=null,this._wakeupHandler=null,this._pollListener=null,this._pendingMainOps=[],this._pendingVmOps=[],this._cachedIsAppProcess=null;try{this._tryInitialize()}catch{}}_tryInitialize(){if(this._initialized)return!0;if(this._apiError!==null)throw this._apiError;let e;try{e=pt(),this.api=e}catch(r){throw this._apiError=r,r}if(e===null)return!1;let n=new Ie(e);return this.vm=n,$o(n),je._initialize(n,e),this.classFactory=new je,this._initialized=!0,!0}_dispose(){if(this.api===null)return;let{vm:e}=this;e.perform(n=>{je._disposeAll(n),y.dispose(n)}),Script.nextTick(()=>{Ie.dispose(e)})}get available(){return this._tryInitialize()}get androidVersion(){return dt()}synchronized(e,n){let{$h:r=e}=e;if(!(r instanceof NativePointer))throw new Error("Java.synchronized: the first argument `obj` must be either a pointer or a Java instance");let o=this.vm.getEnv();de("VM::MonitorEnter",o.monitorEnter(r));try{n()}finally{o.monitorExit(r)}}enumerateLoadedClasses(e){this._checkAvailable();let{flavor:n}=this.api;n==="jvm"?this._enumerateLoadedClassesJvm(e):n==="art"?this._enumerateLoadedClassesArt(e):this._enumerateLoadedClassesDalvik(e)}enumerateLoadedClassesSync(){let e=[];return this.enumerateLoadedClasses({onMatch(n){e.push(n)},onComplete(){}}),e}enumerateClassLoaders(e){this._checkAvailable();let{flavor:n}=this.api;if(n==="jvm")this._enumerateClassLoadersJvm(e);else if(n==="art")this._enumerateClassLoadersArt(e);else throw new Error("Enumerating class loaders is not supported on Dalvik")}enumerateClassLoadersSync(){let e=[];return this.enumerateClassLoaders({onMatch(n){e.push(n)},onComplete(){}}),e}_enumerateLoadedClassesJvm(e){let{api:n,vm:r}=this,{jvmti:o}=n,i=r.getEnv(),s=Memory.alloc(Au),c=Memory.alloc(di);o.getLoadedClasses(s,c);let a=s.readS32(),l=c.readPointer(),d=[];for(let p=0;p!==a;p++)d.push(l.add(p*di).readPointer());o.deallocate(l);try{for(let p of d){let f=i.getClassName(p);e.onMatch(f,p)}e.onComplete()}finally{d.forEach(p=>{i.deleteLocalRef(p)})}}_enumerateClassLoadersJvm(e){this.choose("java.lang.ClassLoader",e)}_enumerateLoadedClassesArt(e){let{vm:n,api:r}=this,o=n.getEnv(),i=r["art::JavaVMExt::AddGlobalRef"],{vm:s}=r;ye(n,o,c=>{let a=Hn(l=>{let d=i(s,c,l);try{let p=o.getClassName(d);e.onMatch(p,d)}finally{o.deleteGlobalRef(d)}return!0});r["art::ClassLinker::VisitClasses"](r.artClassLinker.address,a)}),e.onComplete()}_enumerateClassLoadersArt(e){let{classFactory:n,vm:r,api:o}=this,i=r.getEnv(),s=o["art::ClassLinker::VisitClassLoaders"];if(s===void 0)throw new Error("This API is only available on Android >= 7.0");let c=n.use("java.lang.ClassLoader"),a=[],l=o["art::JavaVMExt::AddGlobalRef"],{vm:d}=o;ye(r,i,p=>{let f=Zn(u=>(a.push(l(d,p,u)),!0));$n(()=>{s(o.artClassLinker.address,f)})});try{a.forEach(p=>{let f=n.cast(p,c);e.onMatch(f)})}finally{a.forEach(p=>{i.deleteGlobalRef(p)})}e.onComplete()}_enumerateLoadedClassesDalvik(e){let{api:n}=this,r=ptr("0xcbcacccd"),o=172,i=8,c=n.gDvm.add(o).readPointer(),a=c.readS32(),d=c.add(12).readPointer(),p=a*i;for(let f=0;f{let s=i.loader;return i.loader=s!==null?n.wrap(s,o,r):null,i})}scheduleOnMainThread(e){this.performNow(()=>{this._pendingMainOps.push(e);let{_wakeupHandler:n}=this;if(n===null){let{classFactory:r}=this,o=r.use("android.os.Handler"),i=r.use("android.os.Looper");n=o.$new(i.getMainLooper()),this._wakeupHandler=n}this._pollListener===null&&(this._pollListener=Interceptor.attach(Process.getModuleByName("libc.so").getExportByName("epoll_wait"),this._makePollHook()),Interceptor.flush()),n.sendEmptyMessage(1)})}_makePollHook(){let e=Process.id,{_pendingMainOps:n}=this;return function(){if(this.threadId!==e)return;let r;for(;(r=n.shift())!==void 0;)try{r()}catch(o){Script.nextTick(()=>{throw o})}}}perform(e){if(this._checkAvailable(),!this._isAppProcess()||this.classFactory.loader!==null)try{this.vm.perform(e)}catch(n){Script.nextTick(()=>{throw n})}else this._pendingVmOps.push(e),this._pendingVmOps.length===1&&this._performPendingVmOpsWhenReady()}performNow(e){return this._checkAvailable(),this.vm.perform(()=>{let{classFactory:n}=this;if(this._isAppProcess()&&n.loader===null){let o=n.use("android.app.ActivityThread").currentApplication();o!==null&&ui(n,o)}return e()})}_performPendingVmOpsWhenReady(){this.vm.perform(()=>{let{classFactory:e}=this,n=e.use("android.app.ActivityThread"),r=n.currentApplication();if(r!==null){ui(e,r),this._performPendingVmOps();return}let o=this,i=!1,s="early",c=n.handleBindApplication;c.implementation=function(d){if(d.instrumentationName.value!==null){s="late";let f=e.use("android.app.LoadedApk").makeApplication;f.implementation=function(u,_){return i||(i=!0,pi(e,this),o._performPendingVmOps()),f.apply(this,arguments)}}c.apply(this,arguments)};let l=n.getPackageInfo.overloads.map(d=>[d.argumentTypes.length,d]).sort(([d],[p])=>p-d).map(([d,p])=>p)[0];l.implementation=function(...d){let p=l.call(this,...d);return!i&&s==="early"&&(i=!0,pi(e,p),o._performPendingVmOps()),p}})}_performPendingVmOps(){let{vm:e,_pendingVmOps:n}=this,r;for(;(r=n.shift())!==void 0;)try{e.perform(r)}catch(o){Script.nextTick(()=>{throw o})}}use(e,n){return this.classFactory.use(e,n)}openClassFile(e){return this.classFactory.openClassFile(e)}choose(e,n){this.classFactory.choose(e,n)}retain(e){return this.classFactory.retain(e)}cast(e,n){return this.classFactory.cast(e,n)}array(e,n){return this.classFactory.array(e,n)}backtrace(e){return qn(this.vm,e)}isMainThread(){let e=this.classFactory.use("android.os.Looper"),n=e.getMainLooper(),r=e.myLooper();return r===null?!1:n.$isSameObject(r)}registerClass(e){return this.classFactory.registerClass(e)}deoptimizeEverything(){let{vm:e}=this;return Yn(e,e.getEnv())}deoptimizeBootImage(){let{vm:e}=this;return Xn(e,e.getEnv())}deoptimizeMethod(e){let{vm:n}=this;return Qn(n,n.getEnv(),e)}_checkAvailable(){if(!this.available)throw new Error("Java API not available")}_isAppProcess(){let e=this._cachedIsAppProcess;if(e===null){if(this.api.flavor==="jvm")return e=!1,this._cachedIsAppProcess=e,e;let n=new NativeFunction(Module.getGlobalExportByName("readlink"),"pointer",["pointer","pointer","pointer"],{exceptions:"propagate"}),r=Memory.allocUtf8String("/proc/self/exe"),o=1024,i=Memory.alloc(o),s=n(r,i,ptr(o)).toInt32();if(s!==-1){let c=i.readUtf8String(s);e=/^\/system\/bin\/app_process/.test(c)}else e=!0;this._cachedIsAppProcess=e}return e}};function ui(t,e){let n=t.use("android.os.Process");t.loader=e.getClassLoader(),n.myUid()===n.SYSTEM_UID.value?(t.cacheDir="/data/system",t.codeCacheDir="/data/dalvik-cache"):"getCodeCacheDir"in e?(t.cacheDir=e.getCacheDir().getCanonicalPath(),t.codeCacheDir=e.getCodeCacheDir().getCanonicalPath()):(t.cacheDir=e.getFilesDir().getCanonicalPath(),t.codeCacheDir=e.getCacheDir().getCanonicalPath())}function pi(t,e){let n=t.use("java.io.File");t.loader=e.getClassLoader();let r=n.$new(e.getDataDir()).getCanonicalPath();t.cacheDir=r,t.codeCacheDir=r+"/cache"}var wr=new Sr;Script.bindWeak(wr,()=>{wr._dispose()});var gt=wr;gt.performNow(function(){try{let t="top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry",e=null;try{e=gt.use(t)}catch{gt.enumerateClassLoaders({onMatch(r){if(e===null)try{r.loadClass(t),e=gt.ClassFactory.get(r).use(t)}catch{}},onComplete(){}})}if(e===null)throw new Error("GuestRuntimeRegistry ClassLoader was not found");send({kind:"fridabox-registry",value:e.describe()})}catch(t){send({kind:"fridabox-error",value:String(t.stack||t)})}}); diff --git a/scripts/dist/sample-hook.js b/scripts/dist/sample-hook.js new file mode 100644 index 0000000..00c1be3 --- /dev/null +++ b/scripts/dist/sample-hook.js @@ -0,0 +1,1887 @@ +📦 +236304 /scripts/sample-hook.js +✄ +var _i=Object.defineProperty;var mi=(t,e)=>{for(var n in e)_i(t,n,{get:e[n],enumerable:!0})};var we=[],be=[],Gt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";for(let t=0,e=Gt.length;t0)throw new Error("Invalid string. Length must be a multiple of 4");let n=t.indexOf("=");n===-1&&(n=e);let r=n===e?0:4-n%4;return[n,r]}function bi(t,e,n){return(e+n)*3/4-n}function Cr(t){let e=gi(t),n=e[0],r=e[1],o=new Uint8Array(bi(t,n,r)),i=0,s=r>0?n-4:n,c;for(c=0;c>16&255,o[i++]=a>>8&255,o[i++]=a&255}if(r===2){let a=be[t.charCodeAt(c)]<<2|be[t.charCodeAt(c+1)]>>4;o[i++]=a&255}if(r===1){let a=be[t.charCodeAt(c)]<<10|be[t.charCodeAt(c+1)]<<4|be[t.charCodeAt(c+2)]>>2;o[i++]=a>>8&255,o[i++]=a&255}return o}function yi(t){return we[t>>18&63]+we[t>>12&63]+we[t>>6&63]+we[t&63]}function Ei(t,e,n){let r=[];for(let o=e;os?s:i+o));if(n===1){let i=t[e-1];r.push(we[i>>2]+we[i<<4&63]+"==")}else if(n===2){let i=(t[e-2]<<8)+t[e-1];r.push(we[i>>10]+we[i>>4&63]+we[i<<2&63]+"=")}return r.join("")}function tt(t,e,n,r,o){let i,s,c=o*8-r-1,a=(1<>1,d=-7,p=n?o-1:0,f=n?-1:1,u=t[e+p];for(p+=f,i=u&(1<<-d)-1,u>>=-d,d+=c;d>0;)i=i*256+t[e+p],p+=f,d-=8;for(s=i&(1<<-d)-1,i>>=-d,d+=r;d>0;)s=s*256+t[e+p],p+=f,d-=8;if(i===0)i=1-l;else{if(i===a)return s?NaN:(u?-1:1)*(1/0);s=s+Math.pow(2,r),i=i-l}return(u?-1:1)*s*Math.pow(2,i-r)}function Ht(t,e,n,r,o,i){let s,c,a,l=i*8-o-1,d=(1<>1,f=o===23?Math.pow(2,-24)-Math.pow(2,-77):0,u=r?0:i-1,_=r?1:-1,h=e<0||e===0&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(c=isNaN(e)?1:0,s=d):(s=Math.floor(Math.log(e)/Math.LN2),e*(a=Math.pow(2,-s))<1&&(s--,a*=2),s+p>=1?e+=f/a:e+=f*Math.pow(2,1-p),e*a>=2&&(s++,a/=2),s+p>=d?(c=0,s=d):s+p>=1?(c=(e*a-1)*Math.pow(2,o),s=s+p):(c=e*Math.pow(2,p-1)*Math.pow(2,o),s=0));o>=8;)t[n+u]=c&255,u+=_,c/=256,o-=8;for(s=s<0;)t[n+u]=s&255,u+=_,s/=256,l-=8;t[n+u-_]|=h*128}var wi={INSPECT_MAX_BYTES:50},Zt=2147483647;m.TYPED_ARRAY_SUPPORT=!0;Object.defineProperty(m.prototype,"parent",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.buffer}});Object.defineProperty(m.prototype,"offset",{enumerable:!0,get:function(){if(m.isBuffer(this))return this.byteOffset}});function Ae(t){if(t>Zt)throw new RangeError('The value "'+t+'" is invalid for option "size"');let e=new Uint8Array(t);return Object.setPrototypeOf(e,m.prototype),e}function m(t,e,n){if(typeof t=="number"){if(typeof e=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return Qt(t)}return xr(t,e,n)}m.poolSize=8192;function xr(t,e,n){if(typeof t=="string")return Ci(t,e);if(ArrayBuffer.isView(t))return Ti(t);if(t==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(t instanceof ArrayBuffer||t&&t.buffer instanceof ArrayBuffer||t instanceof SharedArrayBuffer||t&&t.buffer instanceof SharedArrayBuffer)return Wt(t,e,n);if(typeof t=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');let r=t.valueOf&&t.valueOf();if(r!=null&&r!==t)return m.from(r,e,n);let o=Ai(t);if(o)return o;if(typeof Symbol<"u"&&Symbol.toPrimitive!=null&&typeof t[Symbol.toPrimitive]=="function")return m.from(t[Symbol.toPrimitive]("string"),e,n);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t)}m.from=function(t,e,n){return xr(t,e,n)};Object.setPrototypeOf(m.prototype,Uint8Array.prototype);Object.setPrototypeOf(m,Uint8Array);function Nr(t){if(typeof t!="number")throw new TypeError('"size" argument must be of type number');if(t<0)throw new RangeError('The value "'+t+'" is invalid for option "size"')}function Ii(t,e,n){return Nr(t),t<=0?Ae(t):e!==void 0?typeof n=="string"?Ae(t).fill(e,n):Ae(t).fill(e):Ae(t)}m.alloc=function(t,e,n){return Ii(t,e,n)};function Qt(t){return Nr(t),Ae(t<0?0:Yt(t)|0)}m.allocUnsafe=function(t){return Qt(t)};m.allocUnsafeSlow=function(t){return Qt(t)};function Ci(t,e){if((typeof e!="string"||e==="")&&(e="utf8"),!m.isEncoding(e))throw new TypeError("Unknown encoding: "+e);let n=kr(t,e)|0,r=Ae(n),o=r.write(t,e);return o!==n&&(r=r.slice(0,o)),r}function qt(t){let e=t.length<0?0:Yt(t.length)|0,n=Ae(e);for(let r=0;r=Zt)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+Zt.toString(16)+" bytes");return t|0}m.isBuffer=function(e){return e!=null&&e._isBuffer===!0&&e!==m.prototype};m.compare=function(e,n){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),n instanceof Uint8Array&&(n=m.from(n,n.offset,n.byteLength)),!m.isBuffer(e)||!m.isBuffer(n))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(e===n)return 0;let r=e.length,o=n.length;for(let i=0,s=Math.min(r,o);io.length?(m.isBuffer(s)||(s=m.from(s.buffer,s.byteOffset,s.byteLength)),s.copy(o,i)):Uint8Array.prototype.set.call(o,s,i);else if(m.isBuffer(s))s.copy(o,i);else throw new TypeError('"list" argument must be an Array of Buffers');i+=s.length}return o};function kr(t,e){if(m.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||t instanceof ArrayBuffer)return t.byteLength;if(typeof t!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);let n=t.length,r=arguments.length>2&&arguments[2]===!0;if(!r&&n===0)return 0;let o=!1;for(;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":return Kt(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return n*2;case"hex":return n>>>1;case"base64":return Br(t).length;default:if(o)return r?-1:Kt(t).length;e=(""+e).toLowerCase(),o=!0}}m.byteLength=kr;function Li(t,e,n){let r=!1;if((e===void 0||e<0)&&(e=0),e>this.length||((n===void 0||n>this.length)&&(n=this.length),n<=0)||(n>>>=0,e>>>=0,n<=e))return"";for(t||(t="utf8");;)switch(t){case"hex":return Di(this,e,n);case"utf8":case"utf-8":return jr(this,e,n);case"ascii":return Pi(this,e,n);case"latin1":case"binary":return Fi(this,e,n);case"base64":return Ri(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ui(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}m.prototype._isBuffer=!0;function Oe(t,e,n){let r=t[e];t[e]=t[n],t[n]=r}m.prototype.swap16=function(){let e=this.length;if(e%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let n=0;nn&&(e+=" ... "),""};m.prototype[Symbol.for("nodejs.util.inspect.custom")]=m.prototype.inspect;m.prototype.compare=function(e,n,r,o,i){if(e instanceof Uint8Array&&(e=m.from(e,e.offset,e.byteLength)),!m.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(n===void 0&&(n=0),r===void 0&&(r=e?e.length:0),o===void 0&&(o=0),i===void 0&&(i=this.length),n<0||r>e.length||o<0||i>this.length)throw new RangeError("out of range index");if(o>=i&&n>=r)return 0;if(o>=i)return-1;if(n>=r)return 1;if(n>>>=0,r>>>=0,o>>>=0,i>>>=0,this===e)return 0;let s=i-o,c=r-n,a=Math.min(s,c),l=this.slice(o,i),d=e.slice(n,r);for(let p=0;p2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,Number.isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0)if(o)n=0;else return-1;if(typeof e=="string"&&(e=m.from(e,r)),m.isBuffer(e))return e.length===0?-1:Tr(t,e,n,r,o);if(typeof e=="number")return e=e&255,typeof Uint8Array.prototype.indexOf=="function"?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):Tr(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function Tr(t,e,n,r,o){let i=1,s=t.length,c=e.length;if(r!==void 0&&(r=String(r).toLowerCase(),r==="ucs2"||r==="ucs-2"||r==="utf16le"||r==="utf-16le")){if(t.length<2||e.length<2)return-1;i=2,s/=2,c/=2,n/=2}function a(d,p){return i===1?d[p]:d.readUInt16BE(p*i)}let l;if(o){let d=-1;for(l=n;ls&&(n=s-c),l=n;l>=0;l--){let d=!0;for(let p=0;po&&(r=o)):r=o;let i=e.length;r>i/2&&(r=i/2);let s;for(s=0;s>>0,isFinite(r)?(r=r>>>0,o===void 0&&(o="utf8")):(o=r,r=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let i=this.length-n;if((r===void 0||r>i)&&(r=i),e.length>0&&(r<0||n<0)||n>this.length)throw new RangeError("Attempt to write outside buffer bounds");o||(o="utf8");let s=!1;for(;;)switch(o){case"hex":return xi(this,e,n,r);case"utf8":case"utf-8":return Ni(this,e,n,r);case"ascii":case"latin1":case"binary":return ki(this,e,n,r);case"base64":return Mi(this,e,n,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return ji(this,e,n,r);default:if(s)throw new TypeError("Unknown encoding: "+o);o=(""+o).toLowerCase(),s=!0}};m.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Ri(t,e,n){return e===0&&n===t.length?$t(t):$t(t.slice(e,n))}function jr(t,e,n){n=Math.min(t.length,n);let r=[],o=e;for(;o239?4:i>223?3:i>191?2:1;if(o+c<=n){let a,l,d,p;switch(c){case 1:i<128&&(s=i);break;case 2:a=t[o+1],(a&192)===128&&(p=(i&31)<<6|a&63,p>127&&(s=p));break;case 3:a=t[o+1],l=t[o+2],(a&192)===128&&(l&192)===128&&(p=(i&15)<<12|(a&63)<<6|l&63,p>2047&&(p<55296||p>57343)&&(s=p));break;case 4:a=t[o+1],l=t[o+2],d=t[o+3],(a&192)===128&&(l&192)===128&&(d&192)===128&&(p=(i&15)<<18|(a&63)<<12|(l&63)<<6|d&63,p>65535&&p<1114112&&(s=p))}}s===null?(s=65533,c=1):s>65535&&(s-=65536,r.push(s>>>10&1023|55296),s=56320|s&1023),r.push(s),o+=c}return Oi(r)}var Ar=4096;function Oi(t){let e=t.length;if(e<=Ar)return String.fromCharCode.apply(String,t);let n="",r=0;for(;rr)&&(n=r);let o="";for(let i=e;ir&&(e=r),n<0?(n+=r,n<0&&(n=0)):n>r&&(n=r),nn)throw new RangeError("Trying to access beyond buffer length")}m.prototype.readUintLE=m.prototype.readUIntLE=function(e,n,r){e=e>>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e],i=1,s=0;for(;++s>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e+--n],i=1;for(;n>0&&(i*=256);)o+=this[e+--n]*i;return o};m.prototype.readUint8=m.prototype.readUInt8=function(e,n){return e=e>>>0,n||se(e,1,this.length),this[e]};m.prototype.readUint16LE=m.prototype.readUInt16LE=function(e,n){return e=e>>>0,n||se(e,2,this.length),this[e]|this[e+1]<<8};m.prototype.readUint16BE=m.prototype.readUInt16BE=function(e,n){return e=e>>>0,n||se(e,2,this.length),this[e]<<8|this[e+1]};m.prototype.readUint32LE=m.prototype.readUInt32LE=function(e,n){return e=e>>>0,n||se(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+this[e+3]*16777216};m.prototype.readUint32BE=m.prototype.readUInt32BE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]*16777216+(this[e+1]<<16|this[e+2]<<8|this[e+3])};m.prototype.readBigUInt64LE=function(e){e=e>>>0,$e(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&nt(e,this.length-8);let o=n+this[++e]*2**8+this[++e]*2**16+this[++e]*2**24,i=this[++e]+this[++e]*2**8+this[++e]*2**16+r*2**24;return BigInt(o)+(BigInt(i)<>>0,$e(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&nt(e,this.length-8);let o=n*2**24+this[++e]*2**16+this[++e]*2**8+this[++e],i=this[++e]*2**24+this[++e]*2**16+this[++e]*2**8+r;return(BigInt(o)<>>0,n=n>>>0,r||se(e,n,this.length);let o=this[e],i=1,s=0;for(;++s=i&&(o-=Math.pow(2,8*n)),o};m.prototype.readIntBE=function(e,n,r){e=e>>>0,n=n>>>0,r||se(e,n,this.length);let o=n,i=1,s=this[e+--o];for(;o>0&&(i*=256);)s+=this[e+--o]*i;return i*=128,s>=i&&(s-=Math.pow(2,8*n)),s};m.prototype.readInt8=function(e,n){return e=e>>>0,n||se(e,1,this.length),this[e]&128?(255-this[e]+1)*-1:this[e]};m.prototype.readInt16LE=function(e,n){e=e>>>0,n||se(e,2,this.length);let r=this[e]|this[e+1]<<8;return r&32768?r|4294901760:r};m.prototype.readInt16BE=function(e,n){e=e>>>0,n||se(e,2,this.length);let r=this[e+1]|this[e]<<8;return r&32768?r|4294901760:r};m.prototype.readInt32LE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24};m.prototype.readInt32BE=function(e,n){return e=e>>>0,n||se(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]};m.prototype.readBigInt64LE=function(e){e=e>>>0,$e(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&nt(e,this.length-8);let o=this[e+4]+this[e+5]*2**8+this[e+6]*2**16+(r<<24);return(BigInt(o)<>>0,$e(e,"offset");let n=this[e],r=this[e+7];(n===void 0||r===void 0)&&nt(e,this.length-8);let o=(n<<24)+this[++e]*2**16+this[++e]*2**8+this[++e];return(BigInt(o)<>>0,n||se(e,4,this.length),tt(this,e,!0,23,4)};m.prototype.readFloatBE=function(e,n){return e=e>>>0,n||se(e,4,this.length),tt(this,e,!1,23,4)};m.prototype.readDoubleLE=function(e,n){return e=e>>>0,n||se(e,8,this.length),tt(this,e,!0,52,8)};m.prototype.readDoubleBE=function(e,n){return e=e>>>0,n||se(e,8,this.length),tt(this,e,!1,52,8)};function pe(t,e,n,r,o,i){if(!m.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||et.length)throw new RangeError("Index out of range")}m.prototype.writeUintLE=m.prototype.writeUIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,r=r>>>0,!o){let c=Math.pow(2,8*r)-1;pe(this,e,n,r,c,0)}let i=1,s=0;for(this[n]=e&255;++s>>0,r=r>>>0,!o){let c=Math.pow(2,8*r)-1;pe(this,e,n,r,c,0)}let i=r-1,s=1;for(this[n+i]=e&255;--i>=0&&(s*=256);)this[n+i]=e/s&255;return n+r};m.prototype.writeUint8=m.prototype.writeUInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,255,0),this[n]=e&255,n+1};m.prototype.writeUint16LE=m.prototype.writeUInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeUint16BE=m.prototype.writeUInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,65535,0),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeUint32LE=m.prototype.writeUInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n+3]=e>>>24,this[n+2]=e>>>16,this[n+1]=e>>>8,this[n]=e&255,n+4};m.prototype.writeUint32BE=m.prototype.writeUInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,4294967295,0),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};function Rr(t,e,n,r,o){Ur(e,r,o,t,n,7);let i=Number(e&BigInt(4294967295));t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i,i=i>>8,t[n++]=i;let s=Number(e>>BigInt(32)&BigInt(4294967295));return t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s,s=s>>8,t[n++]=s,n}function Or(t,e,n,r,o){Ur(e,r,o,t,n,7);let i=Number(e&BigInt(4294967295));t[n+7]=i,i=i>>8,t[n+6]=i,i=i>>8,t[n+5]=i,i=i>>8,t[n+4]=i;let s=Number(e>>BigInt(32)&BigInt(4294967295));return t[n+3]=s,s=s>>8,t[n+2]=s,s=s>>8,t[n+1]=s,s=s>>8,t[n]=s,n+8}m.prototype.writeBigUInt64LE=function(e,n=0){return Rr(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeBigUInt64BE=function(e,n=0){return Or(this,e,n,BigInt(0),BigInt("0xffffffffffffffff"))};m.prototype.writeIntLE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let i=0,s=1,c=0;for(this[n]=e&255;++i>0)-c&255;return n+r};m.prototype.writeIntBE=function(e,n,r,o){if(e=+e,n=n>>>0,!o){let a=Math.pow(2,8*r-1);pe(this,e,n,r,a-1,-a)}let i=r-1,s=1,c=0;for(this[n+i]=e&255;--i>=0&&(s*=256);)e<0&&c===0&&this[n+i+1]!==0&&(c=1),this[n+i]=(e/s>>0)-c&255;return n+r};m.prototype.writeInt8=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,1,127,-128),e<0&&(e=255+e+1),this[n]=e&255,n+1};m.prototype.writeInt16LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e&255,this[n+1]=e>>>8,n+2};m.prototype.writeInt16BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,2,32767,-32768),this[n]=e>>>8,this[n+1]=e&255,n+2};m.prototype.writeInt32LE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),this[n]=e&255,this[n+1]=e>>>8,this[n+2]=e>>>16,this[n+3]=e>>>24,n+4};m.prototype.writeInt32BE=function(e,n,r){return e=+e,n=n>>>0,r||pe(this,e,n,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),this[n]=e>>>24,this[n+1]=e>>>16,this[n+2]=e>>>8,this[n+3]=e&255,n+4};m.prototype.writeBigInt64LE=function(e,n=0){return Rr(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};m.prototype.writeBigInt64BE=function(e,n=0){return Or(this,e,n,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))};function Pr(t,e,n,r,o,i){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function Fr(t,e,n,r,o){return e=+e,n=n>>>0,o||Pr(t,e,n,4,34028234663852886e22,-34028234663852886e22),Ht(t,e,n,r,23,4),n+4}m.prototype.writeFloatLE=function(e,n,r){return Fr(this,e,n,!0,r)};m.prototype.writeFloatBE=function(e,n,r){return Fr(this,e,n,!1,r)};function Dr(t,e,n,r,o){return e=+e,n=n>>>0,o||Pr(t,e,n,8,17976931348623157e292,-17976931348623157e292),Ht(t,e,n,r,52,8),n+8}m.prototype.writeDoubleLE=function(e,n,r){return Dr(this,e,n,!0,r)};m.prototype.writeDoubleBE=function(e,n,r){return Dr(this,e,n,!1,r)};m.prototype.copy=function(e,n,r,o){if(!m.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r||(r=0),!o&&o!==0&&(o=this.length),n>=e.length&&(n=e.length),n||(n=0),o>0&&o=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length),e.length-n>>0,r=r===void 0?this.length:r>>>0,e||(e=0);let i;if(typeof e=="number")for(i=n;i2**32?o=Lr(String(n)):typeof n=="bigint"&&(o=String(n),(n>BigInt(2)**BigInt(32)||n<-(BigInt(2)**BigInt(32)))&&(o=Lr(o)),o+="n"),r+=` It must be ${e}. Received ${o}`,r},RangeError);function Lr(t){let e="",n=t.length,r=t[0]==="-"?1:0;for(;n>=r+4;n-=3)e=`_${t.slice(n-3,n)}${e}`;return`${t.slice(0,n)}${e}`}function Bi(t,e,n){$e(e,"offset"),(t[e]===void 0||t[e+n]===void 0)&&nt(e,t.length-(n+1))}function Ur(t,e,n,r,o,i){if(t>n||t3?e===0||e===BigInt(0)?c=`>= 0${s} and < 2${s} ** ${(i+1)*8}${s}`:c=`>= -(2${s} ** ${(i+1)*8-1}${s}) and < 2 ** ${(i+1)*8-1}${s}`:c=`>= ${e}${s} and <= ${n}${s}`,new Ge.ERR_OUT_OF_RANGE("value",c,t)}Bi(r,o,i)}function $e(t,e){if(typeof t!="number")throw new Ge.ERR_INVALID_ARG_TYPE(e,"number",t)}function nt(t,e,n){throw Math.floor(t)!==t?($e(t,n),new Ge.ERR_OUT_OF_RANGE(n||"offset","an integer",t)):e<0?new Ge.ERR_BUFFER_OUT_OF_BOUNDS:new Ge.ERR_OUT_OF_RANGE(n||"offset",`>= ${n?1:0} and <= ${e}`,t)}var zi=/[^+/0-9A-Za-z-_]/g;function Vi(t){if(t=t.split("=")[0],t=t.trim().replace(zi,""),t.length<2)return"";for(;t.length%4!==0;)t=t+"=";return t}function Kt(t,e){e=e||1/0;let n,r=t.length,o=null,i=[];for(let s=0;s55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&i.push(239,191,189);continue}else if(s+1===r){(e-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&i.push(239,191,189),o=n;continue}n=(o-55296<<10|n-56320)+65536}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;i.push(n)}else if(n<2048){if((e-=2)<0)break;i.push(n>>6|192,n&63|128)}else if(n<65536){if((e-=3)<0)break;i.push(n>>12|224,n>>6&63|128,n&63|128)}else if(n<1114112){if((e-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,n&63|128)}else throw new Error("Invalid code point")}return i}function Ji(t){let e=[];for(let n=0;n>8,o=n%256,i.push(o),i.push(r);return i}function Br(t){return Cr(Vi(t))}function yt(t,e,n,r){let o;for(o=0;o=e.length||o>=t.length);++o)e[o+n]=t[o];return o}var $i=function(){let t="0123456789abcdef",e=new Array(256);for(let n=0;n<16;++n){let r=n*16;for(let o=0;o<16;++o)e[r+o]=t[n]+t[o]}return e}();var Dt={};mi(Dt,{ArtMethod:()=>Nt,ArtStackVisitor:()=>jn,DVM_JNI_ENV_OFFSET_SELF:()=>co,HandleVector:()=>lt,VariableSizedHandleScope:()=>dt,backtrace:()=>qn,deoptimizeBootImage:()=>Xn,deoptimizeEverything:()=>Yn,deoptimizeMethod:()=>Qn,ensureClassInitialized:()=>hc,getAndroidApiLevel:()=>ee,getAndroidVersion:()=>ut,getApi:()=>J,getArtApexVersion:()=>zn,getArtClassSpec:()=>Jn,getArtFieldSpec:()=>Pt,getArtMethodSpec:()=>_e,getArtThreadFromEnv:()=>Ft,getArtThreadSpec:()=>qe,makeArtClassLoaderVisitor:()=>Zn,makeArtClassVisitor:()=>Hn,makeMethodMangler:()=>al,makeObjectVisitorPredicate:()=>tr,revertGlobalPatches:()=>Wn,translateMethod:()=>cl,withAllArtThreadsSuspended:()=>$n,withRunnableArtThread:()=>ye});var{pageSize:en,pointerSize:Hi}=Process,tn=class{constructor(e){this.sliceSize=e,this.slicesPerPage=en/e,this.pages=[],this.free=[]}allocateSlice(e,n){let r=e.near===void 0,o=n===1;if(r&&o){let i=this.free.pop();if(i!==void 0)return i}else if(n{n.deleteGlobalRef(e)})}}y.prototype.fromReflectedMethod=x(7,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.fromReflectedField=x(8,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.toReflectedMethod=x(9,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getSuperclass=x(10,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isAssignableFrom=x(11,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.toReflectedField=x(12,"pointer",["pointer","pointer","pointer","uint8"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.throw=x(13,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.exceptionOccurred=x(15,"pointer",["pointer"],function(t){return t(this.handle)});y.prototype.exceptionDescribe=x(16,"void",["pointer"],function(t){t(this.handle)});y.prototype.exceptionClear=x(17,"void",["pointer"],function(t){t(this.handle)});y.prototype.pushLocalFrame=x(19,"int32",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.popLocalFrame=x(20,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newGlobalRef=x(21,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.deleteGlobalRef=x(22,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.deleteLocalRef=x(23,"void",["pointer","pointer"],function(t,e){t(this.handle,e)});y.prototype.isSameObject=x(24,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.newLocalRef=x(25,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.allocObject=x(27,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectClass=x(31,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.isInstanceOf=x(32,"uint8",["pointer","pointer","pointer"],function(t,e,n){return!!t(this.handle,e,n)});y.prototype.getMethodId=x(33,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getFieldId=x(94,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getIntField=x(100,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStaticMethodId=x(113,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticFieldId=x(144,"pointer",["pointer","pointer","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,Memory.allocUtf8String(n),Memory.allocUtf8String(r))});y.prototype.getStaticIntField=x(150,"int32",["pointer","pointer","pointer"],function(t,e,n){return t(this.handle,e,n)});y.prototype.getStringLength=x(164,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getStringChars=x(165,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringChars=x(166,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.newStringUtf=x(167,"pointer",["pointer","pointer"],function(t,e){let n=Memory.allocUtf8String(e);return t(this.handle,n)});y.prototype.getStringUtfChars=x(169,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseStringUtfChars=x(170,"void",["pointer","pointer","pointer"],function(t,e,n){t(this.handle,e,n)});y.prototype.getArrayLength=x(171,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.newObjectArray=x(172,"pointer",["pointer","int32","pointer","pointer"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.getObjectArrayElement=x(173,"pointer",["pointer","pointer","int32"],function(t,e,n){return t(this.handle,e,n)});y.prototype.setObjectArrayElement=x(174,"void",["pointer","pointer","int32","pointer"],function(t,e,n,r){t(this.handle,e,n,r)});y.prototype.newBooleanArray=x(175,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newByteArray=x(176,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newCharArray=x(177,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newShortArray=x(178,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newIntArray=x(179,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newLongArray=x(180,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newFloatArray=x(181,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.newDoubleArray=x(182,"pointer",["pointer","int32"],function(t,e){return t(this.handle,e)});y.prototype.getBooleanArrayElements=x(183,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getByteArrayElements=x(184,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getCharArrayElements=x(185,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getShortArrayElements=x(186,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getIntArrayElements=x(187,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getLongArrayElements=x(188,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getFloatArrayElements=x(189,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.getDoubleArrayElements=x(190,"pointer",["pointer","pointer","pointer"],function(t,e){return t(this.handle,e,NULL)});y.prototype.releaseBooleanArrayElements=x(191,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseByteArrayElements=x(192,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseCharArrayElements=x(193,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseShortArrayElements=x(194,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseIntArrayElements=x(195,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseLongArrayElements=x(196,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseFloatArrayElements=x(197,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.releaseDoubleArrayElements=x(198,"pointer",["pointer","pointer","pointer","int32"],function(t,e,n){t(this.handle,e,n,Me)});y.prototype.getByteArrayRegion=x(200,"void",["pointer","pointer","int","int","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setBooleanArrayRegion=x(207,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setByteArrayRegion=x(208,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setCharArrayRegion=x(209,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setShortArrayRegion=x(210,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setIntArrayRegion=x(211,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setLongArrayRegion=x(212,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setFloatArrayRegion=x(213,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.setDoubleArrayRegion=x(214,"void",["pointer","pointer","int32","int32","pointer"],function(t,e,n,r,o){t(this.handle,e,n,r,o)});y.prototype.registerNatives=x(215,"int32",["pointer","pointer","pointer","int32"],function(t,e,n,r){return t(this.handle,e,n,r)});y.prototype.monitorEnter=x(217,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.monitorExit=x(218,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getDirectBufferAddress=x(230,"pointer",["pointer","pointer"],function(t,e){return t(this.handle,e)});y.prototype.getObjectRefType=x(232,"int32",["pointer","pointer"],function(t,e){return t(this.handle,e)});var Vr=new Map;function It(t,e,n,r){return gn(this,"p",ga,t,e,n,r)}function mn(t,e,n,r){return gn(this,"v",ba,t,e,n,r)}function ma(t,e,n,r){return gn(this,"n",ya,t,e,n,r)}function gn(t,e,n,r,o,i,s){if(s!==void 0)return n(t,r,o,i,s);let c=[r,e,o].concat(i).join("|"),a=Vr.get(c);return a===void 0&&(a=n(t,r,o,i,Jr),Vr.set(c,a)),a}function ga(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer"].concat(r),o)}function ba(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer","..."].concat(r),o)}function ya(t,e,n,r,o){return new NativeFunction(wt(t).add(e*St).readPointer(),n,["pointer","pointer","pointer","pointer","..."].concat(r),o)}y.prototype.constructor=function(t,e){return mn.call(this,Wi,"pointer",t,e)};y.prototype.vaMethod=function(t,e,n){let r=ca[t];if(r===void 0)throw new Error("Unsupported type: "+t);return mn.call(this,r,t,e,n)};y.prototype.nonvirtualVaMethod=function(t,e,n){let r=la[t];if(r===void 0)throw new Error("Unsupported type: "+t);return ma.call(this,r,t,e,n)};y.prototype.staticVaMethod=function(t,e,n){let r=da[t];if(r===void 0)throw new Error("Unsupported type: "+t);return mn.call(this,r,t,e,n)};y.prototype.getField=function(t){let e=ua[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,t,[])};y.prototype.getStaticField=function(t){let e=fa[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,t,[])};y.prototype.setField=function(t){let e=pa[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,"void",[t])};y.prototype.setStaticField=function(t){let e=ha[t];if(e===void 0)throw new Error("Unsupported type: "+t);return It.call(this,e,"void",[t])};var on=null;y.prototype.javaLangClass=function(){if(on===null){let t=this.findClass("java/lang/Class");try{let e=this.getMethodId.bind(this,t);on={handle:Pe(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getSimpleName:e("getSimpleName","()Ljava/lang/String;"),getGenericSuperclass:e("getGenericSuperclass","()Ljava/lang/reflect/Type;"),getDeclaredConstructors:e("getDeclaredConstructors","()[Ljava/lang/reflect/Constructor;"),getDeclaredMethods:e("getDeclaredMethods","()[Ljava/lang/reflect/Method;"),getDeclaredFields:e("getDeclaredFields","()[Ljava/lang/reflect/Field;"),isArray:e("isArray","()Z"),isPrimitive:e("isPrimitive","()Z"),isInterface:e("isInterface","()Z"),getComponentType:e("getComponentType","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return on};var sn=null;y.prototype.javaLangObject=function(){if(sn===null){let t=this.findClass("java/lang/Object");try{let e=this.getMethodId.bind(this,t);sn={handle:Pe(this.newGlobalRef(t)),toString:e("toString","()Ljava/lang/String;"),getClass:e("getClass","()Ljava/lang/Class;")}}finally{this.deleteLocalRef(t)}}return sn};var an=null;y.prototype.javaLangReflectConstructor=function(){if(an===null){let t=this.findClass("java/lang/reflect/Constructor");try{an={getGenericParameterTypes:this.getMethodId(t,"getGenericParameterTypes","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return an};var cn=null;y.prototype.javaLangReflectMethod=function(){if(cn===null){let t=this.findClass("java/lang/reflect/Method");try{let e=this.getMethodId.bind(this,t);cn={getName:e("getName","()Ljava/lang/String;"),getGenericParameterTypes:e("getGenericParameterTypes","()[Ljava/lang/reflect/Type;"),getParameterTypes:e("getParameterTypes","()[Ljava/lang/Class;"),getGenericReturnType:e("getGenericReturnType","()Ljava/lang/reflect/Type;"),getGenericExceptionTypes:e("getGenericExceptionTypes","()[Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),isVarArgs:e("isVarArgs","()Z")}}finally{this.deleteLocalRef(t)}}return cn};var ln=null;y.prototype.javaLangReflectField=function(){if(ln===null){let t=this.findClass("java/lang/reflect/Field");try{let e=this.getMethodId.bind(this,t);ln={getName:e("getName","()Ljava/lang/String;"),getType:e("getType","()Ljava/lang/Class;"),getGenericType:e("getGenericType","()Ljava/lang/reflect/Type;"),getModifiers:e("getModifiers","()I"),toString:e("toString","()Ljava/lang/String;")}}finally{this.deleteLocalRef(t)}}return ln};var dn=null;y.prototype.javaLangReflectTypeVariable=function(){if(dn===null){let t=this.findClass("java/lang/reflect/TypeVariable");try{let e=this.getMethodId.bind(this,t);dn={handle:Pe(this.newGlobalRef(t)),getName:e("getName","()Ljava/lang/String;"),getBounds:e("getBounds","()[Ljava/lang/reflect/Type;"),getGenericDeclaration:e("getGenericDeclaration","()Ljava/lang/reflect/GenericDeclaration;")}}finally{this.deleteLocalRef(t)}}return dn};var un=null;y.prototype.javaLangReflectWildcardType=function(){if(un===null){let t=this.findClass("java/lang/reflect/WildcardType");try{let e=this.getMethodId.bind(this,t);un={handle:Pe(this.newGlobalRef(t)),getLowerBounds:e("getLowerBounds","()[Ljava/lang/reflect/Type;"),getUpperBounds:e("getUpperBounds","()[Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return un};var pn=null;y.prototype.javaLangReflectGenericArrayType=function(){if(pn===null){let t=this.findClass("java/lang/reflect/GenericArrayType");try{pn={handle:Pe(this.newGlobalRef(t)),getGenericComponentType:this.getMethodId(t,"getGenericComponentType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return pn};var fn=null;y.prototype.javaLangReflectParameterizedType=function(){if(fn===null){let t=this.findClass("java/lang/reflect/ParameterizedType");try{let e=this.getMethodId.bind(this,t);fn={handle:Pe(this.newGlobalRef(t)),getActualTypeArguments:e("getActualTypeArguments","()[Ljava/lang/reflect/Type;"),getRawType:e("getRawType","()Ljava/lang/reflect/Type;"),getOwnerType:e("getOwnerType","()Ljava/lang/reflect/Type;")}}finally{this.deleteLocalRef(t)}}return fn};var hn=null;y.prototype.javaLangString=function(){if(hn===null){let t=this.findClass("java/lang/String");try{hn={handle:Pe(this.newGlobalRef(t))}}finally{this.deleteLocalRef(t)}}return hn};y.prototype.getClassName=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangClass().getName);try{return this.stringFromJni(e)}finally{this.deleteLocalRef(e)}};y.prototype.getObjectClassName=function(t){let e=this.getObjectClass(t);try{return this.getClassName(e)}finally{this.deleteLocalRef(e)}};y.prototype.getActualTypeArgument=function(t){let e=this.vaMethod("pointer",[])(this.handle,t,this.javaLangReflectParameterizedType().getActualTypeArguments);if(this.throwIfExceptionPending(),!e.isNull())try{return this.getTypeNameFromFirstTypeElement(e)}finally{this.deleteLocalRef(e)}};y.prototype.getTypeNameFromFirstTypeElement=function(t){if(this.getArrayLength(t)>0){let n=this.getObjectArrayElement(t,0);try{return this.getTypeName(n)}finally{this.deleteLocalRef(n)}}else return"java.lang.Object"};y.prototype.getTypeName=function(t,e){let n=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle))return this.getArrayTypeName(t);if(this.isInstanceOf(t,this.javaLangReflectParameterizedType().handle)){let r=n(this.handle,t,this.javaLangReflectParameterizedType().getRawType);this.throwIfExceptionPending();let o;try{o=this.getTypeName(r)}finally{this.deleteLocalRef(r)}return e&&(o+="<"+this.getActualTypeArgument(t)+">"),o}else return this.isInstanceOf(t,this.javaLangReflectTypeVariable().handle)||this.isInstanceOf(t,this.javaLangReflectWildcardType().handle),"java.lang.Object"};y.prototype.getArrayTypeName=function(t){let e=this.vaMethod("pointer",[]);if(this.isInstanceOf(t,this.javaLangClass().handle))return this.getClassName(t);if(this.isInstanceOf(t,this.javaLangReflectGenericArrayType().handle)){let n=e(this.handle,t,this.javaLangReflectGenericArrayType().getGenericComponentType);this.throwIfExceptionPending();try{return"[L"+this.getTypeName(n)+";"}finally{this.deleteLocalRef(n)}}else return"[Ljava.lang.Object;"};y.prototype.stringFromJni=function(t){let e=this.getStringChars(t);if(e.isNull())throw new Error("Unable to access string");try{let n=this.getStringLength(t);return e.readUtf16String(n)}finally{this.releaseStringChars(t,e)}};var Gr=65542,He=Process.pointerSize,bn=Process.getCurrentThreadId(),Fe=new Map,ot=new Map;function Ie(t){let e=t.vm,n=null,r=null,o=null;function i(){let c=e.readPointer(),a={exceptions:"propagate"};n=new NativeFunction(c.add(4*He).readPointer(),"int32",["pointer","pointer","pointer"],a),r=new NativeFunction(c.add(5*He).readPointer(),"int32",["pointer"],a),o=new NativeFunction(c.add(6*He).readPointer(),"int32",["pointer","pointer","int32"],a)}this.handle=e,this.perform=function(c){let a=Process.getCurrentThreadId(),l=s(a);if(l!==null)return c(l);let d=this._tryGetEnv(),p=d!==null;p||(d=this.attachCurrentThread(),Fe.set(a,!0)),this.link(a,d);try{return c(d)}finally{let f=a===bn;if(f||this.unlink(a),!p&&!f){let u=Fe.get(a);Fe.delete(a),u&&this.detachCurrentThread()}}},this.attachCurrentThread=function(){let c=Memory.alloc(He);return de("VM::AttachCurrentThread",n(e,c,NULL)),new y(c.readPointer(),this)},this.detachCurrentThread=function(){de("VM::DetachCurrentThread",r(e))},this.preventDetachDueToClassLoader=function(){let c=Process.getCurrentThreadId();Fe.has(c)&&Fe.set(c,!1)},this.getEnv=function(){let c=s(Process.getCurrentThreadId());if(c!==null)return c;let a=Memory.alloc(He),l=o(e,a,Gr);if(l===-2)throw new Error("Current thread is not attached to the Java VM; please move this code inside a Java.perform() callback");return de("VM::GetEnv",l),new y(a.readPointer(),this)},this.tryGetEnv=function(){let c=s(Process.getCurrentThreadId());return c!==null?c:this._tryGetEnv()},this._tryGetEnv=function(){let c=this.tryGetEnvHandle(Gr);return c===null?null:new y(c,this)},this.tryGetEnvHandle=function(c){let a=Memory.alloc(He);return o(e,a,c)!==0?null:a.readPointer()},this.makeHandleDestructor=function(c){return()=>{this.perform(a=>{a.deleteGlobalRef(c)})}},this.link=function(c,a){let l=ot.get(c);l===void 0?ot.set(c,[a,1]):l[1]++},this.unlink=function(c){let a=ot.get(c);a[1]===1?ot.delete(c):a[1]--};function s(c){let a=ot.get(c);return a===void 0?null:a[0]}i.call(this)}Ie.dispose=function(t){Fe.get(bn)===!0&&(Fe.delete(bn),t.detachCurrentThread())};var Ea=4,v=Process.pointerSize,{readU32:va,readPointer:Sa,writeU32:wa,writePointer:Ia}=NativePointer.prototype,Ca=1,Ta=8,Aa=16,Lt=256,La=524288,xa=2097152,ao=1073741824,Na=524288,ka=134217728,$r=1048576,Ma=2097152,ja=268435456,Ra=268435456,Oa=0,xn=3,Nn=5,Bn=ptr(1).not(),Pa=2147467263,Fa=4294963200,Ot=17*v,Da=18*v,co=12,Ua=112,Ba=116,za=0,En=56,Hr=4,Va=8,Ja=10,Ga=12,$a=14,Ha=28,Za=36,qa=0,Wa=1,Ka=2,Qa=3,Ya=4,Xa=5,ec=6,tc=7,Zr=2147483648,nc=28,ct=3*v,rc=3*v,oc=1,ic=1,lo=le(mc),sc=le(xc),_e=le(kc),qe=le(Mc),ac=le(jc),cc=le(Vc),ut=le(Fc),uo=le(Dc),ee=le(Uc),zn=le(Bc),lc=le(Hc),dc=Process.arch==="ia32"?Ml:kl,W={exceptions:"propagate"},it={},vn=null,Sn=null,po=null,oe=null,Vn=[],xt=new Map,fo=[],wn=null,qr=0,Wr=!1,Kr=!1,st=null,uc=[],In=null,Ct=null;function J(){return vn===null&&(vn=pc()),vn}function pc(){let t=Process.enumerateModules().filter(u=>/^lib(art|dvm).so$/.test(u.name)).filter(u=>!/\/system\/fake-libs/.test(u.path));if(t.length===0)return null;let e=t[0],n=e.name.indexOf("art")!==-1?"art":"dalvik",r=n==="art",o={module:e,find(u){let{module:_}=this,h=_.findExportByName(u);return h===null&&(h=_.findSymbolByName(u)),h},flavor:n,addLocalReference:null};o.isApiLevel34OrApexEquivalent=r&&(o.find("_ZN3art7AppInfo29GetPrimaryApkReferenceProfileEv")!==null||o.find("_ZN3art6Thread15RunFlipFunctionEPS0_")!==null);let i=r?{functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],artInterpreterToCompiledCodeBridge:function(u){this.artInterpreterToCompiledCodeBridge=u},_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE:["art::JavaVMExt::AddGlobalRef","pointer",["pointer","pointer","pointer"]],_ZN3art17ReaderWriterMutex13ExclusiveLockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveLock","void",["pointer","pointer"]],_ZN3art17ReaderWriterMutex15ExclusiveUnlockEPNS_6ThreadE:["art::ReaderWriterMutex::ExclusiveUnlock","void",["pointer","pointer"]],_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE:function(u){this["art::IndirectReferenceTable::Add"]=new NativeFunction(u,"pointer",["pointer","uint","pointer"],W)},_ZN3art9JavaVMExt12DecodeGlobalEPv:function(u){let _;ee()>=26?_=dc(u,["pointer","pointer"]):_=new NativeFunction(u,"pointer",["pointer","pointer"],W),this["art::JavaVMExt::DecodeGlobal"]=function(h,g,b){return _(h,b)}},_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv:["art::JavaVMExt::DecodeGlobal","pointer",["pointer","pointer","pointer"]],_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZNK3art6Thread13DecodeJObjectEP8_jobject:["art::Thread::DecodeJObject","pointer",["pointer","pointer"]],_ZN3art10ThreadList10SuspendAllEPKcb:["art::ThreadList::SuspendAll","void",["pointer","pointer","bool"]],_ZN3art10ThreadList10SuspendAllEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::ThreadList::SuspendAll"]=function(h,g,b){return _(h)}},_ZN3art10ThreadList9ResumeAllEv:["art::ThreadList::ResumeAll","void",["pointer"]],_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE:["art::ClassLinker::VisitClasses","void",["pointer","pointer"]],_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer"],W);this["art::ClassLinker::VisitClasses"]=function(h,g){_(h,g,NULL)}},_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE:["art::ClassLinker::VisitClassLoaders","void",["pointer","pointer"]],_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_:["art::gc::Heap::VisitObjects","void",["pointer","pointer","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:["art::gc::Heap::GetInstances","void",["pointer","pointer","pointer","int","pointer"]],_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE:function(u){let _=new NativeFunction(u,"void",["pointer","pointer","pointer","bool","int","pointer"],W);this["art::gc::Heap::GetInstances"]=function(h,g,b,E,C){_(h,g,b,0,E,C)}},_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","uint","bool"]],_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb:["art::StackVisitor::StackVisitor","void",["pointer","pointer","pointer","uint","size_t","bool"]],_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb:["art::StackVisitor::WalkStack","void",["pointer","bool"]],_ZNK3art12StackVisitor9GetMethodEv:["art::StackVisitor::GetMethod","pointer",["pointer"]],_ZNK3art12StackVisitor16DescribeLocationEv:function(u){this["art::StackVisitor::DescribeLocation"]=At(u,["pointer"])},_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv:function(u){this["art::StackVisitor::GetCurrentQuickFrameInfo"]=$c(u)},_ZN3art7Context6CreateEv:["art::Context::Create","pointer",[]],_ZN3art6Thread18GetLongJumpContextEv:["art::Thread::GetLongJumpContext","pointer",["pointer"]],_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE:function(u){this["art::mirror::Class::GetDescriptor"]=u},_ZN3art6mirror5Class11GetLocationEv:function(u){this["art::mirror::Class::GetLocation"]=At(u,["pointer"])},_ZN3art9ArtMethod12PrettyMethodEb:function(u){this["art::ArtMethod::PrettyMethod"]=At(u,["pointer","bool"])},_ZN3art12PrettyMethodEPNS_9ArtMethodEb:function(u){this["art::ArtMethod::PrettyMethodNullSafe"]=At(u,["pointer","bool"])},_ZN3art6Thread14CurrentFromGdbEv:["art::Thread::CurrentFromGdb","pointer",[]],_ZN3art6mirror6Object5CloneEPNS_6ThreadE:function(u){this["art::mirror::Object::Clone"]=new NativeFunction(u,"pointer",["pointer","pointer"],W)},_ZN3art6mirror6Object5CloneEPNS_6ThreadEm:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","pointer"],W);this["art::mirror::Object::Clone"]=function(h,g){let b=NULL;return _(h,g,b)}},_ZN3art6mirror6Object5CloneEPNS_6ThreadEj:function(u){let _=new NativeFunction(u,"pointer",["pointer","pointer","uint"],W);this["art::mirror::Object::Clone"]=function(h,g){return _(h,g,0)}},_ZN3art3Dbg14SetJdwpAllowedEb:["art::Dbg::SetJdwpAllowed","void",["bool"]],_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE:["art::Dbg::ConfigureJdwp","void",["pointer"]],_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv:["art::InternalDebuggerControlCallback::StartDebugger","void",["pointer"]],_ZN3art3Dbg9StartJdwpEv:["art::Dbg::StartJdwp","void",[]],_ZN3art3Dbg8GoActiveEv:["art::Dbg::GoActive","void",[]],_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE:["art::Dbg::RequestDeoptimization","void",["pointer"]],_ZN3art3Dbg20ManageDeoptimizationEv:["art::Dbg::ManageDeoptimization","void",[]],_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv:["art::Instrumentation::EnableDeoptimization","void",["pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc:["art::Instrumentation::DeoptimizeEverything","void",["pointer","pointer"]],_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv:function(u){let _=new NativeFunction(u,"void",["pointer"],W);this["art::Instrumentation::DeoptimizeEverything"]=function(h,g){_(h)}},_ZN3art7Runtime19DeoptimizeBootImageEv:["art::Runtime::DeoptimizeBootImage","void",["pointer"]],_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE:["art::Instrumentation::Deoptimize","void",["pointer","pointer"]],_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID:["art::jni::JniIdManager::DecodeMethodId","pointer",["pointer","pointer"]],_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID:["art::jni::JniIdManager::DecodeFieldId","pointer",["pointer","pointer"]],_ZN3art11interpreter18GetNterpEntryPointEv:["art::interpreter::GetNterpEntryPoint","pointer",[]],_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi:["art::Monitor::TranslateLocation","void",["pointer","uint32","pointer","pointer"]]},variables:{_ZN3art3Dbg9gRegistryE:function(u){this.isJdwpStarted=()=>!u.readPointer().isNull()},_ZN3art3Dbg15gDebuggerActiveE:function(u){this.isDebuggerActive=()=>!!u.readU8()}},optionals:new Set(["artInterpreterToCompiledCodeBridge","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art9JavaVMExt12AddGlobalRefEPNS_6ThreadEPNS_6mirror6ObjectE","_ZN3art9JavaVMExt12DecodeGlobalEPv","_ZN3art9JavaVMExt12DecodeGlobalEPNS_6ThreadEPv","_ZNK3art6Thread19DecodeGlobalJObjectEP8_jobject","_ZNK3art6Thread13DecodeJObjectEP8_jobject","_ZN3art10ThreadList10SuspendAllEPKcb","_ZN3art10ThreadList10SuspendAllEv","_ZN3art11ClassLinker12VisitClassesEPNS_12ClassVisitorE","_ZN3art11ClassLinker12VisitClassesEPFbPNS_6mirror5ClassEPvES4_","_ZNK3art11ClassLinker17VisitClassLoadersEPNS_18ClassLoaderVisitorE","_ZN3art6mirror6Object5CloneEPNS_6ThreadE","_ZN3art6mirror6Object5CloneEPNS_6ThreadEm","_ZN3art6mirror6Object5CloneEPNS_6ThreadEj","_ZN3art22IndirectReferenceTable3AddEjPNS_6mirror6ObjectE","_ZN3art22IndirectReferenceTable3AddENS_15IRTSegmentStateENS_6ObjPtrINS_6mirror6ObjectEEE","_ZN3art2gc4Heap12VisitObjectsEPFvPNS_6mirror6ObjectEPvES5_","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art2gc4Heap12GetInstancesERNS_24VariableSizedHandleScopeENS_6HandleINS_6mirror5ClassEEEbiRNSt3__16vectorINS4_INS5_6ObjectEEENS8_9allocatorISB_EEEE","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEjb","_ZN3art12StackVisitorC2EPNS_6ThreadEPNS_7ContextENS0_13StackWalkKindEmb","_ZN3art12StackVisitor9WalkStackILNS0_16CountTransitionsE0EEEvb","_ZNK3art12StackVisitor9GetMethodEv","_ZNK3art12StackVisitor16DescribeLocationEv","_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv","_ZN3art7Context6CreateEv","_ZN3art6Thread18GetLongJumpContextEv","_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE","_ZN3art6mirror5Class11GetLocationEv","_ZN3art9ArtMethod12PrettyMethodEb","_ZN3art12PrettyMethodEPNS_9ArtMethodEb","_ZN3art3Dbg13ConfigureJdwpERKNS_4JDWP11JdwpOptionsE","_ZN3art31InternalDebuggerControlCallback13StartDebuggerEv","_ZN3art3Dbg15gDebuggerActiveE","_ZN3art15instrumentation15Instrumentation20EnableDeoptimizationEv","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEPKc","_ZN3art15instrumentation15Instrumentation20DeoptimizeEverythingEv","_ZN3art7Runtime19DeoptimizeBootImageEv","_ZN3art15instrumentation15Instrumentation10DeoptimizeEPNS_9ArtMethodE","_ZN3art3Dbg9StartJdwpEv","_ZN3art3Dbg8GoActiveEv","_ZN3art3Dbg21RequestDeoptimizationERKNS_21DeoptimizationRequestE","_ZN3art3Dbg20ManageDeoptimizationEv","_ZN3art3Dbg9gRegistryE","_ZN3art3jni12JniIdManager14DecodeMethodIdEP10_jmethodID","_ZN3art3jni12JniIdManager13DecodeFieldIdEP9_jfieldID","_ZN3art11interpreter18GetNterpEntryPointEv","_ZN3art7Monitor17TranslateLocationEPNS_9ArtMethodEjPPKcPi"])}:{functions:{_Z20dvmDecodeIndirectRefP6ThreadP8_jobject:["dvmDecodeIndirectRef","pointer",["pointer","pointer"]],_Z15dvmUseJNIBridgeP6MethodPv:["dvmUseJNIBridge","void",["pointer","pointer"]],_Z20dvmHeapSourceGetBasev:["dvmHeapSourceGetBase","pointer",[]],_Z21dvmHeapSourceGetLimitv:["dvmHeapSourceGetLimit","pointer",[]],_Z16dvmIsValidObjectPK6Object:["dvmIsValidObject","uint8",["pointer"]],JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]]},variables:{gDvmJni:function(u){this.gDvmJni=u},gDvm:function(u){this.gDvm=u}}},{functions:s={},variables:c={},optionals:a=new Set}=i,l=[];for(let[u,_]of Object.entries(s)){let h=o.find(u);h!==null?typeof _=="function"?_.call(o,h):o[_[0]]=new NativeFunction(h,_[1],_[2],W):a.has(u)||l.push(u)}for(let[u,_]of Object.entries(c)){let h=o.find(u);h!==null?_.call(o,h):a.has(u)||l.push(u)}if(l.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+l.join(", "));let d=Memory.alloc(v),p=Memory.alloc(Ea);if(de("JNI_GetCreatedJavaVMs",o.JNI_GetCreatedJavaVMs(d,1,p)),p.readInt()===0)return null;if(o.vm=d.readPointer(),r){let u=ee(),_;u>=27?_=33554432:u>=24?_=16777216:_=0,o.kAccCompileDontBother=_;let h=o.vm.add(v).readPointer();o.artRuntime=h;let g=lo(o),b=g.offset,E=b.instrumentation;o.artInstrumentation=E!==null?h.add(E):null,zn()>=36e7&&o.artInstrumentation!=null&&(o.artInstrumentation=o.artInstrumentation.readPointer()),o.artHeap=h.add(b.heap).readPointer(),o.artThreadList=h.add(b.threadList).readPointer();let A=h.add(b.classLinker).readPointer(),M=Nc(h,g).offset,R=A.add(M.quickResolutionTrampoline).readPointer(),k=A.add(M.quickImtConflictTrampoline).readPointer(),N=A.add(M.quickGenericJniTrampoline).readPointer(),S=A.add(M.quickToInterpreterBridgeTrampoline).readPointer();o.artClassLinker={address:A,quickResolutionTrampoline:R,quickImtConflictTrampoline:k,quickGenericJniTrampoline:N,quickToInterpreterBridgeTrampoline:S};let L=new Ie(o);o.artQuickGenericJniTrampoline=Cn(N,L),o.artQuickToInterpreterBridge=Cn(S,L),o.artQuickResolutionTrampoline=Cn(R,L),o["art::JavaVMExt::AddGlobalRef"]===void 0&&(o["art::JavaVMExt::AddGlobalRef"]=Cl(o)),o["art::JavaVMExt::DecodeGlobal"]===void 0&&(o["art::JavaVMExt::DecodeGlobal"]=Tl(o)),o["art::ArtMethod::PrettyMethod"]===void 0&&(o["art::ArtMethod::PrettyMethod"]=o["art::ArtMethod::PrettyMethodNullSafe"]),o["art::interpreter::GetNterpEntryPoint"]!==void 0?o.artNterpEntryPoint=o["art::interpreter::GetNterpEntryPoint"]():o.artNterpEntryPoint=o.find("ExecuteNterpImpl"),oe=Wc(o,L),Nl(o);let j=null;Object.defineProperty(o,"jvmti",{get(){return j===null&&(j=[fc(L,this.artRuntime)]),j[0]}})}let f=e.enumerateImports().filter(u=>u.name.indexOf("_Z")===0).reduce((u,_)=>(u[_.name]=_.address,u),{});return o.$new=new NativeFunction(f._Znwm||f._Znwj,"pointer",["ulong"],W),o.$delete=new NativeFunction(f._ZdlPv,"void",["pointer"],W),po=r?Pn:Fn,o}function fc(t,e){let n=null;return t.perform(()=>{let r=J().find("_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE");if(r===null)return;let o=new NativeFunction(r,"bool",["pointer","pointer","pointer"]),i=Memory.alloc(v);if(!o(e,Memory.allocUtf8String("libopenjdkjvmti.so"),i))return;let c=Et.v1_2|1073741824,a=t.tryGetEnvHandle(c);if(a===null)return;n=new Le(a,t);let l=Memory.alloc(8);l.writeU64(vt.canTagObjects),n.addCapabilities(l)!==0&&(n=null)}),n}function hc(t,e){J().flavor==="art"&&t.getClassName(e)}function _c(t){return{offset:v===4?{globalsLock:32,globals:72}:{globalsLock:64,globals:112}}}function mc(t){let e=t.vm,n=t.artRuntime,r=v===4?200:384,o=r+100*v,i=ee(),s=uo(),{isApiLevel34OrApexEquivalent:c}=t,a=null;for(let d=r;d!==o;d+=v)if(n.add(d).readPointer().equals(e)){let f,u=null;i>=33||s==="Tiramisu"||c?(f=[d-4*v],u=d-v):i>=30||s==="R"?(f=[d-3*v,d-4*v],u=d-v):i>=29?f=[d-2*v]:i>=27?f=[d-ct-3*v]:f=[d-ct-2*v];for(let _ of f){let h=_-v,g=h-v,b;c?b=g-9*v:i>=24?b=g-8*v:i>=23?b=g-7*v:b=g-4*v;let E={offset:{heap:b,threadList:g,internTable:h,classLinker:_,jniIdManager:u}};if(ho(n,E)!==null){a=E;break}}break}if(a===null)throw new Error("Unable to determine Runtime field offsets");let l=zn()>=36e7;return a.offset.instrumentation=l?Sc(t):bc(t),a.offset.jniIdsIndirection=Tc(t),a}var gc={ia32:Qr,x64:Qr,arm:yc,arm64:Ec};function bc(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:xe(e,gc[Process.arch],{limit:30})}function Qr(t){if(t.mnemonic!=="lea")return null;let e=t.operands[1].value.disp;return e<256||e>1024?null:e}function yc(t){if(t.mnemonic!=="add.w")return null;let e=t.operands;if(e.length!==3)return null;let n=e[2];return n.type!=="imm"?null:n.value}function Ec(t){if(t.mnemonic!=="add")return null;let e=t.operands;if(e.length!==3||e[0].value==="sp"||e[1].value==="sp")return null;let n=e[2];if(n.type!=="imm")return null;let r=n.value.valueOf();return r<256||r>1024?null:r}var vc={ia32:Yr,x64:Yr,arm:wc,arm64:Ic};function Sc(t){let e=t["art::Runtime::DeoptimizeBootImage"];return e===void 0?null:xe(e,vc[Process.arch],{limit:30})}function Yr(t){if(t.mnemonic!=="mov")return null;let e=t.operands;if(e[0].value!=="rax")return null;let r=e[1];if(r.type!=="mem")return null;let o=r.value;if(o.base!=="rdi")return null;let i=o.disp;return i<256||i>1024?null:i}function wc(t){return null}function Ic(t){if(t.mnemonic!=="ldr")return null;let e=t.operands;if(e[0].value==="x0")return null;let n=e[1].value;if(n.base!=="x0")return null;let r=n.disp;return r<256||r>1024?null:r}var Cc={ia32:Xr,x64:Xr,arm:Ac,arm64:Lc};function Tc(t){let e=t.find("_ZN3art7Runtime12SetJniIdTypeENS_9JniIdTypeE");if(e===null)return null;let n=xe(e,Cc[Process.arch],{limit:20});if(n===null)throw new Error("Unable to determine Runtime.jni_ids_indirection_ offset");return n}function Xr(t){return t.mnemonic==="cmp"?t.operands[0].value.disp:null}function Ac(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Lc(t,e){if(e===null)return null;let{mnemonic:n}=t,{mnemonic:r}=e;return n==="cmp"&&r==="ldr"||n==="bl"&&r==="str"?e.operands[1].value.disp:null}function xc(){let e={"4-21":136,"4-22":136,"4-23":172,"4-24":196,"4-25":196,"4-26":196,"4-27":196,"4-28":212,"4-29":172,"4-30":180,"4-31":180,"8-21":224,"8-22":224,"8-23":296,"8-24":344,"8-25":344,"8-26":352,"8-27":352,"8-28":392,"8-29":328,"8-30":336,"8-31":336}[`${v}-${ee()}`];if(e===void 0)throw new Error("Unable to determine Instrumentation field offsets");return{offset:{forcedInterpretOnly:4,deoptimizationEnabled:e}}}function Nc(t,e){let n=ho(t,e);if(n===null)throw new Error("Unable to determine ClassLinker field offsets");return n}function ho(t,e){if(Sn!==null)return Sn;let{classLinker:n,internTable:r}=e.offset,o=t.add(n).readPointer(),i=t.add(r).readPointer(),s=v===4?100:200,c=s+100*v,a=ee(),l=null;for(let d=s;d!==c;d+=v)if(o.add(d).readPointer().equals(i)){let f;a>=30||uo()==="R"?f=6:a>=29?f=4:a>=23?f=3:f=5;let u=d+f*v,_;a>=23?_=u-2*v:_=u-3*v,l={offset:{quickResolutionTrampoline:_,quickImtConflictTrampoline:u-v,quickGenericJniTrampoline:u,quickToInterpreterBridgeTrampoline:u+v}};break}return l!==null&&(Sn=l),l}function Jn(t){let n=null;return t.perform(r=>{let o=Pt(t),i=_e(t),s={artArrayLengthSize:4,artArrayEntrySize:o.size,artArrayMax:50},c={artArrayLengthSize:v,artArrayEntrySize:i.size,artArrayMax:100},a=(f,u,_)=>{let h=f.add(u).readPointer();if(h.isNull())return null;let g=_===4?h.readU32():h.readU64().valueOf();return g<=0?null:{length:g,data:h.add(_)}},l=(f,u,_,h)=>{try{let g=a(f,u,h.artArrayLengthSize);if(g===null)return!1;let b=Math.min(g.length,h.artArrayMax);for(let E=0;E!==b;E++)if(g.data.add(E*h.artArrayEntrySize).equals(_))return!0}catch{}return!1},d=r.findClass("java/lang/Thread"),p=r.newGlobalRef(d);try{let f;ye(t,r,N=>{f=J()["art::JavaVMExt::DecodeGlobal"](t,N,p)});let u=no(r.getFieldId(p,"name","Ljava/lang/String;")),_=no(r.getStaticFieldId(p,"MAX_PRIORITY","I")),h=-1,g=-1;for(let N=0;N!==256;N+=4)h===-1&&l(f,N,_,s)&&(h=N),g===-1&&l(f,N,u,s)&&(g=N);if(g===-1||h===-1)throw new Error("Unable to find fields in java/lang/Thread; please file a bug");let b=g!==h?h:0,E=g,C=-1,A=Kn(r.getMethodId(p,"getName","()Ljava/lang/String;"));for(let N=0;N!==256;N+=4)C===-1&&l(f,N,A,c)&&(C=N);if(C===-1)throw new Error("Unable to find methods in java/lang/Thread; please file a bug");let M=-1,k=a(f,C,c.artArrayLengthSize).length;for(let N=C;N!==256;N+=4)if(f.add(N).readU16()===k){M=N;break}if(M===-1)throw new Error("Unable to find copied methods in java/lang/Thread; please file a bug");n={offset:{ifields:E,methods:C,sfields:b,copiedMethodsOffset:M}}}finally{r.deleteLocalRef(d),r.deleteGlobalRef(p)}}),n}function kc(t){let e=J(),n;return t.perform(r=>{let o=r.findClass("android/os/Process"),i=Kn(r.getStaticMethodId(o,"getElapsedCpuTime","()J"));r.deleteLocalRef(o);let s=Process.getModuleByName("libandroid_runtime.so"),c=s.base,a=c.add(s.size),l=ee(),d=l<=21?8:v,p=Ca|Ta|Aa|Lt,f=~(ao|ja|Ma)>>>0,u=null,_=null,h=2;for(let E=0;E!==64&&h!==0;E+=4){let C=i.add(E);if(u===null){let A=C.readPointer();A.compare(c)>=0&&A.compare(a)<0&&(u=E,h--)}_===null&&(C.readU32()&f)===p&&(_=E,h--)}if(h!==0)throw new Error("Unable to determine ArtMethod field offsets");let g=u+d;n={size:l<=21?g+32:g+v,offset:{jniCode:u,quickCode:g,accessFlags:_}},"artInterpreterToCompiledCodeBridge"in e&&(n.offset.interpreterCode=u-d)}),n}function Pt(t){let e=ee();return e>=23?{size:16,offset:{accessFlags:4}}:e>=21?{size:24,offset:{accessFlags:12}}:null}function Mc(t){let e=ee(),n;return t.perform(r=>{let o=Ft(r),i=r.handle,s=null,c=null,a=null,l=null,d=null,p=null;for(let f=144;f!==256;f+=v)if(o.add(f).readPointer().equals(i)){c=f-6*v,d=f-4*v,p=f+2*v,e<=22&&(c-=v,s=c-v-9*8-3*4,a=f+6*v,d-=v,p-=v),l=f+9*v,e<=22&&(l+=2*v+4,v===8&&(l+=4)),e>=23&&(l+=v);break}if(l===null)throw new Error("Unable to determine ArtThread field offsets");n={offset:{isExceptionReportedToInstrumentation:s,exception:c,throwLocation:a,topHandleScope:l,managedStack:d,self:p}}}),n}function jc(){return ee()>=23?{offset:{topQuickFrame:0,link:v}}:{offset:{topQuickFrame:2*v,link:0}}}var Rc={ia32:eo,x64:eo,arm:Oc,arm64:Pc};function Cn(t,e){let n;return e.perform(r=>{let o=Ft(r),i=Rc[Process.arch],s=Instruction.parse(t),c=i(s);c!==null?n=o.add(c).readPointer():n=t}),n}function eo(t){return t.mnemonic==="jmp"?t.operands[0].value.disp:null}function Oc(t){return t.mnemonic==="ldr.w"?t.operands[1].value.disp:null}function Pc(t){return t.mnemonic==="ldr"?t.operands[1].value.disp:null}function Ft(t){return t.handle.add(v).readPointer()}function Fc(){return Gn("ro.build.version.release")}function Dc(){return Gn("ro.build.version.codename")}function Uc(){return parseInt(Gn("ro.build.version.sdk"),10)}function Bc(){try{let t=File.readAllText("/proc/self/mountinfo"),e=null,n=new Map;for(let o of t.trimEnd().split(` +`)){let i=o.split(" "),s=i[4];if(!s.startsWith("/apex/com.android.art"))continue;let c=i[10];s.includes("@")?n.set(c,s.split("@")[1]):e=c}let r=n.get(e);return r!==void 0?parseInt(r):to()}catch{return to()}}function to(){return ee()*1e7}var Tn=null,zc=92;function Gn(t){Tn===null&&(Tn=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("__system_property_get"),"int",["pointer","pointer"],W));let e=Memory.alloc(zc);return Tn(Memory.allocUtf8String(t),e),e.readUtf8String()}function ye(t,e,n){let r=cc(t,e),o=Ft(e).toString();if(it[o]=n,r(e.handle),it[o]!==void 0)throw delete it[o],new Error("Unable to perform state transition; please file a bug")}function Vc(t,e){let n=new NativeCallback(Jc,"void",["pointer"]);return go(t,e,n)}function Jc(t){let e=t.toString(),n=it[e];delete it[e],n(t)}function $n(t){let e=J(),n=e.artThreadList;e["art::ThreadList::SuspendAll"](n,Memory.allocUtf8String("frida"),!1?1:0);try{t()}finally{e["art::ThreadList::ResumeAll"](n)}}var kn=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((i,s)=>e(s)===!0?1:0,"bool",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function Hn(t){return J()["art::ClassLinker::VisitClasses"]instanceof NativeFunction?new kn(t):new NativeCallback(n=>t(n)===!0?1:0,"bool",["pointer","pointer"])}var Mn=class{constructor(e){let n=Memory.alloc(4*v),r=n.add(v);n.writePointer(r);let o=new NativeCallback((i,s)=>{e(s)},"void",["pointer","pointer"]);r.add(2*v).writePointer(o),this.handle=n,this._onVisit=o}};function Zn(t){return new Mn(t)}var Gc={"include-inlined-frames":0,"skip-inlined-frames":1},jn=class{constructor(e,n,r,o=0,i=!0){let s=J(),c=512,a=3*v,l=Memory.alloc(c+a);s["art::StackVisitor::StackVisitor"](l,e,n,Gc[r],o,i?1:0);let d=l.add(c);l.writePointer(d);let p=new NativeCallback(this._visitFrame.bind(this),"bool",["pointer"]);d.add(2*v).writePointer(p),this.handle=l,this._onVisitFrame=p;let f=l.add(v===4?12:24);this._curShadowFrame=f,this._curQuickFrame=f.add(v),this._curQuickFramePc=f.add(2*v),this._curOatQuickMethodHeader=f.add(3*v),this._getMethodImpl=s["art::StackVisitor::GetMethod"],this._descLocImpl=s["art::StackVisitor::DescribeLocation"],this._getCQFIImpl=s["art::StackVisitor::GetCurrentQuickFrameInfo"]}walkStack(e=!1){J()["art::StackVisitor::WalkStack"](this.handle,e?1:0)}_visitFrame(){return this.visitFrame()?1:0}visitFrame(){throw new Error("Subclass must implement visitFrame")}getMethod(){let e=this._getMethodImpl(this.handle);return e.isNull()?null:new Nt(e)}getCurrentQuickFramePc(){return this._curQuickFramePc.readPointer()}getCurrentQuickFrame(){return this._curQuickFrame.readPointer()}getCurrentShadowFrame(){return this._curShadowFrame.readPointer()}describeLocation(){let e=new jt;return this._descLocImpl(e,this.handle),e.disposeToString()}getCurrentOatQuickMethodHeader(){return this._curOatQuickMethodHeader.readPointer()}getCurrentQuickFrameInfo(){return this._getCQFIImpl(this.handle)}},Nt=class{constructor(e){this.handle=e}prettyMethod(e=!0){let n=new jt;return J()["art::ArtMethod::PrettyMethod"](n,this.handle,e?1:0),n.disposeToString()}toString(){return`ArtMethod(handle=${this.handle})`}};function $c(t){return function(e){let n=Memory.alloc(12);return lc(t)(n,e),{frameSizeInBytes:n.readU32(),coreSpillMask:n.add(4).readU32(),fpSpillMask:n.add(8).readU32()}}}function Hc(t){let e=NULL;switch(Process.arch){case"ia32":e=Ze(32,n=>{n.putMovRegRegOffsetPtr("ecx","esp",4),n.putMovRegRegOffsetPtr("edx","esp",8),n.putCallAddressWithArguments(t,["ecx","edx"]),n.putMovRegReg("esp","ebp"),n.putPopReg("ebp"),n.putRet()});break;case"x64":e=Ze(32,n=>{n.putPushReg("rdi"),n.putCallAddressWithArguments(t,["rsi"]),n.putPopReg("rdi"),n.putMovRegPtrReg("rdi","rax"),n.putMovRegOffsetPtrReg("rdi",8,"edx"),n.putRet()});break;case"arm":e=Ze(16,n=>{n.putCallAddressWithArguments(t,["r0","r1"]),n.putPopRegs(["r0","lr"]),n.putMovRegReg("pc","lr")});break;case"arm64":e=Ze(64,n=>{n.putPushRegReg("x0","lr"),n.putCallAddressWithArguments(t,["x1"]),n.putPopRegReg("x2","lr"),n.putStrRegRegOffset("x0","x2",0),n.putStrRegRegOffset("w1","x2",8),n.putRet()});break}return new NativeFunction(e,"void",["pointer","pointer"],W)}var Zc={ia32:globalThis.X86Relocator,x64:globalThis.X86Relocator,arm:globalThis.ThumbRelocator,arm64:globalThis.Arm64Relocator},Rn={ia32:globalThis.X86Writer,x64:globalThis.X86Writer,arm:globalThis.ThumbWriter,arm64:globalThis.Arm64Writer};function Ze(t,e){wn===null&&(wn=Memory.alloc(Process.pageSize));let n=wn.add(qr),r=Process.arch,o=Rn[r];return Memory.patchCode(n,t,i=>{let s=new o(i,{pc:n});if(e(s),s.flush(),s.offset>t)throw new Error(`Wrote ${s.offset}, exceeding maximum of ${t}`)}),qr+=t,r==="arm"?n.or(1):n}function qc(t,e){Kc(e),tl(e)}function Wc(t,e){let n=qe(e).offset,r=ac().offset,o=` +#include + +extern GMutex lock; +extern GHashTable * methods; +extern GHashTable * replacements; +extern gpointer last_seen_art_method; + +extern gpointer get_oat_quick_method_header_impl (gpointer method, gpointer pc); + +void +init (void) +{ + g_mutex_init (&lock); + methods = g_hash_table_new_full (NULL, NULL, NULL, NULL); + replacements = g_hash_table_new_full (NULL, NULL, NULL, NULL); +} + +void +finalize (void) +{ + g_hash_table_unref (replacements); + g_hash_table_unref (methods); + g_mutex_clear (&lock); +} + +gboolean +is_replacement_method (gpointer method) +{ + gboolean is_replacement; + + g_mutex_lock (&lock); + + is_replacement = g_hash_table_contains (replacements, method); + + g_mutex_unlock (&lock); + + return is_replacement; +} + +gpointer +get_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + + g_mutex_unlock (&lock); + + return replacement_method; +} + +void +set_replacement_method (gpointer original_method, + gpointer replacement_method) +{ + g_mutex_lock (&lock); + + g_hash_table_insert (methods, original_method, replacement_method); + g_hash_table_insert (replacements, replacement_method, original_method); + + g_mutex_unlock (&lock); +} + +void +synchronize_replacement_methods (guint quick_code_offset, + void * nterp_entrypoint, + void * quick_to_interpreter_bridge) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + { + void ** quick_code; + + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + quick_code = hooked_method + quick_code_offset; + if (*quick_code == nterp_entrypoint) + *quick_code = quick_to_interpreter_bridge; + } + + g_mutex_unlock (&lock); +} + +void +delete_replacement_method (gpointer original_method) +{ + gpointer replacement_method; + + g_mutex_lock (&lock); + + replacement_method = g_hash_table_lookup (methods, original_method); + if (replacement_method != NULL) + { + g_hash_table_remove (methods, original_method); + g_hash_table_remove (replacements, replacement_method); + } + + g_mutex_unlock (&lock); +} + +gpointer +translate_method (gpointer method) +{ + gpointer translated_method; + + g_mutex_lock (&lock); + + translated_method = g_hash_table_lookup (replacements, method); + + g_mutex_unlock (&lock); + + return (translated_method != NULL) ? translated_method : method; +} + +gpointer +find_replacement_method_from_quick_code (gpointer method, + gpointer thread) +{ + gpointer replacement_method; + gpointer managed_stack; + gpointer top_quick_frame; + gpointer link_managed_stack; + gpointer * link_top_quick_frame; + + replacement_method = get_replacement_method (method); + if (replacement_method == NULL) + return NULL; + + /* + * Stack check. + * + * Return NULL to indicate that the original method should be invoked, otherwise + * return a pointer to the replacement ArtMethod. + * + * If the caller is our own JNI replacement stub, then a stack transition must + * have been pushed onto the current thread's linked list. + * + * Therefore, we invoke the original method if the following conditions are met: + * 1- The current managed stack is empty. + * 2- The ArtMethod * inside the linked managed stack's top quick frame is the + * same as our replacement. + */ + managed_stack = thread + ${n.managedStack}; + top_quick_frame = *((gpointer *) (managed_stack + ${r.topQuickFrame})); + if (top_quick_frame != NULL) + return replacement_method; + + link_managed_stack = *((gpointer *) (managed_stack + ${r.link})); + if (link_managed_stack == NULL) + return replacement_method; + + link_top_quick_frame = GSIZE_TO_POINTER (*((gsize *) (link_managed_stack + ${r.topQuickFrame})) & ~((gsize) 1)); + if (link_top_quick_frame == NULL || *link_top_quick_frame != replacement_method) + return replacement_method; + + return NULL; +} + +void +on_interpreter_do_call (GumInvocationContext * ic) +{ + gpointer method, replacement_method; + + method = gum_invocation_context_get_nth_argument (ic, 0); + + replacement_method = get_replacement_method (method); + if (replacement_method != NULL) + gum_invocation_context_replace_nth_argument (ic, 0, replacement_method); +} + +gpointer +on_art_method_get_oat_quick_method_header (gpointer method, + gpointer pc) +{ + if (is_replacement_method (method)) + return NULL; + + return get_oat_quick_method_header_impl (method, pc); +} + +void +on_art_method_pretty_method (GumInvocationContext * ic) +{ + const guint this_arg_index = ${Process.arch==="arm64"?0:1}; + gpointer method; + + method = gum_invocation_context_get_nth_argument (ic, this_arg_index); + if (method == NULL) + gum_invocation_context_replace_nth_argument (ic, this_arg_index, last_seen_art_method); + else + last_seen_art_method = method; +} + +void +on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic) +{ + GHashTableIter iter; + gpointer hooked_method, replacement_method; + + g_mutex_lock (&lock); + + g_hash_table_iter_init (&iter, methods); + while (g_hash_table_iter_next (&iter, &hooked_method, &replacement_method)) + *((uint32_t *) replacement_method) = *((uint32_t *) hooked_method); + + g_mutex_unlock (&lock); +} +`,i=8,s=v,c=v,a=v,d=Memory.alloc(i+s+c+a),p=d.add(i),f=p.add(s),u=f.add(c),_=t.find(v===4?"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj":"_ZN3art9ArtMethod23GetOatQuickMethodHeaderEm"),h=new CModule(o,{lock:d,methods:p,replacements:f,last_seen_art_method:u,get_oat_quick_method_header_impl:_??ptr("0xdeadbeef")}),g={exceptions:"propagate",scheduling:"exclusive"};return{handle:h,replacedMethods:{isReplacement:new NativeFunction(h.is_replacement_method,"bool",["pointer"],g),get:new NativeFunction(h.get_replacement_method,"pointer",["pointer"],g),set:new NativeFunction(h.set_replacement_method,"void",["pointer","pointer"],g),synchronize:new NativeFunction(h.synchronize_replacement_methods,"void",["uint","pointer","pointer"],g),delete:new NativeFunction(h.delete_replacement_method,"void",["pointer"],g),translate:new NativeFunction(h.translate_method,"pointer",["pointer"],g),findReplacementFromQuickCode:h.find_replacement_method_from_quick_code},getOatQuickMethodHeaderImpl:_,hooks:{Interpreter:{doCall:h.on_interpreter_do_call},ArtMethod:{getOatQuickMethodHeader:h.on_art_method_get_oat_quick_method_header,prettyMethod:h.on_art_method_pretty_method},Gc:{copyingPhase:{onLeave:h.on_leave_gc_concurrent_copying_copying_phase},runFlip:{onEnter:h.on_leave_gc_concurrent_copying_copying_phase}}}}}function Kc(t){Kr||(Kr=!0,Qc(t),Yc(),Xc(),el())}function Qc(t){let e=J();[e.artQuickGenericJniTrampoline,e.artQuickToInterpreterBridge,e.artQuickResolutionTrampoline].forEach(r=>{Memory.protect(r,32,"rwx");let o=new Mt(r);o.activate(t),fo.push(o)})}function Yc(){let t=J(),e=ee(),{isApiLevel34OrApexEquivalent:n}=t,r;if(e<=22)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_6mirror9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(e<=33&&!n)r=/^_ZN3art11interpreter6DoCallILb[0-1]ELb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE$/;else if(n)r=/^_ZN3art11interpreter6DoCallILb[0-1]EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtbPNS_6JValueE$/;else throw new Error("Unable to find method invocation in ART; please file a bug");let o=t.module,i=[...o.enumerateExports(),...o.enumerateSymbols()].filter(s=>r.test(s.name));if(i.length===0)throw new Error("Unable to find method invocation in ART; please file a bug");for(let s of i)Interceptor.attach(s.address,oe.hooks.Interpreter.doCall)}function Xc(){let t=J(),n=t.module.findSymbolByName("_ZN3art2gc4Heap22CollectGarbageInternalENS0_9collector6GcTypeENS0_7GcCauseEbj");if(n===null)return;let{artNterpEntryPoint:r,artQuickToInterpreterBridge:o}=t,i=_e(t.vm).offset.quickCode;Interceptor.attach(n,{onLeave(){oe.replacedMethods.synchronize(i,r,o)}})}function el(){let t=[["_ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE","e90340f8 : ff0ff0ff"],["_ZN3art11ClassLinker26VisiblyInitializedCallback29AdjustThreadVisibilityCounterEPNS_6ThreadEl","7f0f00f9 : 1ffcffff"]],e=J(),n=e.module;for(let[r,o]of t){let i=n.findSymbolByName(r);if(i===null)continue;let s=Memory.scanSync(i,8192,o);if(s.length===0)return;let{artNterpEntryPoint:c,artQuickToInterpreterBridge:a}=e,l=_e(e.vm).offset.quickCode;Interceptor.attach(s[0].address,function(){oe.replacedMethods.synchronize(l,c,a)});return}}function tl(t){if(Wr)return;if(Wr=!0,!rl()){let{getOatQuickMethodHeaderImpl:i}=oe;if(i===null)return;try{Interceptor.replace(i,oe.hooks.ArtMethod.getOatQuickMethodHeader)}catch{}}let e=ee(),n=null,r=J();e>28?n=r.find("_ZN3art2gc9collector17ConcurrentCopying12CopyingPhaseEv"):e>22&&(n=r.find("_ZN3art2gc9collector17ConcurrentCopying12MarkingPhaseEv")),n!==null&&Interceptor.attach(n,oe.hooks.Gc.copyingPhase);let o=null;o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_"),o===null&&(o=r.find("_ZN3art6Thread15RunFlipFunctionEPS0_b")),o!==null&&Interceptor.attach(o,oe.hooks.Gc.runFlip)}var nl={arm:{signatures:[{pattern:["b0 68","01 30","0c d0","1b 98",":","c0 ff","c0 ff","00 ff","00 2f"],validateMatch:An},{pattern:["d8 f8 08 00","01 30","0c d0","1b 98",":","f0 ff ff 0f","ff ff","00 ff","00 2f"],validateMatch:An},{pattern:["b0 68","01 30","40 f0 c3 80","00 25",":","c0 ff","c0 ff","c0 fb 00 d0","ff f8"],validateMatch:An}],instrument:il},arm64:{signatures:[{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","88 39 00 f0",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 00 00 9f"],offset:1,validateMatch:Ln},{pattern:["0a 40 b9","1f 05 00 31","40 01 00 54","00 0e 40 f9",":","fc ff ff","1f fc ff ff","1f 00 00 ff","00 fc ff ff"],offset:1,validateMatch:Ln},{pattern:["0a 40 b9","1f 05 00 31","01 34 00 54","e0 03 1f aa",":","fc ff ff","1f fc ff ff","1f 00 00 ff","e0 ff ff ff"],offset:1,validateMatch:Ln}],instrument:sl}};function An({address:t,size:e}){let n=Instruction.parse(t.or(1)),[r,o]=n.operands,i=o.value.base,s=r.value,c=Instruction.parse(n.next.add(2)),a=ptr(c.operands[0].value),l=c.address.add(c.size),d,p;return c.mnemonic==="beq"?(d=l,p=a):(d=a,p=l),xe(d.or(1),f,{limit:3});function f(u){let{mnemonic:_}=u;if(!(_==="ldr"||_==="ldr.w"))return null;let{base:h,disp:g}=u.operands[1].value;return h===i&&g===20?{methodReg:i,scratchReg:s,target:{whenTrue:a,whenRegularMethod:d,whenRuntimeMethod:p}}:null}}function Ln({address:t,size:e}){let[n,r]=Instruction.parse(t).operands,o=r.value.base,i="x"+n.value.substring(1),s=Instruction.parse(t.add(8)),c=ptr(s.operands[0].value),a=t.add(12),l,d;return s.mnemonic==="b.eq"?(l=a,d=c):(l=c,d=a),xe(l,p,{limit:3});function p(f){if(f.mnemonic!=="ldr")return null;let{base:u,disp:_}=f.operands[1].value;return u===o&&_===24?{methodReg:o,scratchReg:i,target:{whenTrue:c,whenRegularMethod:l,whenRuntimeMethod:d}}:null}}function rl(){if(ee()<31)return!1;let t=nl[Process.arch];if(t===void 0)return!1;let e=t.signatures.map(({pattern:r,offset:o=0,validateMatch:i=ol})=>({pattern:new MatchPattern(r.join("")),offset:o,validateMatch:i})),n=[];for(let{base:r,size:o}of J().module.enumerateRanges("--x"))for(let{pattern:i,offset:s,validateMatch:c}of e){let a=Memory.scanSync(r,o,i).map(({address:l,size:d})=>({address:l.sub(s),size:d+s})).filter(l=>{let d=c(l);return d===null?!1:(l.validationResult=d,!0)});n.push(...a)}return n.length===0?!1:(n.forEach(t.instrument),!0)}function ol(){return{}}var kt=class{constructor(e,n,r){this.address=e,this.size=n,this.originalCode=e.readByteArray(n),this.trampoline=r}revert(){Memory.patchCode(this.address,this.size,e=>{e.writeByteArray(this.originalCode)})}};function il({address:t,size:e,validationResult:n}){let{methodReg:r,target:o}=n,i=Memory.alloc(Process.pageSize),s=e;Memory.patchCode(i,256,c=>{let a=new ThumbWriter(c,{pc:i}),l=new ThumbRelocator(t,a);for(let _=0;_!==2;_++)l.readOne();l.writeAll(),l.readOne(),l.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=[45,237,16,10];a.putBytes(d);let p=["r0","r1","r2","r3"];a.putPushRegs(p),a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegImm("r0",0),a.putPopRegs(p);let f=[189,236,16,10];a.putBytes(f),a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),l.readOne();let u=l.input.address.equals(o.whenRegularMethod);for(a.putLabel(u?"regular_method":"runtime_or_replacement_method"),l.writeOne();s<10;){let _=l.readOne();if(_===0){s=10;break}s=_}l.writeAll(),a.putBranchAddress(t.add(s+1)),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(o.whenTrue),a.flush()}),Vn.push(new kt(t,s,i)),Memory.patchCode(t,s,c=>{let a=new ThumbWriter(c,{pc:t});a.putLdrRegAddress("pc",i.or(1)),a.flush()})}function sl({address:t,size:e,validationResult:n}){let{methodReg:r,scratchReg:o,target:i}=n,s=Memory.alloc(Process.pageSize);Memory.patchCode(s,256,c=>{let a=new Arm64Writer(c,{pc:s}),l=new Arm64Relocator(t,a);for(let _=0;_!==2;_++)l.readOne();l.writeAll(),l.readOne(),l.skipOne(),a.putBCondLabel("eq","runtime_or_replacement_method");let d=["d0","d1","d2","d3","d4","d5","d6","d7","x0","x1","x2","x3","x4","x5","x6","x7","x8","x9","x10","x11","x12","x13","x14","x15","x16","x17"],p=d.length;for(let _=0;_!==p;_+=2)a.putPushRegReg(d[_],d[_+1]);a.putCallAddressWithArguments(oe.replacedMethods.isReplacement,[r]),a.putCmpRegReg("x0","xzr");for(let _=p-2;_>=0;_-=2)a.putPopRegReg(d[_],d[_+1]);a.putBCondLabel("ne","runtime_or_replacement_method"),a.putBLabel("regular_method"),l.readOne();let f=l.input,u=f.address.equals(i.whenRegularMethod);a.putLabel(u?"regular_method":"runtime_or_replacement_method"),l.writeOne(),a.putBranchAddress(f.next),a.putLabel(u?"runtime_or_replacement_method":"regular_method"),a.putBranchAddress(i.whenTrue),a.flush()}),Vn.push(new kt(t,e,s)),Memory.patchCode(t,e,c=>{let a=new Arm64Writer(c,{pc:t});a.putLdrRegAddress(o,s),a.putBrReg(o),a.flush()})}function al(t){return new po(t)}function cl(t){return oe.replacedMethods.translate(t)}function qn(t,e={}){let{limit:n=16}=e,r=t.getEnv();return st===null&&(st=ll(t,r)),st.backtrace(r,n)}function ll(t,e){let n=J(),r=Memory.alloc(Process.pointerSize),o=new CModule(` +#include +#include +#include +#include +#include + +typedef struct _ArtBacktrace ArtBacktrace; +typedef struct _ArtStackFrame ArtStackFrame; + +typedef struct _ArtStackVisitor ArtStackVisitor; +typedef struct _ArtStackVisitorVTable ArtStackVisitorVTable; + +typedef struct _ArtClass ArtClass; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtThread ArtThread; +typedef struct _ArtContext ArtContext; + +typedef struct _JNIEnv JNIEnv; + +typedef struct _StdString StdString; +typedef struct _StdTinyString StdTinyString; +typedef struct _StdLargeString StdLargeString; + +typedef enum { + STACK_WALK_INCLUDE_INLINED_FRAMES, + STACK_WALK_SKIP_INLINED_FRAMES, +} StackWalkKind; + +struct _StdTinyString +{ + guint8 unused; + gchar data[(3 * sizeof (gpointer)) - 1]; +}; + +struct _StdLargeString +{ + gsize capacity; + gsize size; + gchar * data; +}; + +struct _StdString +{ + union + { + guint8 flags; + StdTinyString tiny; + StdLargeString large; + }; +}; + +struct _ArtBacktrace +{ + GChecksum * id; + GArray * frames; + gchar * frames_json; +}; + +struct _ArtStackFrame +{ + ArtMethod * method; + gsize dexpc; + StdString description; +}; + +struct _ArtStackVisitorVTable +{ + void (* unused1) (void); + void (* unused2) (void); + bool (* visit) (ArtStackVisitor * visitor); +}; + +struct _ArtStackVisitor +{ + ArtStackVisitorVTable * vtable; + + guint8 padding[512]; + + ArtStackVisitorVTable vtable_storage; + + ArtBacktrace * backtrace; +}; + +struct _ArtMethod +{ + guint32 declaring_class; + guint32 access_flags; +}; + +extern GumTlsKey current_backtrace; + +extern void (* perform_art_thread_state_transition) (JNIEnv * env); + +extern ArtContext * art_make_context (ArtThread * thread); + +extern void art_stack_visitor_init (ArtStackVisitor * visitor, ArtThread * thread, void * context, StackWalkKind walk_kind, + size_t num_frames, bool check_suspended); +extern void art_stack_visitor_walk_stack (ArtStackVisitor * visitor, bool include_transitions); +extern ArtMethod * art_stack_visitor_get_method (ArtStackVisitor * visitor); +extern void art_stack_visitor_describe_location (StdString * description, ArtStackVisitor * visitor); +extern ArtMethod * translate_method (ArtMethod * method); +extern void translate_location (ArtMethod * method, guint32 pc, const gchar ** source_file, gint32 * line_number); +extern void get_class_location (StdString * result, ArtClass * klass); +extern void cxx_delete (void * mem); +extern unsigned long strtoul (const char * str, char ** endptr, int base); + +static bool visit_frame (ArtStackVisitor * visitor); +static void art_stack_frame_destroy (ArtStackFrame * frame); + +static void append_jni_type_name (GString * s, const gchar * name, gsize length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_get_data (StdString * str); + +void +init (void) +{ + current_backtrace = gum_tls_key_new (); +} + +void +finalize (void) +{ + gum_tls_key_free (current_backtrace); +} + +ArtBacktrace * +_create (JNIEnv * env, + guint limit) +{ + ArtBacktrace * bt; + + bt = g_new (ArtBacktrace, 1); + bt->id = g_checksum_new (G_CHECKSUM_SHA1); + bt->frames = (limit != 0) + ? g_array_sized_new (FALSE, FALSE, sizeof (ArtStackFrame), limit) + : g_array_new (FALSE, FALSE, sizeof (ArtStackFrame)); + g_array_set_clear_func (bt->frames, (GDestroyNotify) art_stack_frame_destroy); + bt->frames_json = NULL; + + gum_tls_key_set_value (current_backtrace, bt); + + perform_art_thread_state_transition (env); + + gum_tls_key_set_value (current_backtrace, NULL); + + return bt; +} + +void +_on_thread_state_transition_complete (ArtThread * thread) +{ + ArtContext * context; + ArtStackVisitor visitor = { + .vtable_storage = { + .visit = visit_frame, + }, + }; + + context = art_make_context (thread); + + art_stack_visitor_init (&visitor, thread, context, STACK_WALK_SKIP_INLINED_FRAMES, 0, true); + visitor.vtable = &visitor.vtable_storage; + visitor.backtrace = gum_tls_key_get_value (current_backtrace); + + art_stack_visitor_walk_stack (&visitor, false); + + cxx_delete (context); +} + +static bool +visit_frame (ArtStackVisitor * visitor) +{ + ArtBacktrace * bt = visitor->backtrace; + ArtStackFrame frame; + const gchar * description, * dexpc_part; + + frame.method = art_stack_visitor_get_method (visitor); + + art_stack_visitor_describe_location (&frame.description, visitor); + + description = std_string_get_data (&frame.description); + if (strstr (description, " '<") != NULL) + goto skip; + + dexpc_part = strstr (description, " at dex PC 0x"); + if (dexpc_part == NULL) + goto skip; + frame.dexpc = strtoul (dexpc_part + 13, NULL, 16); + + g_array_append_val (bt->frames, frame); + + g_checksum_update (bt->id, (guchar *) &frame.method, sizeof (frame.method)); + g_checksum_update (bt->id, (guchar *) &frame.dexpc, sizeof (frame.dexpc)); + + return true; + +skip: + std_string_destroy (&frame.description); + return true; +} + +static void +art_stack_frame_destroy (ArtStackFrame * frame) +{ + std_string_destroy (&frame->description); +} + +void +_destroy (ArtBacktrace * backtrace) +{ + g_free (backtrace->frames_json); + g_array_free (backtrace->frames, TRUE); + g_checksum_free (backtrace->id); + g_free (backtrace); +} + +const gchar * +_get_id (ArtBacktrace * backtrace) +{ + return g_checksum_get_string (backtrace->id); +} + +const gchar * +_get_frames (ArtBacktrace * backtrace) +{ + GArray * frames = backtrace->frames; + JsonBuilder * b; + guint i; + JsonNode * root; + + if (backtrace->frames_json != NULL) + return backtrace->frames_json; + + b = json_builder_new_immutable (); + + json_builder_begin_array (b); + + for (i = 0; i != frames->len; i++) + { + ArtStackFrame * frame = &g_array_index (frames, ArtStackFrame, i); + gchar * description, * ret_type, * paren_open, * paren_close, * arg_types, * token, * method_name, * class_name; + GString * signature; + gchar * cursor; + ArtMethod * translated_method; + StdString location; + gsize dexpc; + const gchar * source_file; + gint32 line_number; + + description = std_string_get_data (&frame->description); + + ret_type = strchr (description, '\\'') + 1; + + paren_open = strchr (ret_type, '('); + paren_close = strchr (paren_open, ')'); + *paren_open = '\\0'; + *paren_close = '\\0'; + + arg_types = paren_open + 1; + + token = strrchr (ret_type, '.'); + *token = '\\0'; + + method_name = token + 1; + + token = strrchr (ret_type, ' '); + *token = '\\0'; + + class_name = token + 1; + + signature = g_string_sized_new (128); + + append_jni_type_name (signature, class_name, method_name - class_name - 1); + g_string_append_c (signature, ','); + g_string_append (signature, method_name); + g_string_append (signature, ",("); + + if (arg_types != paren_close) + { + for (cursor = arg_types; cursor != NULL;) + { + gsize length; + gchar * next; + + token = strstr (cursor, ", "); + if (token != NULL) + { + length = token - cursor; + next = token + 2; + } + else + { + length = paren_close - cursor; + next = NULL; + } + + append_jni_type_name (signature, cursor, length); + + cursor = next; + } + } + + g_string_append_c (signature, ')'); + + append_jni_type_name (signature, ret_type, class_name - ret_type - 1); + + translated_method = translate_method (frame->method); + dexpc = (translated_method == frame->method) ? frame->dexpc : 0; + + get_class_location (&location, GSIZE_TO_POINTER (translated_method->declaring_class)); + + translate_location (translated_method, dexpc, &source_file, &line_number); + + json_builder_begin_object (b); + + json_builder_set_member_name (b, "signature"); + json_builder_add_string_value (b, signature->str); + + json_builder_set_member_name (b, "origin"); + json_builder_add_string_value (b, std_string_get_data (&location)); + + json_builder_set_member_name (b, "className"); + json_builder_add_string_value (b, class_name); + + json_builder_set_member_name (b, "methodName"); + json_builder_add_string_value (b, method_name); + + json_builder_set_member_name (b, "methodFlags"); + json_builder_add_int_value (b, translated_method->access_flags); + + json_builder_set_member_name (b, "fileName"); + json_builder_add_string_value (b, source_file); + + json_builder_set_member_name (b, "lineNumber"); + json_builder_add_int_value (b, line_number); + + json_builder_end_object (b); + + std_string_destroy (&location); + g_string_free (signature, TRUE); + } + + json_builder_end_array (b); + + root = json_builder_get_root (b); + backtrace->frames_json = json_to_string (root, FALSE); + json_node_unref (root); + + return backtrace->frames_json; +} + +static void +append_jni_type_name (GString * s, + const gchar * name, + gsize length) +{ + gchar shorty = '\\0'; + gsize i; + + switch (name[0]) + { + case 'b': + if (strncmp (name, "boolean", length) == 0) + shorty = 'Z'; + else if (strncmp (name, "byte", length) == 0) + shorty = 'B'; + break; + case 'c': + if (strncmp (name, "char", length) == 0) + shorty = 'C'; + break; + case 'd': + if (strncmp (name, "double", length) == 0) + shorty = 'D'; + break; + case 'f': + if (strncmp (name, "float", length) == 0) + shorty = 'F'; + break; + case 'i': + if (strncmp (name, "int", length) == 0) + shorty = 'I'; + break; + case 'l': + if (strncmp (name, "long", length) == 0) + shorty = 'J'; + break; + case 's': + if (strncmp (name, "short", length) == 0) + shorty = 'S'; + break; + case 'v': + if (strncmp (name, "void", length) == 0) + shorty = 'V'; + break; + } + + if (shorty != '\\0') + { + g_string_append_c (s, shorty); + + return; + } + + if (length > 2 && name[length - 2] == '[' && name[length - 1] == ']') + { + g_string_append_c (s, '['); + append_jni_type_name (s, name, length - 2); + + return; + } + + g_string_append_c (s, 'L'); + + for (i = 0; i != length; i++) + { + gchar ch = name[i]; + if (ch != '.') + g_string_append_c (s, ch); + else + g_string_append_c (s, '/'); + } + + g_string_append_c (s, ';'); +} + +static void +std_string_destroy (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + if (is_large) + cxx_delete (str->large.data); +} + +static gchar * +std_string_get_data (StdString * str) +{ + bool is_large = (str->flags & 1) != 0; + return is_large ? str->large.data : str->tiny.data; +} +`,{current_backtrace:Memory.alloc(Process.pointerSize),perform_art_thread_state_transition:r,art_make_context:n["art::Thread::GetLongJumpContext"]??n["art::Context::Create"],art_stack_visitor_init:n["art::StackVisitor::StackVisitor"],art_stack_visitor_walk_stack:n["art::StackVisitor::WalkStack"],art_stack_visitor_get_method:n["art::StackVisitor::GetMethod"],art_stack_visitor_describe_location:n["art::StackVisitor::DescribeLocation"],translate_method:oe.replacedMethods.translate,translate_location:n["art::Monitor::TranslateLocation"],get_class_location:n["art::mirror::Class::GetLocation"],cxx_delete:n.$delete,strtoul:Process.getModuleByName("libc.so").getExportByName("strtoul")}),i=new NativeFunction(o._create,"pointer",["pointer","uint"],W),s=new NativeFunction(o._destroy,"void",["pointer"],W),c={exceptions:"propagate",scheduling:"exclusive"},a=new NativeFunction(o._get_id,"pointer",["pointer"],c),l=new NativeFunction(o._get_frames,"pointer",["pointer"],c),d=go(t,e,o._on_thread_state_transition_complete);o._performData=d,r.writePointer(d),o.backtrace=(f,u)=>{let _=i(f,u),h=new On(_);return Script.bindWeak(h,p.bind(null,_)),h};function p(f){s(f)}return o.getId=f=>a(f).readUtf8String(),o.getFrames=f=>JSON.parse(l(f).readUtf8String()),o}var On=class{constructor(e){this.handle=e}get id(){return st.getId(this.handle)}get frames(){return st.getFrames(this.handle)}};function Wn(){xt.forEach(t=>{t.vtablePtr.writePointer(t.vtable),t.vtableCountPtr.writeS32(t.vtableCount)}),xt.clear();for(let t of fo.splice(0))t.deactivate();for(let t of Vn.splice(0))t.revert()}function Kn(t){return _o(t,"art::jni::JniIdManager::DecodeMethodId")}function no(t){return _o(t,"art::jni::JniIdManager::DecodeFieldId")}function _o(t,e){let n=J(),r=lo(n).offset,o=r.jniIdManager,i=r.jniIdsIndirection;if(o!==null&&i!==null){let s=n.artRuntime;if(s.add(i).readInt()!==Oa){let a=s.add(o).readPointer();return n[e](a,t)}}return t}var dl={ia32:ul,x64:pl,arm:fl,arm64:hl};function ul(t,e,n,r,o){let i=qe(o).offset,s=_e(o).offset,c;return Memory.patchCode(t,128,a=>{let l=new X86Writer(a,{pc:t}),d=new X86Relocator(e,l),p=[15,174,4,36],f=[15,174,12,36];l.putPushax(),l.putMovRegReg("ebp","esp"),l.putAndRegU32("esp",4294967280),l.putSubRegImm("esp",512),l.putBytes(p),l.putMovRegFsU32Ptr("ebx",i.self),l.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["eax","ebx"]),l.putTestRegReg("eax","eax"),l.putJccShortLabel("je","restore_registers","no-hint"),l.putMovRegOffsetPtrReg("ebp",7*4,"eax"),l.putLabel("restore_registers"),l.putBytes(f),l.putMovRegReg("esp","ebp"),l.putPopax(),l.putJccShortLabel("jne","invoke_replacement","no-hint");do c=d.readOne();while(c{let l=new X86Writer(a,{pc:t}),d=new X86Relocator(e,l),p=[15,174,4,36],f=[15,174,12,36];l.putPushax(),l.putMovRegReg("rbp","rsp"),l.putAndRegU32("rsp",4294967280),l.putSubRegImm("rsp",512),l.putBytes(p),l.putMovRegGsU32Ptr("rbx",i.self),l.putCallAddressWithAlignedArguments(oe.replacedMethods.findReplacementFromQuickCode,["rdi","rbx"]),l.putTestRegReg("rax","rax"),l.putJccShortLabel("je","restore_registers","no-hint"),l.putMovRegOffsetPtrReg("rbp",8*8,"rax"),l.putLabel("restore_registers"),l.putBytes(f),l.putMovRegReg("rsp","rbp"),l.putPopax(),l.putJccShortLabel("jne","invoke_replacement","no-hint");do c=d.readOne();while(c{let l=new ThumbWriter(a,{pc:t}),d=new ThumbRelocator(s,l),p=[45,237,16,10],f=[189,236,16,10];l.putPushRegs(["r1","r2","r3","r5","r6","r7","r8","r10","r11","lr"]),l.putBytes(p),l.putSubRegRegImm("sp","sp",8),l.putStrRegRegOffset("r0","sp",0),l.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["r0","r9"]),l.putCmpRegImm("r0",0),l.putBCondLabel("eq","restore_registers"),l.putStrRegRegOffset("r0","sp",0),l.putLabel("restore_registers"),l.putLdrRegRegOffset("r0","sp",0),l.putAddRegRegImm("sp","sp",8),l.putBytes(f),l.putPopRegs(["lr","r11","r10","r8","r7","r6","r5","r3","r2","r1"]),l.putBCondLabel("ne","invoke_replacement");do c=d.readOne();while(c{let a=new Arm64Writer(c,{pc:t}),l=new Arm64Relocator(e,a);a.putPushRegReg("d0","d1"),a.putPushRegReg("d2","d3"),a.putPushRegReg("d4","d5"),a.putPushRegReg("d6","d7"),a.putPushRegReg("x1","x2"),a.putPushRegReg("x3","x4"),a.putPushRegReg("x5","x6"),a.putPushRegReg("x7","x20"),a.putPushRegReg("x21","x22"),a.putPushRegReg("x23","x24"),a.putPushRegReg("x25","x26"),a.putPushRegReg("x27","x28"),a.putPushRegReg("x29","lr"),a.putSubRegRegImm("sp","sp",16),a.putStrRegRegOffset("x0","sp",0),a.putCallAddressWithArguments(oe.replacedMethods.findReplacementFromQuickCode,["x0","x19"]),a.putCmpRegReg("x0","xzr"),a.putBCondLabel("eq","restore_registers"),a.putStrRegRegOffset("x0","sp",0),a.putLabel("restore_registers"),a.putLdrRegRegOffset("x0","sp",0),a.putAddRegRegImm("sp","sp",16),a.putPopRegReg("x29","lr"),a.putPopRegReg("x27","x28"),a.putPopRegReg("x25","x26"),a.putPopRegReg("x23","x24"),a.putPopRegReg("x21","x22"),a.putPopRegReg("x7","x20"),a.putPopRegReg("x5","x6"),a.putPopRegReg("x3","x4"),a.putPopRegReg("x1","x2"),a.putPopRegReg("d6","d7"),a.putPopRegReg("d4","d5"),a.putPopRegReg("d2","d3"),a.putPopRegReg("d0","d1"),a.putBCondLabel("ne","invoke_replacement");do s=l.readOne();while(s{let o=new X86Writer(r,{pc:t});o.putJmpAddress(e),o.flush()})}function ml(t,e,n){let r=t.and(Bn);Memory.patchCode(r,16,o=>{let i=new ThumbWriter(o,{pc:r});i.putLdrRegAddress("pc",e.or(1)),i.flush()})}function gl(t,e,n){Memory.patchCode(t,16,r=>{let o=new Arm64Writer(r,{pc:t});n===16?o.putLdrRegAddress("x16",e):o.putAdrpRegAddress("x16",e),o.putBrReg("x16"),o.flush()})}var bl={ia32:5,x64:16,arm:8,arm64:16},Mt=class{constructor(e){this.quickCode=e,this.quickCodeAddress=Process.arch==="arm"?e.and(Bn):e,this.redirectSize=0,this.trampoline=null,this.overwrittenPrologue=null,this.overwrittenPrologueLength=0}_canRelocateCode(e,n){let r=Rn[Process.arch],o=Zc[Process.arch],{quickCodeAddress:i}=this,s=new r(i),c=new o(i,s),a;if(Process.arch==="arm64"){let l=new Set(["x16","x17"]);do{let d=c.readOne(),p=new Set(l),{read:f,written:u}=c.input.regsAccessed;for(let _ of[f,u])for(let h of _){let g;h.startsWith("w")?g="x"+h.substring(1):g=h,p.delete(g)}if(p.size===0)break;a=d,l=p}while(a=e}_allocateTrampoline(){Ct===null&&(Ct=nn(v===4?128:256));let e=bl[Process.arch],n,r,o=1,i={};if(v===4||this._canRelocateCode(e,i))n=e,r={};else{let s;Process.arch==="x64"?(n=5,s=Pa):Process.arch==="arm64"&&(n=8,s=Fa,o=4096),r={near:this.quickCodeAddress,maxDistance:s}}return this.redirectSize=n,this.trampoline=Ct.allocateSlice(r,o),i}_destroyTrampoline(){Ct.freeSlice(this.trampoline)}activate(e){let n=this._allocateTrampoline(),{trampoline:r,quickCode:o,redirectSize:i}=this,s=dl[Process.arch],c=s(r,o,i,n,e);this.overwrittenPrologueLength=c,this.overwrittenPrologue=Memory.dup(this.quickCodeAddress,c);let a=_l[Process.arch];a(o,r,i)}deactivate(){let{quickCodeAddress:e,overwrittenPrologueLength:n}=this,r=Rn[Process.arch];Memory.patchCode(e,n,o=>{let i=new r(o,{pc:e}),{overwrittenPrologue:s}=this;i.putBytes(s.readByteArray(n)),i.flush()}),this._destroyTrampoline()}};function yl(t){let e=J(),{module:n,artClassLinker:r}=e;return t.equals(r.quickGenericJniTrampoline)||t.equals(r.quickToInterpreterBridgeTrampoline)||t.equals(r.quickResolutionTrampoline)||t.equals(r.quickImtConflictTrampoline)||t.compare(n.base)>=0&&t.compare(n.base.add(n.size))<0}var Pn=class{constructor(e){let n=Kn(e);this.methodId=n,this.originalMethod=null,this.hookedMethodId=n,this.replacementMethodId=null,this.interceptor=null}replace(e,n,r,o,i){let{kAccCompileDontBother:s,artNterpEntryPoint:c}=i;this.originalMethod=oo(this.methodId,o);let a=this.originalMethod.accessFlags;if((a&Ra)!==0&&El()){let u=this.originalMethod.jniCode;this.hookedMethodId=u.add(2*v).readPointer(),this.originalMethod=oo(this.hookedMethodId,o)}let{hookedMethodId:l}=this,d=Sl(l,o);this.replacementMethodId=d,Tt(d,{jniCode:e,accessFlags:(a&~(xa|La|$r)|Lt|s)>>>0,quickCode:i.artClassLinker.quickGenericJniTrampoline,interpreterCode:i.artInterpreterToCompiledCodeBridge},o);let p=ao|ka|$r;(a&Lt)===0&&(p|=Na),Tt(l,{accessFlags:(a&~p|s)>>>0},o);let f=this.originalMethod.quickCode;if(c!==null&&f.equals(c)&&Tt(l,{quickCode:i.artQuickToInterpreterBridge},o),!yl(f)){let u=new Mt(f);u.activate(o),this.interceptor=u}oe.replacedMethods.set(l,d),qc(l,o)}revert(e){let{hookedMethodId:n,interceptor:r}=this;Tt(n,this.originalMethod,e),oe.replacedMethods.delete(n),r!==null&&(r.deactivate(),this.interceptor=null)}resolveTarget(e,n,r,o){return this.hookedMethodId}};function El(){return ee()<28}function oo(t,e){let r=_e(e).offset;return["jniCode","accessFlags","quickCode","interpreterCode"].reduce((o,i)=>{let s=r[i];if(s===void 0)return o;let c=t.add(s),a=i==="accessFlags"?va:Sa;return o[i]=a.call(c),o},{})}function Tt(t,e,n){let o=_e(n).offset;Object.keys(e).forEach(i=>{let s=o[i];if(s===void 0)return;let c=t.add(s);(i==="accessFlags"?wa:Ia).call(c,e[i])})}var Fn=class{constructor(e){this.methodId=e,this.originalMethod=null}replace(e,n,r,o,i){let{methodId:s}=this;this.originalMethod=Memory.dup(s,En);let c=r.reduce((f,u)=>f+u.size,0);n&&c++;let a=(s.add(Hr).readU32()|Lt)>>>0,l=c,d=0,p=c;s.add(Hr).writeU32(a),s.add(Ja).writeU16(l),s.add(Ga).writeU16(d),s.add($a).writeU16(p),s.add(Za).writeU32(vl(s)),i.dvmUseJNIBridge(s,e)}revert(e){Memory.copy(this.methodId,this.originalMethod,En)}resolveTarget(e,n,r,o){let i=r.handle.add(co).readPointer(),s;if(n)s=o.dvmDecodeIndirectRef(i,e.$h);else{let f=e.$borrowClassHandle(r);s=o.dvmDecodeIndirectRef(i,f.value),f.unref(r)}let c;n?c=s.add(za).readPointer():c=s;let a=c.toString(16),l=xt.get(a);if(l===void 0){let f=c.add(Ba),u=c.add(Ua),_=f.readPointer(),h=u.readS32(),g=h*v,b=Memory.alloc(2*g);Memory.copy(b,_,g),f.writePointer(b),l={classObject:c,vtablePtr:f,vtableCountPtr:u,vtable:_,vtableCount:h,shadowVtable:b,shadowVtableCount:h,targetMethods:new Map},xt.set(a,l)}let d=this.methodId.toString(16),p=l.targetMethods.get(d);if(p===void 0){p=Memory.dup(this.originalMethod,En);let f=l.shadowVtableCount++;l.shadowVtable.add(f*v).writePointer(p),p.add(Va).writeU16(f),l.vtableCountPtr.writeS32(l.shadowVtableCount),l.targetMethods.set(d,p)}return p}};function vl(t){if(Process.arch!=="ia32")return Zr;let e=t.add(Ha).readPointer().readCString();if(e===null||e.length===0||e.length>65535)return Zr;let n;switch(e[0]){case"V":n=qa;break;case"F":n=Wa;break;case"D":n=Ka;break;case"J":n=Qa;break;case"Z":case"B":n=tc;break;case"C":n=ec;break;case"S":n=Xa;break;default:n=Ya;break}let r=0;for(let o=e.length-1;o>0;o--){let i=e[o];r+=i==="D"||i==="J"?2:1}return n<= 8.0");ye(t,e,r=>{n["art::Runtime::DeoptimizeBootImage"](n.artRuntime)})}function mo(t,e,n,r){let o=J();if(ee()<24)throw new Error("This API is only available on Android >= 7.0");ye(t,e,i=>{if(ee()<30){if(!o.isJdwpStarted()){let c=wl(o);uc.push(c)}o.isDebuggerActive()||o["art::Dbg::GoActive"]();let s=Memory.alloc(8+v);switch(s.writeU32(n),n){case xn:break;case Nn:s.add(8).writePointer(r);break;default:throw new Error("Unsupported deoptimization kind")}o["art::Dbg::RequestDeoptimization"](s),o["art::Dbg::ManageDeoptimization"]()}else{let s=o.artInstrumentation;if(s===null)throw new Error("Unable to find Instrumentation class in ART; please file a bug");let c=o["art::Instrumentation::EnableDeoptimization"];switch(c!==void 0&&(s.add(sc().offset.deoptimizationEnabled).readU8()||c(s)),n){case xn:o["art::Instrumentation::DeoptimizeEverything"](s,Memory.allocUtf8String("frida"));break;case Nn:o["art::Instrumentation::Deoptimize"](s,r);break;default:throw new Error("Unsupported deoptimization kind")}}})}var Dn=class{constructor(){let e=Process.getModuleByName("libart.so"),n=e.getExportByName("_ZN3art4JDWP12JdwpAdbState6AcceptEv"),r=e.getExportByName("_ZN3art4JDWP12JdwpAdbState15ReceiveClientFdEv"),o=io(),i=io();this._controlFd=o[0],this._clientFd=i[0];let s=null;s=Interceptor.attach(n,function(c){let a=c[0];Memory.scanSync(a.add(8252),256,"00 ff ff ff ff 00")[0].address.add(1).writeS32(o[1]),s.detach()}),Interceptor.replace(r,new NativeCallback(function(c){return Interceptor.revert(r),i[1]},"int",["pointer"])),Interceptor.flush(),this._handshakeRequest=this._performHandshake()}async _performHandshake(){let e=new UnixInputStream(this._clientFd,{autoClose:!1}),n=new UnixOutputStream(this._clientFd,{autoClose:!1}),r=[74,68,87,80,45,72,97,110,100,115,104,97,107,101];try{await n.writeAll(r),await e.readAll(r.length)}catch{}}};function wl(t){let e=new Dn;t["art::Dbg::SetJdwpAllowed"](1);let n=Il();t["art::Dbg::ConfigureJdwp"](n);let r=t["art::InternalDebuggerControlCallback::StartDebugger"];return r!==void 0?r(NULL):t["art::Dbg::StartJdwp"](),e}function Il(){let t=ee()<28?2:3,e=0,n=t,r=!0,o=!1,i=e,s=8+ct+2,c=Memory.alloc(s);return c.writeU32(n).add(4).writeU8(r?1:0).add(1).writeU8(o?1:0).add(1).add(ct).writeU16(i),c}function io(){In===null&&(In=new NativeFunction(Process.getModuleByName("libc.so").getExportByName("socketpair"),"int",["int","int","int","pointer"]));let t=Memory.alloc(8);if(In(oc,ic,0,t)===-1)throw new Error("Unable to create socketpair for JDWP");return[t.readS32(),t.add(4).readS32()]}function Cl(t){let e=_c().offset,n=t.vm.add(e.globalsLock),r=t.vm.add(e.globals),o=t["art::IndirectReferenceTable::Add"],i=t["art::ReaderWriterMutex::ExclusiveLock"],s=t["art::ReaderWriterMutex::ExclusiveUnlock"],c=0;return function(a,l,d){i(n,l);try{return o(r,c,d)}finally{s(n,l)}}}function Tl(t){let e=t["art::Thread::DecodeJObject"];if(e===void 0)throw new Error("art::Thread::DecodeJObject is not available; please file a bug");return function(n,r,o){return e(r,o)}}var Al={ia32:so,x64:so,arm:Ll,arm64:xl};function go(t,e,n){let r=J(),o=e.handle.readPointer(),i,s=r.find("_ZN3art3JNIILb1EE14ExceptionClearEP7_JNIEnv");s!==null?i=s:i=o.add(Ot).readPointer();let c,a=r.find("_ZN3art3JNIILb1EE10FatalErrorEP7_JNIEnvPKc");a!==null?c=a:c=o.add(Da).readPointer();let l=Al[Process.arch];if(l===void 0)throw new Error("Not yet implemented for "+Process.arch);let d=null,p=qe(t).offset,f=p.exception,u=new Set,_=p.isExceptionReportedToInstrumentation;_!==null&&u.add(_);let h=p.throwLocation;h!==null&&(u.add(h),u.add(h+v),u.add(h+2*v));let g=65536,b=Memory.alloc(g);return Memory.patchCode(b,g,E=>{d=l(E,b,i,c,f,u,n)}),d._code=b,d._callback=n,d}function so(t,e,n,r,o,i,s){let c={},a=new Set,l=[n];for(;l.length>0;){let h=l.shift();if(Object.values(c).some(({begin:M,end:R})=>h.compare(M)>=0&&h.compare(R)<0))continue;let b=h.toString(),E={begin:h},C=null,A=!1;do{if(h.equals(r)){A=!0;break}let M=Instruction.parse(h);C=M;let R=c[M.address.toString()];if(R!==void 0){delete c[R.begin.toString()],c[b]=R,R.begin=E.begin,E=null;break}let k=null;switch(M.mnemonic){case"jmp":k=ptr(M.operands[0].value),A=!0;break;case"je":case"jg":case"jle":case"jne":case"js":k=ptr(M.operands[0].value);break;case"ret":A=!0;break}k!==null&&(a.add(k.toString()),l.push(k),l.sort((N,S)=>N.compare(S))),h=M.next}while(!A);E!==null&&(E.end=C.address.add(C.size),c[b]=E)}let d=Object.keys(c).map(h=>c[h]);d.sort((h,g)=>h.begin.compare(g.begin));let p=c[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new X86Writer(t,{pc:e}),u=!1,_=null;return d.forEach(h=>{let g=h.end.sub(h.begin).toInt32(),b=new X86Relocator(h.begin,f),E;for(;(E=b.readOne())!==0;){let C=b.input,{mnemonic:A}=C,M=C.address.toString();a.has(M)&&f.putLabel(M);let R=!0;switch(A){case"jmp":f.putJmpNearLabel(fe(C.operands[0])),R=!1;break;case"je":case"jg":case"jle":case"jne":case"js":f.putJccNearLabel(A,fe(C.operands[0]),"no-hint"),R=!1;break;case"mov":{let[k,N]=C.operands;if(k.type==="mem"&&N.type==="imm"){let S=k.value,L=S.disp;if(L===o&&N.value.valueOf()===0){if(_=S.base,f.putPushfx(),f.putPushax(),f.putMovRegReg("xbp","xsp"),v===4)f.putAndRegU32("esp",4294967280);else{let j=_!=="rdi"?"rdi":"rsi";f.putMovRegU64(j,uint64("0xfffffffffffffff0")),f.putAndRegReg("rsp",j)}f.putCallAddressWithAlignedArguments(s,[_]),f.putMovRegReg("xsp","xbp"),f.putPopax(),f.putPopfx(),u=!0,R=!1}else i.has(L)&&S.base===_&&(R=!1)}break}case"call":{let k=C.operands[0];k.type==="mem"&&k.value.disp===Ot&&(v===4?(f.putPopReg("eax"),f.putMovRegRegOffsetPtr("eax","eax",4),f.putPushReg("eax")):f.putMovRegRegOffsetPtr("rdi","rdi",8),f.putCallAddressWithArguments(s,[]),u=!0,R=!1);break}}if(R?b.writeAll():b.skipOne(),E===g)break}b.dispose()}),f.dispose(),u||er(),new NativeFunction(e,"void",["pointer"],W)}function Ll(t,e,n,r,o,i,s){let c={},a=new Set,l=ptr(1).not(),d=[n];for(;d.length>0;){let b=d.shift();if(Object.values(c).some(({begin:L,end:j})=>b.compare(L)>=0&&b.compare(j)<0))continue;let C=b.and(l),A=C.toString(),M=b.and(1),R={begin:C},k=null,N=!1,S=0;do{if(b.equals(r)){N=!0;break}let L=Instruction.parse(b),{mnemonic:j}=L;k=L;let O=b.and(l).toString(),D=c[O];if(D!==void 0){delete c[D.begin.toString()],c[A]=D,D.begin=R.begin,R=null;break}let U=S===0,F=null;switch(j){case"b":F=ptr(L.operands[0].value),N=U;break;case"beq.w":case"beq":case"bne":case"bne.w":case"bgt":F=ptr(L.operands[0].value);break;case"cbz":case"cbnz":F=ptr(L.operands[1].value);break;case"pop.w":U&&(N=L.operands.filter(z=>z.value==="pc").length===1);break}switch(j){case"it":S=1;break;case"itt":S=2;break;case"ittt":S=3;break;case"itttt":S=4;break;default:S>0&&S--;break}F!==null&&(a.add(F.toString()),d.push(F.or(M)),d.sort((z,X)=>z.compare(X))),b=L.next}while(!N);R!==null&&(R.end=k.address.add(k.size),c[A]=R)}let p=Object.keys(c).map(b=>c[b]);p.sort((b,E)=>b.begin.compare(E.begin));let f=c[n.and(l).toString()];p.splice(p.indexOf(f),1),p.unshift(f);let u=new ThumbWriter(t,{pc:e}),_=!1,h=null,g=null;return p.forEach(b=>{let E=new ThumbRelocator(b.begin,u),C=b.begin,A=b.end,M=0;do{if(E.readOne()===0)throw new Error("Unexpected end of block");let k=E.input;C=k.address,M=k.size;let{mnemonic:N}=k,S=C.toString();a.has(S)&&u.putLabel(S);let L=!0;switch(N){case"b":u.putBLabel(fe(k.operands[0])),L=!1;break;case"beq.w":u.putBCondLabelWide("eq",fe(k.operands[0])),L=!1;break;case"bne.w":u.putBCondLabelWide("ne",fe(k.operands[0])),L=!1;break;case"beq":case"bne":case"bgt":u.putBCondLabelWide(N.substr(1),fe(k.operands[0])),L=!1;break;case"cbz":{let j=k.operands;u.putCbzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"cbnz":{let j=k.operands;u.putCbnzRegLabel(j[0].value,fe(j[1])),L=!1;break}case"str":case"str.w":{let j=k.operands[1].value,w=j.disp;if(w===o){h=j.base;let O=h!=="r4"?"r4":"r5",D=["r0","r1","r2","r3",O,"r9","r12","lr"];u.putPushRegs(D),u.putMrsRegReg(O,"apsr-nzcvq"),u.putCallAddressWithArguments(s,[h]),u.putMsrRegReg("apsr-nzcvq",O),u.putPopRegs(D),_=!0,L=!1}else i.has(w)&&j.base===h&&(L=!1);break}case"ldr":{let[j,w]=k.operands;if(w.type==="mem"){let O=w.value;O.base[0]==="r"&&O.disp===Ot&&(g=j.value)}break}case"blx":k.operands[0].value===g&&(u.putLdrRegRegOffset("r0","r0",4),u.putCallAddressWithArguments(s,["r0"]),_=!0,g=null,L=!1);break}L?E.writeAll():E.skipOne()}while(!C.add(M).equals(A));E.dispose()}),u.dispose(),_||er(),new NativeFunction(e.or(1),"void",["pointer"],W)}function xl(t,e,n,r,o,i,s){let c={},a=new Set,l=[n];for(;l.length>0;){let b=l.shift();if(Object.values(c).some(({begin:k,end:N})=>b.compare(k)>=0&&b.compare(N)<0))continue;let C=b.toString(),A={begin:b},M=null,R=!1;do{if(b.equals(r)){R=!0;break}let k;try{k=Instruction.parse(b)}catch(L){if(b.readU32()===0){R=!0;break}else throw L}M=k;let N=c[k.address.toString()];if(N!==void 0){delete c[N.begin.toString()],c[C]=N,N.begin=A.begin,A=null;break}let S=null;switch(k.mnemonic){case"b":S=ptr(k.operands[0].value),R=!0;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":S=ptr(k.operands[0].value);break;case"cbz":case"cbnz":S=ptr(k.operands[1].value);break;case"tbz":case"tbnz":S=ptr(k.operands[2].value);break;case"ret":R=!0;break}S!==null&&(a.add(S.toString()),l.push(S),l.sort((L,j)=>L.compare(j))),b=k.next}while(!R);A!==null&&(A.end=M.address.add(M.size),c[C]=A)}let d=Object.keys(c).map(b=>c[b]);d.sort((b,E)=>b.begin.compare(E.begin));let p=c[n.toString()];d.splice(d.indexOf(p),1),d.unshift(p);let f=new Arm64Writer(t,{pc:e});f.putBLabel("performTransition");let u=e.add(f.offset);f.putPushAllXRegisters(),f.putCallAddressWithArguments(s,["x0"]),f.putPopAllXRegisters(),f.putRet(),f.putLabel("performTransition");let _=!1,h=null,g=null;return d.forEach(b=>{let E=b.end.sub(b.begin).toInt32(),C=new Arm64Relocator(b.begin,f),A;for(;(A=C.readOne())!==0;){let M=C.input,{mnemonic:R}=M,k=M.address.toString();a.has(k)&&f.putLabel(k);let N=!0;switch(R){case"b":f.putBLabel(fe(M.operands[0])),N=!1;break;case"b.eq":case"b.ne":case"b.le":case"b.gt":f.putBCondLabel(R.substr(2),fe(M.operands[0])),N=!1;break;case"cbz":{let S=M.operands;f.putCbzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"cbnz":{let S=M.operands;f.putCbnzRegLabel(S[0].value,fe(S[1])),N=!1;break}case"tbz":{let S=M.operands;f.putTbzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"tbnz":{let S=M.operands;f.putTbnzRegImmLabel(S[0].value,S[1].value.valueOf(),fe(S[2])),N=!1;break}case"str":{let S=M.operands,L=S[0].value,j=S[1].value,w=j.disp;L==="xzr"&&w===o?(h=j.base,f.putPushRegReg("x0","lr"),f.putMovRegReg("x0",h),f.putBlImm(u),f.putPopRegReg("x0","lr"),_=!0,N=!1):i.has(w)&&j.base===h&&(N=!1);break}case"ldr":{let S=M.operands,L=S[1].value;L.base[0]==="x"&&L.disp===Ot&&(g=S[0].value);break}case"blr":M.operands[0].value===g&&(f.putLdrRegRegOffset("x0","x0",8),f.putCallAddressWithArguments(s,["x0"]),_=!0,g=null,N=!1);break}if(N?C.writeAll():C.skipOne(),A===E)break}C.dispose()}),f.dispose(),_||er(),new NativeFunction(e,"void",["pointer"],W)}function er(){throw new Error("Unable to parse ART internals; please file a bug")}function Nl(t){let e=t["art::ArtMethod::PrettyMethod"];e!==void 0&&(Interceptor.attach(e.impl,oe.hooks.ArtMethod.prettyMethod),Interceptor.flush())}function fe(t){return ptr(t.value).toString()}function kl(t,e){return new NativeFunction(t,"pointer",e,W)}function Ml(t,e){let n=new NativeFunction(t,"void",["pointer"].concat(e),W);return function(){let r=Memory.alloc(v);return n(r,...arguments),r.readPointer()}}function At(t,e){let{arch:n}=Process;switch(n){case"ia32":case"arm64":{let r;n==="ia32"?r=Ze(64,s=>{let c=1+e.length,a=c*4;s.putSubRegImm("esp",a);for(let l=0;l!==c;l++){let d=l*4;s.putMovRegRegOffsetPtr("eax","esp",a+4+d),s.putMovRegOffsetPtrReg("esp",d,"eax")}s.putCallAddress(t),s.putAddRegImm("esp",a-4),s.putRet()}):r=Ze(32,s=>{s.putMovRegReg("x8","x0"),e.forEach((c,a)=>{s.putMovRegReg("x"+a,"x"+(a+1))}),s.putLdrRegAddress("x7",t),s.putBrReg("x7")});let o=new NativeFunction(r,"void",["pointer"].concat(e),W),i=function(...s){o(...s)};return i.handle=r,i.impl=t,i}default:{let r=new NativeFunction(t,"void",["pointer"].concat(e),W);return r.impl=t,r}}}var jt=class{constructor(){this.handle=Memory.alloc(ct)}dispose(){let[e,n]=this._getData();n||J().$delete(e)}disposeToString(){let e=this.toString();return this.dispose(),e}toString(){let[e]=this._getData();return e.readUtf8String()}_getData(){let e=this.handle,n=(e.readU8()&1)===0;return[n?e.add(1):e.add(2*v).readPointer(),n]}},Un=class{$delete(){this.dispose(),J().$delete(this)}constructor(e,n){this.handle=e,this._begin=e,this._end=e.add(v),this._storage=e.add(2*v),this._elementSize=n}init(){this.begin=NULL,this.end=NULL,this.storage=NULL}dispose(){J().$delete(this.begin)}get begin(){return this._begin.readPointer()}set begin(e){this._begin.writePointer(e)}get end(){return this._end.readPointer()}set end(e){this._end.writePointer(e)}get storage(){return this._storage.readPointer()}set storage(e){this._storage.writePointer(e)}get size(){return this.end.sub(this.begin).toInt32()/this._elementSize}},lt=class t extends Un{static $new(){let e=new t(J().$new(rc));return e.init(),e}constructor(e){super(e,v)}get handles(){let e=[],n=this.begin,r=this.end;for(;!n.equals(r);)e.push(n.readPointer()),n=n.add(v);return e}},jl=0,bo=v,yo=bo+4,Rl=-1,Rt=class t{$delete(){this.dispose(),J().$delete(this)}constructor(e){this.handle=e,this._link=e.add(jl),this._numberOfReferences=e.add(bo)}init(e,n){this.link=e,this.numberOfReferences=n}dispose(){}get link(){return new t(this._link.readPointer())}set link(e){this._link.writePointer(e)}get numberOfReferences(){return this._numberOfReferences.readS32()}set numberOfReferences(e){this._numberOfReferences.writeS32(e)}},Eo=Dl(yo),vo=Eo+v,Ol=vo+v,dt=class t extends Rt{static $new(e,n){let r=new t(J().$new(Ol));return r.init(e,n),r}constructor(e){super(e),this._self=e.add(Eo),this._currentScope=e.add(vo);let o=(64-v-4-4)/4;this._scopeLayout=at.layoutForCapacity(o),this._topHandleScopePtr=null}init(e,n){let r=e.add(qe(n).offset.topHandleScope);this._topHandleScopePtr=r,super.init(r.readPointer(),Rl),this.self=e,this.currentScope=at.$new(this._scopeLayout),r.writePointer(this)}dispose(){this._topHandleScopePtr.writePointer(this.link);let e;for(;(e=this.currentScope)!==null;){let n=e.link;e.$delete(),this.currentScope=n}}get self(){return this._self.readPointer()}set self(e){this._self.writePointer(e)}get currentScope(){let e=this._currentScope.readPointer();return e.isNull()?null:new at(e,this._scopeLayout)}set currentScope(e){this._currentScope.writePointer(e)}newHandle(e){return this.currentScope.newHandle(e)}},at=class t extends Rt{static $new(e){let n=new t(J().$new(e.size),e);return n.init(),n}constructor(e,n){super(e);let{offset:r}=n;this._refsStorage=e.add(r.refsStorage),this._pos=e.add(r.pos),this._layout=n}init(){super.init(NULL,this._layout.numberOfReferences),this.pos=0}get pos(){return this._pos.readU32()}set pos(e){this._pos.writeU32(e)}newHandle(e){let n=this.pos,r=this._refsStorage.add(n*4);return r.writeS32(e.toInt32()),this.pos=n+1,r}static layoutForCapacity(e){let n=yo,r=n+e*4;return{size:r+4,numberOfReferences:e,offset:{refsStorage:n,pos:r}}}},Pl={arm:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let i=[26625,18947,17041,53505,19202,18200,18288,48896],s=i.length*2,c=s+4,a=c+4;return Memory.patchCode(r,a,function(l){i.forEach((d,p)=>{l.add(p*2).writeU16(d)}),l.add(s).writeS32(t),l.add(c).writePointer(o)}),r.or(1)},arm64:function(t,e){let n=Process.pageSize,r=Memory.alloc(n);Memory.protect(r,n,"rwx");let o=new NativeCallback(e,"void",["pointer"]);r._onMatchCallback=o;let i=[3107979265,402653378,1795293247,1409286241,1476395139,3592355936,3596551104],s=i.length*4,c=s+4,a=c+8;return Memory.patchCode(r,a,function(l){i.forEach((d,p)=>{l.add(p*4).writeU32(d)}),l.add(s).writeS32(t),l.add(c).writePointer(o)}),r}};function tr(t,e){return(Pl[Process.arch]||Fl)(t,e)}function Fl(t,e){return new NativeCallback(n=>{n.readS32()===t&&e(n)},"void",["pointer","pointer"])}function Dl(t){let e=t%v;return e!==0?t+v-e:t}var Ul=4,{pointerSize:V}=Process,Bl=256,zl=65536,Vl=131072,Jl=33554432,Gl=67108864,$l=134217728,De={exceptions:"propagate"},Co=le(od),Hl=le(sd),Zl=le(td),nr=null,rr=!1,Ut=new Map,pt=new Map;function Ce(){return nr===null&&(nr=ql()),nr}function ql(){let t=Process.enumerateModules().filter(a=>/jvm.(dll|dylib|so)$/.test(a.name));if(t.length===0)return null;let e=t[0],n={flavor:"jvm"},r=Process.platform==="windows"?[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]],"VMThread::execute":["VMThread::execute","void",["pointer"]],"Method::size":["Method::size","int",["int"]],"Method::set_native_function":["Method::set_native_function","void",["pointer","pointer","int"]],"Method::clear_native_function":["Method::clear_native_function","void",["pointer"]],"Method::jmethod_id":["Method::jmethod_id","pointer",["pointer"]],"ClassLoaderDataGraph::classes_do":["ClassLoaderDataGraph::classes_do","void",["pointer"]],"NMethodSweeper::sweep_code_cache":["NMethodSweeper::sweep_code_cache","void",[]],"OopMapCache::flush_obsolete_entries":["OopMapCache::flush_obsolete_entries","void",["pointer"]]},variables:{"VM_RedefineClasses::`vftable'":function(a){this.vtableRedefineClasses=a},"VM_RedefineClasses::doit":function(a){this.redefineClassesDoIt=a},"VM_RedefineClasses::doit_prologue":function(a){this.redefineClassesDoItPrologue=a},"VM_RedefineClasses::doit_epilogue":function(a){this.redefineClassesDoItEpilogue=a},"VM_RedefineClasses::allow_nested_vm_operations":function(a){this.redefineClassesAllow=a},"NMethodSweeper::_traversals":function(a){this.traversals=a},"NMethodSweeper::_should_sweep":function(a){this.shouldSweep=a}},optionals:[]}]:[{module:e,functions:{JNI_GetCreatedJavaVMs:["JNI_GetCreatedJavaVMs","int",["pointer","int","pointer"]],_ZN6Method4sizeEb:["Method::size","int",["int"]],_ZN6Method19set_native_functionEPhb:["Method::set_native_function","void",["pointer","pointer","int"]],_ZN6Method21clear_native_functionEv:["Method::clear_native_function","void",["pointer"]],_ZN6Method24restore_unshareable_infoEP10JavaThread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method24restore_unshareable_infoEP6Thread:["Method::restore_unshareable_info","void",["pointer","pointer"]],_ZN6Method11link_methodERK12methodHandleP10JavaThread:["Method::link_method","void",["pointer","pointer","pointer"]],_ZN6Method10jmethod_idEv:["Method::jmethod_id","pointer",["pointer"]],_ZN6Method10clear_codeEv:function(a){let l=new NativeFunction(a,"void",["pointer"],De);this["Method::clear_code"]=function(d){l(d)}},_ZN6Method10clear_codeEb:function(a){let l=new NativeFunction(a,"void",["pointer","int"],De),d=0;this["Method::clear_code"]=function(p){l(p,d)}},_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass:["VM_RedefineClasses::mark_dependent_code","void",["pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeEv:["VM_RedefineClasses::flush_dependent_code","void",[]],_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread:["VM_RedefineClasses::flush_dependent_code","void",["pointer","pointer","pointer"]],_ZN19ResolvedMethodTable21adjust_method_entriesEPb:["ResolvedMethodTable::adjust_method_entries","void",["pointer"]],_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb:["MemberNameTable::adjust_method_entries","void",["pointer","pointer","pointer"]],_ZN17ConstantPoolCache21adjust_method_entriesEPb:function(a){let l=new NativeFunction(a,"void",["pointer","pointer"],De);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){l(d,f)}},_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb:function(a){let l=new NativeFunction(a,"void",["pointer","pointer","pointer"],De);this["ConstantPoolCache::adjust_method_entries"]=function(d,p,f){l(d,p,f)}},_ZN20ClassLoaderDataGraph10classes_doEP12KlassClosure:["ClassLoaderDataGraph::classes_do","void",["pointer"]],_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb:["ClassLoaderDataGraph::clean_deallocate_lists","void",["int"]],_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_:["JavaThread::thread_from_jni_environment","pointer",["pointer"]],_ZN8VMThread7executeEP12VM_Operation:["VMThread::execute","void",["pointer"]],_ZN11OopMapCache22flush_obsolete_entriesEv:["OopMapCache::flush_obsolete_entries","void",["pointer"]],_ZN14NMethodSweeper11force_sweepEv:["NMethodSweeper::force_sweep","void",[]],_ZN14NMethodSweeper16sweep_code_cacheEv:["NMethodSweeper::sweep_code_cache","void",[]],_ZN14NMethodSweeper17sweep_in_progressEv:["NMethodSweeper::sweep_in_progress","bool",[]],JVM_Sleep:["JVM_Sleep","void",["pointer","pointer","long"]]},variables:{_ZN18VM_RedefineClasses14_the_class_oopE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses10_the_classE:function(a){this.redefineClass=a},_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass:function(a){this.doKlass=a},_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass:function(a){this.doKlass=a},_ZTV18VM_RedefineClasses:function(a){this.vtableRedefineClasses=a},_ZN18VM_RedefineClasses4doitEv:function(a){this.redefineClassesDoIt=a},_ZN18VM_RedefineClasses13doit_prologueEv:function(a){this.redefineClassesDoItPrologue=a},_ZN18VM_RedefineClasses13doit_epilogueEv:function(a){this.redefineClassesDoItEpilogue=a},_ZN18VM_RedefineClassesD0Ev:function(a){this.redefineClassesDispose0=a},_ZN18VM_RedefineClassesD1Ev:function(a){this.redefineClassesDispose1=a},_ZNK18VM_RedefineClasses26allow_nested_vm_operationsEv:function(a){this.redefineClassesAllow=a},_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream:function(a){this.redefineClassesOnError=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread:function(a){this.createNewDefaultVtableIndices=a},_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread:function(a){this.createNewDefaultVtableIndices=a},_ZN19Abstract_VM_Version19jre_release_versionEv:function(a){let d=new NativeFunction(a,"pointer",[],De)().readCString();this.version=d.startsWith("1.8")?8:d.startsWith("9.")?9:parseInt(d.slice(0,2),10),this.versionS=d},_ZN14NMethodSweeper11_traversalsE:function(a){this.traversals=a},_ZN14NMethodSweeper21_sweep_fractions_leftE:function(a){this.fractions=a},_ZN14NMethodSweeper13_should_sweepE:function(a){this.shouldSweep=a}},optionals:["_ZN6Method24restore_unshareable_infoEP10JavaThread","_ZN6Method24restore_unshareable_infoEP6Thread","_ZN6Method11link_methodERK12methodHandleP10JavaThread","_ZN6Method10clear_codeEv","_ZN6Method10clear_codeEb","_ZN18VM_RedefineClasses19mark_dependent_codeEP13InstanceKlass","_ZN18VM_RedefineClasses20flush_dependent_codeEv","_ZN18VM_RedefineClasses20flush_dependent_codeEP13InstanceKlassP6Thread","_ZN18VM_RedefineClasses20flush_dependent_codeE19instanceKlassHandleP6Thread","_ZN19ResolvedMethodTable21adjust_method_entriesEPb","_ZN15MemberNameTable21adjust_method_entriesEP13InstanceKlassPb","_ZN17ConstantPoolCache21adjust_method_entriesEPb","_ZN17ConstantPoolCache21adjust_method_entriesEP13InstanceKlassPb","_ZN20ClassLoaderDataGraph22clean_deallocate_listsEb","_ZN10JavaThread27thread_from_jni_environmentEP7JNIEnv_","_ZN14NMethodSweeper11force_sweepEv","_ZN14NMethodSweeper17sweep_in_progressEv","_ZN18VM_RedefineClasses14_the_class_oopE","_ZN18VM_RedefineClasses10_the_classE","_ZN18VM_RedefineClasses25AdjustCpoolCacheAndVtable8do_klassEP5Klass","_ZN18VM_RedefineClasses22AdjustAndCleanMetadata8do_klassEP5Klass","_ZN18VM_RedefineClassesD0Ev","_ZN18VM_RedefineClassesD1Ev","_ZNK18VM_RedefineClasses14print_on_errorEP12outputStream","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP10JavaThread","_ZN13InstanceKlass33create_new_default_vtable_indicesEiP6Thread","_ZN14NMethodSweeper21_sweep_fractions_leftE"]}],o=[];if(r.forEach(function(a){let l=a.module,d=a.functions||{},p=a.variables||{},f=new Set(a.optionals||[]),u=l.enumerateExports().reduce(function(h,g){return h[g.name]=g,h},{}),_=l.enumerateSymbols().reduce(function(h,g){return h[g.name]=g,h},u);Object.keys(d).forEach(function(h){let g=_[h];if(g!==void 0){let b=d[h];typeof b=="function"?b.call(n,g.address):n[b[0]]=new NativeFunction(g.address,b[1],b[2],De)}else f.has(h)||o.push(h)}),Object.keys(p).forEach(function(h){let g=_[h];g!==void 0?p[h].call(n,g.address):f.has(h)||o.push(h)})}),o.length>0)throw new Error("Java API only partially available; please file a bug. Missing: "+o.join(", "));let i=Memory.alloc(V),s=Memory.alloc(Ul);if(de("JNI_GetCreatedJavaVMs",n.JNI_GetCreatedJavaVMs(i,1,s)),s.readInt()===0)return null;n.vm=i.readPointer();let c=Process.platform==="windows"?{$new:["??2@YAPEAX_K@Z","pointer",["ulong"]],$delete:["??3@YAXPEAX@Z","void",["pointer"]]}:{$new:["_Znwm","pointer",["ulong"]],$delete:["_ZdlPv","void",["pointer"]]};for(let[a,[l,d,p]]of Object.entries(c)){let f=Module.findGlobalExportByName(l);if(f===null&&(f=DebugSymbol.fromName(l).address,f.isNull()))throw new Error(`unable to find C++ allocator API, missing: '${l}'`);n[a]=new NativeFunction(f,d,p,De)}return n.jvmti=Wl(n),n["JavaThread::thread_from_jni_environment"]===void 0&&(n["JavaThread::thread_from_jni_environment"]=Ql(n)),n}function Wl(t){let e=new Ie(t),n;return e.perform(()=>{let r=e.tryGetEnvHandle(Et.v1_0);if(r===null)throw new Error("JVMTI not available");n=new Le(r,e);let o=Memory.alloc(8);o.writeU64(vt.canTagObjects);let i=n.addCapabilities(o);de("getEnvJvmti::AddCapabilities",i)}),n}var Kl={x64:Yl};function Ql(t){let e=null,n=Kl[Process.arch];if(n!==void 0){let o=new Ie(t).perform(i=>i.handle.readPointer().add(6*V).readPointer());e=xe(o,n,{limit:11})}return e===null?()=>{throw new Error("Unable to make thread_from_jni_environment() helper for the current architecture")}:r=>r.add(e)}function Yl(t){if(t.mnemonic!=="lea")return null;let{base:e,disp:n}=t.operands[1].value;return e==="rdi"&&n<0?n:null}function To(t,e){}var or=class{constructor(e){this.methodId=e,this.method=e.readPointer(),this.originalMethod=null,this.newMethod=null,this.resolved=null,this.impl=null,this.key=e.toString(16)}replace(e,n,r,o,i){let{key:s}=this,c=pt.get(s);c!==void 0&&(pt.delete(s),this.method=c.method,this.originalMethod=c.originalMethod,this.newMethod=c.newMethod,this.resolved=c.resolved),this.impl=e,Ut.set(s,this),So(o)}revert(e){let{key:n}=this;Ut.delete(n),pt.set(n,this),So(e)}resolveTarget(e,n,r,o){let{resolved:i,originalMethod:s,methodId:c}=this;if(i!==null)return i;if(s===null)return c;s.oldMethod.vtableIndexPtr.writeS32(-2);let l=Memory.alloc(V);return l.writePointer(this.method),this.resolved=l,l}};function So(t){rr||(rr=!0,Script.nextTick(Xl,t))}function Xl(t){let e=new Map(Ut),n=new Map(pt);Ut.clear(),pt.clear(),rr=!1,t.perform(r=>{let o=Ce(),i=o["JavaThread::thread_from_jni_environment"](r.handle),s=!1;Ao(()=>{e.forEach(c=>{let{method:a,originalMethod:l,impl:d,methodId:p,newMethod:f}=c;l===null?(c.originalMethod=xo(a),c.newMethod=nd(a,d,i),wo(c.newMethod,p,i)):o["Method::set_native_function"](f.method,d,0)}),n.forEach(c=>{let{originalMethod:a,methodId:l,newMethod:d}=c;if(a!==null){rd(a);let p=a.oldMethod;p.oldMethod=d,wo(p,l,i),s=!0}})}),s&&ed(r.handle)})}function ed(t){let{fractions:e,shouldSweep:n,traversals:r,"NMethodSweeper::sweep_code_cache":o,"NMethodSweeper::sweep_in_progress":i,"NMethodSweeper::force_sweep":s,JVM_Sleep:c}=Ce();if(s!==void 0)Thread.sleep(.05),s(),Thread.sleep(.05),s();else{let a=r.readS64(),l=a+2;for(;l>a;)e.writeS32(1),c(t,NULL,50),i()||Ao(()=>{Thread.sleep(.05)}),n.readU8()===0&&(e.writeS32(1),o()),a=r.readS64()}}function Ao(t,e,n){let{execute:r,vtable:o,vtableSize:i,doItOffset:s,prologueOffset:c,epilogueOffset:a}=Zl(),l=Memory.dup(o,i),d=Memory.alloc(V*25);d.writePointer(l);let p=new NativeCallback(t,"void",["pointer"]);l.add(s).writePointer(p);let f=null;e!==void 0&&(f=new NativeCallback(e,"int",["pointer"]),l.add(c).writePointer(f));let u=null;n!==void 0&&(u=new NativeCallback(n,"void",["pointer"]),l.add(a).writePointer(u)),r(d)}function td(){let{vtableRedefineClasses:t,redefineClassesDoIt:e,redefineClassesDoItPrologue:n,redefineClassesDoItEpilogue:r,redefineClassesOnError:o,redefineClassesAllow:i,redefineClassesDispose0:s,redefineClassesDispose1:c,"VMThread::execute":a}=Ce(),l=t.add(2*V),d=15*V,p=Memory.dup(l,d),f=new NativeCallback(()=>{},"void",["pointer"]),u,_,h;for(let g=0;g!==d;g+=V){let b=p.add(g),E=b.readPointer();o!==void 0&&E.equals(o)||s!==void 0&&E.equals(s)||c!==void 0&&E.equals(c)?b.writePointer(f):E.equals(e)?u=g:E.equals(n)?(_=g,b.writePointer(i)):E.equals(r)&&(h=g,b.writePointer(f))}return{execute:a,emptyCallback:f,vtable:p,vtableSize:d,doItOffset:u,prologueOffset:_,epilogueOffset:h}}function Lo(t){return new or(t)}function wo(t,e,n){let{method:r,oldMethod:o}=t,i=Ce();t.methodsArray.add(t.methodIndex*V).writePointer(r),t.vtableIndex>=0&&t.vtable.add(t.vtableIndex*V).writePointer(r),e.writePointer(r),o.accessFlagsPtr.writeU32((o.accessFlags|zl|Vl)>>>0);let s=i["OopMapCache::flush_obsolete_entries"];if(s!==void 0){let{oopMapCache:_}=t;_.isNull()||s(_)}let c=i["VM_RedefineClasses::mark_dependent_code"],a=i["VM_RedefineClasses::flush_dependent_code"];c!==void 0?(c(NULL,t.instanceKlass),a()):a(NULL,t.instanceKlass,n);let l=Memory.alloc(1);l.writeU8(1),i["ConstantPoolCache::adjust_method_entries"](t.cache,t.instanceKlass,l);let d=Memory.alloc(3*V),p=Memory.alloc(V);p.writePointer(i.doKlass),d.writePointer(p),d.add(V).writePointer(n),d.add(2*V).writePointer(n),i.redefineClass!==void 0&&i.redefineClass.writePointer(t.instanceKlass),i["ClassLoaderDataGraph::classes_do"](d);let f=i["ResolvedMethodTable::adjust_method_entries"];if(f!==void 0)f(l);else{let{memberNames:_}=t;if(!_.isNull()){let h=i["MemberNameTable::adjust_method_entries"];h!==void 0&&h(_,t.instanceKlass,l)}}let u=i["ClassLoaderDataGraph::clean_deallocate_lists"];u!==void 0&&u(0)}function nd(t,e,n){let r=Ce(),o=xo(t);o.constPtr.writePointer(o.const);let i=(o.accessFlags|Bl|Jl|Gl|$l)>>>0;if(o.accessFlagsPtr.writeU32(i),o.signatureHandler.writePointer(NULL),o.adapter.writePointer(NULL),o.i2iEntry.writePointer(NULL),r["Method::clear_code"](o.method),o.dataPtr.writePointer(NULL),o.countersPtr.writePointer(NULL),o.stackmapPtr.writePointer(NULL),r["Method::clear_native_function"](o.method),r["Method::set_native_function"](o.method,e,0),r["Method::restore_unshareable_info"](o.method,n),r.version>=17){let s=Memory.alloc(2*V);s.writePointer(o.method),s.add(V).writePointer(n),r["Method::link_method"](o.method,s,n)}return o}function xo(t){let e=Co(),n=t.add(e.method.constMethodOffset).readPointer(),r=n.add(e.constMethod.sizeOffset).readS32()*V,o=Memory.alloc(r+e.method.size);Memory.copy(o,n,r);let i=o.add(r);Memory.copy(i,t,e.method.size);let s=Io(i,o,r),c=Io(t,n,r);return s.oldMethod=c,s}function Io(t,e,n){let r=Ce(),o=Co(),i=t.add(o.method.constMethodOffset),s=t.add(o.method.methodDataOffset),c=t.add(o.method.methodCountersOffset),a=t.add(o.method.accessFlagsOffset),l=a.readU32(),d=o.getAdapterPointer(t,e),p=t.add(o.method.i2iEntryOffset),f=t.add(o.method.signatureHandlerOffset),u=e.add(o.constMethod.constantPoolOffset).readPointer(),_=e.add(o.constMethod.stackmapDataOffset),h=u.add(o.constantPool.instanceKlassOffset).readPointer(),g=u.add(o.constantPool.cacheOffset).readPointer(),b=Hl(),E=h.add(b.methodsOffset).readPointer(),C=E.readS32(),A=E.add(V),M=e.add(o.constMethod.methodIdnumOffset).readU16(),R=t.add(o.method.vtableIndexOffset),k=R.readS32(),N=h.add(b.vtableOffset),S=h.add(b.oopMapCacheOffset).readPointer(),L=r.version>=10?h.add(b.memberNamesOffset).readPointer():NULL;return{method:t,methodSize:o.method.size,const:e,constSize:n,constPtr:i,dataPtr:s,countersPtr:c,stackmapPtr:_,instanceKlass:h,methodsArray:A,methodsCount:C,methodIndex:M,vtableIndex:k,vtableIndexPtr:R,vtable:N,accessFlags:l,accessFlagsPtr:a,adapter:d,i2iEntry:p,signatureHandler:f,memberNames:L,cache:g,oopMapCache:S}}function rd(t){let{oldMethod:e}=t;e.accessFlagsPtr.writeU32(e.accessFlags),e.vtableIndexPtr.writeS32(e.vtableIndex)}function od(){let t=Ce(),{version:e}=t,n;e>=17?n="method:early":e>=9&&e<=16?n="const-method":n="method:late";let o=t["Method::size"](1)*V,i=V,s=2*V,c=3*V,a=4*V,l=n==="method:early"?V:0,d=a+l,p=d+4,f=p+4+8,u=f+V,_=l!==0?a:u,h=o-2*V,g=o-V,b=8,E=b+V,C=E+V,A=n==="const-method"?V:0,M=C+A,R=M+14,k=2*V,N=3*V;return{getAdapterPointer:A!==0?function(L,j){return j.add(C)}:function(L,j){return L.add(_)},method:{size:o,constMethodOffset:i,methodDataOffset:s,methodCountersOffset:c,accessFlagsOffset:d,vtableIndexOffset:p,i2iEntryOffset:f,nativeFunctionOffset:h,signatureHandlerOffset:g},constMethod:{constantPoolOffset:b,stackmapDataOffset:E,sizeOffset:M,methodIdnumOffset:R},constantPool:{cacheOffset:k,instanceKlassOffset:N}}}var id={x64:ad};function sd(){let{version:t,createNewDefaultVtableIndices:e}=Ce(),n=id[Process.arch];if(n===void 0)throw new Error(`Missing vtable offset parser for ${Process.arch}`);let r=xe(e,n,{limit:32});if(r===null)throw new Error("Unable to deduce vtable offset");let o=t>=10&&t<=11||t>=15?17:18,i=r-7*V,s=r-17*V,c=r-o*V;return{vtableOffset:r,methodsOffset:i,memberNamesOffset:s,oopMapCacheOffset:c}}function ad(t){if(t.mnemonic!=="mov")return null;let e=t.operands[0];if(e.type!=="mem")return null;let{value:n}=e;if(n.scale!==1)return null;let{disp:r}=n;return r<256?null:r+16}var No=J;try{ut()}catch{No=Ce}var ft=No;var cd=`#include +#include + +#define kAccStatic 0x0008 +#define kAccConstructor 0x00010000 + +typedef struct _Model Model; +typedef struct _EnumerateMethodsContext EnumerateMethodsContext; + +typedef struct _JavaApi JavaApi; +typedef struct _JavaClassApi JavaClassApi; +typedef struct _JavaMethodApi JavaMethodApi; +typedef struct _JavaFieldApi JavaFieldApi; + +typedef struct _JNIEnv JNIEnv; +typedef guint8 jboolean; +typedef gint32 jint; +typedef jint jsize; +typedef gpointer jobject; +typedef jobject jclass; +typedef jobject jstring; +typedef jobject jarray; +typedef jarray jobjectArray; +typedef gpointer jfieldID; +typedef gpointer jmethodID; + +typedef struct _jvmtiEnv jvmtiEnv; +typedef enum +{ + JVMTI_ERROR_NONE = 0 +} jvmtiError; + +typedef struct _ArtApi ArtApi; +typedef guint32 ArtHeapReference; +typedef struct _ArtObject ArtObject; +typedef struct _ArtClass ArtClass; +typedef struct _ArtClassLinker ArtClassLinker; +typedef struct _ArtClassVisitor ArtClassVisitor; +typedef struct _ArtClassVisitorVTable ArtClassVisitorVTable; +typedef struct _ArtMethod ArtMethod; +typedef struct _ArtString ArtString; + +typedef union _StdString StdString; +typedef struct _StdStringShort StdStringShort; +typedef struct _StdStringLong StdStringLong; + +typedef void (* ArtVisitClassesFunc) (ArtClassLinker * linker, ArtClassVisitor * visitor); +typedef const char * (* ArtGetClassDescriptorFunc) (ArtClass * klass, StdString * storage); +typedef void (* ArtPrettyMethodFunc) (StdString * result, ArtMethod * method, jboolean with_signature); + +struct _Model +{ + GHashTable * members; +}; + +struct _EnumerateMethodsContext +{ + GPatternSpec * class_query; + GPatternSpec * method_query; + jboolean include_signature; + jboolean ignore_case; + jboolean skip_system_classes; + GHashTable * groups; +}; + +struct _JavaClassApi +{ + jmethodID get_declared_methods; + jmethodID get_declared_fields; +}; + +struct _JavaMethodApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaFieldApi +{ + jmethodID get_name; + jmethodID get_modifiers; +}; + +struct _JavaApi +{ + jvmtiEnv * jvmti; + JavaClassApi clazz; + JavaMethodApi method; + JavaFieldApi field; +}; + +struct _JNIEnv +{ + gpointer * functions; +}; + +struct _jvmtiEnv +{ + gpointer * functions; +}; + +struct _ArtApi +{ + gboolean available; + + guint class_offset_ifields; + guint class_offset_methods; + guint class_offset_sfields; + guint class_offset_copied_methods_offset; + + guint method_size; + guint method_offset_access_flags; + + guint field_size; + guint field_offset_access_flags; + + guint alignment_padding; + + ArtClassLinker * linker; + ArtVisitClassesFunc visit_classes; + ArtGetClassDescriptorFunc get_class_descriptor; + ArtPrettyMethodFunc pretty_method; + + void (* free) (gpointer mem); +}; + +struct _ArtObject +{ + ArtHeapReference klass; + ArtHeapReference monitor; +}; + +struct _ArtClass +{ + ArtObject parent; + + ArtHeapReference class_loader; +}; + +struct _ArtClassVisitor +{ + ArtClassVisitorVTable * vtable; + gpointer user_data; +}; + +struct _ArtClassVisitorVTable +{ + void (* reserved1) (ArtClassVisitor * self); + void (* reserved2) (ArtClassVisitor * self); + jboolean (* visit) (ArtClassVisitor * self, ArtClass * klass); +}; + +struct _ArtString +{ + ArtObject parent; + + gint32 count; + guint32 hash_code; + + union + { + guint16 value[0]; + guint8 value_compressed[0]; + }; +}; + +struct _StdStringShort +{ + guint8 size; + gchar data[(3 * sizeof (gpointer)) - sizeof (guint8)]; +}; + +struct _StdStringLong +{ + gsize capacity; + gsize size; + gchar * data; +}; + +union _StdString +{ + StdStringShort s; + StdStringLong l; +}; + +static void model_add_method (Model * self, const gchar * name, jmethodID id, jint modifiers); +static void model_add_field (Model * self, const gchar * name, jfieldID id, jint modifiers); +static void model_free (Model * model); + +static jboolean collect_matching_class_methods (ArtClassVisitor * self, ArtClass * klass); +static gchar * finalize_method_groups_to_json (GHashTable * groups); +static GPatternSpec * make_pattern_spec (const gchar * pattern, jboolean ignore_case); +static gchar * class_name_from_signature (const gchar * signature); +static gchar * format_method_signature (const gchar * name, const gchar * signature); +static void append_type (GString * output, const gchar ** type); + +static gpointer read_art_array (gpointer object_base, guint field_offset, guint length_size, guint * length); + +static void std_string_destroy (StdString * str); +static gchar * std_string_c_str (StdString * self); + +extern GMutex lock; +extern GArray * models; +extern JavaApi java_api; +extern ArtApi art_api; + +void +init (void) +{ + g_mutex_init (&lock); + models = g_array_new (FALSE, FALSE, sizeof (Model *)); +} + +void +finalize (void) +{ + guint n, i; + + n = models->len; + for (i = 0; i != n; i++) + { + Model * model = g_array_index (models, Model *, i); + model_free (model); + } + + g_array_unref (models); + g_mutex_clear (&lock); +} + +Model * +model_new (jclass class_handle, + gpointer class_object, + JNIEnv * env) +{ + Model * model; + GHashTable * members; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * funcs = env->functions; + jmethodID (* from_reflected_method) (JNIEnv *, jobject) = funcs[7]; + jfieldID (* from_reflected_field) (JNIEnv *, jobject) = funcs[8]; + jobject (* to_reflected_method) (JNIEnv *, jclass, jmethodID, jboolean) = funcs[9]; + jobject (* to_reflected_field) (JNIEnv *, jclass, jfieldID, jboolean) = funcs[12]; + void (* delete_local_ref) (JNIEnv *, jobject) = funcs[23]; + jobject (* call_object_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[34]; + jint (* call_int_method) (JNIEnv *, jobject, jmethodID, ...) = funcs[49]; + const char * (* get_string_utf_chars) (JNIEnv *, jstring, jboolean *) = funcs[169]; + void (* release_string_utf_chars) (JNIEnv *, jstring, const char *) = funcs[170]; + jsize (* get_array_length) (JNIEnv *, jarray) = funcs[171]; + jobject (* get_object_array_element) (JNIEnv *, jobjectArray, jsize) = funcs[173]; + jsize n, i; + + model = g_new (Model, 1); + + members = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + model->members = members; + + if (jvmti != NULL) + { + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_fields) (jvmtiEnv *, jclass, jint *, jfieldID **) = jf[53]; + jvmtiError (* get_field_name) (jvmtiEnv *, jclass, jfieldID, char **, char **, char **) = jf[60]; + jvmtiError (* get_field_modifiers) (jvmtiEnv *, jclass, jfieldID, jint *) = jf[62]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_method_modifiers) (jvmtiEnv *, jmethodID, jint *) = jf[66]; + jint method_count; + jmethodID * methods; + jint field_count; + jfieldID * fields; + char * name; + jint modifiers; + + get_class_methods (jvmti, class_handle, &method_count, &methods); + for (i = 0; i != method_count; i++) + { + jmethodID method = methods[i]; + + get_method_name (jvmti, method, &name, NULL, NULL); + get_method_modifiers (jvmti, method, &modifiers); + + model_add_method (model, name, method, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, methods); + + get_class_fields (jvmti, class_handle, &field_count, &fields); + for (i = 0; i != field_count; i++) + { + jfieldID field = fields[i]; + + get_field_name (jvmti, class_handle, field, &name, NULL, NULL); + get_field_modifiers (jvmti, class_handle, field, &modifiers); + + model_add_field (model, name, field, modifiers); + + deallocate (jvmti, name); + } + deallocate (jvmti, fields); + } + else if (art_api.available) + { + gpointer elements; + guint n, i; + const guint field_arrays[] = { + art_api.class_offset_ifields, + art_api.class_offset_sfields + }; + guint field_array_cursor; + gboolean merged_fields = art_api.class_offset_sfields == 0; + + elements = read_art_array (class_object, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) (class_object + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + jmethodID id; + guint32 access_flags; + jboolean is_static; + jobject method, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) (id + art_api.method_offset_access_flags); + if ((access_flags & kAccConstructor) != 0) + continue; + is_static = (access_flags & kAccStatic) != 0; + method = to_reflected_method (env, class_handle, id, is_static); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + + for (field_array_cursor = 0; field_array_cursor != G_N_ELEMENTS (field_arrays); field_array_cursor++) + { + jboolean is_static; + + if (field_arrays[field_array_cursor] == 0) + continue; + + if (!merged_fields) + is_static = field_array_cursor == 1; + + elements = read_art_array (class_object, field_arrays[field_array_cursor], sizeof (guint32), &n); + for (i = 0; i != n; i++) + { + jfieldID id; + guint32 access_flags; + jobject field, name; + const char * name_str; + jint modifiers; + + id = elements + (i * art_api.field_size); + + access_flags = *(guint32 *) (id + art_api.field_offset_access_flags); + if (merged_fields) + is_static = (access_flags & kAccStatic) != 0; + field = to_reflected_field (env, class_handle, id, is_static); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + modifiers = access_flags & 0xffff; + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + } + } + else + { + jobject elements; + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_methods); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject method, name; + const char * name_str; + jmethodID id; + jint modifiers; + + method = get_object_array_element (env, elements, i); + name = call_object_method (env, method, java_api.method.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_method (env, method); + modifiers = call_int_method (env, method, java_api.method.get_modifiers); + + model_add_method (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, method); + } + delete_local_ref (env, elements); + + elements = call_object_method (env, class_handle, java_api.clazz.get_declared_fields); + n = get_array_length (env, elements); + for (i = 0; i != n; i++) + { + jobject field, name; + const char * name_str; + jfieldID id; + jint modifiers; + + field = get_object_array_element (env, elements, i); + name = call_object_method (env, field, java_api.field.get_name); + name_str = get_string_utf_chars (env, name, NULL); + id = from_reflected_field (env, field); + modifiers = call_int_method (env, field, java_api.field.get_modifiers); + + model_add_field (model, name_str, id, modifiers); + + release_string_utf_chars (env, name, name_str); + delete_local_ref (env, name); + delete_local_ref (env, field); + } + delete_local_ref (env, elements); + } + + g_mutex_lock (&lock); + g_array_append_val (models, model); + g_mutex_unlock (&lock); + + return model; +} + +static void +model_add_method (Model * self, + const gchar * name, + jmethodID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + const gchar * value; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + value = g_hash_table_lookup (members, key); + if (value == NULL) + g_hash_table_insert (members, key, g_strdup_printf ("m:%c0x%zx", type, id)); + else + g_hash_table_insert (members, key, g_strdup_printf ("%s:%c0x%zx", value, type, id)); +} + +static void +model_add_field (Model * self, + const gchar * name, + jfieldID id, + jint modifiers) +{ + GHashTable * members = self->members; + gchar * key, type; + + if (name[0] == '$') + key = g_strdup_printf ("_%s", name); + else + key = g_strdup (name); + while (g_hash_table_contains (members, key)) + { + gchar * new_key = g_strdup_printf ("_%s", key); + g_free (key); + key = new_key; + } + + type = (modifiers & kAccStatic) != 0 ? 's' : 'i'; + + g_hash_table_insert (members, key, g_strdup_printf ("f:%c0x%zx", type, id)); +} + +static void +model_free (Model * model) +{ + g_hash_table_unref (model->members); + + g_free (model); +} + +gboolean +model_has (Model * self, + const gchar * member) +{ + return g_hash_table_contains (self->members, member); +} + +const gchar * +model_find (Model * self, + const gchar * member) +{ + return g_hash_table_lookup (self->members, member); +} + +gchar * +model_list (Model * self) +{ + GString * result; + GHashTableIter iter; + guint i; + const gchar * name; + + result = g_string_sized_new (128); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, self->members); + for (i = 0; g_hash_table_iter_next (&iter, (gpointer *) &name, NULL); i++) + { + if (i > 0) + g_string_append_c (result, ','); + + g_string_append_c (result, '"'); + g_string_append (result, name); + g_string_append_c (result, '"'); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +gchar * +enumerate_methods_art (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes) +{ + gchar * result; + EnumerateMethodsContext ctx; + ArtClassVisitor visitor; + ArtClassVisitorVTable visitor_vtable = { NULL, }; + + ctx.class_query = make_pattern_spec (class_query, ignore_case); + ctx.method_query = make_pattern_spec (method_query, ignore_case); + ctx.include_signature = include_signature; + ctx.ignore_case = ignore_case; + ctx.skip_system_classes = skip_system_classes; + ctx.groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + visitor.vtable = &visitor_vtable; + visitor.user_data = &ctx; + + visitor_vtable.visit = collect_matching_class_methods; + + art_api.visit_classes (art_api.linker, &visitor); + + result = finalize_method_groups_to_json (ctx.groups); + + g_hash_table_unref (ctx.groups); + g_pattern_spec_free (ctx.method_query); + g_pattern_spec_free (ctx.class_query); + + return result; +} + +static jboolean +collect_matching_class_methods (ArtClassVisitor * self, + ArtClass * klass) +{ + EnumerateMethodsContext * ctx = self->user_data; + const char * descriptor; + StdString descriptor_storage = { 0, }; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + JsonBuilder * group; + size_t class_name_length; + GHashTable * seen_method_names; + gpointer elements; + guint n, i; + + if (ctx->skip_system_classes && klass->class_loader == 0) + goto skip_class; + + descriptor = art_api.get_class_descriptor (klass, &descriptor_storage); + if (descriptor[0] != 'L') + goto skip_class; + + class_name = class_name_from_signature (descriptor); + + if (ctx->ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (ctx->class_query, normalized_class_name)) + goto skip_class; + + group = NULL; + class_name_length = strlen (class_name); + seen_method_names = ctx->include_signature ? NULL : g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + elements = read_art_array (klass, art_api.class_offset_methods, sizeof (gsize), NULL); + n = *(guint16 *) ((gpointer) klass + art_api.class_offset_copied_methods_offset); + for (i = 0; i != n; i++) + { + ArtMethod * method; + guint32 access_flags; + jboolean is_constructor; + StdString method_name = { 0, }; + const gchar * bare_method_name; + gchar * bare_method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + method = elements + (i * art_api.method_size); + + access_flags = *(guint32 *) ((gpointer) method + art_api.method_offset_access_flags); + is_constructor = (access_flags & kAccConstructor) != 0; + + art_api.pretty_method (&method_name, method, ctx->include_signature); + bare_method_name = std_string_c_str (&method_name); + if (ctx->include_signature) + { + const gchar * return_type_end, * name_begin; + GString * name; + + return_type_end = strchr (bare_method_name, ' '); + name_begin = return_type_end + 1 + class_name_length + 1; + if (is_constructor && g_str_has_prefix (name_begin, "")) + goto skip_method; + + name = g_string_sized_new (64); + + if (is_constructor) + { + g_string_append (name, "$init"); + g_string_append (name, strchr (name_begin, '>') + 1); + } + else + { + g_string_append (name, name_begin); + } + g_string_append (name, ": "); + g_string_append_len (name, bare_method_name, return_type_end - bare_method_name); + + bare_method_name_copy = g_string_free (name, FALSE); + bare_method_name = bare_method_name_copy; + } + else + { + const gchar * name_begin; + + name_begin = bare_method_name + class_name_length + 1; + if (is_constructor && strcmp (name_begin, "") == 0) + goto skip_method; + + if (is_constructor) + bare_method_name = "$init"; + else + bare_method_name += class_name_length + 1; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, bare_method_name)) + goto skip_method; + + if (ctx->ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (bare_method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = bare_method_name; + } + + if (!g_pattern_match_string (ctx->method_query, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + group = g_hash_table_lookup (ctx->groups, GUINT_TO_POINTER (klass->class_loader)); + if (group == NULL) + { + group = json_builder_new_immutable (); + g_hash_table_insert (ctx->groups, GUINT_TO_POINTER (klass->class_loader), group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + json_builder_add_int_value (group, klass->class_loader); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, bare_method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (bare_method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (bare_method_name_copy); + std_string_destroy (&method_name); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + if (group == NULL) + goto skip_class; + + json_builder_end_array (group); + json_builder_end_object (group); + +skip_class: + g_free (class_name_copy); + g_free (class_name); + std_string_destroy (&descriptor_storage); + + return TRUE; +} + +gchar * +enumerate_methods_jvm (const gchar * class_query, + const gchar * method_query, + jboolean include_signature, + jboolean ignore_case, + jboolean skip_system_classes, + JNIEnv * env) +{ + gchar * result; + GPatternSpec * class_pattern, * method_pattern; + GHashTable * groups; + gpointer * ef = env->functions; + jobject (* new_global_ref) (JNIEnv *, jobject) = ef[21]; + void (* delete_local_ref) (JNIEnv *, jobject) = ef[23]; + jboolean (* is_same_object) (JNIEnv *, jobject, jobject) = ef[24]; + jvmtiEnv * jvmti = java_api.jvmti; + gpointer * jf = jvmti->functions - 1; + jvmtiError (* deallocate) (jvmtiEnv *, void * mem) = jf[47]; + jvmtiError (* get_class_signature) (jvmtiEnv *, jclass, char **, char **) = jf[48]; + jvmtiError (* get_class_methods) (jvmtiEnv *, jclass, jint *, jmethodID **) = jf[52]; + jvmtiError (* get_class_loader) (jvmtiEnv *, jclass, jobject *) = jf[57]; + jvmtiError (* get_method_name) (jvmtiEnv *, jmethodID, char **, char **, char **) = jf[64]; + jvmtiError (* get_loaded_classes) (jvmtiEnv *, jint *, jclass **) = jf[78]; + jint class_count, class_index; + jclass * classes; + + class_pattern = make_pattern_spec (class_query, ignore_case); + method_pattern = make_pattern_spec (method_query, ignore_case); + groups = g_hash_table_new_full (NULL, NULL, NULL, NULL); + + if (get_loaded_classes (jvmti, &class_count, &classes) != JVMTI_ERROR_NONE) + goto emit_results; + + for (class_index = 0; class_index != class_count; class_index++) + { + jclass klass = classes[class_index]; + jobject loader = NULL; + gboolean have_loader = FALSE; + char * signature = NULL; + gchar * class_name = NULL; + gchar * class_name_copy = NULL; + const gchar * normalized_class_name; + jint method_count, method_index; + jmethodID * methods = NULL; + JsonBuilder * group = NULL; + GHashTable * seen_method_names = NULL; + + if (skip_system_classes) + { + if (get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_class; + have_loader = TRUE; + + if (loader == NULL) + goto skip_class; + } + + if (get_class_signature (jvmti, klass, &signature, NULL) != JVMTI_ERROR_NONE) + goto skip_class; + + class_name = class_name_from_signature (signature); + + if (ignore_case) + { + class_name_copy = g_utf8_strdown (class_name, -1); + normalized_class_name = class_name_copy; + } + else + { + normalized_class_name = class_name; + } + + if (!g_pattern_match_string (class_pattern, normalized_class_name)) + goto skip_class; + + if (get_class_methods (jvmti, klass, &method_count, &methods) != JVMTI_ERROR_NONE) + goto skip_class; + + if (!include_signature) + seen_method_names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + for (method_index = 0; method_index != method_count; method_index++) + { + jmethodID method = methods[method_index]; + const gchar * method_name; + char * method_name_value = NULL; + char * method_signature_value = NULL; + gchar * method_name_copy = NULL; + const gchar * normalized_method_name; + gchar * normalized_method_name_copy = NULL; + + if (get_method_name (jvmti, method, &method_name_value, include_signature ? &method_signature_value : NULL, NULL) != JVMTI_ERROR_NONE) + goto skip_method; + method_name = method_name_value; + + if (method_name[0] == '<') + { + if (strcmp (method_name, "") == 0) + method_name = "$init"; + else if (strcmp (method_name, "") == 0) + goto skip_method; + } + + if (include_signature) + { + method_name_copy = format_method_signature (method_name, method_signature_value); + method_name = method_name_copy; + } + + if (seen_method_names != NULL && g_hash_table_contains (seen_method_names, method_name)) + goto skip_method; + + if (ignore_case) + { + normalized_method_name_copy = g_utf8_strdown (method_name, -1); + normalized_method_name = normalized_method_name_copy; + } + else + { + normalized_method_name = method_name; + } + + if (!g_pattern_match_string (method_pattern, normalized_method_name)) + goto skip_method; + + if (group == NULL) + { + if (!have_loader && get_class_loader (jvmti, klass, &loader) != JVMTI_ERROR_NONE) + goto skip_method; + + if (loader == NULL) + { + group = g_hash_table_lookup (groups, NULL); + } + else + { + GHashTableIter iter; + jobject cur_loader; + JsonBuilder * cur_group; + + g_hash_table_iter_init (&iter, groups); + while (g_hash_table_iter_next (&iter, (gpointer *) &cur_loader, (gpointer *) &cur_group)) + { + if (cur_loader != NULL && is_same_object (env, cur_loader, loader)) + { + group = cur_group; + break; + } + } + } + + if (group == NULL) + { + jobject l; + gchar * str; + + l = (loader != NULL) ? new_global_ref (env, loader) : NULL; + + group = json_builder_new_immutable (); + g_hash_table_insert (groups, l, group); + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "loader"); + str = g_strdup_printf ("0x%" G_GSIZE_MODIFIER "x", GPOINTER_TO_SIZE (l)); + json_builder_add_string_value (group, str); + g_free (str); + + json_builder_set_member_name (group, "classes"); + json_builder_begin_array (group); + } + + json_builder_begin_object (group); + + json_builder_set_member_name (group, "name"); + json_builder_add_string_value (group, class_name); + + json_builder_set_member_name (group, "methods"); + json_builder_begin_array (group); + } + + json_builder_add_string_value (group, method_name); + + if (seen_method_names != NULL) + g_hash_table_add (seen_method_names, g_strdup (method_name)); + +skip_method: + g_free (normalized_method_name_copy); + g_free (method_name_copy); + deallocate (jvmti, method_signature_value); + deallocate (jvmti, method_name_value); + } + +skip_class: + if (group != NULL) + { + json_builder_end_array (group); + json_builder_end_object (group); + } + + if (seen_method_names != NULL) + g_hash_table_unref (seen_method_names); + + deallocate (jvmti, methods); + + g_free (class_name_copy); + g_free (class_name); + deallocate (jvmti, signature); + + if (loader != NULL) + delete_local_ref (env, loader); + + delete_local_ref (env, klass); + } + + deallocate (jvmti, classes); + +emit_results: + result = finalize_method_groups_to_json (groups); + + g_hash_table_unref (groups); + g_pattern_spec_free (method_pattern); + g_pattern_spec_free (class_pattern); + + return result; +} + +static gchar * +finalize_method_groups_to_json (GHashTable * groups) +{ + GString * result; + GHashTableIter iter; + guint i; + JsonBuilder * group; + + result = g_string_sized_new (1024); + + g_string_append_c (result, '['); + + g_hash_table_iter_init (&iter, groups); + for (i = 0; g_hash_table_iter_next (&iter, NULL, (gpointer *) &group); i++) + { + JsonNode * root; + gchar * json; + + if (i > 0) + g_string_append_c (result, ','); + + json_builder_end_array (group); + json_builder_end_object (group); + + root = json_builder_get_root (group); + json = json_to_string (root, FALSE); + g_string_append (result, json); + g_free (json); + json_node_unref (root); + + g_object_unref (group); + } + + g_string_append_c (result, ']'); + + return g_string_free (result, FALSE); +} + +static GPatternSpec * +make_pattern_spec (const gchar * pattern, + jboolean ignore_case) +{ + GPatternSpec * spec; + + if (ignore_case) + { + gchar * str = g_utf8_strdown (pattern, -1); + spec = g_pattern_spec_new (str); + g_free (str); + } + else + { + spec = g_pattern_spec_new (pattern); + } + + return spec; +} + +static gchar * +class_name_from_signature (const gchar * descriptor) +{ + gchar * result, * c; + + result = g_strdup (descriptor + 1); + + for (c = result; *c != '\\0'; c++) + { + if (*c == '/') + *c = '.'; + } + + c[-1] = '\\0'; + + return result; +} + +static gchar * +format_method_signature (const gchar * name, + const gchar * signature) +{ + GString * sig; + const gchar * cursor; + gint arg_index; + + sig = g_string_sized_new (128); + + g_string_append (sig, name); + + cursor = signature; + arg_index = -1; + while (TRUE) + { + const gchar c = *cursor; + + if (c == '(') + { + g_string_append_c (sig, c); + cursor++; + arg_index = 0; + } + else if (c == ')') + { + g_string_append_c (sig, c); + cursor++; + break; + } + else + { + if (arg_index >= 1) + g_string_append (sig, ", "); + + append_type (sig, &cursor); + + if (arg_index != -1) + arg_index++; + } + } + + g_string_append (sig, ": "); + append_type (sig, &cursor); + + return g_string_free (sig, FALSE); +} + +static void +append_type (GString * output, + const gchar ** type) +{ + const gchar * cursor = *type; + + switch (*cursor) + { + case 'Z': + g_string_append (output, "boolean"); + cursor++; + break; + case 'B': + g_string_append (output, "byte"); + cursor++; + break; + case 'C': + g_string_append (output, "char"); + cursor++; + break; + case 'S': + g_string_append (output, "short"); + cursor++; + break; + case 'I': + g_string_append (output, "int"); + cursor++; + break; + case 'J': + g_string_append (output, "long"); + cursor++; + break; + case 'F': + g_string_append (output, "float"); + cursor++; + break; + case 'D': + g_string_append (output, "double"); + cursor++; + break; + case 'V': + g_string_append (output, "void"); + cursor++; + break; + case 'L': + { + gchar ch; + + cursor++; + for (; (ch = *cursor) != ';'; cursor++) + { + g_string_append_c (output, (ch != '/') ? ch : '.'); + } + cursor++; + + break; + } + case '[': + *type = cursor + 1; + append_type (output, type); + g_string_append (output, "[]"); + return; + default: + g_string_append (output, "BUG"); + cursor++; + } + + *type = cursor; +} + +void +dealloc (gpointer mem) +{ + g_free (mem); +} + +static gpointer +read_art_array (gpointer object_base, + guint field_offset, + guint length_size, + guint * length) +{ + gpointer result, header; + guint n; + + header = GSIZE_TO_POINTER (*(guint64 *) (object_base + field_offset)); + if (header != NULL) + { + result = header + length_size; + if (length_size == sizeof (guint32)) + n = *(guint32 *) header; + else + n = *(guint64 *) header; + } + else + { + result = NULL; + n = 0; + } + + if (length != NULL) + *length = n; + + return result; +} + +static void +std_string_destroy (StdString * str) +{ + if ((str->l.capacity & 1) != 0) + art_api.free (str->l.data); +} + +static gchar * +std_string_c_str (StdString * self) +{ + if ((self->l.capacity & 1) != 0) + return self->l.data; + + return self->s.data; +} +`,ld=/(.+)!([^/]+)\/?([isu]+)?/,Ee=null,Mo=null,Ue=class t{static build(e,n){return ko(n),Mo(e,n,r=>new t(Ee.new(e,r,n)))}static enumerateMethods(e,n,r){ko(r);let o=e.match(ld);if(o===null)throw new Error("Invalid query; format is: class!method -- see documentation of Java.enumerateMethods(query) for details");let i=Memory.allocUtf8String(o[1]),s=Memory.allocUtf8String(o[2]),c=!1,a=!1,l=!1,d=o[3];d!==void 0&&(c=d.indexOf("s")!==-1,a=d.indexOf("i")!==-1,l=d.indexOf("u")!==-1);let p;if(n.jvmti!==null){let f=Ee.enumerateMethodsJvm(i,s,We(c),We(a),We(l),r);try{p=JSON.parse(f.readUtf8String()).map(u=>{let _=ptr(u.loader);return u.loader=_.isNull()?null:_,u})}finally{Ee.dealloc(f)}}else ye(r.vm,r,f=>{let u=Ee.enumerateMethodsArt(i,s,We(c),We(a),We(l));try{let _=n["art::JavaVMExt::AddGlobalRef"],{vm:h}=n;p=JSON.parse(u.readUtf8String()).map(g=>{let b=g.loader;return g.loader=b!==0?_(h,f,ptr(b)):null,g})}finally{Ee.dealloc(u)}});return p}constructor(e){this.handle=e}has(e){return Ee.has(this.handle,Memory.allocUtf8String(e))!==0}find(e){return Ee.find(this.handle,Memory.allocUtf8String(e)).readUtf8String()}list(){let e=Ee.list(this.handle);try{return JSON.parse(e.readUtf8String())}finally{Ee.dealloc(e)}}};function ko(t){Ee===null&&(Ee=dd(t),Mo=ud(Ee,t.vm))}function dd(t){let e=ft(),{jvmti:n=null}=e,{pointerSize:r}=Process,o=8,i=r,s=7*r,c=10*4+5*r,a=o+i+s+c,d=Memory.alloc(a),p=d.add(o),f=p.add(i),{getDeclaredMethods:u,getDeclaredFields:_}=t.javaLangClass(),h=t.javaLangReflectMethod(),g=t.javaLangReflectField(),b=f;[n!==null?n:NULL,u,_,h.getName,h.getModifiers,g.getName,g.getModifiers].forEach(k=>{b=b.writePointer(k).add(r)});let E=f.add(s),{vm:C}=t;if(e.flavor==="art"){let k;if(n!==null)k=[0,0,0,0];else{let j=Jn(C).offset;k=[j.ifields,j.methods,j.sfields,j.copiedMethodsOffset]}let N=_e(C),S=Pt(C),L=E;[1,...k,N.size,N.offset.accessFlags,S.size,S.offset.accessFlags,4294967295].forEach(j=>{L=L.writeUInt(j).add(4)}),[e.artClassLinker.address,e["art::ClassLinker::VisitClasses"],e["art::mirror::Class::GetDescriptor"],e["art::ArtMethod::PrettyMethod"],Process.getModuleByName("libc.so").getExportByName("free")].forEach((j,w)=>{j===void 0&&(j=NULL),L=L.writePointer(j).add(r)})}let A=new CModule(cd,{lock:d,models:p,java_api:f,art_api:E}),M={exceptions:"propagate"},R={exceptions:"propagate",scheduling:"exclusive"};return{handle:A,new:new NativeFunction(A.model_new,"pointer",["pointer","pointer","pointer"],M),has:new NativeFunction(A.model_has,"bool",["pointer","pointer"],R),find:new NativeFunction(A.model_find,"pointer",["pointer","pointer"],R),list:new NativeFunction(A.model_list,"pointer",["pointer"],R),enumerateMethodsArt:new NativeFunction(A.enumerate_methods_art,"pointer",["pointer","pointer","bool","bool","bool"],M),enumerateMethodsJvm:new NativeFunction(A.enumerate_methods_jvm,"pointer",["pointer","pointer","bool","bool","bool","pointer"],M),dealloc:new NativeFunction(A.dealloc,"void",["pointer"],R)}}function ud(t,e){let n=ft();if(n.flavor!=="art")return pd;let r=n["art::JavaVMExt::DecodeGlobal"];return function(o,i,s){let c;return ye(e,i,a=>{let l=r(e,a,o);c=s(l)}),c}}function pd(t,e,n){return n(NULL)}function We(t){return t?1:0}var ht=class{constructor(e,n){this.items=new Map,this.capacity=e,this.destroy=n}dispose(e){let{items:n,destroy:r}=this;n.forEach(o=>{r(o,e)}),n.clear()}get(e){let{items:n}=this,r=n.get(e);return r!==void 0&&(n.delete(e),n.set(e,r)),r}set(e,n,r){let{items:o}=this,i=o.get(e);if(i!==void 0)o.delete(e),this.destroy(i,r);else if(o.size===this.capacity){let s=o.keys().next().value,c=o.get(s);o.delete(s),this.destroy(c,r)}o.set(e,n)}};var _t=1,ar=256,jo=65536,fd=305419896,Ro=32,Oo=12,Po=8,Fo=8,Do=4,Uo=4,Bo=12,hd=0,_d=1,md=2,gd=3,bd=4,yd=5,Ed=6,vd=4096,Sd=4097,wd=4099,Id=8192,Cd=8193,Td=8194,Ad=8195,Ld=8196,xd=8198,Nd=24,kd=28,Md=2,jd=24,zo=m.from([3,0,7,14,0]),ir="Ldalvik/annotation/Throws;",Rd=m.from([0]);function Od(t){let e=new cr,n=Object.assign({},t);return e.addClass(n),e.build()}var cr=class{constructor(){this.classes=[]}addClass(e){this.classes.push(e)}build(){let e=Dd(this.classes),{classes:n,interfaces:r,fields:o,methods:i,protos:s,parameters:c,annotationDirectories:a,annotationSets:l,throwsAnnotations:d,types:p,strings:f}=e,u=0,_=0,h=8,g=12,b=20,E=112;u+=E;let C=u,A=f.length*Uo;u+=A;let M=u,R=p.length*Do;u+=R;let k=u,N=s.length*Oo;u+=N;let S=u,L=o.length*Po;u+=L;let j=u,w=i.length*Fo;u+=w;let O=u,D=n.length*Ro;u+=D;let U=u,F=l.map(T=>{let P=u;return T.offset=P,u+=4+T.items.length*4,P}),z=n.reduce((T,P)=>(P.classData.constructorMethods.forEach(H=>{let[,q,Z]=H;(q&ar)===0&&Z>=0&&(H.push(u),T.push({offset:u,superConstructor:Z}),u+=jd)}),T),[]);a.forEach(T=>{T.offset=u,u+=16+T.methods.length*8});let X=r.map(T=>{u=sr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),te=c.map(T=>{u=sr(u,4);let P=u;return T.offset=P,u+=4+2*T.types.length,P}),ae=[],Q=f.map(T=>{let P=u,B=m.from(me(T.length)),H=m.from(T,"utf8"),q=m.concat([B,H,Rd]);return ae.push(q),u+=q.length,P}),ie=z.map(T=>{let P=u;return u+=zo.length,P}),Y=d.map(T=>{let P=Fd(T);return T.offset=u,u+=P.length,P}),ne=n.map((T,P)=>{T.classData.offset=u;let B=Pd(T);return u+=B.length,B}),Se=0,Xe=0;u=sr(u,4);let $=u,he=r.length+c.length,Te=4+(o.length>0?1:0)+2+l.length+z.length+a.length+(he>0?1:0)+1+ie.length+d.length+n.length+1,Re=4+Te*Bo;u+=Re;let ke=u-U,Je=u,I=m.alloc(Je);I.write(`dex +035`),I.writeUInt32LE(Je,32),I.writeUInt32LE(E,36),I.writeUInt32LE(fd,40),I.writeUInt32LE(Se,44),I.writeUInt32LE(Xe,48),I.writeUInt32LE($,52),I.writeUInt32LE(f.length,56),I.writeUInt32LE(C,60),I.writeUInt32LE(p.length,64),I.writeUInt32LE(M,68),I.writeUInt32LE(s.length,72),I.writeUInt32LE(k,76),I.writeUInt32LE(o.length,80),I.writeUInt32LE(o.length>0?S:0,84),I.writeUInt32LE(i.length,88),I.writeUInt32LE(j,92),I.writeUInt32LE(n.length,96),I.writeUInt32LE(O,100),I.writeUInt32LE(ke,104),I.writeUInt32LE(U,108),Q.forEach((T,P)=>{I.writeUInt32LE(T,C+P*Uo)}),p.forEach((T,P)=>{I.writeUInt32LE(T,M+P*Do)}),s.forEach((T,P)=>{let[B,H,q]=T,Z=k+P*Oo;I.writeUInt32LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q!==null?q.offset:0,Z+8)}),o.forEach((T,P)=>{let[B,H,q]=T,Z=S+P*Po;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),i.forEach((T,P)=>{let[B,H,q]=T,Z=j+P*Fo;I.writeUInt16LE(B,Z),I.writeUInt16LE(H,Z+2),I.writeUInt32LE(q,Z+4)}),n.forEach((T,P)=>{let{interfaces:B,annotationsDirectory:H}=T,q=B!==null?B.offset:0,Z=H!==null?H.offset:0,et=0,ge=O+P*Ro;I.writeUInt32LE(T.index,ge),I.writeUInt32LE(T.accessFlags,ge+4),I.writeUInt32LE(T.superClassIndex,ge+8),I.writeUInt32LE(q,ge+12),I.writeUInt32LE(T.sourceFileIndex,ge+16),I.writeUInt32LE(Z,ge+20),I.writeUInt32LE(T.classData.offset,ge+24),I.writeUInt32LE(et,ge+28)}),l.forEach((T,P)=>{let{items:B}=T,H=F[P];I.writeUInt32LE(B.length,H),B.forEach((q,Z)=>{I.writeUInt32LE(q.offset,H+4+Z*4)})}),z.forEach((T,P)=>{let{offset:B,superConstructor:H}=T,q=1,Z=1,et=1,ge=0,bt=4;I.writeUInt16LE(q,B),I.writeUInt16LE(Z,B+2),I.writeUInt16LE(et,B+4),I.writeUInt16LE(ge,B+6),I.writeUInt32LE(ie[P],B+8),I.writeUInt32LE(bt,B+12),I.writeUInt16LE(4208,B+16),I.writeUInt16LE(H,B+18),I.writeUInt16LE(0,B+20),I.writeUInt16LE(14,B+22)}),a.forEach(T=>{let P=T.offset,B=0,H=0,q=T.methods.length,Z=0;I.writeUInt32LE(B,P),I.writeUInt32LE(H,P+4),I.writeUInt32LE(q,P+8),I.writeUInt32LE(Z,P+12),T.methods.forEach((et,ge)=>{let bt=P+16+ge*8,[fi,hi]=et;I.writeUInt32LE(fi,bt),I.writeUInt32LE(hi.offset,bt+4)})}),r.forEach((T,P)=>{let B=X[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),c.forEach((T,P)=>{let B=te[P];I.writeUInt32LE(T.types.length,B),T.types.forEach((H,q)=>{I.writeUInt16LE(H,B+4+q*2)})}),ae.forEach((T,P)=>{T.copy(I,Q[P])}),ie.forEach(T=>{zo.copy(I,T)}),Y.forEach((T,P)=>{T.copy(I,d[P].offset)}),ne.forEach((T,P)=>{T.copy(I,n[P].classData.offset)}),I.writeUInt32LE(Te,$);let ce=[[hd,1,_],[_d,f.length,C],[md,p.length,M],[gd,s.length,k]];o.length>0&&ce.push([bd,o.length,S]),ce.push([yd,i.length,j]),ce.push([Ed,n.length,O]),l.forEach((T,P)=>{ce.push([wd,T.items.length,F[P]])}),z.forEach(T=>{ce.push([Cd,1,T.offset])}),a.forEach(T=>{ce.push([xd,1,T.offset])}),he>0&&ce.push([Sd,he,X.concat(te)[0]]),ce.push([Td,f.length,Q[0]]),ie.forEach(T=>{ce.push([Ad,1,T])}),d.forEach(T=>{ce.push([Ld,1,T.offset])}),n.forEach(T=>{ce.push([Id,1,T.classData.offset])}),ce.push([vd,1,$]),ce.forEach((T,P)=>{let[B,H,q]=T,Z=$+4+P*Bo;I.writeUInt16LE(B,Z),I.writeUInt32LE(H,Z+4),I.writeUInt32LE(q,Z+8)});let Ir=new Checksum("sha1");return Ir.update(I.slice(g+b)),m.from(Ir.getDigest()).copy(I,g),I.writeUInt32LE(Gd(I,g),h),I}};function Pd(t){let{instanceFields:e,constructorMethods:n,virtualMethods:r}=t.classData;return m.from([0].concat(me(e.length)).concat(me(n.length)).concat(me(r.length)).concat(e.reduce((i,[s,c])=>i.concat(me(s)).concat(me(c)),[])).concat(n.reduce((i,[s,c,,a])=>i.concat(me(s)).concat(me(c)).concat(me(a||0)),[])).concat(r.reduce((i,[s,c])=>i.concat(me(s)).concat(me(c)).concat([0]),[])))}function Fd(t){let{thrownTypes:e}=t;return m.from([Md].concat(me(t.type)).concat([1]).concat(me(t.value)).concat([kd,e.length]).concat(e.reduce((n,r)=>(n.push(Nd,r),n),[])))}function Dd(t){let e=new Set,n=new Set,r={},o=[],i=[],s={},c=new Set,a=new Set;t.forEach(w=>{let{name:O,superClass:D,sourceFileName:U}=w;e.add("this"),e.add(O),n.add(O),e.add(D),n.add(D),e.add(U),w.interfaces.forEach(F=>{e.add(F),n.add(F)}),w.fields.forEach(F=>{let[z,X]=F;e.add(z),e.add(X),n.add(X),o.push([w.name,X,z])}),w.methods.some(([F])=>F==="")||(w.methods.unshift(["","V",[]]),c.add(O)),w.methods.forEach(F=>{let[z,X,te,ae=[],Q]=F;e.add(z);let ie=l(X,te),Y=null;if(ae.length>0){let ne=ae.slice();ne.sort(),Y=ne.join("|");let Se=s[Y];Se===void 0&&(Se={id:Y,types:ne},s[Y]=Se),e.add(ir),n.add(ir),ae.forEach(Xe=>{e.add(Xe),n.add(Xe)}),e.add("value")}if(i.push([w.name,ie,z,Y,Q]),z===""){a.add(O+"|"+ie);let ne=D+"|"+ie;c.has(O)&&!a.has(ne)&&(i.push([D,ie,z,null,0]),a.add(ne))}})});function l(w,O){let D=[w].concat(O),U=D.join("|");if(r[U]!==void 0)return U;e.add(w),n.add(w),O.forEach(z=>{e.add(z),n.add(z)});let F=D.map(Jd).join("");return e.add(F),r[U]=[U,F,w,O],U}let d=Array.from(e);d.sort();let p=d.reduce((w,O,D)=>(w[O]=D,w),{}),f=Array.from(n).map(w=>p[w]);f.sort(Vo);let u=f.reduce((w,O,D)=>(w[d[O]]=D,w),{}),_=Object.keys(r).map(w=>r[w]);_.sort(Bd);let h={},g=_.map(w=>{let[,O,D,U]=w,F;if(U.length>0){let z=U.join("|");F=h[z],F===void 0&&(F={types:U.map(X=>u[X]),offset:-1},h[z]=F)}else F=null;return[p[O],u[D],F]}),b=_.reduce((w,O,D)=>{let[U]=O;return w[U]=D,w},{}),E=Object.keys(h).map(w=>h[w]),C=o.map(w=>{let[O,D,U]=w;return[u[O],u[D],p[U]]});C.sort(zd);let A=i.map(w=>{let[O,D,U,F,z]=w;return[u[O],b[D],p[U],F,z]});A.sort(Vd);let M=Object.keys(s).map(w=>s[w]).map(w=>({id:w.id,type:u[ir],value:p.value,thrownTypes:w.types.map(O=>u[O]),offset:-1})),R=M.map(w=>({id:w.id,items:[w],offset:-1})),k=R.reduce((w,O,D)=>(w[O.id]=D,w),{}),N={},S=[],L=t.map(w=>{let O=u[w.name],D=_t,U=u[w.superClass],F,z=w.interfaces.map($=>u[$]);if(z.length>0){z.sort(Vo);let $=z.join("|");F=N[$],F===void 0&&(F={types:z,offset:-1},N[$]=F)}else F=null;let X=p[w.sourceFileName],te=A.reduce(($,he,Te)=>{let[Re,ke,Je,I,ce]=he;return Re===O&&$.push([Te,Je,I,ke,ce]),$},[]),ae=null,Q=te.filter(([,,$])=>$!==null).map(([$,,he])=>[$,R[k[he]]]);Q.length>0&&(ae={methods:Q,offset:-1},S.push(ae));let ie=C.reduce(($,he,Te)=>{let[Re]=he;return Re===O&&$.push([Te>0?1:0,_t]),$},[]),Y=p[""],ne=te.filter(([,$])=>$===Y).map(([$,,,he])=>{if(c.has(w.name)){let Te=-1,Re=A.length;for(let ke=0;ke!==Re;ke++){let[Je,I,ce]=A[ke];if(Je===U&&ce===Y&&I===he){Te=ke;break}}return[$,_t|jo,Te]}else return[$,_t|jo|ar,-1]}),Se=Ud(te.filter(([,$])=>$!==Y).map(([$,,,,he])=>[$,he|_t|ar]));return{index:O,accessFlags:D,superClassIndex:U,interfaces:F,sourceFileIndex:X,annotationsDirectory:ae,classData:{instanceFields:ie,constructorMethods:ne,virtualMethods:Se,offset:-1}}}),j=Object.keys(N).map(w=>N[w]);return{classes:L,interfaces:j,fields:C,methods:A,protos:g,parameters:E,annotationDirectories:S,annotationSets:R,throwsAnnotations:M,types:f,strings:d}}function Ud(t){let e=0;return t.map(([n,r],o)=>{let i;return o===0?i=[n,r]:i=[n-e,r],e=n,i})}function Vo(t,e){return t-e}function Bd(t,e){let[,,n,r]=t,[,,o,i]=e;if(no)return 1;let s=r.join("|"),c=i.join("|");return sc?1:0}function zd(t,e){let[n,r,o]=t,[i,s,c]=e;return n!==i?n-i:o!==c?o-c:r-s}function Vd(t,e){let[n,r,o]=t,[i,s,c]=e;return n!==i?n-i:o!==c?o-c:r-s}function Jd(t){let e=t[0];return e==="L"||e==="["?"L":t}function me(t){if(t<=127)return[t];let e=[],n=!1;do{let r=t&127;t>>=7,n=t!==0,n&&(r|=128),e.push(r)}while(n);return e}function sr(t,e){let n=t%e;return n===0?t:t+e-n}function Gd(t,e){let n=1,r=0,o=t.length;for(let i=e;i>>0}var Jo=Od;var $d=1,lr=null,Go=null;function $o(t){lr=t}function dr(t,e,n){let r=Ke(t);return r===null&&(t.indexOf("[")===0?r=ur(t,e,n):(t[0]==="L"&&t[t.length-1]===";"&&(t=t.substring(1,t.length-1)),r=Zd(t,e,n))),Object.assign({className:t},r)}var Ho={boolean:{name:"Z",type:"uint8",size:1,byteSize:1,defaultValue:!1,isCompatible(t){return typeof t=="boolean"},fromJni(t){return!!t},toJni(t){return t?1:0},read(t){return t.readU8()},write(t,e){t.writeU8(e)},toString(){return this.name}},byte:{name:"B",type:"int8",size:1,byteSize:1,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-128&&t<=127},fromJni:ve,toJni:ve,read(t){return t.readS8()},write(t,e){t.writeS8(e)},toString(){return this.name}},char:{name:"C",type:"uint16",size:1,byteSize:2,defaultValue:0,isCompatible(t){if(typeof t!="string"||t.length!==1)return!1;let e=t.charCodeAt(0);return e>=0&&e<=65535},fromJni(t){return String.fromCharCode(t)},toJni(t){return t.charCodeAt(0)},read(t){return t.readU16()},write(t,e){t.writeU16(e)},toString(){return this.name}},short:{name:"S",type:"int16",size:1,byteSize:2,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-32768&&t<=32767},fromJni:ve,toJni:ve,read(t){return t.readS16()},write(t,e){t.writeS16(e)},toString(){return this.name}},int:{name:"I",type:"int32",size:1,byteSize:4,defaultValue:0,isCompatible(t){return Number.isInteger(t)&&t>=-2147483648&&t<=2147483647},fromJni:ve,toJni:ve,read(t){return t.readS32()},write(t,e){t.writeS32(e)},toString(){return this.name}},long:{name:"J",type:"int64",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"||t instanceof Int64},fromJni:ve,toJni:ve,read(t){return t.readS64()},write(t,e){t.writeS64(e)},toString(){return this.name}},float:{name:"F",type:"float",size:1,byteSize:4,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readFloat()},write(t,e){t.writeFloat(e)},toString(){return this.name}},double:{name:"D",type:"double",size:2,byteSize:8,defaultValue:0,isCompatible(t){return typeof t=="number"},fromJni:ve,toJni:ve,read(t){return t.readDouble()},write(t,e){t.writeDouble(e)},toString(){return this.name}},void:{name:"V",type:"void",size:0,byteSize:0,defaultValue:void 0,isCompatible(t){return t===void 0},fromJni(){},toJni(){return NULL},toString(){return this.name}}},Hd=new Set(Object.values(Ho).map(t=>t.name));function Ke(t){let e=Ho[t];return e!==void 0?e:null}function Zd(t,e,n){let r=n._types[e?1:0],o=r[t];return o!==void 0||(t==="java.lang.Object"?o=qd(n):o=Wd(t,e,n),r[t]=o),o}function qd(t){return{name:"Ljava/lang/Object;",type:"pointer",size:1,defaultValue:NULL,isCompatible(e){return e===null?!0:e===void 0?!1:e.$h instanceof NativePointer?!0:typeof e=="string"},fromJni(e,n,r){return e.isNull()?null:t.cast(e,t.use("java.lang.Object"),r)},toJni(e,n){return e===null?NULL:typeof e=="string"?n.newStringUtf(e):e.$h}}}function Wd(t,e,n){let r=null,o=null,i=null;function s(){return r===null&&(r=n.use(t).class),r}function c(l){let d=s();return o===null&&(o=d.isInstance.overload("java.lang.Object")),o.call(d,l)}function a(){if(i===null){let l=s();i=n.use("java.lang.String").class.isAssignableFrom(l)}return i}return{name:Be(t),type:"pointer",size:1,defaultValue:NULL,isCompatible(l){return l===null?!0:l===void 0?!1:l.$h instanceof NativePointer?c(l):typeof l=="string"&&a()},fromJni(l,d,p){return l.isNull()?null:a()&&e?d.stringFromJni(l):n.cast(l,n.use(t),p)},toJni(l,d){return l===null?NULL:typeof l=="string"?d.newStringUtf(l):l.$h},toString(){return this.name}}}var Kd=[["Z","boolean"],["B","byte"],["C","char"],["D","double"],["F","float"],["I","int"],["J","long"],["S","short"]].reduce((t,[e,n])=>(t["["+e]=Qd("["+e,n),t),{});function Qd(t,e){let n=y.prototype,r=nu(e),o={typeName:e,newArray:n["new"+r+"Array"],setRegion:n["set"+r+"ArrayRegion"],getElements:n["get"+r+"ArrayElements"],releaseElements:n["release"+r+"ArrayElements"]};return{name:t,type:"pointer",size:1,defaultValue:NULL,isCompatible(i){return tu(i,e)},fromJni(i,s,c){return Xd(i,o,s,c)},toJni(i,s){return eu(i,o,s)}}}function ur(t,e,n){let r=Kd[t];if(r!==void 0)return r;if(t.indexOf("[")!==0)throw new Error("Unsupported type: "+t);let o=t.substring(1),i=dr(o,e,n),s=0,c=o.length;for(;s!==c&&o[s]==="[";)s++;o=o.substring(s),o[0]==="L"&&o[o.length-1]===";"&&(o=o.substring(1,o.length-1));let a=o.replace(/\./g,"/");Hd.has(a)?a="[".repeat(s)+a:a="[".repeat(s)+"L"+a+";";let l="["+a;return o="[".repeat(s)+o,{name:t.replace(/\./g,"/"),type:"pointer",size:1,defaultValue:NULL,isCompatible(d){return d===null?!0:typeof d!="object"||d.length===void 0?!1:d.every(function(p){return i.isCompatible(p)})},fromJni(d,p,f){if(d.isNull())return null;let u=[],_=p.getArrayLength(d);for(let h=0;h!==_;h++){let g=p.getObjectArrayElement(d,h);try{u.push(i.fromJni(g,p))}finally{p.deleteLocalRef(g)}}try{u.$w=n.cast(d,n.use(l),f)}catch{n.use("java.lang.reflect.Array").newInstance(n.use(o).class,0),u.$w=n.cast(d,n.use(l),f)}return u.$dispose=Yd,u},toJni(d,p){if(d===null)return NULL;if(!(d instanceof Array))throw new Error("Expected an array");let f=d.$w;if(f!==void 0)return f.$h;let u=d.length,h=n.use(o).$borrowClassHandle(p);try{let g=p.newObjectArray(u,h.value,NULL);p.throwIfExceptionPending();for(let b=0;b!==u;b++){let E=i.toJni(d[b],p);try{p.setObjectArrayElement(g,b,E)}finally{i.type==="pointer"&&p.getObjectRefType(E)===$d&&p.deleteLocalRef(E)}p.throwIfExceptionPending()}return g}finally{h.unref(p)}}}}function Yd(){let t=this.length;for(let e=0;e!==t;e++){let n=this[e];if(n===null)continue;let r=n.$dispose;if(r===void 0)break;r.call(n)}this.$w.$dispose()}function Xd(t,e,n,r){if(t.isNull())return null;let o=Ke(e.typeName),i=n.getArrayLength(t);return new Bt(t,e,o,i,n,r)}function eu(t,e,n){if(t===null)return NULL;let r=t.$h;if(r!==void 0)return r;let o=t.length,i=Ke(e.typeName),s=e.newArray.call(n,o);if(s.isNull())throw new Error("Unable to construct array");if(o>0){let c=i.byteSize,a=i.write,l=i.toJni,d=Memory.alloc(o*i.byteSize);for(let p=0;p!==o;p++)a(d.add(p*c),l(t[p]));e.setRegion.call(n,s,0,o,d),n.throwIfExceptionPending()}return s}function tu(t,e){if(t===null)return!0;if(t instanceof Bt)return t.$s.typeName===e;if(!(typeof t=="object"&&t.length!==void 0))return!1;let r=Ke(e);return Array.prototype.every.call(t,o=>r.isCompatible(o))}function Bt(t,e,n,r,o,i=!0){if(i){let s=o.newGlobalRef(t);this.$h=s,this.$r=Script.bindWeak(this,o.vm.makeHandleDestructor(s))}else this.$h=t,this.$r=null;return this.$s=e,this.$t=n,this.length=r,new Proxy(this,Go)}Go={has(t,e){return e in t?!0:t.tryParseIndex(e)!==null},get(t,e,n){let r=t.tryParseIndex(e);return r===null?t[e]:t.readElement(r)},set(t,e,n,r){let o=t.tryParseIndex(e);return o===null?(t[e]=n,!0):(t.writeElement(o,n),!0)},ownKeys(t){let e=[],{length:n}=t;for(let r=0;r!==n;r++){let o=r.toString();e.push(o)}return e.push("length"),e},getOwnPropertyDescriptor(t,e){return t.tryParseIndex(e)!==null?{writable:!0,configurable:!0,enumerable:!0}:Object.getOwnPropertyDescriptor(t,e)}};Object.defineProperties(Bt.prototype,{$dispose:{enumerable:!0,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t))}},$clone:{value(t){return new Bt(this.$h,this.$s,this.$t,this.length,t)}},tryParseIndex:{value(t){if(typeof t=="symbol")return null;let e=parseInt(t);return isNaN(e)||e<0||e>=this.length?null:e}},readElement:{value(t){return this.withElements(e=>{let n=this.$t;return n.fromJni(n.read(e.add(t*n.byteSize)))})}},writeElement:{value(t,e){let{$h:n,$s:r,$t:o}=this,i=lr.getEnv(),s=Memory.alloc(o.byteSize);o.write(s,o.toJni(e)),r.setRegion.call(i,n,t,1,s)}},withElements:{value(t){let{$h:e,$s:n}=this,r=lr.getEnv(),o=n.getElements.call(r,e);if(o.isNull())throw new Error("Unable to get array elements");try{return t(o)}finally{n.releaseElements.call(r,e,o)}}},toJSON:{value(){let{length:t,$t:e}=this,{byteSize:n,fromJni:r,read:o}=e;return this.withElements(i=>{let s=[];for(let c=0;c!==t;c++){let a=r(o(i.add(c*n)));s.push(a)}return s})}},toString:{value(){return this.toJSON().toString()}}});function Be(t){return"L"+t.replace(/\./g,"/")+";"}function nu(t){return t.charAt(0).toUpperCase()+t.slice(1)}function ve(t){return t}var ru=4,{ensureClassInitialized:Zo,makeMethodMangler:Xo}=Dt,ou=8,hr=1,gt=2,Ne=3,pr=1,_r=2,zt=1,ei=2,qo=Symbol("PENDING_USE"),Wo="/data/local/tmp",{getCurrentThreadId:Jt,pointerSize:mt}=Process,ue={state:"empty",factories:[],loaders:null,Integer:null},G=null,K=null,ti=null,ni=null,ri=null,oi=null,ii=null,Ko=null,fr=null,Ye=new Map,je=class t{static _initialize(e,n){G=e,K=n,ti=n.flavor==="art",n.flavor==="jvm"&&(Zo=To,Xo=Lo)}static _disposeAll(e){ue.factories.forEach(n=>{n._dispose(e)})}static get(e){let n=Iu(),r=n.factories[0];if(e===null)return r;let o=n.loaders.get(e);if(o!==null){let s=r.cast(o,n.Integer);return n.factories[s.intValue()]}let i=new t;return i.loader=e,i.cacheDir=r.cacheDir,br(i,e),i}constructor(){this.cacheDir=Wo,this.codeCacheDir=Wo+"/dalvik-cache",this.tempFileNaming={prefix:"frida",suffix:""},this._classes={},this._classHandles=new ht(10,su),this._patchedMethods=new Set,this._loader=null,this._types=[{},{}],ue.factories.push(this)}_dispose(e){Array.from(this._patchedMethods).forEach(n=>{n.implementation=null}),this._patchedMethods.clear(),Wn(),this._classHandles.dispose(e),this._classes={}}get loader(){return this._loader}set loader(e){let n=this._loader===null&&e!==null;this._loader=e,n&&ue.state==="ready"&&this===ue.factories[0]&&br(this,e)}use(e,n={}){let r=n.cache!=="skip",o=r?this._getUsedClass(e):void 0;if(o===void 0)try{let i=G.getEnv(),{_loader:s}=this,c=s!==null?cu(e,s,i):au(e);o=this._make(e,c,i)}finally{r&&this._setUsedClass(e,o)}return o}_getUsedClass(e){let n;for(;(n=this._classes[e])===qo;)Thread.sleep(.05);return n===void 0&&(this._classes[e]=qo),n}_setUsedClass(e,n){n!==void 0?this._classes[e]=n:delete this._classes[e]}_make(e,n,r){let o=iu(),i=Object.create(Er.prototype,{[Symbol.for("n")]:{value:e},$n:{get(){return this[Symbol.for("n")]}},[Symbol.for("C")]:{value:o},$C:{get(){return this[Symbol.for("C")]}},[Symbol.for("w")]:{value:null,writable:!0},$w:{get(){return this[Symbol.for("w")]},set(a){this[Symbol.for("w")]=a}},[Symbol.for("_s")]:{writable:!0},$_s:{get(){return this[Symbol.for("_s")]},set(a){this[Symbol.for("_s")]=a}},[Symbol.for("c")]:{value:[null]},$c:{get(){return this[Symbol.for("c")]}},[Symbol.for("m")]:{value:new Map},$m:{get(){return this[Symbol.for("m")]}},[Symbol.for("l")]:{value:null,writable:!0},$l:{get(){return this[Symbol.for("l")]},set(a){this[Symbol.for("l")]=a}},[Symbol.for("gch")]:{value:n},$gch:{get(){return this[Symbol.for("gch")]}},[Symbol.for("f")]:{value:this},$f:{get(){return this[Symbol.for("f")]}}});o.prototype=i;let s=new o(null);i[Symbol.for("w")]=s,i.$w=s;let c=s.$borrowClassHandle(r);try{let a=c.value;Zo(r,a),i.$l=Ue.build(a,r)}finally{c.unref(r)}return s}retain(e){let n=G.getEnv();return e.$clone(n)}cast(e,n,r){let o=G.getEnv(),i=e.$h;i===void 0&&(i=e);let s=n.$borrowClassHandle(o);try{if(!o.isInstanceOf(i,s.value))throw new Error(`Cast from '${o.getObjectClassName(i)}' to '${n.$n}' isn't possible`)}finally{s.unref(o)}let c=n.$C;return new c(i,zt,o,r)}wrap(e,n,r){let o=n.$C,i=new o(e,zt,r,!1);return i.$r=Script.bindWeak(i,G.makeHandleDestructor(e)),i}array(e,n){let r=G.getEnv(),o=Ke(e);o!==null&&(e=o.name);let i=ur("["+e,!1,this),s=i.toJni(n,r);return i.fromJni(s,r,!0)}registerClass(e){let n=G.getEnv(),r=[];try{let o=this.use("java.lang.Class"),i=n.javaLangReflectMethod(),s=n.vaMethod("pointer",[]),c=e.name,a=e.implements||[],l=e.superClass||this.use("java.lang.Object"),d=[],p=[],f={name:Be(c),sourceFileName:Tu(c),superClass:Be(l.$n),interfaces:a.map(S=>Be(S.$n)),fields:d,methods:p},u=a.slice();a.forEach(S=>{Array.prototype.slice.call(S.class.getInterfaces()).forEach(L=>{let j=this.cast(L,o).getCanonicalName();u.push(this.use(j))})});let _=e.fields||{};Object.getOwnPropertyNames(_).forEach(S=>{let L=this._getType(_[S]);d.push([S,L.name])});let h={},g={};u.forEach(S=>{let L=S.$borrowClassHandle(n);r.push(L);let j=L.value;S.$ownMembers.filter(w=>S[w].overloads!==void 0).forEach(w=>{let O=S[w],D=O.overloads,U=D.map(F=>Qo(w,F.returnType,F.argumentTypes));h[w]=[O,U,j],D.forEach((F,z)=>{let X=U[z];g[X]=[F,j]})})});let b=e.methods||{},C=Object.keys(b).reduce((S,L)=>{let j=b[L],w=L==="$init"?"":L;return j instanceof Array?S.push(...j.map(O=>[w,O])):S.push([w,j]),S},[]),A=[];C.forEach(([S,L])=>{let j=Ne,w,O,D=[],U;if(typeof L=="function"){let te=h[S];if(te!==void 0&&Array.isArray(te)){let[ae,Q,ie]=te;if(Q.length>1)throw new Error(`More than one overload matching '${S}': signature must be specified`);delete g[Q[0]];let Y=ae.overloads[0];j=Y.type,w=Y.returnType,O=Y.argumentTypes,U=L;let ne=n.toReflectedMethod(ie,Y.handle,0),Se=s(n.handle,ne,i.getGenericExceptionTypes);D=yr(n,Se).map(Be),n.deleteLocalRef(Se),n.deleteLocalRef(ne)}else w=this._getType("void"),O=[],U=L}else{if(L.isStatic&&(j=gt),w=this._getType(L.returnType||"void"),O=(L.argumentTypes||[]).map(Q=>this._getType(Q)),U=L.implementation,typeof U!="function")throw new Error("Expected a function implementation for method: "+S);let te=Qo(S,w,O),ae=g[te];if(ae!==void 0){let[Q,ie]=ae;delete g[te],j=Q.type,w=Q.returnType,O=Q.argumentTypes;let Y=n.toReflectedMethod(ie,Q.handle,0),ne=s(n.handle,Y,i.getGenericExceptionTypes);D=yr(n,ne).map(Be),n.deleteLocalRef(ne),n.deleteLocalRef(Y)}}let F=w.name,z=O.map(te=>te.name),X="("+z.join("")+")"+F;p.push([S,F,z,D,j===gt?ou:0]),A.push([S,X,j,w,O,U])});let M=Object.keys(g);if(M.length>0)throw new Error("Missing implementation for: "+M.join(", "));let R=Vt.fromBuffer(Jo(f),this);try{R.load()}finally{R.file.delete()}let k=this.use(e.name),N=C.length;if(N>0){let S=3*mt,L=Memory.alloc(N*S),j=[],w=[];A.forEach(([U,F,z,X,te,ae],Q)=>{let ie=Memory.allocUtf8String(U),Y=Memory.allocUtf8String(F),ne=si(U,k,z,X,te,ae);L.add(Q*S).writePointer(ie),L.add(Q*S+mt).writePointer(Y),L.add(Q*S+2*mt).writePointer(ne),w.push(ie,Y),j.push(ne)});let O=k.$borrowClassHandle(n);r.push(O);let D=O.value;n.registerNatives(D,L,N),n.throwIfExceptionPending(),k.$nativeMethods=j}return k}finally{r.forEach(o=>{o.unref(n)})}}choose(e,n){let r=G.getEnv(),{flavor:o}=K;if(o==="jvm")this._chooseObjectsJvm(e,r,n);else if(o==="art"){let i=K["art::gc::Heap::VisitObjects"]===void 0;if(i&&K["art::gc::Heap::GetInstances"]===void 0)return this._chooseObjectsJvm(e,r,n);ye(G,r,s=>{i?this._chooseObjectsArtPreA12(e,r,s,n):this._chooseObjectsArtLegacy(e,r,s,n)})}else this._chooseObjectsDalvik(e,r,n)}_chooseObjectsJvm(e,n,r){let o=this.use(e),{jvmti:i}=K,s=1,c=3,a=o.$borrowClassHandle(n),l=int64(a.value.toString());try{let d=new NativeCallback((b,E,C,A)=>(C.writeS64(l),s),"int",["int64","int64","pointer","pointer"]);i.iterateOverInstancesOfClass(a.value,c,d,a.value);let p=Memory.alloc(8);p.writeS64(l);let f=Memory.alloc(ru),u=Memory.alloc(mt);i.getObjectsWithTags(1,p,f,u,NULL);let _=f.readS32(),h=u.readPointer(),g=[];for(let b=0;b!==_;b++)g.push(h.add(b*mt).readPointer());i.deallocate(h);try{for(let b of g){let E=this.cast(b,o);if(r.onMatch(E)==="stop")break}r.onComplete()}finally{g.forEach(b=>{n.deleteLocalRef(b)})}}finally{a.unref(n)}}_chooseObjectsArtPreA12(e,n,r,o){let i=this.use(e),s=dt.$new(r,G),c,a=i.$borrowClassHandle(n);try{let f=K["art::JavaVMExt::DecodeGlobal"](K.vm,r,a.value);c=s.newHandle(f)}finally{a.unref(n)}let l=0,d=lt.$new();K["art::gc::Heap::GetInstances"](K.artHeap,s,c,l,d);let p=d.handles.map(f=>n.newGlobalRef(f));d.$delete(),s.$delete();try{for(let f of p){let u=this.cast(f,i);if(o.onMatch(u)==="stop")break}o.onComplete()}finally{p.forEach(f=>{n.deleteGlobalRef(f)})}}_chooseObjectsArtLegacy(e,n,r,o){let i=this.use(e),s=[],c=K["art::JavaVMExt::AddGlobalRef"],a=K.vm,l,d=i.$borrowClassHandle(n);try{l=K["art::JavaVMExt::DecodeGlobal"](a,r,d.value).toInt32()}finally{d.unref(n)}let p=tr(l,f=>{s.push(c(a,r,f))});K["art::gc::Heap::VisitObjects"](K.artHeap,p,NULL);try{for(let f of s){let u=this.cast(f,i);if(o.onMatch(u)==="stop")break}}finally{s.forEach(f=>{n.deleteGlobalRef(f)})}o.onComplete()}_chooseObjectsDalvik(e,n,r){let o=this.use(e);if(K.addLocalReference===null){let s=Process.getModuleByName("libdvm.so"),c;switch(Process.arch){case"arm":c="2d e9 f0 41 05 46 15 4e 0c 46 7e 44 11 b3 43 68";break;case"ia32":c="8d 64 24 d4 89 5c 24 1c 89 74 24 20 e8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 85 d2";break}Memory.scan(s.base,s.size,c,{onMatch:(a,l)=>{let d;if(Process.arch==="arm")a=a.or(1),d=new NativeFunction(a,"pointer",["pointer","pointer"]);else{let p=Memory.alloc(Process.pageSize);Memory.patchCode(p,16,f=>{let u=new X86Writer(f,{pc:p});u.putMovRegRegOffsetPtr("eax","esp",4),u.putMovRegRegOffsetPtr("edx","esp",8),u.putJmpAddress(a),u.flush()}),d=new NativeFunction(p,"pointer",["pointer","pointer"]),d._thunk=p}return K.addLocalReference=d,G.perform(p=>{i(this,p)}),"stop"},onError(a){},onComplete(){K.addLocalReference===null&&r.onComplete()}})}else i(this,n);function i(s,c){let{DVM_JNI_ENV_OFFSET_SELF:a}=Dt,l=c.handle.add(a).readPointer(),d,p=o.$borrowClassHandle(c);try{d=K.dvmDecodeIndirectRef(l,p.value)}finally{p.unref(c)}let f=d.toMatchPattern(),u=K.dvmHeapSourceGetBase(),h=K.dvmHeapSourceGetLimit().sub(u).toInt32();Memory.scan(u,h,f,{onMatch:(g,b)=>{K.dvmIsValidObject(g)&&G.perform(E=>{let C=E.handle.add(a).readPointer(),A,M=K.addLocalReference(C,g);try{A=s.cast(M,o)}finally{E.deleteLocalRef(M)}if(r.onMatch(A)==="stop")return"stop"})},onError(g){},onComplete(){r.onComplete()}})}}openClassFile(e){return new Vt(e,null,this)}_getType(e,n=!0){return dr(e,n,this)}};function iu(){return function(t,e,n,r){return Er.call(this,t,e,n,r)}}function Er(t,e,n,r=!0){if(t!==null)if(r){let o=n.newGlobalRef(t);this.$h=o,this.$r=Script.bindWeak(this,G.makeHandleDestructor(o))}else this.$h=t,this.$r=null;else this.$h=null,this.$r=null;return this.$t=e,new Proxy(this,ni)}ni={has(t,e){return e in t?!0:t.$has(e)},get(t,e,n){if(typeof e!="string"||e.startsWith("$")||e==="class")return t[e];let r=t.$find(e);return r!==null?r(n):t[e]},set(t,e,n,r){return t[e]=n,!0},ownKeys(t){return t.$list()},getOwnPropertyDescriptor(t,e){return Object.prototype.hasOwnProperty.call(t,e)?Object.getOwnPropertyDescriptor(t,e):{writable:!1,configurable:!0,enumerable:!0}}};Object.defineProperties(Er.prototype,{[Symbol.for("new")]:{enumerable:!1,get(){return this.$getCtor("allocAndInit")}},$new:{enumerable:!0,get(){return this[Symbol.for("new")]}},[Symbol.for("alloc")]:{enumerable:!1,value(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=t.allocObject(e.value);return this.$f.cast(n,this)}finally{e.unref(t)}}},$alloc:{enumerable:!0,get(){return this[Symbol.for("alloc")]}},[Symbol.for("init")]:{enumerable:!1,get(){return this.$getCtor("initOnly")}},$init:{enumerable:!0,get(){return this[Symbol.for("init")]}},[Symbol.for("dispose")]:{enumerable:!1,value(){let t=this.$r;t!==null&&(this.$r=null,Script.unbindWeak(t)),this.$h!==null&&(this.$h=void 0)}},$dispose:{enumerable:!0,get(){return this[Symbol.for("dispose")]}},[Symbol.for("clone")]:{enumerable:!1,value(t){let e=this.$C;return new e(this.$h,this.$t,t)}},$clone:{value(t){return this[Symbol.for("clone")](t)}},[Symbol.for("class")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$borrowClassHandle(t);try{let n=this.$f;return n.cast(e.value,n.use("java.lang.Class"))}finally{e.unref(t)}}},class:{enumerable:!0,get(){return this[Symbol.for("class")]}},[Symbol.for("className")]:{enumerable:!1,get(){let t=this.$h;return t===null?this.$n:G.getEnv().getObjectClassName(t)}},$className:{enumerable:!0,get(){return this[Symbol.for("className")]}},[Symbol.for("ownMembers")]:{enumerable:!1,get(){return this.$l.list()}},$ownMembers:{enumerable:!0,get(){return this[Symbol.for("ownMembers")]}},[Symbol.for("super")]:{enumerable:!1,get(){let t=G.getEnv(),e=this.$s.$C;return new e(this.$h,ei,t)}},$super:{enumerable:!0,get(){return this[Symbol.for("super")]}},[Symbol.for("s")]:{enumerable:!1,get(){let t=Object.getPrototypeOf(this),e=t.$_s;if(e===void 0){let n=G.getEnv(),r=this.$borrowClassHandle(n);try{let o=n.getSuperclass(r.value);if(o.isNull())e=null;else try{let i=n.getClassName(o),s=t.$f;if(e=s._getUsedClass(i),e===void 0)try{let c=lu(this);e=s._make(i,c,n)}finally{s._setUsedClass(i,e)}}finally{n.deleteLocalRef(o)}}finally{r.unref(n)}t.$_s=e}return e}},$s:{get(){return this[Symbol.for("s")]}},[Symbol.for("isSameObject")]:{enumerable:!1,value(t){return G.getEnv().isSameObject(t.$h,this.$h)}},$isSameObject:{value(t){return this[Symbol.for("isSameObject")](t)}},[Symbol.for("getCtor")]:{enumerable:!1,value(t){let e=this.$c,n=e[0];if(n===null){let r=G.getEnv(),o=this.$borrowClassHandle(r);try{n=du(o.value,this.$w,r),e[0]=n}finally{o.unref(r)}}return n[t]}},$getCtor:{value(t){return this[Symbol.for("getCtor")](t)}},[Symbol.for("borrowClassHandle")]:{enumerable:!1,value(t){let e=this.$n,n=this.$f._classHandles,r=n.get(e);return r===void 0&&(r=new vr(this.$gch(t),t),n.set(e,r,t)),r.ref()}},$borrowClassHandle:{value(t){return this[Symbol.for("borrowClassHandle")](t)}},[Symbol.for("copyClassHandle")]:{enumerable:!1,value(t){let e=this.$borrowClassHandle(t);try{return t.newLocalRef(e.value)}finally{e.unref(t)}}},$copyClassHandle:{value(t){return this[Symbol.for("copyClassHandle")](t)}},[Symbol.for("getHandle")]:{enumerable:!1,value(t){let e=this.$h;if(e===void 0)throw new Error("Wrapper is disposed; perhaps it was borrowed from a hook instead of calling Java.retain() to make a long-lived wrapper?");return e}},$getHandle:{value(t){return this[Symbol.for("getHandle")](t)}},[Symbol.for("list")]:{enumerable:!1,value(){let t=this.$s,e=t!==null?t.$list():[],n=this.$l;return Array.from(new Set(e.concat(n.list())))}},$list:{get(){return this[Symbol.for("list")]}},[Symbol.for("has")]:{enumerable:!1,value(t){if(this.$m.has(t)||this.$l.has(t))return!0;let r=this.$s;return!!(r!==null&&r.$has(t))}},$has:{value(t){return this[Symbol.for("has")](t)}},[Symbol.for("find")]:{enumerable:!1,value(t){let e=this.$m,n=e.get(t);if(n!==void 0)return n;let o=this.$l.find(t);if(o!==null){let s=G.getEnv(),c=this.$borrowClassHandle(s);try{n=uu(t,o,c.value,this.$w,s)}finally{c.unref(s)}return e.set(t,n),n}let i=this.$s;return i!==null?i.$find(t):null}},$find:{value(t){return this[Symbol.for("find")](t)}},[Symbol.for("toJSON")]:{enumerable:!1,value(){let t=this.$n;if(this.$h===null)return``;let n=this.$className;return t===n?``:``}},toJSON:{get(){return this[Symbol.for("toJSON")]}}});function vr(t,e){this.value=e.newGlobalRef(t),e.deleteLocalRef(t),this.refs=1}vr.prototype.ref=function(){return this.refs++,this};vr.prototype.unref=function(t){--this.refs===0&&t.deleteGlobalRef(this.value)};function su(t,e){t.unref(e)}function au(t){let e=t.replace(/\./g,"/");return function(n){let r=Jt();ci(r);try{return n.findClass(e)}finally{li(r)}}}function cu(t,e,n){return fr===null&&(Ko=n.vaMethod("pointer",["pointer"]),fr=e.loadClass.overload("java.lang.String").handle),n=null,function(r){let o=r.newStringUtf(t),i=Jt();ci(i);try{let s=Ko(r.handle,e.$h,fr,o);return r.throwIfExceptionPending(),s}finally{li(i),r.deleteLocalRef(o)}}}function lu(t){return function(e){let n=t.$borrowClassHandle(e);try{return e.getSuperclass(n.value)}finally{n.unref(e)}}}function du(t,e,n){let{$n:r,$f:o}=e,i=Cu(r),s=n.javaLangClass(),c=n.javaLangReflectConstructor(),a=n.vaMethod("pointer",[]),l=n.vaMethod("uint8",[]),d=[],p=[],f=o._getType(r,!1),u=o._getType("void",!1),_=a(n.handle,t,s.getDeclaredConstructors);try{let h=n.getArrayLength(_);if(h!==0)for(let g=0;g!==h;g++){let b,E,C=n.getObjectArrayElement(_,g);try{b=n.fromReflectedMethod(C),E=a(n.handle,C,c.getGenericParameterTypes)}finally{n.deleteLocalRef(C)}let A;try{A=yr(n,E).map(M=>o._getType(M))}finally{n.deleteLocalRef(E)}d.push(Qe(i,e,hr,b,f,A,n)),p.push(Qe(i,e,Ne,b,u,A,n))}else{if(l(n.handle,t,s.isInterface))throw new Error("cannot instantiate an interface");let b=n.javaLangObject(),E=n.getMethodId(b,"","()V");d.push(Qe(i,e,hr,E,f,[],n)),p.push(Qe(i,e,Ne,E,u,[],n))}}finally{n.deleteLocalRef(_)}if(p.length===0)throw new Error("no supported overloads");return{allocAndInit:mr(d),initOnly:mr(p)}}function uu(t,e,n,r,o){return e.startsWith("m")?pu(t,e,n,r,o):vu(t,e,n,r,o)}function pu(t,e,n,r,o){let{$f:i}=r,s=e.split(":").slice(1),c=o.javaLangReflectMethod(),a=o.vaMethod("pointer",[]),l=o.vaMethod("uint8",[]),d=s.map(f=>{let u=f[0]==="s"?gt:Ne,_=ptr(f.substr(1)),h,g=[],b=o.toReflectedMethod(n,_,u===gt?1:0);try{let E=!!l(o.handle,b,c.isVarArgs),C=a(o.handle,b,c.getGenericReturnType);o.throwIfExceptionPending();try{h=i._getType(o.getTypeName(C))}finally{o.deleteLocalRef(C)}let A=a(o.handle,b,c.getParameterTypes);try{let M=o.getArrayLength(A);for(let R=0;R!==M;R++){let k=o.getObjectArrayElement(A,R),N;try{N=E&&R===M-1?o.getArrayTypeName(k):o.getTypeName(k)}finally{o.deleteLocalRef(k)}let S=i._getType(N);g.push(S)}}finally{o.deleteLocalRef(A)}}catch{return null}finally{o.deleteLocalRef(b)}return Qe(t,r,u,_,h,g,o)}).filter(f=>f!==null);if(d.length===0)throw new Error("No supported overloads");t==="valueOf"&&bu(d);let p=mr(d);return function(f){return p}}function mr(t){let e=fu();return Object.setPrototypeOf(e,ri),e._o=t,e}function fu(){let t=function(){return t.invoke(this,arguments)};return t}ri=Object.create(Function.prototype,{overloads:{enumerable:!0,get(){return this._o}},overload:{value(...t){let e=this._o,n=t.length,r=t.join(":");for(let o=0;o!==e.length;o++){let i=e[o],{argumentTypes:s}=i;if(s.length!==n)continue;if(s.map(a=>a.className).join(":")===r)return i}gr(this.methodName,this.overloads,"specified argument types do not match any of:")}},methodName:{enumerable:!0,get(){return this._o[0].methodName}},holder:{enumerable:!0,get(){return this._o[0].holder}},type:{enumerable:!0,get(){return this._o[0].type}},handle:{enumerable:!0,get(){return ze(this),this._o[0].handle}},implementation:{enumerable:!0,get(){return ze(this),this._o[0].implementation},set(t){ze(this),this._o[0].implementation=t}},returnType:{enumerable:!0,get(){return ze(this),this._o[0].returnType}},argumentTypes:{enumerable:!0,get(){return ze(this),this._o[0].argumentTypes}},canInvokeWith:{enumerable:!0,get(t){return ze(this),this._o[0].canInvokeWith}},clone:{enumerable:!0,value(t){return ze(this),this._o[0].clone(t)}},invoke:{value(t,e){let n=this._o,r=t.$h!==null;for(let o=0;o!==n.length;o++){let i=n[o];if(i.canInvokeWith(e)){if(i.type===Ne&&!r){let s=this.methodName;if(s==="toString")return``;throw new Error(s+": cannot call instance method without an instance")}return i.apply(t,e)}}if(this.methodName==="toString")return``;gr(this.methodName,this.overloads,"argument types do not match any of:")}}});function Qo(t,e,n){return`${e.className} ${t}(${n.map(r=>r.className).join(", ")})`}function ze(t){let e=t._o;e.length>1&&gr(e[0].methodName,e,"has more than one overload, use .overload() to choose from:")}function gr(t,e,n){let o=e.slice().sort((i,s)=>i.argumentTypes.length-s.argumentTypes.length).map(i=>i.argumentTypes.length>0?".overload('"+i.argumentTypes.map(c=>c.className).join("', '")+"')":".overload()");throw new Error(`${t}(): ${n} + ${o.join(` + `)}`)}function Qe(t,e,n,r,o,i,s,c){let a=o.type,l=i.map(f=>f.type);s===null&&(s=G.getEnv());let d,p;return n===Ne?(d=s.vaMethod(a,l,c),p=s.nonvirtualVaMethod(a,l,c)):n===gt?(d=s.staticVaMethod(a,l,c),p=d):(d=s.constructor(l,c),p=d),hu([t,e,n,r,o,i,d,p])}function hu(t){let e=_u();return Object.setPrototypeOf(e,oi),e._p=t,e}function _u(){let t=function(){return t.invoke(this,arguments)};return t}oi=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return this._p[0]}},holder:{enumerable:!0,get(){return this._p[1]}},type:{enumerable:!0,get(){return this._p[2]}},handle:{enumerable:!0,get(){return this._p[3]}},implementation:{enumerable:!0,get(){let t=this._r;return t!==void 0?t:null},set(t){let e=this._p,n=e[1];if(e[2]===hr)throw new Error("Reimplementing $new is not possible; replace implementation of $init instead");let o=this._r;if(o!==void 0&&(n.$f._patchedMethods.delete(this),o._m.revert(G),this._r=void 0),t!==null){let[i,s,c,a,l,d]=e,p=si(i,s,c,l,d,t,this),f=Xo(a);p._m=f,this._r=p,f.replace(p,c===Ne,d,G,K),n.$f._patchedMethods.add(this)}}},returnType:{enumerable:!0,get(){return this._p[4]}},argumentTypes:{enumerable:!0,get(){return this._p[5]}},canInvokeWith:{enumerable:!0,value(t){let e=this._p[5];return t.length!==e.length?!1:e.every((n,r)=>n.isCompatible(t[r]))}},clone:{enumerable:!0,value(t){let e=this._p.slice(0,6);return Qe(...e,null,t)}},invoke:{value(t,e){let n=G.getEnv(),r=this._p,o=r[2],i=r[4],s=r[5],c=this._r,a=o===Ne,l=e.length,d=2+l;n.pushLocalFrame(d);let p=null;try{let f;a?f=t.$getHandle():(p=t.$borrowClassHandle(n),f=p.value);let u,_=t.$t;c===void 0?u=r[3]:(u=c._m.resolveTarget(t,a,n,K),ti&&c._c.has(Jt())&&(_=ei));let h=[n.handle,f,u];for(let E=0;E!==l;E++)h.push(s[E].toJni(e[E],n));let g;_===zt?g=r[6]:(g=r[7],a&&h.splice(2,0,t.$copyClassHandle(n)));let b=g.apply(null,h);return n.throwIfExceptionPending(),i.fromJni(b,n,!0)}finally{p!==null&&p.unref(n),n.popLocalFrame(NULL)}}},toString:{enumerable:!0,value(){return`function ${this.methodName}(${this.argumentTypes.map(t=>t.className).join(", ")}): ${this.returnType.className}`}}});function si(t,e,n,r,o,i,s=null){let c=new Set,a=mu([t,e,n,r,o,i,s,c]),l=new NativeCallback(a,r.type,["pointer","pointer"].concat(o.map(d=>d.type)));return l._c=c,l}function mu(t){return function(){return gu(arguments,t)}}function gu(t,e){let n=new y(t[0],G),[r,o,i,s,c,a,l,d]=e,p=[],f;if(i===Ne){let h=o.$C;f=new h(t[1],zt,n,!1)}else f=o;let u=Jt();n.pushLocalFrame(3);let _=!0;G.link(u,n);try{d.add(u);let h;l===null||!Ye.has(u)?h=a:h=l;let g=[],b=t.length-2;for(let A=0;A!==b;A++){let R=c[A].fromJni(t[2+A],n,!1);g.push(R),p.push(R)}let E=h.apply(f,g);if(!s.isCompatible(E))throw new Error(`Implementation for ${r} expected return value compatible with ${s.className}`);let C=s.toJni(E,n);return s.type==="pointer"&&(C=n.popLocalFrame(C),_=!1,p.push(E)),C}catch(h){let g=h.$h;return g!==void 0?n.throw(g):Script.nextTick(()=>{throw h}),s.defaultValue}finally{G.unlink(u),_&&n.popLocalFrame(NULL),d.delete(u),p.forEach(h=>{if(h===null)return;let g=h.$dispose;g!==void 0&&g.call(h)})}}function bu(t){let{holder:e,type:n}=t[0];t.some(o=>o.type===n&&o.argumentTypes.length===0)||t.push(yu([e,n]))}function yu(t){let e=Eu();return Object.setPrototypeOf(e,ii),e._p=t,e}function Eu(){return function(){return this}}ii=Object.create(Function.prototype,{methodName:{enumerable:!0,get(){return"valueOf"}},holder:{enumerable:!0,get(){return this._p[0]}},type:{enumerable:!0,get(){return this._p[1]}},handle:{enumerable:!0,get(){return NULL}},implementation:{enumerable:!0,get(){return null},set(t){}},returnType:{enumerable:!0,get(){let t=this.holder;return t.$f.use(t.$n)}},argumentTypes:{enumerable:!0,get(){return[]}},canInvokeWith:{enumerable:!0,value(t){return t.length===0}},clone:{enumerable:!0,value(t){throw new Error("Invalid operation")}}});function vu(t,e,n,r,o){let i=e[2]==="s"?pr:_r,s=ptr(e.substr(3)),{$f:c}=r,a,l=o.toReflectedField(n,s,i===pr?1:0);try{a=o.vaMethod("pointer",[])(o.handle,l,o.javaLangReflectField().getGenericType),o.throwIfExceptionPending()}finally{o.deleteLocalRef(l)}let d;try{d=c._getType(o.getTypeName(a))}finally{o.deleteLocalRef(a)}let p,f,u=d.type;return i===pr?(p=o.getStaticField(u),f=o.setStaticField(u)):(p=o.getField(u),f=o.setField(u)),Su([i,d,s,p,f])}function Su(t){return function(e){return new ai([e].concat(t))}}function ai(t){this._p=t}Object.defineProperties(ai.prototype,{value:{enumerable:!0,get(){let[t,e,n,r,o]=this._p,i=G.getEnv();i.pushLocalFrame(4);let s=null;try{let c;if(e===_r){if(c=t.$getHandle(),c===null)throw new Error("Cannot access an instance field without an instance")}else s=t.$borrowClassHandle(i),c=s.value;let a=o(i.handle,c,r);return i.throwIfExceptionPending(),n.fromJni(a,i,!0)}finally{s!==null&&s.unref(i),i.popLocalFrame(NULL)}},set(t){let[e,n,r,o,,i]=this._p,s=G.getEnv();s.pushLocalFrame(4);let c=null;try{let a;if(n===_r){if(a=e.$getHandle(),a===null)throw new Error("Cannot access an instance field without an instance")}else c=e.$borrowClassHandle(s),a=c.value;if(!r.isCompatible(t))throw new Error(`Expected value compatible with ${r.className}`);let l=r.toJni(t,s);i(s.handle,a,o,l),s.throwIfExceptionPending()}finally{c!==null&&c.unref(s),s.popLocalFrame(NULL)}}},holder:{enumerable:!0,get(){return this._p[0]}},fieldType:{enumerable:!0,get(){return this._p[1]}},fieldReturnType:{enumerable:!0,get(){return this._p[2]}},toString:{enumerable:!0,value(){let t=`Java.Field{holder: ${this.holder}, fieldType: ${this.fieldType}, fieldReturnType: ${this.fieldReturnType}, value: ${this.value}}`;return t.length<200?t:`Java.Field{ + holder: ${this.holder}, + fieldType: ${this.fieldType}, + fieldReturnType: ${this.fieldReturnType}, + value: ${this.value}, +}`.split(` +`).map(n=>n.length>200?n.slice(0,n.indexOf(" ")+1)+"...,":n).join(` +`)}}});var Vt=class t{static fromBuffer(e,n){let r=Yo(n),o=r.getCanonicalPath().toString(),i=new File(o,"w");return i.write(e.buffer),i.close(),wu(o,n),new t(o,r,n)}constructor(e,n,r){this.path=e,this.file=n,this._factory=r}load(){let{_factory:e}=this,{codeCacheDir:n}=e,r=e.use("dalvik.system.DexClassLoader"),o=e.use("java.io.File"),i=this.file;if(i===null&&(i=e.use("java.io.File").$new(this.path)),!i.exists())throw new Error("File not found");o.$new(n).mkdirs(),e.loader=r.$new(i.getCanonicalPath(),n,null,e.loader),G.preventDetachDueToClassLoader()}getClassNames(){let{_factory:e}=this,n=e.use("dalvik.system.DexFile"),r=Yo(e),o=n.loadDex(this.path,r.getCanonicalPath(),0),i=[],s=o.entries();for(;s.hasMoreElements();)i.push(s.nextElement().toString());return i}};function Yo(t){let{cacheDir:e,tempFileNaming:n}=t,r=t.use("java.io.File"),o=r.$new(e);return o.mkdirs(),r.createTempFile(n.prefix,n.suffix+".dex",o)}function wu(t,e){e.use("java.io.File").$new(t).setWritable(!1,!1)}function Iu(){switch(ue.state){case"empty":{ue.state="pending";let t=ue.factories[0],e=t.use("java.util.HashMap"),n=t.use("java.lang.Integer");ue.loaders=e.$new(),ue.Integer=n;let r=t.loader;return r!==null&&br(t,r),ue.state="ready",ue}case"pending":do Thread.sleep(.05);while(ue.state==="pending");return ue;case"ready":return ue}}function br(t,e){let{factories:n,loaders:r,Integer:o}=ue,i=o.$new(n.indexOf(t));r.put(e,i);for(let s=e.getParent();s!==null&&!r.containsKey(s);s=s.getParent())r.put(s,i)}function ci(t){let e=Ye.get(t);e===void 0&&(e=0),e++,Ye.set(t,e)}function li(t){let e=Ye.get(t);if(e===void 0)throw new Error(`Thread ${t} is not ignored`);e--,e===0?Ye.delete(t):Ye.set(t,e)}function Cu(t){return t.slice(t.lastIndexOf(".")+1)}function yr(t,e){let n=[],r=t.getArrayLength(e);for(let o=0;o!==r;o++){let i=t.getObjectArrayElement(e,o);try{n.push(t.getTypeName(i))}finally{t.deleteLocalRef(i)}}return n}function Tu(t){let e=t.split(".");return e[e.length-1]+".java"}var Au=4,di=Process.pointerSize,Sr=class{ACC_PUBLIC=1;ACC_PRIVATE=2;ACC_PROTECTED=4;ACC_STATIC=8;ACC_FINAL=16;ACC_SYNCHRONIZED=32;ACC_BRIDGE=64;ACC_VARARGS=128;ACC_NATIVE=256;ACC_ABSTRACT=1024;ACC_STRICT=2048;ACC_SYNTHETIC=4096;constructor(){this.classFactory=null,this.ClassFactory=je,this.vm=null,this.api=null,this._initialized=!1,this._apiError=null,this._wakeupHandler=null,this._pollListener=null,this._pendingMainOps=[],this._pendingVmOps=[],this._cachedIsAppProcess=null;try{this._tryInitialize()}catch{}}_tryInitialize(){if(this._initialized)return!0;if(this._apiError!==null)throw this._apiError;let e;try{e=ft(),this.api=e}catch(r){throw this._apiError=r,r}if(e===null)return!1;let n=new Ie(e);return this.vm=n,$o(n),je._initialize(n,e),this.classFactory=new je,this._initialized=!0,!0}_dispose(){if(this.api===null)return;let{vm:e}=this;e.perform(n=>{je._disposeAll(n),y.dispose(n)}),Script.nextTick(()=>{Ie.dispose(e)})}get available(){return this._tryInitialize()}get androidVersion(){return ut()}synchronized(e,n){let{$h:r=e}=e;if(!(r instanceof NativePointer))throw new Error("Java.synchronized: the first argument `obj` must be either a pointer or a Java instance");let o=this.vm.getEnv();de("VM::MonitorEnter",o.monitorEnter(r));try{n()}finally{o.monitorExit(r)}}enumerateLoadedClasses(e){this._checkAvailable();let{flavor:n}=this.api;n==="jvm"?this._enumerateLoadedClassesJvm(e):n==="art"?this._enumerateLoadedClassesArt(e):this._enumerateLoadedClassesDalvik(e)}enumerateLoadedClassesSync(){let e=[];return this.enumerateLoadedClasses({onMatch(n){e.push(n)},onComplete(){}}),e}enumerateClassLoaders(e){this._checkAvailable();let{flavor:n}=this.api;if(n==="jvm")this._enumerateClassLoadersJvm(e);else if(n==="art")this._enumerateClassLoadersArt(e);else throw new Error("Enumerating class loaders is not supported on Dalvik")}enumerateClassLoadersSync(){let e=[];return this.enumerateClassLoaders({onMatch(n){e.push(n)},onComplete(){}}),e}_enumerateLoadedClassesJvm(e){let{api:n,vm:r}=this,{jvmti:o}=n,i=r.getEnv(),s=Memory.alloc(Au),c=Memory.alloc(di);o.getLoadedClasses(s,c);let a=s.readS32(),l=c.readPointer(),d=[];for(let p=0;p!==a;p++)d.push(l.add(p*di).readPointer());o.deallocate(l);try{for(let p of d){let f=i.getClassName(p);e.onMatch(f,p)}e.onComplete()}finally{d.forEach(p=>{i.deleteLocalRef(p)})}}_enumerateClassLoadersJvm(e){this.choose("java.lang.ClassLoader",e)}_enumerateLoadedClassesArt(e){let{vm:n,api:r}=this,o=n.getEnv(),i=r["art::JavaVMExt::AddGlobalRef"],{vm:s}=r;ye(n,o,c=>{let a=Hn(l=>{let d=i(s,c,l);try{let p=o.getClassName(d);e.onMatch(p,d)}finally{o.deleteGlobalRef(d)}return!0});r["art::ClassLinker::VisitClasses"](r.artClassLinker.address,a)}),e.onComplete()}_enumerateClassLoadersArt(e){let{classFactory:n,vm:r,api:o}=this,i=r.getEnv(),s=o["art::ClassLinker::VisitClassLoaders"];if(s===void 0)throw new Error("This API is only available on Android >= 7.0");let c=n.use("java.lang.ClassLoader"),a=[],l=o["art::JavaVMExt::AddGlobalRef"],{vm:d}=o;ye(r,i,p=>{let f=Zn(u=>(a.push(l(d,p,u)),!0));$n(()=>{s(o.artClassLinker.address,f)})});try{a.forEach(p=>{let f=n.cast(p,c);e.onMatch(f)})}finally{a.forEach(p=>{i.deleteGlobalRef(p)})}e.onComplete()}_enumerateLoadedClassesDalvik(e){let{api:n}=this,r=ptr("0xcbcacccd"),o=172,i=8,c=n.gDvm.add(o).readPointer(),a=c.readS32(),d=c.add(12).readPointer(),p=a*i;for(let f=0;f{let s=i.loader;return i.loader=s!==null?n.wrap(s,o,r):null,i})}scheduleOnMainThread(e){this.performNow(()=>{this._pendingMainOps.push(e);let{_wakeupHandler:n}=this;if(n===null){let{classFactory:r}=this,o=r.use("android.os.Handler"),i=r.use("android.os.Looper");n=o.$new(i.getMainLooper()),this._wakeupHandler=n}this._pollListener===null&&(this._pollListener=Interceptor.attach(Process.getModuleByName("libc.so").getExportByName("epoll_wait"),this._makePollHook()),Interceptor.flush()),n.sendEmptyMessage(1)})}_makePollHook(){let e=Process.id,{_pendingMainOps:n}=this;return function(){if(this.threadId!==e)return;let r;for(;(r=n.shift())!==void 0;)try{r()}catch(o){Script.nextTick(()=>{throw o})}}}perform(e){if(this._checkAvailable(),!this._isAppProcess()||this.classFactory.loader!==null)try{this.vm.perform(e)}catch(n){Script.nextTick(()=>{throw n})}else this._pendingVmOps.push(e),this._pendingVmOps.length===1&&this._performPendingVmOpsWhenReady()}performNow(e){return this._checkAvailable(),this.vm.perform(()=>{let{classFactory:n}=this;if(this._isAppProcess()&&n.loader===null){let o=n.use("android.app.ActivityThread").currentApplication();o!==null&&ui(n,o)}return e()})}_performPendingVmOpsWhenReady(){this.vm.perform(()=>{let{classFactory:e}=this,n=e.use("android.app.ActivityThread"),r=n.currentApplication();if(r!==null){ui(e,r),this._performPendingVmOps();return}let o=this,i=!1,s="early",c=n.handleBindApplication;c.implementation=function(d){if(d.instrumentationName.value!==null){s="late";let f=e.use("android.app.LoadedApk").makeApplication;f.implementation=function(u,_){return i||(i=!0,pi(e,this),o._performPendingVmOps()),f.apply(this,arguments)}}c.apply(this,arguments)};let l=n.getPackageInfo.overloads.map(d=>[d.argumentTypes.length,d]).sort(([d],[p])=>p-d).map(([d,p])=>p)[0];l.implementation=function(...d){let p=l.call(this,...d);return!i&&s==="early"&&(i=!0,pi(e,p),o._performPendingVmOps()),p}})}_performPendingVmOps(){let{vm:e,_pendingVmOps:n}=this,r;for(;(r=n.shift())!==void 0;)try{e.perform(r)}catch(o){Script.nextTick(()=>{throw o})}}use(e,n){return this.classFactory.use(e,n)}openClassFile(e){return this.classFactory.openClassFile(e)}choose(e,n){this.classFactory.choose(e,n)}retain(e){return this.classFactory.retain(e)}cast(e,n){return this.classFactory.cast(e,n)}array(e,n){return this.classFactory.array(e,n)}backtrace(e){return qn(this.vm,e)}isMainThread(){let e=this.classFactory.use("android.os.Looper"),n=e.getMainLooper(),r=e.myLooper();return r===null?!1:n.$isSameObject(r)}registerClass(e){return this.classFactory.registerClass(e)}deoptimizeEverything(){let{vm:e}=this;return Yn(e,e.getEnv())}deoptimizeBootImage(){let{vm:e}=this;return Xn(e,e.getEnv())}deoptimizeMethod(e){let{vm:n}=this;return Qn(n,n.getEnv(),e)}_checkAvailable(){if(!this.available)throw new Error("Java API not available")}_isAppProcess(){let e=this._cachedIsAppProcess;if(e===null){if(this.api.flavor==="jvm")return e=!1,this._cachedIsAppProcess=e,e;let n=new NativeFunction(Module.getGlobalExportByName("readlink"),"pointer",["pointer","pointer","pointer"],{exceptions:"propagate"}),r=Memory.allocUtf8String("/proc/self/exe"),o=1024,i=Memory.alloc(o),s=n(r,i,ptr(o)).toInt32();if(s!==-1){let c=i.readUtf8String(s);e=/^\/system\/bin\/app_process/.test(c)}else e=!0;this._cachedIsAppProcess=e}return e}};function ui(t,e){let n=t.use("android.os.Process");t.loader=e.getClassLoader(),n.myUid()===n.SYSTEM_UID.value?(t.cacheDir="/data/system",t.codeCacheDir="/data/dalvik-cache"):"getCodeCacheDir"in e?(t.cacheDir=e.getCacheDir().getCanonicalPath(),t.codeCacheDir=e.getCodeCacheDir().getCanonicalPath()):(t.cacheDir=e.getFilesDir().getCanonicalPath(),t.codeCacheDir=e.getCacheDir().getCanonicalPath())}function pi(t,e){let n=t.use("java.io.File");t.loader=e.getClassLoader();let r=n.$new(e.getDataDir()).getCanonicalPath();t.cacheDir=r,t.codeCacheDir=r+"/cache"}var wr=new Sr;Script.bindWeak(wr,()=>{wr._dispose()});var Ve=wr;Ve.perform(()=>{let t="top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry",e=null;try{e=Ve.use(t)}catch{Ve.enumerateClassLoaders({onMatch(s){if(e===null)try{s.loadClass(t),e=Ve.ClassFactory.get(s).use(t)}catch{}},onComplete(){}})}if(e===null)throw new Error("GuestRuntimeRegistry ClassLoader was not found");let n=e.getGuestClassLoader();if(n===null)throw new Error("GuestRuntimeRegistry has no guest ClassLoader");Ve.classFactory.loader=n;let o=Ve.use("com.qm4rs.fridabox.sample.Target").add.overload("int","int");o.implementation=function(i,s){return console.log("[sample-hook] Target.add("+i+", "+s+") => 1337"),1337},console.log("[sample-hook] installed for "+e.getGuestPackageName())}); diff --git a/scripts/guest-bootstrap.js b/scripts/guest-bootstrap.js new file mode 100644 index 0000000..605d2e7 --- /dev/null +++ b/scripts/guest-bootstrap.js @@ -0,0 +1,75 @@ +'use strict'; + +import Java from 'frida-java-bridge'; + +const REGISTRY = 'top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry'; +const MAX_ATTEMPTS = 40; +const RETRY_MS = 250; +let registry = null; +let guestLoader = null; + +function findRegistry() { + try { + return Java.use(REGISTRY); + } catch (_) { + let found = null; + Java.enumerateClassLoaders({ + onMatch(loader) { + if (found !== null) return; + try { + loader.loadClass(REGISTRY); + const factory = Java.ClassFactory.get(loader); + found = factory.use(REGISTRY); + } catch (_) {} + }, + onComplete() {} + }); + return found; + } +} + +function bootstrap(attempt) { + Java.perform(() => { + registry = findRegistry(); + if (registry !== null) { + guestLoader = registry.getGuestClassLoader(); + if (guestLoader !== null) { + Java.classFactory.loader = guestLoader; + console.log('[FridaBox] package=' + registry.getGuestPackageName()); + console.log('[FridaBox] process=' + registry.getGuestProcessName()); + console.log('[FridaBox] userId=' + registry.getGuestUserId()); + console.log('[FridaBox] virtualProcessId=' + registry.getVirtualProcessId()); + console.log('[FridaBox] source=' + registry.getGuestSourceDir()); + console.log('[FridaBox] ClassLoader=' + guestLoader.toString()); + return; + } + } + if (attempt + 1 < MAX_ATTEMPTS) { + setTimeout(() => bootstrap(attempt + 1), RETRY_MS); + } else { + console.error('[FridaBox] guest ClassLoader unavailable after ' + (MAX_ATTEMPTS * RETRY_MS) + ' ms'); + } + }); +} + +bootstrap(0); + +rpc.exports = { + info() { + return Java.performNow(() => registry === null ? { error: 'registry unavailable' } : JSON.parse(registry.describe())); + }, + useclass(className) { + return Java.performNow(() => { + if (guestLoader === null) throw new Error('guest ClassLoader is not ready'); + Java.classFactory.loader = guestLoader; + return Java.use(className).$className; + }); + }, + enumerateloadedclasses(prefix) { + const match = prefix || ''; + return Java.performNow(() => Java.enumerateLoadedClassesSync().filter(name => name.indexOf(match) === 0)); + }, + enumeratemodules() { + return Process.enumerateModules().map(module => ({ name: module.name, base: module.base.toString(), path: module.path })); + } +}; diff --git a/scripts/native-load-monitor.js b/scripts/native-load-monitor.js new file mode 100644 index 0000000..8693663 --- /dev/null +++ b/scripts/native-load-monitor.js @@ -0,0 +1,26 @@ +'use strict'; + +const seen = new Set(); + +function report(module) { + if (seen.has(module.path)) return; + seen.add(module.path); + console.log('[native-load] ' + module.name + ' base=' + module.base + ' path=' + module.path); + if (typeof globalThis.onGuestModuleLoaded === 'function') { + try { globalThis.onGuestModuleLoaded(module); } catch (error) { console.error(error.stack || error); } + } +} + +Process.enumerateModules().forEach(report); +Process.attachModuleObserver({ onAdded: report, onRemoved() {} }); + +['dlopen', 'android_dlopen_ext'].forEach(name => { + const address = Module.findGlobalExportByName(name); + if (address === null) return; + Interceptor.attach(address, { + onEnter(args) { this.path = args[0].isNull() ? null : args[0].readCString(); }, + onLeave(result) { + if (this.path !== null) console.log('[' + name + '] ' + this.path + ' => ' + result); + } + }); +}); diff --git a/scripts/registry-probe.js b/scripts/registry-probe.js new file mode 100644 index 0000000..d7ef48c --- /dev/null +++ b/scripts/registry-probe.js @@ -0,0 +1,28 @@ +'use strict'; + +import Java from 'frida-java-bridge'; + +Java.performNow(function () { + try { + const name = 'top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry'; + let Registry = null; + try { + Registry = Java.use(name); + } catch (_) { + Java.enumerateClassLoaders({ + onMatch(loader) { + if (Registry !== null) return; + try { + loader.loadClass(name); + Registry = Java.ClassFactory.get(loader).use(name); + } catch (_) {} + }, + onComplete() {} + }); + } + if (Registry === null) throw new Error('GuestRuntimeRegistry ClassLoader was not found'); + send({kind: 'fridabox-registry', value: Registry.describe()}); + } catch (error) { + send({kind: 'fridabox-error', value: String(error.stack || error)}); + } +}); diff --git a/scripts/sample-hook.js b/scripts/sample-hook.js new file mode 100644 index 0000000..6d8ca5b --- /dev/null +++ b/scripts/sample-hook.js @@ -0,0 +1,33 @@ +'use strict'; + +import Java from 'frida-java-bridge'; + +Java.perform(() => { + const registryName = 'top.niunaijun.blackbox.instrumentation.GuestRuntimeRegistry'; + let Registry = null; + try { + Registry = Java.use(registryName); + } catch (_) { + Java.enumerateClassLoaders({ + onMatch(loader) { + if (Registry !== null) return; + try { + loader.loadClass(registryName); + Registry = Java.ClassFactory.get(loader).use(registryName); + } catch (_) {} + }, + onComplete() {} + }); + } + if (Registry === null) throw new Error('GuestRuntimeRegistry ClassLoader was not found'); + const loader = Registry.getGuestClassLoader(); + if (loader === null) throw new Error('GuestRuntimeRegistry has no guest ClassLoader'); + Java.classFactory.loader = loader; + const Target = Java.use('com.qm4rs.fridabox.sample.Target'); + const add = Target.add.overload('int', 'int'); + add.implementation = function (a, b) { + console.log('[sample-hook] Target.add(' + a + ', ' + b + ') => 1337'); + return 1337; + }; + console.log('[sample-hook] installed for ' + Registry.getGuestPackageName()); +}); diff --git a/settings.gradle b/settings.gradle index 2c1007d..794d96e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,14 @@ pluginManagement { + resolutionStrategy { + eachPlugin { + if (requested.id.id == "com.android.application" || + requested.id.id == "com.android.library") { + useModule("com.android.tools.build:gradle:${requested.version}") + } + } + } repositories { + maven { url "https://maven.aliyun.com/repository/google" } maven { url "https://www.jitpack.io" } google() @@ -17,6 +26,7 @@ pluginManagement { dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { + maven { url "https://maven.aliyun.com/repository/google" } maven { url "https://www.jitpack.io" } google() mavenCentral() @@ -29,3 +39,4 @@ include ':app' include(":black-reflection") include(":compiler") include ':Bcore' +include ':sample-guest' diff --git a/tools/attach_guest.py b/tools/attach_guest.py new file mode 100644 index 0000000..6ea3857 --- /dev/null +++ b/tools/attach_guest.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python3 +"""Discover FridaBox Gadget endpoints and attach by virtual guest identity.""" + +from __future__ import annotations + +import argparse +import json +import pathlib +import queue +import re +import subprocess +import sys +import threading +import time +from dataclasses import dataclass +from typing import Any + +from forward_frida_ports import authorized_device, forward_ports + +ROOT = pathlib.Path(__file__).resolve().parents[1] +AGENT_DIST = ROOT / "scripts/dist" +BOOTSTRAP = AGENT_DIST / "guest-bootstrap.js" +REGISTRY_PROBE = AGENT_DIST / "registry-probe.js" +FRIDA_VERSION = "17.16.0" + + +@dataclass +class Endpoint: + port: int + device: Any + session: Any + info: dict[str, Any] + + +def device_listening_ports(adb: str, serial: str, base_port: int, count: int) -> list[int]: + """Return listening device ports in the configured range, or the range if ss is unavailable.""" + result = subprocess.run( + [adb, "-s", serial, "shell", "ss", "-ltn"], + text=True, + capture_output=True, + check=False, + ) + if result.returncode != 0 or "not found" in result.stderr.lower(): + return list(range(base_port, base_port + count)) + upper = base_port + count + ports: set[int] = set() + for line in result.stdout.splitlines(): + if "LISTEN" not in line: + continue + for value in re.findall(r":(\d+)\b", line): + port = int(value) + if base_port <= port < upper: + ports.add(port) + return sorted(ports) + + +def message_printer(message: dict[str, Any], data: bytes | None) -> None: + if message.get("type") == "send": + print(f"[script] {message.get('payload')}") + elif message.get("type") == "error": + print(f"[script-error] {message.get('stack') or message}", file=sys.stderr) + else: + print(f"[script-message] {message}") + if data: + print(f"[script-data] {len(data)} bytes") + + +def probe_endpoint(frida: Any, port: int) -> Endpoint | None: + manager = frida.get_device_manager() + device = manager.add_remote_device(f"127.0.0.1:{port}") + processes = device.enumerate_processes() + gadget = next((process for process in processes if process.name == "Gadget"), None) + if gadget is None: + return None + session = device.attach(gadget.pid) + answers: queue.Queue[dict[str, Any]] = queue.Queue() + + def on_message(message: dict[str, Any], _data: bytes | None) -> None: + if message.get("type") == "send" and isinstance(message.get("payload"), dict): + answers.put(message["payload"]) + elif message.get("type") == "error": + answers.put({ + "kind": "fridabox-error", + "value": message.get("stack") or message.get("description") or str(message), + }) + + script = session.create_script(REGISTRY_PROBE.read_text(encoding="utf-8")) + script.on("message", on_message) + script.load() + try: + answer = answers.get(timeout=4.0) + except queue.Empty: + script.unload() + session.detach() + return None + script.unload() + if answer.get("kind") != "fridabox-registry": + print(f"Port {port} rejected: {answer.get('value', 'registry probe failed')}", file=sys.stderr) + session.detach() + return None + try: + info = json.loads(answer["value"]) + except (KeyError, TypeError, json.JSONDecodeError): + session.detach() + return None + return Endpoint(port, device, session, info) + + +def discover(frida: Any, ports: list[int]) -> list[Endpoint]: + endpoints: list[Endpoint] = [] + for port in ports: + try: + endpoint = probe_endpoint(frida, port) + if endpoint is not None: + endpoints.append(endpoint) + except Exception as error: + text = str(error).lower() + if "version" in text and ("mismatch" in text or "incompatible" in text): + print_version_fix(frida, error) + continue + return endpoints + + +def print_version_fix(frida: Any, error: Exception) -> None: + local = getattr(frida, "__version__", "unknown") + print(f"Frida protocol/version error (client {local}, Gadget {FRIDA_VERSION}): {error}", file=sys.stderr) + print(f"Fix: {sys.executable} -m pip install --upgrade frida=={FRIDA_VERSION}", file=sys.stderr) + + +def print_table(endpoints: list[Endpoint]) -> None: + headings = ("PORT", "GUEST PACKAGE", "GUEST PROCESS", "VPID", "SOURCE APK") + rows = [ + (str(item.port), str(item.info.get("package")), str(item.info.get("process")), + str(item.info.get("virtualProcessId")), str(item.info.get("sourceDir"))) + for item in endpoints + ] + widths = [len(value) for value in headings] + for row in rows: + widths = [max(width, len(value)) for width, value in zip(widths, row)] + print(" ".join(value.ljust(width) for value, width in zip(headings, widths))) + print(" ".join("-" * width for width in widths)) + for row in rows: + print(" ".join(value.ljust(width) for value, width in zip(row, widths))) + + +def loadable_user_agent(source: pathlib.Path) -> pathlib.Path: + if source.parent.name != "dist": + compiled = source.parent / "dist" / source.name + if compiled.is_file(): + return compiled + return source + + +def attach_scripts(endpoint: Endpoint, user_script: pathlib.Path | None, keep_alive: bool) -> None: + scripts = [] + bootstrap = endpoint.session.create_script(BOOTSTRAP.read_text(encoding="utf-8")) + bootstrap.on("message", message_printer) + bootstrap.load() + scripts.append(bootstrap) + bootstrap_info: dict[str, Any] | None = None + for _attempt in range(40): + try: + candidate = bootstrap.exports_sync.info() + bootstrap.exports_sync.useclass("java.lang.Object") + if isinstance(candidate, dict) and "error" not in candidate: + bootstrap_info = candidate + break + except Exception: + pass + time.sleep(0.25) + if bootstrap_info is None: + raise RuntimeError("guest bootstrap did not select a ClassLoader within 10 seconds") + modules = bootstrap.exports_sync.enumeratemodules() + print("GuestRuntimeRegistry: " + json.dumps(bootstrap_info, sort_keys=True), flush=True) + print(f"Native modules: {len(modules)}", flush=True) + for module in modules[:12]: + print(f" {module.get('name')} @ {module.get('base')} {module.get('path')}", flush=True) + if user_script is not None: + agent = loadable_user_agent(user_script) + script = endpoint.session.create_script(agent.read_text(encoding="utf-8")) + script.on("message", message_printer) + script.load() + scripts.append(script) + print(f"Attached on port {endpoint.port} to {endpoint.info.get('package')} / {endpoint.info.get('process')}") + if keep_alive or user_script is not None: + stopped = threading.Event() + try: + while not stopped.wait(0.5): + pass + except KeyboardInterrupt: + print("Detaching…") + for script in reversed(scripts): + try: + script.unload() + except Exception: + pass + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--list", action="store_true", help="discover and list guests") + parser.add_argument("--package", help="guest package to attach") + parser.add_argument("--process", help="optional guest process name") + parser.add_argument("--script", type=pathlib.Path, help="user JavaScript loaded after bootstrap") + parser.add_argument("--keep-alive", action="store_true") + parser.add_argument("--base-port", type=int, default=27042) + parser.add_argument("--count", type=int, default=32) + args = parser.parse_args() + if not args.list and not args.package: + parser.error("use --list or --package PACKAGE") + if args.script is not None and not args.script.is_file(): + parser.error(f"script does not exist: {args.script}") + if not BOOTSTRAP.is_file() or not REGISTRY_PROBE.is_file(): + raise SystemExit("Compiled Frida 17 agents are missing; run: npm ci && python tools/build_frida_agents.py") + + import shutil + adb = shutil.which("adb") + if adb is None: + raise SystemExit("adb was not found on PATH; install Android platform-tools") + try: + serial = authorized_device(adb) + forward_ports(adb, serial, args.base_port, args.count) + except (RuntimeError, subprocess.CalledProcessError) as error: + raise SystemExit(str(error)) from error + + try: + import frida + except ImportError as error: + raise SystemExit(f"Install controller dependencies: {sys.executable} -m pip install -r tools/requirements.txt") from error + local_major = str(getattr(frida, "__version__", "0")).split(".", 1)[0] + if local_major != FRIDA_VERSION.split(".", 1)[0]: + print_version_fix(frida, RuntimeError("major versions differ")) + return 2 + ports = device_listening_ports(adb, serial, args.base_port, args.count) + endpoints = discover(frida, ports) + print_table(endpoints) + if args.list: + for endpoint in endpoints: + endpoint.session.detach() + return 0 + matches = [item for item in endpoints if item.info.get("package") == args.package] + if args.process: + matches = [item for item in matches if item.info.get("process") == args.process] + if not matches: + raise SystemExit("No matching FridaBox guest endpoint was discovered") + chosen = matches[0] + for endpoint in endpoints: + if endpoint is not chosen: + endpoint.session.detach() + try: + attach_scripts(chosen, args.script, args.keep_alive) + finally: + chosen.session.detach() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/build_frida_agents.py b/tools/build_frida_agents.py new file mode 100644 index 0000000..eca9322 --- /dev/null +++ b/tools/build_frida_agents.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +"""Build Frida 17 Java agents with the explicitly pinned Java bridge.""" + +from __future__ import annotations + +import os +import pathlib +import subprocess +import sys + +ROOT = pathlib.Path(__file__).resolve().parents[1] +SCRIPTS = ROOT / "scripts" +OUTPUT = SCRIPTS / "dist" +ENTRIES = ("registry-probe.js", "guest-bootstrap.js", "sample-hook.js") + + +def compiler_path() -> pathlib.Path: + name = "frida-compile.cmd" if os.name == "nt" else "frida-compile" + path = ROOT / "node_modules" / ".bin" / name + if not path.is_file(): + raise SystemExit("Install pinned agent dependencies first: npm ci") + return path + + +def main() -> int: + compiler = compiler_path() + OUTPUT.mkdir(parents=True, exist_ok=True) + for name in ENTRIES: + subprocess.run( + [str(compiler), str(SCRIPTS / name), "-o", str(OUTPUT / name), "-S", "-c"], + cwd=ROOT, + check=True, + ) + print("Built Frida agents: " + ", ".join(str(OUTPUT / name) for name in ENTRIES)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/fetch_frida_gadget.py b/tools/fetch_frida_gadget.py new file mode 100644 index 0000000..d0ce85c --- /dev/null +++ b/tools/fetch_frida_gadget.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Fetch and verify the pinned official Frida Gadget Android ARM64 binary.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import lzma +import pathlib +import shutil +import tempfile +import urllib.request + +VERSION = "17.16.0" +ASSET = f"frida-gadget-{VERSION}-android-arm64.so.xz" +API_URL = f"https://api.github.com/repos/frida/frida/releases/tags/{VERSION}" +ROOT = pathlib.Path(__file__).resolve().parents[1] +DEST = ROOT / "app/src/main/jniLibs/arm64-v8a/libfrida-gadget.so" +CHECKSUM = ROOT / "tools/frida-gadget-17.16.0.sha256" +EXPECTED_SHA256 = "6bf149e5d1c5ec701e7b822cab57bb243f1c2a03318fa974fe373ee711a9ed9e" + + +def sha256(path: pathlib.Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def release_asset_url() -> str: + request = urllib.request.Request( + API_URL, + headers={"Accept": "application/vnd.github+json", "User-Agent": "FridaBox-build"}, + ) + with urllib.request.urlopen(request, timeout=30) as response: + release = json.load(response) + if release.get("tag_name") != VERSION: + raise RuntimeError(f"GitHub returned unexpected release {release.get('tag_name')!r}") + for asset in release.get("assets", []): + if asset.get("name") == ASSET: + return str(asset["browser_download_url"]) + raise RuntimeError(f"Release {VERSION} does not contain {ASSET}") + + +def fetch(force: bool = False) -> str: + if DEST.exists() and not force: + digest = sha256(DEST) + if digest != EXPECTED_SHA256: + raise RuntimeError(f"Existing Gadget SHA-256 mismatch: {digest}") + CHECKSUM.write_text(f"{digest} {DEST.name}\n", encoding="ascii") + return digest + DEST.parent.mkdir(parents=True, exist_ok=True) + with tempfile.TemporaryDirectory(prefix="fridabox-") as temp_dir: + archive = pathlib.Path(temp_dir) / ASSET + request = urllib.request.Request(release_asset_url(), headers={"User-Agent": "FridaBox-build"}) + with urllib.request.urlopen(request, timeout=120) as response, archive.open("wb") as output: + shutil.copyfileobj(response, output) + temporary_output = pathlib.Path(temp_dir) / DEST.name + with lzma.open(archive, "rb") as source, temporary_output.open("wb") as output: + shutil.copyfileobj(source, output) + if temporary_output.stat().st_size < 1_000_000: + raise RuntimeError("Downloaded Gadget is unexpectedly small") + shutil.move(str(temporary_output), DEST) + digest = sha256(DEST) + if digest != EXPECTED_SHA256: + DEST.unlink(missing_ok=True) + raise RuntimeError(f"Downloaded Gadget SHA-256 mismatch: {digest}") + CHECKSUM.write_text(f"{digest} {DEST.name}\n", encoding="ascii") + return digest + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--force", action="store_true", help="replace an existing Gadget") + args = parser.parse_args() + digest = fetch(args.force) + print(f"Frida Gadget {VERSION}: {DEST}") + print(f"SHA-256: {digest}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/forward_frida_ports.py b/tools/forward_frida_ports.py new file mode 100644 index 0000000..c4e174b --- /dev/null +++ b/tools/forward_frida_ports.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +"""Forward the FridaBox Gadget discovery range through ADB.""" + +from __future__ import annotations + +import argparse +import shutil +import subprocess + + +def authorized_device(adb: str) -> str: + result = subprocess.run([adb, "devices"], check=True, text=True, capture_output=True) + devices = [] + unauthorized = [] + for line in result.stdout.splitlines()[1:]: + fields = line.split() + if len(fields) >= 2 and fields[1] == "device": + devices.append(fields[0]) + elif len(fields) >= 2 and fields[1] == "unauthorized": + unauthorized.append(fields[0]) + if not devices: + suffix = f"; unauthorized: {', '.join(unauthorized)}" if unauthorized else "" + raise RuntimeError("No authorized Android device found" + suffix) + return devices[0] + + +def forward_ports(adb: str, serial: str, base_port: int, count: int) -> None: + for port in range(base_port, base_port + count): + subprocess.run( + [adb, "-s", serial, "forward", f"tcp:{port}", f"tcp:{port}"], + check=True, + stdout=subprocess.DEVNULL, + ) + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--base-port", type=int, default=27042) + parser.add_argument("--count", type=int, default=32) + args = parser.parse_args() + adb = shutil.which("adb") + if adb is None: + raise SystemExit("adb was not found on PATH; install Android platform-tools") + try: + serial = authorized_device(adb) + forward_ports(adb, serial, args.base_port, args.count) + except (RuntimeError, subprocess.CalledProcessError) as error: + raise SystemExit(str(error)) from error + print(f"Forwarded {args.base_port}..{args.base_port + args.count - 1} on {serial}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/frida-gadget-17.16.0.sha256 b/tools/frida-gadget-17.16.0.sha256 new file mode 100644 index 0000000..e8b4f04 --- /dev/null +++ b/tools/frida-gadget-17.16.0.sha256 @@ -0,0 +1 @@ +6bf149e5d1c5ec701e7b822cab57bb243f1c2a03318fa974fe373ee711a9ed9e libfrida-gadget.so diff --git a/tools/requirements.txt b/tools/requirements.txt new file mode 100644 index 0000000..519fcfe --- /dev/null +++ b/tools/requirements.txt @@ -0,0 +1 @@ +frida==17.16.0