Skip to content

Repository files navigation

LSPosed Universal Template

License: CC BY-NC-ND 4.0

A quick-start Android/Vector module template for authorized testing and rapid prototyping.

What it includes:

  • Modern libxposed API 102 entry point (io.github.libxposed:api:102.0.0, compileOnly).
  • One module APK for both rooted Vector and rootless LSPatch 1.0. LSPatch 1.0 is rebuilt on Vector and loads modern libxposed API-102 modules through META-INF/xposed/java_init.list; the obsolete API-93-only lspatch flavor is no longer needed. See docs/LSPATCH_NONROOT.md.
  • Both onPackageLoaded and onPackageReady callbacks are overridden for broad compatibility.
  • Process-level filter: TemplateConfig.TARGET_PROCESS_SUFFIXES + SKIP_PROCESS_SUFFIXES default to hooking only the main process and skipping common anti-cheat / push / crash-handler satellite processes.
  • Modern libxposed metadata under META-INF/xposed/:
    • java_init.list
    • scope.list
    • module.prop with the correct exceptionMode=protective key
  • A safe Java hook smoke test using the API 102 interceptor-chain style.
  • FeatureRegistry — runtime feature flags (bool/float) with best-effort persistence and live-updating overlay toggles bound to each feature key. OPSEC caveat: persistence writes a plaintext toggle file into the target app's own sandbox (getFilesDir()); a readable file naming your features/toggles inside the target is a detection surface, so prefer in-memory-only state for stealth (drop the save()/load() calls or point FEATURE_STATE_FILE_NAME at a path outside the target).
  • EngineDetector — identifies Unity / Unreal / Cocos2d-x / Godot / Flutter / React-Native / Xamarin targets at startup so you can branch hook strategies.
  • NativeUtils — JNI helpers for /proc/self/maps module lookup, IDA-style pattern scan, dlsym resolution, and safe mprotect-guarded read/write-memory primitives.
  • A movable dark/lavender Nyx-styled floating menu:
    • movable oval bubble
    • movable rectangular panel when opened (drag the header)
    • one toggle row per FeatureRegistry bool feature
  • Optional native scaffold using ByteDance ShadowHook (com.bytedance.android:shadowhook:2.0.1) registered via JNI_OnLoad / RegisterNatives so there are no package-derived JNI export names in the .so symbol table.
  • Debug/release split with VERBOSE_LOGS as a BuildConfig field — release builds strip verbose logs and run R8. Note that proguard-rules.pro deliberately -keeps the classes the framework/JNI must find by name — the entry class (ModuleEntry), NativeBridge, and NativeUtils (their method names are bound as strings in JNI_OnLoad), and the FeatureRegistry.KEY_* constants — so those names are not obfuscated and stay visible to an app enumerating its classloader. Everything not kept is renamed/obfuscated by R8.
  • Neutral log tag (AppRuntime) and worker thread name; release builds disable verbose Java and native logging by default.
  • The documented LSPatch/SAI workflow deliberately signs both the module and every patched target split with the same existing Android debug key at ${HOME}/.android/debug.keystore. This is a stable local test key, not a production-distribution key.
  • Configure script supports --native-lib to rename the packaged .so away from the obvious libtemplate_native.so.
  • Frida-first Android emulator workflow documentation for reconnaissance before building permanent hooks.
  • Engine-specific native workflow notes for Unity IL2CPP and other native-heavy targets, kept as optional documentation so the template remains engine-neutral.

Use this only on apps/systems you own or are authorized to test.

Current researched versions

  • Verified against upstream releases on 2026-08-19.
  • libxposed API: 102.0.0; Vector 2.2 and LSPatch 1.0 implement modern API level 102.
  • LSPatch: stable v1.0 build 455 (released 2026-08-18). The newest prerelease checked was canary-460 (2026-08-19); use stable unless you are validating a specific canary fix.
  • ByteDance Android inline hook library (shadowhook): 2.0.1.
  • Android Gradle Plugin 9.3.1, Gradle 9.7.0, compile/target SDK 37, Android NDK 29.0.14206865, CMake 4.1.2, and AndroidX Annotation 1.10.0.
  • The resolved Kotlin stdlib remains 2.2.10, supplied by AGP's built-in Kotlin toolchain and ShadowHook. Do not override only the stdlib to 2.4.x; update the compiler/runtime together when a later AGP toolchain adopts it.
  • ShadowHook supports armeabi-v7a and arm64-v8a; it does not support x86/x86_64 or Houdini-translated environments.

Quick start

From this directory:

./tools/configure-template.py \
  --package com.yourname.yourmodule \
  --name "Your Module" \
  --target com.example.target \
  --author "YourName" \
  --native-lib audio_util      # optional; renames libtemplate_native.so

Then build:

./gradlew :app:assembleRelease

Install:

adb install -r app/build/outputs/apk/release/app-release.apk

Enable the module in Vector, select the target scope, then force-stop and reopen the target app:

adb shell am force-stop com.example.target
adb shell monkey -p com.example.target 1
adb logcat -c
adb logcat -s AppRuntime shadowhook_tag

Release builds silence these logs by default (BuildConfig.VERBOSE_LOGS=false). Use ./gradlew :app:installDebug while developing to get the chatty tag.

Files you normally edit first

  • app/src/main/java/com/template/lsposed/TemplateConfig.java
  • app/src/main/resources/META-INF/xposed/scope.list
  • app/src/main/resources/META-INF/xposed/module.prop
  • app/src/main/res/values/strings.xml

Modern libxposed API shape

The entry class extends io.github.libxposed.api.XposedModule and is listed in:

app/src/main/resources/META-INF/xposed/java_init.list

Hooking is interceptor-chain based:

hook(method)
    .setExceptionMode(XposedInterface.ExceptionMode.PROTECTIVE)
    .intercept(chain -> {
        Object result = chain.proceed();
        // post-call logic
        return result;
    });

Important points:

  • Keep libxposed as compileOnly; never package the framework API into the APK.
  • Keep scope tight. Do not hook every app unless you are building a framework/system module and know why.
  • Use PROTECTIVE exception mode for release builds so hook failures do not crash the target app.
  • Use deoptimize(executable) only when you actually need it; overusing deopt can hurt performance.
  • API 102 hot reload is deliberately disabled (autoHotReload=false): the template owns native hooks, a worker thread, and Activity lifecycle callbacks, so safe hot reload requires a target-specific teardown/unhook implementation first.

ShadowHook notes

ShadowHook is the recommended native inline-hook scaffold in this template because it is actively maintained and supports:

  • hook by function address or library + symbol
  • pending hooks for ELFs loaded later
  • hook modes per proxy function (shared, multi, unique)
  • instruction-level intercepts
  • linker init/fini callbacks
  • operation records for debugging

The template’s native code installs a harmless libc.so!getpid smoke-test hook and returns the original value unchanged. Replace that with your app-specific native hook only after finding stable symbols/addresses with Frida.

See docs/SHADOWHOOK_NOTES.md.

Engine-specific native workflows

The template is deliberately not IL2CPP-specific. EngineDetector is only a routing helper: use it to decide which research notes or hook installers are relevant, but keep target-specific offsets, metadata dumps, and generated analysis files out of main.

For Unity IL2CPP targets, see docs/ENGINE_NATIVE_WORKFLOWS.md. That document covers static metadata recovery, RVA-to-runtime-address mapping, value-type ABI checks, delayed library loading, and settings-bridge issues that also apply to other native-heavy engines. Treat it as a playbook for a branch that targets one app, not as default template behavior.

Non-root delivery (LSPatch)

LSPatch 1.0 uses Vector's runtime and accepts this template's modern API-102 module directly. Build the same release APK used by rooted Vector. For this template, the non-root workflow is always:

  1. embed the module with -m (never use manager mode);
  2. sign the module and every patched target split with ${HOME}/.android/debug.keystore;
  3. package the patched target APK set as target-lspatched.apks; and
  4. install that bundle with SAI (Split APKs Installer).
ANDROID_DEBUG_KEYSTORE="${HOME}/.android/debug.keystore"
test -f "$ANDROID_DEBUG_KEYSTORE"
env -u TEMPLATE_KS_PATH -u TEMPLATE_KS_PASS \
  -u TEMPLATE_KEY_ALIAS -u TEMPLATE_KEY_PASS \
  ./gradlew :app:assembleRelease

The module is already nested inside the patched base APK, so do not add app-release.apk as a separate top-level member of the .apks archive. The complete copy-paste patch, signing, bundling, verification, and SAI installation workflow is in docs/LSPATCH_NONROOT.md.

Frida-first workflow

Use Frida first to answer questions like:

  • What process and ABI am I actually in?
  • Which classes/methods are loaded?
  • Which native libraries load and when?
  • Which exported symbols exist?
  • Which Java methods or native symbols are stable enough to become permanent libxposed/ShadowHook hooks?

Use the latest undetected Frida server linked in docs/FRIDA_EMULATOR_QUICKSTART.md for this workflow. Keep the host frida-tools version and device frida-server version aligned, and do not mix these steps with stock frida-server unless you are intentionally debugging a version/build mismatch.

See docs/FRIDA_EMULATOR_QUICKSTART.md.

Moving the menu panel

Tap the Nyx bubble to open the rectangular display. Drag the title/subtitle header area to move the open panel. The bubble itself is also draggable.

Architecture warning

If you use an x86/x86_64 emulator, Java libxposed hooks can still work, but the native ShadowHook scaffold will not. For native inline-hook testing, use a real arm64 device or an arm64 emulator image on Apple Silicon.

Repository files

  • LICENSE — CC BY-NC-ND 4.0 license notice and official license links.
  • SECURITY.md — safe issue-reporting expectations.
  • CONTRIBUTING.md — contribution and validation expectations.
  • docs/ENGINE_NATIVE_WORKFLOWS.md — optional notes for Unity IL2CPP and native-heavy targets.
  • docs/LSPATCH_NONROOT.md — non-root delivery via LSPatch 1.0 (modes, splits, signing, CLI).
  • .github/workflows/android.yml — GitHub Actions build for debug and release APKs.

License

This project is licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC-BY-NC-ND-4.0). You may share the unmodified template with attribution for non-commercial use. Do not distribute modified versions without separate permission.

About

Reusable Android LSPosed/Xposed runtime instrumentation template with engine detection, native utilities, overlays, and feature toggles

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages