add loader's loader

This commit is contained in:
327135569 2021-04-24 11:29:36 +08:00
parent 2da58b2ab9
commit ab1a213161
7 changed files with 192 additions and 0 deletions

1
appstub/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

62
appstub/build.gradle Normal file
View File

@ -0,0 +1,62 @@
apply plugin: 'com.android.application'
android {
compileSdk 30
buildToolsVersion "30.0.3"
defaultConfig {
minSdk rootProject.ext.androidMinSdkVersion
targetSdk rootProject.ext.androidTargetSdkVersion
versionCode 1
versionName "1.0"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
applicationVariants.all { variant ->
def buildType = variant.name.capitalize()
def variantLowered = variant.name.toLowerCase()
variant.outputs.all {
outputFileName = "${variant.getFlavorName()}-${variant.versionName}.apk"
}
task "copyDex$buildType"(type: Copy) {
dependsOn("assemble$buildType")
def dexFilePath = "$buildDir/intermediates/dex/${variantLowered}/mergeDex${buildType}/classes.dex"
from dexFilePath
rename "(.*).dex", "classes-${version_name}.dex"
into "$rootProject.projectDir/out/list-dex"
}
task "copySo$buildType"(type: Copy) {
dependsOn("assemble$buildType")
from "$buildDir/intermediates/merged_native_libs/${variantLowered}/out/lib"
into "$rootProject.projectDir/out/list-so"
}
task "copy$buildType"() {
dependsOn("copySo$buildType")
dependsOn("copyDex$buildType")
doLast {
System.out.println("Dex and so files has been copy to ${rootProject.projectDir}${File.separator}out")
}
}
}
}
dependencies {
implementation project(':share')
compileOnly project(":hiddenapi-stubs")
}

View File

21
appstub/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lsposed.lspatch.appstub">
</manifest>

View File

@ -0,0 +1,102 @@
package org.lsposed.lspatch.appstub;
import android.app.ActivityThread;
import android.app.Application;
import android.content.Context;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import dalvik.system.InMemoryDexClassLoader;
public class LSPApplicationSub extends Application {
final static String TAG = LSPApplicationSub.class.getSimpleName();
static Object realLSPApplication = null;
static {
// load real lsp loader from asset
Context context = createAppContext();
if (context == null) {
Log.e(TAG, "create context err");
}
else {
try {
InputStream inputStream = context.getAssets().open("lsploader.dex");
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
InMemoryDexClassLoader inMemoryDexClassLoader = new InMemoryDexClassLoader(ByteBuffer.wrap(buffer.toByteArray()), LSPApplicationSub.class.getClassLoader());
Class<?> lspa = inMemoryDexClassLoader.loadClass("org.lsposed.lspatch.appstub.LSPApplication");
realLSPApplication = lspa.newInstance();
}
catch (Exception e) {
throw new IllegalStateException("wtf", e);
}
}
}
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
if (realLSPApplication != null) {
try {
realLSPApplication.getClass().getMethod("attachBaseContext", Context.class).invoke(realLSPApplication, base);
}
catch (Exception e) {
throw new IllegalStateException("wtf", e);
}
}
}
// copy from app project
public static Context createAppContext() {
try {
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method currentActivityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");
currentActivityThreadMethod.setAccessible(true);
Object activityThreadObj = currentActivityThreadMethod.invoke(null);
Field boundApplicationField = activityThreadClass.getDeclaredField("mBoundApplication");
boundApplicationField.setAccessible(true);
Object mBoundApplication = boundApplicationField.get(activityThreadObj); // AppBindData
if (mBoundApplication == null) {
Log.e(TAG, "mBoundApplication null");
return null;
}
Field infoField = mBoundApplication.getClass().getDeclaredField("info"); // info
infoField.setAccessible(true);
Object loadedApkObj = infoField.get(mBoundApplication); // LoadedApk
if (loadedApkObj == null) {
Log.e(TAG, "loadedApkObj null");
return null;
}
Class<?> contextImplClass = Class.forName("android.app.ContextImpl");
Method createAppContextMethod = contextImplClass.getDeclaredMethod("createAppContext", activityThreadClass, loadedApkObj.getClass());
createAppContextMethod.setAccessible(true);
Object context = createAppContextMethod.invoke(null, (ActivityThread) activityThreadObj, loadedApkObj);
if (context instanceof Context) {
return (Context) context;
}
}
catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -13,3 +13,4 @@ project(':manager-service').projectDir = new File('mmp/manager-service')
include ':patch'
include ':axmlprinter'
include ':share'
include ':appstub'