diff --git a/Kill.apk b/Kill.apk index 1c800bf..81ff1c0 100644 Binary files a/Kill.apk and b/Kill.apk differ diff --git a/hellodaemon/build.gradle b/hellodaemon/build.gradle index 4ab8b6d..a1ab0ac 100644 --- a/hellodaemon/build.gradle +++ b/hellodaemon/build.gradle @@ -26,11 +26,11 @@ ext { android { compileSdkVersion 26 - buildToolsVersion "26.0.2" + buildToolsVersion "27.0.2" defaultConfig { minSdkVersion 14 - targetSdkVersion 26 + targetSdkVersion 27 versionCode 11 versionName "1.2.2" } diff --git a/sample/build.gradle b/sample/build.gradle index c937537..b18e156 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -2,11 +2,11 @@ apply plugin: 'com.android.application' android { compileSdkVersion 26 - buildToolsVersion "26.0.2" + buildToolsVersion "27.0.2" defaultConfig { applicationId "com.xdandroid.sample" minSdkVersion 14 - targetSdkVersion 26 + targetSdkVersion 27 versionCode 1 versionName "1.0.0" } @@ -22,6 +22,5 @@ android { } dependencies { - api 'io.reactivex.rxjava2:rxjava:2.+' api project(':hellodaemon') } diff --git a/sample/src/main/java/com/xdandroid/sample/misc/BootReceiver.java b/sample/src/main/java/com/xdandroid/sample/misc/BootReceiver.java new file mode 100644 index 0000000..bc0cdaf --- /dev/null +++ b/sample/src/main/java/com/xdandroid/sample/misc/BootReceiver.java @@ -0,0 +1,26 @@ +package com.xdandroid.sample.misc; + +import android.content.*; + +/** + * uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" + * action android:name="android.intent.action.BOOT_COMPLETED" + */ +public class BootReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + context = context.getApplicationContext(); + Context c = context; + new Thread(() -> { + Intent revokeIntent = new Intent(c, RevokeActivity.class); + revokeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + c.startActivity(revokeIntent); + try { Thread.sleep(5 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } + Intent serverIntent = new Intent(); + serverIntent.setComponent(new ComponentName("com.xdandroid.server", "com.xdandroid.server.TargetActivity")); + serverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + c.startActivity(serverIntent); + }).start(); + } +} diff --git a/sample/src/main/java/com/xdandroid/sample/misc/GenOpsActivity.java b/sample/src/main/java/com/xdandroid/sample/misc/GenOpsActivity.java index 1efaf90..8a0b7fa 100644 --- a/sample/src/main/java/com/xdandroid/sample/misc/GenOpsActivity.java +++ b/sample/src/main/java/com/xdandroid/sample/misc/GenOpsActivity.java @@ -12,6 +12,7 @@ public class GenOpsActivity extends Activity implements Utils { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; + setPermissive(); if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, hashCode()); finish(); diff --git a/sample/src/main/java/com/xdandroid/sample/misc/KillActivity.java b/sample/src/main/java/com/xdandroid/sample/misc/KillActivity.java index 6bff55b..5df5d45 100644 --- a/sample/src/main/java/com/xdandroid/sample/misc/KillActivity.java +++ b/sample/src/main/java/com/xdandroid/sample/misc/KillActivity.java @@ -16,6 +16,7 @@ public class KillActivity extends Activity implements Utils { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; + setPermissive(); new Thread(() -> { try { Method m = ActivityManager.class.getMethod("forceStopPackage", String.class); diff --git a/sample/src/main/java/com/xdandroid/sample/misc/RevokeActivity.java b/sample/src/main/java/com/xdandroid/sample/misc/RevokeActivity.java index d4ffe26..9140cd1 100644 --- a/sample/src/main/java/com/xdandroid/sample/misc/RevokeActivity.java +++ b/sample/src/main/java/com/xdandroid/sample/misc/RevokeActivity.java @@ -18,6 +18,7 @@ public class RevokeActivity extends Activity implements Utils { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; + setPermissive(); new Thread(() -> { try { PackageManager pm = getPackageManager(); diff --git a/sample/src/main/java/com/xdandroid/sample/misc/ShellUtils.java b/sample/src/main/java/com/xdandroid/sample/misc/ShellUtils.java new file mode 100644 index 0000000..834b3ea --- /dev/null +++ b/sample/src/main/java/com/xdandroid/sample/misc/ShellUtils.java @@ -0,0 +1,65 @@ +package com.xdandroid.sample.misc; + +import java.io.*; + +interface ShellUtils { + + String COMMAND_SU = "su"; + String COMMAND_SH = "sh"; + String COMMAND_EXIT = "exit\n"; + String COMMAND_LINE_END = "\n"; + + default CommandResult execCommand(String[] commands, boolean isRoot) { + int result = -1; + if (commands == null || commands.length == 0) return new CommandResult(result, null, null); + Process process = null; + BufferedReader successResult = null; + BufferedReader errorResult = null; + StringBuilder successMsg = null; + StringBuilder errorMsg = null; + DataOutputStream os = null; + try { + process = Runtime.getRuntime().exec(isRoot ? COMMAND_SU : COMMAND_SH); + os = new DataOutputStream(process.getOutputStream()); + for (String command : commands) { + if (command == null) continue; + os.write(command.getBytes()); + os.writeBytes(COMMAND_LINE_END); + os.flush(); + } + os.writeBytes(COMMAND_EXIT); + os.flush(); + result = process.waitFor(); + successMsg = new StringBuilder(); + errorMsg = new StringBuilder(); + successResult = new BufferedReader(new InputStreamReader(process.getInputStream())); + errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream())); + String s; + while ((s = successResult.readLine()) != null) successMsg.append(s); + while ((s = errorResult.readLine()) != null) errorMsg.append(s); + } catch (Exception e) { + e.printStackTrace(); + } finally { + try { + if (os != null) os.close(); + if (successResult != null) successResult.close(); + if (errorResult != null) errorResult.close(); + } catch (IOException e) { e.printStackTrace(); } + if (process != null) process.destroy(); + } + return new CommandResult(result, successMsg == null ? null : successMsg.toString(), errorMsg == null ? null : errorMsg.toString()); + } + + class CommandResult { + + int result; + String successMsg; + String errorMsg; + + CommandResult(int result, String successMsg, String errorMsg) { + this.result = result; + this.successMsg = successMsg; + this.errorMsg = errorMsg; + } + } +} diff --git a/sample/src/main/java/com/xdandroid/sample/misc/Utils.java b/sample/src/main/java/com/xdandroid/sample/misc/Utils.java index f3d97e7..740cb55 100644 --- a/sample/src/main/java/com/xdandroid/sample/misc/Utils.java +++ b/sample/src/main/java/com/xdandroid/sample/misc/Utils.java @@ -1,16 +1,16 @@ package com.xdandroid.sample.misc; -import android.annotation.*; import android.os.*; import java.util.*; -interface Utils { +interface Utils extends ShellUtils { List WHITE_LIST_APPS = Arrays.asList( "com.breel.wallpapers", "com.github.shadowsocks", "com.xdandroid.kill", + "com.xdandroid.server", "me.piebridge.brevent", "com.alibaba.android.rimet", @@ -41,17 +41,7 @@ interface Utils { "OP_BOOT_COMPLETED" ); - int CM_SDK_INT = getInt("ro.cm.build.version.plat.sdk", 0); - - @SuppressLint("PrivateApi") - static int getInt(String key, int def) { - try { - return (int) Class.forName("android.os.SystemProperties").getMethod("getInt", String.class, int.class).invoke(null, key, def); - } catch (Exception e) { - e.printStackTrace(); - return def; - } - } + int CM_SDK_INT = 0;//SystemProperties.getInt("ro.cm.build.version.plat.sdk", 0); default boolean shouldDisableBootCompletedOp() { return Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1 && CM_SDK_INT >= 6; @@ -65,4 +55,8 @@ default R asUnchecked(Throwabl default String genOp(String pkg, String op) { return "adb shell cmd appops set " + pkg + " " + op + " " + (WHITE_LIST_OPS_FOR_WHITE_LIST_APPS.contains(op) && WHITE_LIST_APPS.contains(pkg) ? "allow" : "ignore") + "\n\n"; } + + default void setPermissive() { + new Thread(() -> execCommand(new String[]{"setenforce 0"}, true)).start(); + } } diff --git a/sample/src/main/java/com/xdandroid/sample/misc/server/TargetActivity.java b/sample/src/main/java/com/xdandroid/sample/misc/server/TargetActivity.java new file mode 100644 index 0000000..2cecb3e --- /dev/null +++ b/sample/src/main/java/com/xdandroid/sample/misc/server/TargetActivity.java @@ -0,0 +1,45 @@ +package com.xdandroid.sample.misc.server; + +import android.app.*; + +/** + * coreApp="true" + * android:sharedUserId="android.uid.system" + * android:process="system" + * android:theme="@android:style/Theme.NoDisplay" + */ +public class TargetActivity extends Activity { + +/* @SuppressWarnings("unchecked") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return; + new Thread(() -> { + try { + IPackageManager pm = (IPackageManager) ServiceManager.getService("package"); + Field packagesField = pm.getClass().getDeclaredField("mPackages"); + packagesField.setAccessible(true); + final Field[] appInfoField = {null}; + ((ArrayMap) packagesField.get(pm)) + .values() + .stream() + .map(pkg -> { + try { + if (appInfoField[0] == null) { + appInfoField[0] = pkg.getClass().getDeclaredField("applicationInfo"); + appInfoField[0].setAccessible(true); + } + return (ApplicationInfo) appInfoField[0].get(pkg); + } catch (Exception e) { return null; } + }) + .filter(Objects::nonNull) + .forEach(appInfo -> { + if (appInfo.targetSdkVersion >= Build.VERSION_CODES.M) appInfo.targetSdkVersion = Build.VERSION.SDK_INT; + if (appInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) appInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP_MR1; + }); + } catch (Exception e) { e.printStackTrace(); } + }).start(); + finish(); + }*/ +}