开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 7504|回复: 5
收起左侧

[技术专题] 【JS逆向】新浪微博登录RSA+其他 | 每日JS(附登录例子)

[复制链接]
结帖率:100% (4/4)
发表于 2019-12-16 16:53:23 | 显示全部楼层 |阅读模式   安徽省亳州市


简书图片无法加载,看图可以去原帖:https://www.jianshu.com/p/b20d8d89d288

第六天

JavaScript逆向练习6

0x01 目标网址

http://weibo.com

0x02 定位JS

1. 随便输入账号密码验证码,如果是不存在的账号,会直接提示密码错误,如果是是存在的账号,会提示输入验证码,,这里假设是带验证码的,点击登录后,查看提交的参数,可以看到,在登录包里有许多看不懂的加参数,一个个来分析。

1.png

2. 分析下参数

参数 来源
entry weibo 固定
gateway 1 固定
from 固定
savestate 7 固定
qrcode_flag false 固定
useticket 1 固定
pagerefer 固定
pcid yf-826260aed11d* 上次返回
door 1111 验证码
vsnf 1 固定
su MT*****NjY= JS计算
service miniblog 固定
servertime 1576135789 JS计算
nonce NLUYC0 上次返回
pwencode rsa2 固定
rsakv 1330428213 上次返回
sp 2395de422727c06* JS计算
sr 1536*864 固定
encoding UTF-8 固定
prelt 82 JS计算
url https://weibo.com/* 固定
returntype META 固定

其中上次返回是在登陆之前的一次请求中返回的内容

2.png

其他的JS计算也不全是加密,有的只是单纯计算的值,下面一个个找。

3. Ctrl+Shift+F调出搜索面板,本着越生僻越好搜的原则,先搜索prelt,看到只有一个js结果。

点进第一个结果,点花括号格式化一下,Ctrl+Fprelt,只有两个结果,而且第一个returntype: "TEXT"明显不是要找的,所以第二个上面下断点。

3.png

同时观察断点处,发现f是在上面由makeRequest定义的,所以这里先搜一下看看makeRequest的定义在哪。

4.png

直接找到了加密处,就是makeRequest,可以看到还有其他参数也是在这里生成的,包括固定的一些。在782行这里也下个断点。

4. 重新输入账号密码验证码,点击登录,JS被断了下来。

5.png

直接先把su给扣下来:

e.su = sinaSSOEncoder.base64.encode(urlencode(a));

可以看到参数a是账号,跟进urlencode发现只是一个简单的encodeURIComponent

urlencode = function(a) {
    return encodeURIComponent(a)
}

再找sinaSSOEncoder,直接Ctrl+F搜索,找到定义处:

var sinaSSOEncoder = sinaSSOEncoder || {};

这个语句意思是如果sinaSSOEncoder不为空(即转为bool类型不为false),则把sinaSSOEncoder赋值给前面的变量(也是sinaSSOEncoder),如果sinaSSOEncoder为空,则把后面的{}赋值给前面的sinaSSOEncoder,所以这里首先生成了空对象。

所以再找定义处,往下翻一下,看到有两个函数调用了.call(sinaSSOEncoder);,这就是加密对象的定义了,两个函数全部拿走。

继续往下运行,发现对servertime进行了赋值,那就搜一下后面的.servertime =(前面不带对象名,但带上.,后面带上空格和等于号),可以快速定位。

6.png

这里看到,其实就是一个a循环加2的意思,在这里下个断点,断下来之后可以从右侧Call Stack里看到参数a的来源,找到调用处发现就是上一次请求返回的servertime,也就是说,参数servertime就是上次返回的servertime循环加2,所以这里可以直接在外部语言实现。

下一个参数是sp,在上面的加密处已经看到了sp,大致看到是一个RSA,而且RSA对象的定义已经被扣下来过了,这里没啥要做的了,只是加密的参数要注意看下,一个是上次返回的nonce,一个是计算完的servertime,还有一个是明文密码,再加上其他字符组合成了加密参数。

7.png

最后一个参数是prelt,这个参数位置在一开始第一次下断点的那里:

f.prelt = preloginTime;

直接搜preloginTime,可以定位到269行:

8.png

这段意思是prelt就是上一次请求的回调函数中new Date减去上一次请求的起始new Date再减去请求返回的exectime,也就是等于上一次请求的本地总耗时减去云端耗时。

5. 参数找完了,到这里已经可以开始改写了。

参数列表如下:

参数 来源
entry weibo 固定
gateway 1 固定
from 固定
savestate 7 固定
qrcode_flag false 固定
useticket 1 固定
pagerefer 固定
pcid yf-826260aed11d 上次返回
door 1111 验证码
vsnf 1 固定
su MTU1NTU1NTY2NjY= base64+URL编码 手机号
service miniblog 固定
servertime 1576135789 以上次返回的为基数,每次+2(从上次请求到提交登录的时间差除以2取整,一般为4~10)
nonce NLUYC0 上次返回
pwencode rsa2 固定
rsakv 1330428213 上次返回
sp 2395de422727c06ce JS计算    RSA加密
sr 1536*864 固定   屏幕宽*高
encoding UTF-8 固定
prelt 82 可随机,约等于上一次请求的本地耗时减去云端耗时,上一次请求的回调函数中new Date-上一次请求的起始new Date-请求返回的exectime
url https://weibo.co 固定
returntype META 固定

0x03 改写JS

1. 先把调用函数拿过来。

function test(pass, servertime, nonce) {
    rsaPubkey = "EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443"
    var f = new sinaSSOEncoder.RSAKey;
    f.setPublic(rsaPubkey, "10001");
    b = f.encrypt([servertime, nonce].join("\t") + "\n" + pass)
    return b
}

2. 除了参数sp,其他全部可以用Python直接实现,具体代码见下文。

PS. base64也可以用JS内的方法实现,写个调用函数就行了。

function b64(username) {
    a = sinaSSOEncoder.base64.encode(encodeURIComponent(username));
    return a
}

0x04 代码

# -*- encoding: utf-8 -*-
'''
@File    :   0x05-weibo.com.py
home.php?mod=space&uid=116177    :   2019/12/12 18:17:26
@Author  :   独孤孤独嘟咕噜犊子
home.php?mod=space&uid=59980 :   1.0
home.php?mod=space&uid=95579    :   https://www.jianshu.com/u/6a4c6ef97be7
@Desc    :   微博登录RSA+其他
'''

# start

import execjs
import requests
import time
import json
import re
import random
import base64
from urllib.parse import quote, unquote

# 初始化参数
HEADERS = {
    'User-Agent':
    'Mozilla/5.0 (Linux; Android 8.0; DUK-AL20 Build/HUAWEIDUK-AL20; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044353 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070333) NetType/WIFI Language/zh_CN Process/tools'
}
s = requests.Session()
s.headers.update(HEADERS)
loginURL = 'https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19)'

# 登录参数
username = '15555556666'
password = 'ermao6@qq.com'

# 加载js
with open('js/0x05-weibo.com.js') as f:  # 坑0x01 相对路径前面不带/,带/不报错但读不出数据
    jscode = f.read()
ctx = execjs.compile(jscode)  # execjs载入js代码

def get_key(username_b64):
    url = 'https://login.sina.com.cn/sso/prelogin.php'
    params = {
        'entry': 'weibo',
        'callback': 'sinaSSOController.preloginCallBack',
        'su': quote(username_b64, encoding='utf-8'),
        'rsakt': 'mod',
        'checkpin': '1',
        'client': 'ssologin.js(v1.4.19)',
        '_': int(time.time() * 1000)
    }
    res = s.get(url, params=params).text
    start = res.index('{')
    res = res[start:-1]
    json_res = json.loads(res)
    # print(json_res)
    return json_res

def get_verify(p):
    url = 'https://login.sina.com.cn/cgi/pin.php?s=0&p=' + p
    image = s.get(url).content
    ocr = 'http://127.0.0.1:678'  # 本地验证码识别接口
    code = s.post(ocr, data=image).text
    with open('js/image/' + code + '.png', 'wb') as f:
        f.write(image)
    return code

def login(username, password):
    # 通过base64库实现
    # username_b64 = str(base64.b64encode(username.encode('utf-8')), encoding='utf-8')

    # 通过js内函数实现
    username_b64 = ctx.call('b64', username)

    key = get_key(username_b64)
    imageCode = get_verify(key['pcid'])
    servertime = key['servertime'] + random.randint(2, 6) * 2
    # 通过call调用js代码里的函数
    enPass = ctx.call('test', password, servertime, key['nonce'])
    data = {
        'entry': 'weibo',
        'gateway': '1',
        'from': '',
        'savestate': '7',
        'qrcode_flag': 'false',
        'useticket': '1',
        'pagerefer': '',
        'pcid': key['pcid'],
        'door': imageCode,
        'vsnf': '1',
        'su': username_b64,
        'service': 'miniblog',
        'servertime': servertime,
        'nonce': key['nonce'],
        'pwencode': 'rsa2',
        'rsakv': key['rsakv'],
        'sp': enPass,
        'sr': '1536*864',
        'encoding': 'UTF-8',
        'prelt': random.randint(21, 45) * 2,
        'url':
        'https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack',
        'returntype': 'META'
    }
    result = s.post(loginURL, data=data).text
    if '&sign=' in result:  # 登录成功
        # 取下一个要跳转才能实现登录的URL
        success = re.findall(r'url='(.*?)'', result)
        if success:
            res = s.get(success[0]).text
            # 取下一个要跳转才能实现登录的URL
            next_url = re.findall(r"location.replace\('(.*?)'\)", res)[0]
            s.get(next_url)
            userid_url = 'https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&sudaref=weibo.com'
            # 登录成功,取userID
            res = s.get(userid_url).text
            start = res.index('{')
            end = res.index(')')
            res = res[start:end]
            json_res = json.loads(res)
            uid = json_res['userinfo']['uniqueid']
            print('登录成功 => UID:' + uid)
    else:  # 登录失败
        reason = re.findall(r'&reason=(.*?)'', result)
        if reason:
            print(unquote(reason[0], encoding='gbk'))
    # print(result)
    return result

if __name__ == "__main__":
    login(username, password)

结帖率:32% (6/19)

签到天数: 1 天

发表于 2024-2-27 10:10:16 | 显示全部楼层   贵州省黔东南苗族侗族自治州
收藏收藏,学习下!
回复 支持 反对

使用道具 举报

签到天数: 6 天

发表于 2019-12-31 16:24:39 | 显示全部楼层   江西省新余市
向大佬学习学习
回复 支持 反对

使用道具 举报

结帖率:33% (2/6)

签到天数: 13 天

发表于 2019-12-19 20:14:58 | 显示全部楼层   广东省汕尾市
为什么图片都看不到呢
回复 支持 反对

使用道具 举报

结帖率:46% (11/24)
发表于 2019-12-16 17:42:04 | 显示全部楼层   广东省惠州市
楼主辛苦了 讲这么细 难得
回复 支持 反对

使用道具 举报

结帖率:100% (6/6)

签到天数: 20 天

发表于 2019-12-16 17:39:47 | 显示全部楼层   河南省郑州市
给楼主顶一个
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表