1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 19:17:38 +08:00

feat: token login.

This commit is contained in:
Mrs4s 2021-03-27 19:38:56 +08:00
parent ede433b4f6
commit 369e834557
5 changed files with 126 additions and 15 deletions

View File

@ -1,6 +1,7 @@
package client package client
import ( import (
"crypto/md5"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"math/rand" "math/rand"
@ -352,6 +353,53 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
return seq, packet return seq, packet
} }
func (c *QQClient) buildRequestChangeSigPacket() (uint16, []byte) {
seq := c.nextSeq()
req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) {
w.WriteUInt16(11)
w.WriteUInt16(17)
w.Write(tlv.T100(c.version.SSOVersion, 100, c.version.MainSigMap))
w.Write(tlv.T10A(c.sigInfo.tgt))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T108(SystemDeviceInfo.IMEI))
h := md5.Sum(c.sigInfo.d2Key)
w.Write(tlv.T144(
SystemDeviceInfo.AndroidId,
SystemDeviceInfo.GenDeviceInfoData(),
SystemDeviceInfo.OSType,
SystemDeviceInfo.Version.Release,
SystemDeviceInfo.SimInfo,
SystemDeviceInfo.APN,
false, true, false, tlv.GuidFlag(),
SystemDeviceInfo.Model,
SystemDeviceInfo.Guid,
SystemDeviceInfo.Brand,
h[:],
))
w.Write(tlv.T143(c.sigInfo.d2))
w.Write(tlv.T142(c.version.ApkId))
w.Write(tlv.T154(seq))
w.Write(tlv.T18(16, uint32(c.Uin)))
w.Write(tlv.T141(SystemDeviceInfo.SimInfo, SystemDeviceInfo.APN))
w.Write(tlv.T8(2052))
w.Write(tlv.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign))
w.Write(tlv.T177(c.version.BuildTime, c.version.SdkVersion))
w.Write(tlv.T187(SystemDeviceInfo.MacAddress))
w.Write(tlv.T188(SystemDeviceInfo.AndroidId))
w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5))
w.Write(tlv.T511([]string{
"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",
}))
//w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
})
sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.exchange_emp", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{})
return seq, packet
}
// StatSvc.register // StatSvc.register
func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()

View File

@ -263,6 +263,38 @@ func (c *QQClient) Login() (*LoginResponse, error) {
return &l, nil return &l, nil
} }
func (c *QQClient) TokenLogin(token []byte) error {
if c.Online {
return ErrAlreadyOnline
}
if c.Conn == nil {
err := c.connect()
if err != nil {
return err
}
go c.netLoop()
}
{
r := binary.NewReader(token)
c.Uin = r.ReadInt64()
c.sigInfo.d2 = r.ReadBytesShort()
c.sigInfo.d2Key = r.ReadBytesShort()
c.sigInfo.tgt = r.ReadBytesShort()
c.sigInfo.srmToken = r.ReadBytesShort()
c.sigInfo.t133 = r.ReadBytesShort()
c.sigInfo.encryptedA1 = r.ReadBytesShort()
c.sigInfo.wtSessionTicketKey = r.ReadBytesShort()
c.OutGoingPacketSessionId = r.ReadBytesShort()
SystemDeviceInfo.TgtgtKey = r.ReadBytesShort()
}
_, err := c.sendAndWait(c.buildRequestChangeSigPacket())
if err != nil {
return err
}
c.init()
return nil
}
func (c *QQClient) FetchQRCode() (*QRCodeLoginResponse, error) { func (c *QQClient) FetchQRCode() (*QRCodeLoginResponse, error) {
if c.Online { if c.Online {
return nil, ErrAlreadyOnline return nil, ErrAlreadyOnline
@ -384,6 +416,21 @@ func (c *QQClient) init() {
}) })
} }
func (c *QQClient) GenToken() []byte {
return binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt64(uint64(c.Uin))
w.WriteBytesShort(c.sigInfo.d2)
w.WriteBytesShort(c.sigInfo.d2Key)
w.WriteBytesShort(c.sigInfo.tgt)
w.WriteBytesShort(c.sigInfo.srmToken)
w.WriteBytesShort(c.sigInfo.t133)
w.WriteBytesShort(c.sigInfo.encryptedA1)
w.WriteBytesShort(c.sigInfo.wtSessionTicketKey)
w.WriteBytesShort(c.OutGoingPacketSessionId)
w.WriteBytesShort(SystemDeviceInfo.TgtgtKey)
})
}
func (c *QQClient) GetVipInfo(target int64) (*VipInfo, error) { func (c *QQClient) GetVipInfo(target int64) (*VipInfo, error) {
b, err := utils.HttpGetBytes(fmt.Sprintf("https://h5.vip.qq.com/p/mc/cardv2/other?platform=1&qq=%d&adtag=geren&aid=mvip.pingtai.mobileqq.androidziliaoka.fromqita", target), c.getCookiesWithDomain("h5.vip.qq.com")) b, err := utils.HttpGetBytes(fmt.Sprintf("https://h5.vip.qq.com/p/mc/cardv2/other?platform=1&qq=%d&adtag=geren&aid=mvip.pingtai.mobileqq.androidziliaoka.fromqita", target), c.getCookiesWithDomain("h5.vip.qq.com"))
if err != nil { if err != nil {

View File

@ -53,7 +53,7 @@ func decodeLoginResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (in
if m.Exists(0x403) { if m.Exists(0x403) {
c.randSeed = m[0x403] c.randSeed = m[0x403]
} }
c.decodeT119(m[0x119]) c.decodeT119(m[0x119], SystemDeviceInfo.TgtgtKey)
return LoginResponse{ return LoginResponse{
Success: true, Success: true,
}, nil }, nil
@ -204,11 +204,15 @@ func decodeExchangeEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byt
m := reader.ReadTlvMap(2) m := reader.ReadTlvMap(2)
if t != 0 { if t != 0 {
c.Error("exchange_emp error: %v", t) c.Error("exchange_emp error: %v", t)
return nil, nil return nil, errors.New("exchange_emp failed")
} }
if cmd == 15 { // TODO: 免密登录 if cmd == 15 {
c.decodeT119R(m[0x119]) c.decodeT119R(m[0x119])
} }
if cmd == 11 {
h := md5.Sum(c.sigInfo.d2Key)
c.decodeT119(m[0x119], h[:])
}
return nil, nil return nil, nil
} }

View File

@ -3,6 +3,7 @@ package client
import ( import (
"crypto/md5" "crypto/md5"
"fmt" "fmt"
"github.com/Mrs4s/MiraiGo/utils"
"time" "time"
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
@ -19,8 +20,8 @@ func (c *QQClient) decodeT161(data []byte) {
} }
} }
func (c *QQClient) decodeT119(data []byte) { func (c *QQClient) decodeT119(data, ek []byte) {
tea := binary.NewTeaCipher(SystemDeviceInfo.TgtgtKey) tea := binary.NewTeaCipher(ek)
reader := binary.NewReader(tea.Decrypt(data)) reader := binary.NewReader(tea.Decrypt(data))
reader.ReadBytes(2) reader.ReadBytes(2)
m := reader.ReadTlvMap(2) m := reader.ReadTlvMap(2)
@ -85,9 +86,9 @@ func (c *QQClient) decodeT119(data []byte) {
c.sigInfo = &loginSigInfo{ c.sigInfo = &loginSigInfo{
loginBitmap: 0, loginBitmap: 0,
srmToken: m[0x16a], srmToken: utils.Select(m[0x16a], c.sigInfo.srmToken),
t133: m[0x133], t133: utils.Select(m[0x133], c.sigInfo.t133),
encryptedA1: m[0x106], encryptedA1: utils.Select(m[0x106], c.sigInfo.encryptedA1),
tgt: m[0x10a], tgt: m[0x10a],
tgtKey: m[0x10d], tgtKey: m[0x10d],
userStKey: m[0x10e], userStKey: m[0x10e],
@ -96,12 +97,13 @@ func (c *QQClient) decodeT119(data []byte) {
sKeyExpiredTime: time.Now().Unix() + 21600, sKeyExpiredTime: time.Now().Unix() + 21600,
d2: m[0x143], d2: m[0x143],
d2Key: m[0x305], d2Key: m[0x305],
wtSessionTicketKey: m[0x134], wtSessionTicketKey: utils.Select(m[0x134], c.sigInfo.wtSessionTicketKey),
deviceToken: m[0x322], deviceToken: m[0x322],
psKeyMap: psKeyMap, psKeyMap: psKeyMap,
pt4TokenMap: pt4TokenMap, pt4TokenMap: pt4TokenMap,
} }
if len(c.PasswordMd5[:]) > 0 {
key := md5.Sum(append(append(c.PasswordMd5[:], []byte{0x00, 0x00, 0x00, 0x00}...), binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt32(uint32(c.Uin)) })...)) key := md5.Sum(append(append(c.PasswordMd5[:], []byte{0x00, 0x00, 0x00, 0x00}...), binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt32(uint32(c.Uin)) })...))
decrypted := binary.NewTeaCipher(key[:]).Decrypt(c.sigInfo.encryptedA1) decrypted := binary.NewTeaCipher(key[:]).Decrypt(c.sigInfo.encryptedA1)
if len(decrypted) > 51+16 { if len(decrypted) > 51+16 {
@ -109,6 +111,7 @@ func (c *QQClient) decodeT119(data []byte) {
dr.ReadBytes(51) dr.ReadBytes(51)
SystemDeviceInfo.TgtgtKey = dr.ReadBytes(16) SystemDeviceInfo.TgtgtKey = dr.ReadBytes(16)
} }
}
c.Nickname = nick c.Nickname = nick
c.Age = age c.Age = age
c.Gender = gender c.Gender = gender

View File

@ -56,3 +56,12 @@ func MultiReadSeeker(r ...io.ReadSeeker) io.ReadSeeker {
readers: r, readers: r,
} }
} }
// Select 如果A为nil 将会返回 B 否则返回A
// 对应 ?? 语法
func Select(a, b []byte) []byte {
if a == nil {
return b
}
return a
}