9 Commits

Author SHA1 Message Date
352aa5f737 Merge pull request #268 from huankong233/master
修正错误部分错误
2024-03-01 01:34:47 +08:00
9546e90bec 修正报错无法通过 Websocket 返回 2024-03-01 00:23:46 +08:00
26b4d95ad8 修正错误的拼写 2024-02-29 23:56:00 +08:00
4a6109fbe6 修正 websocket 中 alias 的名称
修正 QuickOperation 中 错误的返回
2024-02-29 23:35:23 +08:00
d6142173c9 Merge pull request #267 from PisLuanyao/master
NativeLoader
2024-02-29 22:42:01 +08:00
38cf806b40 Shamrock: review
Signed-off-by: 白池 <whitechi73@outlook.com>
2024-02-29 22:40:36 +08:00
82269bb171 NativeLoader
应该是这样关?
猫脑过载.png
2024-02-29 20:43:18 +08:00
fc0d7a62af NativeLoader
修复isEmu里因手残导致的问题
2024-02-29 19:32:36 +08:00
1f620bcc06 NativeLoader
现在,可以在HMA做了隐藏的情况下正确加载库文件

借鉴过来的,貌似会导致亿点问题

感觉isEmu也会翻车呢  ┭┮﹏┭┮
2024-02-29 11:29:26 +08:00
7 changed files with 122 additions and 30 deletions

View File

@ -16,7 +16,7 @@ import moe.fuqiuluo.symbols.OneBotHandler
import moe.fuqiuluo.symbols.decodeProtobuf
import protobuf.fav.WeiyunComm
@OneBotHandler("fav.add_text_msg", ["fav.add_text_msg"])
@OneBotHandler("fav.add_text_msg", ["fav.add_text_message"])
internal object FavAddTextMsg: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val uin = session.getLong("user_id")

View File

@ -106,7 +106,7 @@ internal object QuickOperation : IActionHandler() {
}
return logic("操作成功", session.echo)
return ok("操作成功", session.echo)
}
override val requiredParams: Array<String> = arrayOf("context", "operation", "self_id")

View File

@ -7,7 +7,7 @@ import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("sanc_qrcode")
@OneBotHandler("scan_qrcode")
internal object ScanQRCode: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val qrcode = QRoute.api(IQRCodeApi::class.java)

View File

@ -1,6 +1,7 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import moe.fuqiuluo.shamrock.helper.ParamsException
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.jsonArray
@ -9,6 +10,7 @@ import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_group_message", ["send_group_msg"])
internal object SendGroupMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
try{
val groupId = session.getLong("group_id")
val retryCnt = session.getIntOrNull("retry_cnt")
val recallDuration = session.getLongOrNull("recall_duration")
@ -23,6 +25,11 @@ internal object SendGroupMessage: IActionHandler() {
val message = session.getArray("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId.toString(), message, session.echo, retryCnt = retryCnt ?: 5, recallDuration = recallDuration)
}
} catch (e: ParamsException) {
return noParam(e.message!!, session.echo)
} catch (e: Throwable) {
return logic(e.message ?: e.toString(), session.echo)
}
}
override val requiredParams: Array<String> = arrayOf("message", "group_id")

View File

@ -1,7 +1,10 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.structures.GuildInfo
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
@ -17,11 +20,16 @@ internal object SendGroupSign: IActionHandler() {
suspend operator fun invoke(groupId: Long, echo: JsonElement = EmptyJsonString): String {
val ret = GroupSvc.groupSign(groupId)
return if (ret.isSuccess) {
ok(ret.getOrNull() ?: "", echo)
ok(Message(message = ret.getOrNull() ?: ""), echo, "成功")
} else {
logic(ret.exceptionOrNull()?.message ?: "", echo)
}
}
override val requiredParams: Array<String> = arrayOf("group_id")
@Serializable
data class Message(
@SerialName("message") var message: String = ""
)
}

View File

@ -1,11 +1,14 @@
package moe.fuqiuluo.shamrock.xposed.loader
import android.annotation.SuppressLint
import android.content.Context
import android.os.Build
import de.robv.android.xposed.XposedBridge
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.XposedEntry
import moe.fuqiuluo.shamrock.xposed.loader.tmpnativehelper.moduleClassLoader
import mqq.app.MobileQQ
import oicq.wlogin_sdk.tools.MD5
import java.io.File
internal object NativeLoader {
@ -17,6 +20,33 @@ internal object NativeLoader {
return externalLibPath.resolve("libffmpegkit.so").exists()
}
private val isEmu: Boolean
get() {
if (Build.SUPPORTED_ABIS.any { it.contains("x86") }) {
XposedBridge.log("[Shamrock] 通过SUPPORTED_ABIS检测到 Android x86")
return true
}
return try {
val clazz = Class.forName("dalvik.system.VMRuntime")
val method = clazz.getDeclaredMethod("getRuntime")
val runtime = method.invoke(null)
val field = clazz.getDeclaredField("vmInstructionSet")
field.isAccessible = true
val instructionSet = field.get(runtime) as String
if ( instructionSet.contains("x86") ) {
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
true
} else false
} catch (e: Exception) {
XposedBridge.log("[Shamrock] $e")
false
}
}
private fun getLibFilePath(name: String): String {
return if (isEmu) "lib/x86_64/lib${name}.so" else "lib/arm64-v8a/lib$name.so"
}
/**
* 使目标进程可以使用来自模块的库
*/
@ -24,17 +54,7 @@ internal object NativeLoader {
fun load(name: String) {
try {
if (name == "shamrock" || name == "clover") {
val context = MobileQQ.getContext()
val packageManager = context.packageManager
val applicationInfo = packageManager.getApplicationInfo("moe.fuqiuluo.shamrock.hided", 0)
val file = File(applicationInfo.nativeLibraryDir)
LogCenter.log("LoadLibrary(name = $name)")
System.load(file.resolve("lib$name.so").also {
if (!it.exists()) {
LogCenter.log("LoadLibrary(name = $name) failed, file not exists.", level = Level.ERROR)
return
}
}.absolutePath)
onLoadByCopiedLibrary(name, getCtx())
} else {
val sourceFile = externalLibPath.resolve("lib$name.so")
val soFile = MobileQQ.getContext().filesDir.parentFile!!.resolve("txlib").resolve("lib$name.so")
@ -54,4 +74,55 @@ internal object NativeLoader {
XposedBridge.log(e)
}
}
private inline fun getCtx() = MobileQQ.getContext()
@SuppressLint("UnsafeDynamicallyLoadedCode")
private fun onLoadByCopiedLibrary(name: String, context: Context) {
val soDir = File(context.filesDir, "SM_LIBS")
if (soDir.isFile) {
soDir.delete()
}
if (!soDir.exists()) {
soDir.mkdirs()
}
val soPath = getLibFilePath(name)
val soFile = File(soDir, name)
fun reloadSo(tmp: File? = null) {
LogCenter.log("SO文件大小不一致或不存在正在重新加载", Level.INFO)
soFile.delete()
if (tmp == null) moduleClassLoader.getResourceAsStream(soPath).use { origin ->
soFile.outputStream().use { origin.copyTo(it) }
} else tmp.renameTo(soFile)
}
try {
if (!soFile.exists()) {
reloadSo()
} else {
val tmpSoFile = soFile.resolve("$name.tmp").also { file ->
if (file.exists()) file.delete()
file.outputStream().use {
moduleClassLoader.getResourceAsStream(soPath).use { origin ->
origin.copyTo(it)
}
}
}
if (soFile.length() != tmpSoFile.length() || MD5.getFileMD5(soFile).let {
it != MD5.getFileMD5(tmpSoFile)
}) {
reloadSo(tmpSoFile)
}
}
try {
System.load(soFile.absolutePath)
LogCenter.log("加载SO文件成功 -> ${soFile.path}", Level.INFO)
} catch (e: Throwable) {
LogCenter.log(e.toString(), Level.WARN)
throw e
}
} catch (e: Exception) {
LogCenter.log(e.toString(), Level.WARN)
throw e
}
}
}

View File

@ -0,0 +1,6 @@
@file:JvmName("ModuleInfo")
package moe.fuqiuluo.shamrock.xposed.loader.tmpnativehelper
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader
val moduleClassLoader: ClassLoader = LuoClassloader::class.java.classLoader!!