Clean hook
This commit is contained in:
parent
a10c8276c9
commit
0ef781a693
27
README.md
27
README.md
|
|
@ -14,33 +14,22 @@ LSPatch provides a way to insert dex and so into the target APK by repackaging.
|
||||||
1. download the artifact
|
1. download the artifact
|
||||||
1. run `java -jar lspatch.jar`
|
1. run `java -jar lspatch.jar`
|
||||||
|
|
||||||
|
## Dev
|
||||||
|
|
||||||
|
```
|
||||||
|
Android Studio Arctic Fox | 2020.3.1 +
|
||||||
|
```
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```
|
```
|
||||||
Android Studio Arctic Fox | 2020.3.1 Beta 3
|
gradlew build<Debug|Release>
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
||||||
gradlew build[Debug|Release]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Android Versions
|
## Supported Android Versions
|
||||||
Same with [LSPosed](
|
|
||||||
https://github.com/LSPosed/LSPosed#supported-versions)
|
|
||||||
|
|
||||||
## Principle
|
In theory, same with [LSPosed](https://github.com/LSPosed/LSPosed#supported-versions)
|
||||||
|
|
||||||
1. Decompress target APK.
|
|
||||||
1. Patch the app property of AndroidManifest.xml in the target APK, changing it to the Application class in the inserted dex.
|
|
||||||
1. Copy all files in `list-so`, `list-assets`, `list-dex` into target APK.
|
|
||||||
1. Package and sign target APK.
|
|
||||||
|
|
||||||
Running Stage:
|
|
||||||
1. Inserted dex initializes LSPosed
|
|
||||||
1. New ClassLoader from `assets/lsploader.dex`.
|
|
||||||
1. Loads the Xposed module installed in the system with new ClassLoader.
|
|
||||||
|
|
||||||
## Known issues
|
## Known issues
|
||||||
|
|
||||||
1. Can't solve the signature verification issue perfectly
|
1. Can't solve the signature verification issue perfectly
|
||||||
1. If you use under Windows, you need open `CMD/Powershell` with `Run as Administrator`, See [Code](https://github.com/LSPosed/LSPatch/blob/ab1a213161f90ec7ac604df47434201170b92b9a/patch/src/main/java/org/lsposed/patch/util/FileUtils.java#L67-L70).
|
|
||||||
|
|
|
||||||
|
|
@ -68,8 +68,6 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
private static ClassLoader appClassLoader;
|
private static ClassLoader appClassLoader;
|
||||||
private static Object activityThread;
|
private static Object activityThread;
|
||||||
|
|
||||||
private static int TRANSACTION_getPackageInfo_ID = -1;
|
|
||||||
|
|
||||||
final static public int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
final static public int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000;
|
||||||
final static public int PER_USER_RANGE = 100000;
|
final static public int PER_USER_RANGE = 100000;
|
||||||
|
|
||||||
|
|
@ -277,27 +275,14 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void byPassSignature(Context context) throws ClassNotFoundException, IllegalAccessException {
|
private static int getTranscationId(String clsName, String trasncationName) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
|
||||||
Field[] pmStubFields = Class.forName("android.content.pm.IPackageManager$Stub").getDeclaredFields();
|
Field field = Class.forName(clsName).getDeclaredField(trasncationName);
|
||||||
for (Field field : pmStubFields) {
|
|
||||||
if (!Modifier.isStatic(field.getModifiers()) || field.getType() != int.class) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
int fieldValue = field.getInt(null);
|
return field.getInt(null);
|
||||||
String fieldName = field.getName();
|
|
||||||
field.setAccessible(false);
|
|
||||||
|
|
||||||
if (fieldName.equals("TRANSACTION_getPackageInfo")) {
|
|
||||||
TRANSACTION_getPackageInfo_ID = fieldValue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TRANSACTION_getPackageInfo_ID == -1) {
|
|
||||||
throw new IllegalStateException("getPackageInfo transaction id null");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void byPassSignature(Context context) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException {
|
||||||
|
final int TRANSACTION_getPackageInfo = getTranscationId("android.content.pm.IPackageManager$Stub", "TRANSACTION_getPackageInfo");
|
||||||
XposedHelpers.findAndHookMethod("android.os.BinderProxy", appClassLoader, "transact", int.class, Parcel.class, Parcel.class, int.class, new XC_MethodHook() {
|
XposedHelpers.findAndHookMethod("android.os.BinderProxy", appClassLoader, "transact", int.class, Parcel.class, Parcel.class, int.class, new XC_MethodHook() {
|
||||||
@Override
|
@Override
|
||||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||||
|
|
@ -322,7 +307,7 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
if (desc == null || desc.isEmpty() || !desc.equals("android.content.pm.IPackageManager")) {
|
if (desc == null || desc.isEmpty() || !desc.equals("android.content.pm.IPackageManager")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id == TRANSACTION_getPackageInfo_ID) {
|
if (id == TRANSACTION_getPackageInfo) {
|
||||||
out.readException();
|
out.readException();
|
||||||
if (0 != out.readInt()) {
|
if (0 != out.readInt()) {
|
||||||
PackageInfo packageInfo = PackageInfo.CREATOR.createFromParcel(out);
|
PackageInfo packageInfo = PackageInfo.CREATOR.createFromParcel(out);
|
||||||
|
|
@ -352,13 +337,14 @@ public class LSPApplication extends ApplicationServiceClient {
|
||||||
out.setDataPosition(0);
|
out.setDataPosition(0);
|
||||||
}
|
}
|
||||||
} catch (Throwable err) {
|
} catch (Throwable err) {
|
||||||
err.printStackTrace();
|
// should not happen, just crash app
|
||||||
|
throw new IllegalStateException("lsp hook error", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void doHook(Context context) throws IllegalAccessException, ClassNotFoundException, IOException {
|
private static void doHook(Context context) throws IllegalAccessException, ClassNotFoundException, IOException, NoSuchFieldException {
|
||||||
if (isApplicationProxied()) {
|
if (isApplicationProxied()) {
|
||||||
hookContextImplSetOuterContext();
|
hookContextImplSetOuterContext();
|
||||||
hookInstallContentProviders();
|
hookInstallContentProviders();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ import java.util.jar.JarFile;
|
||||||
public class LSPatch {
|
public class LSPatch {
|
||||||
|
|
||||||
static class PatchError extends Error {
|
static class PatchError extends Error {
|
||||||
|
public PatchError(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
PatchError(String message) {
|
PatchError(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
@ -254,7 +258,8 @@ public class LSPatch {
|
||||||
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("armeabi") ? "armeabi-v7a" : arch) + "/liblspd.so")) {
|
try (var is = getClass().getClassLoader().getResourceAsStream("assets/so/" + (arch.equals("armeabi") ? "armeabi-v7a" : arch) + "/liblspd.so")) {
|
||||||
zFile.add(entryName, is, false); // no compress for so
|
zFile.add(entryName, is, false); // no compress for so
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new PatchError("Error when adding native lib: " + e);
|
// More exception info
|
||||||
|
throw new PatchError("Error when adding native lib", e);
|
||||||
}
|
}
|
||||||
if (verbose)
|
if (verbose)
|
||||||
System.out.println("added " + entryName);
|
System.out.println("added " + entryName);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue