From 8a968656c116916707f34bdf531e0ef2ead08981 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sat, 3 Oct 2020 13:19:02 +0800 Subject: [PATCH 01/14] fix decode error. --- client/builders.go | 2 +- client/decoders.go | 2 +- client/tlv_decoders.go | 29 +++++++++++++++++------------ protocol/tlv/t144.go | 8 +++++--- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/client/builders.go b/client/builders.go index de540f1a..b80e1099 100644 --- a/client/builders.go +++ b/client/builders.go @@ -46,7 +46,7 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { w.Write(tlv.T107(0)) w.Write(tlv.T142("com.tencent.mobileqq")) w.Write(tlv.T144( - SystemDeviceInfo.AndroidId, + []byte(SystemDeviceInfo.IMEI), SystemDeviceInfo.GenDeviceInfoData(), SystemDeviceInfo.OSType, SystemDeviceInfo.Version.Release, diff --git a/client/decoders.go b/client/decoders.go index c01e585a..48d9c7d0 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -139,7 +139,7 @@ func decodeExchangeEmpResponse(c *QQClient, _ uint16, payload []byte) (interface return nil, nil } if cmd == 15 { // TODO: 免密登录 - c.decodeT119(m[0x119]) + c.decodeT119R(m[0x119]) } return nil, nil } diff --git a/client/tlv_decoders.go b/client/tlv_decoders.go index bf548e1d..174ea06d 100644 --- a/client/tlv_decoders.go +++ b/client/tlv_decoders.go @@ -23,18 +23,6 @@ func (c *QQClient) decodeT119(data []byte) { reader := binary.NewReader(tea.Decrypt(data)) reader.ReadBytes(2) m := reader.ReadTlvMap(2) - if len(c.sigInfo.sKey) > 0 { // refresh - if t120, ok := m[0x120]; ok { - c.sigInfo.sKey = t120 - c.sigInfo.sKeyExpiredTime = time.Now().Unix() + 43200 // 86400 / 2 - c.Debug("skey updated: %v", c.sigInfo.sKey) - } - if t11a, ok := m[0x11a]; ok { - c.Nickname, c.Age, c.Gender = readT11A(t11a) - c.Debug("account info updated: " + c.Nickname) - } - return - } if t130, ok := m[0x130]; ok { c.decodeT130(t130) } @@ -117,6 +105,23 @@ func (c *QQClient) decodeT119(data []byte) { c.Gender = gender } +// wtlogin.exchange_emp +func (c *QQClient) decodeT119R(data []byte) { + tea := binary.NewTeaCipher(SystemDeviceInfo.TgtgtKey) + reader := binary.NewReader(tea.Decrypt(data)) + reader.ReadBytes(2) + m := reader.ReadTlvMap(2) + if t120, ok := m[0x120]; ok { + c.sigInfo.sKey = t120 + c.sigInfo.sKeyExpiredTime = time.Now().Unix() + 43200 // 86400 / 2 + c.Debug("skey updated: %v", c.sigInfo.sKey) + } + if t11a, ok := m[0x11a]; ok { + c.Nickname, c.Age, c.Gender = readT11A(t11a) + c.Debug("account info updated: " + c.Nickname) + } +} + func (c *QQClient) decodeT130(data []byte) { reader := binary.NewReader(data) reader.ReadBytes(2) diff --git a/protocol/tlv/t144.go b/protocol/tlv/t144.go index 61bcb02d..a7c86c21 100644 --- a/protocol/tlv/t144.go +++ b/protocol/tlv/t144.go @@ -1,9 +1,11 @@ package tlv -import "github.com/Mrs4s/MiraiGo/binary" +import ( + "github.com/Mrs4s/MiraiGo/binary" +) func T144( - androidId, devInfo, osType, osVersion, simInfo, apn []byte, + imei, devInfo, osType, osVersion, simInfo, apn []byte, isGuidFromFileNull, isGuidAvailable, isGuidChanged bool, guidFlag uint32, buildModel, guid, buildBrand, tgtgtKey []byte, @@ -13,7 +15,7 @@ func T144( w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) { w.EncryptAndWrite(tgtgtKey, binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(5) - w.Write(T109(androidId)) + w.Write(T109(imei)) w.Write(T52D(devInfo)) w.Write(T124(osType, osVersion, simInfo, apn)) w.Write(T128(isGuidFromFileNull, isGuidAvailable, isGuidChanged, guidFlag, buildModel, guid, buildBrand)) From 6da8636424fc3e6ebb5a6d186e3ee5406d46735f Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 4 Oct 2020 12:52:22 +0800 Subject: [PATCH 02/14] add: MemberCardUpdatedEvent. --- client/entities.go | 6 ++++++ client/events.go | 16 ++++++++++++++++ client/global.go | 15 +++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/client/entities.go b/client/entities.go index dac40505..dd1bbb98 100644 --- a/client/entities.go +++ b/client/entities.go @@ -119,6 +119,12 @@ type ( Member *GroupMemberInfo } + MemberCardUpdatedEvent struct { + Group *GroupInfo + OldCard string + Member *GroupMemberInfo + } + IGroupNotifyEvent interface { From() int64 Content() string diff --git a/client/events.go b/client/events.go index 38ad020c..4de6607a 100644 --- a/client/events.go +++ b/client/events.go @@ -17,6 +17,7 @@ type eventHandlers struct { leaveGroupHandlers []func(*QQClient, *GroupLeaveEvent) memberJoinedHandlers []func(*QQClient, *MemberJoinGroupEvent) memberLeavedHandlers []func(*QQClient, *MemberLeaveGroupEvent) + memberCardUpdatedHandlers []func(*QQClient, *MemberCardUpdatedEvent) permissionChangedHandlers []func(*QQClient, *MemberPermissionChangedEvent) groupInvitedHandlers []func(*QQClient, *GroupInvitedRequest) joinRequestHandlers []func(*QQClient, *UserJoinGroupRequest) @@ -69,6 +70,10 @@ func (c *QQClient) OnGroupMemberLeaved(f func(*QQClient, *MemberLeaveGroupEvent) c.eventHandlers.memberLeavedHandlers = append(c.eventHandlers.memberLeavedHandlers, f) } +func (c *QQClient) OnGroupMemberCardUpdated(f func(*QQClient, *MemberCardUpdatedEvent)) { + c.eventHandlers.memberCardUpdatedHandlers = append(c.eventHandlers.memberCardUpdatedHandlers, f) +} + func (c *QQClient) OnGroupMemberPermissionChanged(f func(*QQClient, *MemberPermissionChangedEvent)) { c.eventHandlers.permissionChangedHandlers = append(c.eventHandlers.permissionChangedHandlers, f) } @@ -237,6 +242,17 @@ func (c *QQClient) dispatchMemberLeaveEvent(e *MemberLeaveGroupEvent) { } } +func (c *QQClient) dispatchMemberCardUpdatedEvent(e *MemberCardUpdatedEvent) { + if e == nil { + return + } + for _, f := range c.eventHandlers.memberCardUpdatedHandlers { + cover(func() { + f(c, e) + }) + } +} + func (c *QQClient) dispatchPermissionChanged(e *MemberPermissionChangedEvent) { if e == nil { return diff --git a/client/global.go b/client/global.go index c474d90e..e251e365 100644 --- a/client/global.go +++ b/client/global.go @@ -311,6 +311,21 @@ func (c *QQClient) parseGroupMessage(m *msg.Message) *message.GroupMessage { Member: info, }) } + if m.Head.GroupInfo != nil && m.Head.GroupInfo.GroupCard != "" && mem.CardName != m.Head.GroupInfo.GroupCard { + old := mem.CardName + if mem.Nickname == m.Head.GroupInfo.GroupCard { + mem.CardName = "" + } else { + mem.CardName = m.Head.GroupInfo.GroupCard + } + if old != mem.CardName { + go c.dispatchMemberCardUpdatedEvent(&MemberCardUpdatedEvent{ + Group: group, + OldCard: old, + Member: mem, + }) + } + } sender = &message.Sender{ Uin: mem.Uin, Nickname: mem.Nickname, From 43db052ad6e4e483aaf449402c9800a9190b9aaf Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Sun, 4 Oct 2020 13:37:10 +0800 Subject: [PATCH 03/14] fix typo. --- protocol/packets/builders.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/packets/builders.go b/protocol/packets/builders.go index 0ddacda3..3e4c8e36 100644 --- a/protocol/packets/builders.go +++ b/protocol/packets/builders.go @@ -24,11 +24,11 @@ func BuildLoginPacket(uin int64, bodyType byte, key, body, extraData []byte) []b return w.Bytes() } -func BuildUniPacket(uin int64, seq uint16, commandName string, bodyType byte, sessionId, extraData, key, body []byte) []byte { +func BuildUniPacket(uin int64, seq uint16, commandName string, encryptType byte, sessionId, extraData, key, body []byte) []byte { w := binary.NewWriter() w.WriteIntLvPacket(4, func(w *binary.Writer) { w.WriteUInt32(0x0B) - w.WriteByte(bodyType) + w.WriteByte(encryptType) w.WriteUInt32(uint32(seq)) w.WriteByte(0) w.WriteString(strconv.FormatInt(uin, 10)) From 61f9b7412e3822531bd9638eea6c9b306327a7b1 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Mon, 5 Oct 2020 23:34:11 +0800 Subject: [PATCH 04/14] update protocol version & fix protocol error & support sms verify. --- client/builders.go | 76 +++++++++++++++++++++++++++++++++----------- client/client.go | 66 +++++++++++++++++++++++++++----------- client/decoders.go | 38 +++++++++++++++++++--- client/entities.go | 19 +++++++---- client/global.go | 58 +++++++++++++++++++++++++++++++++ protocol/tlv/t100.go | 4 +-- protocol/tlv/t106.go | 4 +-- protocol/tlv/t174.go | 10 ++++++ protocol/tlv/t177.go | 6 ++-- protocol/tlv/t17a.go | 12 +++++++ protocol/tlv/t17c.go | 12 +++++++ protocol/tlv/t197.go | 10 ++++++ protocol/tlv/t198.go | 10 ++++++ 13 files changed, 269 insertions(+), 56 deletions(-) create mode 100644 protocol/tlv/t174.go create mode 100644 protocol/tlv/t17a.go create mode 100644 protocol/tlv/t17c.go create mode 100644 protocol/tlv/t197.go create mode 100644 protocol/tlv/t198.go diff --git a/client/builders.go b/client/builders.go index 210e6f84..0896ff9b 100644 --- a/client/builders.go +++ b/client/builders.go @@ -40,11 +40,11 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { w.Write(tlv.T18(16, uint32(c.Uin))) w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress)) - w.Write(tlv.T106(uint32(c.Uin), 0, uint32(SystemDeviceInfo.Protocol), c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 0)) - w.Write(tlv.T116(184024956, 0x10400)) - w.Write(tlv.T100(uint32(SystemDeviceInfo.Protocol), 34869472)) + w.Write(tlv.T106(uint32(c.Uin), 0, c.version.AppId, c.version.SSOVersion, c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 0)) + w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) + w.Write(tlv.T100(c.version.SSOVersion, c.version.AppId, c.version.MainSigMap)) w.Write(tlv.T107(0)) - w.Write(tlv.T142("com.tencent.mobileqq")) + w.Write(tlv.T142(c.version.ApkId)) w.Write(tlv.T144( []byte(SystemDeviceInfo.IMEI), SystemDeviceInfo.GenDeviceInfoData(), @@ -60,7 +60,7 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { )) w.Write(tlv.T145(SystemDeviceInfo.Guid)) - w.Write(tlv.T147(16, []byte("8.2.7"), []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D})) + w.Write(tlv.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign)) /* if (miscBitMap & 0x80) != 0{ w.Write(tlv.T166(1)) @@ -84,12 +84,12 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { if len(SystemDeviceInfo.WifiBSSID) != 0 && len(SystemDeviceInfo.WifiSSID) != 0 { w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID)) } - w.Write(tlv.T177()) + w.Write(tlv.T177(c.version.BuildTime, c.version.SdkVersion)) w.Write(tlv.T516()) w.Write(tlv.T521()) w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00}))) }) - sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{}) return seq, packet } @@ -102,11 +102,11 @@ func (c *QQClient) buildDeviceLockLoginPacket(t402 []byte) (uint16, []byte) { w.Write(tlv.T8(2052)) w.Write(tlv.T104(c.t104)) - w.Write(tlv.T116(150470524, 66560)) + w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) h := md5.Sum(append(append(SystemDeviceInfo.Guid, []byte("stMNokHgxZUGhsYp")...), t402...)) w.Write(tlv.T401(h[:])) }) - sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{}) return seq, packet } @@ -122,7 +122,45 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt w.Write(tlv.T104(c.t104)) w.Write(tlv.T116(150470524, 66560)) }) - sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) + packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{}) + return seq, packet +} + +func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { + seq := c.nextSeq() + req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { + w.WriteUInt16(8) + w.WriteUInt16(6) + + w.Write(tlv.T8(2052)) + w.Write(tlv.T104(c.t104)) + w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) + w.Write(tlv.T174(c.t174)) + w.Write(tlv.T17A(9)) + w.Write(tlv.T197()) + }) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) + packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{}) + return seq, packet +} + +func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { + seq := c.nextSeq() + req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { + w.WriteUInt16(7) + w.WriteUInt16(7) + + w.Write(tlv.T8(2052)) + w.Write(tlv.T104(c.t104)) + w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) + w.Write(tlv.T174(c.t174)) + w.Write(tlv.T17C(code)) + h := md5.Sum(append(append(SystemDeviceInfo.Guid, []byte("12 34567890123456")...), c.t402...)) + w.Write(tlv.T401(h[:])) + w.Write(tlv.T198()) + }) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "wtlogin.login", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, req, c.ksid) packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, []byte{}) return seq, packet } @@ -135,9 +173,9 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { w.Write(tlv.T18(16, uint32(c.Uin))) w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress)) - w.Write(tlv.T106(uint32(c.Uin), 0, uint32(SystemDeviceInfo.Protocol), c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 1)) - w.Write(tlv.T116(150470524, 66560)) - w.Write(tlv.T100(2, 34869472)) + w.Write(tlv.T106(uint32(c.Uin), 0, c.version.AppId, c.version.SSOVersion, c.PasswordMd5, true, SystemDeviceInfo.Guid, SystemDeviceInfo.TgtgtKey, 1)) + w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) + w.Write(tlv.T100(c.version.SSOVersion, 2, c.version.MainSigMap)) w.Write(tlv.T107(0)) w.Write(tlv.T144( SystemDeviceInfo.AndroidId, @@ -152,7 +190,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { SystemDeviceInfo.Brand, SystemDeviceInfo.TgtgtKey, )) - w.Write(tlv.T142("com.tencent.mobileqq")) + w.Write(tlv.T142(c.version.ApkId)) w.Write(tlv.T145(SystemDeviceInfo.Guid)) w.Write(tlv.T16A(c.sigInfo.srmToken)) w.Write(tlv.T154(seq)) @@ -163,8 +201,8 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { "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.T147(16, []byte("8.2.7"), []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D})) - w.Write(tlv.T177()) + 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)) @@ -218,7 +256,7 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) { Context: make(map[string]string), Status: make(map[string]string), } - sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "StatSvc.register", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, pkt.ToBytes(), c.ksid) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "StatSvc.register", SystemDeviceInfo.IMEI, c.sigInfo.tgt, c.OutGoingPacketSessionId, pkt.ToBytes(), c.ksid) packet := packets.BuildLoginPacket(c.Uin, 1, c.sigInfo.d2Key, sso, c.sigInfo.d2) return seq, packet } @@ -691,7 +729,7 @@ func (c *QQClient) buildImageUploadPacket(data, updKey []byte, commandId int32, } return c.nextGroupDataTransSeq() }(), - Appid: int32(SystemDeviceInfo.Protocol), + Appid: int32(c.version.AppId), Dataflag: 4096, CommandId: commandId, LocaleId: 2052, @@ -1081,7 +1119,7 @@ func (c *QQClient) buildGroupAdminSetPacket(groupCode, member int64, flag bool) func (c *QQClient) buildGroupInfoRequestPacket(groupCode int64) (uint16, []byte) { seq := c.nextSeq() body := &oidb.D88DReqBody{ - AppId: proto.Uint32(uint32(SystemDeviceInfo.Protocol)), + AppId: proto.Uint32(c.version.AppId), ReqGroupInfo: []*oidb.ReqGroupInfo{ { GroupCode: proto.Uint64(uint64(groupCode)), diff --git a/client/client.go b/client/client.go index 3f6f4094..adc1d8bb 100644 --- a/client/client.go +++ b/client/client.go @@ -50,12 +50,15 @@ type QQClient struct { servers []*net.TCPAddr currServerIndex int retryTimes int + version *versionInfo syncCookie []byte pubAccountCookie []byte msgCtrlBuf []byte ksid []byte t104 []byte + t174 []byte + t402 []byte // only for sms t150 []byte t149 []byte t528 []byte @@ -159,10 +162,11 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { groupSeq: int32(rand.Intn(20000)), friendSeq: 22911, highwayApplyUpSeq: 77918, - ksid: []byte("|454001228437590|A8.2.7.27f6ea96"), + ksid: []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", SystemDeviceInfo.IMEI)), eventHandlers: &eventHandlers{}, msgSvcCache: utils.NewCache(time.Second * 15), transCache: utils.NewCache(time.Second * 15), + version: genVersionInfo(SystemDeviceInfo.Protocol), servers: []*net.TCPAddr{ // default servers {IP: net.IP{42, 81, 169, 46}, Port: 8080}, {IP: net.IP{42, 81, 172, 81}, Port: 80}, @@ -212,6 +216,47 @@ func (c *QQClient) Login() (*LoginResponse, error) { return &l, nil } +// SubmitCaptcha send captcha to server +func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, error) { + seq, packet := c.buildCaptchaPacket(result, sign) + rsp, err := c.sendAndWait(seq, packet) + if err != nil { + return nil, err + } + l := rsp.(LoginResponse) + if l.Success { + c.registerClient() + if !c.heartbeatEnabled { + c.startHeartbeat() + } + } + return &l, nil +} + +func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { + rsp, err := c.sendAndWait(c.buildSMSCodeSubmitPacket(code)) + if err != nil { + return nil, err + } + l := rsp.(LoginResponse) + if l.Success { + c.registerClient() + if !c.heartbeatEnabled { + c.startHeartbeat() + } + } + return &l, nil +} + +func (c *QQClient) RequestSMS() bool { + rsp, err := c.sendAndWait(c.buildSMSRequestPacket()) + if err != nil { + c.Error("request sms error: %v", err) + return false + } + return rsp.(LoginResponse).Error == SMSNeededError +} + 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 { @@ -283,23 +328,6 @@ func (c *QQClient) GetSummaryInfo(target int64) (*SummaryCardInfo, error) { return rsp.(*SummaryCardInfo), nil } -// SubmitCaptcha send captcha to server -func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, error) { - seq, packet := c.buildCaptchaPacket(result, sign) - rsp, err := c.sendAndWait(seq, packet) - if err != nil { - return nil, err - } - l := rsp.(LoginResponse) - if l.Success { - c.registerClient() - if !c.heartbeatEnabled { - c.startHeartbeat() - } - } - return &l, nil -} - // ReloadFriendList refresh QQClient.FriendList field via GetFriendList() func (c *QQClient) ReloadFriendList() error { rsp, err := c.GetFriendList() @@ -1118,7 +1146,7 @@ func (c *QQClient) startHeartbeat() { func (c *QQClient) doHeartbeat() { if c.Online { seq := c.nextSeq() - sso := packets.BuildSsoPacket(seq, uint32(SystemDeviceInfo.Protocol), "Heartbeat.Alive", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, []byte{}, c.ksid) + sso := packets.BuildSsoPacket(seq, c.version.AppId, "Heartbeat.Alive", SystemDeviceInfo.IMEI, []byte{}, c.OutGoingPacketSessionId, []byte{}, c.ksid) packet := packets.BuildLoginPacket(c.Uin, 0, []byte{}, sso, []byte{}) _, err := c.sendAndWait(seq, packet) if err != nil { diff --git a/client/decoders.go b/client/decoders.go index 48d9c7d0..024e5611 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -80,11 +80,41 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er } // need captcha if t == 160 { + + if t174, ok := m[0x174]; ok { // 短信验证 + c.t104 = m[0x104] + c.t174 = t174 + c.t402 = m[0x402] + return LoginResponse{ + Success: false, + Error: SMSNeededError, + SMSPhone: string(m[0x178][4:]), + ErrorMessage: string(m[0x17e]), + }, nil + } + + if _, ok := m[0x17b]; ok { // 二次验证 + c.t104 = m[0x104] + return LoginResponse{ + Success: false, + Error: SMSNeededError, + }, nil + } + + if t204, ok := m[0x204]; ok { // 扫码验证 + return LoginResponse{ + Success: false, + Error: UnsafeDeviceError, + VerifyUrl: string(t204), + ErrorMessage: "", + }, nil + } + + } + + if t == 162 { return LoginResponse{ - Success: false, - Error: UnsafeDeviceError, - VerifyUrl: string(m[0x204]), - ErrorMessage: "", + Error: TooManySMSRequestError, }, nil } diff --git a/client/entities.go b/client/entities.go index dd1bbb98..1ba97af2 100644 --- a/client/entities.go +++ b/client/entities.go @@ -30,6 +30,9 @@ type ( // Unsafe device VerifyUrl string + // SMS needed + SMSPhone string + // other error ErrorMessage string } @@ -246,18 +249,20 @@ type ( ) const ( - NeedCaptcha LoginError = 1 - OtherLoginError LoginError = 3 - UnsafeDeviceError LoginError = 4 - UnknownLoginError LoginError = -1 + NeedCaptcha LoginError = 1 + OtherLoginError LoginError = 3 + UnsafeDeviceError LoginError = 4 + SMSNeededError LoginError = 5 + TooManySMSRequestError LoginError = 6 + UnknownLoginError LoginError = -1 Owner MemberPermission = iota Administrator Member - AndroidPhone ClientProtocol = 537062845 - AndroidPad ClientProtocol = 537062409 - AndroidWatch ClientProtocol = 537061176 + AndroidPhone ClientProtocol = 1 + AndroidPad ClientProtocol = 2 + AndroidWatch ClientProtocol = 3 ) func (g *GroupInfo) UpdateName(newName string) { diff --git a/client/global.go b/client/global.go index e251e365..0ebb0818 100644 --- a/client/global.go +++ b/client/global.go @@ -68,6 +68,19 @@ type groupMessageBuilder struct { MessageSlices []*msg.Message } +type versionInfo struct { + ApkId string + AppId uint32 + SortVersionName string + BuildTime uint32 + ApkSign []byte + SdkVersion string + SSOVersion uint32 + MiscBitmap uint32 + SubSigmap uint32 + MainSigMap uint32 +} + // default var SystemDeviceInfo = &DeviceInfo{ Display: []byte("MIRAI.123456.001"), @@ -127,6 +140,51 @@ func GenRandomDevice() { SystemDeviceInfo.GenNewTgtgtKey() } +func genVersionInfo(p ClientProtocol) *versionInfo { + switch p { + case AndroidPhone: // Dumped from mirai by qq android v8.2.7 + return &versionInfo{ + ApkId: "com.tencent.mobileqq", + AppId: 537062845, + SortVersionName: "8.2.7", + BuildTime: 1571193922, + ApkSign: []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D}, + SdkVersion: "6.0.0.2413", + SSOVersion: 5, + MiscBitmap: 184024956, + SubSigmap: 0x10400, + MainSigMap: 34869472, + } + case AndroidWatch: + return &versionInfo{ + ApkId: "com.tencent.mobileqq", + AppId: 537061176, + SortVersionName: "8.2.7", + BuildTime: 1571193922, + ApkSign: []byte{0xA6, 0xB7, 0x45, 0xBF, 0x24, 0xA2, 0xC2, 0x77, 0x52, 0x77, 0x16, 0xF6, 0xF3, 0x6E, 0xB6, 0x8D}, + SdkVersion: "6.0.0.2413", + SSOVersion: 5, + MiscBitmap: 184024956, + SubSigmap: 0x10400, + MainSigMap: 34869472, + } + case AndroidPad: // Dumped by qq-hd v5.8.9 + return &versionInfo{ + ApkId: "com.tencent.minihd.qq", + AppId: 537065549, + SortVersionName: "5.8.9", + BuildTime: 1595836208, + ApkSign: []byte{170, 57, 120, 244, 31, 217, 111, 249, 145, 74, 102, 158, 24, 100, 116, 199}, + SdkVersion: "6.0.0.2433", + SSOVersion: 12, + MiscBitmap: 150470524, + SubSigmap: 66560, + MainSigMap: 1970400, + } + } + return nil +} + func (info *DeviceInfo) ToJson() []byte { f := &DeviceInfoFile{ Display: string(info.Display), diff --git a/protocol/tlv/t100.go b/protocol/tlv/t100.go index eaca527c..4e9b0cb0 100644 --- a/protocol/tlv/t100.go +++ b/protocol/tlv/t100.go @@ -4,12 +4,12 @@ import ( "github.com/Mrs4s/MiraiGo/binary" ) -func T100(protocol, mainSigMap uint32) []byte { +func T100(ssoVersion, protocol, mainSigMap uint32) []byte { return binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(0x100) w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(1) - w.WriteUInt32(5) + w.WriteUInt32(ssoVersion) w.WriteUInt32(16) w.WriteUInt32(protocol) w.WriteUInt32(0) // App client version diff --git a/protocol/tlv/t106.go b/protocol/tlv/t106.go index 1407224e..7e7b2b2b 100644 --- a/protocol/tlv/t106.go +++ b/protocol/tlv/t106.go @@ -8,13 +8,13 @@ import ( "time" ) -func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte { +func T106(uin, salt, protocol, ssoVer uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte { return binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(0x106) body := binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(4) w.WriteUInt32(rand.Uint32()) - w.WriteUInt32(5) + w.WriteUInt32(ssoVer) w.WriteUInt32(16) // appId w.WriteUInt32(0) // app client version if uin == 0 { diff --git a/protocol/tlv/t174.go b/protocol/tlv/t174.go new file mode 100644 index 00000000..67e88a21 --- /dev/null +++ b/protocol/tlv/t174.go @@ -0,0 +1,10 @@ +package tlv + +import "github.com/Mrs4s/MiraiGo/binary" + +func T174(data []byte) []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt16(0x174) + w.WriteTlv(data) + }) +} diff --git a/protocol/tlv/t177.go b/protocol/tlv/t177.go index e76bbfc0..d7e8e701 100644 --- a/protocol/tlv/t177.go +++ b/protocol/tlv/t177.go @@ -2,13 +2,13 @@ package tlv import "github.com/Mrs4s/MiraiGo/binary" -func T177() []byte { +func T177(buildTime uint32, sdkVersion string) []byte { return binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(0x177) w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) { w.WriteByte(0x01) - w.WriteUInt32(1571193922) - w.WriteTlv([]byte("6.0.0.2413")) + w.WriteUInt32(buildTime) + w.WriteTlv([]byte(sdkVersion)) })) }) } diff --git a/protocol/tlv/t17a.go b/protocol/tlv/t17a.go new file mode 100644 index 00000000..e881fd02 --- /dev/null +++ b/protocol/tlv/t17a.go @@ -0,0 +1,12 @@ +package tlv + +import "github.com/Mrs4s/MiraiGo/binary" + +func T17A(value int32) []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt16(0x17a) + w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt32(uint32(value)) + })) + }) +} diff --git a/protocol/tlv/t17c.go b/protocol/tlv/t17c.go new file mode 100644 index 00000000..eeec297f --- /dev/null +++ b/protocol/tlv/t17c.go @@ -0,0 +1,12 @@ +package tlv + +import "github.com/Mrs4s/MiraiGo/binary" + +func T17C(code string) []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt16(0x17c) + w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) { + w.WriteStringShort(code) + })) + }) +} diff --git a/protocol/tlv/t197.go b/protocol/tlv/t197.go new file mode 100644 index 00000000..2babb615 --- /dev/null +++ b/protocol/tlv/t197.go @@ -0,0 +1,10 @@ +package tlv + +import "github.com/Mrs4s/MiraiGo/binary" + +func T197() []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt16(0x197) + w.WriteTlv([]byte{0}) + }) +} diff --git a/protocol/tlv/t198.go b/protocol/tlv/t198.go new file mode 100644 index 00000000..0e36f681 --- /dev/null +++ b/protocol/tlv/t198.go @@ -0,0 +1,10 @@ +package tlv + +import "github.com/Mrs4s/MiraiGo/binary" + +func T198() []byte { + return binary.NewWriterF(func(w *binary.Writer) { + w.WriteUInt16(0x198) + w.WriteTlv([]byte{0}) + }) +} From 3cd432faceb9cfa8fb2236604da5d4795ee59214 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Mon, 5 Oct 2020 23:37:38 +0800 Subject: [PATCH 05/14] fix typo. --- client/global.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/global.go b/client/global.go index 0ebb0818..70ab161f 100644 --- a/client/global.go +++ b/client/global.go @@ -142,7 +142,7 @@ func GenRandomDevice() { func genVersionInfo(p ClientProtocol) *versionInfo { switch p { - case AndroidPhone: // Dumped from mirai by qq android v8.2.7 + case AndroidPhone: // Dumped by mirai from qq android v8.2.7 return &versionInfo{ ApkId: "com.tencent.mobileqq", AppId: 537062845, @@ -168,7 +168,7 @@ func genVersionInfo(p ClientProtocol) *versionInfo { SubSigmap: 0x10400, MainSigMap: 34869472, } - case AndroidPad: // Dumped by qq-hd v5.8.9 + case AndroidPad: // Dumped from qq-hd v5.8.9 return &versionInfo{ ApkId: "com.tencent.minihd.qq", AppId: 537065549, From cc0279f22e20f3dc92b0fc590183e36971494d14 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Mon, 5 Oct 2020 23:43:06 +0800 Subject: [PATCH 06/14] support: multi verify. --- client/decoders.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/decoders.go b/client/decoders.go index 024e5611..cc9c9b96 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -85,6 +85,15 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er c.t104 = m[0x104] c.t174 = t174 c.t402 = m[0x402] + if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ? + return LoginResponse{ + Success: false, + Error: SMSNeededError | UnsafeDeviceError, + VerifyUrl: string(t204), + SMSPhone: string(m[0x178][4:]), + ErrorMessage: string(m[0x17e]), + }, nil + } return LoginResponse{ Success: false, Error: SMSNeededError, From 7538f1f1285ec8b97ee4e6e9dfdfa3c1fee8a88f Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Mon, 5 Oct 2020 23:48:13 +0800 Subject: [PATCH 07/14] fix decode error. --- client/decoders.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/decoders.go b/client/decoders.go index cc9c9b96..5505e8c3 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -85,19 +85,23 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er c.t104 = m[0x104] c.t174 = t174 c.t402 = m[0x402] + phone := func() string { + r := binary.NewReader(m[0x178]) + return r.ReadStringLimit(int(r.ReadInt32())) + }() if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ? return LoginResponse{ Success: false, Error: SMSNeededError | UnsafeDeviceError, VerifyUrl: string(t204), - SMSPhone: string(m[0x178][4:]), + SMSPhone: phone, ErrorMessage: string(m[0x17e]), }, nil } return LoginResponse{ Success: false, Error: SMSNeededError, - SMSPhone: string(m[0x178][4:]), + SMSPhone: phone, ErrorMessage: string(m[0x17e]), }, nil } From f9b3c399e5e04426c6c47bdbbbb5cc0595a5ab84 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Mon, 5 Oct 2020 23:57:59 +0800 Subject: [PATCH 08/14] fix typo. --- client/builders.go | 4 ++-- client/client.go | 10 +++++----- client/decoders.go | 6 +++--- client/entities.go | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/client/builders.go b/client/builders.go index 0896ff9b..0e183c6e 100644 --- a/client/builders.go +++ b/client/builders.go @@ -127,7 +127,7 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt return seq, packet } -func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { +func (c *QQClient) buildSNSRequestPacket() (uint16, []byte) { seq := c.nextSeq() req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { w.WriteUInt16(8) @@ -145,7 +145,7 @@ func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { return seq, packet } -func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { +func (c *QQClient) buildSNSCodeSubmitPacket(code string) (uint16, []byte) { seq := c.nextSeq() req := packets.BuildOicqRequestPacket(c.Uin, 0x810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { w.WriteUInt16(7) diff --git a/client/client.go b/client/client.go index adc1d8bb..b817a302 100644 --- a/client/client.go +++ b/client/client.go @@ -233,8 +233,8 @@ func (c *QQClient) SubmitCaptcha(result string, sign []byte) (*LoginResponse, er return &l, nil } -func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { - rsp, err := c.sendAndWait(c.buildSMSCodeSubmitPacket(code)) +func (c *QQClient) SubmitSNS(code string) (*LoginResponse, error) { + rsp, err := c.sendAndWait(c.buildSNSCodeSubmitPacket(code)) if err != nil { return nil, err } @@ -248,13 +248,13 @@ func (c *QQClient) SubmitSMS(code string) (*LoginResponse, error) { return &l, nil } -func (c *QQClient) RequestSMS() bool { - rsp, err := c.sendAndWait(c.buildSMSRequestPacket()) +func (c *QQClient) RequestSNS() bool { + rsp, err := c.sendAndWait(c.buildSNSRequestPacket()) if err != nil { c.Error("request sms error: %v", err) return false } - return rsp.(LoginResponse).Error == SMSNeededError + return rsp.(LoginResponse).Error == SNSNeededError } func (c *QQClient) GetVipInfo(target int64) (*VipInfo, error) { diff --git a/client/decoders.go b/client/decoders.go index 5505e8c3..4327ef95 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -92,7 +92,7 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ? return LoginResponse{ Success: false, - Error: SMSNeededError | UnsafeDeviceError, + Error: SNSNeededError | UnsafeDeviceError, VerifyUrl: string(t204), SMSPhone: phone, ErrorMessage: string(m[0x17e]), @@ -100,7 +100,7 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er } return LoginResponse{ Success: false, - Error: SMSNeededError, + Error: SNSNeededError, SMSPhone: phone, ErrorMessage: string(m[0x17e]), }, nil @@ -110,7 +110,7 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er c.t104 = m[0x104] return LoginResponse{ Success: false, - Error: SMSNeededError, + Error: SNSNeededError, }, nil } diff --git a/client/entities.go b/client/entities.go index 1ba97af2..d70c22bc 100644 --- a/client/entities.go +++ b/client/entities.go @@ -252,7 +252,7 @@ const ( NeedCaptcha LoginError = 1 OtherLoginError LoginError = 3 UnsafeDeviceError LoginError = 4 - SMSNeededError LoginError = 5 + SNSNeededError LoginError = 5 TooManySMSRequestError LoginError = 6 UnknownLoginError LoginError = -1 From 071d50aec7f199556d05fb57500699be8feed3b6 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Tue, 6 Oct 2020 18:36:27 +0800 Subject: [PATCH 09/14] fix typo. --- protocol/packets/global.go | 11 ++++++----- protocol/tlv/t106.go | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/protocol/packets/global.go b/protocol/packets/global.go index e7cd5140..37c55011 100644 --- a/protocol/packets/global.go +++ b/protocol/packets/global.go @@ -52,12 +52,12 @@ func BuildOicqRequestPacket(uin int64, commandId uint16, encrypt IEncryptMethod, return p.Bytes() } -func BuildSsoPacket(seq uint16, protocol uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte { +func BuildSsoPacket(seq uint16, appId uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte { p := binary.NewWriter() p.WriteIntLvPacket(4, func(writer *binary.Writer) { writer.WriteUInt32(uint32(seq)) - writer.WriteUInt32(protocol) - writer.WriteUInt32(protocol) + writer.WriteUInt32(appId) + writer.WriteUInt32(appId) writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) if len(extData) == 0 || len(extData) == 4 { writer.WriteUInt32(0x04) @@ -66,8 +66,9 @@ func BuildSsoPacket(seq uint16, protocol uint32, commandName, imei string, extDa writer.Write(extData) } writer.WriteString(commandName) - writer.WriteUInt32(0x08) - writer.Write(outPacketSessionId) + writer.WriteIntLvPacket(4, func(w *binary.Writer) { + w.Write(outPacketSessionId) + }) writer.WriteString(imei) writer.WriteUInt32(0x04) { diff --git a/protocol/tlv/t106.go b/protocol/tlv/t106.go index 7e7b2b2b..2255d669 100644 --- a/protocol/tlv/t106.go +++ b/protocol/tlv/t106.go @@ -8,7 +8,7 @@ import ( "time" ) -func T106(uin, salt, protocol, ssoVer uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte { +func T106(uin, salt, appId, ssoVer uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte, wtf uint32) []byte { return binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt16(0x106) body := binary.NewWriterF(func(w *binary.Writer) { @@ -36,7 +36,7 @@ func T106(uin, salt, protocol, ssoVer uint32, passwordMd5 [16]byte, guidAvailabl } else { w.Write(guid) } - w.WriteUInt32(protocol) + w.WriteUInt32(appId) w.WriteUInt32(1) // password login b := make([]byte, 8) binary2.BigEndian.PutUint64(b, uint64(uin)) From c2cd2cef0b4b95c4a3d30293d73d4aa56d4ee7e1 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Wed, 7 Oct 2020 20:12:43 +0800 Subject: [PATCH 10/14] update error. --- client/decoders.go | 2 +- client/entities.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/client/decoders.go b/client/decoders.go index 4327ef95..329c7162 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -92,7 +92,7 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er if t204, ok := m[0x204]; ok { // 同时支持扫码验证 ? return LoginResponse{ Success: false, - Error: SNSNeededError | UnsafeDeviceError, + Error: SNSOrVerifyNeededError, VerifyUrl: string(t204), SMSPhone: phone, ErrorMessage: string(m[0x17e]), diff --git a/client/entities.go b/client/entities.go index d70c22bc..b796f165 100644 --- a/client/entities.go +++ b/client/entities.go @@ -254,6 +254,7 @@ const ( UnsafeDeviceError LoginError = 4 SNSNeededError LoginError = 5 TooManySMSRequestError LoginError = 6 + SNSOrVerifyNeededError LoginError = 7 UnknownLoginError LoginError = -1 Owner MemberPermission = iota From 6e7abb00aaa63531f505e19c91e9547006f41917 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Wed, 7 Oct 2020 22:23:22 +0800 Subject: [PATCH 11/14] fix typo. --- client/decoders.go | 2 +- client/entities.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/decoders.go b/client/decoders.go index 329c7162..f1a66438 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -127,7 +127,7 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er if t == 162 { return LoginResponse{ - Error: TooManySMSRequestError, + Error: TooManySNSRequestError, }, nil } diff --git a/client/entities.go b/client/entities.go index b796f165..ecb35898 100644 --- a/client/entities.go +++ b/client/entities.go @@ -253,7 +253,7 @@ const ( OtherLoginError LoginError = 3 UnsafeDeviceError LoginError = 4 SNSNeededError LoginError = 5 - TooManySMSRequestError LoginError = 6 + TooManySNSRequestError LoginError = 6 SNSOrVerifyNeededError LoginError = 7 UnknownLoginError LoginError = -1 From 8ca54d6aac442962d74abb7a7b32a3ea7257c5a0 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Thu, 8 Oct 2020 15:09:11 +0800 Subject: [PATCH 12/14] fix count error. --- client/builders.go | 2 +- client/decoders.go | 5 +++-- client/entities.go | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/client/builders.go b/client/builders.go index 0e183c6e..4d036203 100644 --- a/client/builders.go +++ b/client/builders.go @@ -36,7 +36,7 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { seq := c.nextSeq() req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { w.WriteUInt16(9) - w.WriteUInt16(17) + w.WriteUInt16(0x17) w.Write(tlv.T18(16, uint32(c.Uin))) w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress)) diff --git a/client/decoders.go b/client/decoders.go index f1a66438..baa19a37 100644 --- a/client/decoders.go +++ b/client/decoders.go @@ -56,8 +56,9 @@ func decodeLoginResponse(c *QQClient, _ uint16, payload []byte) (interface{}, er c.t104, _ = m[0x104] if m.Exists(0x192) { // slider, not supported yet return LoginResponse{ - Success: false, - Error: UnknownLoginError, + Success: false, + VerifyUrl: string(m[0x192]), + Error: SliderNeededError, }, nil } if m.Exists(0x165) { // image diff --git a/client/entities.go b/client/entities.go index ecb35898..1611e31e 100644 --- a/client/entities.go +++ b/client/entities.go @@ -255,6 +255,7 @@ const ( SNSNeededError LoginError = 5 TooManySNSRequestError LoginError = 6 SNSOrVerifyNeededError LoginError = 7 + SliderNeededError LoginError = 8 UnknownLoginError LoginError = -1 Owner MemberPermission = iota From e1f2ae7f80ed3a40dbc312497745c9cb783def88 Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Thu, 8 Oct 2020 15:15:14 +0800 Subject: [PATCH 13/14] add t191 switch. --- client/builders.go | 10 ++++++++-- client/client.go | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/client/builders.go b/client/builders.go index 4d036203..95c5e5f0 100644 --- a/client/builders.go +++ b/client/builders.go @@ -36,7 +36,11 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { seq := c.nextSeq() req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.ECDH, c.RandomKey, func(w *binary.Writer) { w.WriteUInt16(9) - w.WriteUInt16(0x17) + if c.AllowSlider { + w.WriteUInt16(0x17) + } else { + w.WriteUInt16(0x16) + } w.Write(tlv.T18(16, uint32(c.Uin))) w.Write(tlv.T1(uint32(c.Uin), SystemDeviceInfo.IpAddress)) @@ -80,7 +84,9 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) { if len(SystemDeviceInfo.IMSIMd5) != 0 { w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5)) } - w.Write(tlv.T191(0x82)) + if c.AllowSlider { + w.Write(tlv.T191(0x82)) + } if len(SystemDeviceInfo.WifiBSSID) != 0 && len(SystemDeviceInfo.WifiSSID) != 0 { w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID)) } diff --git a/client/client.go b/client/client.go index b817a302..0bd207f6 100644 --- a/client/client.go +++ b/client/client.go @@ -31,6 +31,7 @@ import ( type QQClient struct { Uin int64 PasswordMd5 [16]byte + AllowSlider bool Nickname string Age uint16 From 5a7da6298521f3532defc8417734d5a44476ddee Mon Sep 17 00:00:00 2001 From: Mrs4s <1844812067@qq.com> Date: Thu, 8 Oct 2020 15:50:30 +0800 Subject: [PATCH 14/14] add: Disconnect() --- client/client.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/client.go b/client/client.go index 0bd207f6..13a10c86 100644 --- a/client/client.go +++ b/client/client.go @@ -986,6 +986,13 @@ func (c *QQClient) connect() error { return nil } +func (c *QQClient) Disconnect() { + if c.Online { + c.Online = false + c.Conn.Close() + } +} + func (c *QQClient) SetCustomServer(servers []*net.TCPAddr) { c.servers = append(servers, c.servers...) }