JS逆向—RSA逆向分析

JS逆向—RSA逆向分析

一. 分析思路

  1. 抓包分析定位关键字段
  2. 逆向分析找到加密函数和参数实现
  3. 编写脚本模拟发包实现

二. 具体实现

1. 抓包分析

image

得到关键字段uid和pwd,其中uid为用户名,pwd为加密编码后的结果

2. 加密代码逆向

搜索pwd得到关键的ajax代码

image

找到关键函数encryptedString和参数key_to_encode,password.val(),其中password.val()为输入的密码明文,key_to_encode是随机产生的参数。

在源码当中定位得到key_to_encode的生成,使用js脚本生成,显然是RSA加密

image

继续跟踪定位得到encryptedString函数,是用了一个RSA库实现,非常清晰。

image

至此,加密算法逆向分析结束。

三. python模拟

1. 加密算法模拟

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Util.number import bytes_to_long, long_to_bytes

# 假设的公钥组件
n_hex = "978C0A92D2173439707498F0944AA476B1B62595877DD6FA87F6E2AC6DCB3D0BF0B82857439C99B5091192BC134889DFF60C562EC54EFBA4FF2F9D55ADBCCEA4A2FBA80CB398ED501280A007C83AF30C3D1A142D6133C63012B90AB26AC60C898FB66EDC3192C3EC4FF66925A64003B72496099F4F09A9FB72A2CF9E4D770C41"
e = 65537  # 常见的RSA指数值

# 从十六进制字符串转换模数n到整数
n = int(n_hex, 16)

# 创建一个RSA公钥对象
rsa_key = RSA.construct((n, e))

# 加密函数
def encrypt_string(key, password):
    cipher = PKCS1_OAEP.new(key)  # 使用OAEP填充
    encrypted_bytes = cipher.encrypt(password.encode('utf-8'))  # 加密字符串
    return encrypted_bytes.hex()  # 返回加密后的十六进制字符串

# 假设password是待加密的字符串
password = "1234567"
encrypted = encrypt_string(rsa_key.publickey(), password)
print(f"Encrypted: {encrypted}")

2. 模拟登录

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Util.number import bytes_to_long, long_to_bytes
import requests

# 假设的公钥组件
n_hex = "978C0A92D2173439707498F0944AA476B1B62595877DD6FA87F6E2AC6DCB3D0BF0B82857439C99B5091192BC134889DFF60C562EC54EFBA4FF2F9D55ADBCCEA4A2FBA80CB398ED501280A007C83AF30C3D1A142D6133C63012B90AB26AC60C898FB66EDC3192C3EC4FF66925A64003B72496099F4F09A9FB72A2CF9E4D770C41"
e = 65537  # 常见的RSA指数值

# 从十六进制字符串转换模数n到整数
n = int(n_hex, 16)

# 创建一个RSA公钥对象
rsa_key = RSA.construct((n, e))

# 加密函数
def encrypt_string(key, password):
    cipher = PKCS1_OAEP.new(key)  # 使用OAEP填充
    encrypted_bytes = cipher.encrypt(password.encode('utf-8'))  # 加密字符串
    return encrypted_bytes.hex()  # 返回加密后的十六进制字符串

# 假设password是待加密的字符串
password = "1234567"
pwd = encrypt_string(rsa_key.publickey(), password)

# 构造请求头
headers = {
    'Host': 'passport.fang.com',
    'Cookie': 'g_sourcepage=txz_dl%5Egg_pc; global_cookie=o8zi3zwj7kyir93uvavm8vi8m1rlxwnyfoe; unique_cookie=U_o8zi3zwj7kyir93uvavm8vi8m1rlxwnyfoe*4; otherid=ddc7e676246bbe8e0a58210fd7d61042; token=903c85d9c3f4445192b474395a826940; __utma=147393320.1125698195.1719456429.1719456429.1719459272.2; __utmc=147393320; __utmz=147393320.1719456429.1.1.utmcsr=www1.fang.com|utmccn=(referral)|utmcmd=referral|utmcct=/; __utmb=147393320.2.10.1719459272; __utmt_t0=1; __utmt_t1=1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0',
    'Accept': '*/*',
    'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
    'Accept-Encoding': 'gzip, deflate',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With': 'XMLHttpRequest',
    'Origin': 'https://passport.fang.com',
    'Referer': 'https://passport.fang.com/?backurl=https%3A%2F%2Fpassport.fang.com%2F%3Fbackurl%3Dhttps%253A%252F%252Fwww1.fang.com%252F%E2%80%98',
    'Sec-Fetch-Dest': 'empty',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-origin',
    'Priority': 'u=1',
    'Te': 'trailers',
    # 注意:'Connection': 'close' 通常在requests库中不需要显式设置,因为requests会处理连接
}
uid = '121212'
data = {
    'uid': '121212',
    'pwd': '7111ead865ca918a83ffe93a925caf04064b549f4f9429945100b5c526e06db058ef0b7f58bce0b7ca14ea63bc9bbc601982d629fa63d2fad3c6b05648773ca609a9afba73dcac019004fa0746886948671d93d9aa3df078d771e9f689855e26d53199c6330f35d871cf7057aab28e25221d809272ab25e071242378e907ba91',
    'Service': 'soufun-passport-web',
    'AutoLogin': '1'
}

# 发送POST请求
response = requests.post(
    'https://passport.fang.com/loginwithpwdStrong.api',
    headers=headers,
    data=data
)

# 打印响应内容
print(response.text)

由于使用了验证码进行反爬,因此需要进一步分析验证码的破解,不在这里进行详细说明。

posted @ 2024-06-27 14:21  ONE_ZJ  阅读(20)  评论(0编辑  收藏  举报