js逆向-JS加密破解进阶

发布时间:2023年12月18日

目录

一、JS逆向进阶一:破解AES加密

(一)AES对称加密算法原理

(二)破解AES加密

(三)实战:发现报告网

二、JS逆向进阶二:破解RSA加密

(一)RSA非对称加密算法原理

(二)破解RSA加密

(三)实战:36氪:破解RSA加密,逆向解析36氪登陆参数

三、JS逆向进阶三:解决多个请求使用相同加密算法的情况

四、JS逆向进阶四:破解参数混合加密

五、JS逆向进阶五:解决密钥需要额外获取的情况

六、JS逆向进阶六:基础JS混淆加密破解


一、JS逆向进阶一:破解AES加密

(一)AES对称加密算法原理

安装一个模块:pip install pycryptodome

# 把明文拆分成 128bits 的部分,如果最后的部分不足128bits,就需要进行 padding(填充)
# 密钥的长度 128bits, 192bits, 256bits
# 长度不固定
# CBC 是最常用的模式,还需要一个128bits 的iv(随机向量)

import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

# 加密
def encrypt(plaintext, key, iv):
    # 三个值均转为二进制形式
    plaintext = plaintext.encode()
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    # 密文(加密后的文字)(pad:进行填充)
    ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
    # 变为base64的形式
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext

# 解密
def decrypt(ciphertext, key, iv):
    ciphertext = base64.b64decode(ciphertext)
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
    plaintext = plaintext.decode()
    return plaintext



plaintext = "apple"
key = "0123456789abcdef"
iv = "abcdef0123456789"

ciphertext = encrypt(plaintext, key, iv)
print(ciphertext)
plaintext = decrypt(ciphertext, key, iv)
print(plaintext)

(二)破解AES加密

以下为加密数据

添加xhr断点,以下为加密部分的js函数

import base64
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

def encrypt(plaintext, key, iv):
    plaintext = plaintext.encode()
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
    # 变为base64的形式
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext

def decrypt(ciphertext, key, iv):
    ciphertext = base64.b64decode(ciphertext)
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)
    plaintext = plaintext.decode()
    return plaintext



plaintext = "abcd"
key = "0123456789abcdef"
iv = "abcdef0123456789"

code = encrypt(plaintext, key, iv)
url = "http://127.0.0.1:5000/api/C14L02"
headers = {
    "User-Agent": "xxxx",
    "Refer": "http://127.0.0.1:5000/api/C14L02"
}
data = {
    "code":code
}
res = requests.post(url, headers= headers, data=data)
print(res.json())

(三)实战:发现报告网

发现密码区域为加密数据

添加xhr断点,找到书写加密函数的区域并添加debug断点,放开url的xhr断点,可看到具体的值

在控制台中可看到的时间戳为13位,比要求数据少3位。但是在python中的时间戳time.time()函数刚好为整数部分

data参数中加密函数中:

在控制台查看分析数据

_()函数:md5加密字符串长度不变,经过验证为md5加密。D().ne()函数:因AES加密前后不一致,猜测,现在点进去这个函数

注意:

(1)iv此网站只截取字符串的后16位

(2)在requests发送请求时,此网站data要求转为json格式数据,请求头添加content-type参数不然会报错

(3)python中最终转为了base64格式,网站中的AES加密后为16进制的格式,需要修改一下

import time
import hashlib
import requests
import json
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

def encrypt(plaintext, key, iv):
    plaintext = plaintext.encode()
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
    ciphertext = ciphertext.hex()
    return ciphertext

mobile = "19244359876"
password = "WAJ23Aww"
ts = int(time.time())

# D().ne("".concat(a).concat(o), _()("".concat(s.slice(3)).concat(a)))

plaintext = str(ts) + password
key = mobile[3:] + str(ts)
key = hashlib.md5(key.encode()).hexdigest()
iv = key[-16:]
ciphertext = encrypt(plaintext, key, iv)

url = "https://api.fxbaogao.com/mofoun/user/login/byPhoneNumber"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "Refer": "https://www.fxbaogao.com/"
}
data = {
    "data" : ciphertext,
    "mobile": mobile,
    "time": str(ts)
}
data = json.dunmps(data)
res = requests.post(url=url, headers= headers, data=data)
print(res.text)

二、JS逆向进阶二:破解RSA加密

(一)RSA非对称加密算法原理

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
from Crypto import Random
import base64

# 生成key
def genKeys():
    random_generator = Random.new().read
    rsa = RSA.generate(2048, random_generator)
    private_key = rsa.exportKey()
    public_key = rsa.public_key().exportKey()

    with open("./C14/rsa_private_key.pem", "wb") as f:
        f.write(private_key)

    with open("./C14/rsa_public_key.pem", "wb") as f:
        f.write(public_key)    

def get_key(key_file):
    with open(key_file, "r") as f:
        data = f.read()
        key = RSA.importKey(data)
    return key

def encrypt(plaintext, public_key):
    plaintext = plaintext.encode()
    cipher = PKCS1_cipher.new(public_key)
    ciphertext = cipher.encrypt(plaintext)
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext

def decrypt(ciphertext, private_key):
    cipher = PKCS1_cipher.new(private_key)
    ciphertext = base64.b64decode(ciphertext)
    plaintext = cipher.decrypt(ciphertext, 0).decode()
    return plaintext

public_key = get_key("./C14/rsa_public_key.pem")
private_key = get_key("./C14/rsa_private_key.pem")

plaintext = "hello"
ciphertext = encrypt(plaintext, public_key)
print(ciphertext)

plaintext = decrypt(ciphertext, private_key)
print(plaintext)

(二)破解RSA加密

此处为加密数据部分

xhr断点

import time
import requests
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
from Crypto import Random
import base64


def encrypt(plaintext, public_key):
    plaintext = plaintext.encode()
    cipher = PKCS1_cipher.new(public_key)
    ciphertext = cipher.encrypt(plaintext)
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext


public_key = """xxxxxx"""
public_key = RSA.importKey(public_key)
ts = int(time.time()*1000)
ciphertext = encrypt(str(ts), public_key)
print(ciphertext)

url = "http://127.0.0.1:5000/api/C14L05"
headers = {
    "User-Agent":"xxx",
    "referer":"http://127.0.0.1:5000/C14L05"
}
data = {
    "code":ciphertext
}
res = requests.post(url, headers=headers, data=data)
print(res.json())

(三)实战:36氪:破解RSA加密,逆向解析36氪登陆参数

此处为加密形式

全局搜索"mobileNo",并打断点查看数据内容

控制台可知,后面部分即为电话号和密码

点击进入,前面的函数的js

由函数可知上方的i即为publickey

import time
import requests
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher
from Crypto import Random
import base64


def encrypt(plaintext, public_key):
    plaintext = plaintext.encode()
    cipher = PKCS1_cipher.new(public_key)
    ciphertext = cipher.encrypt(plaintext)
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext

# 需要带上---部分
public_key = """-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCeiLxP4ZavN8qhI+x+whAiFpGWpY9y1AHSQC86qEMBVnmqC8vdZAfxxuQWeQaeMWG07lXhXegTjZ5wn9pHnjg15wbjRGSTfwuZxSFW6sS3GYlrg40ckqAagzIjkE+5OLPsdjVYQyhLfKxj/79oOfjl/lV3rQnk/SSczHW0PEyUbQIDAQAB-----END PUBLIC KEY-----"""
public_key = RSA.importKey(public_key)
ts = int(time.time() * 1000)
mobile = encrypt("19833679937", public_key)
password = encrypt("ssddef", public_key)

url = "https://gateway.36kr.com/api/mus/login/byMobilePassword"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "referer":"https://36kr.com/",
    "Content-Type": "application/json"
}
data = {
    "krtoken" : "",
    "param" : { 
        "countryCode": "86",
        "mobileNo": mobile,
        "password" : password
    },
    "partner_id": "web",
    "timestamp": ts

}
data = json.dumps(data)
res = requests.post(url, headers=headers, data=data)
print(res.json())

三、JS逆向进阶三:解决多个请求使用相同加密算法的情况

JS函数如下

书写代码:

如下图可知,多个请求使用相同加密算法

四、JS逆向进阶四:破解参数混合加密

以下为加密数据,全局搜索”acode"

import base64
import hashlib
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

def encrypt(plaintext, key, iv):
    plaintext = plaintext.encode()
    key = key.encode()
    iv = iv.encode()
    
    cipher =AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
    ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))
    ciphertext = ciphertext.b64encode(ciphertext).decode()
    return ciphertext

key1 = "0123456789abcdef"
key2 = "987654321abcdef"
iv = "abcdef0123456789"

ts = int(time.time()*1000)
code = encrypt(str(ts), key1, iv)
acode = hashlib.md5(code.encode()).hexdigest()
bcode = encrypt(code, key2, iv)

url = "https://127.0.0.1:5000/api/C14L09"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "referer":"https://127.0.0.1:5000/api/C14L09"
    "Content-Type": "application/json"
}
data = {
    "timestamp":ts,
    "acode":acode,
    "bcode":bcode
}
data = json.dumps(data)
res = requests.post(url, headers=headers, data=data)
print(res.json())

五、JS逆向进阶五:解决密钥需要额外获取的情况

以下位置为加密数据部分

以下为函数部分

如上述函数知,需要获取public_key

import requests
import base64
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as PKCS1_signature
from Crypto.Cipher import PKCS1_v1_5 as PKCS1_cipher


url = "https://127.0.0.1:5000/api/C14L11/get_key"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "referer":"https://127.0.0.1:5000/api/C14L11"
}
res = requests.post(url, headers=headers)

def encrypt(plaintext, public_key):
    plaintext = plaintext.encode()
    cipher = PKCS1_cipher.new(public_key)
    ciphertext = cipher.encrypt(plaintext)
    ciphertext = base64.b64encode(ciphertext).decode()
    return ciphertext

public_key = RSA.importKey(res.text)
code = encrypt("abc123", public_key)

url = "https://127.0.0.1:5000/api/C14L11/get_data"
data = {
    "code": code

}
res = requests.post(url, headers=headers, data=data)
print(res.json())

六、JS逆向进阶六:基础JS混淆加密破解

以下为加密函数

在控制台中查看各个函数代表的含义

import time
import random
import requests


timestamp = int(time.time() * 1000)
rand = int(random.random() * 500 + 100)
mySign = str(timestamp) + '-' + str(rand)
print(mySign)

url = "https://127.0.0.1:5000/api/C14L12"
headers = {
    "sign": mySign,
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
    "referer":"https://127.0.0.1:5000/api/C14L12"
}
res = requests.get(url, headers=headers)
print(res.json())
文章来源:https://blog.csdn.net/liyunyang2000/article/details/134622123
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。