这只是一篇记录,所以没有过程
使用 HttpCanary 抓包获得如下文本:
dFEy3gnB3tfSbY1pCKYRFNOvL29NHC/NzQpqZt2U/C0jGm20ctb8z8913yfjk6OAChbygUNf9NT2aqxS3uljmZl/dUlpi7O4lt6UniHdKTVe5MnJhVG3f68q7fd0cRMiwiUBPNz04vGr4aW1Hl7vM1vtl8eynEQj4mjvBbnqsYfwXaKP0a2k/6+MfaQnpJ0SoaRrm06dM2BqavHHuY3afsIR0/gmyY7nUanLQmv6zb07SbqxJoLu6tGF0q4o4vayc6vUHD+1DbSCN4gWd2Q+TQU31MLYWac4oyW1oLBdE7vBmVMKY14Yg3RIfvkEzmri4QrOk+cwaWimZosd2p8KTb97lRF5Ahy/G0ENvszOV9UJ8bDvgkCU9T32UZI+qrdRvOblvKciU7rB4dUAhDlcakzuM3vwtynZGBR21Q8NOJ6SBZGkfm1aKQzXcvBo6wnkDcyW8Il0WbW+0Kn9FwKRliG4Q4cWEWto3G3FVX0nj8+uecGwr5zKDLYXkZPItteR6p/dyjMwElLamOy6RqDqvGTIoeCKrA4FIPJE8o+yaInyrDjqAN6BXQ3+ktTa78YW+oPp/mV6ZYVHK3k0lNNsSrQ2m3+G9D6+jVb1iCrZ3EbaBlmBT0oHE6D6L33ZR6Lt
看一眼觉得是 base64,于是直接解码,转 utf-8,得到乱码,再猜,应该是 AES。
直接祭出之前在论坛上看到的帖子 某 APP 的网络逆向分析过程
一顿操作过后查看算法助手的日志,通过搜索密文前面部分 dFEy3gnB3tf
,找到加密算法,果然是 AES/CBC。
得到密钥如下:
- 原文:
jCCHeqNSbI2xrb5O
- base64:
akNDSGVxTlNiSTJ4cmI1Tw==
- hex:
6a43434865714e53624932787262354f
iv 如下:
- 原文:略
- base64:
dFEy3gnB3tfSbY1pCKYRFA==
- hex:
745132de09c1ded7d26d8d6908a61114
解密内容:
- base64:
068vb00cL83NCmpm3ZT8LSMabbRy1vzPz3XfJ+OTo4AKFvKBQ1/01PZqrFLe6WOZmX91SWmLs7iW3pSeId0pNV7kycmFUbd/ryrt93RxEyLCJQE83PTi8avhpbUeXu8zW+2Xx7KcRCPiaO8Fueqxh/Bdoo/RraT/r4x9pCeknRKhpGubTp0zYGpq8ce5jdp+whHT+CbJjudRqctCa/rNvTtJurEmgu7q0YXSriji9rJzq9QcP7UNtII3iBZ3ZD5NBTfUwthZpzijJbWgsF0Tu8GZUwpjXhiDdEh++QTOauLhCs6T5zBpaKZmix3anwpNv3uVEXkCHL8bQQ2+zM5X1QnxsO+CQJT1PfZRkj6qt1G85uW8pyJTusHh1QCEOVxqTO4ze/C3KdkYFHbVDw04npIFkaR+bVopDNdy8GjrCeQNzJbwiXRZtb7Qqf0XApGWIbhDhxYRa2jcbcVVfSePz655wbCvnMoMtheRk8i215Hqn93KMzASUtqY7LpGoOq8ZMih4IqsDgUg8kTyj7JoifKsOOoA3oFdDf6S1Nrvxhb6g+n+ZXplhUcreTSU02xKtDabf4b0Pr6NVvWIKtncRtoGWYFPSgcToPovfdlHou0=
- hex:
d3af2f6f4d1c2fcdcd0a6a66dd94fc2d231a6db472d6fccfcf75df27e393a3800a16f281435ff4d4f66aac52dee96399997f7549698bb3b896de949e21dd29355ee4c9c98551b77faf2aedf774711322c225013cdcf4e2f1abe1a5b51e5eef335bed97c7b29c4423e268ef05b9eab187f05da28fd1ada4ffaf8c7da427a49d12a1a46b9b4e9d33606a6af1c7b98dda7ec211d3f826c98ee751a9cb426bfacdbd3b49bab12682eeead185d2ae28e2f6b273abd41c3fb50db48237881677643e4d0537d4c2d859a738a325b5a0b05d13bbc199530a635e188374487ef904ce6ae2e10ace93e7306968a6668b1dda9f0a4dbf7b951179021cbf1b410dbeccce57d509f1b0ef824094f53df651923eaab751bce6e5bca72253bac1e1d50084395c6a4cee337bf0b729d9181476d50f0d389e920591a47e6d5a290cd772f068eb09e40dcc96f0897459b5bed0a9fd1702919621b8438716116b68dc6dc5557d278fcfae79c1b0af9cca0cb6179193c8b6d791ea9fddca33301252da98ecba46a0eabc64c8a1e08aac0e0520f244f28fb26889f2ac38ea00de815d0dfe92d4daefc616fa83e9fe657a6585472b793494d36c4ab4369b7f86f43ebe8d56f5882ad9dc46da0659814f4a0713a0fa2f7dd947a2ed
直接对比抓包得到的内容和解密内容,发现抓包的内容前面部分是 IV,后面部分根本对应不上,那就应该是先拼接了数据,然后再 base64,由于 base64 的算法问题导致对不上(可以百度看看 base64 的算法,与原文是 4:3 的关系)。
所以,全部转为 hex 看看,
Node.js
console.log(Buffer.from('抓包数据', 'base64').toString('hex'));
Python
from base64 import b64decode
from binascii import hexlify
print(hexlify(b64decode('抓包数据')).decode('utf-8'))
都得到以下结果:
745132de09c1ded7d26d8d6908a61114d3af2f6f4d1c2fcdcd0a6a66dd94fc2d231a6db472d6fccfcf75df27e393a3800a16f281435ff4d4f66aac52dee96399997f7549698bb3b896de949e21dd29355ee4c9c98551b77faf2aedf774711322c225013cdcf4e2f1abe1a5b51e5eef335bed97c7b29c4423e268ef05b9eab187f05da28fd1ada4ffaf8c7da427a49d12a1a46b9b4e9d33606a6af1c7b98dda7ec211d3f826c98ee751a9cb426bfacdbd3b49bab12682eeead185d2ae28e2f6b273abd41c3fb50db48237881677643e4d0537d4c2d859a738a325b5a0b05d13bbc199530a635e188374487ef904ce6ae2e10ace93e7306968a6668b1dda9f0a4dbf7b951179021cbf1b410dbeccce57d509f1b0ef824094f53df651923eaab751bce6e5bca72253bac1e1d50084395c6a4cee337bf0b729d9181476d50f0d389e920591a47e6d5a290cd772f068eb09e40dcc96f0897459b5bed0a9fd1702919621b8438716116b68dc6dc5557d278fcfae79c1b0af9cca0cb6179193c8b6d791ea9fddca33301252da98ecba46a0eabc64c8a1e08aac0e0520f244f28fb26889f2ac38ea00de815d0dfe92d4daefc616fa83e9fe657a6585472b793494d36c4ab4369b7f86f43ebe8d56f5882ad9dc46da0659814f4a0713a0fa2f7dd947a2ed
不难看出,抓包得到的数据就是拼接了 IV 和密文,然后 base64 编码。
Node.js
import { createDecipheriv } from 'node:crypto';
/**
* aes-128-cbc 解密
* @Param text hex 密文
* @param key hex 密钥
* @param iv hex 向量
* @returns 原文
*/
function aesDecrypt(text: string, key: string, iv: string) {
const decipher = createDecipheriv(
'aes-128-cbc',
Buffer.from(key, 'hex'),
Buffer.from(iv, 'hex')
);
return decipher.update(text, 'hex', 'utf-8') + decipher.final('utf-8');
}
const text = '请求体';
// 密钥是固定的
const secret = '6a43434865714e53624932787262354f';
// 将响应体转化为 hex
const hexText = Buffer.from(text, 'base64').toString('hex');
// 取出 iv
const iv = hexText.slice(0, 32);
// 取出密文
const content = hexText.slice(32);
// 因为 secret 是 16 字节,所以 iv 也是 16 字节,用 aes-128-cbc 解密
console.log(aesDecrypt(content, secret, iv));
Python
from base64 import b64decode
from binascii import hexlify, unhexlify
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
def aes_decrypt(cipher_text: bytes, secret: bytes, iv: bytes) -> str:
"""Decrypts cipher_text using AES"""
decipher = AES.new(secret, AES.MODE_CBC, iv)
return unpad(decipher.decrypt(cipher_text), AES.block_size).decode('utf-8')
text = '请求体'
# 密钥是固定的
secret = '6a43434865714e53624932787262354f'
# 将响应体 base64 转化为 hex
text = hexlify(b64decode(text))
# 取出 iv
iv = text[:32]
# 取出密文
content = text[32:]
print(aes_decrypt(unhexlify(content), unhexlify(secret), unhexlify(iv)))
最后,得到明文如下:
<?xml version="1.0" encoding="UTF-8"?><result resultCode="0"><uploadResult><uploadTaskID>2swcGFp</uploadTaskID><newContentIDList length="1"><newContent><contentID>1D11rPNF7A5T18920240319221148535</contentID><contentName>IMG_20240319_195233.jpg</contentName><isNeedUpload>0</isNeedUpload><fileEtag>1881502553506057480</fileEtag><overridenFlag>0</overridenFlag><fileVersion>1881490571142887732</fileVersion></newContent></newContentIDList></uploadResult></result>