Shamrock: 修复配置文件下发

Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
白池 2024-03-10 07:44:02 +08:00
parent 07364c8298
commit 638bf72392
10 changed files with 175 additions and 15 deletions

View File

@ -0,0 +1,7 @@
package kritor.service
@Target(AnnotationTarget.FUNCTION)
annotation class Grpc(
val serviceName: String,
val funcName: String
)

2
kritor

@ -1 +1 @@
Subproject commit 0dd59dd2d43324ba13f14e2b8ebc5df07ed9821d
Subproject commit f4fa15754e266182b5f2c08c54c88c21c61eb065

View File

@ -0,0 +1,43 @@
# Shamrock Config
# 资源上传群组
resource_group=883536416
# 强制使用平板模式
force_tablet=false
# 被动反向RPC开关
passive_rpc=false
# 被动反向RPC地址
rpc_address=
# 第一个被动RPC鉴权token
rpc_address.ticket=
# 如果有多个请使用
# 我是第二个地址
#rpc_address.1=
# 第二个被动RPC鉴权token
#rpc_address.1.ticket=
# 主动正向RPC开关
active_rpc=false
# 主动正向RPC端口
rpc_port=5700
# 主动RPC鉴权token
active_ticket=
# 多鉴权token支持
# 第二个主动RPC鉴权token
#active_ticket.1=
# 自回复开关
#alive_reply=false
# 自回复消息
enable_self_message=false
# 旧BDH兼容开关
enable_old_bdh=false
# 反JVM调用栈跟踪
anti_jvm_trace=true
# 调试模式
#debug=false

View File

@ -1,20 +1,32 @@
@file:OptIn(ExperimentalCoroutinesApi::class)
package kritor.server
import io.grpc.ServerBuilder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kritor.service.*
import moe.fuqiuluo.shamrock.helper.LogCenter
import kotlin.coroutines.CoroutineContext
class KritorServer(
private val port: Int
) {
): CoroutineScope {
private val server = ServerBuilder
.forPort(port)
.addService(Authentication)
.build()!!
fun start(block: Boolean = false) {
LogCenter.log("KritorServer started at port $port.")
server.start()
if (block) {
server.awaitTermination()
}
}
override val coroutineContext: CoroutineContext =
Dispatchers.IO.limitedParallelism(12)
}

View File

@ -0,0 +1,49 @@
package kritor.service
import io.kritor.AuthCode
import io.kritor.AuthReq
import io.kritor.AuthRsp
import io.kritor.AuthenticationGrpcKt
import io.kritor.authRsp
import moe.fuqiuluo.shamrock.config.ActiveTicket
import moe.fuqiuluo.shamrock.config.ShamrockConfig
import qq.service.QQInterfaces
object Authentication: AuthenticationGrpcKt.AuthenticationCoroutineImplBase() {
@Grpc("Authentication", "Auth")
override suspend fun auth(request: AuthReq): AuthRsp {
if (QQInterfaces.app.account != request.account) {
return authRsp {
code = AuthCode.NO_ACCOUNT
msg = "No such account"
}
}
val activeTicketName = ActiveTicket.name()
var index = 0
while (true) {
val ticket = ShamrockConfig.getProperty(activeTicketName + if (index == 0) "" else ".$index", null)
if (ticket.isNullOrEmpty()) {
if (index == 0) {
return authRsp {
code = AuthCode.OK
msg = "OK"
}
} else {
break
}
} else if (ticket == request.ticket) {
return authRsp {
code = AuthCode.OK
msg = "OK"
}
}
index++
}
return authRsp {
code = AuthCode.NO_TICKET
msg = "Invalid ticket"
}
}
}

View File

@ -0,0 +1,7 @@
package moe.fuqiuluo.shamrock.config
object ActiveTicket: ConfigKey<String>() {
override fun name(): String = "active_ticket"
override fun default(): String = ""
}

View File

@ -1,6 +1,8 @@
package moe.fuqiuluo.shamrock.config
import android.content.Intent
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader.moduleLoader
import mqq.app.MobileQQ
import java.util.Properties
@ -17,11 +19,22 @@ private val configKeys = setOf(
ResourceGroup,
RPCAddress,
RPCPort,
)
internal object ShamrockConfig: Properties() {
init {
if (!configFile.exists()) {
moduleLoader.getResourceAsStream("assets/config.properties")?.use {
configDir.resolve("default.prop").outputStream().use { output ->
it.copyTo(output)
}
}
moduleLoader.getResourceAsStream("assets/config.properties")?.use {
configFile.outputStream().use { output ->
it.copyTo(output)
}
}
}
if (configFile.exists()) configFile.inputStream().use {
load(it)
}
@ -40,13 +53,34 @@ internal object ShamrockConfig: Properties() {
fun updateConfig(intent: Intent? = null) {
intent?.let {
for (key in configKeys) {
val value = intent.getStringExtra(key.name())
if (value != null) setProperty(key.name(), value)
when (key.default()) {
is String -> {
val value = intent.getStringExtra(key.name())
if (value != null) setProperty(key.name(), value)
}
is Boolean -> {
val value = intent.getBooleanExtra(key.name(), key.default() as Boolean)
setProperty(key.name(), value.toString())
}
is Int -> {
val value = intent.getIntExtra(key.name(), key.default() as Int)
setProperty(key.name(), value.toString())
}
is Long -> {
val value = intent.getLongExtra(key.name(), key.default() as Long)
setProperty(key.name(), value.toString())
}
}
}
if (getProperty(ActiveTicket.name()).isNullOrEmpty()) {
setProperty(ActiveTicket.name(), "") // 初始化ticket
}
setProperty(IsInit.name(), "true")
}
configFile.outputStream().use {
store(it, "Shamrock Config ${System.currentTimeMillis()}")
store(it, "Shamrock Config")
}
}

View File

@ -4,6 +4,8 @@ package moe.fuqiuluo.shamrock.xposed.actions
import android.content.Context
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kritor.server.KritorServer
import moe.fuqiuluo.shamrock.config.ActiveRPC
import moe.fuqiuluo.shamrock.config.RPCPort
@ -17,10 +19,11 @@ private lateinit var server: KritorServer
@XposedHook(Process.MAIN, priority = 10)
internal class InitRemoteService : IAction {
override fun invoke(ctx: Context) {
if (ActiveRPC.get() && !::server.isInitialized) {
server = KritorServer(RPCPort.get())
server.start()
GlobalScope.launch {
if (ActiveRPC.get() && !::server.isInitialized) {
server = KritorServer(RPCPort.get())
server.start()
}
}
}
}

View File

@ -34,8 +34,6 @@ internal object NativeLoader {
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
true
} else false
}.onFailure {
XposedBridge.log("[Shamrock] ${it.stackTraceToString()}")
}.getOrElse { false }
private fun getLibFilePath(name: String): String {

View File

@ -4,6 +4,8 @@ import com.tencent.qphone.base.remote.FromServiceMsg
import com.tencent.qphone.base.remote.ToServiceMsg
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
typealias MsfPush = (FromServiceMsg) -> Unit
typealias MsfResp = (ToServiceMsg, FromServiceMsg) -> Unit
@ -45,8 +47,13 @@ internal object MSFHandler {
}
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
val cmd = toServiceMsg.getAttribute("respkey") as Int
val resp = mRespHandler[cmd]
resp?.invoke(toServiceMsg, fromServiceMsg)
runCatching {
val cmd = toServiceMsg.getAttribute("__respkey") as? Int?
?: return@runCatching
val resp = mRespHandler[cmd]
resp?.invoke(toServiceMsg, fromServiceMsg)
}.onFailure {
LogCenter.log("MSF.onResp failed: ${it.message}", Level.ERROR)
}
}
}