js逆向
js逆向就是从网页的js找到加密的参数,实现破解加密,拿到cookie
微博登录案例
手动操作流程
- 访问首页https://weibo.com
- 输入用户名和密码
- 点击登录
- 如果有验证码,就输入验证码验证
- 成功跳转到微博首页面
1.请求分析
请求回的响应是否包含cookie,也即是看首页面的响应头中是否包含set-cookie。如果包含,那么这个请求是登录过程中必须的。经过查看,发现在首页面的响应头中,包含set-cookie,这个请求是登录的第一个请求。
2.寻找请求数据
第一次的请求
第二次的请求
观察data的变化,发现除了最后有个时间戳解决浏览器缓存之外,其他参数都是固定的。
nonce,pwencode,rsakv,以及sp的值都明确指明了参数被js加密了
一个servertime ertime 时间戳不管它,一个su,预测u就是username,一个sp,p应该是sp
3. 寻找加密的js
根据经验,在请求页面的html之后,还会去请求页面中的js,css,图片等信息。css,图片信息我们可以排除,一般情况,不会是登录的必须请求。一种常见的手法是,将后续请求需要用到的参数放到js中,然后通过js异步请求来完成登录。所以,我们在Network中过滤出所有的js请求。排除一些功能性的js,例如jquery之类,找出可能是参数的js。
https://login.sina.com.cn/sso/prelogin.php

这是一条jsonp的请求,其中包含了几个关键参数pubkey,nonce,rsakv,这是rsa加密用的参数
然后分析这个jsonp的请求data

现在要请求该url,拿到部分的加密数据,用session来访问
import reimport timeimport jsonimport requestssession = requests.session()session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'})# 1.请求首页面session.get('https://weibo.com')# 2.请求pre_login 获取参数params = { 'entry': 'weibo', 'callback': 'sinaSSOController.preloginCallBack', 'su': '', 'rsakt': 'mod', 'client': 'ssologin.js(v1.4.19)', '_': int(time.time()) }res = session.get(url='https://login.sina.com.cn/sso/prelogin.php', params=params)data = json.loads(re.findall(r'((.*?))', res.text)[0])print(data)data就是上面的json数据
4.点击登录后请求的分析
先清空调试工具中的请求历史,然后勾选Preserver log和Disable cache,保证抓包的正确。
点击开发者工具Elements选项卡,点击左上角的选中按钮,然后用鼠标左定位页面中的登录按钮。

再点击开发工具窗口中的右边的子窗口,选中Events Listeners, 找到click事件,从而定位到js代码。

然后再点击,右边的js代码,会打开调试工具的sources窗口,它由3个子窗口组成,从左往右依次为,文件目录窗口,js代码窗口和调试窗口。

点击格式化后,js代码会自动跳到上面click监听时间执行的入口函数处

打好断点后,就可以开始调试了,点击登录按钮,js会暂停到刚才断点处

必须一步一步调试,知道找到关键代码,js调试需要极有耐心。头发就会慢慢掉的。
上面是常规做法。但是,我教你另一种情况,可以换另外一种方法定位。那就是如果你要找某个请求的触发函数,那么可以直接在networking选项窗口直接定位,这样不用一个个跳,因为看js真的让人头疼的事
输入错误密码,然后点击登录,请求的Initiator字段显示了,发送这条请求的发起对象
打上断点,然后进行调试。
然后点击登录

将代码往前,就会发现用户名和密码

在用户名和密码的加密函数在断点

现在就是想看makerequest中发生了啥?所以要一步一步调试
先到了变量e的生成
明显知道a 就是用户名,b 就是密码
这里参数就是在这里生成的,再往下看看

先对a进行了encodeURIComponent(a)
再往下跳回了base64
再跳去了base64生成函数中,

一个encode编码,一个base64
import base64def encrypt_username(self): ''' 对账号进行base64加密 :return: ''' return base64.b64encode(self.username.encode())su 搞定,剩下sp
再往下看找 b 和sp
import rsafrom binascii import b2a_hexdef encrypt_password(self): ''' 对密码进行rsa加密 :return: ''' result = self.per_login() my_password = str(result['servertime']) + 't' + str(result['nonce']) + '' + str(self.password) publicky = rsa.PublicKey(int(result['pubkey'],16),int('10001',16)) return b2a_hex(rsa.encrypt(my_password.encode(),publicky))总体思路
- su 是base64的编码
- sp 是rsa的公密钥加密 rsa的公密钥来自预请求的json中
- 还有一个时间戳要乘以1000 int(time.time()*1000)
- 用session 先获得预请求,拿到rsa的公密钥,在将su,sp加密,用post请求访问url

回复 【微博】 获取登录代码














