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

supported skey refresh. thanks @wfjsw

This commit is contained in:
Mrs4s 2020-10-01 20:24:48 +08:00
parent 58921a86ee
commit d83f26daee
7 changed files with 96 additions and 9 deletions

View File

@ -6,7 +6,7 @@ qq-android协议的golang实现 移植于mirai
建议基于 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 使用框架开发。
同时提供不基于 CQHTTP 的原生框架 [MiraiGo-Template](https://github.com/Logiase/MiraiGo-Template)进行开发。
同时提供不基于 CQHTTP 的原生框架 [MiraiGo-Template] (https://github.com/Logiase/MiraiGo-Template)进行开发。
# 已完成功能/开发计划
#### 登录

View File

@ -40,9 +40,9 @@ 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))
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)))
w.Write(tlv.T100(uint32(SystemDeviceInfo.Protocol), 34869472))
w.Write(tlv.T107(0))
w.Write(tlv.T142("com.tencent.mobileqq"))
w.Write(tlv.T144(
@ -127,6 +127,54 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
return seq, packet
}
func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
seq := c.nextSeq()
req := packets.BuildOicqRequestPacket(c.Uin, 0x0810, crypto.NewEncryptSession(c.sigInfo.t133), c.sigInfo.wtSessionTicketKey, func(w *binary.Writer) {
w.WriteUInt16(15)
w.WriteUInt16(21)
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.T107(0))
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,
SystemDeviceInfo.TgtgtKey,
))
w.Write(tlv.T142("com.tencent.mobileqq"))
w.Write(tlv.T145(SystemDeviceInfo.Guid))
w.Write(tlv.T16A(c.sigInfo.srmToken))
w.Write(tlv.T154(seq))
w.Write(tlv.T141(SystemDeviceInfo.SimInfo, SystemDeviceInfo.APN))
w.Write(tlv.T8(2052))
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.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.T187(SystemDeviceInfo.MacAddress))
w.Write(tlv.T188(SystemDeviceInfo.AndroidId))
w.Write(tlv.T194(SystemDeviceInfo.IMSIMd5))
w.Write(tlv.T202(SystemDeviceInfo.WifiBSSID, SystemDeviceInfo.WifiSSID))
w.Write(tlv.T516())
})
packet := packets.BuildUniPacket(c.Uin, seq, "wtlogin.exchange_emp", 2, c.OutGoingPacketSessionId, []byte{}, make([]byte, 16), req)
return seq, packet
}
// StatSvc.register
func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
seq := c.nextSeq()

View File

@ -94,6 +94,7 @@ type loginSigInfo struct {
userStKey []byte
userStWebSig []byte
sKey []byte
sKeyExpiredTime int64
d2 []byte
d2Key []byte
wtSessionTicketKey []byte
@ -121,6 +122,7 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
decoders: map[string]func(*QQClient, uint16, []byte) (interface{}, error){
"wtlogin.login": decodeLoginResponse,
"wtlogin.exchange_emp": decodeExchangeEmpResponse,
"StatSvc.register": decodeClientRegisterResponse,
"StatSvc.ReqMSFOffline": decodeMSFOfflinePacket,
"StatSvc.GetDevLoginInfo": decodeDevListResponse,
@ -849,6 +851,10 @@ func (c *QQClient) SolveFriendRequest(req *NewFriendRequest, accept bool) {
}
func (c *QQClient) getCookies() string {
if c.sigInfo.sKeyExpiredTime < time.Now().Unix() {
c.Debug("skey expired. refresh...")
_, _ = c.sendAndWait(c.buildRequestTgtgtNopicsigPacket())
}
return fmt.Sprintf("uin=o%d; skey=%s;", c.Uin, c.sigInfo.sKey)
}

View File

@ -127,6 +127,23 @@ func decodeClientRegisterResponse(_ *QQClient, _ uint16, payload []byte) (interf
return nil, nil
}
// wtlogin.exchange_emp
func decodeExchangeEmpResponse(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
reader := binary.NewReader(payload)
cmd := reader.ReadUInt16()
t := reader.ReadByte()
reader.ReadUInt16()
m := reader.ReadTlvMap(2)
if t != 0 {
c.Error("exchange_emp error: %v", t)
return nil, nil
}
if cmd == 15 { // TODO: 免密登录
c.decodeT119(m[0x119])
}
return nil, nil
}
// ConfigPushSvc.PushReq
func decodePushReqPacket(c *QQClient, _ uint16, payload []byte) (interface{}, error) {
request := &jce.RequestPacket{}

View File

@ -23,7 +23,18 @@ 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)
}
@ -79,6 +90,10 @@ func (c *QQClient) decodeT119(data []byte) {
//a1, noPicSig = readT531(t531)
}
if _, ok := m[0x138]; ok {
//readT138(t138) // chg time
}
c.sigInfo = &loginSigInfo{
loginBitmap: 0,
srmToken: m[0x16a],
@ -88,6 +103,7 @@ func (c *QQClient) decodeT119(data []byte) {
userStKey: m[0x10e],
userStWebSig: m[0x103],
sKey: m[0x120],
sKeyExpiredTime: time.Now().Unix() + 43200, // 86400 / 2
d2: m[0x143],
d2Key: m[0x305],
wtSessionTicketKey: m[0x134],

View File

@ -4,7 +4,7 @@ import (
"github.com/Mrs4s/MiraiGo/binary"
)
func T100(protocol uint32) []byte {
func T100(protocol, mainSigMap uint32) []byte {
return binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt16(0x100)
w.WriteTlv(binary.NewWriterF(func(w *binary.Writer) {
@ -13,7 +13,7 @@ func T100(protocol uint32) []byte {
w.WriteUInt32(16)
w.WriteUInt32(protocol)
w.WriteUInt32(0) // App client version
w.WriteUInt32(34869472)
w.WriteUInt32(mainSigMap) // 34869472
}))
})
}

View File

@ -8,7 +8,7 @@ import (
"time"
)
func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool, guid, tgtgtKey []byte) []byte {
func T106(uin, salt, protocol 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) {
@ -27,7 +27,7 @@ func T106(uin, salt, protocol uint32, passwordMd5 [16]byte, guidAvailable bool,
w.WriteByte(0x01)
w.Write(passwordMd5[:])
w.Write(tgtgtKey)
w.WriteUInt32(0)
w.WriteUInt32(wtf)
w.WriteBool(guidAvailable)
if len(guid) == 0 {
for i := 0; i < 4; i++ {