github.com/Mrs4s/MiraiGo@v0.0.0-20240226124653-54bdd873e3fe/client/internal/network/transport.go (about)

     1  package network
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	"github.com/Mrs4s/MiraiGo/binary"
     8  	"github.com/Mrs4s/MiraiGo/client/internal/auth"
     9  	"github.com/Mrs4s/MiraiGo/client/pb"
    10  	"github.com/Mrs4s/MiraiGo/internal/proto"
    11  	"github.com/Mrs4s/MiraiGo/wrapper"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // Transport is a network transport.
    16  type Transport struct {
    17  	Sig     *auth.SigInfo
    18  	Version *auth.AppVersion
    19  	Device  *auth.Device
    20  
    21  	// connection
    22  	// conn *TCPClient
    23  }
    24  
    25  var WhiteListCommands = `
    26  ConnAuthSvr.fast_qq_login
    27  ConnAuthSvr.sdk_auth_api
    28  ConnAuthSvr.sdk_auth_api_emp
    29  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoBarrage
    30  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoComment
    31  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoFollow
    32  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoLike
    33  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoPush
    34  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.DoReply
    35  FeedCloudSvr.trpc.feedcloud.commwriter.ComWriter.PublishFeed
    36  FeedCloudSvr.trpc.videocircle.circleprofile.CircleProfile.SetProfile
    37  friendlist.addFriend
    38  friendlist.AddFriendReq
    39  friendlist.ModifyGroupInfoReq
    40  MessageSvc.PbSendMsg
    41  MsgProxy.SendMsg
    42  OidbSvc.0x4ff_9
    43  OidbSvc.0x4ff_9_IMCore
    44  OidbSvc.0x56c_6
    45  OidbSvc.0x6d9_4
    46  OidbSvc.0x758
    47  OidbSvc.0x758_0
    48  OidbSvc.0x758_1
    49  OidbSvc.0x88d_0
    50  OidbSvc.0x89a_0
    51  OidbSvc.0x89b_1
    52  OidbSvc.0x8a1_0
    53  OidbSvc.0x8a1_7
    54  OidbSvc.0x8ba
    55  OidbSvc.0x9fa
    56  OidbSvc.oidb_0x758
    57  OidbSvcTrpcTcp.0x101e_1
    58  OidbSvcTrpcTcp.0x101e_2
    59  OidbSvcTrpcTcp.0x1100_1
    60  OidbSvcTrpcTcp.0x1105_1
    61  OidbSvcTrpcTcp.0x1107_1
    62  OidbSvcTrpcTcp.0x55f_0
    63  OidbSvcTrpcTcp.0x6d9_4
    64  OidbSvcTrpcTcp.0xf55_1
    65  OidbSvcTrpcTcp.0xf57_1
    66  OidbSvcTrpcTcp.0xf57_106
    67  OidbSvcTrpcTcp.0xf57_9
    68  OidbSvcTrpcTcp.0xf65_1
    69  OidbSvcTrpcTcp.0xf65_10 
    70  OidbSvcTrpcTcp.0xf67_1
    71  OidbSvcTrpcTcp.0xf67_5
    72  OidbSvcTrpcTcp.0xf6e_1
    73  OidbSvcTrpcTcp.0xf88_1
    74  OidbSvcTrpcTcp.0xf89_1
    75  OidbSvcTrpcTcp.0xfa5_1
    76  ProfileService.getGroupInfoReq
    77  ProfileService.GroupMngReq
    78  QChannelSvr.trpc.qchannel.commwriter.ComWriter.DoComment
    79  QChannelSvr.trpc.qchannel.commwriter.ComWriter.DoReply
    80  QChannelSvr.trpc.qchannel.commwriter.ComWriter.PublishFeed
    81  qidianservice.135
    82  qidianservice.207
    83  qidianservice.269
    84  qidianservice.290
    85  SQQzoneSvc.addComment
    86  SQQzoneSvc.addReply
    87  SQQzoneSvc.forward
    88  SQQzoneSvc.like
    89  SQQzoneSvc.publishmood
    90  SQQzoneSvc.shuoshuo
    91  trpc.group_pro.msgproxy.sendmsg
    92  trpc.login.ecdh.EcdhService.SsoNTLoginPasswordLoginUnusualDevice
    93  trpc.o3.ecdh_access.EcdhAccess.SsoEstablishShareKey
    94  trpc.o3.ecdh_access.EcdhAccess.SsoSecureA2Access
    95  trpc.o3.ecdh_access.EcdhAccess.SsoSecureA2Establish
    96  trpc.o3.ecdh_access.EcdhAccess.SsoSecureAccess
    97  trpc.o3.report.Report.SsoReport
    98  trpc.passwd.manager.PasswdManager.SetPasswd
    99  trpc.passwd.manager.PasswdManager.VerifyPasswd
   100  trpc.qlive.relationchain_svr.RelationchainSvr.Follow
   101  trpc.qlive.word_svr.WordSvr.NewPublicChat
   102  trpc.qqhb.qqhb_proxy.Handler.sso_handle
   103  trpc.springfestival.redpacket.LuckyBag.SsoSubmitGrade
   104  wtlogin.device_lock
   105  wtlogin.exchange_emp
   106  wtlogin.login
   107  wtlogin.name2uin
   108  wtlogin.qrlogin
   109  wtlogin.register
   110  wtlogin.trans_emp
   111  wtlogin_device.login
   112  wtlogin_device.tran_sim_emp
   113  `
   114  
   115  func (t *Transport) packBody(req *Request, w *binary.Writer) {
   116  	pos := w.FillUInt32()
   117  	if req.Type == RequestTypeLogin {
   118  		w.WriteUInt32(uint32(req.SequenceID))
   119  		w.WriteUInt32(t.Version.AppId)
   120  		w.WriteUInt32(t.Version.SubAppId)
   121  		w.Write([]byte{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00})
   122  		tgt := t.Sig.TGT
   123  		if len(tgt) == 0 || len(tgt) == 4 {
   124  			w.WriteUInt32(0x04)
   125  		} else {
   126  			w.WriteUInt32(uint32(len(tgt) + 4))
   127  			w.Write(tgt)
   128  		}
   129  	}
   130  	w.WriteString(req.CommandName)
   131  	w.WriteUInt32(uint32(len(t.Sig.OutPacketSessionID) + 4))
   132  	w.Write(t.Sig.OutPacketSessionID)
   133  	if req.Type == RequestTypeLogin {
   134  		w.WriteString((*t.Device).IMEI)
   135  		w.WriteUInt32(0x04)
   136  
   137  		w.WriteUInt16(uint16(len(t.Sig.Ksid)) + 2)
   138  		w.Write(t.Sig.Ksid)
   139  	}
   140  	if strings.Contains(WhiteListCommands, req.CommandName) {
   141  		secSign := t.PackSecSign(req)
   142  		w.WriteUInt32(uint32(len(secSign) + 4))
   143  		w.Write(secSign)
   144  	}
   145  
   146  	w.WriteUInt32(0x04 + uint32(len(t.Device.QImei16)))
   147  	w.Write([]byte(t.Device.QImei16))
   148  
   149  	w.WriteUInt32At(pos, uint32(w.Len()-pos))
   150  
   151  	w.WriteUInt32(uint32(len(req.Body) + 4))
   152  	w.Write(req.Body)
   153  }
   154  
   155  func (t *Transport) PackSecSign(req *Request) []byte {
   156  	if wrapper.FekitGetSign == nil {
   157  		return []byte{}
   158  	}
   159  	sign, extra, token, err := wrapper.FekitGetSign(uint64(req.SequenceID), strconv.FormatInt(req.Uin, 10), req.CommandName, t.Version.QUA, req.Body)
   160  	if err != nil {
   161  		return []byte{}
   162  	}
   163  	m := &pb.SSOReserveField{
   164  		Flag:        0,
   165  		Qimei:       t.Device.QImei16,
   166  		NewconnFlag: 0,
   167  		Uid:         strconv.FormatInt(req.Uin, 10),
   168  		Imsi:        0,
   169  		NetworkType: 1,
   170  		IpStackType: 1,
   171  		MessageType: 0,
   172  		SecInfo: &pb.SsoSecureInfo{
   173  			SecSig:         sign,
   174  			SecDeviceToken: token,
   175  			SecExtra:       extra,
   176  		},
   177  		SsoIpOrigin: 0,
   178  	}
   179  	data, err := proto.Marshal(m)
   180  	if err != nil {
   181  		panic(errors.Wrap(err, "failed to unmarshal protobuf SSOReserveField"))
   182  	}
   183  	return data
   184  }
   185  
   186  // PackPacket packs a packet.
   187  func (t *Transport) PackPacket(req *Request) []byte {
   188  	// todo(wdvxdr): combine pack packet, send packet and return the response
   189  	if len(t.Sig.D2) == 0 {
   190  		req.EncryptType = EncryptTypeEmptyKey
   191  	}
   192  
   193  	w := binary.SelectWriter()
   194  	defer binary.PutWriter(w)
   195  
   196  	pos := w.FillUInt32()
   197  	// vvv w.Write(head) vvv
   198  	w.WriteUInt32(uint32(req.Type))
   199  	w.WriteByte(byte(req.EncryptType))
   200  	switch req.Type {
   201  	case RequestTypeLogin:
   202  		switch req.EncryptType {
   203  		case EncryptTypeD2Key:
   204  			w.WriteUInt32(uint32(len(t.Sig.D2) + 4))
   205  			w.Write(t.Sig.D2)
   206  		default:
   207  			w.WriteUInt32(4)
   208  		}
   209  	case RequestTypeSimple:
   210  		w.WriteUInt32(uint32(req.SequenceID))
   211  	}
   212  	w.WriteByte(0x00)
   213  	w.WriteString(strconv.FormatInt(req.Uin, 10))
   214  	// ^^^ w.Write(head) ^^^
   215  
   216  	w2 := binary.SelectWriter()
   217  	t.packBody(req, w2)
   218  	body := w2.Bytes()
   219  	// encrypt body
   220  	switch req.EncryptType {
   221  	case EncryptTypeD2Key:
   222  		body = binary.NewTeaCipher(t.Sig.D2Key).Encrypt(body)
   223  	case EncryptTypeEmptyKey:
   224  		emptyKey := make([]byte, 16)
   225  		body = binary.NewTeaCipher(emptyKey).Encrypt(body)
   226  	}
   227  	w.Write(body)
   228  	binary.PutWriter(w2)
   229  
   230  	w.WriteUInt32At(pos, uint32(w.Len()))
   231  	return append([]byte(nil), w.Bytes()...)
   232  }