Python模拟登陆 —— 征服验证码 9 微博weibo.com

登录界面

抓包分析可以使用Http Analyzer,Filders,但是看起来很复杂,还是使用火狐好(chrome远远没有火狐好用)。

首先,在输入用户名后,会进行预登录,网址为:http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=ZW5nbGFuZHNldSU0MDE2My5jb20%3D&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.18)&_=1443156845536,通过响应(sinaSSOController.preloginCallBack({"retcode":0,"servertime":1443156842,"pcid":"gz-e88b75a929252baec7c12c741985eaa45627","nonce":"2L4IZ3","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","showpin":0,"exectime":16})),我们可以获得四个有用的变量,servertime、nonce、pubkey和rsakv。

新浪微博的用户名加密目前采用Base64加密算法,而新浪微博登录密码的加密算法使用RSA2,这是模拟登陆的重点,需要先创建一个rsa公钥,公钥的两个参数新浪微博都给了固定值,第一个参数是登录第一步中的pubkey,第二个参数是js加密文件中的‘10001’(针对网友的提问进行更新:这个其实就是在ssologin.js的响应中). 这两个值需要先从16进制转换成10进制,把10001转成十进制为65537,随后加入servertime和nonce再次加密。

要提交的数据是:

postdata = {
        'entry': 'weibo',
        'gateway': '1',
        'from': '',
        'savestate': '7',
        'useticket': '1',
        'pagerefer': "http://login.sina.com.cn/sso/logout.php?entry=miniblog&r=http%3A%2F%2Fweibo.com%2Flogout.php%3Fbackurl",
        'vsnf': '1',
        'su': su,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': nonce,
        'pwencode': 'rsa2',
        'rsakv': rsakv,
        'sp': password_secret,
        'sr': '1366*768',
        'encoding': 'UTF-8',
        'prelt': '115',
        'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        'returntype': 'META'
        }

提交之后,因为重定向,还要获取重定向的url。

使用python3。

import time
import base64
import rsa
import binascii
import requests
import re
import random
try:
    from PIL import Image
except:
    pass
try:
    from urllib.parse import quote_plus
except:
    from urllib import quote_plus

'''
如果没有开启登录保护,不用输入验证码就可以登录
如果开启登录保护,需要输入验证码

'''


# 构造 Request headers
agent = 'Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0'
headers = {
    'User-Agent': agent
}

session = requests.session()

# 访问 初始页面带上 cookie
index_url = "http://weibo.com/login.php"
try:
    session.get(index_url, headers=headers, timeout=2)
except:
    session.get(index_url, headers=headers)
try:
    input = raw_input
except:
    pass


def get_su(username):
    """
    对 email 地址和手机号码 先 javascript 中 encodeURIComponent
    对应 Python 3 中的是 urllib.parse.quote_plus
    然后在 base64 加密后decode
    """
    username_quote = quote_plus(username)
    username_base64 = base64.b64encode(username_quote.encode("utf-8"))
    return username_base64.decode("utf-8")


# 预登陆获得 servertime, nonce, pubkey, rsakv
def get_server_data(su):
    pre_url = "http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su="
    pre_url = pre_url + su + "&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.18)&_="
    pre_url = pre_url + str(int(time.time() * 1000))
    pre_data_res = session.get(pre_url, headers=headers)

    sever_data = eval(pre_data_res.content.decode("utf-8").replace("sinaSSOController.preloginCallBack", ''))

    return sever_data


# print(sever_data)


def get_password(password, servertime, nonce, pubkey):
    rsaPublickey = int(pubkey, 16)
    key = rsa.PublicKey(rsaPublickey, 65537)  # 创建公钥
    message = str(servertime) + '\t' + str(nonce) + '\n' + str(password)  # 拼接明文js加密文件中得到
    message = message.encode("utf-8")
    passwd = rsa.encrypt(message, key)  # 加密
    passwd = binascii.b2a_hex(passwd)  # 将加密信息转换为16进制。
    return passwd


def get_cha(pcid):
    cha_url = "http://login.sina.com.cn/cgi/pin.php?r="
    cha_url = cha_url + str(int(random.random() * 100000000)) + "&s=0&p="
    cha_url = cha_url + pcid
    cha_page = session.get(cha_url, headers=headers)
    with open("cha.jpg", 'wb') as f:
        f.write(cha_page.content)
        f.close()
    try:
        im = Image.open("cha.jpg")
        im.show()
        im.close()
    except:
        print(u"请到当前目录下,找到验证码后输入")


def login(username, password):
    # su 是加密后的用户名
    su = get_su(username)
    sever_data = get_server_data(su)
    servertime = sever_data["servertime"]
    nonce = sever_data['nonce']
    rsakv = sever_data["rsakv"]
    pubkey = sever_data["pubkey"]
    showpin = sever_data["showpin"]
    password_secret = get_password(password, servertime, nonce, pubkey)

    postdata = {
        'entry': 'weibo',
        'gateway': '1',
        'from': '',
        'savestate': '7',
        'useticket': '1',
        'pagerefer': "http://login.sina.com.cn/sso/logout.php?entry=miniblog&r=http%3A%2F%2Fweibo.com%2Flogout.php%3Fbackurl",
        'vsnf': '1',
        'su': su,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': nonce,
        'pwencode': 'rsa2',
        'rsakv': rsakv,
        'sp': password_secret,
        'sr': '1366*768',
        'encoding': 'UTF-8',
        'prelt': '115',
        'url': 'http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        'returntype': 'META'
        }
    login_url = 'http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)'
    if showpin == 0:
        login_page = session.post(login_url, data=postdata, headers=headers)
    else:
        pcid = sever_data["pcid"]
        get_cha(pcid)
        postdata['door'] = input(u"请输入验证码")
        login_page = session.post(login_url, data=postdata, headers=headers)
    login_loop = (login_page.content.decode("GBK"))
    # print(login_loop)
    pa = r'location\.replace\([\'"](.*?)[\'"]\)'
    loop_url = re.findall(pa, login_loop)[0]
    # print(loop_url)
    # 此出还可以加上一个是否登录成功的判断,下次改进的时候写上
    login_index = session.get(loop_url, headers=headers)
    uuid = login_index.text
    uuid_pa = r'"uniqueid":"(.*?)"'
    uuid_res = re.findall(uuid_pa, uuid, re.S)[0]
    web_weibo_url = "http://weibo.com/%s/profile?topnav=1&wvr=6&is_all=1" % uuid_res
    weibo_page = session.get(web_weibo_url, headers=headers)
    weibo_pa = r'<title>(.*?)</title>'
    # print(weibo_page.content.decode("utf-8"))
    userID = re.findall(weibo_pa, weibo_page.content.decode("utf-8", 'ignore'), re.S)[0]
    print(u"欢迎你 %s, 登陆成功" % userID)


if __name__ == "__main__":
    username = input(u'用户名:')
    password = input(u'密码:')
    login(username, password)

另可参考: http://blog.csdn.net/andrewseu/article/details/48730735 http://www.jianshu.com/p/816594c83c74 https://github.com/ResolveWang

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大魏分享(微信公众号:david-share)

如何为微服务做安全加密? | 微服务系列第十一篇

在微服务架构中实现可靠且强大的安全实现非常重要。微服务的体系结构向应用程序公开了多个入口点,并且通信可能需要多个网络跃点,因此未授权访问的风险很高。这需要比传统...

35980
来自专栏大内老A

[WCF安全系列]实例演示:TLS/SSL在WCF中的应用[SSL over TCP]

在接下来的系列文章中我们正是讨论关于身份认证的主题。在前面我们已经谈到了,WCF中的认证属于“双向认证”,既包括服务对客户端的认证(以下简称客户端认证),也包括...

27970
来自专栏IMWeb前端团队

Nodejs进阶:核心模块https 之 如何优雅的访问12306

本文作者:IMWeb 陈映平 原文出处:IMWeb社区 未经同意,禁止转载 模块概览 这个模块的重要性,基本不用强调了。在网络安全问题日益严峻的今天,...

314100
来自专栏叔叔的博客

SpringCloud config配置文件加密

? 一、前言 配置文件中,有些敏感数据需要加密处理。 SpringCloud config server可以结合jce实现这个功能。 二、配置 下载jce ...

42060
来自专栏七夜安全博客

你不知道的 HTTPS中间人攻击

研究生毕业了,好好给自己放了个假期,休息了两周,文章博客都没有更新。从大学开始基本上没过暑假,匆匆忙忙的。再过两天,就要去腾讯工作了,做了自己喜欢的网络安全,重...

18230
来自专栏Android开发与分享

【Android】RxJava的使用(四)线程控制 —— Scheduler

375120
来自专栏挖坑填坑

使用.net core ABP和Angular模板构建博客管理系统(完善前台服务)

1、 列表页面继承了PagedListingComponentBase类,这个类到底提供了些什么。 2、在处理的时候应该有提示和遮罩层显得更加友好。 3、作...

13520
来自专栏Albert陈凯

2018-10-31 代码中的敏感信息加密方案

https://juejin.im/post/5bd79dc4f265da0acb13df0d

18440
来自专栏FreeBuf

直面冥王:最新爆发的C#敲诈木马HadesLocker解读

近日哈勃分析系统捕获到一类由C#语言编写的新的敲诈勒索木马。之前出现 的C#语言编写的木马只是简单地调用了一些C#库来辅助开发。与之相比,这次的变种增加了多层嵌...

31760
来自专栏LeoXu的博客

一种C/S架构下的 RSA + AES 组合加密方案业务流程

一、初步方案: 1、客户端初始化,调用服务端AES加密key获取接口; 2、服务端从配置文件获取AES加密key,用RSA私钥对其进行加密,返回给客户端; ...

14120

扫码关注云+社区

领取腾讯云代金券