Skip to content

Latest commit

Β 

History

History
178 lines (159 loc) Β· 4.18 KB

File metadata and controls

178 lines (159 loc) Β· 4.18 KB

Building a Custom LSPosed Module

Template for creating your own Xposed/LSPosed module.

Module structure

MyModule/
β”œβ”€β”€ common/
β”‚   β”œβ”€β”€ system.prop       # optional system properties
β”‚   └── service.sh        # optional post-fs-data script
β”œβ”€β”€ src/main/
β”‚   β”œβ”€β”€ AndroidManifest.xml
β”‚   └── java/com/example/mymodule/
β”‚       └── MainHook.java
β”œβ”€β”€ module.prop           # metadata
β”œβ”€β”€ build.gradle
└── README.md

1. module.prop

id=my_xposed_module
name=My Cool Module
version=1.0
versionCode=1
author=YourName
description=Does something cool with Xposed
minApi=31

2. MainHook.java (LSPosed)

package com.example.mymodule;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import de.robv.android.xposed.XposedHelpers;

public class MainHook implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
        if (!lpparam.packageName.equals("com.example.targetapp")) {
            return;
        }

        // Hook a method
        XposedHelpers.findAndHookMethod(
            "com.example.targetapp.MainActivity",
            lpparam.classLoader,
            "onCreate",
            android.os.Bundle.class,
            new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) {
                    // Your code here
                    XposedHelpers.callMethod(param.thisObject, "setTitle", "Hooked!");
                }
            }
        );
    }
}

3. AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.mymodule">

    <application
        android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher">
        <meta-data
            android:name="xposedmodule"
            android:value="true" />
        <meta-data
            android:name="xposedminversion"
            android:value="90" />
        <meta-data
            android:name="xposeddescription"
            android:value="@string/module_description" />
    </application>
</manifest>

4. build.gradle

plugins {
    id 'com.android.application'
}

android {
    compileSdk 33
    defaultConfig {
        applicationId "com.example.mymodule"
        minSdk 31
        targetSdk 33
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
        }
    }
}

dependencies {
    compileOnly 'de.robv.android.xposed:api:82'
}

5. Build & install

./gradlew build
adb install build/outputs/apk/release/app-release.apk
# Then enable in LSPosed Manager

Common hooks

Hook constructor

XposedHelpers.findAndHookConstructor(
    "com.example.Class",
    lpparam.classLoader,
    String.class,
    new XC_MethodHook() {
        protected void afterHookedMethod(MethodHookParam param) {
            // param.args[0] = first String arg
        }
    }
);

Replace method return

XposedHelpers.findAndHookMethod(
    "com.example.Class",
    lpparam.classLoader,
    "isRooted",
    new XC_MethodReplacement() {
        protected Object replaceHookedMethod(MethodHookParam param) {
            return false;  // Always return false
        }
    }
);

Hook void methods

XposedHelpers.findAndHookMethod(
    "android.app.Activity",
    lpparam.classLoader,
    "onCreate",
    Bundle.class,
    new XC_MethodHook() {
        protected void beforeHookedMethod(MethodHookParam param) {
            // Run before onCreate
        }
        protected void afterHookedMethod(MethodHookParam param) {
            // Run after onCreate
        }
    }
);

Testing

  1. Create test app with target activities
  2. Enable module in LSPosed
  3. Reload Xposed scope
  4. Verify hook fires via logcat
  5. Check XposedBridge.log() for debug output

Resources