Shamrock: 修復ファイルリストの取得に失敗しました

This commit is contained in:
WhiteChi 2023-11-05 15:58:20 +08:00
parent 68977e4a86
commit 72600364ff
7 changed files with 69 additions and 51 deletions

View File

@ -11,6 +11,7 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.proto.protobufOf
import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
@ -35,45 +36,35 @@ internal abstract class BaseSvc {
return ToServiceMsg("mobileqq.service", app.currentAccountUin, cmd)
}
suspend fun sendOidbAW(cmd: String, cmdId: Int, serviceId: Int, data: ByteArray, trpc: Boolean = false): ByteArray? {
return suspendCoroutine { continuation ->
val seq = MsfCore.getNextSeq()
val timer = timer(initialDelay = 5000L, period = 5000L) {
suspend fun sendOidbAW(cmd: String, cmdId: Int, serviceId: Int, data: ByteArray, trpc: Boolean = false, timeout: Long = 5000L): ByteArray? {
return withTimeoutOrNull(timeout) {
suspendCoroutine { continuation ->
val seq = MsfCore.getNextSeq()
GlobalScope.launch(Dispatchers.Default) {
PacketHandler.unregisterLessHandler(seq)
continuation.resume(null)
DynamicReceiver.register(IPCRequest(cmd, seq) {
val buffer = it.getByteArrayExtra("buffer")!!
continuation.resume(buffer)
})
}
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
else sendOidb(cmd, cmdId, serviceId, data, seq)
}
GlobalScope.launch(Dispatchers.Default) {
DynamicReceiver.register(IPCRequest(cmd, seq) {
val buffer = it.getByteArrayExtra("buffer")!!
timer.cancel()
continuation.resume(buffer)
})
}
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
else sendOidb(cmd, cmdId, serviceId, data, seq)
}
}?.copyOf()
}
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray): ByteArray? {
return suspendCoroutine { continuation ->
val seq = MsfCore.getNextSeq()
val timer = timer(initialDelay = 5000L, period = 5000L) {
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray, timeout: Long = 5000L): ByteArray? {
return withTimeoutOrNull<ByteArray?>(timeout) {
suspendCoroutine { continuation ->
val seq = MsfCore.getNextSeq()
GlobalScope.launch(Dispatchers.Default) {
PacketHandler.unregisterLessHandler(seq)
continuation.resume(null)
DynamicReceiver.register(IPCRequest(cmd, seq) {
val buffer = it.getByteArrayExtra("buffer")!!
continuation.resume(buffer)
})
sendBuffer(cmd, isPb, data, seq)
}
}
GlobalScope.launch(Dispatchers.Default) {
DynamicReceiver.register(IPCRequest(cmd, seq) {
val buffer = it.getByteArrayExtra("buffer")!!
timer.cancel()
continuation.resume(buffer)
})
sendBuffer(cmd, isPb, data, seq)
}
}
}?.copyOf()
}
fun sendOidb(cmd: String, cmdId: Int, serviceId: Int, buffer: ByteArray, seq: Int = -1, trpc: Boolean = false) {

View File

@ -1,12 +1,17 @@
package moe.fuqiuluo.qqinterface.servlet
import com.tencent.mobileqq.pb.ByteStringMicro
import io.ktor.util.Deflate
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import moe.fuqiuluo.proto.protobufOf
import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.DeflateTools
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
import tencent.im.oidb.oidb_sso
@ -92,7 +97,7 @@ internal object FileSvc: BaseSvc() {
)
}
suspend fun getGroupRootFiles(groupId: Long): GroupFileList {
suspend fun getGroupRootFiles(groupId: Long): Result<GroupFileList> {
return getGroupFiles(groupId, "/")
}
@ -100,7 +105,7 @@ internal object FileSvc: BaseSvc() {
return FileUrl(RichProtoSvc.getGroupFileDownUrl(groupId, fileId, busid))
}
suspend fun getGroupFiles(groupId: Long, folderId: String): GroupFileList {
suspend fun getGroupFiles(groupId: Long, folderId: String): Result<GroupFileList> {
val fileSystemInfo = getGroupFileSystemInfo(groupId)
val rspGetFileListBuffer = sendOidbAW("OidbSvc.0x6d8_1", 1752, 1, oidb_0x6d8.ReqBody().also {
it.file_list_info_req.set(oidb_0x6d8.GetFileListReqBody().apply {
@ -122,17 +127,20 @@ internal object FileSvc: BaseSvc() {
uint32_show_onlinedoc_folder.set(0)
})
}.toByteArray())
}.toByteArray(), timeout = 15_000L)
val files = arrayListOf<FileInfo>()
val dirs = arrayListOf<FolderInfo>()
if (rspGetFileListBuffer != null) {
oidb_0x6d8.RspBody().mergeFrom(oidb_sso.OIDBSSOPkg()
.mergeFrom(rspGetFileListBuffer.slice(4))
.bytes_bodybuffer.get()
.toByteArray()).file_list_info_rsp.apply {
return kotlin.runCatching {
val files = arrayListOf<FileInfo>()
val dirs = arrayListOf<FolderInfo>()
if (rspGetFileListBuffer != null) {
val oidb = oidb_sso.OIDBSSOPkg().mergeFrom(rspGetFileListBuffer.slice(4).let {
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
})
oidb_0x6d8.RspBody().mergeFrom(oidb.bytes_bodybuffer.get().toByteArray())
.file_list_info_rsp.apply {
rpt_item_list.get().forEach { file ->
if (file.uint32_type.get() == 1) {
if (file.uint32_type.get() == oidb_0x6d8.GetFileListRspBody.TYPE_FILE) {
val fileInfo = file.file_info
files.add(FileInfo(
groupId = groupId,
@ -147,7 +155,8 @@ internal object FileSvc: BaseSvc() {
uploadUin = fileInfo.uint64_uploader_uin.get(),
uploadNick = fileInfo.str_uploader_name.get()
))
} else if (file.uint32_type.get() == 2) {
}
else if (file.uint32_type.get() == oidb_0x6d8.GetFileListRspBody.TYPE_FOLDER) {
val folderInfo = file.folder_info
dirs.add(FolderInfo(
groupId = groupId,
@ -158,14 +167,19 @@ internal object FileSvc: BaseSvc() {
creator = folderInfo.uint64_create_uin.get(),
creatorNick = folderInfo.str_creator_name.get()
))
} else {
LogCenter.log("未知文件类型: ${file.uint32_type.get()}", Level.WARN)
}
}
}
} else {
throw RuntimeException("获取群文件列表失败")
}
} else {
throw RuntimeException("获取群文件列表失败")
}
return GroupFileList(files, dirs)
GroupFileList(files, dirs)
}.onFailure {
LogCenter.log(it.message + ", buffer: ${rspGetFileListBuffer.toHexString()}", Level.ERROR)
}
}
@Serializable

View File

@ -13,7 +13,10 @@ internal object GetGroupRootFiles: IActionHandler() {
}
suspend operator fun invoke(groupId: String, echo: JsonElement = EmptyJsonString): String {
return ok(FileSvc.getGroupRootFiles(groupId.toLong()), echo = echo)
FileSvc.getGroupRootFiles(groupId.toLong()).onSuccess {
return ok(it, echo = echo)
}.getOrNull()
return error(why = "获取失败,请查看日志", echo = echo)
}
override val requiredParams: Array<String> = arrayOf("group_id")

View File

@ -14,7 +14,10 @@ internal object GetGroupSubFiles: IActionHandler() {
}
suspend operator fun invoke(groupId: String, folderId: String, echo: JsonElement = EmptyJsonString): String {
return ok(FileSvc.getGroupFiles(groupId.toLong(), folderId), echo)
FileSvc.getGroupFiles(groupId.toLong(), folderId).onSuccess {
return ok(it, echo = echo)
}.getOrNull()
return error(why = "获取失败,请查看日志", echo = echo)
}
override val requiredParams: Array<String> = arrayOf("group_id", "folder_id")

View File

@ -9,7 +9,8 @@ data class ServiceConfig(
@SerialName("default_token") var defaultToken: String? = null,
@SerialName("active_websocket") var activeWebSocket: ConnectionConfig? = null,
@SerialName("passive_websocket") var passiveWebSocket: MutableList<ConnectionConfig>? = null,
@SerialName("allow-temp-session") var allowTempSession: Boolean = false
@SerialName("allow-temp-session") var allowTempSession: Boolean = false,
@SerialName("anti_qq_trace") var antiTrace: Boolean = true
)
@Serializable

View File

@ -208,4 +208,8 @@ internal object ShamrockConfig {
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
mmkv.putFloat(key, value)
}
fun isAntiTrace(): Boolean {
return Config.antiTrace
}
}

View File

@ -11,6 +11,7 @@ import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
import moe.fuqiuluo.shamrock.tools.hookMethod
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader
import mqq.app.MobileQQ
@ -21,7 +22,8 @@ import mqq.app.MobileQQ
class AntiDetection: IAction {
override fun invoke(ctx: Context) {
antiFindPackage(ctx)
antiTrace()
if (ShamrockConfig.isAntiTrace())
antiTrace()
antiMemoryWalking()
}