首页 > 作文

重新加载js文件(页面重新加载JS方法)

更新时间:2023-04-05 21:06:52 阅读: 评论:0

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

本次的逆向目标是wb的登录,虽然登录的加密参数没有太多,但是登录的流程稍微复杂一点,经历了很多次中转,细分下来大约要经过九次处理才能成功登录。

在登录过程中遇到的加密参数只有一个,即密码加密,加密后的密码在获取 token 的时候会用到,获取 token 是一个 post 请求,其 form data 里的 sp 值就是加密后的密码,类似于:
e23c5d62dbf9f8364005f331e487873c70d7ab0e8dd2057c3e66d1ae5d2837ef1dcf86……

登录流程

首先来理清一下登录流程,每一步特殊的参数进都行了说明,没有提及的参数表示是定值,直接复制即可。

大致流程如下:

预登陆获取加密密码获取 token获取加密后的账号发送验证码校验验证码访问 redirect url访问 crossdomain2 url通过 passport url 登录

1.预登陆

预登陆为 get 请求,query string parameters 中主要包含两个比较重要的参数:su:用户名经过 ba64 编码得到,_: 13 位时间戳,返回的数据包含一个 json,可用正则提取出来,json 里面包含 retcode,rvertime,pcid,nonce,pubkey,rsakv, exectime 七个参数值,其中大多数值都是后面的请求当中要用到的,部分值是加密密码要用到的,返回数据数示例:

xxxxssocontroller.prelogincallback({    "retcode": 0,    "rvertime": 1627461942,    "pcid": "gz-1cd535198c0efe850b96944c7945e8fd514b",    "nonce": "gwbocl",    "pubkey": "eb2a38568661887fa180bddb5cabd5f21c7bfd59c090cb2d245......",    "rsakv": 1330428213,    "exectime": 16})

2.获取加密后的密码

密码的加密使用的是 rsa 加密,可以通过 python 或者 js 来获取加密后的密码,js 加密的逆向在后面拿出来单独分析。

3.获取 token

这个 token 值在后面的获取加密手机号、发送验证码、校验验证码等步骤中都会用到,获取 token 值为 post 请求,query string parameters 的值是固定的:client: ssologin.js(v1.4.19),form data 的值相对来说比较多,但是除了加密的密码以外,其他参数其实都是可以在第1步预登陆返回的数据里找到,主要的参数如下:

su:用户名经过 ba64 加密得到rvertime:通过第1步预登陆返回的 json 里面获取nonce:通过第1步预登陆返回的 json 里面获取rsakv:通过第1步预登陆返回的 json 里面获取sp:加密后的密码prelt:随机值

返回数据为 html 源码,可以从里面提取 token 值,类似于:
2ngfharzfafaip_qwx70npj8gw4lgj7rbcnbyb3rly3rpb24.,如果返回的 token 不是这种,则说明账号或者密码错误。

4.获取加密后的账号

前面我们遇到的 su 是用户名经过 ba64 加密得到,这里它对用户名进行了进一步的加密处理,加密后的用户名在发送验证码和校验验证码的时候会用到,get 请求,query string parameters 的参数也比较简单,token 就是第3步获取的 token 值,callback_url 是网站的主页我是一只小鸟,返回数据是 html 源码,可以使用 xpath 语法://input[@name=’encrypt_mobile’]/@value 来提取加密后的账号,其值类似于:f2de0b5e333a,这里需要注意的是,即便是同一个账号,每次加密的结果也是不一样的。

5.发送验证码

发送验证码是一个 post 请求,其参数也比较简单,query string parameters 里的 token 是第3步获取的 token,form data 里的 encrypt_mobile 是第4步获取的加密后的账号,返回的数据是验证码发送的状态,例如:{‘retcode’: 20000000, ‘msg’: ‘succ’, ‘data’: []}。

6.校验验证码

校验验证码是一个 post 请求,其参数也非常简单,query string parameters 里的 token 是第3步获取的 token,form data 里的 encrypt_mobile 是第4步获取的加密后的账号,code 是第5步收到的验证码,返回数据是一个 json,retcode 和 msg 代表校验的状态,redirect url 是校验步骤完成后接着要访问的页面,在下一步中要用到,返回的数据示例:

{  "retcode": 20000000,  "msg": "succ",  "data": {    "redirect_url": "https://login.xxxx.com.cn/sso/login.php?entry=xxxxx&returntype=meta&crossdomain=1&cdult=3&alt=alt-ntcxnjmymta2oa==-1630292617-yf-78b1dde6833847576b0dc4b77a6c77c4-1&savestate=30&url=https://xxxxx.com"  }}

7.访问 redirect url

这一步的请求接口其实就是第6步返回的 redirect url,get 请求,类似于:
https://login.xxxx.com.cn/sso/login.php?entry=xxxxx&returntype=meta……

返回的数据是 html 源码,我们要从中提取 crossdomain2 的 url,提取的结果类似于:
https://login.xxxx.com.cn/crossdomain2.php?action=login&entry=xxxxx……,同样的,这个 url 也是接下来需要访问的页面。

8.访问 crossdomain2 url

这一步的请求接口就是第7步提取的 crossdomain2 url,get 请求,类似于:
https://login.xxxx.com.cn/crossdomain2.php?action=login&entry=xxxxx……

返回的数据同样是 html 源码,我们要从中提取真正的登录的 url,提取的结果类似于:
/d/file/titlepic/xxxxx.com url 就能实现登录操作了。

9.通过 passport url 登录

这是最后一步,也是真正的登录操作,get 请求,请求接口就是第8步提取的 passport url,类似于:
/d/file/titlepic/xxxxx.com id 和用户名,类似于:

({"result":true,"urinfo":{"uniqueid":"5712321368","displayname":"tomb"}});

自此,wb的完整登录流程已完成,可以直接拿登录成功后的 cookies 进行其他操作了。

加密密码逆向

在登录流程中,第2步是获取加密后的密码,在登录的第3步获取 token 里,请求的 query string parameters 包含了一个加密参数 sp,这个就是加密后的密码,接下来我们对密码的加密进行逆向分析。

直接全局搜索 sp 关键字,发现有很多值,这里我们又用到了前面讲过的技巧,尝试搜索 sp=、sp: 或者 var sp 等来缩小范围,在本案例中,我们尝试搜索 sp=,可以看到在 index.js 里面只有一个值,埋下断点进行调试,可以看到 sp 其实就是 b 的值:

ps:搜索时要注意,不能在登录成功后的页面进行搜索,此时资源已刷新,重新加载了,加密的 js 文件已经没有了,需要在登录界面输入错误的账号密码来抓包、搜索、断点。

继续往上追踪这个 b 的值,关键代码有个 if-el 语句,分别埋下断点,经过调试可以看到 b 的值在 if 下面生成:

分析一下两行关键代码:

f.tpublic(me.rsapubkey, "10001");b = f.encrypt([me.rvertime, me.nonce].join("t") + "n" + b)

me.rsapubkey、me.rvertime、me.nonce 都是第1步预登陆返回的数据。

把鼠标移到 f.tpublic 和 f.encrypt,可以看到分别是 br 和 bt 函数:

分别跟进这两个函数,可以看到都在一个匿名函数下面:

直接将整个匿名函数复制下来,去掉最外面的匿名函数,进行本地调试,调试过程中会提示 navigator 未定义,查看复制的源码,里面用到了 navigator.appname 和 navigator.appversion,直接定义即可,或者置空都行。

navigator = {    appname: "netscape",    appversion: "5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/91.0.4472.124 safari/537.36"}

继续调试会发现在 var c = this.dopublic(b); 提示对象不支持此属性或方法,搜索 dopublic 发现有一句 bq.prototype.dopublic = bs;,这里直接将其改为 dopublic = bs; 即可。

分析整个 rsa 加密逻辑,项目管理课程其实也可以通过 python 来实现,代码示例(pubkey 需要补全):

import rsaimport binasciipre_parameter = {        "retcode": 0,        "rvertime": 1627461942,        "pcid": "gz-1cd535198c0efe850b96944c7945e8fd514b",        "nonce": "gwbocl",        "pubkey": "eb2a38568661887fa180bddb5cabd5f21c7bfd59c090cb2d245......",        "rsakv": 1330428213,        "exectime": 16}password = '12345678'public_key = rsa.publickey(int(pre_parameter['pubkey'], 16), int('10001', 16))text = '%st%sn%s' % (pre_parameter['rvertime'], pre_parameter['nonce'], password)encrypted_str = rsa.encrypt(text.encode(), public_key)encrypted_password = binascii.b2a_hex(encrypted_str).decode()print(encrypted_password)

完整代码

github 关注 k 哥爬虫,持续分享爬虫相关代码!欢迎 star !
https://github.com/kgepachong/

**以下只演示部分关键代码,不能直接运行!**完整代码仓库地址:
/d/file/titlepic/crawler/

关键 js 加密代码架构

navigator = {    appname: "netscape",    appversion: "5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/91.0.4472.124 safari/537.36"}function bt(a) {}function bs(a) {}function br(a, b) {}// 此处省略 n 个函数bl.prototype.nextbytes = bk;dopublic = bs;bq.prototype.tpublic = br;bq.prototype.encrypt = bt;this.rsakey = bqfunction getencryptedpassword(me, b) {    br(me.pubkey, "10001");    b = bt([me.rvertime, me.nonce].join("t") + "n" + b);    return b}// 测试样例// var me = {//     "retcode": 0,//     "rvertime": 1627283238,//     "pcid": "gz-a9243276722ed6d4671f21310e2665c92ba4",//     "nonce": "n0y3sz",//     "pubkey": "eb2a38568661887fa180bddb5cabd5f21c7bfd59c090cb2d245a87ac253062882729293e5506350508e7f9aa3bb77f4333231490f915f6d63c55fe2f08a49b353f444ad3993cacc02db784abbb8e42a9b1bbfffb38be18d78e87a0e41b9b8f73a928ee0ccee1f6739884b9777e4fe9e88a1bbe495927ac4a799b3181d6442443",//     "rsakv": "1330428213",//     "exectime": 13// }// var b = '12312312312'  // 密码// console.log(getencryptedpassword(me, b))

python 登录关键代码

#!/usr/bin/env python3# -*- coding: utf-8 -*-import reimport jsonimport timeimport ba64import binasciiimport rsaimport execjsimport requestsfrom lxml import etree# 判断某些请求是否成功的标志respon_success_str = 'succ'pre_login_url = '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'get_token_url = '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'protection_url = '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'nd_code_url = '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'confirm_url = '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'headers = {    'host': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',    'referer': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',    'c-ch-ua': '" not;a brand";v="99", "google chrome";v="91", "chromium";v="91"',    'ur-agent': 'mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) c加入学生会的好处hrome/91.0.4472.124 safari/537.36'}ssion = requests.ssion()def get_pre_parameter(urname: str) -> dict:    su = ba64.b64encode(urname.encode())    time_now = str(int(time.time() * 1000))    params = {        'entry': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',        'callback': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',        'su': su,        'rsakt': 'mod',        'checkpin': 1,        'client': 'ssologin.js(v1.4.19)',        '_': time_now,    }    respon = ssion.get(url=pre_login_url, params=params, headers=headers).text    parameter_dict = json.loads(re.findall(r'((.*))', respon)[0])    # print('1.【pre parameter】: %s' % parameter_dict)    return parameter_dictdef get_encrypted_password(pre_parameter: dict, password: str) -> str:    # 通过 js 获取加密后的密码    # with open('encrypt.js', 'r', encoding='utf-8') as f:    #     js = f.read()    # encrypted_password = execjs.compile(js).call('getencryptedpassword', pre_parameter, password)    # # print('2.【encrypted password】: %s' % encrypted_password)    # return encrypted_password    # 通过 python 的 rsa 模块和 binascii 模块获取加密后的密码    public_key = rsa.publickey(int(pre_parameter['pubkey'], 16), int('10001', 16))    text = '%st%sn%s' % (pre_parameter['rvertime'], pre_parameter['nonce'], password)    encrypted_str = rsa.encrypt(text.encode(), public_key)    encrypted_password = binascii.b2a_hex(encrypted_str).decode()    # print('2.【encrypted password】: %s' % encrypted_password)    return encrypted_passworddef get_token(encrypted_password: str, pre_parameter: dict, urname: str) -> str:    su = ba64.b64encode(urname.encode())    data = {        'entry': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',        'gateway': 1,        'from': '',        'savestate': 7,        'qrcode_flag': fal,        'uticket': 1,        'pagerefer': '',        'vsnf': 1,        'su': su,        'rvice': 'miniblog',        'rvertime': pre_parameter['rvertime'],        'nonce': pre_parameter['nonce'],        'pwencode': 'rsa2',        'rsakv': pre_parameter['rsakv'],        'sp': encrypted_password,        'sr': '1920*1080',        'encoding': 'utf-8',        'prelt': 38,        'url': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler',        'returntype': 'meta'    }    respon = ssion.post(url=get_token_url, headers=headers, data=data)    # respon.encoding = 'gbk'    ajax_login_url = re.findall(r'replace("(.*)")', respon.text)[0]    token = ajax_login_url.split('token%3d')[-1]    if 'weibo' not in token:        # print('3.【token】: %s' % token)        return token    el:        rai exception('登录失败! 用户名或者密码错误!')def get_encrypted_mobile(token: str) -> str:    params = {        'token': token,        'callback_url': '脱敏处理,完整代码关注 github:/d/file/titlepic/crawler'    }    respon = ssion.get(url=protection_url, params=params, headers=headers)    tree = etree.html(respon.text)    encrypted_mobile = tree.xpath("//input[@name='encrypt_mobile']/@value")[0]    # print('4.【encrypted mobile】: %s' % encrypted_mobile)    return encrypted_mobiledef nd_code(token: str, encrypt_mobile: str) -> str:    params 刘心情人节伴奏= {'token': token}    data = {'encrypt_mobile': encrypt_mobile}    respon = ssion.post(url=nd_code_url, params=params, data=data, headers=headers).json()    if respon['msg'] == respon_success_str:        code = input('请输入验证码: ')        # print('5.【code】: %s' % code)        return code    el:        # print('5.【failed to nd verification code】: %s' % respon)        rai exception('验证码发送失败: %s' % respon)def confirm_code(encrypted_mobile: str, code: str, token: str) -> str:    params = {'token': token}    data = {        'encrypt_mobile': encrypted_mobile,        'code': code    }    respon = ssion.post(url=confirm_url, params=params, data=data, headers=headers).json()    if respon['msg'] == respon_success_str:        redirect_url = respon['data']['redirect_url']        # print('6.【redirect url】: %s' % redirect_url)        return redirect_url    el:        # print('6.【验证码校验失败】: %s' % respon)        rai exception('验证码校验失败: %s' % respon)def get_cross_domain2_url(redirect_url: str) -> str:    respon = ssion.get(url=redirect_url, headers=headers).text    cross_domain2_url = re.findall(r'replace("(.*)")', respon)[0]    # print('7.【cross domain2 url】: %s' % cross_domain2_url)    return cross_domain2_urldef get_passport_url(cross_domain2_url: str) -> str:    respon = ssion.get(url=cross_domain2_url, headers=headers).text    passport_url_str = re.findall(r'tcrossdomainurllist((.*))', respon)[0]    passport_url = json.loads(passport_url_str)['arrurl'][0]    # print('8.【passport url】: %s' % passport_url)    return passport_urldef login(passport_url: str) -> none:    respon = ssion.get(url=passport_url, headers=headers).text    login_result = json.loads(respon.replace('(', '').replace(');', ''))    if login_result['result']:        ur_unique_id = login_result['urinfo']['uniqueid']        ur_display_name = login_result['urinfo']['displayn学期总结500字ame']        print('登录成功!用户 id:%s,用户名:%s' % (ur_unique_id, ur_display_name))    el:        rai exception('登录失败:%s' % login_result)def main():    urname = input('请输入登录账号: ')    password = input('请输入登录密码: ')    # 1.预登陆,获取一个字典参数,包含后面要用的 rvertime、nonce、pubkey、rsakv    pre_parameter = get_pre_parameter(urname)    # 2.通过 js 或者 python 获取加密后的密码    encrypted_password = get_encrypted_password(pre_parameter, password)    # 3.获取 token    token = get_token(encrypted_password, pre_parameter, urname)    # 4.通过 protection url 获取加密后的手机号    encrypted_mobile = get_encrypted_mobile(token)    # 5.发送手机验证码    code = nd_code(token, encrypted_mobile)    # 6.校验验证码,校验成功则返回一个重定向的 url    redirect_url = confirm_code(encrypted_mobile, code, token)    # 7.访问重定向的 url,提取 crossdomain2 url    cross_domain2_url = get_cross_domain2_url(redirect_url)    # 8.访问 crossdomain2 url,提取 passport url    passport_url = get_passport_url(cross_domain2_url)    # 9.访问 passport url 进行登录操作    login(passport_url)if __name__ == '__main__':    main()

本文发布于:2023-04-05 21:04:04,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/670dd0793c60b16d6b7a0069fbb329ba.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:重新加载js文件(页面重新加载JS方法).doc

本文 PDF 下载地址:重新加载js文件(页面重新加载JS方法).pdf

标签:验证码   密码   代码   完整
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图