feat:增加自定义linker注入

This commit is contained in:
jiqiu2021
2025-06-26 19:59:33 +08:00
parent eb41d924b4
commit d793712a13
27 changed files with 2055 additions and 34 deletions

View File

@@ -29,8 +29,8 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
coreLibraryDesugaringEnabled false
}
}

View File

@@ -13,6 +13,8 @@ import android.widget.ProgressBar;
import android.app.Dialog;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -134,15 +136,24 @@ public class AppListFragment extends Fragment implements AppListAdapter.OnAppTog
TextView packageName = dialogView.findViewById(R.id.packageName);
RecyclerView soListRecyclerView = dialogView.findViewById(R.id.soListRecyclerView);
TextView emptyText = dialogView.findViewById(R.id.emptyText);
SwitchMaterial switchHideInjection = dialogView.findViewById(R.id.switchHideInjection);
RadioGroup injectionMethodGroup = dialogView.findViewById(R.id.injectionMethodGroup);
RadioButton radioStandardInjection = dialogView.findViewById(R.id.radioStandardInjection);
RadioButton radioRiruInjection = dialogView.findViewById(R.id.radioRiruInjection);
RadioButton radioCustomLinkerInjection = dialogView.findViewById(R.id.radioCustomLinkerInjection);
appIcon.setImageDrawable(appInfo.getAppIcon());
appName.setText(appInfo.getAppName());
packageName.setText(appInfo.getPackageName());
// Load current config
boolean hideInjection = configManager.getHideInjection();
switchHideInjection.setChecked(hideInjection);
String injectionMethod = configManager.getAppInjectionMethod(appInfo.getPackageName());
if ("custom_linker".equals(injectionMethod)) {
radioCustomLinkerInjection.setChecked(true);
} else if ("riru".equals(injectionMethod)) {
radioRiruInjection.setChecked(true);
} else {
radioStandardInjection.setChecked(true);
}
// Setup SO list
List<ConfigManager.SoFile> globalSoFiles = configManager.getAllSoFiles();
@@ -165,8 +176,16 @@ public class AppListFragment extends Fragment implements AppListAdapter.OnAppTog
.setTitle("配置注入")
.setView(dialogView)
.setPositiveButton("保存", (dialog, which) -> {
// Save hide injection setting
configManager.setHideInjection(switchHideInjection.isChecked());
// Save injection method
String selectedMethod;
if (radioCustomLinkerInjection.isChecked()) {
selectedMethod = "custom_linker";
} else if (radioRiruInjection.isChecked()) {
selectedMethod = "riru";
} else {
selectedMethod = "standard";
}
configManager.setAppInjectionMethod(appInfo.getPackageName(), selectedMethod);
// Save SO selection
if (soListRecyclerView.getAdapter() != null) {

View File

@@ -227,6 +227,24 @@ public class ConfigManager {
saveConfig();
}
public String getAppInjectionMethod(String packageName) {
AppConfig appConfig = config.perAppConfig.get(packageName);
if (appConfig == null) {
return "standard"; // Default to standard
}
return appConfig.injectionMethod != null ? appConfig.injectionMethod : "standard";
}
public void setAppInjectionMethod(String packageName, String method) {
AppConfig appConfig = config.perAppConfig.get(packageName);
if (appConfig == null) {
appConfig = new AppConfig();
config.perAppConfig.put(packageName, appConfig);
}
appConfig.injectionMethod = method;
saveConfig();
}
// Copy SO files directly to app's data directory
private void deploySoFilesToApp(String packageName) {
AppConfig appConfig = config.perAppConfig.get(packageName);
@@ -384,6 +402,7 @@ public class ConfigManager {
public static class AppConfig {
public boolean enabled = false;
public List<SoFile> soFiles = new ArrayList<>();
public String injectionMethod = "standard"; // "standard", "riru" or "custom_linker"
}
public static class SoFile {

View File

@@ -77,20 +77,66 @@
android:textColor="?android:attr/textColorTertiary"
android:visibility="gone" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/switchHideInjection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="隐藏注入"
android:layout_marginTop="8dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="使用Riru Hide隐藏注入的SO文件"
android:textSize="12sp"
android:text="注入方式"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginStart="56dp"
android:layout_marginTop="4dp" />
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp" />
<RadioGroup
android:id="@+id/injectionMethodGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/radioStandardInjection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="标准注入"
android:checked="true" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginBottom="8dp"
android:text="使用标准dlopen方式注入"
android:textColor="?android:attr/textColorSecondary"
android:textSize="12sp" />
<RadioButton
android:id="@+id/radioRiruInjection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Riru注入" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="使用Riru Hide隐藏注入的SO文件"
android:textSize="12sp"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginStart="32dp"
android:layout_marginBottom="8dp" />
<RadioButton
android:id="@+id/radioCustomLinkerInjection"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="自定义Linker注入" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="使用自定义ELF加载器进行注入"
android:textSize="12sp"
android:textColor="?android:attr/textColorSecondary"
android:layout_marginStart="32dp" />
</RadioGroup>
</LinearLayout>