目录
一、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 plaintextplaintext = "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, unpaddef 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 ciphertextdef 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 plaintextplaintext = "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, unpaddef 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 ciphertextmobile = "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().readrsa = 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 keydef encrypt(plaintext, public_key):plaintext = plaintext.encode()cipher = PKCS1_cipher.new(public_key)ciphertext = cipher.encrypt(plaintext)ciphertext = base64.b64encode(ciphertext).decode()return ciphertextdef decrypt(ciphertext, private_key):cipher = PKCS1_cipher.new(private_key)ciphertext = base64.b64decode(ciphertext)plaintext = cipher.decrypt(ciphertext, 0).decode()return plaintextpublic_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 base64def encrypt(plaintext, public_key):plaintext = plaintext.encode()cipher = PKCS1_cipher.new(public_key)ciphertext = cipher.encrypt(plaintext)ciphertext = base64.b64encode(ciphertext).decode()return ciphertextpublic_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 base64def 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, unpaddef 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 ciphertextkey1 = "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_cipherurl = "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 ciphertextpublic_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 requeststimestamp = 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())