From 0d35d5834b554880e6fa89ffc1e5430f0c405539 Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Thu, 23 Nov 2023 23:53:11 +0800 Subject: [PATCH] =?UTF-8?q?`Shamrock`:=20=E9=87=91=E3=83=A1=E3=83=80?= =?UTF-8?q?=E3=83=AB=E5=85=8D=E9=99=A4=E3=80=81=E3=82=B7=E3=82=B9=E3=83=86?= =?UTF-8?q?=E3=83=A0=E3=83=AC=E3=83=99=E3=83=AB=E3=81=AE=E4=BF=9D=E6=B4=BB?= =?UTF-8?q?=E3=82=92=E3=82=B5=E3=83=9D=E3=83=BC=E3=83=88=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../shamrock/ui/fragment/LabFragment.kt | 30 +++++++++++++++---- .../shamrock/remote/api/OtherAction.kt | 12 ++++---- .../shamrock/xposed/loader/FuckAMS.kt | 26 +++++++++++----- 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0ab89fa..b33864a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -47,7 +47,7 @@ android:value="基于 Xposed 实现 OneBot 标准的 QQ 机器人框架" /> + android:value="93" /> diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt index 275af4c..288c719 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt @@ -1,5 +1,6 @@ package moe.fuqiuluo.shamrock.ui.fragment +import android.content.Context import android.widget.Toast import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.absolutePadding @@ -22,6 +23,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import moe.fuqiuluo.shamrock.R import moe.fuqiuluo.shamrock.ui.app.AppRuntime +import moe.fuqiuluo.shamrock.ui.app.Level import moe.fuqiuluo.shamrock.ui.app.ShamrockConfig import moe.fuqiuluo.shamrock.ui.theme.GlobalColor import moe.fuqiuluo.shamrock.ui.theme.LocalString @@ -90,7 +92,7 @@ fun LabFragment() { modifier = Modifier.padding(top = 12.dp), painter = painterResource(id = R.drawable.round_logo_dev_24), title = "实验功能" - ) { + ) { color -> Column { Divider( modifier = Modifier, @@ -101,7 +103,7 @@ fun LabFragment() { Function( title = "自动清理QQ垃圾", desc = "也许会导致奇怪的问题(无效)。", - descColor = it, + descColor = color, isSwitch = ShamrockConfig.isAutoClean(ctx) ) { ShamrockConfig.setAutoClean(ctx, it) @@ -112,7 +114,7 @@ fun LabFragment() { Function( title = "拦截QQ无用收包", desc = "测试阶段,可能导致网络异常或掉线。", - descColor = it, + descColor = color, isSwitch = ShamrockConfig.isInjectPacket(ctx) ) { ShamrockConfig.setInjectPacket(ctx, it) @@ -123,7 +125,7 @@ fun LabFragment() { Function( title = "自动唤醒QQ", desc = "QQ进程死亡时重新打开QQ进程,前提本进程存活。", - descColor = it, + descColor = color, isSwitch = ShamrockConfig.enableAutoStart(ctx) ) { ShamrockConfig.setAutoStart(ctx, it) @@ -133,12 +135,30 @@ fun LabFragment() { Function( title = "开启Shell接口", desc = "可能导致设备被入侵,请勿随意开启。", - descColor = it, + descColor = color, isSwitch = ShamrockConfig.allowShell(ctx) ) { ShamrockConfig.setShellStatus(ctx, it) return@Function true } + + kotlin.runCatching { + ctx.getSharedPreferences("shared_config", Context.MODE_WORLD_READABLE) + }.onSuccess { + Function( + title = "免死金牌", + desc = "由系统复活QQ和Shamrock,需要重新启动系统。", + descColor = color, + isSwitch = it.getBoolean("persistent", false) + ) { v -> + it.edit().putBoolean("persistent", v).apply() + scope.toast(ctx, "重启系统生效哦!") + return@Function true + } + }.onFailure { + AppRuntime.log("无法启用免死金牌选项,当前Lsposed模块未激活或者不支持NewSharedPreferences。", Level.WARN) + } + } } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/OtherAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/OtherAction.kt index 1deca8a..995a90c 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/OtherAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/OtherAction.kt @@ -4,6 +4,7 @@ import io.ktor.http.ContentType import io.ktor.http.content.PartData import io.ktor.http.content.forEachPart import io.ktor.http.content.streamProvider +import io.ktor.server.application.Application import io.ktor.server.application.call import io.ktor.server.request.receiveMultipart import io.ktor.server.response.respondText @@ -27,6 +28,7 @@ import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray import moe.fuqiuluo.shamrock.tools.getOrPost import moe.fuqiuluo.shamrock.tools.isJsonArray +import moe.fuqiuluo.shamrock.tools.json import moe.fuqiuluo.shamrock.tools.respond import moe.fuqiuluo.shamrock.utils.FileUtils import moe.fuqiuluo.shamrock.utils.MD5 @@ -39,7 +41,7 @@ fun Routing.otherAction() { post("/shell") { val runtime = Runtime.getRuntime() val dir = fetchOrThrow("dir") - val out = StringBuilder() + val out = hashMapOf() withTimeoutOrNull(5000L) { if (isJsonArray("cmd")) { val cmd = fetchPostJsonArray("cmd").map { @@ -59,17 +61,15 @@ fun Routing.otherAction() { respond(false, Status.IAmTired, "执行超时") } else { it.inputStream.use { - out.append("stdout:\n") - out.append(it.readBytes().toString(Charsets.UTF_8)) + out["out"] = it.readBytes().toString(Charsets.UTF_8) } it.errorStream.use { - out.append("\nstderr:\n") - out.append(it.readBytes().toString(Charsets.UTF_8)) + out["err"] = it.readBytes().toString(Charsets.UTF_8) } } } - call.respondText(out.toString()) + call.respondText(out.json.toString(), ContentType.Application.Json) } } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt index 77568e7..e94002b 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/loader/FuckAMS.kt @@ -3,6 +3,8 @@ package moe.fuqiuluo.shamrock.xposed.loader import android.content.pm.ApplicationInfo import android.os.Build +import com.arthenica.ffmpegkit.BuildConfig +import de.robv.android.xposed.XSharedPreferences import de.robv.android.xposed.XposedBridge import de.robv.android.xposed.XposedHelpers import moe.fuqiuluo.shamrock.tools.hookMethod @@ -16,6 +18,7 @@ internal object FuckAMS { private lateinit var KeepThread: Thread private lateinit var METHOD_IS_KILLED: Method + private var allowPersistent: Boolean = false fun injectAMS(loader: ClassLoader) { kotlin.runCatching { @@ -24,15 +27,24 @@ internal object FuckAMS { increaseAdj(it.result) } }.onFailure { - XposedBridge.log("Plan A failed: ${it.message}") + XposedBridge.log("[Shamrock] Plan A failed: ${it.message}") } + + val pref = XSharedPreferences("moe.fuqiuluo.shamrock", "shared_config") + if (pref.file.canRead()) { + allowPersistent = pref.getBoolean("persistent", false) + XposedBridge.log("[Shamrock] allowPersistent = $allowPersistent") + } else { + XposedBridge.log("[Shamrock] unable to load XSharedPreferences") + } + kotlin.runCatching { val ProcessList = XposedHelpers.findClass("com.android.server.am.ProcessList", loader) ProcessList.hookMethod("newProcessRecordLocked").after { increaseAdj(it.result) } }.onFailure { - XposedBridge.log("Plan B failed: ${it.message}") + XposedBridge.log("[Shamrock] Plan B failed: ${it.message}") } } @@ -75,14 +87,14 @@ internal object FuckAMS { if (!it.isAccessible) it.isAccessible = true }.get(record) as ApplicationInfo if(applicationInfo.processName in KeepPackage) { - XposedBridge.log("Process is keeping: $record") + XposedBridge.log("[Shamrock] Process is keeping: $record") KeepRecords.add(record) keepByAdj(record) // Error - //if (noDied.exists()) { - // XposedBridge.log("Open NoDied Mode!!!") - // keepByPersistent(record) - //} + if (allowPersistent) { + XposedBridge.log("[Shamrock] Open NoDied Mode!!!") + keepByPersistent(record) + } checkThread() } }