Commit 5f16f23c authored by Him188's avatar Him188

QQA Debugging update

parent 9353a5af
...@@ -36,9 +36,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler ...@@ -36,9 +36,13 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
println("Sending login") println("Sending login")
LoginPacket.SubCommand9(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>() LoginPacket.SubCommand9(bot.client).sendAndExpect<LoginPacket.LoginPacketResponse>()
println("SessionTicket=${bot.client.wLoginSigInfo.wtSessionTicket.data.toUHexString()}") println("SessionTicket=${bot.client.wLoginSigInfo.wtSessionTicket.data.toUHexString()}")
println("SessionTicketKey=${bot.client.wLoginSigInfo.d2Key.toUHexString()}") println("d2key=${bot.client.wLoginSigInfo.d2Key.toUHexString()}")
println("SessionTicketKey=${bot.client.wLoginSigInfo.wtSessionTicketKey.toUHexString()}") println("SessionTicketKey=${bot.client.wLoginSigInfo.wtSessionTicketKey.toUHexString()}")
delay(2000) delay(2000)
println()
println()
println()
println("Sending ReqRegister")
SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>() SvcReqRegisterPacket(bot.client, RegPushReason.setOnlineStatus).sendAndExpect<SvcReqRegisterPacket.Response>()
} }
......
...@@ -6,6 +6,7 @@ import kotlinx.io.core.ByteReadPacket ...@@ -6,6 +6,7 @@ import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.buildPacket import kotlinx.io.core.buildPacket
import kotlinx.io.core.writeFully import kotlinx.io.core.writeFully
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.LoginPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
...@@ -110,10 +111,12 @@ internal inline fun PacketFactory<*>.buildOutgingPacket( ...@@ -110,10 +111,12 @@ internal inline fun PacketFactory<*>.buildOutgingPacket(
internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
bodyType: Byte, // login=2, uni=1
extraData: ByteArray = EMPTY_BYTE_ARRAY, extraData: ByteArray = EMPTY_BYTE_ARRAY,
name: String? = null, name: String? = null,
id: PacketId = this.id, id: PacketId = this.id,
ssoExtraData: ByteReadPacket = BRP_STUB, ssoExtraData: ByteReadPacket = BRP_STUB,
key: ByteArray = KEY_16_ZEROS,
body: BytePacketBuilder.(sequenceId: Int) -> Unit body: BytePacketBuilder.(sequenceId: Int) -> Unit
): OutgoingPacket { ): OutgoingPacket {
val sequenceId: Int = client.nextSsoSequenceId() val sequenceId: Int = client.nextSsoSequenceId()
...@@ -121,7 +124,7 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( ...@@ -121,7 +124,7 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
return OutgoingPacket(name, id, sequenceId, buildPacket { return OutgoingPacket(name, id, sequenceId, buildPacket {
writeIntLVPacket(lengthOffset = { it + 4 }) { writeIntLVPacket(lengthOffset = { it + 4 }) {
writeInt(0x00_00_00_0A) writeInt(0x00_00_00_0A)
writeByte(0x02) writeByte(bodyType)
extraData.let { extraData.let {
writeInt(it.size + 4) writeInt(it.size + 4)
writeFully(it) writeFully(it)
...@@ -133,10 +136,8 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket( ...@@ -133,10 +136,8 @@ internal inline fun PacketFactory<*>.buildLoginOutgoingPacket(
writeStringUtf8(it) writeStringUtf8(it)
} }
encryptAndWrite(KEY_16_ZEROS) { encryptAndWrite(key) {
writeLoginSsoPacket(client, subAppId, id, ssoExtraData, sequenceId) { body(sequenceId)
body(sequenceId)
}
} }
} }
}) })
...@@ -169,7 +170,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY) ...@@ -169,7 +170,7 @@ private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
* byte[] body() * byte[] body()
*/ */
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
private inline fun BytePacketBuilder.writeLoginSsoPacket( internal inline fun BytePacketBuilder.writeLoginSsoPacket(
client: QQAndroidClient, client: QQAndroidClient,
subAppId: Long, subAppId: Long,
packetId: PacketId, packetId: PacketId,
......
...@@ -68,22 +68,32 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf( ...@@ -68,22 +68,32 @@ internal object KnownPacketFactories : List<PacketFactory<*>> by mutableListOf(
} }
check(remaining.toInt() == expectedLength) { "Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? " } check(remaining.toInt() == expectedLength) { "Invalid packet length. Expected $expectedLength, got ${rawInput.remaining} Probably packets merged? " }
// login // login
when (val flag1 = readInt()) { val flag1 = readInt()
0x0A -> when (val flag2 = readByte().toInt()) { when (val flag2 = readByte().toInt()) {
0x02 -> { 0x02 -> {
val flag3 = readByte().toInt() val flag3 = readByte().toInt()
check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" } check(flag3 == 0) { "Illegal flag3. Expected 0, got $flag3" }
bot.logger.verbose("got uinAccount = " + readString(readInt() - 4)) // uinAccount
//debugPrint("remaining")
}
else -> error("Illegal flag2. Expected 0x02, got $flag2")
}
when (flag1) {
0x0A -> parseLoginSsoPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
0x0B -> parseUniPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
}
}
bot.logger.verbose(readString(readInt() - 4)) // uinAccount private suspend fun parseUniPacket(bot: QQAndroidBot, rawInput: ByteReadPacket, consumer: PacketConsumer) =
rawInput.debugIfFail("Login sso packet") {
readIoBuffer(readInt() - 4).withUse {
//00 01 4E 64 FF FF D8 E8 00 00 00 14 6E 65 65 64 20 41 32 20 61 6E 64 20 49 4D 45 49 00 00 00 04 00 00 00 08 60 7F B6 23 00 00 00 00 00 00 00 04
val sequenceId = readInt()
//debugPrint("remaining") }
parseLoginSsoPacket(bot, decryptBy(DECRYPTER_16_ZERO), consumer)
} readIoBuffer(readInt() - 4).withUse {
else -> error("Illegal flag2. Expected 0x02, got $flag2") debugPrintln("收到 UniPacket 的 body=${this.readBytes().toUHexString()}")
}
// 00 00 00 60 00 00 00 0B 02 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 CE 35 53 19 84 A8 1A B8 5B 48 E3 7C D0 A6 BA 58 6A EB CE 50 B9 A0 98 D5 B9 D0 1C 72 E2 86 24 FC 55 44 6C 6E E3 F9 15 6C EC 6C 6B 94 40 F7 B4 45 CF B4 D0 79 84 FE 30 EA 98 84 44 84 02 32 70 DD D7 07 07 72 DE 87 59 AC
0x0B ->
else -> error("Illegal flag1. Expected 0x0A or 0x0B, got $flag1")
} }
} }
......
...@@ -35,137 +35,139 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { ...@@ -35,137 +35,139 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
operator fun invoke( operator fun invoke(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, subAppId) { sequenceId -> ): OutgoingPacket = buildLoginOutgoingPacket(client, subAppId = subAppId, bodyType = 2) { sequenceId ->
writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), id) { writeLoginSsoPacket(client, subAppId, id, sequenceId = sequenceId) {
writeShort(9) // subCommand writeOicqRequestPacket(client, EncryptMethodECDH7(client.ecdh), id) {
writeShort(17) // count of TLVs, probably ignored by server? writeShort(9) // subCommand
//writeShort(LoginType.PASSWORD.value.toShort()) writeShort(17) // count of TLVs, probably ignored by server?
//writeShort(LoginType.PASSWORD.value.toShort())
t18(appId, client.appClientVersion, client.uin)
t1(client.uin, client.device.ipAddress) t18(appId, client.appClientVersion, client.uin)
t106( t1(client.uin, client.device.ipAddress)
appId, t106(
subAppId /* maybe 1*/, appId,
client.appClientVersion, subAppId /* maybe 1*/,
client.uin, client.appClientVersion,
1, client.uin,
client.account.passwordMd5, 1,
0, client.account.passwordMd5,
client.uin.toByteArray(), 0,
client.tgtgtKey, client.uin.toByteArray(),
true, client.tgtgtKey,
client.device.guid, true,
LoginType.PASSWORD client.device.guid,
) LoginType.PASSWORD
)
/* // from GetStWithPasswd /* // from GetStWithPasswd
int mMiscBitmap = this.mMiscBitmap; int mMiscBitmap = this.mMiscBitmap;
if (t.uinDeviceToken) { if (t.uinDeviceToken) {
mMiscBitmap = (this.mMiscBitmap | 0x2000000); mMiscBitmap = (this.mMiscBitmap | 0x2000000);
} }
// defaults true // defaults true
if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L) if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L)
*/ */
t116(client.miscBitMap, client.subSigMap) t116(client.miscBitMap, client.subSigMap)
t100(appId, subAppId, client.appClientVersion, client.mainSigMap or 0xC0) t100(appId, subAppId, client.appClientVersion, client.mainSigMap or 0xC0)
t107(0) t107(0)
// t108(byteArrayOf()) // t108(byteArrayOf())
// ignored: t104() // ignored: t104()
t142(client.apkId) t142(client.apkId)
// if login with non-number uin // if login with non-number uin
// t112() // t112()
t144( t144(
androidId = client.device.androidId, androidId = client.device.androidId,
androidDevInfo = client.device.generateDeviceInfoData(), androidDevInfo = client.device.generateDeviceInfoData(),
osType = client.device.osType, osType = client.device.osType,
osVersion = client.device.version.release, osVersion = client.device.version.release,
networkType = client.networkType, networkType = client.networkType,
simInfo = client.device.simInfo, simInfo = client.device.simInfo,
unknown = byteArrayOf(), unknown = byteArrayOf(),
apn = client.device.apn, apn = client.device.apn,
isGuidFromFileNull = false, isGuidFromFileNull = false,
isGuidAvailable = true, isGuidAvailable = true,
isGuidChanged = false, isGuidChanged = false,
guidFlag = guidFlag(GuidSource.FROM_STORAGE, MacOrAndroidIdChangeFlag.NoChange), guidFlag = guidFlag(GuidSource.FROM_STORAGE, MacOrAndroidIdChangeFlag.NoChange),
buildModel = client.device.model, buildModel = client.device.model,
guid = client.device.guid, guid = client.device.guid,
buildBrand = client.device.brand, buildBrand = client.device.brand,
tgtgtKey = client.tgtgtKey tgtgtKey = client.tgtgtKey
) )
//this.build().debugPrint("傻逼") //this.build().debugPrint("傻逼")
t145(client.device.guid) t145(client.device.guid)
t147(appId, client.apkVersionName, client.apkSignatureMd5) t147(appId, client.apkVersionName, client.apkSignatureMd5)
if (client.miscBitMap and 0x80 != 0) { if (client.miscBitMap and 0x80 != 0) {
t166(1) t166(1)
} }
// ignored t16a because array5 is null // ignored t16a because array5 is null
t154(sequenceId) t154(sequenceId)
t141(client.device.simInfo, client.networkType, client.device.apn) t141(client.device.simInfo, client.networkType, client.device.apn)
t8(2052) t8(2052)
t511( t511(
listOf( listOf(
"tenpay.com", "tenpay.com",
"openmobile.qq.com", "openmobile.qq.com",
"docs.qq.com", "docs.qq.com",
"connect.qq.com", "connect.qq.com",
"qzone.qq.com", "qzone.qq.com",
"vip.qq.com", "vip.qq.com",
"qun.qq.com", "qun.qq.com",
"game.qq.com", "game.qq.com",
"qqweb.qq.com", "qqweb.qq.com",
"office.qq.com", "office.qq.com",
"ti.qq.com", "ti.qq.com",
"mail.qq.com", "mail.qq.com",
"qzone.com", "qzone.com",
"mma.qq.com" "mma.qq.com"
)
) )
)
// ignored t172 because rollbackSig is null // ignored t172 because rollbackSig is null
// ignored t185 because loginType is not SMS // ignored t185 because loginType is not SMS
// ignored t400 because of first login // ignored t400 because of first login
t187(client.device.macAddress) t187(client.device.macAddress)
t188(client.device.androidId) t188(client.device.androidId)
val imsi = client.device.imsiMd5 val imsi = client.device.imsiMd5
if (imsi.isNotEmpty()) { if (imsi.isNotEmpty()) {
t194(imsi) t194(imsi)
} }
t191() t191()
/* /*
t201(N = byteArrayOf())*/ t201(N = byteArrayOf())*/
val bssid = client.device.wifiBSSID val bssid = client.device.wifiBSSID
val ssid = client.device.wifiSSID val ssid = client.device.wifiSSID
if (bssid != null && ssid != null) { if (bssid != null && ssid != null) {
t202(bssid, ssid) t202(bssid, ssid)
} }
t177() t177()
t516() t516()
t521() t521()
t525(buildPacket { t525(buildPacket {
t536(buildPacket { t536(buildPacket {
//com.tencent.loginsecsdk.ProtocolDet#packExtraData //com.tencent.loginsecsdk.ProtocolDet#packExtraData
writeByte(1) // const writeByte(1) // const
writeByte(0) // data count writeByte(0) // data count
}.readBytes()) }.readBytes())
}) })
// this.build().debugPrint("傻逼") // this.build().debugPrint("傻逼")
// ignored t318 because not logging in by QR // ignored t318 because not logging in by QR
}
} }
} }
} }
...@@ -335,7 +337,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() { ...@@ -335,7 +337,7 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse>() {
var a1: ByteArray? = null var a1: ByteArray? = null
var noPicSig: ByteArray? = null var noPicSig: ByteArray? = null
tlvMap119[0x531]?.let { tlvMap119[0x531]?.let {
analysisTlv0x531(it){ arg1, arg2 -> analysisTlv0x531(it) { arg1, arg2 ->
a1 = arg1 a1 = arg1
noPicSig = arg2 noPicSig = arg2
} }
......
...@@ -11,8 +11,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister ...@@ -11,8 +11,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.jce.SvcReqRegister
import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket import net.mamoe.mirai.qqandroid.network.protocol.jce.writeUniRequestPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory import net.mamoe.mirai.qqandroid.network.protocol.packet.PacketFactory
import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgingPacket import net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769 import net.mamoe.mirai.qqandroid.network.protocol.packet.oidb.oidb0x769.Oidb0x769
import net.mamoe.mirai.qqandroid.network.protocol.packet.writeLoginSsoPacket
import net.mamoe.mirai.qqandroid.utils.NetworkType import net.mamoe.mirai.qqandroid.utils.NetworkType
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.io.encodeToString import net.mamoe.mirai.utils.io.encodeToString
...@@ -34,65 +35,79 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon ...@@ -34,65 +35,79 @@ internal object SvcReqRegisterPacket : PacketFactory<SvcReqRegisterPacket.Respon
internal object Response : Packet internal object Response : Packet
const val subAppId = 537062845L
init {
_id = PacketId(0, "StatSvc.register")
}
operator fun invoke( operator fun invoke(
client: QQAndroidClient, client: QQAndroidClient,
regPushReason: RegPushReason = RegPushReason.setOnlineStatus regPushReason: RegPushReason = RegPushReason.setOnlineStatus
): OutgoingPacket = buildOutgingPacket(client, key = client.wLoginSigInfo.d2Key) { ): OutgoingPacket = buildLoginOutgoingPacket(
writeUniRequestPacket { client,
sServantName = "PushService" bodyType = 1,
sFuncName = "SvcReqRegister" extraData = client.wLoginSigInfo.d2.data,
sBuffer = jceMap( key = client.wLoginSigInfo.d2Key,
0, subAppId = subAppId
"SvcReqRegister" to jceStruct( ) { sequenceId ->
writeLoginSsoPacket(client, subAppId= subAppId, packetId = id, sequenceId = sequenceId){
writeUniRequestPacket {
sServantName = "PushService"
sFuncName = "SvcReqRegister"
sBuffer = jceMap(
0, 0,
SvcReqRegister( "SvcReqRegister" to jceStruct(
cConnType = 0, 0,
lBid = 1 or 2 or 4, SvcReqRegister(
lUin = client.uin, cConnType = 0,
iStatus = client.onlineStatus.id, lBid = 1 or 2 or 4,
bKikPC = 0, // 是否把 PC 踢下线 lUin = client.uin,
bKikWeak = 0, iStatus = client.onlineStatus.id,
timeStamp = currentTimeSeconds, // millis or seconds?? bKikPC = 0, // 是否把 PC 踢下线
iLargeSeq = 0, bKikWeak = 0,
bRegType = timeStamp = currentTimeSeconds, // millis or seconds??
(if (regPushReason == RegPushReason.appRegister || iLargeSeq = 0,
regPushReason == RegPushReason.fillRegProxy || bRegType =
regPushReason == RegPushReason.createDefaultRegInfo || (if (regPushReason == RegPushReason.appRegister ||
regPushReason == RegPushReason.setOnlineStatus regPushReason == RegPushReason.fillRegProxy ||
) 0 else 1).toByte(), regPushReason == RegPushReason.createDefaultRegInfo ||
bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0, regPushReason == RegPushReason.setOnlineStatus
iOSVersion = client.device.version.sdk.toLong(), ) 0 else 1).toByte(),
cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0, bIsSetStatus = if (regPushReason == RegPushReason.setOnlineStatus) 1 else 0,
vecGuid = client.device.guid, iOSVersion = client.device.version.sdk.toLong(),
strDevName = client.device.model.encodeToString(), cNetType = if (client.networkType == NetworkType.WIFI) 1 else 0,
strDevType = client.device.model.encodeToString(), vecGuid = client.device.guid,
strOSVer = client.device.version.release.encodeToString(), strDevName = client.device.model.encodeToString(),
strDevType = client.device.model.encodeToString(),
strOSVer = client.device.version.release.encodeToString(),
// register 时还需要 // register 时还需要
/* /*
var44.uNewSSOIp = field_127445; var44.uNewSSOIp = field_127445;
var44.uOldSSOIp = field_127444; var44.uOldSSOIp = field_127444;
var44.strVendorName = ROMUtil.getRomName(); var44.strVendorName = ROMUtil.getRomName();
var44.strVendorOSName = ROMUtil.getRomVersion(20); var44.strVendorOSName = ROMUtil.getRomVersion(20);
*/ */
bytes_0x769_reqbody = ProtoBuf.dump( bytes_0x769_reqbody = ProtoBuf.dump(
Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody( Oidb0x769.RequestBody.serializer(), Oidb0x769.RequestBody(
rpt_config_list = listOf( rpt_config_list = listOf(
Oidb0x769.ConfigSeq( Oidb0x769.ConfigSeq(
type = 46, type = 46,
version = 4 version = 4
), ),
Oidb0x769.ConfigSeq( Oidb0x769.ConfigSeq(
type = 283, type = 283,
version = 0 version = 0
)
) )
) )
) ),
), bSetMute = 0
bSetMute = 0 )
) )
) )
) }
} }
} }
......
...@@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() { ...@@ -20,7 +20,7 @@ internal object TransEmpPacket : PacketFactory<TransEmpPacket.Response>() {
@Suppress("FunctionName") @Suppress("FunctionName")
fun SubCommand1( fun SubCommand1(
client: QQAndroidClient client: QQAndroidClient
): OutgoingPacket = buildLoginOutgoingPacket(client, subAppId, ssoExtraData = byteArrayOf().toReadPacket()) { ): OutgoingPacket = buildLoginOutgoingPacket(client, bodyType = 2, subAppId = subAppId, ssoExtraData = byteArrayOf().toReadPacket()) {
writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) { writeOicqRequestPacket(client, EncryptMethodECDH135(client.ecdh), id) {
// oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody // oicq.wlogin_sdk.request.trans_emp_1#packTransEmpBody
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment