From c3934778c75beaa3f7abe12093375637ab30d06b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=B1=A0?= Date: Sun, 10 Mar 2024 01:56:02 +0800 Subject: [PATCH] =?UTF-8?q?`Shamrock`:=20=E4=BF=AE=E6=AD=A3=E9=A2=91?= =?UTF-8?q?=E9=81=93proto=E6=96=87=E4=BB=B6=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 白池 --- .../ui/service/handlers/InitHandler.kt | 11 +- xposed/build.gradle.kts | 36 +- .../main/java/kritor/server/KritorServer.kt | 20 ++ .../moe/fuqiuluo/shamrock/config/ConfigKey.kt | 3 + .../shamrock/config/ShamrockConfig.kt | 3 +- .../shamrock/internals/NTServiceFetcher.kt | 3 +- .../xposed/actions/InitRemoteService.kt | 11 + .../java/qq/service/internals/AioListener.kt | 314 ++++++++++++++++++ 8 files changed, 395 insertions(+), 6 deletions(-) create mode 100644 xposed/src/main/java/kritor/server/KritorServer.kt create mode 100644 xposed/src/main/java/qq/service/internals/AioListener.kt diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/service/handlers/InitHandler.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/service/handlers/InitHandler.kt index 148b6c4..349d555 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/service/handlers/InitHandler.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/service/handlers/InitHandler.kt @@ -18,12 +18,17 @@ internal object InitHandler: ModuleHandler() { val maps = hashMapOf() - RPCPort.update(context, maps) - RPCAddress.update(context, maps) - ForceTablet.update(context, maps) ActiveRPC.update(context, maps) + AliveReply.update(context, maps) + AntiJvmTrace.update(context, maps) + DebugMode.update(context, maps) + EnableOldBDH.update(context, maps) + EnableSelfMessage.update(context, maps) + ForceTablet.update(context, maps) PassiveRPC.update(context, maps) ResourceGroup.update(context, maps) + RPCAddress.update(context, maps) + RPCPort.update(context, maps) callback(context, 1, maps) } diff --git a/xposed/build.gradle.kts b/xposed/build.gradle.kts index 9dd0046..c8d9842 100644 --- a/xposed/build.gradle.kts +++ b/xposed/build.gradle.kts @@ -5,6 +5,7 @@ plugins { id("org.jetbrains.kotlin.android") id("kotlin-kapt") id("com.google.devtools.ksp") version "1.9.22-1.0.17" + id("com.google.protobuf") version "0.9.4" kotlin("plugin.serialization") version "1.9.22" } @@ -63,6 +64,8 @@ dependencies { compileOnly ("de.robv.android.xposed:api:82") compileOnly (project(":qqinterface")) + protobuf(project(":kritor")) + implementation(project(":protobuf")) implementation(project(":annotations")) ksp(project(":processor")) @@ -84,7 +87,13 @@ dependencies { implementation(ktor("client", "core")) implementation(ktor("client", "okhttp")) implementation(ktor("serialization", "kotlinx-json")) - implementation(ktor("network", "tls-certificates")) + + implementation("io.grpc:grpc-stub:1.62.2") + implementation("io.grpc:grpc-protobuf:1.62.2") + implementation("com.google.protobuf:protobuf-java-util:3.25.1") + implementation("com.google.protobuf:protobuf-kotlin:3.25.3") + implementation("io.grpc:grpc-kotlin-stub:1.4.1") + implementation("io.grpc:grpc-okhttp:1.62.2") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") @@ -92,3 +101,28 @@ dependencies { androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.01")) androidTestImplementation("androidx.compose.ui:ui-test-junit4") } + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.25.3" + } + plugins { + create("grpc") { + artifact = "io.grpc:protoc-gen-grpc-java:1.62.2" + } + create("grpckt") { + artifact = "io.grpc:protoc-gen-grpc-kotlin:1.4.1:jdk8@jar" + } + } + generateProtoTasks { + all().forEach { + it.plugins { + create("grpc") + create("grpckt") + } + it.builtins { + create("kotlin") + } + } + } +} diff --git a/xposed/src/main/java/kritor/server/KritorServer.kt b/xposed/src/main/java/kritor/server/KritorServer.kt new file mode 100644 index 0000000..80c0706 --- /dev/null +++ b/xposed/src/main/java/kritor/server/KritorServer.kt @@ -0,0 +1,20 @@ +package kritor.server + +import io.grpc.ServerBuilder +import moe.fuqiuluo.shamrock.helper.LogCenter + +class KritorServer( + private val port: Int +) { + private val server = ServerBuilder + .forPort(port) + .build()!! + + fun start(block: Boolean = false) { + LogCenter.log("KritorServer started at port $port.") + server.start() + if (block) { + server.awaitTermination() + } + } +} \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ConfigKey.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ConfigKey.kt index b3e2d67..0e92222 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ConfigKey.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ConfigKey.kt @@ -10,3 +10,6 @@ abstract class ConfigKey { } } +internal inline fun > T.get(): Type { + return ShamrockConfig[this] +} diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ShamrockConfig.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ShamrockConfig.kt index 4866b18..9ca6dac 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ShamrockConfig.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/config/ShamrockConfig.kt @@ -16,7 +16,8 @@ private val configKeys = setOf( PassiveRPC, ResourceGroup, RPCAddress, - RPCPort + RPCPort, + ) internal object ShamrockConfig: Properties() { diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/internals/NTServiceFetcher.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/internals/NTServiceFetcher.kt index a6e3885..8f03741 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/internals/NTServiceFetcher.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/internals/NTServiceFetcher.kt @@ -10,6 +10,7 @@ import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.tools.hookMethod import moe.fuqiuluo.shamrock.utils.PlatformUtils +import qq.service.internals.AioListener import qq.service.internals.msgService internal object NTServiceFetcher { @@ -58,7 +59,7 @@ internal object NTServiceFetcher { try { LogCenter.log("Register MSG listener successfully.") - //msgService.addMsgListener(AioListener) + msgService.addMsgListener(AioListener) // 接口缺失 暂不使用 //groupService.addKernelGroupListener(GroupEventListener) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt index 937c114..7677640 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt @@ -4,12 +4,23 @@ package moe.fuqiuluo.shamrock.xposed.actions import android.content.Context import kotlinx.coroutines.DelicateCoroutinesApi +import kritor.server.KritorServer +import moe.fuqiuluo.shamrock.config.ActiveRPC +import moe.fuqiuluo.shamrock.config.RPCPort +import moe.fuqiuluo.shamrock.config.ShamrockConfig +import moe.fuqiuluo.shamrock.config.get import moe.fuqiuluo.symbols.Process import moe.fuqiuluo.symbols.XposedHook +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() + } } } diff --git a/xposed/src/main/java/qq/service/internals/AioListener.kt b/xposed/src/main/java/qq/service/internals/AioListener.kt new file mode 100644 index 0000000..c14fe19 --- /dev/null +++ b/xposed/src/main/java/qq/service/internals/AioListener.kt @@ -0,0 +1,314 @@ +package qq.service.internals + +import com.tencent.qqnt.kernel.nativeinterface.BroadcastHelperTransNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.Contact +import com.tencent.qqnt.kernel.nativeinterface.ContactMsgBoxInfo +import com.tencent.qqnt.kernel.nativeinterface.CustomWithdrawConfig +import com.tencent.qqnt.kernel.nativeinterface.DevInfo +import com.tencent.qqnt.kernel.nativeinterface.DownloadRelateEmojiResultInfo +import com.tencent.qqnt.kernel.nativeinterface.EmojiNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.EmojiResourceInfo +import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.FirstViewDirectMsgNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.FirstViewGroupGuildInfo +import com.tencent.qqnt.kernel.nativeinterface.FreqLimitInfo +import com.tencent.qqnt.kernel.nativeinterface.GroupFileListResult +import com.tencent.qqnt.kernel.nativeinterface.GroupGuildNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.GroupItem +import com.tencent.qqnt.kernel.nativeinterface.GuildInteractiveNotificationItem +import com.tencent.qqnt.kernel.nativeinterface.GuildMsgAbFlag +import com.tencent.qqnt.kernel.nativeinterface.GuildNotificationAbstractInfo +import com.tencent.qqnt.kernel.nativeinterface.HitRelatedEmojiWordsResult +import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgListener +import com.tencent.qqnt.kernel.nativeinterface.ImportOldDbMsgNotifyInfo +import com.tencent.qqnt.kernel.nativeinterface.InputStatusInfo +import com.tencent.qqnt.kernel.nativeinterface.KickedInfo +import com.tencent.qqnt.kernel.nativeinterface.MsgAbstract +import com.tencent.qqnt.kernel.nativeinterface.MsgElement +import com.tencent.qqnt.kernel.nativeinterface.MsgRecord +import com.tencent.qqnt.kernel.nativeinterface.MsgSetting +import com.tencent.qqnt.kernel.nativeinterface.RecvdOrder +import com.tencent.qqnt.kernel.nativeinterface.RelatedWordEmojiInfo +import com.tencent.qqnt.kernel.nativeinterface.SearchGroupFileResult +import com.tencent.qqnt.kernel.nativeinterface.TabStatusInfo +import com.tencent.qqnt.kernel.nativeinterface.TempChatInfo +import com.tencent.qqnt.kernel.nativeinterface.UnreadCntInfo +import moe.fuqiuluo.shamrock.helper.Level +import moe.fuqiuluo.shamrock.helper.LogCenter + +object AioListener: IKernelMsgListener { + override fun onRecvMsg(arrayList: ArrayList?) { + + } + + override fun onMsgRecall(chatType: Int, peerId: String, msgId: Long) { + LogCenter.log("onMsgRecall($chatType, $peerId, $msgId)") + } + + override fun onAddSendMsg(record: MsgRecord) { + + } + + override fun onMsgInfoListUpdate(msgList: ArrayList?) { + + } + + override fun onTempChatInfoUpdate(tempChatInfo: TempChatInfo) { + + } + + override fun onMsgAbstractUpdate(arrayList: ArrayList?) { + //arrayList?.forEach { + // LogCenter.log("onMsgAbstractUpdate($it)", Level.WARN) + //} + } + + override fun onRecvMsgSvrRspTransInfo( + j2: Long, + contact: Contact?, + i2: Int, + i3: Int, + str: String?, + bArr: ByteArray? + ) { + LogCenter.log("onRecvMsgSvrRspTransInfo($j2, $contact, $i2, $i3, $str)", Level.DEBUG) + } + + override fun onRecvS2CMsg(arrayList: ArrayList?) { + LogCenter.log("onRecvS2CMsg(${arrayList.toString()})", Level.DEBUG) + } + + override fun onRecvSysMsg(arrayList: ArrayList?) { + LogCenter.log("onRecvSysMsg(${arrayList.toString()})", Level.DEBUG) + } + + override fun onBroadcastHelperDownloadComplete(broadcastHelperTransNotifyInfo: BroadcastHelperTransNotifyInfo?) {} + + override fun onBroadcastHelperProgerssUpdate(broadcastHelperTransNotifyInfo: BroadcastHelperTransNotifyInfo?) {} + + override fun onChannelFreqLimitInfoUpdate( + contact: Contact?, + z: Boolean, + freqLimitInfo: FreqLimitInfo? + ) { + + } + + override fun onContactUnreadCntUpdate(unreadMap: HashMap>) { + // 推送未读消息数量 + } + + override fun onCustomWithdrawConfigUpdate(customWithdrawConfig: CustomWithdrawConfig?) { + LogCenter.log("onCustomWithdrawConfigUpdate: " + customWithdrawConfig.toString(), Level.DEBUG) + } + + override fun onDraftUpdate(contact: Contact?, arrayList: ArrayList?, j2: Long) { + LogCenter.log("onDraftUpdate: " + contact.toString() + "|" + arrayList + "|" + j2.toString(), Level.DEBUG) + } + + override fun onEmojiDownloadComplete(emojiNotifyInfo: EmojiNotifyInfo?) { + + } + + override fun onEmojiResourceUpdate(emojiResourceInfo: EmojiResourceInfo?) { + + } + + override fun onFeedEventUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) { + + } + + override fun onFileMsgCome(arrayList: ArrayList?) { + + } + + override fun onFirstViewDirectMsgUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) { + + } + + override fun onFirstViewGroupGuildMapping(arrayList: ArrayList?) { + + } + + override fun onGrabPasswordRedBag( + i2: Int, + str: String?, + i3: Int, + recvdOrder: RecvdOrder?, + msgRecord: MsgRecord? + ) { + + } + + override fun onKickedOffLine(kickedInfo: KickedInfo?) { + LogCenter.log("onKickedOffLine($kickedInfo)") + } + + override fun onRichMediaUploadComplete(notifyInfo: FileTransNotifyInfo) { + LogCenter.log({ "[BDH] 资源上传完成(${notifyInfo.trasferStatus}, ${notifyInfo.fileId}, ${notifyInfo.msgId}, ${notifyInfo.commonFileInfo})" }, Level.DEBUG) + } + + override fun onRecvOnlineFileMsg(arrayList: ArrayList?) { + LogCenter.log(("onRecvOnlineFileMsg" + arrayList?.joinToString { ", " }), Level.DEBUG) + } + + override fun onRichMediaDownloadComplete(fileTransNotifyInfo: FileTransNotifyInfo) { + + } + + override fun onRichMediaProgerssUpdate(fileTransNotifyInfo: FileTransNotifyInfo) { + + } + + override fun onSearchGroupFileInfoUpdate(searchGroupFileResult: SearchGroupFileResult?) { + LogCenter.log("onSearchGroupFileInfoUpdate($searchGroupFileResult)", Level.DEBUG) + } + + override fun onGroupFileInfoAdd(groupItem: GroupItem?) { + LogCenter.log("onGroupFileInfoAdd: " + groupItem.toString(), Level.DEBUG) + } + + override fun onGroupFileInfoUpdate(groupFileListResult: GroupFileListResult?) { + LogCenter.log("onGroupFileInfoUpdate: " + groupFileListResult.toString(), Level.DEBUG) + } + + override fun onGroupGuildUpdate(groupGuildNotifyInfo: GroupGuildNotifyInfo?) { + LogCenter.log("onGroupGuildUpdate: " + groupGuildNotifyInfo.toString(), Level.DEBUG) + } + + override fun onGroupTransferInfoAdd(groupItem: GroupItem?) { + LogCenter.log("onGroupTransferInfoAdd: " + groupItem.toString(), Level.DEBUG) + } + + override fun onGroupTransferInfoUpdate(groupFileListResult: GroupFileListResult?) { + LogCenter.log("onGroupTransferInfoUpdate: " + groupFileListResult.toString(), Level.DEBUG) + } + + override fun onGuildInteractiveUpdate(guildInteractiveNotificationItem: GuildInteractiveNotificationItem?) { + + } + + override fun onGuildMsgAbFlagChanged(guildMsgAbFlag: GuildMsgAbFlag?) { + + } + + override fun onGuildNotificationAbstractUpdate(guildNotificationAbstractInfo: GuildNotificationAbstractInfo?) { + + } + + override fun onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: DownloadRelateEmojiResultInfo?) { + + } + + override fun onHitEmojiKeywordResult(hitRelatedEmojiWordsResult: HitRelatedEmojiWordsResult?) { + + } + + override fun onHitRelatedEmojiResult(relatedWordEmojiInfo: RelatedWordEmojiInfo?) { + + } + + override fun onImportOldDbProgressUpdate(importOldDbMsgNotifyInfo: ImportOldDbMsgNotifyInfo?) { + + } + + override fun onInputStatusPush(inputStatusInfo: InputStatusInfo?) { + + } + + override fun onLineDev(devList: ArrayList?) { + //LogCenter.log("onLineDev($arrayList)") + } + + override fun onLogLevelChanged(newLevel: Long) { + + } + + override fun onMsgBoxChanged(arrayList: ArrayList?) { + + } + + override fun onMsgDelete(contact: Contact?, arrayList: ArrayList?) { + + } + + override fun onMsgEventListUpdate(hashMap: HashMap>?) { + + } + + override fun onMsgInfoListAdd(arrayList: ArrayList?) { + + } + + override fun onMsgQRCodeStatusChanged(i2: Int) { + + } + + override fun onMsgSecurityNotify(msgRecord: MsgRecord?) { + LogCenter.log("onMsgSecurityNotify($msgRecord)") + } + + override fun onMsgSettingUpdate(msgSetting: MsgSetting?) { + + } + + override fun onNtFirstViewMsgSyncEnd() { + + } + + override fun onNtMsgSyncEnd() { + LogCenter.log("NTKernel同步消息完成", Level.DEBUG) + } + + override fun onNtMsgSyncStart() { + LogCenter.log("NTKernel同步消息开始", Level.DEBUG) + } + + override fun onReadFeedEventUpdate(firstViewDirectMsgNotifyInfo: FirstViewDirectMsgNotifyInfo?) { + + } + + override fun onRecvGroupGuildFlag(i2: Int) { + + } + + override fun onRecvUDCFlag(i2: Int) { + LogCenter.log("onRecvUDCFlag($i2)", Level.DEBUG) + } + + override fun onSendMsgError(j2: Long, contact: Contact?, i2: Int, str: String?) { + LogCenter.log("onSendMsgError($j2, $contact, $j2, $str)", Level.DEBUG) + } + + override fun onSysMsgNotification(i2: Int, j2: Long, j3: Long, arrayList: ArrayList?) { + LogCenter.log("onSysMsgNotification($i2, $j2, $j3, $arrayList)", Level.DEBUG) + } + + override fun onUnreadCntAfterFirstView(hashMap: HashMap>?) { + + } + + override fun onUnreadCntUpdate(hashMap: HashMap>?) { + + } + + override fun onUserChannelTabStatusChanged(z: Boolean) { + + } + + override fun onUserOnlineStatusChanged(z: Boolean) { + + } + + override fun onUserTabStatusChanged(arrayList: ArrayList?) { + LogCenter.log("onUserTabStatusChanged($arrayList)", Level.DEBUG) + } + + override fun onlineStatusBigIconDownloadPush(i2: Int, j2: Long, str: String?) { + + } + + override fun onlineStatusSmallIconDownloadPush(i2: Int, j2: Long, str: String?) { + + } +} \ No newline at end of file