mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: 修复配置文件下发
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
07364c8298
commit
638bf72392
7
annotations/src/main/java/kritor/service/Grpc.kt
Normal file
7
annotations/src/main/java/kritor/service/Grpc.kt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package kritor.service
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class Grpc(
|
||||||
|
val serviceName: String,
|
||||||
|
val funcName: String
|
||||||
|
)
|
2
kritor
2
kritor
@ -1 +1 @@
|
|||||||
Subproject commit 0dd59dd2d43324ba13f14e2b8ebc5df07ed9821d
|
Subproject commit f4fa15754e266182b5f2c08c54c88c21c61eb065
|
43
xposed/src/main/assets/config.properties
Normal file
43
xposed/src/main/assets/config.properties
Normal 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
|
@ -1,20 +1,32 @@
|
|||||||
|
@file:OptIn(ExperimentalCoroutinesApi::class)
|
||||||
package kritor.server
|
package kritor.server
|
||||||
|
|
||||||
import io.grpc.ServerBuilder
|
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 moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class KritorServer(
|
class KritorServer(
|
||||||
private val port: Int
|
private val port: Int
|
||||||
) {
|
): CoroutineScope {
|
||||||
private val server = ServerBuilder
|
private val server = ServerBuilder
|
||||||
.forPort(port)
|
.forPort(port)
|
||||||
|
.addService(Authentication)
|
||||||
.build()!!
|
.build()!!
|
||||||
|
|
||||||
fun start(block: Boolean = false) {
|
fun start(block: Boolean = false) {
|
||||||
LogCenter.log("KritorServer started at port $port.")
|
LogCenter.log("KritorServer started at port $port.")
|
||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
if (block) {
|
if (block) {
|
||||||
server.awaitTermination()
|
server.awaitTermination()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val coroutineContext: CoroutineContext =
|
||||||
|
Dispatchers.IO.limitedParallelism(12)
|
||||||
}
|
}
|
49
xposed/src/main/java/kritor/service/Authentication.kt
Normal file
49
xposed/src/main/java/kritor/service/Authentication.kt
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.config
|
||||||
|
|
||||||
|
object ActiveTicket: ConfigKey<String>() {
|
||||||
|
override fun name(): String = "active_ticket"
|
||||||
|
|
||||||
|
override fun default(): String = ""
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package moe.fuqiuluo.shamrock.config
|
package moe.fuqiuluo.shamrock.config
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader.moduleLoader
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import java.util.Properties
|
import java.util.Properties
|
||||||
|
|
||||||
@ -17,11 +19,22 @@ private val configKeys = setOf(
|
|||||||
ResourceGroup,
|
ResourceGroup,
|
||||||
RPCAddress,
|
RPCAddress,
|
||||||
RPCPort,
|
RPCPort,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
internal object ShamrockConfig: Properties() {
|
internal object ShamrockConfig: Properties() {
|
||||||
init {
|
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 {
|
if (configFile.exists()) configFile.inputStream().use {
|
||||||
load(it)
|
load(it)
|
||||||
}
|
}
|
||||||
@ -40,13 +53,34 @@ internal object ShamrockConfig: Properties() {
|
|||||||
fun updateConfig(intent: Intent? = null) {
|
fun updateConfig(intent: Intent? = null) {
|
||||||
intent?.let {
|
intent?.let {
|
||||||
for (key in configKeys) {
|
for (key in configKeys) {
|
||||||
val value = intent.getStringExtra(key.name())
|
when (key.default()) {
|
||||||
if (value != null) setProperty(key.name(), value)
|
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")
|
setProperty(IsInit.name(), "true")
|
||||||
}
|
}
|
||||||
configFile.outputStream().use {
|
configFile.outputStream().use {
|
||||||
store(it, "Shamrock Config ${System.currentTimeMillis()}")
|
store(it, "Shamrock Config")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@ package moe.fuqiuluo.shamrock.xposed.actions
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import kritor.server.KritorServer
|
import kritor.server.KritorServer
|
||||||
import moe.fuqiuluo.shamrock.config.ActiveRPC
|
import moe.fuqiuluo.shamrock.config.ActiveRPC
|
||||||
import moe.fuqiuluo.shamrock.config.RPCPort
|
import moe.fuqiuluo.shamrock.config.RPCPort
|
||||||
@ -17,10 +19,11 @@ private lateinit var server: KritorServer
|
|||||||
@XposedHook(Process.MAIN, priority = 10)
|
@XposedHook(Process.MAIN, priority = 10)
|
||||||
internal class InitRemoteService : IAction {
|
internal class InitRemoteService : IAction {
|
||||||
override fun invoke(ctx: Context) {
|
override fun invoke(ctx: Context) {
|
||||||
if (ActiveRPC.get() && !::server.isInitialized) {
|
GlobalScope.launch {
|
||||||
server = KritorServer(RPCPort.get())
|
if (ActiveRPC.get() && !::server.isInitialized) {
|
||||||
server.start()
|
server = KritorServer(RPCPort.get())
|
||||||
|
server.start()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,6 @@ internal object NativeLoader {
|
|||||||
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
|
XposedBridge.log("[Shamrock] 反射检测到 Android x86")
|
||||||
true
|
true
|
||||||
} else false
|
} else false
|
||||||
}.onFailure {
|
|
||||||
XposedBridge.log("[Shamrock] ${it.stackTraceToString()}")
|
|
||||||
}.getOrElse { false }
|
}.getOrElse { false }
|
||||||
|
|
||||||
private fun getLibFilePath(name: String): String {
|
private fun getLibFilePath(name: String): String {
|
||||||
|
@ -4,6 +4,8 @@ import com.tencent.qphone.base.remote.FromServiceMsg
|
|||||||
import com.tencent.qphone.base.remote.ToServiceMsg
|
import com.tencent.qphone.base.remote.ToServiceMsg
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
|
||||||
typealias MsfPush = (FromServiceMsg) -> Unit
|
typealias MsfPush = (FromServiceMsg) -> Unit
|
||||||
typealias MsfResp = (ToServiceMsg, FromServiceMsg) -> Unit
|
typealias MsfResp = (ToServiceMsg, FromServiceMsg) -> Unit
|
||||||
@ -45,8 +47,13 @@ internal object MSFHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
|
fun onResp(toServiceMsg: ToServiceMsg, fromServiceMsg: FromServiceMsg) {
|
||||||
val cmd = toServiceMsg.getAttribute("respkey") as Int
|
runCatching {
|
||||||
val resp = mRespHandler[cmd]
|
val cmd = toServiceMsg.getAttribute("__respkey") as? Int?
|
||||||
resp?.invoke(toServiceMsg, fromServiceMsg)
|
?: return@runCatching
|
||||||
|
val resp = mRespHandler[cmd]
|
||||||
|
resp?.invoke(toServiceMsg, fromServiceMsg)
|
||||||
|
}.onFailure {
|
||||||
|
LogCenter.log("MSF.onResp failed: ${it.message}", Level.ERROR)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user