From 75dc5c029492394302e09008751deaf550ae9519 Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Sat, 4 Nov 2023 03:41:43 +0800 Subject: [PATCH] =?UTF-8?q?`ShamrockPublic`:=20=E3=82=AA=E3=83=BC=E3=83=90?= =?UTF-8?q?=E3=83=A1=E3=83=A2=E3=83=AA=E3=83=AD=E3=83=BC=E3=83=9F=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E6=A4=9C=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WhiteChi --- .../shamrock/remote/api/MessageAction.kt | 56 ++++++++++++--- .../shamrock/xposed/actions/AntiDetection.kt | 70 ++++++++++++++++++- 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt index a794522..93a1e83 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt @@ -11,6 +11,7 @@ import io.ktor.server.routing.route import moe.fuqiuluo.shamrock.remote.action.handlers.* import moe.fuqiuluo.shamrock.tools.fetchGetOrNull import moe.fuqiuluo.shamrock.tools.fetchGetOrThrow +import moe.fuqiuluo.shamrock.tools.fetchOrNull import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray import moe.fuqiuluo.shamrock.tools.fetchPostJsonString @@ -36,19 +37,43 @@ fun Routing.messageAction() { val msgType = fetchGetOrThrow("message_type") val message = fetchGetOrThrow("message") val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false - val peerIdKey = if(msgType == "group") "group_id" else "user_id" val chatType = MessageHelper.obtainMessageTypeByDetailType(msgType) - call.respondText(SendMessage(chatType, fetchGetOrThrow(peerIdKey), message, autoEscape)) + + val userId = fetchGetOrNull("user_id") + val groupId = fetchGetOrNull("group_id") + + call.respondText(SendMessage( + chatType = chatType, + peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!, + message = message, + autoEscape = autoEscape, + fromId = groupId ?: userId ?: "" + )) } post { val msgType = fetchPostOrThrow("message_type") val chatType = MessageHelper.obtainMessageTypeByDetailType(msgType) - val peerId = fetchPostOrThrow(if(msgType == "group") "group_id" else "user_id") + + val userId = fetchPostOrNull("user_id") + val groupId = fetchPostOrNull("group_id") + call.respondText(if (isJsonData() && !isJsonString("message")) { - SendMessage(chatType, peerId, fetchPostJsonArray("message")) + SendMessage( + chatType = chatType, + peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!, + message = fetchPostJsonArray("message"), + fromId = groupId ?: userId ?: "" + ) } else { val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false - SendMessage(chatType, peerId, fetchPostOrThrow("message"), autoEscape) + //SendMessage(chatType, peerId, fetchPostOrThrow("message"), autoEscape) + SendMessage( + chatType = chatType, + peerId = if (chatType == MsgConstant.KCHATTYPEC2C) userId!! else groupId!!, + message = fetchPostOrThrow("message"), + autoEscape = autoEscape, + fromId = groupId ?: userId ?: "" + ) }) } } @@ -95,16 +120,31 @@ fun Routing.messageAction() { } post { val userId = fetchPostOrThrow("user_id") + val groupId = fetchPostOrNull("group_id") val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false val result = if (isJsonData()) { if (isJsonString("message")) { - SendMessage(MsgConstant.KCHATTYPEC2C, userId, fetchPostJsonString("message"), autoEscape) + SendMessage( + chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP, + userId, + fetchPostJsonString("message"), + autoEscape + ) } else { - SendMessage(MsgConstant.KCHATTYPEC2C, userId, fetchPostJsonArray("message")) + SendMessage( + chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP, + userId, + fetchPostJsonArray("message") + ) } } else { - SendMessage(MsgConstant.KCHATTYPEC2C, userId, fetchPostOrThrow("message"), autoEscape) + SendMessage( + chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP, + userId, + fetchPostOrThrow("message"), + autoEscape + ) } call.respondText(result) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt index f0ef577..0e62eaf 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/AntiDetection.kt @@ -2,16 +2,82 @@ package moe.fuqiuluo.shamrock.xposed.actions import android.content.Context +import android.os.Build import moe.fuqiuluo.shamrock.tools.hookMethod -import java.lang.Exception /** * 反检测 */ class AntiDetection: IAction { override fun invoke(ctx: Context) { + antiTrace() + antiMemoryWalking() + } + + val isModuleStack = fun String.(): Boolean { + return contains("fuqiuluo") || contains("shamrock") || contains("whitechi") || contains("lsposed") || contains("xposed") + } + + private fun antiMemoryWalking() { + val c = Class.forName("dalvik.system.VMDebug") + //val startMethodTracingMethod = c.getDeclaredMethod( + // "startMethodTracing", String::class.java, + // Integer.TYPE, Integer.TYPE, java.lang.Boolean.TYPE, Integer.TYPE + //) + //val stopMethodTracingMethod = c.getDeclaredMethod("stopMethodTracing") + //val getMethodTracingModeMethod = c.getDeclaredMethod("getMethodTracingMode") + //val getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String::class.java) + //val getRuntimeStatsMethod = c.getDeclaredMethod("getRuntimeStats") + + c.hookMethod("countInstancesOfClass").before { + val clz = it.args[0] as Class<*> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if(clz.packageName.isModuleStack()) { + it.result = 0L + } + } else { + if(clz.canonicalName?.isModuleStack() == true) { + it.result = 0L + } + } + } + + c.hookMethod("countInstancesOfClasses").before { + val clzs = it.args[0] as Array> + clzs.forEach { clz -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if(clz.packageName.isModuleStack()) { + it.result = 0L + return@forEach + } + } else { + if(clz.canonicalName?.isModuleStack() == true) { + it.result = 0L + return@forEach + } + } + } + } + + c.hookMethod("getInstancesOfClasses").after { + val clzs = it.args[0] as Array> + clzs.forEachIndexed { _, clz -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if(clz.packageName.isModuleStack()) { + it.result = Array(0) { } + } + } else { + if(clz.canonicalName?.isModuleStack() == true) { + it.result = Array(0) { } + } + } + } + } + } + + private fun antiTrace() { val isModuleStack = fun StackTraceElement.(): Boolean { - return className.contains("fuqiuluo") || className.contains("shamrock") || className.contains("whitechi") + return className.isModuleStack() } Thread::class.java.hookMethod("getName").after {