package clientsdk import ( "fmt" "strconv" "strings" "time" "xiawan/wx/clientsdk/android/mmproto" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/clientsdk/baseutils" "xiawan/wx/clientsdk/cecdh" "xiawan/wx/clientsdk/extinfo" clientsdk "xiawan/wx/clientsdk/hybrid" "xiawan/wx/clientsdk/mmtls" "xiawan/wx/protobuf/wechat" "github.com/gogo/protobuf/proto" "github.com/lunny/log" ) type SecLoginKeyMgr struct { WeChatPubKeyVersion byte WeChatPubKey string `json:"-"` SourceData []byte `json:"-"` PriKey []byte `json:"-"` PubKey []byte `json:"-"` FinalSha256 []byte `json:"-"` } func (Sec *SecLoginKeyMgr) Reset() { Sec.PubKey = []byte{} Sec.PriKey = []byte{} Sec.FinalSha256 = []byte{} Sec.SourceData = []byte{} } func (Sec *SecLoginKeyMgr) SetKey() { if 146 == Sec.WeChatPubKeyVersion { Sec.WeChatPubKeyVersion = 145 Sec.WeChatPubKey = clientsdk.WeChatPubKey_145 } else { Sec.WeChatPubKeyVersion = 146 Sec.WeChatPubKey = clientsdk.WeChatPubKey_146 } } func NewSecLoginKeyMgrByVer(ver byte) *SecLoginKeyMgr { sec := &SecLoginKeyMgr{} switch ver { case 146: sec.WeChatPubKeyVersion = 146 sec.WeChatPubKey = clientsdk.WeChatPubKey_146 break case 145: sec.WeChatPubKeyVersion = 145 sec.WeChatPubKey = clientsdk.WeChatPubKey_145 break } return sec } func NewSecLoginKeyMgr() *SecLoginKeyMgr { return &SecLoginKeyMgr{ WeChatPubKeyVersion: 146, WeChatPubKey: clientsdk.WeChatPubKey_146, } } // GetManualAuthAccountProtobuf 组用户登录基本信息 func GetManualAuthRsaReqDataProtobuf(userInfo *baseinfo.UserInfo, wxid string, newpass string) *wechat.ManualAuthRsaReqData { var tmpNid uint32 = 713 userInfo.EcPublicKey, userInfo.EcPrivateKey = cecdh.GenerateEccKey() authRequest := &wechat.ManualAuthRsaReqData{} // aes_key var aesKey wechat.SKBuiltinString_ var tmpAesKeyLen uint32 = 16 aesKey.Len = &tmpAesKeyLen aesKey.Buffer = []byte(userInfo.SessionKey) authRequest.RandomEncryKey = &aesKey // 其它参数 var ecdhKey wechat.ECDHKey var key wechat.SKBuiltinString_ key.Buffer = userInfo.EcPublicKey var tmpLen = (uint32)(len(userInfo.EcPublicKey)) key.Len = &tmpLen ecdhKey.Nid = &tmpNid ecdhKey.Key = &key authRequest.CliPubEcdhkey = &ecdhKey authRequest.UserName = &wxid //判断是否为iPad登录的伪密码 if !strings.HasPrefix(newpass, "extdevnewpwd_") && !strings.HasPrefix(newpass, "strdm@") { newpass = baseutils.Md5Value(newpass) } authRequest.Pwd = &newpass return authRequest } // GetManualAuthAesReqProtobuf 生成自动登陆aesreq项 func GetManualAuthAesReqDataProtobuf(userInfo *baseinfo.UserInfo) *wechat.ManualAuthAesReqData { if userInfo.DeviceInfoA16 != nil { return GetManualAuthAesReqDataProtobufA16(userInfo) } zeroUint32 := uint32(0) zeroInt32 := int32(0) emptyString := string("") var aesRequest wechat.ManualAuthAesReqData // BaseRequest baseReq := GetBaseRequest(userInfo) var tmpScene uint32 = 1 baseReq.Scene = &tmpScene baseReq.SessionKey = []byte{} aesRequest.BaseRequest = baseReq inputType := uint32(2) aesRequest.InputType = &inputType if userInfo.Ticket != "" { aesRequest.BaseReqInfo = &wechat.BaseAuthReqInfo{ AuthTicket: proto.String(userInfo.Ticket), } aesRequest.InputType = proto.Uint32(1) } // imei aesRequest.Imei = &userInfo.DeviceInfo.Imei aesRequest.TimeZone = &userInfo.DeviceInfo.TimeZone aesRequest.DeviceName = &userInfo.DeviceInfo.DeviceName aesRequest.DeviceType = &userInfo.DeviceInfo.DeviceName aesRequest.Channel = &zeroInt32 aesRequest.Language = &userInfo.DeviceInfo.Language aesRequest.BuiltinIpseq = &zeroUint32 aesRequest.Signature = &emptyString aesRequest.SoftType = &userInfo.DeviceInfo.SoftTypeXML aesRequest.DeviceBrand = &userInfo.DeviceInfo.DeviceBrand aesRequest.RealCountry = &userInfo.DeviceInfo.RealCountry aesRequest.BundleId = &userInfo.DeviceInfo.BundleID aesRequest.AdSource = &userInfo.DeviceInfo.AdSource // ClientSeqId tmpTime := int(time.Now().UnixNano() / 1000000000) tmpTimeStr := strconv.Itoa(tmpTime) var strClientSeqID = string(userInfo.DeviceInfo.Imei + "-" + tmpTimeStr) aesRequest.ClientSeqId = &strClientSeqID // TimeStamp tmpTime2 := uint32(time.Now().UnixNano() / 1000000000) aesRequest.TimeStamp = &tmpTime2 // extSpamInfo var extSpamInfo wechat.SKBuiltinString_ extSpamInfo.Buffer = GetExtPBSpamInfoDataLogin(userInfo) extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen aesRequest.ExtSpamInfo = &extSpamInfo return &aesRequest } func SendHybridManualAutoRequest(userInfo *baseinfo.UserInfo, newpass string, wxid string, keyVer byte) (*baseinfo.PackHeader, error) { if keyVer == 0 { keyVer = 146 } else if keyVer == 145 { userInfo.HybridLogin = true } secKeyMgr := NewSecLoginKeyMgrByVer(keyVer) req := &wechat.ManualAuthRequest{ RsaReqData: GetManualAuthRsaReqDataProtobuf(userInfo, wxid, newpass), AesReqData: GetManualAuthAesReqDataProtobuf(userInfo), } reqData, err := proto.Marshal(req) if err != nil { return nil, err } //加密 encrypt, epKey, token, ecdhpairkey, err := clientsdk.HybridEncrypt(reqData, secKeyMgr.WeChatPubKey) if err != nil { return nil, err } ecdhPacket := &wechat.EcdhPacket{ Type: proto.Uint32(1), Key: &wechat.BufferT{ ILen: proto.Uint32(415), Buffer: ecdhpairkey.PubKey, }, Token: token, Url: proto.String(""), ProtobufData: encrypt, } secKeyMgr.PubKey = ecdhpairkey.PubKey secKeyMgr.PriKey = ecdhpairkey.PriKey secKeyMgr.SourceData = reqData secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, epKey[24:]...) secKeyMgr.FinalSha256 = append(secKeyMgr.FinalSha256, reqData...) ecdhDataPacket, err := proto.Marshal(ecdhPacket) if err != nil { return nil, err } packHeader := CreatePackHead(userInfo, baseinfo.MMPackDataTypeUnCompressed, 252, ecdhDataPacket, ecdhDataPacket, uint32(len(ecdhDataPacket)), 12, uint32(0x4e)) //设置Hybrid 加密密钥版本 packHeader.HybridKeyVer = secKeyMgr.WeChatPubKeyVersion //开始组头 retData := PackHeaderSerialize(packHeader, false) //fmt.Println(hex.EncodeToString(retData)) resp, err := mmtls.MMHTTPPostData(userInfo.MMInfo, "/cgi-bin/micromsg-bin/secmanualauth", retData) if err != nil { return nil, err } packHeader, err = DecodePackHeader(resp, nil) if err != nil { return nil, err } packHeader.Data, err = clientsdk.HybridEcdhDecrypt(packHeader.Data, secKeyMgr.PriKey, secKeyMgr.PubKey, secKeyMgr.FinalSha256) if err != nil { return nil, err } return packHeader, err } func GetManualAuthAesReqDataProtobufA16(userInfo *baseinfo.UserInfo) *wechat.ManualAuthAesReqData { AndroidId16 := userInfo.DeviceInfoA16 zeroUint32 := uint32(0) zeroInt32 := int32(0) var aesRequest wechat.ManualAuthAesReqData // BaseRequest baseReq := GetBaseRequest(userInfo) var tmpScene uint32 = 1 baseReq.Scene = &tmpScene baseReq.SessionKey = []byte{} baseReq.DeviceId = AndroidId16.DeviceId //A0cb9c716a607ed baseReq.ClientVersion = &baseinfo.AndroidClientVersion baseReq.OsType = &baseinfo.AndroidDeviceType aesRequest.BaseRequest = baseReq aesRequest.Imei = proto.String(AndroidId16.AndriodImei(AndroidId16.DeviceIdStr[:15])) //353978478595717 //000 B7366BF-2.5.27.9.568.1.035714929332437306bef21034caa37f01cf44dd6b7af383Eeedf 378Dbbf Technologies, Inc bcf737873:05:71:93:21:1ehalf thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt evtstrm aes pmull sha1 sha2 crc32189df3a2df2ce70c0fdffb2b56ae884cChinanet-cbfda9f:5e:d7:79:a5:880"Chinanet-cbfda"com.tencent.mmgoogle/bullhead/bullhead:8.1.0/DFA3.345967.885/3472334:user/release-keysbullheadCCD72fgooglebullheadbullheadbullhead0BDCnull0wifi357149293324373data/user/0/com.tencent.mm/0116403trueA0cb9c716a607edb30303566-6534-6636-6561-31643565393834313334383364313462643335653537 aesRequest.SoftType = proto.String(AndroidId16.AndriodGetSoftType(AndroidId16.DeviceIdStr)) aesRequest.BuiltinIpseq = &zeroUint32 aesRequest.ClientSeqId = proto.String(fmt.Sprintf("%s_%d", AndroidId16.DeviceIdStr, (time.Now().UnixNano() / 1e6))) aesRequest.DeviceName = proto.String(AndroidId16.AndroidManufacturer(AndroidId16.DeviceIdStr) + "-" + AndroidId16.AndroidPhoneModel(AndroidId16.DeviceIdStr)) // aesRequest.DeviceType = proto.String(AndroidId16.AndriodDeviceType(AndroidId16.DeviceIdStr)) aesRequest.Language = proto.String("Zh") aesRequest.TimeZone = proto.String("8.0") aesRequest.Channel = &zeroInt32 // aesRequest.Ostype = &baseinfo.AndroidDeviceType aesRequest.Signature = proto.String(AndroidId16.AndriodPackageSign(AndroidId16.DeviceIdStr)) //189df3a2df2ce70c0fdffb2b56ae884c // TimeStamp tmpTime2 := uint32(time.Now().UnixNano() / 1000000000) aesRequest.TimeStamp = &tmpTime2 aesRequest.DeviceBrand = proto.String("google") //Eeedf 37armeabi-10d aesRequest.DeviceModel = proto.String(AndroidId16.AndroidPhoneModel(AndroidId16.DeviceIdStr) + AndroidId16.AndroidArch(AndroidId16.DeviceIdStr)) aesRequest.RealCountry = proto.String("cn") aesRequest.BundleId = proto.String("com.tencent.mm") inputType := uint32(2) aesRequest.InputType = &inputType ext, err := GetExtSpamInfoAndroid(userInfo) if err != nil { log.Error("Android extSpam err", err.Error()) } // extSpamInfo var extSpamInfo wechat.SKBuiltinString_ extSpamInfo.Buffer = ext extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen aesRequest.ExtSpamInfo = &extSpamInfo return &aesRequest } // GetManualAuthAesReqProtobuf 生成自动登陆aesreq项 func GetManualAuthAesReqDataA16Protobuf(userInfo *baseinfo.UserInfo) []byte { AndroidId16 := userInfo.DeviceInfoA16 zeroUint32 := uint32(0) zeroInt32 := int32(0) var emptyString = string("") var aesRequest wechat.ManualAuthAesReqData // BaseRequest baseReq := GetBaseRequest(userInfo) // BaseAuthReqInfo var baseReqInfo wechat.BaseAuthReqInfo baseReqInfo.AuthReqFlag = &zeroUint32 baseReqInfo.AuthTicket = &emptyString aesRequest.BaseReqInfo = &baseReqInfo var tmpScene uint32 = 1 baseReq.Scene = &tmpScene baseReq.SessionKey = []byte{} baseReq.DeviceId = AndroidId16.DeviceId baseReq.ClientVersion = &baseinfo.AndroidClientVersion baseReq.OsType = &baseinfo.AndroidDeviceType aesRequest.BaseRequest = baseReq aesRequest.Imei = proto.String(AndroidId16.AndriodImei(AndroidId16.DeviceIdStr)) aesRequest.SoftType = proto.String(AndroidId16.AndriodGetSoftType(AndroidId16.DeviceIdStr)) aesRequest.BuiltinIpseq = &zeroUint32 aesRequest.ClientSeqId = proto.String(fmt.Sprintf("%s_%d", AndroidId16.DeviceIdStr, (time.Now().UnixNano() / 1e6))) aesRequest.DeviceName = proto.String(AndroidId16.AndroidManufacturer(AndroidId16.DeviceIdStr) + "-" + AndroidId16.AndroidPhoneModel(AndroidId16.DeviceIdStr)) aesRequest.DeviceType = proto.String(AndroidId16.AndriodDeviceType(AndroidId16.DeviceIdStr)) aesRequest.Language = proto.String("Zh") aesRequest.TimeZone = proto.String("8.0") aesRequest.Channel = &zeroInt32 // TimeStamp tmpTime2 := uint32(time.Now().UnixNano() / 1000000000) aesRequest.TimeStamp = &tmpTime2 aesRequest.DeviceBrand = proto.String("google") aesRequest.DeviceModel = proto.String(AndroidId16.AndroidPhoneModel(AndroidId16.DeviceIdStr)) // + AndroidId16.AndroidArch(AndroidId16.DeviceIdStr) aesRequest.RealCountry = proto.String("cn") aesRequest.BundleId = proto.String("com.tencent.mm") inputType := uint32(2) aesRequest.InputType = &inputType aesRequest.Ostype = &baseinfo.AndroidDeviceType aesRequest.Signature = proto.String(AndroidId16.AndriodPackageSign(AndroidId16.DeviceIdStr)) // ext, err := GetExtSpamInfoAndroid(userInfo) if err != nil { log.Error("Android extSpam err", err.Error()) } // extSpamInfo var extSpamInfo wechat.SKBuiltinString_ extSpamInfo.Buffer = ext extSpamInfoLen := uint32(len(extSpamInfo.Buffer)) extSpamInfo.Len = &extSpamInfoLen aesRequest.ExtSpamInfo = &extSpamInfo reqData, _ := proto.Marshal(&aesRequest) return reqData } func GetExtSpamInfoAndroid(userInfo *baseinfo.UserInfo) ([]byte, error) { deviceToken := userInfo.DeviceInfoA16.DeviceToken T := time.Now().Unix() Wcstf, _ := extinfo.GetWcstf(userInfo.WxId) Wcste, _ := extinfo.GetWcste() AndroidCcData := extinfo.AndroidCcData(userInfo.DeviceInfoA16.DeviceIdStr, userInfo.DeviceInfoA16, deviceToken, T) CcData3PB, _ := proto.Marshal(AndroidCcData) curtime := uint32(T) DeviceTokenCCD := &mmproto.DeviceToken{ Version: proto.String(""), Encrypted: proto.Uint32(1), Data: &mmproto.SKBuiltinStringt{ String_: proto.String(deviceToken.GetTrustResponseData().GetDeviceToken()), }, TimeStamp: &curtime, Optype: proto.Uint32(2), Uin: proto.Uint32(0), } DeviceTokenCCDPB, _ := proto.Marshal(DeviceTokenCCD) WCExtInfo := &wechat.WCExtInfoNew{ Wcstf: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(Wcstf))), Buffer: Wcstf, }, Wcste: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(Wcste))), Buffer: Wcste, }, CcData: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(CcData3PB))), Buffer: CcData3PB, }, DeviceToken: &wechat.BufferT{ ILen: proto.Uint32(uint32(len(DeviceTokenCCDPB))), Buffer: DeviceTokenCCDPB, }, } WCExtInfoPB, _ := proto.Marshal(WCExtInfo) return WCExtInfoPB, nil }