Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ jobs:
with:
repository: libxposed/api
path: libxposed/api
ref: 54582730315ba4a3d7cfaf9baf9d23c419e07006

- name: Checkout libxposed/service
uses: actions/checkout@v4
Expand Down
9 changes: 7 additions & 2 deletions core/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-keep class android.** { *; }
-keep class de.robv.android.xposed.** {*;}
-keep class io.github.libxposed.** {*;}
-keep class org.lsposed.lspd.annotation.* {*;}
-keep class org.lsposed.lspd.core.* {*;}
-keep class org.lsposed.lspd.hooker.HandleSystemServerProcessHooker {*;}
-keep class org.lsposed.lspd.hooker.HandleSystemServerProcessHooker$Callback {*;}
Expand All @@ -22,9 +23,13 @@
-keepclassmembers class org.lsposed.lspd.impl.LSPosedHookCallback {
public <methods>;
}
-keepclassmembers,allowoptimization class ** implements io.github.libxposed.api.XposedInterface$Hooker {
public *** before(***);
public *** after(***);
}
-keep,allowoptimization,allowobfuscation @io.github.libxposed.api.annotations.* class * {
@io.github.libxposed.api.annotations.BeforeInvocation <methods>;
@io.github.libxposed.api.annotations.AfterInvocation <methods>;
public *** before(***);
public *** after(***);
}
-assumenosideeffects class android.util.Log {
public static *** v(...);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,10 @@
package de.robv.android.xposed.callbacks;

import android.content.res.XResources;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.concurrent.CopyOnWriteArraySet;

import de.robv.android.xposed.IXposedHookInitPackageResources;
import io.github.libxposed.api.XposedModuleInterface;

/**
* This class is only used for internal purposes, except for the {@link InitPackageResourcesParam}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,10 @@
package de.robv.android.xposed.callbacks;

import android.content.pm.ApplicationInfo;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.concurrent.CopyOnWriteArraySet;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XposedBridge.CopyOnWriteSortedSet;
import io.github.libxposed.api.XposedModuleInterface;

/**
* This class is only used for internal purposes, except for the {@link LoadPackageParam}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.libxposed.api.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterInvocation {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.libxposed.api.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeInvocation {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.github.libxposed.api.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.TYPE_USE})
public @interface XposedHooker {
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

package org.lsposed.lspd.core;

import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/org/lsposed/lspd/core/Startup.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
import org.lsposed.lspd.hooker.AttachHooker;
import org.lsposed.lspd.hooker.CrashDumpHooker;
import org.lsposed.lspd.hooker.HandleSystemServerProcessHooker;
import org.lsposed.lspd.hooker.LoadedApkCtorHooker;
import org.lsposed.lspd.hooker.LoadedApkCreateCLHooker;
import org.lsposed.lspd.hooker.LoadedApkCtorHooker;
import org.lsposed.lspd.hooker.OpenDexFileHooker;
import org.lsposed.lspd.impl.LSPosedContext;
import org.lsposed.lspd.impl.LSPosedHelper;
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/org/lsposed/lspd/hooker/AttachHooker.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

import android.app.ActivityThread;

import androidx.annotation.NonNull;

import de.robv.android.xposed.XposedInit;
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

@XposedHooker
public class AttachHooker implements XposedInterface.Hooker {

@AfterInvocation
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
public static void after(@NonNull XposedInterface.AfterHookCallback callback) {
XposedInit.loadModules((ActivityThread) callback.getThisObject());
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package org.lsposed.lspd.hooker;

import androidx.annotation.NonNull;

import org.lsposed.lspd.impl.LSPosedBridge;
import org.lsposed.lspd.util.Utils.Log;

import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.BeforeInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

@XposedHooker
public class CrashDumpHooker implements XposedInterface.Hooker {

@BeforeInvocation
public static void beforeHookedMethod(XposedInterface.BeforeHookCallback callback) {
public static void before(@NonNull XposedInterface.BeforeHookCallback callback) {
try {
var e = (Throwable) callback.getArgs()[0];
LSPosedBridge.log("Crash unexpectedly: " + Log.getStackTraceString(e));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.lsposed.lspd.util.Hookers;

import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

// system_server initialization
Expand All @@ -42,8 +41,7 @@ public interface Callback {
public static volatile Callback callback = null;

@SuppressLint("PrivateApi")
@AfterInvocation
public static void afterHookedMethod() {
public static void after() {
Hookers.logD("ZygoteInit#handleSystemServerProcess() starts");
try {
// get system_server classLoader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.XposedModuleInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

@SuppressLint("BlockedPrivateApi")
Expand All @@ -77,8 +76,7 @@ static void addLoadedApk(LoadedApk loadedApk) {
loadedApks.add(loadedApk);
}

@AfterInvocation
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
public static void after(@NonNull XposedInterface.AfterHookCallback callback) {
LoadedApk loadedApk = (LoadedApk) callback.getThisObject();

if (callback.getArgs()[0] != null || !loadedApks.contains(loadedApk)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,13 @@
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.XposedInit;
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

// when a package is loaded for an existing process, trigger the callbacks as well
@XposedHooker
public class LoadedApkCtorHooker implements XposedInterface.Hooker {

@AfterInvocation
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
public static void after(XposedInterface.AfterHookCallback callback) {
Hookers.logD("LoadedApk#<init> starts");

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@

import android.os.Build;

import androidx.annotation.NonNull;

import org.lsposed.lspd.impl.LSPosedBridge;
import org.lsposed.lspd.nativebridge.HookBridge;

import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

@XposedHooker
public class OpenDexFileHooker implements XposedInterface.Hooker {

@AfterInvocation
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) {
public static void after(@NonNull XposedInterface.AfterHookCallback callback) {
ClassLoader classLoader = null;
for (var arg : callback.getArgs()) {
if (arg instanceof ClassLoader) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,12 @@
import de.robv.android.xposed.callbacks.XC_LoadPackage;
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.XposedModuleInterface;
import io.github.libxposed.api.annotations.BeforeInvocation;
import io.github.libxposed.api.annotations.XposedHooker;

@XposedHooker
public class StartBootstrapServicesHooker implements XposedInterface.Hooker {

@BeforeInvocation
public static void beforeHookedMethod() {
public static void before(@NonNull XposedInterface.BeforeHookCallback callback) {
logD("SystemServer#startBootstrapServices() starts");

try {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/java/org/lsposed/lspd/impl/LSPosedBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ public static void dummyCallback() {
Method beforeInvocation = null, afterInvocation = null;
var modifiers = Modifier.PUBLIC | Modifier.STATIC;
for (var method : hooker.getDeclaredMethods()) {
if (method.getAnnotation(BeforeInvocation.class) != null) {
if (method.getAnnotation(BeforeInvocation.class) != null || "before".equals(method.getName()) || "beforeHookedMethod".equals(method.getName())) {
if (beforeInvocation != null) {
throw new IllegalArgumentException("More than one method annotated with @BeforeInvocation");
}
Expand All @@ -241,7 +241,7 @@ public static void dummyCallback() {
}
beforeInvocation = method;
}
if (method.getAnnotation(AfterInvocation.class) != null) {
if (method.getAnnotation(AfterInvocation.class) != null || "after".equals(method.getName()) || "afterHookedMethod".equals(method.getName())) {
if (afterInvocation != null) {
throw new IllegalArgumentException("More than one method annotated with @AfterInvocation");
}
Expand Down
37 changes: 37 additions & 0 deletions core/src/main/java/org/lsposed/lspd/impl/LSPosedContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.XposedModule;
import io.github.libxposed.api.XposedModuleInterface;
import io.github.libxposed.api.errors.HookFailedError;
import io.github.libxposed.api.errors.XposedFrameworkError;
import io.github.libxposed.api.utils.DexParser;

Expand Down Expand Up @@ -170,6 +171,32 @@ public MethodUnhooker<Method> hook(@NonNull Method origin, @NonNull Class<? exte
return LSPosedBridge.doHook(origin, PRIORITY_DEFAULT, hooker);
}

@NonNull
@Override
public <T> MethodUnhooker<Constructor<T>> hookClassInitializer(@NonNull Class<T> origin, @NonNull Class<? extends Hooker> hooker) {
return hookClassInitializer(origin, PRIORITY_DEFAULT, hooker);
}

@NonNull
@Override
public <T> MethodUnhooker<Constructor<T>> hookClassInitializer(@NonNull Class<T> origin, int priority, @NonNull Class<? extends Hooker> hooker) {
try {
final var typeParams = hooker.getTypeParameters();
final Class<?>[] typeParamsArray = new Class<?>[typeParams.length];
for (int i = 0; i < typeParams.length; i++) {
try {
typeParamsArray[i] = origin.getClassLoader().loadClass(typeParams[i].getTypeName());
} catch (Throwable e) {
typeParamsArray[i] = Object.class;
}
}

return LSPosedBridge.doHook(origin.getDeclaredConstructor(typeParamsArray), priority, hooker);
} catch (Throwable e) {
throw new HookFailedError(e);
}
}

@Override
@NonNull
public MethodUnhooker<Method> hook(@NonNull Method origin, int priority, @NonNull Class<? extends Hooker> hooker) {
Expand Down Expand Up @@ -213,6 +240,11 @@ public Object invokeOrigin(@NonNull Method method, @Nullable Object thisObject,
return HookBridge.invokeOriginalMethod(method, thisObject, args);
}

@Override
public <T> void invokeOrigin(@NonNull Constructor<T> constructor, @NonNull T thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException {
HookBridge.invokeOriginalMethod(constructor, thisObject, args);
}

private static char getTypeShorty(Class<?> type) {
if (type == int.class) {
return 'I';
Expand Down Expand Up @@ -256,6 +288,11 @@ public Object invokeSpecial(@NonNull Method method, @NonNull Object thisObject,
return HookBridge.invokeSpecialMethod(method, getExecutableShorty(method), method.getDeclaringClass(), thisObject, args);
}

@Override
public <T> void invokeSpecial(@NonNull Constructor<T> constructor, @NonNull T thisObject, Object... args) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException {
HookBridge.invokeSpecialMethod(constructor, getExecutableShorty(constructor), constructor.getDeclaringClass(), thisObject, args);
}

@NonNull
@Override
public <T> T newInstanceOrigin(@NonNull Constructor<T> constructor, Object... args) throws InvocationTargetException, IllegalAccessException, InstantiationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;

import org.lsposed.lspd.util.Utils.Log;

import java.io.File;
import java.io.IOException;
import java.net.URL;
Expand All @@ -24,8 +26,6 @@
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import org.lsposed.lspd.util.Utils.Log;

import hidden.ByteBufferDexClassLoader;
import sun.misc.CompoundEnumeration;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
import org.lsposed.lspd.hooker.HandleSystemServerProcessHooker;
import org.lsposed.lspd.impl.LSPosedHelper;
import org.lsposed.lspd.service.BridgeService;
import org.lsposed.lspd.util.Utils;

import io.github.libxposed.api.XposedInterface;
import io.github.libxposed.api.annotations.AfterInvocation;
import io.github.libxposed.api.annotations.XposedHooker;


public class ParasiticManagerSystemHooker implements HandleSystemServerProcessHooker.Callback {
public static void start() {
HandleSystemServerProcessHooker.callback = new ParasiticManagerSystemHooker();
Expand All @@ -35,8 +32,7 @@ public static void beforeHookedMethod(XposedInterface.BeforeHookCallback callbac

@XposedHooker
private static class Hooker implements XposedInterface.Hooker {
@AfterInvocation
public static void afterHookedMethod(XposedInterface.AfterHookCallback callback) throws Throwable {
public static void after(XposedInterface.AfterHookCallback callback) throws Throwable {
var intent = (Intent) callback.getArgs()[0];
if (intent == null) return;
if (!intent.hasCategory("org.lsposed.manager.LAUNCH_MANAGER")) return;
Expand Down