阅读 33

JS逆向之美团网模拟登录!这教程杠杠滴~

切忌用于一切非法途径,否则后果自行承担!

地址:passport.meituan.com/account/uni…

一、页面分析

打开网页输入账号:138xxxx8888,密码:123456789点击登录抓包

h5Fingerprint和password的模样基本上就是这个亚子的了,正片请往下看…

二、加密解析

1.password解析

加密定位

搜索password参数:

发现 encrypt.encrypt(dataJson.password)加密关键字(encrypt),点击绿色标注的地方进入js文件代码段:

参数解密

打下断点,并点击登录重新抓包,看看是否能够使断点生效:

发现断点生效:dataJson.password = encrypt.encrypt(dataJson.password),控制台打印dataJson.password看看

接下来单步执行:

到这里已经很明了的看到了,函数传入参数str = 123456789(密码),继续单步执行

到这里就已经很明了了,RSA加密。对于RSA,没有必要使用JS进行模拟还原,这里使用python还原即可(当然这里只针对原生的RSA加密生效,如果网站开发人员对算法有所改写的话另说),所以先使用python还原,最后验证提交是否正确即可。

对于RSA算法原理请移步大佬文章参考, 所以我们只需要知道私钥即可进行算法还原,接下来返回开始的断点函数:

鼠标指针放置this.publicKey上面

控制台打印this.publicKey

python还原RSA:

def Rsa_Password(pwd) ->str:

"""

RSA——Python还原算法

:param pwd: 密码明文

:return: 加密字符串

"""

publickey= 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRD8YahHualjGxPMzeIWnAqVGMIrWrrkr5L7gw+5' \

'XT55iIuYXZYLaUFMTOD9iSyfKlL9mvD3ReUX6Lieph3ajJAPPGEuSHwoj5PN1UiQXK3wzAPKcpwrrA' \

'2V4Agu1/RZsyIuzboXgcPexyUYxYUTJH48DeYBGJe2GrYtsmzuIu6QIDAQAB'

rsaPublickey = '-----BEGIN RSA PRIVATE KEY-----\n'+publickey+'\n-----END RSA PRIVATE KEY-----'

key = RSA.importKey(rsaPublickey)

cipher= PKCS1_v1_5.new(key)

encode_str = base64.b64encode(cipher.encrypt(pwd.encode()))

pwd_encode = str(encode_str,encoding='utf-8')

print(pwd_encode)

print('长度:'+ str(len(pwd_encode)))

return pwd_encode

执行结果:

2.h5Fingerprint解析

加密定位

搜索h5Fingerprint

打下断点点击登录:

通过控制台输出可以看的长度很像了,其实他就是h5Fingerprint。单步执行

进入新函数,参数rul是一个网址,在return处打上断点,执行到断点处并打印返回值

加密定位完成,下面讲解参数情况

参数解密

这里先执行完所有断点,重新进入这个函数

这里的 Rohr_Opt.reload和rohr.reload两个匿名函数如下

通过Rohr_Opt.reload进入函数观察

再通过rohr.reload进入函数观察发现其实他们都是执行同一个函数:

在函数return的地方打下断点,并执行到此处

单步执行进入下一步,代码跳到了上面的x(e)方法中

这里参数e变成了一个对象:

其实这里的逻辑就是将原本的e(url)参数先进行一次x(e)加密,然后再将加密之后的字符串赋值给新的e(对象)的sign值,然后再对对象e进行一次x(e)加密,下面看看x方法

进入c(e)

这里先将参数e转字符串然后子在给Oe方法进行处理再赋值给e变量

紧接着再调用ZcGxo(x,e)方法进行处理(参数是一个btoa和e),并赋值给e,最后e即是h5Fingerprint的值

进入ZcGxo方法看看

打下断点,并执行到这里

控制台输出:

到这里已经将加密逻辑过的差不多了,下面讲一讲e参数。

e是一个对象

其中cts,ts为时间戳,mT为滑块轨迹(由于登录需要过滑块验证,这里不对滑块进行讲解)可以写死进行提交测试即可,其余参数也可写死进行测试。

所有东西准备就绪,将涉及加密的js方法代码拿出来改写即可,下面node运行结果:

3.python调用模拟请求

模拟登录代码:

# -- coding: utf-8 --

# @Time : 2021/3/4 15:49

# @Author : Los Angeles Clippers

# @Email: 229456906@qq.com

# @sinaemail: angelesclippers@sina.com

import execjs

import base64

from Crypto.Cipher import PKCS1_v1_5

from Crypto.PublicKey import RSA

import requests

import re

session = requests.session()

"""

passport.meituan.com/account/uni…

"""

def Rsa_Password(pwd) ->str:

"""

RSA——Python还原算法

:param pwd: 密码明文

:return: 加密字符串

"""

publickey= 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCRD8YahHualjGxPMzeIWnAqVGMIrWrrkr5L7gw+5' \

'XT55iIuYXZYLaUFMTOD9iSyfKlL9mvD3ReUX6Lieph3ajJAPPGEuSHwoj5PN1UiQXK3wzAPKcpwrrA' \

'2V4Agu1/RZsyIuzboXgcPexyUYxYUTJH48DeYBGJe2GrYtsmzuIu6QIDAQAB'

rsaPublickey = '-----BEGIN RSA PRIVATE KEY-----\n'+publickey+'\n-----END RSA PRIVATE KEY-----'

key = RSA.importKey(rsaPublickey)

cipher= PKCS1_v1_5.new(key)

encode_str = base64.b64encode(cipher.encrypt(pwd.encode()))

pwd_encode = str(encode_str,encoding='utf-8')

print(pwd_encode)

print('长度:'+ str(len(pwd_encode)))

return pwd_encode

def get_h5Fingerprint(url) -> str:

with open('h5m.js', 'r', encoding='utf-8') as f:

js = f.read()

h5Fingerprint = execjs.compile(js).call('get_h5Fingerprint', url)

print('h5Fingerprint:', h5Fingerprint)

print(len(h5Fingerprint))

return h5Fingerprint

def get_encUrl():

url = "登录 | 美团网"

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',

}

response = session.get(url, headers=headers).text

encUrl_ = "passport.meituan.com" + re.search(r'id="J-normal-form" action="(.*?)"', response).group(1)

encUrl = encUrl_.replace('=', '=').replace('amp;', '')

print('encUrl:', encUrl)

csrf = re.search(r'"csrf" value="(.*?)"', response).group(1)

uuid = re.search(r'uuid=(.*?)&', encUrl).group(1)

token_id = re.search(r'token_id=(.*?)&', encUrl).group(1)

continues = encUrl.split('continue=')[1]

print('csrf:', csrf)

return (encUrl, csrf, uuid, token_id, continues)

def login(dat, h5m, pwd, username):

url = "passport.meituan.com/account/uni…

data = {

'countrycode': '86',

'email': username,

'password': pwd,

'origin': 'account-login',

'csrf': dat[1],

'requestCode': '',

'responseCode': '',

'h5Fingerprint': h5m,

'device_name': '',

'device_type': 'Chrome',

'device_os': 'Window',

'sdkType': 'pc',

}

params = {

'risk_partner': '0',

'risk_platform': '1',

'risk_app': '-1',

'uuid': dat[2],

'token_id': dat[3],

'service': 'www',

'continue': dat[4],

}

headers = {

'Host': 'passport.meituan.com',

'Origin': 'passport.meituan.com',

'Referer': '登录 | 美团网',

'sec-ch-ua': '"Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"',

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',

'X-CSRF-Token': dat[1],

'X-Requested-With': 'XMLHttpRequest',

}

print(data)

print(params)

response = session.post(url, json=data, params=params, headers=headers).text

print(response)

if __name__ == '__main__':

p = '123456789'

username = ''

pwd = Rsa_Password(p)

dat = get_encUrl()

h5m = get_h5Fingerprint(dat[0])

login(dat, h5m, pwd, username)

网页结果:

与网页结果对比,验证了我们的RSA还原正确,且h5Fingerprint参数也通过了验证。

总结

good good xuexi,day day up,少掉头发。

近期有很多朋友通过私信咨询有关Python学习问题。为便于交流,点击蓝色自己加入讨论解答资源基地

源码也点击上面哦

文章分类
代码人生
文章标签