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:
parent
3e2b57eab5
commit
d2dc2e472d
@ -10,6 +10,7 @@ import (
|
||||
"github.com/Mrs4s/MiraiGo/binary/jce"
|
||||
"github.com/Mrs4s/MiraiGo/client/internal/auth"
|
||||
"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/cmd0x352"
|
||||
"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.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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -102,13 +110,19 @@ func (c *QQClient) buildDeviceLockLoginPacket() (uint16, []byte) {
|
||||
w.WriteUInt16(4)
|
||||
|
||||
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.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)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 2, make([]byte, 16), sso, EmptyBytes)
|
||||
return seq, packet
|
||||
req2 := network.Request{
|
||||
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) buildQRCodeFetchRequestPacket() (uint16, []byte) {
|
||||
@ -133,13 +147,21 @@ func (c *QQClient) buildQRCodeFetchRequestPacket() (uint16, []byte) {
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
watch := auth.AndroidWatch.Version()
|
||||
version := c.transport.Version
|
||||
c.transport.Version = auth.AndroidWatch.Version()
|
||||
seq := c.nextSeq()
|
||||
req := c.buildOicqRequestPacket(0, 0x0812, binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteHex(`0000620000001000000072000000`) // trans header
|
||||
@ -156,9 +178,18 @@ func (c *QQClient) buildQRCodeResultQueryRequestPacket(sig []byte) (uint16, []by
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -230,9 +261,16 @@ func (c *QQClient) buildQRCodeLoginPacket(t106, t16a, t318 []byte) (uint16, []by
|
||||
w.Write(wb)
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -243,12 +281,19 @@ func (c *QQClient) buildCaptchaPacket(result string, sign []byte) (uint16, []byt
|
||||
|
||||
w.Write(tlv.T2(result, sign))
|
||||
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))
|
||||
}))
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -258,15 +303,22 @@ func (c *QQClient) buildSMSRequestPacket() (uint16, []byte) {
|
||||
w.WriteUInt16(6)
|
||||
|
||||
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.T174(c.t174))
|
||||
w.Write(tlv.T174(c.sig.T174))
|
||||
w.Write(tlv.T17A(9))
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -276,16 +328,23 @@ func (c *QQClient) buildSMSCodeSubmitPacket(code string) (uint16, []byte) {
|
||||
w.WriteUInt16(7)
|
||||
|
||||
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.T174(c.t174))
|
||||
w.Write(tlv.T174(c.sig.T174))
|
||||
w.Write(tlv.T17C(code))
|
||||
w.Write(tlv.T401(c.g))
|
||||
w.Write(tlv.T401(c.sig.G))
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -296,12 +355,19 @@ func (c *QQClient) buildTicketSubmitPacket(ticket string) (uint16, []byte) {
|
||||
|
||||
w.Write(tlv.T193(ticket))
|
||||
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))
|
||||
}))
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -314,14 +380,14 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
w.Write(tlv.T1(uint32(c.Uin), c.deviceInfo.IpAddress))
|
||||
wb, cl := binary.OpenWriterF(func(bw *binary.Writer) {
|
||||
bw.WriteUInt16(0x106)
|
||||
bw.WriteBytesShort(c.sigInfo.EncryptedA1)
|
||||
bw.WriteBytesShort(c.sig.EncryptedA1)
|
||||
})
|
||||
w.Write(wb)
|
||||
cl()
|
||||
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.T108(c.ksid))
|
||||
w.Write(tlv.T108(c.sig.Ksid))
|
||||
w.Write(tlv.T144(
|
||||
c.deviceInfo.AndroidId,
|
||||
c.deviceInfo.GenDeviceInfoData(),
|
||||
@ -337,7 +403,7 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
))
|
||||
w.Write(tlv.T142(c.version.ApkId))
|
||||
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.T141(c.deviceInfo.SimInfo, c.deviceInfo.APN))
|
||||
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.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.T188(c.deviceInfo.AndroidId))
|
||||
w.Write(tlv.T194(c.deviceInfo.IMSIMd5))
|
||||
@ -363,23 +429,20 @@ func (c *QQClient) buildRequestTgtgtNopicsigPacket() (uint16, []byte) {
|
||||
oicq := codec.OICQ{
|
||||
Uin: uint32(c.Uin),
|
||||
Command: 0x810,
|
||||
EncryptMethod: crypto.NewEncryptSession(c.sigInfo.T133),
|
||||
Key: c.sigInfo.WtSessionTicketKey,
|
||||
EncryptMethod: crypto.NewEncryptSession(c.sig.T133),
|
||||
Key: c.sig.WtSessionTicketKey,
|
||||
Body: req,
|
||||
}
|
||||
|
||||
uni := codec.Uni{
|
||||
nreq := network.Request{
|
||||
Type: network.RequestTypeSimple,
|
||||
EncryptType: network.EncryptTypeEmptyKey,
|
||||
Uin: c.Uin,
|
||||
Seq: seq,
|
||||
SequenceID: int32(seq),
|
||||
CommandName: "wtlogin.exchange_emp",
|
||||
EncryptType: 2,
|
||||
SessionID: c.OutGoingPacketSessionId,
|
||||
ExtraData: EmptyBytes,
|
||||
Key: make([]byte, 16),
|
||||
Body: oicq.Encode(),
|
||||
}
|
||||
|
||||
return seq, uni.Encode()
|
||||
return seq, c.transport.PackPacket(&nreq)
|
||||
}
|
||||
|
||||
func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byte) {
|
||||
@ -389,10 +452,10 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt
|
||||
w.WriteUInt16(17)
|
||||
|
||||
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.T108(c.ksid))
|
||||
h := md5.Sum(c.sigInfo.D2Key)
|
||||
w.Write(tlv.T108(c.sig.Ksid))
|
||||
h := md5.Sum(c.sig.D2Key)
|
||||
w.Write(tlv.T144(
|
||||
c.deviceInfo.AndroidId,
|
||||
c.deviceInfo.GenDeviceInfoData(),
|
||||
@ -406,7 +469,7 @@ func (c *QQClient) buildRequestChangeSigPacket(mainSigMap uint32) (uint16, []byt
|
||||
c.deviceInfo.Brand,
|
||||
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.T154(seq))
|
||||
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))
|
||||
}))
|
||||
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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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
|
||||
@ -472,9 +542,16 @@ func (c *QQClient) buildClientRegisterPacket() (uint16, []byte) {
|
||||
Context: 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)
|
||||
return seq, packet
|
||||
|
||||
req2 := network.Request{
|
||||
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) {
|
||||
@ -766,7 +843,7 @@ func (c *QQClient) buildGroupMemberInfoRequestPacket(groupCode, uin int64) (uint
|
||||
|
||||
// MessageSvc.PbGetMsg
|
||||
func (c *QQClient) buildGetMessageRequestPacket(flag msg.SyncFlag, msgTime int64) (uint16, []byte) {
|
||||
cook := c.syncCookie
|
||||
cook := c.sig.SyncCookie
|
||||
if cook == nil {
|
||||
cook, _ = proto.Marshal(&msg.SyncCookie{
|
||||
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())),
|
||||
}
|
||||
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
|
||||
}
|
||||
*/
|
||||
|
@ -40,8 +40,8 @@ const (
|
||||
)
|
||||
|
||||
func (c *QQClient) c2cMessageSyncProcessor(rsp *msg.GetMessageResponse, info *network.IncomingPacketInfo) {
|
||||
c.syncCookie = rsp.SyncCookie
|
||||
c.pubAccountCookie = rsp.PubAccountCookie
|
||||
c.sig.SyncCookie = rsp.SyncCookie
|
||||
c.sig.PubAccountCookie = rsp.PubAccountCookie
|
||||
// c.msgCtrlBuf = rsp.MsgCtrlBuf
|
||||
if rsp.UinPairMsgs == nil {
|
||||
return
|
||||
|
132
client/client.go
132
client/client.go
@ -20,7 +20,6 @@ import (
|
||||
"github.com/Mrs4s/MiraiGo/client/internal/network"
|
||||
"github.com/Mrs4s/MiraiGo/client/pb/msg"
|
||||
"github.com/Mrs4s/MiraiGo/internal/crypto"
|
||||
"github.com/Mrs4s/MiraiGo/internal/packets"
|
||||
"github.com/Mrs4s/MiraiGo/utils"
|
||||
)
|
||||
|
||||
@ -48,11 +47,13 @@ type QQClient struct {
|
||||
GuildService *GuildService
|
||||
|
||||
// protocol public field
|
||||
SequenceId atomic.Int32
|
||||
OutGoingPacketSessionId []byte
|
||||
RandomKey []byte
|
||||
TCP *network.TCPListener // todo: combine other protocol state into one struct
|
||||
ConnectTime time.Time
|
||||
SequenceId atomic.Int32
|
||||
SessionId []byte
|
||||
RandomKey []byte
|
||||
TCP *network.TCPListener // todo: combine other protocol state into one struct
|
||||
ConnectTime time.Time
|
||||
|
||||
transport *network.Transport
|
||||
|
||||
// internal state
|
||||
handlers HandlerMap
|
||||
@ -65,29 +66,10 @@ type QQClient struct {
|
||||
alive bool
|
||||
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
|
||||
qwebSeq atomic.Int64
|
||||
sigInfo *auth.SigInfo
|
||||
sig *auth.SigInfo
|
||||
highwaySession *highway.Session
|
||||
dpwd []byte
|
||||
// pwdFlag bool
|
||||
// timeDiff int64
|
||||
|
||||
@ -176,22 +158,33 @@ func NewClientEmpty() *QQClient {
|
||||
|
||||
func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
|
||||
cli := &QQClient{
|
||||
Uin: uin,
|
||||
PasswordMd5: passwordMd5,
|
||||
AllowSlider: true,
|
||||
RandomKey: make([]byte, 16),
|
||||
OutGoingPacketSessionId: []byte{0x02, 0xB0, 0x5B, 0x8B},
|
||||
TCP: &network.TCPListener{},
|
||||
sigInfo: &auth.SigInfo{},
|
||||
eventHandlers: &eventHandlers{},
|
||||
msgSvcCache: utils.NewCache(time.Second * 15),
|
||||
transCache: utils.NewCache(time.Second * 15),
|
||||
onlinePushCache: utils.NewCache(time.Second * 15),
|
||||
servers: []*net.TCPAddr{},
|
||||
alive: true,
|
||||
ecdh: crypto.NewEcdh(),
|
||||
highwaySession: new(highway.Session),
|
||||
Uin: uin,
|
||||
PasswordMd5: passwordMd5,
|
||||
AllowSlider: true,
|
||||
RandomKey: make([]byte, 16),
|
||||
TCP: &network.TCPListener{},
|
||||
sig: &auth.SigInfo{
|
||||
OutPacketSessionID: []byte{0x02, 0xB0, 0x5B, 0x8B},
|
||||
},
|
||||
eventHandlers: &eventHandlers{},
|
||||
msgSvcCache: utils.NewCache(time.Second * 15),
|
||||
transCache: utils.NewCache(time.Second * 15),
|
||||
onlinePushCache: utils.NewCache(time.Second * 15),
|
||||
servers: []*net.TCPAddr{},
|
||||
alive: true,
|
||||
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
|
||||
cli.SequenceId.Store(0x3635)
|
||||
cli.requestPacketRequestID.Store(1921334513)
|
||||
@ -256,10 +249,10 @@ func NewClientMd5(uin int64, passwordMd5 [16]byte) *QQClient {
|
||||
}
|
||||
|
||||
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.ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI))
|
||||
c.deviceInfo = info
|
||||
c.sig.Ksid = []byte(fmt.Sprintf("|%s|A8.2.7.27f6ea96", info.IMEI))
|
||||
}
|
||||
|
||||
func (c *QQClient) Release() {
|
||||
@ -301,14 +294,14 @@ func (c *QQClient) TokenLogin(token []byte) error {
|
||||
{
|
||||
r := binary.NewReader(token)
|
||||
c.Uin = r.ReadInt64()
|
||||
c.sigInfo.D2 = r.ReadBytesShort()
|
||||
c.sigInfo.D2Key = r.ReadBytesShort()
|
||||
c.sigInfo.TGT = r.ReadBytesShort()
|
||||
c.sigInfo.SrmToken = r.ReadBytesShort()
|
||||
c.sigInfo.T133 = r.ReadBytesShort()
|
||||
c.sigInfo.EncryptedA1 = r.ReadBytesShort()
|
||||
c.sigInfo.WtSessionTicketKey = r.ReadBytesShort()
|
||||
c.OutGoingPacketSessionId = r.ReadBytesShort()
|
||||
c.sig.D2 = r.ReadBytesShort()
|
||||
c.sig.D2Key = r.ReadBytesShort()
|
||||
c.sig.TGT = r.ReadBytesShort()
|
||||
c.sig.SrmToken = r.ReadBytesShort()
|
||||
c.sig.T133 = r.ReadBytesShort()
|
||||
c.sig.EncryptedA1 = r.ReadBytesShort()
|
||||
c.sig.WtSessionTicketKey = r.ReadBytesShort()
|
||||
c.sig.OutPacketSessionID = r.ReadBytesShort()
|
||||
// SystemDeviceInfo.TgtgtKey = r.ReadBytesShort()
|
||||
c.deviceInfo.TgtgtKey = r.ReadBytesShort()
|
||||
}
|
||||
@ -406,7 +399,7 @@ func (c *QQClient) RequestSMS() bool {
|
||||
}
|
||||
|
||||
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.highwaySession.Uin = strconv.FormatInt(c.Uin, 10)
|
||||
@ -449,14 +442,14 @@ func (c *QQClient) init(tokenLogin bool) error {
|
||||
func (c *QQClient) GenToken() []byte {
|
||||
return binary.NewWriterF(func(w *binary.Writer) {
|
||||
w.WriteUInt64(uint64(c.Uin))
|
||||
w.WriteBytesShort(c.sigInfo.D2)
|
||||
w.WriteBytesShort(c.sigInfo.D2Key)
|
||||
w.WriteBytesShort(c.sigInfo.TGT)
|
||||
w.WriteBytesShort(c.sigInfo.SrmToken)
|
||||
w.WriteBytesShort(c.sigInfo.T133)
|
||||
w.WriteBytesShort(c.sigInfo.EncryptedA1)
|
||||
w.WriteBytesShort(c.sigInfo.WtSessionTicketKey)
|
||||
w.WriteBytesShort(c.OutGoingPacketSessionId)
|
||||
w.WriteBytesShort(c.sig.D2)
|
||||
w.WriteBytesShort(c.sig.D2Key)
|
||||
w.WriteBytesShort(c.sig.TGT)
|
||||
w.WriteBytesShort(c.sig.SrmToken)
|
||||
w.WriteBytesShort(c.sig.T133)
|
||||
w.WriteBytesShort(c.sig.EncryptedA1)
|
||||
w.WriteBytesShort(c.sig.WtSessionTicketKey)
|
||||
w.WriteBytesShort(c.sig.OutPacketSessionID)
|
||||
w.WriteBytesShort(c.deviceInfo.TgtgtKey)
|
||||
})
|
||||
}
|
||||
@ -681,11 +674,11 @@ func (c *QQClient) SolveFriendRequest(req *NewFriendRequest, accept bool) {
|
||||
}
|
||||
|
||||
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.sendAndWait(c.buildRequestTgtgtNopicsigPacket())
|
||||
}
|
||||
return string(c.sigInfo.SKey)
|
||||
return string(c.sig.SKey)
|
||||
}
|
||||
|
||||
func (c *QQClient) getCookies() string {
|
||||
@ -695,7 +688,7 @@ func (c *QQClient) getCookies() string {
|
||||
func (c *QQClient) getCookiesWithDomain(domain string) string {
|
||||
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)
|
||||
} else {
|
||||
return cookie
|
||||
@ -800,8 +793,15 @@ func (c *QQClient) doHeartbeat() {
|
||||
for c.Online.Load() {
|
||||
time.Sleep(time.Second * 30)
|
||||
seq := c.nextSeq()
|
||||
sso := packets.BuildSsoPacket(seq, c.version.AppId, c.version.SubAppId, "Heartbeat.Alive", c.deviceInfo.IMEI, EmptyBytes, c.OutGoingPacketSessionId, EmptyBytes, c.ksid)
|
||||
packet := packets.BuildLoginPacket(c.Uin, 0, EmptyBytes, sso, EmptyBytes)
|
||||
req := network.Request{
|
||||
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)
|
||||
if errors.Is(err, network.ErrConnectionClosed) {
|
||||
continue
|
||||
|
@ -39,10 +39,10 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
reader.ReadUInt16()
|
||||
m := reader.ReadTlvMap(2)
|
||||
if m.Exists(0x402) {
|
||||
c.dpwd = []byte(utils.RandomString(16))
|
||||
c.t402 = m[0x402]
|
||||
h := md5.Sum(append(append(c.deviceInfo.Guid, c.dpwd...), c.t402...))
|
||||
c.g = h[:]
|
||||
c.sig.Dpwd = []byte(utils.RandomString(16))
|
||||
c.sig.T402 = m[0x402]
|
||||
h := md5.Sum(append(append(c.deviceInfo.Guid, c.sig.Dpwd...), c.sig.T402...))
|
||||
c.sig.G = h[:]
|
||||
}
|
||||
if t == 0 { // login success
|
||||
// if t150, ok := m[0x150]; ok {
|
||||
@ -52,7 +52,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
c.decodeT161(t161)
|
||||
}
|
||||
if m.Exists(0x403) {
|
||||
c.randSeed = m[0x403]
|
||||
c.sig.RandSeed = m[0x403]
|
||||
}
|
||||
c.decodeT119(m[0x119], c.deviceInfo.TgtgtKey)
|
||||
return LoginResponse{
|
||||
@ -60,7 +60,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
}, nil
|
||||
}
|
||||
if t == 2 {
|
||||
c.t104 = m[0x104]
|
||||
c.sig.T104 = m[0x104]
|
||||
if m.Exists(0x192) {
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
@ -97,9 +97,9 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
|
||||
if t == 160 || t == 239 {
|
||||
if t174, ok := m[0x174]; ok { // 短信验证
|
||||
c.t104 = m[0x104]
|
||||
c.t174 = t174
|
||||
c.randSeed = m[0x403]
|
||||
c.sig.T104 = m[0x104]
|
||||
c.sig.T174 = t174
|
||||
c.sig.RandSeed = m[0x403]
|
||||
phone := func() string {
|
||||
r := binary.NewReader(m[0x178])
|
||||
return r.ReadStringLimit(int(r.ReadInt32()))
|
||||
@ -122,7 +122,7 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
}
|
||||
|
||||
if _, ok := m[0x17b]; ok { // 二次验证
|
||||
c.t104 = m[0x104]
|
||||
c.sig.T104 = m[0x104]
|
||||
return LoginResponse{
|
||||
Success: false,
|
||||
Error: SMSNeededError,
|
||||
@ -146,8 +146,8 @@ func decodeLoginResponse(c *QQClient, _ *network.IncomingPacketInfo, payload []b
|
||||
}
|
||||
|
||||
if t == 204 {
|
||||
c.t104 = m[0x104]
|
||||
c.randSeed = m[0x403]
|
||||
c.sig.T104 = m[0x104]
|
||||
c.sig.RandSeed = m[0x403]
|
||||
return c.sendAndWait(c.buildDeviceLockLoginPacket())
|
||||
} // drive lock
|
||||
|
||||
@ -210,7 +210,7 @@ func decodeExchangeEmpResponse(c *QQClient, _ *network.IncomingPacketInfo, paylo
|
||||
c.decodeT119R(m[0x119])
|
||||
}
|
||||
if cmd == 11 {
|
||||
h := md5.Sum(c.sigInfo.D2Key)
|
||||
h := md5.Sum(c.sig.D2Key)
|
||||
c.decodeT119(m[0x119], h[:])
|
||||
}
|
||||
return nil, nil
|
||||
|
@ -663,7 +663,7 @@ func (s *GuildService) fetchChannelListState(guildId uint64, channels []*Channel
|
||||
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)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -127,4 +127,26 @@ type SigInfo struct {
|
||||
|
||||
PsKeyMap 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
|
||||
}
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
@ -22,6 +22,6 @@ type Request struct {
|
||||
EncryptType EncryptType
|
||||
SequenceID int32
|
||||
Uin int64
|
||||
Method string
|
||||
CommandName string
|
||||
Body []byte
|
||||
}
|
||||
|
@ -11,95 +11,96 @@ import (
|
||||
// Transport is a network transport.
|
||||
type Transport struct {
|
||||
sessionMu sync.Mutex
|
||||
// todo: combine session fields to a struct
|
||||
tgt []byte
|
||||
d2key []byte
|
||||
sessionID []byte
|
||||
ksid []byte
|
||||
|
||||
version *auth.AppVersion
|
||||
device *auth.Device
|
||||
Sig *auth.SigInfo
|
||||
Version *auth.AppVersion
|
||||
Device *auth.Device
|
||||
|
||||
// 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) {
|
||||
if req.Type == RequestTypeLogin {
|
||||
writer.WriteUInt32(uint32(req.SequenceID))
|
||||
writer.WriteUInt32(t.version.AppId)
|
||||
writer.WriteUInt32(t.version.SubAppId)
|
||||
writer.WriteUInt32(t.Version.AppId)
|
||||
writer.WriteUInt32(t.Version.SubAppId)
|
||||
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)
|
||||
} else {
|
||||
writer.WriteUInt32(uint32(len(t.tgt) + 4))
|
||||
writer.Write(t.tgt)
|
||||
writer.WriteUInt32(uint32(len(tgt) + 4))
|
||||
writer.Write(tgt)
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteString(req.Method)
|
||||
writer.WriteUInt32(uint32(len(t.sessionID) + 4))
|
||||
w.Write(t.sessionID)
|
||||
writer.WriteString(req.CommandName)
|
||||
writer.WriteIntLvPacket(4, func(w *binary.Writer) {
|
||||
w.Write(t.Sig.OutPacketSessionID)
|
||||
})
|
||||
// writer.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4))
|
||||
// w.Write(t.Sig.OutPacketSessionID)
|
||||
if req.Type == RequestTypeLogin {
|
||||
writer.WriteString(t.device.IMEI)
|
||||
writer.WriteString(t.Device.IMEI)
|
||||
writer.WriteUInt32(0x04)
|
||||
{
|
||||
writer.WriteUInt16(uint16(len(t.ksid)) + 2)
|
||||
writer.Write(t.ksid)
|
||||
writer.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2)
|
||||
writer.Write(t.Sig.Ksid)
|
||||
}
|
||||
}
|
||||
writer.WriteUInt32(0x04)
|
||||
})
|
||||
|
||||
w.WriteUInt32(uint32(len(req.Body) + 4))
|
||||
w.Write(req.Body)
|
||||
w.WriteIntLvPacket(4, func(w *binary.Writer) {
|
||||
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 {
|
||||
// todo: return response
|
||||
// PackPacket packs a packet.
|
||||
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) {
|
||||
w.WriteUInt32(uint32(req.Type))
|
||||
w.WriteUInt32(uint32(req.EncryptType))
|
||||
w.WriteByte(byte(req.EncryptType))
|
||||
switch req.Type {
|
||||
case RequestTypeLogin:
|
||||
switch req.EncryptType {
|
||||
case EncryptTypeD2Key:
|
||||
w.WriteUInt32(uint32(len(t.d2key) + 4))
|
||||
w.Write(t.d2key)
|
||||
w.WriteUInt32(uint32(len(t.Sig.D2) + 4))
|
||||
w.Write(t.Sig.D2)
|
||||
default:
|
||||
w.WriteUInt32(4)
|
||||
}
|
||||
case RequestTypeSimple:
|
||||
w.WriteUInt32(uint32(req.SequenceID))
|
||||
}
|
||||
w.WriteByte(0x00)
|
||||
w.WriteString(strconv.FormatInt(req.Uin, 10))
|
||||
})
|
||||
|
||||
w := binary.SelectWriter()
|
||||
defer binary.PutWriter(w)
|
||||
t.packBody(req, w)
|
||||
body := w.Bytes()
|
||||
|
||||
// encrypt body
|
||||
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
|
||||
w.WriteUInt32(uint32(len(head)+len(body)) + 4)
|
||||
w.Write(head)
|
||||
w.Write(body)
|
||||
return append([]byte(nil), w.Bytes()...) // copy
|
||||
}
|
||||
|
||||
func (t *Transport) parse(head []byte) *Request {
|
||||
@ -119,7 +120,7 @@ func (t *Transport) parse(head []byte) *Request {
|
||||
case EncryptTypeNoEncrypt:
|
||||
req.Body = body
|
||||
case EncryptTypeD2Key:
|
||||
req.Body = binary.NewTeaCipher(t.d2key).Decrypt(body)
|
||||
req.Body = binary.NewTeaCipher(t.Sig.D2Key).Decrypt(body)
|
||||
case EncryptTypeEmptyKey:
|
||||
req.Body = binary.NewTeaCipher(emptyKey).Decrypt(body)
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ type (
|
||||
)
|
||||
|
||||
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
|
||||
for _, b := range psKey {
|
||||
accu = accu + (accu << 5) + int(b)
|
||||
|
@ -291,7 +291,7 @@ func (c *QQClient) netLoop() {
|
||||
continue
|
||||
}
|
||||
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 {
|
||||
c.Error("parse incoming packet error: %v", err)
|
||||
if errors.Is(err, packets.ErrSessionExpired) || errors.Is(err, packets.ErrPacketDropped) {
|
||||
@ -306,7 +306,7 @@ func (c *QQClient) netLoop() {
|
||||
continue
|
||||
}
|
||||
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 {
|
||||
c.Error("decrypt payload error: %v", err)
|
||||
if errors.Is(err, packets.ErrUnknownFlag) {
|
||||
|
@ -2,6 +2,7 @@ package client
|
||||
|
||||
import (
|
||||
"github.com/Mrs4s/MiraiGo/client/internal/codec"
|
||||
"github.com/Mrs4s/MiraiGo/client/internal/network"
|
||||
)
|
||||
|
||||
//go:noinline
|
||||
@ -19,30 +20,26 @@ func (c *QQClient) buildOicqRequestPacket(uin int64, command uint16, body []byte
|
||||
//go:noinline
|
||||
func (c *QQClient) uniPacket(command string, body []byte) (uint16, []byte) {
|
||||
seq := c.nextSeq()
|
||||
req := codec.Uni{
|
||||
req := network.Request{
|
||||
Type: network.RequestTypeSimple,
|
||||
EncryptType: network.EncryptTypeD2Key,
|
||||
Uin: c.Uin,
|
||||
Seq: seq,
|
||||
SequenceID: int32(seq),
|
||||
CommandName: command,
|
||||
EncryptType: 1,
|
||||
SessionID: c.OutGoingPacketSessionId,
|
||||
ExtraData: EmptyBytes,
|
||||
Key: c.sigInfo.D2Key,
|
||||
Body: body,
|
||||
}
|
||||
return seq, req.Encode()
|
||||
return seq, c.transport.PackPacket(&req)
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
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,
|
||||
Seq: seq,
|
||||
SequenceID: int32(seq),
|
||||
CommandName: command,
|
||||
EncryptType: 1,
|
||||
SessionID: c.OutGoingPacketSessionId,
|
||||
ExtraData: EmptyBytes,
|
||||
Key: c.sigInfo.D2Key,
|
||||
Body: body,
|
||||
}
|
||||
return req.Encode()
|
||||
return c.transport.PackPacket(&req)
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ func (c *QQClient) buildGetOneDayRoamMsgRequest(target, lastMsgTime, random int6
|
||||
ReadCnt: &count,
|
||||
}
|
||||
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
|
||||
}
|
||||
*/
|
||||
|
@ -157,11 +157,11 @@ func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) {
|
||||
Channel: 4,
|
||||
Inst: 1,
|
||||
ChannelEx: 1,
|
||||
SyncCookie: c.syncCookie,
|
||||
SyncCookie: c.sig.SyncCookie,
|
||||
SyncFlag: 0, // START
|
||||
RambleFlag: 0,
|
||||
GeneralAbi: 1,
|
||||
PubAccountCookie: c.pubAccountCookie,
|
||||
PubAccountCookie: c.sig.PubAccountCookie,
|
||||
},
|
||||
GroupMsg: &jce.SvcReqPullGroupMsgSeq{
|
||||
VerifyType: 0,
|
||||
@ -172,7 +172,7 @@ func (c *QQClient) buildGetOfflineMsgRequestPacket() (uint16, []byte) {
|
||||
flag := msg.SyncFlag_START
|
||||
msgReq, _ := proto.Marshal(&msg.GetMessageRequest{
|
||||
SyncFlag: &flag,
|
||||
SyncCookie: c.syncCookie,
|
||||
SyncCookie: c.sig.SyncCookie,
|
||||
RambleFlag: proto.Int32(0),
|
||||
ContextFlag: proto.Int32(1),
|
||||
OnlineSyncFlag: proto.Int32(0),
|
||||
@ -224,11 +224,11 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
|
||||
Channel: 4,
|
||||
Inst: 1,
|
||||
ChannelEx: 1,
|
||||
SyncCookie: c.syncCookie,
|
||||
SyncCookie: c.sig.SyncCookie,
|
||||
SyncFlag: 0, // START
|
||||
RambleFlag: 0,
|
||||
GeneralAbi: 1,
|
||||
PubAccountCookie: c.pubAccountCookie,
|
||||
PubAccountCookie: c.sig.PubAccountCookie,
|
||||
},
|
||||
GroupMask: 2,
|
||||
EndSeq: int64(rand.Uint32()),
|
||||
@ -237,7 +237,7 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
|
||||
flag := msg.SyncFlag_START
|
||||
msgReq := &msg.GetMessageRequest{
|
||||
SyncFlag: &flag,
|
||||
SyncCookie: c.syncCookie,
|
||||
SyncCookie: c.sig.SyncCookie,
|
||||
RambleFlag: proto.Int32(0),
|
||||
ContextFlag: proto.Int32(1),
|
||||
OnlineSyncFlag: proto.Int32(0),
|
||||
@ -248,7 +248,7 @@ func (c *QQClient) buildSyncMsgRequestPacket() (uint16, []byte) {
|
||||
offMsg, _ := proto.Marshal(msgReq)
|
||||
msgReq.MsgReqType = proto.Int32(2)
|
||||
msgReq.SyncCookie = nil
|
||||
msgReq.PubaccountCookie = c.pubAccountCookie
|
||||
msgReq.PubaccountCookie = c.sig.PubAccountCookie
|
||||
pubMsg, _ := proto.Marshal(msgReq)
|
||||
buf := &jce.RequestDataVersion3{Map: map[string][]byte{
|
||||
"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)),
|
||||
LastReadTime: proto.Uint32(uint32(time)),
|
||||
},
|
||||
}, SyncCookie: c.syncCookie}})
|
||||
}, SyncCookie: c.sig.SyncCookie}})
|
||||
return c.uniPacket("PbMessageSvc.PbMsgReadedReport", req)
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Mrs4s/MiraiGo/client/internal/auth"
|
||||
"github.com/Mrs4s/MiraiGo/utils"
|
||||
|
||||
"github.com/Mrs4s/MiraiGo/binary"
|
||||
@ -44,7 +43,7 @@ func (c *QQClient) decodeT119(data, ek []byte) {
|
||||
}
|
||||
*/
|
||||
if t108, ok := m[0x108]; ok {
|
||||
c.ksid = t108
|
||||
c.sig.Ksid = t108
|
||||
}
|
||||
|
||||
var (
|
||||
@ -91,29 +90,28 @@ func (c *QQClient) decodeT119(data, ek []byte) {
|
||||
}
|
||||
|
||||
// we don't use `c.sigInfo = &auth.SigInfo{...}` here,
|
||||
// because we need spread `SigInfo` to other places
|
||||
*c.sigInfo = auth.SigInfo{
|
||||
LoginBitmap: 0,
|
||||
SrmToken: utils.Select(m[0x16a], c.sigInfo.SrmToken),
|
||||
T133: utils.Select(m[0x133], c.sigInfo.T133),
|
||||
EncryptedA1: utils.Select(m[0x106], c.sigInfo.EncryptedA1),
|
||||
TGT: m[0x10a],
|
||||
TGTKey: m[0x10d],
|
||||
UserStKey: m[0x10e],
|
||||
UserStWebSig: m[0x103],
|
||||
SKey: m[0x120],
|
||||
SKeyExpiredTime: time.Now().Unix() + 21600,
|
||||
D2: m[0x143],
|
||||
D2Key: m[0x305],
|
||||
WtSessionTicketKey: utils.Select(m[0x134], c.sigInfo.WtSessionTicketKey),
|
||||
DeviceToken: m[0x322],
|
||||
// because we need keep other fields in `c.sigInfo`
|
||||
s := c.sig
|
||||
s.LoginBitmap = 0
|
||||
s.SrmToken = utils.Select(m[0x16a], s.SrmToken)
|
||||
s.T133 = utils.Select(m[0x133], s.T133)
|
||||
s.EncryptedA1 = utils.Select(m[0x106], s.EncryptedA1)
|
||||
s.TGT = m[0x10a]
|
||||
s.TGTKey = m[0x10d]
|
||||
s.UserStKey = m[0x10e]
|
||||
s.UserStWebSig = m[0x103]
|
||||
s.SKey = m[0x120]
|
||||
s.SKeyExpiredTime = time.Now().Unix() + 21600
|
||||
s.D2 = m[0x143]
|
||||
s.D2Key = m[0x305]
|
||||
s.WtSessionTicketKey = utils.Select(m[0x134], s.WtSessionTicketKey)
|
||||
s.DeviceToken = m[0x322]
|
||||
|
||||
PsKeyMap: psKeyMap,
|
||||
Pt4TokenMap: pt4TokenMap,
|
||||
}
|
||||
s.PsKeyMap = psKeyMap
|
||||
s.Pt4TokenMap = pt4TokenMap
|
||||
if len(c.PasswordMd5[:]) > 0 {
|
||||
key := md5.Sum(append(append(c.PasswordMd5[:], []byte{0x00, 0x00, 0x00, 0x00}...), binary.NewWriterF(func(w *binary.Writer) { w.WriteUInt32(uint32(c.Uin)) })...))
|
||||
decrypted := binary.NewTeaCipher(key[:]).Decrypt(c.sigInfo.EncryptedA1)
|
||||
decrypted := binary.NewTeaCipher(key[:]).Decrypt(c.sig.EncryptedA1)
|
||||
if len(decrypted) > 51+16 {
|
||||
dr := binary.NewReader(decrypted)
|
||||
dr.ReadBytes(51)
|
||||
@ -132,9 +130,9 @@ func (c *QQClient) decodeT119R(data []byte) {
|
||||
reader.ReadBytes(2)
|
||||
m := reader.ReadTlvMap(2)
|
||||
if t120, ok := m[0x120]; ok {
|
||||
c.sigInfo.SKey = t120
|
||||
c.sigInfo.SKeyExpiredTime = time.Now().Unix() + 21600
|
||||
c.Debug("skey updated: %v", c.sigInfo.SKey)
|
||||
c.sig.SKey = t120
|
||||
c.sig.SKeyExpiredTime = time.Now().Unix() + 21600
|
||||
c.Debug("skey updated: %v", c.sig.SKey)
|
||||
}
|
||||
if t11a, ok := m[0x11a]; ok {
|
||||
c.Nickname, c.Age, c.Gender = readT11A(t11a)
|
||||
|
@ -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)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
@ -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) {
|
||||
if len(payload) < 6 {
|
||||
return nil, errors.WithStack(ErrInvalidPayload)
|
||||
|
Loading…
x
Reference in New Issue
Block a user