1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00

client: pack packet by transport

This commit is contained in:
wdvxdr 2021-12-22 22:29:36 +08:00
parent 3e2b57eab5
commit d2dc2e472d
No known key found for this signature in database
GPG Key ID: 703F8C071DE7A1B6
17 changed files with 343 additions and 347 deletions

View File

@ -10,6 +10,7 @@ import (
"github.com/Mrs4s/MiraiGo/binary/jce" "github.com/Mrs4s/MiraiGo/binary/jce"
"github.com/Mrs4s/MiraiGo/client/internal/auth" "github.com/Mrs4s/MiraiGo/client/internal/auth"
"github.com/Mrs4s/MiraiGo/client/internal/codec" "github.com/Mrs4s/MiraiGo/client/internal/codec"
"github.com/Mrs4s/MiraiGo/client/internal/network"
"github.com/Mrs4s/MiraiGo/client/pb" "github.com/Mrs4s/MiraiGo/client/pb"
"github.com/Mrs4s/MiraiGo/client/pb/cmd0x352" "github.com/Mrs4s/MiraiGo/client/pb/cmd0x352"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
@ -90,9 +91,16 @@ func (c *QQClient) buildLoginPacket() (uint16, []byte) {
w.Write(tlv.T521(0)) w.Write(tlv.T521(0))
w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00}))) w.Write(tlv.T525(tlv.T536([]byte{0x01, 0x00})))
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) { func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) {
@ -102,13 +110,19 @@ func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) {
w.WriteUInt16(4) w.WriteUInt16(4)
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
w.Write(tlv.T104(c.t104)) w.Write(tlv.T104(c.sig.T104))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T401(c.g)) w.Write(tlv.T401(c.sig.G))
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid) req2 := network.Request{
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) Type: network.RequestTypeLogin,
return seq, packet EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildQRCodeFetchRequestPacket() (uint16, []byte) { func (c *QQClient) buildQRCodeFetchRequestPacket() (uint16, []byte) {
@ -133,13 +147,21 @@ func (c *QQClient) buildQRCodeFetchRequestPacket() (uint16, []byte) {
w.Write(tlv.T35(8)) w.Write(tlv.T35(8))
})) }))
})) }))
sso := packets.BuildSsoPacket(seq, watch.AppId, c.version.SubAppId, "wtlogin.trans_emp", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(0, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: 0,
CommandName: "wtlogin.trans_emp",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []byte) { func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []byte) {
watch := auth.AndroidWatch.Version() version := c.transport.Version
c.transport.Version = auth.AndroidWatch.Version()
seq := c.nextSeq() seq := c.nextSeq()
req := c.buildOicqRequestPacket(0, 0x0812, binary.NewWriterF(func(w *binary.Writer) { req := c.buildOicqRequestPacket(0, 0x0812, binary.NewWriterF(func(w *binary.Writer) {
w.WriteHex(`0000620000001000000072000000`) // trans header w.WriteHex(`0000620000001000000072000000`) // trans header
@ -156,9 +178,18 @@ func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []by
w.WriteUInt16(0) // const w.WriteUInt16(0) // const
})) }))
})) }))
sso := packets.BuildSsoPacket(seq, watch.AppId, c.version.SubAppId, "wtlogin.trans_emp", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(0, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: 0,
CommandName: "wtlogin.trans_emp",
Body: req,
}
payload := c.transport.PackPacket(&req2)
c.transport.Version = version
return seq, payload
} }
func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []byte) { func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []byte) {
@ -230,9 +261,16 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by
w.Write(wb) w.Write(wb)
cl() cl()
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byte) { func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byte) {
@ -243,12 +281,19 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
w.Write(tlv.T2(result, sign)) w.Write(tlv.T2(result, sign))
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
w.Write(tlv.T104(c.t104)) w.Write(tlv.T104(c.sig.T104))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) { func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) {
@ -258,15 +303,22 @@ func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) {
w.WriteUInt16(6) w.WriteUInt16(6)
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
w.Write(tlv.T104(c.t104)) w.Write(tlv.T104(c.sig.T104))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T174(c.t174)) w.Write(tlv.T174(c.sig.T174))
w.Write(tlv.T17A(9)) w.Write(tlv.T17A(9))
w.Write(tlv.T197()) w.Write(tlv.T197())
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) { func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) {
@ -276,16 +328,23 @@ func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) {
w.WriteUInt16(7) w.WriteUInt16(7)
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
w.Write(tlv.T104(c.t104)) w.Write(tlv.T104(c.sig.T104))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T174(c.t174)) w.Write(tlv.T174(c.sig.T174))
w.Write(tlv.T17C(code)) w.Write(tlv.T17C(code))
w.Write(tlv.T401(c.g)) w.Write(tlv.T401(c.sig.G))
w.Write(tlv.T198()) w.Write(tlv.T198())
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) { func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) {
@ -296,12 +355,19 @@ func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) {
w.Write(tlv.T193(ticket)) w.Write(tlv.T193(ticket))
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
w.Write(tlv.T104(c.t104)) w.Write(tlv.T104(c.sig.T104))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.login", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) { func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
@ -314,14 +380,14 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
w.Write(tlv.T1(uint32(c.Uin), c.deviceInfo.IpAddress)) w.Write(tlv.T1(uint32(c.Uin), c.deviceInfo.IpAddress))
wb, cl := binary.OpenWriterF(func(bw *binary.Writer) { wb, cl := binary.OpenWriterF(func(bw *binary.Writer) {
bw.WriteUInt16(0x106) bw.WriteUInt16(0x106)
bw.WriteBytesShort(c.sigInfo.EncryptedA1) bw.WriteBytesShort(c.sig.EncryptedA1)
}) })
w.Write(wb) w.Write(wb)
cl() cl()
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T100(c.version.SSOVersion, 2, c.version.MainSigMap)) w.Write(tlv.T100(c.version.SSOVersion, 2, c.version.MainSigMap))
w.Write(tlv.T107(0)) w.Write(tlv.T107(0))
w.Write(tlv.T108(c.ksid)) w.Write(tlv.T108(c.sig.Ksid))
w.Write(tlv.T144( w.Write(tlv.T144(
c.deviceInfo.AndroidId, c.deviceInfo.AndroidId,
c.deviceInfo.GenDeviceInfoData(), c.deviceInfo.GenDeviceInfoData(),
@ -337,7 +403,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
)) ))
w.Write(tlv.T142(c.version.ApkId)) w.Write(tlv.T142(c.version.ApkId))
w.Write(tlv.T145(c.deviceInfo.Guid)) w.Write(tlv.T145(c.deviceInfo.Guid))
w.Write(tlv.T16A(c.sigInfo.SrmToken)) w.Write(tlv.T16A(c.sig.SrmToken))
w.Write(tlv.T154(seq)) w.Write(tlv.T154(seq))
w.Write(tlv.T141(c.deviceInfo.SimInfo, c.deviceInfo.APN)) w.Write(tlv.T141(c.deviceInfo.SimInfo, c.deviceInfo.APN))
w.Write(tlv.T8(2052)) w.Write(tlv.T8(2052))
@ -348,7 +414,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
})) }))
w.Write(tlv.T147(16, []byte(c.version.SortVersionName), c.version.ApkSign)) 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.T177(c.version.BuildTime, c.version.SdkVersion))
w.Write(tlv.T400(c.g, c.Uin, c.deviceInfo.Guid, c.dpwd, 1, 16, c.randSeed)) w.Write(tlv.T400(c.sig.G, c.Uin, c.deviceInfo.Guid, c.sig.Dpwd, 1, 16, c.sig.RandSeed))
w.Write(tlv.T187(c.deviceInfo.MacAddress)) w.Write(tlv.T187(c.deviceInfo.MacAddress))
w.Write(tlv.T188(c.deviceInfo.AndroidId)) w.Write(tlv.T188(c.deviceInfo.AndroidId))
w.Write(tlv.T194(c.deviceInfo.IMSIMd5)) w.Write(tlv.T194(c.deviceInfo.IMSIMd5))
@ -363,23 +429,20 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
oicq := codec.OICQ{ oicq := codec.OICQ{
Uin: uint32(c.Uin), Uin: uint32(c.Uin),
Command: 0x810, Command: 0x810,
EncryptMethod: crypto.NewEncryptSession(c.sigInfo.T133), EncryptMethod: crypto.NewEncryptSession(c.sig.T133),
Key: c.sigInfo.WtSessionTicketKey, Key: c.sig.WtSessionTicketKey,
Body: req, Body: req,
} }
uni := codec.Uni{ nreq := network.Request{
Type: network.RequestTypeSimple,
EncryptType: network.EncryptTypeEmptyKey,
Uin: c.Uin, Uin: c.Uin,
Seq: seq, SequenceID: int32(seq),
CommandName: "wtlogin.exchange_emp", CommandName: "wtlogin.exchange_emp",
EncryptType: 2,
SessionID: c.OutGoingPacketSessionId,
ExtraData: EmptyBytes,
Key: make([]byte, 16),
Body: oicq.Encode(), Body: oicq.Encode(),
} }
return seq, c.transport.PackPacket(&nreq)
return seq, uni.Encode()
} }
func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byte) { func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byte) {
@ -389,10 +452,10 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt
w.WriteUInt16(17) w.WriteUInt16(17)
w.Write(tlv.T100(c.version.SSOVersion, 100, mainSigMap)) w.Write(tlv.T100(c.version.SSOVersion, 100, mainSigMap))
w.Write(tlv.T10A(c.sigInfo.TGT)) w.Write(tlv.T10A(c.sig.TGT))
w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap)) w.Write(tlv.T116(c.version.MiscBitmap, c.version.SubSigmap))
w.Write(tlv.T108(c.ksid)) w.Write(tlv.T108(c.sig.Ksid))
h := md5.Sum(c.sigInfo.D2Key) h := md5.Sum(c.sig.D2Key)
w.Write(tlv.T144( w.Write(tlv.T144(
c.deviceInfo.AndroidId, c.deviceInfo.AndroidId,
c.deviceInfo.GenDeviceInfoData(), c.deviceInfo.GenDeviceInfoData(),
@ -406,7 +469,7 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt
c.deviceInfo.Brand, c.deviceInfo.Brand,
h[:], h[:],
)) ))
w.Write(tlv.T143(c.sigInfo.D2)) w.Write(tlv.T143(c.sig.D2))
w.Write(tlv.T142(c.version.ApkId)) w.Write(tlv.T142(c.version.ApkId))
w.Write(tlv.T154(seq)) w.Write(tlv.T154(seq))
w.Write(tlv.T18(16, uint32(c.Uin))) w.Write(tlv.T18(16, uint32(c.Uin)))
@ -424,9 +487,16 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt
})) }))
// w.Write(tlv.T202(c.deviceInfo.WifiBSSID, c.deviceInfo.WifiSSID)) // w.Write(tlv.T202(c.deviceInfo.WifiBSSID, c.deviceInfo.WifiSSID))
})) }))
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "wtlogin.exchange_emp", c.deviceInfo.IMEI, c.sigInfo.TGT, c.OutGoingPacketSessionId, req, c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeEmptyKey,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.exchange_emp",
Body: req,
}
return seq, c.transport.PackPacket(&req2)
} }
// StatSvc.register // StatSvc.register
@ -472,9 +542,16 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
Context: make(map[string]string), Context: make(map[string]string),
Status: make(map[string]string), Status: make(map[string]string),
} }
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "StatSvc.register", c.deviceInfo.IMEI, c.sigInfo.TGT, c.OutGoingPacketSessionId, pkt.ToBytes(), c.ksid)
packet := packets.BuildLoginPacket(c.Uin, 1, c.sigInfo.D2Key, sso, c.sigInfo.D2) req2 := network.Request{
return seq, packet Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeD2Key,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "StatSvc.register",
Body: pkt.ToBytes(),
}
return seq, c.transport.PackPacket(&req2)
} }
func (c *QQClient) buildStatusSetPacket(status, extStatus int32) (uint16, []byte) { func (c *QQClient) buildStatusSetPacket(status, extStatus int32) (uint16, []byte) {
@ -766,7 +843,7 @@ func (c *QQClient) buildGroupMemberInfoRequestPacket(groupCode, uin int64) (uint
// MessageSvc.PbGetMsg // MessageSvc.PbGetMsg
func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64) (uint16, []byte) { func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64) (uint16, []byte) {
cook := c.syncCookie cook := c.sig.SyncCookie
if cook == nil { if cook == nil {
cook, _ = proto.Marshal(&msg.SyncCookie{ cook, _ = proto.Marshal(&msg.SyncCookie{
Time: &msgTime, Time: &msgTime,
@ -1075,7 +1152,7 @@ func (c *QQClient) buildAppInfoRequestPacket(id string) (uint16, []byte) {
TraceId: proto.String(fmt.Sprintf("%v_%v_%v", c.Uin, time.Now().Format("0102150405"), rand.Int63())), TraceId: proto.String(fmt.Sprintf("%v_%v_%v", c.Uin, time.Now().Format("0102150405"), rand.Int63())),
} }
payload, _ := proto.Marshal(body) payload, _ := proto.Marshal(body)
packet := packets.BuildUniPacket(c.Uin, seq, "LightAppSvc.mini_app_info.GetAppInfoById", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "LightAppSvc.mini_app_info.GetAppInfoById", 1, c.SessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
*/ */

View File

@ -40,8 +40,8 @@ const (
) )
func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *network.IncomingPacketInfo) { func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *network.IncomingPacketInfo) {
c.syncCookie = rsp.SyncCookie c.sig.SyncCookie = rsp.SyncCookie
c.pubAccountCookie = rsp.PubAccountCookie c.sig.PubAccountCookie = rsp.PubAccountCookie
// c.msgCtrlBuf = rsp.MsgCtrlBuf // c.msgCtrlBuf = rsp.MsgCtrlBuf
if rsp.UinPairMsgs == nil { if rsp.UinPairMsgs == nil {
return return

View File

@ -20,7 +20,6 @@ import (
"github.com/Mrs4s/MiraiGo/client/internal/network" "github.com/Mrs4s/MiraiGo/client/internal/network"
"github.com/Mrs4s/MiraiGo/client/pb/msg" "github.com/Mrs4s/MiraiGo/client/pb/msg"
"github.com/Mrs4s/MiraiGo/internal/crypto" "github.com/Mrs4s/MiraiGo/internal/crypto"
"github.com/Mrs4s/MiraiGo/internal/packets"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
) )
@ -48,11 +47,13 @@ type QQClient struct {
GuildService *GuildService GuildService *GuildService
// protocol public field // protocol public field
SequenceId atomic.Int32 SequenceId atomic.Int32
OutGoingPacketSessionId []byte SessionId []byte
RandomKey []byte RandomKey []byte
TCP *network.TCPListener // todo: combine other protocol state into one struct TCP *network.TCPListener // todo: combine other protocol state into one struct
ConnectTime time.Time ConnectTime time.Time
transport *network.Transport
// internal state // internal state
handlers HandlerMap handlers HandlerMap
@ -65,29 +66,10 @@ type QQClient struct {
alive bool alive bool
ecdh *crypto.EncryptECDH ecdh *crypto.EncryptECDH
// tlv cache
t104 []byte
t174 []byte
g []byte
t402 []byte
randSeed []byte // t403
// rollbackSig []byte
// t149 []byte
// t150 []byte
// t528 []byte
// t530 []byte
// sync info
syncCookie []byte
pubAccountCookie []byte
ksid []byte
// msgCtrlBuf []byte
// session info // session info
qwebSeq atomic.Int64 qwebSeq atomic.Int64
sigInfo *auth.SigInfo sig *auth.SigInfo
highwaySession *highway.Session highwaySession *highway.Session
dpwd []byte
// pwdFlag bool // pwdFlag bool
// timeDiff int64 // timeDiff int64
@ -176,22 +158,33 @@ func NewClientEmpty() *QQClient {
func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient { func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
cli := &QQClient{ cli := &QQClient{
Uin: uin, Uin: uin,
PasswordMd5: passwordMd5, PasswordMd5: passwordMd5,
AllowSlider: true, AllowSlider: true,
RandomKey: make([]byte, 16), RandomKey: make([]byte, 16),
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B}, TCP: &network.TCPListener{},
TCP: &network.TCPListener{}, sig: &auth.SigInfo{
sigInfo: &auth.SigInfo{}, OutPacketSessionID: []byte{0x02, 0xB0, 0x5B, 0x8B},
eventHandlers: &eventHandlers{}, },
msgSvcCache: utils.NewCache(time.Second * 15), eventHandlers: &eventHandlers{},
transCache: utils.NewCache(time.Second * 15), msgSvcCache: utils.NewCache(time.Second * 15),
onlinePushCache: utils.NewCache(time.Second * 15), transCache: utils.NewCache(time.Second * 15),
servers: []*net.TCPAddr{}, onlinePushCache: utils.NewCache(time.Second * 15),
alive: true, servers: []*net.TCPAddr{},
ecdh: crypto.NewEcdh(), alive: true,
highwaySession: new(highway.Session), ecdh: crypto.NewEcdh(),
highwaySession: new(highway.Session),
version: new(auth.AppVersion),
deviceInfo: new(auth.Device),
} }
cli.transport = &network.Transport{
Sig: cli.sig,
Version: cli.version,
Device: cli.deviceInfo,
}
{ // init atomic values { // init atomic values
cli.SequenceId.Store(0x3635) cli.SequenceId.Store(0x3635)
cli.requestPacketRequestID.Store(1921334513) cli.requestPacketRequestID.Store(1921334513)
@ -256,10 +249,10 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
} }
func (c *QQClient) UseDevice(info *auth.Device) { func (c *QQClient) UseDevice(info *auth.Device) {
c.version = info.Protocol.Version() *c.version = *info.Protocol.Version()
*c.deviceInfo = *info
c.highwaySession.AppID = int32(c.version.AppId) c.highwaySession.AppID = int32(c.version.AppId)
c.ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI)) c.sig.Ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI))
c.deviceInfo = info
} }
func (c *QQClient) Release() { func (c *QQClient) Release() {
@ -301,14 +294,14 @@ func (c *QQClient) TokenLogin(token []byte) error {
{ {
r := binary.NewReader(token) r := binary.NewReader(token)
c.Uin = r.ReadInt64() c.Uin = r.ReadInt64()
c.sigInfo.D2 = r.ReadBytesShort() c.sig.D2 = r.ReadBytesShort()
c.sigInfo.D2Key = r.ReadBytesShort() c.sig.D2Key = r.ReadBytesShort()
c.sigInfo.TGT = r.ReadBytesShort() c.sig.TGT = r.ReadBytesShort()
c.sigInfo.SrmToken = r.ReadBytesShort() c.sig.SrmToken = r.ReadBytesShort()
c.sigInfo.T133 = r.ReadBytesShort() c.sig.T133 = r.ReadBytesShort()
c.sigInfo.EncryptedA1 = r.ReadBytesShort() c.sig.EncryptedA1 = r.ReadBytesShort()
c.sigInfo.WtSessionTicketKey = r.ReadBytesShort() c.sig.WtSessionTicketKey = r.ReadBytesShort()
c.OutGoingPacketSessionId = r.ReadBytesShort() c.sig.OutPacketSessionID = r.ReadBytesShort()
// SystemDeviceInfo.TgtgtKey = r.ReadBytesShort() // SystemDeviceInfo.TgtgtKey = r.ReadBytesShort()
c.deviceInfo.TgtgtKey = r.ReadBytesShort() c.deviceInfo.TgtgtKey = r.ReadBytesShort()
} }
@ -406,7 +399,7 @@ func (c *QQClient) RequestSMS() bool {
} }
func (c *QQClient) init(tokenLogin bool) error { func (c *QQClient) init(tokenLogin bool) error {
if len(c.g) == 0 { if len(c.sig.G) == 0 {
c.Warning("device lock is disable. http api may fail.") c.Warning("device lock is disable. http api may fail.")
} }
c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10) c.highwaySession.Uin = strconv.FormatInt(c.Uin, 10)
@ -449,14 +442,14 @@ func (c *QQClient) init(tokenLogin bool) error {
func (c *QQClient) GenToken() []byte { func (c *QQClient) GenToken() []byte {
return binary.NewWriterF(func(w *binary.Writer) { return binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt64(uint64(c.Uin)) w.WriteUInt64(uint64(c.Uin))
w.WriteBytesShort(c.sigInfo.D2) w.WriteBytesShort(c.sig.D2)
w.WriteBytesShort(c.sigInfo.D2Key) w.WriteBytesShort(c.sig.D2Key)
w.WriteBytesShort(c.sigInfo.TGT) w.WriteBytesShort(c.sig.TGT)
w.WriteBytesShort(c.sigInfo.SrmToken) w.WriteBytesShort(c.sig.SrmToken)
w.WriteBytesShort(c.sigInfo.T133) w.WriteBytesShort(c.sig.T133)
w.WriteBytesShort(c.sigInfo.EncryptedA1) w.WriteBytesShort(c.sig.EncryptedA1)
w.WriteBytesShort(c.sigInfo.WtSessionTicketKey) w.WriteBytesShort(c.sig.WtSessionTicketKey)
w.WriteBytesShort(c.OutGoingPacketSessionId) w.WriteBytesShort(c.sig.OutPacketSessionID)
w.WriteBytesShort(c.deviceInfo.TgtgtKey) w.WriteBytesShort(c.deviceInfo.TgtgtKey)
}) })
} }
@ -681,11 +674,11 @@ func (c *QQClient) SolveFriendRequest(req *NewFriendRequest, accept bool) {
} }
func (c *QQClient) getSKey() string { func (c *QQClient) getSKey() string {
if c.sigInfo.SKeyExpiredTime < time.Now().Unix() && len(c.g) > 0 { if c.sig.SKeyExpiredTime < time.Now().Unix() && len(c.sig.G) > 0 {
c.Debug("skey expired. refresh...") c.Debug("skey expired. refresh...")
_, _ = c.sendAndWait(c.buildRequestTgtgtNopicsigPacket()) _, _ = c.sendAndWait(c.buildRequestTgtgtNopicsigPacket())
} }
return string(c.sigInfo.SKey) return string(c.sig.SKey)
} }
func (c *QQClient) getCookies() string { func (c *QQClient) getCookies() string {
@ -695,7 +688,7 @@ func (c *QQClient) getCookies() string {
func (c *QQClient) getCookiesWithDomain(domain string) string { func (c *QQClient) getCookiesWithDomain(domain string) string {
cookie := c.getCookies() cookie := c.getCookies()
if psKey, ok := c.sigInfo.PsKeyMap[domain]; ok { if psKey, ok := c.sig.PsKeyMap[domain]; ok {
return fmt.Sprintf("%s p_uin=o%d; p_skey=%s;", cookie, c.Uin, psKey) return fmt.Sprintf("%s p_uin=o%d; p_skey=%s;", cookie, c.Uin, psKey)
} else { } else {
return cookie return cookie
@ -800,8 +793,15 @@ func (c *QQClient) doHeartbeat() {
for c.Online.Load() { for c.Online.Load() {
time.Sleep(time.Second * 30) time.Sleep(time.Second * 30)
seq := c.nextSeq() seq := c.nextSeq()
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "Heartbeat.Alive", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, EmptyBytes, c.ksid) req := network.Request{
packet := packets.BuildLoginPacket(c.Uin, 0, EmptyBytes, sso, EmptyBytes) Type: network.RequestTypeLogin,
EncryptType: network.EncryptTypeNoEncrypt,
SequenceID: int32(seq),
Uin: c.Uin,
CommandName: "wtlogin.login",
Body: EmptyBytes,
}
packet := c.transport.PackPacket(&req)
_, err := c.sendAndWait(seq, packet) _, err := c.sendAndWait(seq, packet)
if errors.Is(err, network.ErrConnectionClosed) { if errors.Is(err, network.ErrConnectionClosed) {
continue continue

View File

@ -39,10 +39,10 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
reader.ReadUInt16() reader.ReadUInt16()
m := reader.ReadTlvMap(2) m := reader.ReadTlvMap(2)
if m.Exists(0x402) { if m.Exists(0x402) {
c.dpwd = []byte(utils.RandomString(16)) c.sig.Dpwd = []byte(utils.RandomString(16))
c.t402 = m[0x402] c.sig.T402 = m[0x402]
h := md5.Sum(append(append(c.deviceInfo.Guid, c.dpwd...), c.t402...)) h := md5.Sum(append(append(c.deviceInfo.Guid, c.sig.Dpwd...), c.sig.T402...))
c.g = h[:] c.sig.G = h[:]
} }
if t == 0 { // login success if t == 0 { // login success
// if t150, ok := m[0x150]; ok { // if t150, ok := m[0x150]; ok {
@ -52,7 +52,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
c.decodeT161(t161) c.decodeT161(t161)
} }
if m.Exists(0x403) { if m.Exists(0x403) {
c.randSeed = m[0x403] c.sig.RandSeed = m[0x403]
} }
c.decodeT119(m[0x119], c.deviceInfo.TgtgtKey) c.decodeT119(m[0x119], c.deviceInfo.TgtgtKey)
return LoginResponse{ return LoginResponse{
@ -60,7 +60,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
}, nil }, nil
} }
if t == 2 { if t == 2 {
c.t104 = m[0x104] c.sig.T104 = m[0x104]
if m.Exists(0x192) { if m.Exists(0x192) {
return LoginResponse{ return LoginResponse{
Success: false, Success: false,
@ -97,9 +97,9 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
if t == 160 || t == 239 { if t == 160 || t == 239 {
if t174, ok := m[0x174]; ok { // 短信验证 if t174, ok := m[0x174]; ok { // 短信验证
c.t104 = m[0x104] c.sig.T104 = m[0x104]
c.t174 = t174 c.sig.T174 = t174
c.randSeed = m[0x403] c.sig.RandSeed = m[0x403]
phone := func() string { phone := func() string {
r := binary.NewReader(m[0x178]) r := binary.NewReader(m[0x178])
return r.ReadStringLimit(int(r.ReadInt32())) return r.ReadStringLimit(int(r.ReadInt32()))
@ -122,7 +122,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
} }
if _, ok := m[0x17b]; ok { // 二次验证 if _, ok := m[0x17b]; ok { // 二次验证
c.t104 = m[0x104] c.sig.T104 = m[0x104]
return LoginResponse{ return LoginResponse{
Success: false, Success: false,
Error: SMSNeededError, Error: SMSNeededError,
@ -146,8 +146,8 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
} }
if t == 204 { if t == 204 {
c.t104 = m[0x104] c.sig.T104 = m[0x104]
c.randSeed = m[0x403] c.sig.RandSeed = m[0x403]
return c.sendAndWait(c.buildDeviceLockLoginPacket()) return c.sendAndWait(c.buildDeviceLockLoginPacket())
} // drive lock } // drive lock
@ -210,7 +210,7 @@ func decodeExchangeEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, paylo
c.decodeT119R(m[0x119]) c.decodeT119R(m[0x119])
} }
if cmd == 11 { if cmd == 11 {
h := md5.Sum(c.sigInfo.D2Key) h := md5.Sum(c.sig.D2Key)
c.decodeT119(m[0x119], h[:]) c.decodeT119(m[0x119], h[:])
} }
return nil, nil return nil, nil

View File

@ -663,7 +663,7 @@ func (s *GuildService) fetchChannelListState(guildId uint64, channels []*Channel
2: ids, 2: ids,
}, },
}) })
packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0x1008_1", 1, s.c.OutGoingPacketSessionId, []byte{}, s.c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(s.c.Uin, seq, "OidbSvcTrpcTcp.0x1008_1", 1, s.c.SessionId, []byte{}, s.c.sigInfo.d2Key, payload)
rsp, err := s.c.sendAndWaitDynamic(seq, packet) rsp, err := s.c.sendAndWaitDynamic(seq, packet)
if err != nil { if err != nil {
return return

View File

@ -127,4 +127,26 @@ type SigInfo struct {
PsKeyMap map[string][]byte PsKeyMap map[string][]byte
Pt4TokenMap map[string][]byte Pt4TokenMap map[string][]byte
// Others
OutPacketSessionID []byte
Dpwd []byte
// tlv cache
T104 []byte
T174 []byte
G []byte
T402 []byte
RandSeed []byte // t403
// rollbackSig []byte
// t149 []byte
// t150 []byte
// t528 []byte
// t530 []byte
// sync info
SyncCookie []byte
PubAccountCookie []byte
Ksid []byte
// msgCtrlBuf []byte
} }

View File

@ -1,41 +0,0 @@
package codec
import (
"strconv"
"github.com/Mrs4s/MiraiGo/binary"
)
type Uni struct {
Uin int64
Seq uint16
CommandName string
EncryptType byte
SessionID []byte
ExtraData []byte
Key []byte
Body []byte
}
func (u *Uni) Encode() []byte {
return binary.NewWriterF(func(w *binary.Writer) {
w2 := binary.SelectWriter()
{ // w.WriteIntLvPacket
w2.WriteUInt32(0x0B)
w2.WriteByte(u.EncryptType)
w2.WriteUInt32(uint32(u.Seq))
w2.WriteByte(0)
w2.WriteString(strconv.FormatInt(u.Uin, 10))
// inline NewWriterF
w3 := binary.SelectWriter()
w3.WriteUniPacket(u.CommandName, u.SessionID, u.ExtraData, u.Body)
w2.EncryptAndWrite(u.Key, w3.Bytes())
binary.PutWriter(w3)
}
data := w2.Bytes()
w.WriteUInt32(uint32(len(data) + 4))
w.Write(data)
binary.PutWriter(w2)
})
}

View File

@ -22,6 +22,6 @@ type Request struct {
EncryptType EncryptType EncryptType EncryptType
SequenceID int32 SequenceID int32
Uin int64 Uin int64
Method string CommandName string
Body []byte Body []byte
} }

View File

@ -11,95 +11,96 @@ import (
// Transport is a network transport. // Transport is a network transport.
type Transport struct { type Transport struct {
sessionMu sync.Mutex sessionMu sync.Mutex
// todo: combine session fields to a struct Sig *auth.SigInfo
tgt []byte Version *auth.AppVersion
d2key []byte Device *auth.Device
sessionID []byte
ksid []byte
version *auth.AppVersion
device *auth.Device
// connection // connection
conn *TCPListener // conn *TCPListener
} }
func (t *Transport) packBody(req *Request, w *binary.Writer) { func (t *Transport) packBody(req *Request) []byte {
w := binary.SelectWriter()
defer binary.PutWriter(w)
w.WriteIntLvPacket(4, func(writer *binary.Writer) { w.WriteIntLvPacket(4, func(writer *binary.Writer) {
if req.Type == RequestTypeLogin { if req.Type == RequestTypeLogin {
writer.WriteUInt32(uint32(req.SequenceID)) writer.WriteUInt32(uint32(req.SequenceID))
writer.WriteUInt32(t.version.AppId) writer.WriteUInt32(t.Version.AppId)
writer.WriteUInt32(t.version.SubAppId) writer.WriteUInt32(t.Version.SubAppId)
writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}) writer.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
if len(t.tgt) == 0 || len(t.tgt) == 4 { tgt := t.Sig.TGT
if len(tgt) == 0 || len(tgt) == 4 {
writer.WriteUInt32(0x04) writer.WriteUInt32(0x04)
} else { } else {
writer.WriteUInt32(uint32(len(t.tgt) + 4)) writer.WriteUInt32(uint32(len(tgt) + 4))
writer.Write(t.tgt) writer.Write(tgt)
} }
} }
writer.WriteString(req.CommandName)
writer.WriteString(req.Method) writer.WriteIntLvPacket(4, func(w *binary.Writer) {
writer.WriteUInt32(uint32(len(t.sessionID) + 4)) w.Write(t.Sig.OutPacketSessionID)
w.Write(t.sessionID) })
// writer.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4))
// w.Write(t.Sig.OutPacketSessionID)
if req.Type == RequestTypeLogin { if req.Type == RequestTypeLogin {
writer.WriteString(t.device.IMEI) writer.WriteString(t.Device.IMEI)
writer.WriteUInt32(0x04) writer.WriteUInt32(0x04)
{ {
writer.WriteUInt16(uint16(len(t.ksid)) + 2) writer.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2)
writer.Write(t.ksid) writer.Write(t.Sig.Ksid)
} }
} }
writer.WriteUInt32(0x04) writer.WriteUInt32(0x04)
}) })
w.WriteUInt32(uint32(len(req.Body) + 4)) w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(req.Body) w.Write(req.Body)
})
// w.WriteUInt32(uint32(len(req.Body) + 4))
// w.Write(req.Body)
return append([]byte(nil), w.Bytes()...)
} }
func (t *Transport) Send(req *Request) error { // PackPacket packs a packet.
// todo: return response func (t *Transport) PackPacket(req *Request) []byte {
// todo(wdvxdr): combine pack packet, send packet and return the response
if len(t.Sig.D2) == 0 {
req.EncryptType = EncryptTypeEmptyKey
}
body := t.packBody(req)
// encrypt body
switch req.EncryptType {
case EncryptTypeD2Key:
body = binary.NewTeaCipher(t.Sig.D2Key).Encrypt(body)
case EncryptTypeEmptyKey:
body = binary.NewTeaCipher(emptyKey).Encrypt(body)
}
head := binary.NewWriterF(func(w *binary.Writer) { head := binary.NewWriterF(func(w *binary.Writer) {
w.WriteUInt32(uint32(req.Type)) w.WriteUInt32(uint32(req.Type))
w.WriteUInt32(uint32(req.EncryptType)) w.WriteByte(byte(req.EncryptType))
switch req.Type { switch req.Type {
case RequestTypeLogin: case RequestTypeLogin:
switch req.EncryptType { switch req.EncryptType {
case EncryptTypeD2Key: case EncryptTypeD2Key:
w.WriteUInt32(uint32(len(t.d2key) + 4)) w.WriteUInt32(uint32(len(t.Sig.D2) + 4))
w.Write(t.d2key) w.Write(t.Sig.D2)
default: default:
w.WriteUInt32(4) w.WriteUInt32(4)
} }
case RequestTypeSimple: case RequestTypeSimple:
w.WriteUInt32(uint32(req.SequenceID)) w.WriteUInt32(uint32(req.SequenceID))
} }
w.WriteByte(0x00)
w.WriteString(strconv.FormatInt(req.Uin, 10)) w.WriteString(strconv.FormatInt(req.Uin, 10))
}) })
w := binary.SelectWriter() w := binary.SelectWriter()
defer binary.PutWriter(w) defer binary.PutWriter(w)
t.packBody(req, w) w.WriteUInt32(uint32(len(head)+len(body)) + 4)
body := w.Bytes() w.Write(head)
w.Write(body)
// encrypt body return append([]byte(nil), w.Bytes()...) // copy
switch req.EncryptType {
case EncryptTypeD2Key:
body = binary.NewTeaCipher(t.d2key).Encrypt(body)
case EncryptTypeEmptyKey:
body = binary.NewTeaCipher(emptyKey).Encrypt(body)
}
w2 := binary.SelectWriter()
defer binary.PutWriter(w2)
w2.WriteUInt32(uint32(len(head) + len(body) + 4))
w2.Write(head)
w2.Write(body)
err := t.conn.Write(w2.Bytes())
if err != nil {
return err
}
return nil
} }
func (t *Transport) parse(head []byte) *Request { func (t *Transport) parse(head []byte) *Request {
@ -119,7 +120,7 @@ func (t *Transport) parse(head []byte) *Request {
case EncryptTypeNoEncrypt: case EncryptTypeNoEncrypt:
req.Body = body req.Body = body
case EncryptTypeD2Key: case EncryptTypeD2Key:
req.Body = binary.NewTeaCipher(t.d2key).Decrypt(body) req.Body = binary.NewTeaCipher(t.Sig.D2Key).Decrypt(body)
case EncryptTypeEmptyKey: case EncryptTypeEmptyKey:
req.Body = binary.NewTeaCipher(emptyKey).Decrypt(body) req.Body = binary.NewTeaCipher(emptyKey).Decrypt(body)
} }

View File

@ -42,7 +42,7 @@ type (
) )
func (c *QQClient) getGtk(domain string) int { func (c *QQClient) getGtk(domain string) int {
if psKey, ok := c.sigInfo.PsKeyMap[domain]; ok { if psKey, ok := c.sig.PsKeyMap[domain]; ok {
accu := 5381 accu := 5381
for _, b := range psKey { for _, b := range psKey {
accu = accu + (accu << 5) + int(b) accu = accu + (accu << 5) + int(b)

View File

@ -291,7 +291,7 @@ func (c *QQClient) netLoop() {
continue continue
} }
data, _ := c.TCP.ReadBytes(int(l) - 4) data, _ := c.TCP.ReadBytes(int(l) - 4)
pkt, err := packets.ParseIncomingPacket(data, c.sigInfo.D2Key) pkt, err := packets.ParseIncomingPacket(data, c.sig.D2Key)
if err != nil { if err != nil {
c.Error("parse incoming packet error: %v", err) c.Error("parse incoming packet error: %v", err)
if errors.Is(err, packets.ErrSessionExpired) || errors.Is(err, packets.ErrPacketDropped) { if errors.Is(err, packets.ErrSessionExpired) || errors.Is(err, packets.ErrPacketDropped) {
@ -306,7 +306,7 @@ func (c *QQClient) netLoop() {
continue continue
} }
if pkt.Flag2 == 2 { if pkt.Flag2 == 2 {
pkt.Payload, err = pkt.DecryptPayload(c.ecdh.InitialShareKey, c.RandomKey, c.sigInfo.WtSessionTicketKey) pkt.Payload, err = pkt.DecryptPayload(c.ecdh.InitialShareKey, c.RandomKey, c.sig.WtSessionTicketKey)
if err != nil { if err != nil {
c.Error("decrypt payload error: %v", err) c.Error("decrypt payload error: %v", err)
if errors.Is(err, packets.ErrUnknownFlag) { if errors.Is(err, packets.ErrUnknownFlag) {

View File

@ -2,6 +2,7 @@ package client
import ( import (
"github.com/Mrs4s/MiraiGo/client/internal/codec" "github.com/Mrs4s/MiraiGo/client/internal/codec"
"github.com/Mrs4s/MiraiGo/client/internal/network"
) )
//go:noinline //go:noinline
@ -19,30 +20,26 @@ func (c *QQClient) buildOicqRequestPacket(uin int64, command uint16, body []byte
//go:noinline //go:noinline
func (c *QQClient) uniPacket(command string, body []byte) (uint16, []byte) { func (c *QQClient) uniPacket(command string, body []byte) (uint16, []byte) {
seq := c.nextSeq() seq := c.nextSeq()
req := codec.Uni{ req := network.Request{
Type: network.RequestTypeSimple,
EncryptType: network.EncryptTypeD2Key,
Uin: c.Uin, Uin: c.Uin,
Seq: seq, SequenceID: int32(seq),
CommandName: command, CommandName: command,
EncryptType: 1,
SessionID: c.OutGoingPacketSessionId,
ExtraData: EmptyBytes,
Key: c.sigInfo.D2Key,
Body: body, Body: body,
} }
return seq, req.Encode() return seq, c.transport.PackPacket(&req)
} }
//go:noinline //go:noinline
func (c *QQClient) uniPacketWithSeq(seq uint16, command string, body []byte) []byte { func (c *QQClient) uniPacketWithSeq(seq uint16, command string, body []byte) []byte {
req := codec.Uni{ req := network.Request{
Type: network.RequestTypeSimple,
EncryptType: network.EncryptTypeD2Key,
Uin: c.Uin, Uin: c.Uin,
Seq: seq, SequenceID: int32(seq),
CommandName: command, CommandName: command,
EncryptType: 1,
SessionID: c.OutGoingPacketSessionId,
ExtraData: EmptyBytes,
Key: c.sigInfo.D2Key,
Body: body, Body: body,
} }
return req.Encode() return c.transport.PackPacket(&req)
} }

View File

@ -139,7 +139,7 @@ func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int6
ReadCnt: &count, ReadCnt: &count,
} }
payload, _ := proto.Marshal(req) payload, _ := proto.Marshal(req)
packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbGetOneDayRoamMsg", 1, c.OutGoingPacketSessionId, EmptyBytes, c.sigInfo.d2Key, payload) packet := packets.BuildUniPacket(c.Uin, seq, "MessageSvc.PbGetOneDayRoamMsg", 1, c.SessionId, EmptyBytes, c.sigInfo.d2Key, payload)
return seq, packet return seq, packet
} }
*/ */

View File

@ -157,11 +157,11 @@ func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) {
Channel: 4, Channel: 4,
Inst: 1, Inst: 1,
ChannelEx: 1, ChannelEx: 1,
SyncCookie: c.syncCookie, SyncCookie: c.sig.SyncCookie,
SyncFlag: 0, // START SyncFlag: 0, // START
RambleFlag: 0, RambleFlag: 0,
GeneralAbi: 1, GeneralAbi: 1,
PubAccountCookie: c.pubAccountCookie, PubAccountCookie: c.sig.PubAccountCookie,
}, },
GroupMsg: &jce.SvcReqPullGroupMsgSeq{ GroupMsg: &jce.SvcReqPullGroupMsgSeq{
VerifyType: 0, VerifyType: 0,
@ -172,7 +172,7 @@ func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) {
flag := msg.SyncFlag_START flag := msg.SyncFlag_START
msgReq, _ := proto.Marshal(&msg.GetMessageRequest{ msgReq, _ := proto.Marshal(&msg.GetMessageRequest{
SyncFlag: &flag, SyncFlag: &flag,
SyncCookie: c.syncCookie, SyncCookie: c.sig.SyncCookie,
RambleFlag: proto.Int32(0), RambleFlag: proto.Int32(0),
ContextFlag: proto.Int32(1), ContextFlag: proto.Int32(1),
OnlineSyncFlag: proto.Int32(0), OnlineSyncFlag: proto.Int32(0),
@ -224,11 +224,11 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
Channel: 4, Channel: 4,
Inst: 1, Inst: 1,
ChannelEx: 1, ChannelEx: 1,
SyncCookie: c.syncCookie, SyncCookie: c.sig.SyncCookie,
SyncFlag: 0, // START SyncFlag: 0, // START
RambleFlag: 0, RambleFlag: 0,
GeneralAbi: 1, GeneralAbi: 1,
PubAccountCookie: c.pubAccountCookie, PubAccountCookie: c.sig.PubAccountCookie,
}, },
GroupMask: 2, GroupMask: 2,
EndSeq: int64(rand.Uint32()), EndSeq: int64(rand.Uint32()),
@ -237,7 +237,7 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
flag := msg.SyncFlag_START flag := msg.SyncFlag_START
msgReq := &msg.GetMessageRequest{ msgReq := &msg.GetMessageRequest{
SyncFlag: &flag, SyncFlag: &flag,
SyncCookie: c.syncCookie, SyncCookie: c.sig.SyncCookie,
RambleFlag: proto.Int32(0), RambleFlag: proto.Int32(0),
ContextFlag: proto.Int32(1), ContextFlag: proto.Int32(1),
OnlineSyncFlag: proto.Int32(0), OnlineSyncFlag: proto.Int32(0),
@ -248,7 +248,7 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
offMsg, _ := proto.Marshal(msgReq) offMsg, _ := proto.Marshal(msgReq)
msgReq.MsgReqType = proto.Int32(2) msgReq.MsgReqType = proto.Int32(2)
msgReq.SyncCookie = nil msgReq.SyncCookie = nil
msgReq.PubaccountCookie = c.pubAccountCookie msgReq.PubaccountCookie = c.sig.PubAccountCookie
pubMsg, _ := proto.Marshal(msgReq) pubMsg, _ := proto.Marshal(msgReq)
buf := &jce.RequestDataVersion3{Map: map[string][]byte{ buf := &jce.RequestDataVersion3{Map: map[string][]byte{
"req_PbOffMsg": jce.NewJceWriter().WriteBytes(append([]byte{0, 0, 0, 0}, offMsg...), 0).Bytes(), "req_PbOffMsg": jce.NewJceWriter().WriteBytes(append([]byte{0, 0, 0, 0}, offMsg...), 0).Bytes(),
@ -280,7 +280,7 @@ func (c *QQClient) buildPrivateMsgReadedPacket(uin, time int64) (uint16, []byte)
PeerUin: proto.Uint64(uint64(uin)), PeerUin: proto.Uint64(uint64(uin)),
LastReadTime: proto.Uint32(uint32(time)), LastReadTime: proto.Uint32(uint32(time)),
}, },
}, SyncCookie: c.syncCookie}}) }, SyncCookie: c.sig.SyncCookie}})
return c.uniPacket("PbMessageSvc.PbMsgReadedReport", req) return c.uniPacket("PbMessageSvc.PbMsgReadedReport", req)
} }

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/Mrs4s/MiraiGo/client/internal/auth"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
"github.com/Mrs4s/MiraiGo/binary" "github.com/Mrs4s/MiraiGo/binary"
@ -44,7 +43,7 @@ func (c *QQClient) decodeT119(data, ek []byte) {
} }
*/ */
if t108, ok := m[0x108]; ok { if t108, ok := m[0x108]; ok {
c.ksid = t108 c.sig.Ksid = t108
} }
var ( var (
@ -91,29 +90,28 @@ func (c *QQClient) decodeT119(data, ek []byte) {
} }
// we don't use `c.sigInfo = &auth.SigInfo{...}` here, // we don't use `c.sigInfo = &auth.SigInfo{...}` here,
// because we need spread `SigInfo` to other places // because we need keep other fields in `c.sigInfo`
*c.sigInfo = auth.SigInfo{ s := c.sig
LoginBitmap: 0, s.LoginBitmap = 0
SrmToken: utils.Select(m[0x16a], c.sigInfo.SrmToken), s.SrmToken = utils.Select(m[0x16a], s.SrmToken)
T133: utils.Select(m[0x133], c.sigInfo.T133), s.T133 = utils.Select(m[0x133], s.T133)
EncryptedA1: utils.Select(m[0x106], c.sigInfo.EncryptedA1), s.EncryptedA1 = utils.Select(m[0x106], s.EncryptedA1)
TGT: m[0x10a], s.TGT = m[0x10a]
TGTKey: m[0x10d], s.TGTKey = m[0x10d]
UserStKey: m[0x10e], s.UserStKey = m[0x10e]
UserStWebSig: m[0x103], s.UserStWebSig = m[0x103]
SKey: m[0x120], s.SKey = m[0x120]
SKeyExpiredTime: time.Now().Unix() + 21600, s.SKeyExpiredTime = time.Now().Unix() + 21600
D2: m[0x143], s.D2 = m[0x143]
D2Key: m[0x305], s.D2Key = m[0x305]
WtSessionTicketKey: utils.Select(m[0x134], c.sigInfo.WtSessionTicketKey), s.WtSessionTicketKey = utils.Select(m[0x134], s.WtSessionTicketKey)
DeviceToken: m[0x322], s.DeviceToken = m[0x322]
PsKeyMap: psKeyMap, s.PsKeyMap = psKeyMap
Pt4TokenMap: pt4TokenMap, s.Pt4TokenMap = pt4TokenMap
}
if len(c.PasswordMd5[:]) > 0 { 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.sig.EncryptedA1)
if len(decrypted) > 51+16 { if len(decrypted) > 51+16 {
dr := binary.NewReader(decrypted) dr := binary.NewReader(decrypted)
dr.ReadBytes(51) dr.ReadBytes(51)
@ -132,9 +130,9 @@ func (c *QQClient) decodeT119R(data []byte) {
reader.ReadBytes(2) reader.ReadBytes(2)
m := reader.ReadTlvMap(2) m := reader.ReadTlvMap(2)
if t120, ok := m[0x120]; ok { if t120, ok := m[0x120]; ok {
c.sigInfo.SKey = t120 c.sig.SKey = t120
c.sigInfo.SKeyExpiredTime = time.Now().Unix() + 21600 c.sig.SKeyExpiredTime = time.Now().Unix() + 21600
c.Debug("skey updated: %v", c.sigInfo.SKey) c.Debug("skey updated: %v", c.sig.SKey)
} }
if t11a, ok := m[0x11a]; ok { if t11a, ok := m[0x11a]; ok {
c.Nickname, c.Age, c.Gender = readT11A(t11a) c.Nickname, c.Age, c.Gender = readT11A(t11a)

View File

@ -1,26 +0,0 @@
package packets
import (
"strconv"
"github.com/Mrs4s/MiraiGo/binary"
)
func BuildLoginPacket(uin int64, bodyType byte, key, body, extraData []byte) []byte {
return binary.NewWriterF(func(w *binary.Writer) {
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.WriteUInt32(0x00_00_00_0A)
w.WriteByte(bodyType)
w.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(extraData)
})
w.WriteByte(0x00)
w.WriteString(strconv.FormatInt(uin, 10))
if len(key) == 0 {
w.Write(body)
} else {
w.EncryptAndWrite(key, body)
}
})
})
}

View File

@ -46,38 +46,6 @@ func BuildCode2DRequestPacket(seq uint32, j uint64, cmd uint16, bodyFunc func(wr
}) })
} }
func BuildSsoPacket(seq uint16, appID, subAppID uint32, commandName, imei string, extData, outPacketSessionId, body, ksid []byte) []byte {
return binary.NewWriterF(func(p *binary.Writer) {
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.WriteUInt32(uint32(seq))
writer.WriteUInt32(appID)
writer.WriteUInt32(subAppID)
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)
} else {
writer.WriteUInt32(uint32(len(extData) + 4))
writer.Write(extData)
}
writer.WriteString(commandName)
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
w.Write(outPacketSessionId)
})
writer.WriteString(imei)
writer.WriteUInt32(0x04)
{
writer.WriteUInt16(uint16(len(ksid)) + 2)
writer.Write(ksid)
}
writer.WriteUInt32(0x04)
})
p.WriteIntLvPacket(4, func(writer *binary.Writer) {
writer.Write(body)
})
})
}
func ParseIncomingPacket(payload, d2key []byte) (*IncomingPacket, error) { func ParseIncomingPacket(payload, d2key []byte) (*IncomingPacket, error) {
if len(payload) < 6 { if len(payload) < 6 {
return nil, errors.WithStack(ErrInvalidPayload) return nil, errors.WithStack(ErrInvalidPayload)