示例#1
0
def send_app_msg_req2buf(wxid,title,des,link_url,thumb_url):
    #protobuf组包
    req = mm_pb2.new_send_app_msg_req(
        login = mm_pb2.LoginInfo(
            aesKey =  Util.sessionKey,
            uin = Util.uin,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 0,
        ),
        info = mm_pb2.new_send_app_msg_req.appmsg_info(
            from_wxid = Util.wxid,
            app_wxid = '',
            tag3 = 0,
            to_wxid = wxid,
            type = 5,
            content = define.SHARE_LINK.format(title,des,link_url,thumb_url),
            utc = Util.get_utc(),
            client_id = '{}{}{}{}'.format(wxid,random.randint(1,99),'T',Util.get_utc()*1000 + random.randint(1,999)),
            tag10 = 3,
            tag11 = 0,
        ),
        tag4 = 0,
        tag6 = 0,
        tag7 = '',
        fromScene = '',
        tag9 = 0,
        tag10 = 0,
    )
     #组包
    return (pack(req.SerializeToString(),222),req.info.content)
示例#2
0
def new_init():
    #protobuf组包
    new_init_request = mm_pb2.NewInitRequest(
        login = mm_pb2.LoginInfo(
            aesKey =  Util.sessionKey,
            uin = 0,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 1,
        ),
        wxid = Util.wxid,
        tag3 = mm_pb2.mmStr(),
        tag4 = mm_pb2.mmStr(),
        language = define.__LANGUAGE__,
    )
    #组包
    send_data = Util.pack(new_init_request.SerializeToString(),139)

    #发包
    ret_bytes = Util.mmPost('/cgi-bin/micromsg-bin/newinit',send_data)
    logger.debug('返回数据:' + str(ret_bytes))

    #解包
    res = mm_pb2.NewInitResponse()
    res.ParseFromString(Util.UnPack(ret_bytes))

    #newinit后保存sync key
    Util.sync_key = res.synckeybytes.key
    logger.debug('sync key len:{}\ndata:{}'.format(res.synckeybytes.len, Util.b2hex(res.synckeybytes.key)))

    #初始化数据
    logger.debug('tag7数量:{}'.format(res.cntList))

    #未读消息
    for i in range(res.cntList):
        if 5 == res.tag7[i].type:                           #未读消息
            msg = mm_pb2.Msg()
            msg.ParseFromString(res.tag7[i].data.data)
            if 10002 == msg.type or 9999 == msg.type:       #过滤系统垃圾消息
                continue
            else:
                logger.info('收到新消息:\ncreate utc time:{}\ntype:{}\nfrom:{}\nto:{}\nraw data:{}\nxml data:{}'.format(msg.createTime, msg.type, msg.from_id.id, msg.to_id.id, msg.raw.content, msg.xmlContent))
    
    return
示例#3
0
def new_init_req2buf():
    #protobuf组包
    new_init_request = mm_pb2.NewInitRequest(
        login = mm_pb2.LoginInfo(
            aesKey =  Util.sessionKey,
            uin = 0,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 1,
        ),
        wxid = Util.wxid,
        tag3 = mm_pb2.mmStr(),
        tag4 = mm_pb2.mmStr(),
        language = define.__LANGUAGE__,
    )

    #组包
    return Util.pack(new_init_request.SerializeToString(),139)
示例#4
0
def new_init_req2buf(cur=b'',max=b''):
    #protobuf组包
    new_init_request = mm_pb2.NewInitRequest(
        login = mm_pb2.LoginInfo(
            aesKey =  Util.sessionKey,
            uin = Util.uin,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 3,
        ),
        wxid = Util.wxid,
        sync_key_cur = cur,
        sync_key_max = max,
        language = define.__LANGUAGE__,
    )

    #组包
    return pack(new_init_request.SerializeToString(),139)
示例#5
0
def login_req2buf(name,password):
    #随机生成16位登录包AesKey
    login_aes_key = bytes(''.join(random.sample(string.ascii_letters + string.digits, 16)), encoding = "utf8")

    #protobuf组包1
    accountRequest = mm_pb2.ManualAuthAccountRequest(
        aes     = mm_pb2.ManualAuthAccountRequest.AesKey(
            len = 16,
            key = login_aes_key
        ),
        ecdh    = mm_pb2.ManualAuthAccountRequest.Ecdh(
            nid = 713,
            ecdhKey = mm_pb2.ManualAuthAccountRequest.Ecdh.EcdhKey(
                len = len(Util.EcdhPubKey),
                key = Util.EcdhPubKey
            )
        ),
        userName = name,
        password1 = Util.GetMd5(password),
        password2 = Util.GetMd5(password)
    )
    #protobuf组包2
    deviceRequest = mm_pb2.ManualAuthDeviceRequest(
        login = mm_pb2.LoginInfo(
            aesKey = login_aes_key,
            uin = 0,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 1,
        ),
        tag2 = mm_pb2.ManualAuthDeviceRequest._Tag2(),
        imei = define.__IMEI__,
        softInfoXml = define.__SOFTINFO__.format(define.__IMEI__,define.__ANDROID_ID__, define.__MANUFACTURER__+" "+define.__MODELNAME__, define.__MOBILE_WIFI_MAC_ADDRESS__, define.__CLIENT_SEQID_SIGN__, define.__AP_BSSID__, define.__MANUFACTURER__,"taurus", define.__MODELNAME__, define.__IMEI__),
        unknown5 = 0,
        clientSeqID = define.__CLIENT_SEQID__,
        clientSeqID_sign = define.__CLIENT_SEQID_SIGN__,
        loginDeviceName = define.__MANUFACTURER__+" "+define.__MODELNAME__,
        deviceInfoXml = define.__DEVICEINFO__.format(define.__MANUFACTURER__, define.__MODELNAME__),
        language = define.__LANGUAGE__,
        timeZone = "8.00",
        unknown13 = 0,
        unknown14 = 0,
        deviceBrand = define.__MANUFACTURER__,
        deviceModel = define.__MODELNAME__+"armeabi-v7a",
        osType = define.__ANDROID_VER__,
        realCountry = "cn",
        unknown22 = 2,                      #Unknown
    )
    
    logger.debug("accountData protobuf数据:" + str(accountRequest.SerializeToString()))
    logger.debug("deviceData protobuf数据:" + str(deviceRequest.SerializeToString()))

    #加密
    reqAccount = Util.compress_and_rsa(accountRequest.SerializeToString())
    reqDevice  = Util.compress_and_aes(deviceRequest.SerializeToString(),login_aes_key)

    logger.debug("加密后数据长度:reqAccount={},reqDevice={}".format(len(reqAccount),len(reqDevice[0])))
    logger.debug("加密后reqAccount数据:" + str(reqAccount))
    logger.debug("加密后reqDevice数据:" + str(reqDevice[0]))

    #封包包体
    subheader = b''
    subheader += struct.pack(">I",len(accountRequest.SerializeToString()))          #accountData protobuf长度
    subheader += struct.pack(">I",len(deviceRequest.SerializeToString()))           #deviceData protobuf长度
    subheader += struct.pack(">I",len(reqAccount))                                  #accountData RSA加密后长度
    body   =  subheader + reqAccount + reqDevice[0]                                 #包体由头信息、账号密码加密后数据、硬件设备信息加密后数据3部分组成
    
    #封包包头
    header = bytearray(0)
    header += bytes([0])                                                            #最后2bit:02--包体不使用压缩算法;前6bit:包头长度,最后计算                                        #
    header += bytes([((0x7<<4) + 0xf)])                                             #07:RSA加密算法  0xf:cookie长度
    header += struct.pack(">I",define.__CLIENT_VERSION__)                           #客户端版本号 网络字节序
    header += bytes([0]*4)                                                          #uin
    header += bytes([0]*15)                                                         #coockie
    header += encoder._VarintBytes(701)                                             #cgi type
    header += encoder._VarintBytes(len(body))                                       #body 压缩前长度
    header += encoder._VarintBytes(len(body))                                       #body 压缩后长度(登录包不需要压缩body数据)
    header += struct.pack(">B",define.__LOGIN_RSA_VER__)                            #RSA秘钥版本
    header += b'\x01\x02'                                                           #Unknown Param
    header[0] = (len(header)<<2) + 2                                                #包头长度

    #组包
    logger.debug('包体数据:' + str(body))
    logger.debug('包头数据:' + str(header))
    senddata = header + body
    
    return (senddata,login_aes_key)
示例#6
0
def Login(name,password):
    #随机生成16位登录包AesKey
    login_aes_key = bytes(''.join(random.sample(string.ascii_letters + string.digits, 16)), encoding = "utf8")

    #生成ECC key
    if not Util.GenEcdhKey():
        logger.info('生成ECC Key失败!')
        return -1

    #protobuf组包1
    accountRequest = mm_pb2.ManualAuthAccountRequest(
        aes     = mm_pb2.ManualAuthAccountRequest.AesKey(
            len = 16,
            key = login_aes_key
        ),
        ecdh    = mm_pb2.ManualAuthAccountRequest.Ecdh(
            nid = 713,
            ecdhKey = mm_pb2.ManualAuthAccountRequest.Ecdh.EcdhKey(
                len = len(Util.EcdhPubKey),
                key = Util.EcdhPubKey
            )
        ),
        userName = name,
        password1 = Util.GetMd5(password),
        password2 = Util.GetMd5(password)
    )
    #protobuf组包2
    deviceRequest = mm_pb2.ManualAuthDeviceRequest(
        login = mm_pb2.LoginInfo(
            aesKey = login_aes_key,
            uin = 0,
            guid = define.__GUID__ + '\0',          #guid以\0结尾
            clientVer = define.__CLIENT_VERSION__,
            androidVer = define.__ANDROID_VER__,
            unknown = 1,
        ),
        tag2 = mm_pb2.ManualAuthDeviceRequest._Tag2(),
        imei = define.__IMEI__,
        softInfoXml = define.__SOFTINFO__.format(define.__IMEI__,define.__ANDROID_ID__, define.__MANUFACTURER__+" "+define.__MODELNAME__, define.__MOBILE_WIFI_MAC_ADDRESS__, define.__CLIENT_SEQID_SIGN__, define.__AP_BSSID__, define.__MANUFACTURER__,"taurus", define.__MODELNAME__, define.__IMEI__),
        unknown5 = 0,
        clientSeqID = define.__CLIENT_SEQID__,
        clientSeqID_sign = define.__CLIENT_SEQID_SIGN__,
        loginDeviceName = define.__MANUFACTURER__+" "+define.__MODELNAME__,
        deviceInfoXml = define.__DEVICEINFO__.format(define.__MANUFACTURER__, define.__MODELNAME__),
        language = define.__LANGUAGE__,
        timeZone = "8.00",
        unknown13 = 0,
        unknown14 = 0,
        deviceBrand = define.__MANUFACTURER__,
        deviceModel = define.__MODELNAME__+"armeabi-v7a",
        osType = define.__ANDROID_VER__,
        realCountry = "cn",
        unknown22 = 2,                      #Unknown
    )
    
    logger.debug("accountData protobuf数据:" + str(accountRequest.SerializeToString()))
    logger.debug("deviceData protobuf数据:" + str(deviceRequest.SerializeToString()))

    #加密
    reqAccount = Util.compress_and_rsa(accountRequest.SerializeToString())
    reqDevice  = Util.compress_and_aes(deviceRequest.SerializeToString(),login_aes_key)

    logger.debug("加密后数据长度:reqAccount={},reqDevice={}".format(len(reqAccount),len(reqDevice[0])))
    logger.debug("加密后reqAccount数据:" + str(reqAccount))
    logger.debug("加密后reqDevice数据:" + str(reqDevice[0]))

    #封包包体
    subheader = b''
    subheader += struct.pack(">I",len(accountRequest.SerializeToString()))          #accountData protobuf长度
    subheader += struct.pack(">I",len(deviceRequest.SerializeToString()))           #deviceData protobuf长度
    subheader += struct.pack(">I",len(reqAccount))                                  #accountData RSA加密后长度
    body   =  subheader + reqAccount + reqDevice[0]                                 #包体由头信息、账号密码加密后数据、硬件设备信息加密后数据3部分组成
    
    #封包包头
    header = bytearray(0)
    header += bytes([0])                                                            #最后2bit:02--包体不使用压缩算法;前6bit:包头长度,最后计算                                        #
    header += bytes([((0x7<<4) + 0xf)])                                             #07:RSA加密算法  0xf:cookie长度
    header += struct.pack(">I",define.__CLIENT_VERSION__)                           #客户端版本号 网络字节序
    header += bytes([0]*4)                                                          #uin
    header += bytes([0]*15)                                                         #coockie
    header += encoder._VarintBytes(701)                                             #cgi type
    header += encoder._VarintBytes(len(body))                                       #body 压缩前长度
    header += encoder._VarintBytes(len(body))                                       #body 压缩后长度(登录包不需要压缩body数据)
    header += struct.pack(">B",define.__LOGIN_RSA_VER__)                            #RSA秘钥版本
    header += b'\x01\x02'                                                           #Unknown Param
    header[0] = (len(header)<<2) + 2                                                #包头长度

    #组包
    logger.debug('包体数据:' + str(body))
    logger.debug('包头数据:' + str(header))
    senddata = header + body
    
    #发包
    loginRetBytes = Util.mmPost('/cgi-bin/micromsg-bin/manualauth',senddata)
    logger.debug('返回数据:' + str(loginRetBytes))

    #解包
    loginRes = mm_pb2.ManualAuthResponse()
    loginRes.result.code = -1
    loginRes.ParseFromString(Util.UnPack(loginRetBytes,login_aes_key))
     
    #登录异常处理
    if -301 == loginRes.result.code:                        #DNS解析失败,请尝试更换idc
        logger.info('登陆结果:\ncode:{}\n请尝试更换DNS重新登陆!'.format(loginRes.result.code))
    elif -106 == loginRes.result.code:                      #需要在IE浏览器中滑动操作解除环境异常/扫码、短信、好友授权(滑动解除异常后需要重新登录一次)
        logger.info('登陆结果:\ncode:{}\nError msg:{}\n'.format(loginRes.result.code,loginRes.result.err_msg.msg[loginRes.result.err_msg.msg.find('<Content><![CDATA[')+len('<Content><![CDATA['):loginRes.result.err_msg.msg.find(']]></Content>')]))
        #打开IE,完成授权
        logger.info('请在浏览器授权后重新登陆!')
        Util.OpenIE(loginRes.result.err_msg.msg[loginRes.result.err_msg.msg.find('<Url><![CDATA[')+len('<Url><![CDATA['):loginRes.result.err_msg.msg.find(']]></Url>')])
    elif loginRes.result.code:                              #其他登录错误
        logger.info('登陆结果:\ncode:{}\nError msg:{}\n'.format(loginRes.result.code,loginRes.result.err_msg.msg[loginRes.result.err_msg.msg.find('<Content><![CDATA[')+len('<Content><![CDATA['):loginRes.result.err_msg.msg.find(']]></Content>')]))
    else:                                                   #登陆成功
        #密钥协商
        Util.sessionKey = Util.aesDecrypt(loginRes.authParam.session.key,Util.DoEcdh(loginRes.authParam.ecdh.ecdhKey.key))
        #保存uin/wxid
        Util.uin = loginRes.authParam.uin
        Util.wxid = loginRes.accountInfo.wxId
        logger.info('登陆成功!\nsession_key:{}\nuin:{}\nwxid:{}\nnickName:{}\nalias:{}'.format(Util.sessionKey,Util.uin,Util.wxid,loginRes.accountInfo.nickName,loginRes.accountInfo.Alias))

    return loginRes.result.code