Merge remote-tracking branch 'origin/master'

This commit is contained in:
liujiahua123123 2019-08-18 13:58:51 +08:00
commit 59fbbd5cd9
14 changed files with 300 additions and 42 deletions

View File

@ -508,7 +508,7 @@ license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
country that you have state to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a

View File

@ -15,7 +15,11 @@ import net.mamoe.mirai.network.packet.client.login.ClientPasswordSubmissionPacke
import net.mamoe.mirai.network.packet.client.login.ClientServerRedirectionPacket
import net.mamoe.mirai.network.packet.client.writeHex
import net.mamoe.mirai.network.packet.server.ServerPacket
import net.mamoe.mirai.network.packet.server.ServerTouchResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginFailedResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginResendResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginSucceedResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginVerificationCodeResponsePacket
import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
import net.mamoe.mirai.utils.MiraiLogger
import java.net.DatagramPacket
import java.net.InetSocketAddress
@ -26,37 +30,60 @@ import java.net.InetSocketAddress
* @author Him188moe @ Mirai Project
*/
class Robot(val number: Int, private val password: String) {
private lateinit var channel: Channel
private var channel: Channel? = null
@ExperimentalUnsignedTypes
internal fun onPacketReceived(packet: ServerPacket) {
packet.decode()
if (packet is ServerTouchResponsePacket) {
if (packet.serverIP != null) {//redirection
connect(packet.serverIP!!)
sendPacket(ClientServerRedirectionPacket(
serverIP = packet.serverIP!!,
qq = number
))
} else {//password submission
sendPacket(ClientPasswordSubmissionPacket(
qq = this.number,
password = this.password,
loginTime = packet.loginTime,
loginIP = packet.loginIP,
token0825 = packet.token,
tgtgtKey = packet.tgtgtKey
))
when (packet) {
is ServerTouchResponsePacket -> {
if (packet.serverIP != null) {//redirection
connect(packet.serverIP!!)
sendPacket(ClientServerRedirectionPacket(
serverIP = packet.serverIP!!,
qq = number
))
} else {//password submission
sendPacket(ClientPasswordSubmissionPacket(
qq = this.number,
password = this.password,
loginTime = packet.loginTime,
loginIP = packet.loginIP,
token0825 = packet.token,
tgtgtKey = packet.tgtgtKey
))
}
}
is ServerLoginFailedResponsePacket -> {
channel = null
println("Login failed: " + packet.state.toString())
return
}
is ServerLoginVerificationCodeResponsePacket -> {
}
is ServerLoginSucceedResponsePacket -> {
}
is ServerLoginResendResponsePacket -> {
}
else -> throw IllegalStateException()
}
}
@ExperimentalUnsignedTypes
private fun sendPacket(packet: ClientPacket) {
packet.encode()
packet.writeHex(Protocol.tail);
channel.writeAndFlush(DatagramPacket(packet.toByteArray()))
channel!!.writeAndFlush(DatagramPacket(packet.toByteArray()))
}
companion object {
@ -106,7 +133,7 @@ class Robot(val number: Int, private val password: String) {
})
channel = b.connect().sync().channel();
channel.closeFuture().sync()
channel!!.closeFuture().sync()
} finally {
group.shutdownGracefully().sync()
}

View File

@ -0,0 +1,17 @@
package net.mamoe.mirai.network.packet.client.login
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.client.ClientPacket
/**
* Dispose_0836
*
* @author Him188moe @ Mirai Project
*/
@PacketId("08 36 31 04")
@ExperimentalUnsignedTypes
class ClientLoginResendPacket3104(val tgtgtKey: ByteArray, val token00BA: ByteArray) : ClientPacket() {
override fun encode() {
}
}

View File

@ -17,7 +17,7 @@ import java.net.InetAddress
*/
@PacketId("08 36 31 03")
@ExperimentalUnsignedTypes
class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: ByteArray, private val loginIP: ByteArray, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
@ExperimentalUnsignedTypes
override fun encode() {
this.writeQQ(qq)
@ -39,7 +39,11 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password:
this.writeHex("03 0F");//tag
this.writeShort(hostName.length / 2);//todo check that
this.writeShort(hostName.length);
this.writeBytes(hostName)
this.writeBytes(hostName)//todo 这个对吗?
/*易语言源码: PCName就是HostName
PCName BytesToStr (Ansi转Utf8 (取主机名 ()))
PCName 取文本左边 (PCName, 取文本长度 (PCName) 3)*/
this.writeHex("00 05 00 06 00 02")
this.writeQQ(qq)
this.writeHex("00 06")//tag

View File

@ -1,4 +1,4 @@
package net.mamoe.mirai.network.packet.client.login
package net.mamoe.mirai.network.packet.client.touch
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId

View File

@ -1,4 +1,4 @@
package net.mamoe.mirai.network.packet.client.login
package net.mamoe.mirai.network.packet.client.touch
import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.network.packet.PacketId

View File

@ -1,11 +0,0 @@
package net.mamoe.mirai.network.packet.server
import java.io.DataInputStream
/**
* @author Him188moe @ Mirai Project
*/
class ServerLoginSucceedPacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
override fun decode() {
}
}

View File

@ -1,9 +1,12 @@
package net.mamoe.mirai.network.packet.server
import net.mamoe.mirai.network.packet.Packet
import net.mamoe.mirai.network.packet.client.toHexString
import net.mamoe.mirai.network.packet.server.login.ServerLoginFailedResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginResendResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginSucceedResponsePacket
import net.mamoe.mirai.network.packet.server.login.ServerLoginVerificationCodeResponsePacket
import net.mamoe.mirai.network.packet.server.touch.ServerTouchResponsePacket
import net.mamoe.mirai.util.toHexString
import java.io.DataInputStream
/**
@ -25,13 +28,36 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
return when (idBytes.joinToString("") { it.toString(16) }) {
"08 25 31 01" -> ServerTouchResponsePacket(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, stream)
"08 25 31 02" -> ServerTouchResponsePacket(ServerTouchResponsePacket.Type.TYPE_08_25_31_02, stream)
"08 36 31 03", "08 36 31 04", "08 36 31 05", "08 36 31 06" -> {
when (bytes.size) {
271, 207 -> {
ServerLoginResendResponsePacket(stream)
}
871 -> return ServerLoginVerificationCodeResponsePacket(stream)
}
else -> throw UnsupportedOperationException()
if (bytes.size > 700) {
return ServerLoginSucceedResponsePacket(stream)
}
return ServerLoginFailedResponsePacket(when (bytes.size) {
319 -> ServerLoginFailedResponsePacket.State.WRONG_PASSWORD
135 -> ServerLoginFailedResponsePacket.State.RETYPE_PASSWORD
279 -> ServerLoginFailedResponsePacket.State.BLOCKED
263 -> ServerLoginFailedResponsePacket.State.UNKNOWN_QQ_NUMBER
551, 487 -> ServerLoginFailedResponsePacket.State.DEVICE_LOCK
359 -> ServerLoginFailedResponsePacket.State.TAKEN_BACK
else -> throw IllegalStateException()
}, stream)
}
else -> throw IllegalStateException()
}
}
}
}
fun DataInputStream.skipUntil(byte: Byte) {
while (readByte() != byte);
}
@ -53,8 +79,8 @@ fun DataInputStream.readIP(): String {
for (i in 0..3) {
val byte = readByte();
buff += (byte.toUByte().toString())
if(i !=3)buff+="."
System.out.println(byte.toHexString())
if (i != 3) buff += "."
println(byte.toHexString())
}
return buff
}

View File

@ -0,0 +1,24 @@
package net.mamoe.mirai.network.packet.server.login
import net.mamoe.mirai.network.packet.server.ServerPacket
import java.io.DataInputStream
/**
* @author Him188moe @ Mirai Project
*/
class ServerLoginFailedResponsePacket(val state: State, input: DataInputStream) : ServerPacket(input) {
enum class State {
WRONG_PASSWORD,
// UNKNOWN,//? 要再次发送某数据包
RETYPE_PASSWORD,//similar to [WRONG_PASSWORD]
BLOCKED,//你的帐号存在被盗风险,已进入保护模式
UNKNOWN_QQ_NUMBER,//你输入的帐号不存在
DEVICE_LOCK,//设备锁
TAKEN_BACK,//被回收
// VERIFICATION_CODE,//需要验证码
// SUCCEED,
}
override fun decode() {
}
}

View File

@ -0,0 +1,35 @@
package net.mamoe.mirai.network.packet.server.login
import net.mamoe.mirai.network.packet.PacketId
import net.mamoe.mirai.network.packet.server.ServerPacket
import java.io.DataInputStream
/**
* @author Him188moe @ Mirai Project
*/
@PacketId("08 36 31 03")
class ServerLoginResendResponsePacket(input: DataInputStream, private val flag: Flag) : ServerPacket(input) {
enum class Flag {
`08 36 31 03`,
OTHER,
}
lateinit var _0836_tlv0006_encr: ByteArray;
lateinit var token: ByteArray
lateinit var tgtgtKey: ByteArray
override fun decode() {
_0836_tlv0006_encr = 取文本中间(data, 76, 359)
when (flag) {
Flag.`08 36 31 03` -> {
token = 取文本中间(data, 460, 167)
}
Flag.OTHER -> {
//do nothing in this packet.
//[this.token] will be set in [Robot]
}
}
m_tgtgtKey = 取文本中间(data, 16, 47)
}
}

View File

@ -0,0 +1,100 @@
# ServerLoginResendResponsePacket
## Dispose_0836
data TeaDecrypt (取文本中间 (data, 43, 取文本长度 (data) 45), #shareKey)
data TeaDecrypt (data, m_tgtgtKey)
.如果真 (data ≠ “”)
_0836_tlv0006_encr 取文本中间 (data, 76, 359)
token 选择 (flag “08 36 31 03”, 取文本中间 (data, 460, 167), m_00BaToken) ' token
m_tgtgtKey 取文本中间 (data, 16, 47) ' tgtgtKey
SetTips (“正在获取帐号信息...”, 9)
.如果 (flag “08 36 31 03”)
SendUdp (Construct_0836_686 (“31 04”, 假, token, _0836_tlv0006_encr)) ' 正常发送
.否则
SendUdp (Construct_0836_686 (“31 06”, 假, token, _0836_tlv0006_encr)) ' 第二次发送
.如果结束
.如果真结束
## Construct_0836_686(
.参数 seq, 文本型
.参数 isVerify, 逻辑型, , 是否需要验证码登录
.参数 token, 文本型
.参数 tlv_0006_encr, 文本型, 可空)
fix1 “03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19 ”
fix2 “00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B ”
qd “00 32 00 63 3E 00 63 02 04 03 06 02 00 04 00 52 D9 00 00 00 00 A9 58 3E 6D 6D 49 AA F6 A6 D9 33 0A E7 7E 36 84 03 01 00 00 68 20 15 8B 00 00 01 02 00 00 03 00 07 DF 00 0A 00 0C 00 01 00 04 00 03 00 04 20 5C 00 ” MD5_32 “68 ” ' 修改
_0836key1 “EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA ”
PCName BytesToStr (Ansi转Utf8 (取主机名 ()))
PCName 取文本左边 (PCName, 取文本长度 (PCName) 3)
MD51 删尾空 (StrSplit (取数据摘要 (到字节集 (g_pass))))
MD52 删尾空 (StrSplit (取数据摘要 (HexToBytes (MD51 “ 00 00 00 00 ” g_QQ))))
crc32_code GetRandomKey (16)
crc32_data 取Crc32 (crc32_code)
.如果真 (isVerify)
tlv_0006_encr Get_tlv_0006 ()
.如果真结束
pack.Empty ()
pack.PutTag (“01 12”)
pack.PutLength (“00 38”)
pack.PutValue (m_0825token)
pack.PutTag (“03 0F”)
pack.putDwordLength (GetDataLength (PCName) 2)
pack.putDwordLength (GetDataLength (PCName))
pack.PutValue (PCName)
pack.PutFix (“00 05 00 06 00 02”)
pack.PutQQ ()
pack.PutTag (“00 06”)
pack.PutLength (“00 78”)
pack.PutValue (tlv_0006_encr)
pack.PutKey (fix2)
pack.PutTag (“00 1A”)
pack.PutLength (“00 40”)
pack.PutValue (TeaEncrypt (fix2, m_tgtgtKey))
pack.PutValue (#_0825data0)
pack.PutValue (#_0825date2)
pack.PutQQ ()
pack.PutZero (4)
pack.PutTag (“01 03”)
pack.PutLength (“00 14”)
pack.PutTag (“00 01”)
pack.PutLength (“00 10”)
pack.PutKey (“60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6”)
' ****************
' 多出来的167字节
pack.PutTag (“01 10”)
pack.PutLength (“00 3C”)
pack.PutTag (“00 01”)
pack.PutLength (“00 38”)
pack.PutValue (token)
' ****************
pack.PutTag (“03 12”)
pack.PutLength (“00 05”)
pack.PutValue (“01 00 00 00 01”)
pack.PutTag (“05 08”)
pack.PutLength (“00 05”)
pack.PutValue (“01 00 00 00 00”)
pack.PutTag (“03 13”)
pack.PutLength (“00 19”)
pack.PutByte (“01”)
pack.PutTag (“01 02”)
pack.PutLength (“00 10”)
pack.PutKey (“04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA”) ' 两次0836包相同
pack.PutZero (3)
pack.PutByte (“00”) ' 可能为00,0F,1F
pack.PutTag (“01 02”)
pack.PutLength (“00 62”)
pack.PutWord (“00 01”)
pack.PutKey (“04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48”) ' 两次0836包不同
pack.PutLength (“00 38”)
pack.PutValue (“E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3”)
pack.PutLength (“00 14”)
pack.PutKey (crc32_code)
pack.PutDword (crc32_data)
调试输出 (pack.GetPacket ())
ret #head “37 13 08 36 ” seq “ ” g_QQ fix1 #publicKey “ 00 00 00 10 ” _0836key1 TeaEncrypt (pack.GetPacket (), #shareKey) #tail
返回 (ret)

View File

@ -0,0 +1,15 @@
package net.mamoe.mirai.network.packet.server.login
import net.mamoe.mirai.network.packet.server.ServerPacket
import java.io.DataInputStream
/**
* @author Him188moe @ Mirai Project
*/
class ServerLoginSucceedResponsePacket(input: DataInputStream) : ServerPacket(input) {
override fun decode() {
TODO()
}
}

View File

@ -0,0 +1,19 @@
package net.mamoe.mirai.network.packet.server.login
import net.mamoe.mirai.network.packet.server.ServerPacket
import java.io.DataInputStream
/**
* @author Him188moe @ Mirai Project
*/
class ServerLoginVerificationCodeResponsePacket(input: DataInputStream) : ServerPacket(input) {
private var verifyCodeLength: Int = 0
private lateinit var verifyCode: String
private lateinit var token00BA: ByteArray
override fun decode() {
TODO()
}
}

View File

@ -1,5 +1,7 @@
package net.mamoe.mirai.network.packet.server
package net.mamoe.mirai.network.packet.server.touch
import net.mamoe.mirai.network.packet.server.ServerPacket
import net.mamoe.mirai.network.packet.server.readIP
import net.mamoe.mirai.util.getRandomKey
import java.io.DataInputStream