mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-24 06:10:09 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
59fbbd5cd9
2
LICENSE
2
LICENSE
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -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)
|
@ -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()
|
||||
}
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user