已迁移平台:segmentfault,搜索 erma0

换平台了,简书发什么都锁定,广告一堆,趁早倒闭吧。

第六天

JavaScript逆向练习6

0x01 目标网址

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计算

returntype

META

固定

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

2.png

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

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

点进第一个结果,点花括号格式化一下,Ctrl+F搜prelt,只有两个结果,而且第一个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

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

@Time : 2019/12/12 18:17:26

@Author : 独孤孤独嘟咕噜犊子

@Version : 1.0

@Link : 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)

android 微博分享回调函数,【JS逆向】新浪微博登录RSA+其他 | 每日JS相关推荐

  1. JS逆向steam登录

    JS逆向steam登录 前言: 我们爬虫有时候,会遇到登录才能获取到数据的情况,最开始的时候我们只需要加入请求的data参数就可以,可是现在网站为了反爬,对登录的密码或者账号都做了加密处理,如果我们不 ...

  2. 微博分享回调成功,但是微博客户端却进入草稿箱,提示错误码 8995。第三方问题排查思路总结

    问题再现 问题描述:Android平台微博分享,app收到api回调,表示分享成功,但是打开微博客户端app,该分享进入草稿箱,并提示 : (8995)app auth fail for appKey ...

  3. android 微博分享需要测试账号密码,Android社交登录授权、分享SDK,支持微信、微博和QQ...

    社交登录授权,分享SDK 支持微信.微博.QQ登录授权 微信好友.微信朋友圈.微博.QQ好友.QQ空间分享 Gradle compile 'com.elbbbird.android:socialsdk ...

  4. Android 微博分享失败问题

    Android开发中微信微博分享或是登录功能是很常见的.但是本人遇到了一个问题,就是在eclipse开发时以上操作都正常,可是发布后以上功能均不可用了,找了半天终于发现了问题的所在,贴在此处及供参考. ...

  5. python爬虫js逆向加密,Web爬虫处理参数js加密、js混淆、js逆向

    中国空气质量在线监测平台(https://www.aqistudy.cn/html/city_detail.html)在众多的练习中,关闭了前台数据信息的展示,也就是说现在网页是这样的: 但我们主要学 ...

  6. java web 微博系统,java web网站集成新浪微博登录

    给网站添加第三方登录的功能,研究了下新浪微博登录的接口,本来想使用它提供的那种js代码库的方式,结果始终搞不定,由于不精通js只能够放弃.下载了个java的SDK包:weibo4j-oauth2-be ...

  7. python爬虫 房天下js逆向模拟登录

    js逆向学习后跟着教程第一次实战.目标链接 这次用到的是requests和execjs,execjs主要是用来执行js代码,win系统直接在命令行pip install execjs安装就ok了. 网 ...

  8. 微博点击图片放大html,新浪微博图片放大效果[artZoom.js]

    (本文示例脚本于2010-05-28更新) 如果说09年是SNS年,那10年肯定微博年,各大网站都推出或者准备推出自己的微博.我这几天都在看新浪微博,对新浪微博的用户体验很欣赏,有些细节我自己也琢磨了 ...

  9. Android之利用回调函数onCreateDialog实现加载对话框

    效果图: 有时候我们需要去做一个Activity启动时的数据加载对话框,关于对话框的各种实现可以通过一起学android之对话框 Dialog的创建(7)来完成,在这里另外介绍一个,利用onCreat ...

最新文章

  1. PAT甲级1037 Magic Coupon:[C++题解]贪心
  2. 角反射器的功能及应用
  3. 户籍恢复需要体检吗_脑梗死后脚麻能恢复吗?需要多久能恢复呢?
  4. Linux-目录和文件管理(二)
  5. 在.Net中执行js
  6. python归并排序算法实现_排序算法之归并排序(附 Python 与 JS 实现)
  7. hdoj6298:Maximum Multiple(找规律,总结)
  8. 通过运算符重载实现复数加减
  9. saga中的saga(A Saga on Sagas) - balavatasky - 博客园
  10. Financial Modeling with Crystal Ball and Excel
  11. Pycharm配置Git教程
  12. python做语音识别
  13. 《shard 入门精要》冯乐乐
  14. 计算机考在职研究生有用吗,报考计算机在职研究生有用吗?
  15. C语言项目-后宫选妃系统-第三天-终结
  16. 2021全球程序员收入报告出炉
  17. Super-Resolution Mapping of Impervious Surfaces from Remotely Sensed Imagery with Points-of-Interest
  18. Mysql的常见面试题 + 索引原理分析
  19. 【资源】国内镜像网站
  20. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:异常问题解析!

热门文章

  1. 特斯拉首次展示上海超级工厂内部照片 预计年底投产
  2. 用虚幻引擎制作逼真毛发:获取白皮书!
  3. 华为nova7 pro防水吗
  4. firfox新标签页打开的设置与优化
  5. 阿里云点播集成播放器的SDK时遇到的黑屏有声音的问题
  6. WebGL自学教程——WebGL示例:开始
  7. mac 10.9 输入法切换
  8. SQL增加语句的方法
  9. 太康县计算机培训学校,河南省太康县职业中等专业学校
  10. Ubuntu18.04.4服务器 安装mysql5.7,navicat远程连接