From 369e834557d70b5035aebb738a5116aac8b61af9 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sat, 27 Mar 2021 19:38:56 +0800 Subject: [PATCH] feat: token login. --- client/builders.go | 48 ++++++++++++++++++++++++++++++++++++++++++ client/client.go | 47 +++++++++++++++++++++++++++++++++++++++++ client/decoders.go | 10 ++++++--- client/tlv_decoders.go | 27 +++++++++++++----------- utils/sys.go | 9 ++++++++ 5 files changed, 126 insertions(+), 15 deletions(-) diff --git a/client/builders.go b/client/builders.go index e5e1697a..1b4f47f6 100644 --- a/client/builders.go +++ b/client/builders.go @@ -1,6 +1,7 @@ package client import ( + "crypto/md5" "encoding/hex" "fmt" "math/rand" @@ -352,6 +353,53 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { 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 func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { seq := c.nextSeq() diff --git a/client/client.go b/client/client.go index 695b3081..27ef22af 100644 --- a/client/client.go +++ b/client/client.go @@ -263,6 +263,38 @@ func (c *QQClient) Login() (*LoginResponse, error) { 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) { if c.Online { 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) { 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 { diff --git a/client/decoders.go b/client/decoders.go index 62154a96..c1a9007a 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -53,7 +53,7 @@ func decodeLoginResponse(c *QQClient, _ *incomingPacketInfo, payload []byte) (in if m.Exists(0x403) { c.randSeed = m[0x403] } - c.decodeT119(m[0x119]) + c.decodeT119(m[0x119], SystemDeviceInfo.TgtgtKey) return LoginResponse{ Success: true, }, nil @@ -204,11 +204,15 @@ func decodeExchangeEmpResponse(c *QQClient, _ *incomingPacketInfo, payload []byt m := reader.ReadTlvMap(2) if t != 0 { 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]) } + if cmd == 11 { + h := md5.Sum(c.sigInfo.d2Key) + c.decodeT119(m[0x119], h[:]) + } return nil, nil } diff --git a/client/tlv_decoders.go b/client/tlv_decoders.go index f9a218d5..b1c087a5 100644 --- a/client/tlv_decoders.go +++ b/client/tlv_decoders.go @@ -3,6 +3,7 @@ package client import ( "crypto/md5" "fmt" + "github.com/Mrs4s/MiraiGo/utils" "time" "github.com/Mrs4s/MiraiGo/binary" @@ -19,8 +20,8 @@ func (c *QQClient) decodeT161(data []byte) { } } -func (c *QQClient) decodeT119(data []byte) { - tea := binary.NewTeaCipher(SystemDeviceInfo.TgtgtKey) +func (c *QQClient) decodeT119(data, ek []byte) { + tea := binary.NewTeaCipher(ek) reader := binary.NewReader(tea.Decrypt(data)) reader.ReadBytes(2) m := reader.ReadTlvMap(2) @@ -85,9 +86,9 @@ func (c *QQClient) decodeT119(data []byte) { c.sigInfo = &loginSigInfo{ loginBitmap: 0, - srmToken: m[0x16a], - t133: m[0x133], - encryptedA1: m[0x106], + srmToken: utils.Select(m[0x16a], c.sigInfo.srmToken), + t133: utils.Select(m[0x133], c.sigInfo.t133), + encryptedA1: utils.Select(m[0x106], c.sigInfo.encryptedA1), tgt: m[0x10a], tgtKey: m[0x10d], userStKey: m[0x10e], @@ -96,18 +97,20 @@ func (c *QQClient) decodeT119(data []byte) { sKeyExpiredTime: time.Now().Unix() + 21600, d2: m[0x143], d2Key: m[0x305], - wtSessionTicketKey: m[0x134], + wtSessionTicketKey: utils.Select(m[0x134], c.sigInfo.wtSessionTicketKey), deviceToken: m[0x322], psKeyMap: psKeyMap, pt4TokenMap: pt4TokenMap, } - 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) - if len(decrypted) > 51+16 { - dr := binary.NewReader(decrypted) - dr.ReadBytes(51) - SystemDeviceInfo.TgtgtKey = dr.ReadBytes(16) + 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)) })...)) + decrypted := binary.NewTeaCipher(key[:]).Decrypt(c.sigInfo.encryptedA1) + if len(decrypted) > 51+16 { + dr := binary.NewReader(decrypted) + dr.ReadBytes(51) + SystemDeviceInfo.TgtgtKey = dr.ReadBytes(16) + } } c.Nickname = nick c.Age = age diff --git a/utils/sys.go b/utils/sys.go index 1dd3d6f8..6d383b21 100644 --- a/utils/sys.go +++ b/utils/sys.go @@ -56,3 +56,12 @@ func MultiReadSeeker(r ...io.ReadSeeker) io.ReadSeeker { readers: r, } } + +// Select 如果A为nil 将会返回 B 否则返回A +// 对应 ?? 语法 +func Select(a, b []byte) []byte { + if a == nil { + return b + } + return a +}