mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-25 06:50:09 +08:00
Android stuff
This commit is contained in:
parent
67903e6737
commit
b062c58015
mirai-core-qqandroid/src
androidMain/kotlin/net/mamoe/mirai/qqandroid/utils
commonMain/kotlin/net/mamoe/mirai/qqandroid
network
utils
jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils
@ -66,6 +66,8 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo(
|
||||
get() = md5(kotlin.runCatching {
|
||||
(context.applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager).subscriberId.toByteArray()
|
||||
}.getOrElse { byteArrayOf() })
|
||||
override val imei: String get() = "858414369211993" // TODO: 2020/1/5 get actual imei and ksid
|
||||
override val ksid: String get() = "|454001228437590|A8.2.0.27f6ea96"
|
||||
override val ipAddress: String get() = localIpAddress()
|
||||
override val androidId: ByteArray get() = Build.ID.toByteArray()
|
||||
override val apn: ByteArray get() = "wifi".toByteArray()
|
||||
|
@ -1,8 +1,11 @@
|
||||
package net.mamoe.mirai.qqandroid.network
|
||||
|
||||
import kotlinx.atomicfu.AtomicInt
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.io.core.toByteArray
|
||||
import net.mamoe.mirai.BotAccount
|
||||
import net.mamoe.mirai.qqandroid.utils.*
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.hexToBytes
|
||||
|
||||
/*
|
||||
@ -33,7 +36,11 @@ internal open class QQAndroidClient(
|
||||
var mainSigMap: Int = 16724722
|
||||
var subSigMap: Int = 0x10400 //=66,560
|
||||
|
||||
var ssoSequenceId: Int = 85602
|
||||
private val _ssoSequenceId: AtomicInt = atomic(85600)
|
||||
|
||||
@MiraiInternalAPI("Do not use directly. Get from the lambda param of buildSsoPacket")
|
||||
internal fun nextSsoSequenceId() = _ssoSequenceId.addAndGet(2)
|
||||
|
||||
var openAppId: Long = 715019303L
|
||||
|
||||
val apkVersionName: ByteArray = "8.2.0".toByteArray()
|
||||
|
@ -1,22 +1,25 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.packet
|
||||
|
||||
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.core.BytePacketBuilder
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import kotlinx.io.core.buildPacket
|
||||
import kotlinx.io.core.writeFully
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.login.PacketId
|
||||
import net.mamoe.mirai.qqandroid.utils.ECDH
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.encryptAndWrite
|
||||
import net.mamoe.mirai.utils.io.writeIntLVPacket
|
||||
import net.mamoe.mirai.utils.io.writeQQ
|
||||
import net.mamoe.mirai.utils.io.writeShortLVByteArray
|
||||
import net.mamoe.mirai.utils.cryptor.DecrypterByteArray
|
||||
import net.mamoe.mirai.utils.cryptor.encryptAndWrite
|
||||
import net.mamoe.mirai.utils.cryptor.encryptBy
|
||||
import net.mamoe.mirai.utils.io.*
|
||||
|
||||
/**
|
||||
* 待发送给服务器的数据包. 它代表着一个 [ByteReadPacket],
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
class OutgoingPacket constructor(
|
||||
internal class OutgoingPacket constructor(
|
||||
name: String?,
|
||||
val packetId: PacketId,
|
||||
val sequenceId: UShort,
|
||||
@ -27,28 +30,218 @@ class OutgoingPacket constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private val KEY_16_ZEROS = ByteArray(16)
|
||||
private val EMPTY_BYTE_ARRAY = ByteArray(0)
|
||||
|
||||
/**
|
||||
* Encryption method to be used for packet body.
|
||||
* Outermost packet for login
|
||||
*
|
||||
* **Packet structure**
|
||||
* int remaining.length + 4
|
||||
* int 0x0A
|
||||
* byte 0x02
|
||||
* int extra data size + 4
|
||||
* byte[] extra data
|
||||
* byte 0
|
||||
* int [uinAccount].length + 4
|
||||
* byte[] uinAccount
|
||||
*
|
||||
* byte[] body encrypted by 16 zero
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
inline class EncryptMethod(val value: UByte) {
|
||||
companion object {
|
||||
val BySessionToken = EncryptMethod(69u)
|
||||
val ByECDH7 = EncryptMethod(7u)
|
||||
// 登录都使用 135
|
||||
val ByECDH135 = EncryptMethod(135u)
|
||||
internal inline fun PacketFactory<*, *>.buildLoginOutgoingPacket(
|
||||
uinAccount: String,
|
||||
extraData: ByteArray = EMPTY_BYTE_ARRAY,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket = OutgoingPacket(name, id, sequenceId, buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(0x00_00_00_0A)
|
||||
writeByte(0x02)
|
||||
writeInt(extraData.size + 4)
|
||||
writeFully(extraData)
|
||||
writeByte(0x00)
|
||||
|
||||
writeInt(uinAccount.length + 4)
|
||||
writeStringUtf8(uinAccount)
|
||||
|
||||
encryptAndWrite(KEY_16_ZEROS, body)
|
||||
}
|
||||
})
|
||||
|
||||
internal class CommandId(val stringValue: String, val id: Int) {
|
||||
override fun toString(): String = stringValue
|
||||
}
|
||||
|
||||
|
||||
private val BRP_STUB = ByteReadPacket(EMPTY_BYTE_ARRAY)
|
||||
|
||||
/**
|
||||
* The second outermost packet for login
|
||||
*
|
||||
*
|
||||
*/
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal inline fun BytePacketBuilder.writeLoginSsoPacket(
|
||||
client: QQAndroidClient,
|
||||
subAppId: Long,
|
||||
commandId: CommandId,
|
||||
extraData: ByteReadPacket = BRP_STUB,
|
||||
body: BytePacketBuilder.(ssoSequenceId: Int) -> Unit
|
||||
) {
|
||||
val ssoSequenceId = client.nextSsoSequenceId()
|
||||
// head
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(ssoSequenceId)
|
||||
writeInt(subAppId.toInt())
|
||||
writeInt(subAppId.toInt())
|
||||
writeHex("01 00 00 00 00 00 00 00 00 00 01 00")
|
||||
if (extraData === BRP_STUB) {
|
||||
writeInt(0x04)
|
||||
} else {
|
||||
writeInt((extraData.remaining + 4).toInt())
|
||||
writePacket(extraData)
|
||||
}
|
||||
writeInt(commandId.stringValue.length + 4)
|
||||
writeStringUtf8(commandId.stringValue)
|
||||
|
||||
writeInt(4 + 4)
|
||||
writeInt(45112203) // 02 B0 5B 8B
|
||||
|
||||
val imei = client.device.imei
|
||||
writeInt(imei.length + 4)
|
||||
writeStringUtf8(imei)
|
||||
|
||||
writeInt(4)
|
||||
|
||||
val ksid = client.device.ksid
|
||||
writeShort((ksid.length + 2).toShort())
|
||||
writeStringUtf8(ksid)
|
||||
|
||||
writeInt(4)
|
||||
}
|
||||
|
||||
// body
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
body(ssoSequenceId)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a outgoing packet.
|
||||
* [OutgoingPacket] is the **outermost** packet structure.
|
||||
* This packet will be sent to the server.
|
||||
* Outermost packet, not for login
|
||||
*
|
||||
* **Packet structure**
|
||||
* int remaining.length + 4
|
||||
* int 0x0B
|
||||
* byte 0x01
|
||||
* byte 0
|
||||
* int [uinAccount].length + 4
|
||||
* byte[] uinAccount
|
||||
*
|
||||
* byte[] body encrypted by [sessionKey]
|
||||
*/
|
||||
internal inline fun PacketFactory<*, *>.buildSessionOutgoingPacket(
|
||||
uinAccount: String,
|
||||
sessionKey: DecrypterByteArray,
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
): ByteReadPacket = buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
writeInt(0x00_00_00_0B)
|
||||
writeByte(0x01)
|
||||
|
||||
writeByte(0)
|
||||
|
||||
writeInt(uinAccount.length + 4)
|
||||
writeStringUtf8(uinAccount)
|
||||
|
||||
encryptAndWrite(sessionKey, body)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encryption method to be used for packet body.
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
interface EncryptMethod {
|
||||
val id: Int
|
||||
|
||||
fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket)
|
||||
}
|
||||
|
||||
internal interface EncryptMethodSessionKey : EncryptMethod {
|
||||
override val id: Int get() = 69
|
||||
val currentLoginState: Int
|
||||
val sessionKey: ByteArray
|
||||
|
||||
/**
|
||||
* buildPacket{
|
||||
* byte 1
|
||||
* byte if (currentLoginState == 2) 3 else 2
|
||||
* fully key
|
||||
* short 258
|
||||
* short 0
|
||||
* fully encrypted
|
||||
* }
|
||||
*/
|
||||
override fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket) {
|
||||
require(currentLoginState == 2 || currentLoginState == 3) { "currentLoginState must be either 2 or 3" }
|
||||
writeByte(1) // const
|
||||
writeByte(if (currentLoginState == 2) 3 else 2)
|
||||
writeFully(sessionKey)
|
||||
writeShort(258) // const
|
||||
writeShort(0) // const, length of publicKey
|
||||
body.encryptBy(sessionKey) { encrypted -> writeFully(encrypted) }
|
||||
}
|
||||
}
|
||||
|
||||
inline class EncryptMethodSessionKeyLoginState2(override val sessionKey: ByteArray) : EncryptMethodSessionKey {
|
||||
override val currentLoginState: Int get() = 2
|
||||
}
|
||||
|
||||
inline class EncryptMethodSessionKeyLoginState3(override val sessionKey: ByteArray) : EncryptMethodSessionKey {
|
||||
override val currentLoginState: Int get() = 3
|
||||
}
|
||||
|
||||
inline class EncryptMethodECDH135(override val ecdh: ECDH) : EncryptMethodECDH {
|
||||
override val id: Int get() = 135
|
||||
}
|
||||
|
||||
inline class EncryptMethodECDH7(override val ecdh: ECDH) : EncryptMethodECDH {
|
||||
override val id: Int get() = 7
|
||||
}
|
||||
|
||||
internal interface EncryptMethodECDH : EncryptMethod {
|
||||
val ecdh: ECDH
|
||||
|
||||
/**
|
||||
* **Packet Structure**
|
||||
* byte 1
|
||||
* byte 1
|
||||
* byte[] [ECDH.privateKey]
|
||||
* short 258
|
||||
* short [ECDH.publicKey].size
|
||||
* byte[] [ECDH.publicKey]
|
||||
* byte[] encrypted `body()` by [ECDH.shareKey]
|
||||
*/
|
||||
override fun BytePacketBuilder.encryptAndWrite(body: ByteReadPacket) = ecdh.run {
|
||||
writeByte(1) // const
|
||||
writeByte(1) // const
|
||||
writeFully(privateKey)
|
||||
writeShort(258) // const
|
||||
writeShortLVByteArray(publicKey)
|
||||
body.encryptBy(shareKey) { encrypted -> writeFully(encrypted) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a request packet
|
||||
* This is the innermost packet structure
|
||||
*
|
||||
* **Packet Structure**
|
||||
* byte 2 // head flag
|
||||
* short 27 + 2 + body.size
|
||||
* short 27 + 2 + remaining.length
|
||||
* ushort client.protocolVersion // const 8001
|
||||
* ushort sequenceId
|
||||
* uint client.account.id
|
||||
@ -60,44 +253,39 @@ inline class EncryptMethod(val value: UByte) {
|
||||
* int 0 // const
|
||||
* bodyBlock()
|
||||
* byte 3 // tail
|
||||
*
|
||||
* @param name optional name to be displayed in logs
|
||||
*
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
|
||||
internal inline fun PacketFactory<*, *>.buildOutgoingPacket(
|
||||
internal inline fun BytePacketBuilder.writeRequestPacket(
|
||||
client: QQAndroidClient,
|
||||
encryptMethod: EncryptMethod,
|
||||
name: String? = null,
|
||||
id: PacketId = this.id,
|
||||
commandId: CommandId,
|
||||
sequenceId: UShort = PacketFactory.atomicNextSequenceId(),
|
||||
bodyBlock: BytePacketBuilder.() -> Unit
|
||||
): OutgoingPacket {
|
||||
val body = buildPacket { bodyBlock() }
|
||||
return OutgoingPacket(name, id, sequenceId, buildPacket {
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
) {
|
||||
val body = encryptMethod.run {
|
||||
buildPacket { encryptAndWrite(buildPacket { bodyBlock() }) }
|
||||
}
|
||||
writeIntLVPacket(lengthOffset = { it + 4 }) {
|
||||
// Head
|
||||
writeByte(0x02) // head
|
||||
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
|
||||
writeShort(client.protocolVersion)
|
||||
writeShort(sequenceId.toShort())
|
||||
writeShort(commandId.id.toShort())
|
||||
writeQQ(client.account.id)
|
||||
writeByte(3) // originally const
|
||||
writeByte(encryptMethod.id.toByte())
|
||||
writeByte(0) // const8_always_0
|
||||
writeInt(2) // originally const
|
||||
writeInt(client.appClientVersion)
|
||||
writeInt(0) // constp_always_0
|
||||
|
||||
// Head
|
||||
writeByte(0x02) // head
|
||||
writeShort((27 + 2 + body.remaining).toShort()) // orthodox algorithm
|
||||
writeShort(client.protocolVersion)
|
||||
writeShort(sequenceId.toShort())
|
||||
writeShort(id.commandId.toShort())
|
||||
writeQQ(client.account.id)
|
||||
writeByte(3) // originally const
|
||||
writeUByte(encryptMethod.value)
|
||||
writeByte(0) // const8_always_0
|
||||
writeInt(2) // originally const
|
||||
writeInt(client.appClientVersion)
|
||||
writeInt(0) // constp_always_0
|
||||
// Body
|
||||
writePacket(body)
|
||||
|
||||
// Body
|
||||
writePacket(body)
|
||||
|
||||
// Tail
|
||||
writeByte(0x03) // tail
|
||||
}
|
||||
})
|
||||
// Tail
|
||||
writeByte(0x03) // tail
|
||||
}
|
||||
}
|
||||
/*
|
||||
00 00 01 64
|
||||
@ -158,57 +346,4 @@ F8 22 FC 39 2E 93 D7 73 A9 75 A2 D4 67 D2 C4 0D F1 02 1F A5 74 8F D8 0E 8E 86 AF
|
||||
|
||||
00 00 00 0E 31 39 39 34 37 30 31 30 32 31 D2 D5 37 8A 3C 47 B1 84 E2 94 B2 AF BF 14 70 4D 73 17 BB 38 BE 82 73 DF A2 87 E0 0A 7A BA 8A 81 71 77 1D E1 71 7F B7 C1 66 1D 8C 3D 41 4F 51 09 6A B7 B7 7B 88 28 A6 5A AB 7E 40 25 9B C8 35 9C C6 E2 3A 5F 94 1D 70 0F D7 89 4D 41 6B 7A 29 A2 70 77 3D F8 1D 32 65 D7 D8 D1 6D 13 42 9C 0C 72 DB 48 95 4B 66 EF B9 E6 E4 C1 3B 2C 36 B0 D7 3F E2 85 C8 2A 8C 65 0F 0B 1C F1 A7 C7 E1 1F 0C 32 F5 08 14 AA 5A 43 CD 8E A8 82 14 24 97 63 F0 53 79 4E 33 8D 5F 1C F8 1C 89 3B 39 44 CC A7 63 5F FC BF 87 42 89 2D A5 F4 BC B2 69 49 54 DD AE E6 3F A2 A2 98 DC 3B D4 A2 27 10 F2 06 42 93 C5 30 4A D4 FA F5 BA A5 B2 4B 56 45 59 94 CA 4C 4B 17 55 C7 23 AF F0 8B E5 DC 3A 1B B6 A7 2E 10 BB 9A E7 70 54 BA F5 4B 70 91
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Encrypt the [body] by [ECDH.shareKey], then write encryption arguments stuff.
|
||||
* This is **the second outermost** packet structure
|
||||
*
|
||||
* **Packet Structure**
|
||||
* byte 1
|
||||
* byte 1
|
||||
* byte[] [ECDH.privateKey]
|
||||
* short 258
|
||||
* short [ECDH.publicKey].size
|
||||
* byte[] [ECDH.publicKey]
|
||||
* byte[] encrypted `body()` by [ECDH.shareKey]
|
||||
*/
|
||||
inline fun BytePacketBuilder.writeECDHEncryptedPacket(
|
||||
ecdh: ECDH,
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
) = ecdh.run {
|
||||
writeByte(1) // const
|
||||
writeByte(1) // const
|
||||
writeFully(privateKey)
|
||||
writeShort(258) // const
|
||||
writeShortLVByteArray(publicKey)
|
||||
encryptAndWrite(shareKey, body)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* buildPacket{
|
||||
* byte 1
|
||||
* if loginState == 2:
|
||||
* byte 3
|
||||
* else:
|
||||
* byte 2
|
||||
* fully key
|
||||
* short 258
|
||||
* short 0
|
||||
* fully encrypted
|
||||
* }
|
||||
*/
|
||||
inline fun BytePacketBuilder.writeTEAEncryptedPacket(
|
||||
loginState: Int,
|
||||
key: ByteArray,
|
||||
body: BytePacketBuilder.() -> Unit
|
||||
) {
|
||||
require(loginState == 2 || loginState == 3)
|
||||
writeByte(1) // const
|
||||
writeByte(if (loginState == 2) 3 else 2) // const
|
||||
writeFully(key)
|
||||
writeShort(258) // const
|
||||
writeShort(0) // const, length of publicKey
|
||||
encryptAndWrite(key, body)
|
||||
}
|
||||
*/
|
@ -18,7 +18,7 @@ import net.mamoe.mirai.utils.cryptor.DecrypterType
|
||||
* @param TDecrypter 服务器回复包解密器
|
||||
*/
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val decrypterType: DecrypterType<TDecrypter>) {
|
||||
internal abstract class PacketFactory<out TPacket : Packet, TDecrypter : Decrypter>(val decrypterType: DecrypterType<TDecrypter>) {
|
||||
|
||||
@Suppress("PropertyName")
|
||||
internal var _id: PacketId = NullPacketId
|
||||
|
@ -22,140 +22,142 @@ class LoginPacketDecrypter(override val value: ByteArray) : DecrypterByteArray {
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, LoginPacketDecrypter>(LoginPacketDecrypter) {
|
||||
init {
|
||||
this._id = PacketId(0x0810, 9)
|
||||
this._id = PacketId(CommandId("wtlogin.login", 0x0810), 9)
|
||||
}
|
||||
|
||||
operator fun invoke(
|
||||
client: QQAndroidClient
|
||||
): OutgoingPacket = buildOutgoingPacket(client, EncryptMethod.ByECDH135) {
|
||||
writeECDHEncryptedPacket(client.ecdh) {
|
||||
writeShort(9) // subCommand
|
||||
writeShort(LoginType.PASSWORD.value.toShort())
|
||||
): OutgoingPacket = buildLoginOutgoingPacket(client.account.id.toString()) {
|
||||
val appId = 16L
|
||||
val subAppId = 537062845L
|
||||
|
||||
val appId = 16L
|
||||
val subAppId = 537062845L
|
||||
writeLoginSsoPacket(client, subAppId, _id.commandId) { ssoSequenceId ->
|
||||
writeRequestPacket(client, EncryptMethodECDH135(client.ecdh), _id.commandId) {
|
||||
writeShort(9) // subCommand
|
||||
writeShort(LoginType.PASSWORD.value.toShort())
|
||||
|
||||
t18(appId, client.appClientVersion, client.account.id)
|
||||
t1(client.account.id, client.device.ipAddress)
|
||||
t106(
|
||||
appId,
|
||||
subAppId /* maybe 1*/,
|
||||
client.appClientVersion,
|
||||
client.account.id,
|
||||
1,
|
||||
client.account.passwordMd5,
|
||||
0,
|
||||
client.account.id.toByteArray(),
|
||||
client.tgtgtKey,
|
||||
true,
|
||||
client.device.guid,
|
||||
LoginType.PASSWORD
|
||||
)
|
||||
|
||||
/* // from GetStWithPasswd
|
||||
int mMiscBitmap = this.mMiscBitmap;
|
||||
if (t.uinDeviceToken) {
|
||||
mMiscBitmap = (this.mMiscBitmap | 0x2000000);
|
||||
}
|
||||
|
||||
|
||||
// defaults true
|
||||
if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L)
|
||||
*/
|
||||
t116(client.miscBitMap, client.subSigMap)
|
||||
t100(appId, subAppId, client.appClientVersion, client.mainSigMap or 0xC0)
|
||||
t107(0)
|
||||
|
||||
// t108(byteArrayOf())
|
||||
// ignored: t104()
|
||||
t142(client.apkId)
|
||||
|
||||
// if login with non-number uin
|
||||
// t112()
|
||||
t144(
|
||||
androidId = client.device.androidId,
|
||||
androidDevInfo = client.device.generateDeviceInfoData(),
|
||||
osType = client.device.osType,
|
||||
osVersion = client.device.version.release,
|
||||
networkType = client.networkType,
|
||||
simInfo = client.device.simInfo,
|
||||
unknown = byteArrayOf(),
|
||||
apn = client.device.apn,
|
||||
isGuidFromFileNull = false,
|
||||
isGuidAvailable = true,
|
||||
isGuidChanged = false,
|
||||
guidFlag = guidFlag(GuidSource.FROM_STORAGE, MacOrAndroidIdChangeFlag.NoChange),
|
||||
buildModel = client.device.model,
|
||||
guid = client.device.guid,
|
||||
buildBrand = client.device.brand,
|
||||
tgtgtKey = client.tgtgtKey
|
||||
)
|
||||
|
||||
t145(client.device.guid)
|
||||
t147(appId, client.apkVersionName, client.apkSignatureMd5)
|
||||
|
||||
if (client.miscBitMap and 0x80 != 0) {
|
||||
t166(1)
|
||||
}
|
||||
|
||||
// ignored t16a because array5 is null
|
||||
|
||||
t154(client.ssoSequenceId)
|
||||
t141(client.device.simInfo, client.networkType, client.device.apn)
|
||||
t8(2052)
|
||||
|
||||
t511(
|
||||
listOf(
|
||||
"tenpay.com",
|
||||
"openmobile.qq.com",
|
||||
"docs.qq.com",
|
||||
"connect.qq.com",
|
||||
"qzone.qq.com",
|
||||
"vip.qq.com",
|
||||
"qun.qq.com",
|
||||
"game.qq.com",
|
||||
"qqweb.qq.com",
|
||||
"office.qq.com",
|
||||
"ti.qq.com",
|
||||
"mail.qq.com",
|
||||
"qzone.com",
|
||||
"mma.qq.com"
|
||||
t18(appId, client.appClientVersion, client.account.id)
|
||||
t1(client.account.id, client.device.ipAddress)
|
||||
t106(
|
||||
appId,
|
||||
subAppId /* maybe 1*/,
|
||||
client.appClientVersion,
|
||||
client.account.id,
|
||||
1,
|
||||
client.account.passwordMd5,
|
||||
0,
|
||||
client.account.id.toByteArray(),
|
||||
client.tgtgtKey,
|
||||
true,
|
||||
client.device.guid,
|
||||
LoginType.PASSWORD
|
||||
)
|
||||
)
|
||||
|
||||
// ignored t172 because rollbackSig is null
|
||||
// ignored t185 because loginType is not SMS
|
||||
// ignored t400 because of first login
|
||||
/* // from GetStWithPasswd
|
||||
int mMiscBitmap = this.mMiscBitmap;
|
||||
if (t.uinDeviceToken) {
|
||||
mMiscBitmap = (this.mMiscBitmap | 0x2000000);
|
||||
}
|
||||
|
||||
t187(client.device.macAddress)
|
||||
t188(client.device.androidId)
|
||||
if (client.device.imsiMd5.isNotEmpty()) {
|
||||
t194(client.device.imsiMd5)
|
||||
|
||||
// defaults true
|
||||
if (ConfigManager.get_loginWithPicSt()) appIdList = longArrayOf(1600000226L)
|
||||
*/
|
||||
t116(client.miscBitMap, client.subSigMap)
|
||||
t100(appId, subAppId, client.appClientVersion, client.mainSigMap or 0xC0)
|
||||
t107(0)
|
||||
|
||||
// t108(byteArrayOf())
|
||||
// ignored: t104()
|
||||
t142(client.apkId)
|
||||
|
||||
// if login with non-number uin
|
||||
// t112()
|
||||
t144(
|
||||
androidId = client.device.androidId,
|
||||
androidDevInfo = client.device.generateDeviceInfoData(),
|
||||
osType = client.device.osType,
|
||||
osVersion = client.device.version.release,
|
||||
networkType = client.networkType,
|
||||
simInfo = client.device.simInfo,
|
||||
unknown = byteArrayOf(),
|
||||
apn = client.device.apn,
|
||||
isGuidFromFileNull = false,
|
||||
isGuidAvailable = true,
|
||||
isGuidChanged = false,
|
||||
guidFlag = guidFlag(GuidSource.FROM_STORAGE, MacOrAndroidIdChangeFlag.NoChange),
|
||||
buildModel = client.device.model,
|
||||
guid = client.device.guid,
|
||||
buildBrand = client.device.brand,
|
||||
tgtgtKey = client.tgtgtKey
|
||||
)
|
||||
|
||||
t145(client.device.guid)
|
||||
t147(appId, client.apkVersionName, client.apkSignatureMd5)
|
||||
|
||||
if (client.miscBitMap and 0x80 != 0) {
|
||||
t166(1)
|
||||
}
|
||||
|
||||
// ignored t16a because array5 is null
|
||||
|
||||
t154(ssoSequenceId)
|
||||
t141(client.device.simInfo, client.networkType, client.device.apn)
|
||||
t8(2052)
|
||||
|
||||
t511(
|
||||
listOf(
|
||||
"tenpay.com",
|
||||
"openmobile.qq.com",
|
||||
"docs.qq.com",
|
||||
"connect.qq.com",
|
||||
"qzone.qq.com",
|
||||
"vip.qq.com",
|
||||
"qun.qq.com",
|
||||
"game.qq.com",
|
||||
"qqweb.qq.com",
|
||||
"office.qq.com",
|
||||
"ti.qq.com",
|
||||
"mail.qq.com",
|
||||
"qzone.com",
|
||||
"mma.qq.com"
|
||||
)
|
||||
)
|
||||
|
||||
// ignored t172 because rollbackSig is null
|
||||
// ignored t185 because loginType is not SMS
|
||||
// ignored t400 because of first login
|
||||
|
||||
t187(client.device.macAddress)
|
||||
t188(client.device.androidId)
|
||||
if (client.device.imsiMd5.isNotEmpty()) {
|
||||
t194(client.device.imsiMd5)
|
||||
}
|
||||
t191()
|
||||
|
||||
/*
|
||||
t201(N = byteArrayOf())*/
|
||||
|
||||
val bssid = client.device.wifiBSSID
|
||||
val ssid = client.device.wifiSSID
|
||||
if (bssid != null && ssid != null) {
|
||||
t202(bssid, ssid)
|
||||
}
|
||||
|
||||
t177()
|
||||
t516()
|
||||
t521()
|
||||
|
||||
t525(buildPacket {
|
||||
t536(buildPacket {
|
||||
//com.tencent.loginsecsdk.ProtocolDet#packExtraData
|
||||
writeByte(1) // const
|
||||
writeByte(0) // data count
|
||||
}.readBytes())
|
||||
})
|
||||
|
||||
// ignored t318 because not logging in by QR
|
||||
}
|
||||
t191()
|
||||
|
||||
/*
|
||||
t201(N = byteArrayOf())*/
|
||||
|
||||
val bssid = client.device.wifiBSSID
|
||||
val ssid = client.device.wifiSSID
|
||||
if (bssid != null && ssid != null) {
|
||||
t202(bssid, ssid)
|
||||
}
|
||||
|
||||
t177()
|
||||
t516()
|
||||
t521()
|
||||
|
||||
t525(buildPacket {
|
||||
t536(buildPacket {
|
||||
//com.tencent.loginsecsdk.ProtocolDet#packExtraData
|
||||
writeByte(1) // const
|
||||
writeByte(0) // data count
|
||||
}.readBytes())
|
||||
})
|
||||
|
||||
// ignored t318 because not logging in by QR
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,20 +172,20 @@ internal object LoginPacket : PacketFactory<LoginPacket.LoginPacketResponse, Log
|
||||
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun PacketId(commandId: Int, subCommandId: Int) = object : PacketId {
|
||||
override val commandId: Int
|
||||
internal fun PacketId(commandId: CommandId, subCommandId: Int) = object : PacketId {
|
||||
override val commandId: CommandId
|
||||
get() = commandId
|
||||
override val subCommandId: Int
|
||||
get() = subCommandId
|
||||
}
|
||||
|
||||
interface PacketId {
|
||||
val commandId: Int // ushort actually
|
||||
internal interface PacketId {
|
||||
val commandId: CommandId // ushort actually
|
||||
val subCommandId: Int // ushort actually
|
||||
}
|
||||
|
||||
object NullPacketId : PacketId {
|
||||
override val commandId: Int
|
||||
internal object NullPacketId : PacketId {
|
||||
override val commandId: CommandId
|
||||
get() = error("uninitialized")
|
||||
override val subCommandId: Int
|
||||
get() = error("uninitialized")
|
||||
|
@ -33,6 +33,8 @@ abstract class DeviceInfo(
|
||||
abstract val wifiSSID: ByteArray?
|
||||
|
||||
abstract val imsiMd5: ByteArray
|
||||
abstract val imei: String
|
||||
abstract val ksid: String
|
||||
|
||||
abstract val ipAddress: String
|
||||
|
||||
|
@ -26,6 +26,8 @@ actual class SystemDeviceInfo actual constructor(context: Context) : DeviceInfo(
|
||||
@UseExperimental(ExperimentalUnsignedTypes::class)
|
||||
override val imsiMd5: ByteArray
|
||||
get() = ubyteArrayOf(0xD4u, 0x1Du, 0x8Cu, 0xD9u, 0x8Fu, 0x00u, 0xB2u, 0x04u, 0xE9u, 0x80u, 0x09u, 0x98u, 0xECu, 0xF8u, 0x42u, 0x7Eu).toByteArray()
|
||||
override val imei: String get() = "858414369211993"
|
||||
override val ksid: String get() = "|454001228437590|A8.2.0.27f6ea96"
|
||||
override val ipAddress: String get() = localIpAddress()
|
||||
override val androidId: ByteArray get() = "QSR1.190920.001".toByteArray()
|
||||
override val apn: ByteArray get() = "wifi".toByteArray()
|
||||
|
Loading…
Reference in New Issue
Block a user