压力大,写个脚本吧

import zipfile
import  base64
import os
def decrypt_password(encrypted_password):
    """解密base64编码的密码"""
    return base64.b64decode(encrypted_password).decode('utf-8')
def brute_force_zip(zip_file,password_file):
    """递归爆破文件
    读取文件密码"""
    with open(password_file,'r')as f:
        encrypted_password = f.readlines()

    # 尝试每个密码
    for encrypted_password in encrypted_password:
       password = decrypt_password(encrypted_password.strip())
       try:
           with zipfile.ZipFile(zip_file,'r')as zf:
               zf.extractall(pwd=password.encode('utf-8'))
           print(f"成功解压{zip_file},密码:{password}")
           return True
       except(zipfile.BadZipfile,RuntimeError):
           continue
    print(f"无法解压{zip_file},密码未找到")
    return False
def recursive_brute_force(start_zip,start_password_file):
    """递归爆破zip文件链"""
    current_zip = start_zip
    current_password_file = start_password_file
    while True:
        if not os.path.exists(current_zip) or not os.path.exists(current_password_file):
            print(f"文件{current_zip}或{current_password_file} 不存在")
            break
        if not brute_force_zip(current_zip,current_password_file):
            break
        # 更新下一个zip文件和密码
        current_zip = os.path.join(os.path.dirname(current_zip),f"password_{int(os.path.splitext(current_password_file)[0].split('_')[-1])-1}.txt")
        current_password_file=os.path.join(os.path.dirname(current_password_file),f"password_{int(os.path.splitext(current_password_file)[0].split('_')[-1])-1}.txt")
        if __name__=="__main__":
            start_zip="zip_99.zip"
            start_password_file = "password_99.txt"
            recursive_brute_force(start_zip,start_password_file)

使用password.txt里的密文base64解密后打开成套压缩包出现
最终文件
考虑到是将所有的password经过base64解密后拼接起来

最后扫二维码即可得到flag

Weevil's Whisper


分析wireshark得到upload里上传的php文件 分析并且写脚本

import base64
import zlib
def xor_decrypt(data, key):
    """实现与PHP代码相同的异或解密"""
    key_len = len(key)
    data_len = len(data)
    result = bytearray()

    for i in range(data_len):
        result.append(data[i] ^ ord(key[i % key_len]))
    return bytes(result)


# 定义密钥和标记
k = "161ebd7d"
kh = "45089b3446ee"
kf = "4e0d86dbcf92"
p = "lFDu8RwONqmag5ex"
def decrypt_data(encrypted_data):
    """解密数据"""
    try:
        # 提取有效载荷(去除头尾标记)
        start = encrypted_data.index(kh) + len(kh)
        end = encrypted_data.index(kf)
        payload = encrypted_data[start:end]

        # Base64解码
        decoded = base64.b64decode(payload)

        # XOR解密
        decrypted = xor_decrypt(decoded, k)

        try:
            # 尝试zlib解压缩
            decompressed = zlib.decompress(decrypted)
            return decompressed.decode('utf-8', errors='ignore')
        except:
            # 如果解压缩失败,直接返回解密后的数据
            return decrypted.decode('utf-8', errors='ignore')

    except Exception as e:
        return f"解密失败: {str(e)}"


response_data = "lFDu8RwONqmag5ex45089b3446eeSap6risomCodHP/PqrQaqvueeU+wURkueAeGLStP+bQE+HqsLq39zTQ2L1hsAA==4e0d86dbcf92"

print("解密后的响应数据:")
print(decrypt_data(response_data))

EzMisc

分析流量包 拿到private_key保存为PRIVATE.pem 接着使用

openssl rsa -in PRIVATE.pem -text

OpenSSL 工具来查看 PEM 格式的私钥文件(PRIVATE.pem)的信息
得到输出

 openssl rsa -in PRIVATE.pem -text
Private-Key: (2048 bit, 2 primes)
modulus:
    00:b3:ee:84:a7:c4:9a:b1:b8:6f:20:6e:b6:89:18:
    00:aa:9a:42:ec:4e:b1:b4:cd:de:74:f7:67:eb:9e:
    07:d0:82:09:72:bd:d3:b2:2b:3c:38:ee:49:70:49:
    52:1e:12:64:0a:44:f5:c6:d4:60:1e:6d:73:57:23:
    c8:a7:36:53:3d:96:37:bc:c8:0d:fb:14:ee:0f:09:
    fb:ae:83:eb:30:9f:68:62:15:04:f1:8b:77:94:11:
    a8:b4:ec:99:87:bf:df:4a:af:e1:77:d2:00:4e:a9:
    8e:de:04:e0:07:34:05:14:f2:8a:f8:d2:c7:86:27:
    58:60:49:1b:83:b3:23:d9:30:9a:48:e6:4e:66:d9:
    1a:ec:bb:0f:7e:39:eb:d9:ba:3f:87:73:2f:24:0c:
    7c:e9:11:03:3b:61:57:bc:90:21:63:d0:3f:56:20:
    5a:b6:ad:29:18:a0:ff:2e:2a:07:93:06:9f:8d:dd:
    ab:c5:00:37:4a:39:ee:af:c2:f1:39:67:8c:f6:73:
    59:91:94:78:0c:7f:e4:93:11:cb:2b:1b:25:45:e3:
    c6:90:e1:db:2e:0c:08:3b:d6:dd:a6:58:48:d6:4c:
    bb:81:0a:42:43:79:a8:8b:be:15:3d:df:3c:8e:79:
    e0:c8:07:ed:1a:a9:b6:87:43:30:da:35:59:83:0c:
    fa:45
publicExponent: 65537 (0x10001)
privateExponent:
    43:6e:a3:56:80:8e:fd:05:c2:d7:e3:c6:12:f0:e4:
    e7:0a:f3:03:be:a6:48:bd:52:9e:81:4d:f7:f6:7c:
    b5:3e:d6:ad:a2:c8:a0:a0:25:6c:ac:98:e7:35:03:
    4a:73:d7:fc:25:45:fa:e3:02:b6:c4:8c:12:5f:3d:
    c6:b4:cc:53:6b:65:ae:21:47:64:0e:be:fc:f1:df:
    d9:d2:64:a5:0f:48:be:61:64:3d:e5:e7:c5:9d:2c:
    9d:c9:81:ec:67:13:16:d9:7d:65:3b:55:94:25:65:
    7e:7d:53:3c:3f:d9:9b:b5:1e:32:0c:44:6c:59:78:
    7c:75:49:93:7c:e2:75:75:68:c8:ff:f4:51:65:a4:
    2e:78:64:6d:26:cf:7d:c1:b2:6a:61:2a:74:13:60:
    b9:48:37:34:25:95:a2:fa:65:1e:4d:fb:fd:d0:a0:
    81:a3:f9:33:48:1e:45:10:84:50:91:f5:dd:bc:e4:
    55:88:51:61:26:86:1f:54:13:c5:30:14:fc:3e:81:
    a0:dc:ac:e7:15:a5:2a:53:84:06:a9:31:bc:c1:b9:
    9f:00:00:00:00:00:00:00:28:ba:49:46:9d:7e:d5:
    39:92:3a:d8:ff:78:ee:2c:c4:a5:ce:31:d1:07:d7:
    07:85:0b:30:54:a2:02:0a:2b:41:fa:54:9b:7a:0c:
    6d
prime1:
    00:ee:84:15:f9:bd:f5:3b:8d:7c:08:9d:de:84:39:
    52:8c:5c:b7:f8:a7:71:11:7a:43:ba:38:30:3f:97:
    70:6c:27:a7:1c:33:44:7f:1d:18:f9:3c:e4:9c:40:
    be:03:f6:b3:76:7f:80:84:e4:32:40:01:38:c4:6c:
    32:81:bf:22:d8:e3:c2:dd:9a:8e:86:fd:ba:c8:68:
    6f:e5:66:71:1b:6a:ac:41:53:02:65:80:f4:f8:50:
    a6:7f:ae:7a:4c:0d:ab:c3:1e:b2:45:fe:54:b5:50:
    5e:70:88:52:a1:49:04:7a:4c:4e:d2:56:e2:04:00:
    00:00:00:00:00:0b:26:69:d7
prime2:
    00:c1:1f:0f:20:4a:6f:e3:b4:f5:8e:56:bd:45:34:
    2e:49:bc:b8:79:2b:b7:3a:fa:cd:fd:29:0a:3d:51:
    6e:8b:f6:83:50:6f:ce:3b:47:d0:cc:6b:84:ab:6a:
    ed:86:d5:ee:18:19:da:42:3b:f2:77:e3:d9:9e:06:
    0b:9f:cb:c7:2a:a9:ae:c4:09:4d:52:2b:ea:de:bb:
    c6:c2:96:b2:44:bf:37:3e:db:34:db:ee:1f:39:af:
    e9:ed:32:64:74:b9:50:0c:7c:68:2d:ae:ec:9f:f4:
    a2:b8:00:00:00:00:00:00:07:85:96:28:ba:99:31:
    be:91:46:7d:f2:7d:c8:11:43
exponent1:
    00:97:24:1a:2c:d4:a3:a6:a6:24:57:ed:7a:08:bd:
    ae:42:85:aa:8a:a5:c8:2f:74:13:a0:d8:64:32:97:
    cb:44:ad:e7:e6:25:d2:9c:de:1a:6a:2d:9d:0c:2a:
    b6:7e:1a:81:64:70:ad:47:08:b7:92:f9:73:38:7c:
    fb:90:5e:47:3d:bb:2e:4b:70:da:2a:4e:74:62:f4:
    53:1b:c1:cb:a0:bc:fb:04:b6:0e:49:b5:eb:05:c3:
    4d:8e:91:48:ac:12:e9:a9:ce:34:d7:c7:af:73:e9:
    c6:be:76:94:2d:e1:f0:35:73:4f:6b:58:65:08:d1:
    57:80:9e:3e:9d:ed:df:fc:a7
exponent2:
    00:bb:42:9e:ac:35:01:a1:cf:0a:7c:66:e7:48:7f:
    7c:92:cb:88:25:16:9a:a9:7a:20:db:66:3c:23:91:
    1e:9c:61:00:9b:b2:8e:4b:35:2b:e5:cc:2b:ec:fb:
    d6:2e:74:aa:56:7c:5b:02:f6:95:fa:62:d9:d5:3d:
    0f:70:77:6c:3c:96:24:7c:ba:78:5b:41:72:91:5f:
    8b:2f:8c:68:77:f8:e2:5c:f4:b9:a0:b8:99:56:9a:
    99:3e:03:2b:1d:73:c3:87:17:ea:fc:c1:2d:79:30:
    00:00:00:00:00:00:29:cc:dd:24:8f:a2:16:ae:0d:
    6a:37:fc:1e:8c:50:22:fb:79
coefficient:
    01:29:53:cd:70:dd:b9:65:3f:c5:8c:be:2e:2c:a8:
    72:bb:74:3a:be:03:d1:43:03:ff:fd:b3:e5:4e:5a:
    1e:9f:10:d3:f1:13:77:ce:7a:71:ab:3b:f4:7b:ce:
    07:40:7e:65:1f:f0:31:36:2c:79:7a:af:da:a4:e8:
    bc:07:4a:ba:21:6d:45:8f:7c:ad:73:34:7c:72:f3:
    e1:0a:59:ff:cd:65:7f:65:7c:63:e9:1b:a5:25:1d:
    e6:18:68:77:95:80:ea:89:3c:62:fb:a6:5b:2a:a6:
    e1:73:83:7b:9d:af:15:1f:1f:82:a0:01:8c:a9:15:
    05:cc:00:00:00:00:00:00
writing RSA key
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCz7oSnxJqxuG8g
braJGACqmkLsTrG0zd5092frngfQgglyvdOyKzw47klwSVIeEmQKRPXG1GAebXNX
I8inNlM9lje8yA37FO4PCfuug+swn2hiFQTxi3eUEai07JmHv99Kr+F30gBOqY7e
BOAHNAUU8or40seGJ1hgSRuDsyPZMJpI5k5m2Rrsuw9+OevZuj+Hcy8kDHzpEQM7
YVe8kCFj0D9WIFq2rSkYoP8uKgeTBp+N3avFADdKOe6vwvE5Z4z2c1mRlHgMf+ST
EcsrGyVF48aQ4dsuDAg71t2mWEjWTLuBCkJDeaiLvhU93zyOeeDIB+0aqbaHQzDa
NVmDDPpFAgMBAAECggEAQ26jVoCO/QXC1+PGEvDk5wrzA76mSL1SnoFN9/Z8tT7W
raLIoKAlbKyY5zUDSnPX/CVF+uMCtsSMEl89xrTMU2tlriFHZA6+/PHf2dJkpQ9I
vmFkPeXnxZ0sncmB7GcTFtl9ZTtVlCVlfn1TPD/Zm7UeMgxEbFl4fHVJk3zidXVo
yP/0UWWkLnhkbSbPfcGyamEqdBNguUg3NCWVovplHk37/dCggaP5M0geRRCEUJH1
3bzkVYhRYSaGH1QTxTAU/D6BoNys5xWlKlOEBqkxvMG5nwAAAAAAAAAouklGnX7V
OZI62P947izEpc4x0QfXB4ULMFSiAgorQfpUm3oMbQKBgQDuhBX5vfU7jXwInd6E
OVKMXLf4p3ERekO6ODA/l3BsJ6ccM0R/HRj5POScQL4D9rN2f4CE5DJAATjEbDKB
vyLY48Ldmo6G/brIaG/lZnEbaqxBUwJlgPT4UKZ/rnpMDavDHrJF/lS1UF5wiFKh
SQR6TE7SVuIEAAAAAAAACyZp1wKBgQDBHw8gSm/jtPWOVr1FNC5JvLh5K7c6+s39
KQo9UW6L9oNQb847R9DMa4Srau2G1e4YGdpCO/J349meBgufy8cqqa7ECU1SK+re
u8bClrJEvzc+2zTb7h85r+ntMmR0uVAMfGgtruyf9KK4AAAAAAAAB4WWKLqZMb6R
Rn3yfcgRQwKBgQCXJBos1KOmpiRX7XoIva5ChaqKpcgvdBOg2GQyl8tErefmJdKc
3hpqLZ0MKrZ+GoFkcK1HCLeS+XM4fPuQXkc9uy5LcNoqTnRi9FMbwcugvPsEtg5J
tesFw02OkUisEumpzjTXx69z6ca+dpQt4fA1c09rWGUI0VeAnj6d7d/8pwKBgQC7
Qp6sNQGhzwp8ZudIf3ySy4glFpqpeiDbZjwjkR6cYQCbso5LNSvlzCvs+9YudKpW
fFsC9pX6YtnVPQ9wd2w8liR8unhbQXKRX4svjGh3+OJc9LmguJlWmpk+Aysdc8OH
F+r8wS15MAAAAAAAACnM3SSPohauDWo3/B6MUCL7eQKBgAEpU81w3bllP8WMvi4s
qHK7dDq+A9FDA//9s+VOWh6fENPxE3fOenGrO/R7zgdAfmUf8DE2LHl6r9qk6LwH
SrohbUWPfK1zNHxy8+EKWf/NZX9lfGPpG6UlHeYYaHeVgOqJPGL7plsqpuFzg3ud
rxUfH4KgAYypFQXMAAAAAAAA
-----END PRIVATE KEY-----

对上述进行分析
这是RSA模数,表示为十六进制格式。模数是两个素数的乘积,在RSA加密中是公开的,也是用于加密和解密的核心参数之一
这是公共指数,通常为65537(这是一个常见的选择,表示为0x10001)。它与模数一起形成公开密钥
这是私有指数,用于私钥解密。它是与模数相关的一个重要参数,被证明是私有的
这两个参数是生成RSA私钥所用的两个素数,分别称为p和q。它们共同决定了模数的值
这些是与prime1和prime2相关的指数,通常用来加速解密过程。它们是privateExponent对prime1-1和prime2-1的模
这是用于求解RSA私钥中p和q的系数,用于结合这两个素数的解密过程
使用脚本得到d具体可参考[](https://blog.csdn.net/Mmmidsummer/article/details/131094217)

import gmpy2
from Crypto.Util.number import long_to_bytes
e = 0x10001
n = 0x00b3ee84a7c49ab1b86f206eb6891800aa9a42ec4eb1b4cdde74f767eb9e07d0820972bdd3b22b3c38ee497049521e12640a44f5c6d4601e6d735723c8a736533d9637bcc80dfb14ee0f09fbae83eb309f68621504f18b779411a8b4ec9987bfdf4aafe177d2004ea98ede04e007340514f28af8d2c786275860491b83b323d9309a48e64e66d91aecbb0f7e39ebd9ba3f87732f240c7ce911033b6157bc902163d03f56205ab6ad2918a0ff2e2a0793069f8dddabc500374a39eeafc2f139678cf673599194780c7fe49311cb2b1b2545e3c690e1db2e0c083bd6dda65848d64cbb810a424379a88bbe153ddf3c8e79e0c807ed1aa9b6874330da3559830cfa45
dp = 0x0097241a2cd4a3a6a62457ed7a08bdae4285aa8aa5c82f7413a0d8643297cb44ade7e625d29cde1a6a2d9d0c2ab67e1a816470ad4708b792f973387cfb905e473dbb2e4b70da2a4e7462f4531bc1cba0bcfb04b60e49b5eb05c34d8e9148ac12e9a9ce34d7c7af73e9c6be76942de1f035734f6b586508d157809e3e9deddffca7
 for x in range(1,e):  #遍历X
    if (dp*e-1)%x==0:
        p=(dp*e-1)//x +1
        if n%p==0:
            q=n//p   #得到q
            phi=(p-1)*(q-1)  #欧拉函数
            d=gmpy2.invert(e,phi)  #求逆元
            print(d)

再对encrypted.enc文件进行dp泄露攻击

import gmpy2
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
e = 0x10001
n = 0xb3ee84a7c49ab1b86f206eb6891800aa9a42ec4eb1b4cdde74f767eb9e07d0820972bdd3b22b3c38ee497049521e12640a44f5c6d4601e6d735723c8a736533d9637bcc80dfb14ee0f09fbae83eb309f68621504f18b779411a8b4ec9987bfdf4aafe177d2004ea98ede04e007340514f28af8d2c786275860491b83b323d9309a48e64e66d91aecbb0f7e39ebd9ba3f87732f240c7ce911033b6157bc902163d03f56205ab6ad2918a0ff2e2a0793069f8dddabc500374a39eeafc2f139678cf673599194780c7fe49311cb2b1b2545e3c690e1db2e0c083bd6dda65848d64cbb810a424379a88bbe153ddf3c8e79e0c807ed1aa9b6874330da3559830cfa45
d = 0x436ea356808efd05c2d7e3c612f0e4e70af303bea648bd529e814df7f67cb53ed6ada2c8a0a0256cac98e735034a73d7fc2545fae302b6c48c125f3dc6b4cc536b65ae2147640ebefcf1dfd9d264a50f48be61643de5e7c59d2c9dc981ec671316d97d653b559425657e7d533c3fd99bb51e320c446c59787c7549937ce2757568c8fff45165a42e78646d26cf7dc1b26a612a741360b94837342595a2fa651e4dfbfdd0a081a3f933481e4510845091f5ddbce45588516126861f5413c53014fc3e81a0dcace715a52a538406a931bcc1b99f269282083dc86f28ba49469d7ed539923ad8ff78ee2cc4a5ce31d107d707850b3054a2020a2b41fa549b7a0c6d
# dp泄露攻击, n ,e, d
rsakey = RSA.construct((n, e, d))  # 重构私钥流
# 读取密文流
with open("C:\\Users\\Lenovo\\Desktop\\EzMisc_f15a94127c2cc1ede4b728e49c4d04ba\\encryted.enc", 'rb') as f:
    enc = f.read()
# 私钥流基于OAEP模式进行密钥填充
rsa = PKCS1_OAEP.new(rsakey)
try:
    m = rsa.decrypt(enc)  # 调用.decrypt()进行解密
    print(m)  # Assuming the decrypted message is a string
except Exception as ex:
    print("Decryption failed:", ex)

终于得到密文M1sc_1s_s0_e@sy!
打开7z压缩包 拿到图片发现全是像素点
根据提示图片经过了Arnold变换 使用猫脸变换脚本进行爆破

import matplotlib.pyplot as plt
import cv2
import numpy as np
def arnold_decode(image, shuffle_times, a, b):
    """ decode for rgb image that encoded by Arnold
    Args:
        image: rgb image encoded by Arnold
        shuffle_times: how many times to shuffle
    Returns:
        decode image
    """
    # 1:创建新图像
    decode_image = np.zeros(shape=image.shape)
    # 2:计算N
    h, w = image.shape[0], image.shape[1]
    N = h  # 或N=w

    # 3:遍历像素坐标变换
    for time in range(shuffle_times):
        for ori_x in range(h):
            for ori_y in range(w):
                # 按照公式坐标变换
                new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N
                new_y = ((-a) * ori_x + ori_y) % N
                decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
        image = np.copy(decode_image)

    return image


def arnold_brute(image, shuffle_times_range, a_range, b_range):
    for c in range(shuffle_times_range[0], shuffle_times_range[1]):
        for a in range(a_range[0], a_range[1]):
            for b in range(b_range[0], b_range[1]):
                print(f"[+] Trying shuffle_times={c} a={a} b={b}")
                decoded_img = arnold_decode(image, c, a, b)
                output_filename = f"flag_decodedc{c}_a{a}_b{b}.png"
                cv2.imwrite(output_filename, decoded_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
if __name__ == "__main__":
    img = cv2.imread("C:\\Users\\Lenovo\\Desktop\\flag.png")
    arnold_brute(img, (5, 8), (15, 17), (25, 30))//这里的参数可以随机调

reproduction

打开流量包进行分析

发现进行多次post请求怀疑是盲注 再进行分析发现每次响应200都会使position+1
现在我们提取请求与响应进行分析 tshark.exe -r hackme.pcapng -Y "http" -T fields -e urlencoded-form.value -e http.response.code> output.txt
然后对数据进行处理

def read_and_process_file(file_path):
    result_dict = []
    with open(file_path, 'r') as file:
        lines = file.readlines()
        for i in range(0, len(lines), 2):
            # 确保有两行可以读取
            if i + 1 < len(lines):
                key_line = lines[i].strip()  # 去除首尾空白字符
                value_line = lines[i + 1].strip()
                pos = key_line.split(',')[0].strip()
                # 截取第一行逗号后的内容作为key
                key = key_line.split(',')[-1].strip()
                # 将处理后的key和value添加到字典中
                result_dict.append({pos:{key:value_line}})
    return result_dict
# 假设你的文件路径是 'your_file.txt'
file_path = 'output.txt'
result = read_and_process_file(file_path)
print(result)

最后编写一个模拟服务端

from flask import Flask, request, jsonify
app = Flask(__name__)
# 定义一个字典,用于存储传入值和对应的响应也就是我们使用上一个脚本处理的数据
response_list = ["脚本处理的数据"]
@app.route('/api/check', methods=['POST'])
def get_response():
    # 从请求的表单数据中获取传入的position和hash参数
    data = request.form
    position = data.get('position', None)
    request_hash = data.get('hash', None)
    # 检查是否提供了position和hash参数
    if not position or not request_hash:
        return jsonify({'code': 400, 'message': 'Missing position or hash parameter'}), 400
    # 根据position找到对应的内部字典
    for item in response_list:
        nested_dict = item.get(position)
        if nested_dict and request_hash in nested_dict:
            # 如果找到匹配的哈希值,返回对应的状态码
            return jsonify({'code': 200, 'message': nested_dict[request_hash]}), int(nested_dict[request_hash])
    # 如果没有找到匹配的哈希值,返回404 Not Found
    return jsonify({'code': 404, 'message': 'Hash not found'}), 404
if __name__ == '__main__':
    app.run(debug=True)

最后在运行的时候使用client.exe应该能访问 但是我这里因为windows的局限性没用ping成功

NetHttP

打开流量包 看到http后面的echo里的字符很像base64加密
使用命令提取 tshark -r NetHttP.pcapng -Y "http" -T fields -e tcp.stream -e frame.number -e frame.len -e http.request.uri -e http.response.code > output.txt
找规律发现长度为465和469的都是密文 使用脚本转换

from collections import defaultdict
import re
import base64
# 读取提取的 HTTP 流量数据
with open("D:\\misc\\wireshark\\output.txt", "r") as file:
    lines = file.readlines()
# 按流号组织数据
stream_data = defaultdict(list)
for line in lines:
    # 使用 strip() 去除换行符,然后按制表符分割
    fields = line.strip().split("\t")
    # 检查字段数量
    if len(fields) == 5:
        stream_id, frame_num, frame_len, request_uri, response_code = fields
    else:
        # 如果字段不足,填充缺失字段为空字符串
        fields += [""] * (5 - len(fields))  # 确保字段数量为 5
        stream_id, frame_num, frame_len, request_uri, response_code = fields
    # 将数据添加到流号对应的列表中
    stream_data[stream_id].append({
        "frame_num": frame_num,
        "frame_len": int(frame_len) if frame_len else 0,  # 如果 frame_len 为空,默认值为 0
        "request_uri": request_uri,
        "response_code": response_code
    })
# 正则表达式匹配 echo%20 和 %20 之间的值
base64_pattern = re.compile(r"echo%20([^%]+)%20")
# 正则表达式匹配单引号里的值
single_quote_pattern = re.compile(r"==\s*'([^']+)'")
flag = ''
# 查找符合条件的流
for stream_id, packets in stream_data.items():
    request_packet = None
    response_packet = None
    # 查找请求包和响应包
    for packet in packets:
        if packet["request_uri"] != "" and (packet["frame_len"] == 469 or packet["frame_len"] == 465):  # 修改为实际的请求包长度
            request_packet = packet
        if packet["response_code"] != "" and packet["frame_len"] == 66:  # 修改为实际的响应包长度
            response_packet = packet
    # 如果找到匹配的请求和响应包,则输出请求 URL 并提取 Base64 数据
    if request_packet and response_packet:
        print(f"Stream ID: {stream_id}")
        print(f"Request URL: {request_packet['request_uri']}")
        # 提取 Base64 数据
        base64_match = base64_pattern.search(request_packet["request_uri"])
        if base64_match:
            base64_value = base64_match.group(1)  # 提取 Base64 编码的值
            try:
                # Base64 解码
                decoded_value = base64.b64decode(base64_value).decode('utf-8')
                print(f"Extracted Base64: {base64_value}")
                print(f"Decoded Value: {decoded_value}")
                # 提取单引号里的值
                single_quote_match = single_quote_pattern.search(decoded_value)
                if single_quote_match:
                    single_quote_value = single_quote_match.group(1)
                    flag += single_quote_value
                    print(f"Value inside single quotes: '{single_quote_value}'")
                else:
                    print("No value found inside single quotes.")
            except Exception as e:
                print(f"Error decoding Base64: {e}")
        else:
            print("No Base64 data found in the request URL.")
        print("-" * 40)
# 输出最终 flag
print(flag)

最终得到密文 将其base64解密 得到 S0I3iWhvszKbOM/OalKTA0fpm5O5chVVnYGyKd5nV4erAzRbV6V6w8b/UiOfQEc3Ijh00hFjYFU1HaxNub9GnlPS/lcam5mATkf2sJS6JgpJo6AShVRxWDYKKrojeUeBZj5MEPI8/4DGGGuHFxmx2bxAahdDe1cGnjTZGWONpNI=
发现加密私钥 和key进行解密

接着使用openssl

openssl rsa -in PRIVATE.pem -text
最后编写脚本

import base64
# RSA 参数
n = 75198391834610743089994427445022622171591577121191724448299339002435832997164232218413508119298295123274196848013892501604504507367027410527023618161491726166765575077336751590544863722532358737240337140569730023629526218796143738463727597005256155751094703947322244106639054703290232743344051122409847668979
d = 47823271942181380918380117208311303072917059719458472058236845602980348253487465624475587910710493956741157673197903864601280854518063619685915091953443290538916965993327948549512195024615088046785300748165298087812720446099735944950660175124872626742440697531498487595767064570672468310421018941583067770553
# Base64 解码密文
s = 'S0I3iWhvszKbOM/OalKTA0fpm5O5chVVnYGyKd5nV4erAzRbV6V6w8b/UiOfQEc3Ijh00hFjYFU1HaxNub9GnlPS/lcam5mATkf2sJS6JgpJo6AShVRxWDYKKrojeUeBZj5MEPI8/4DGGGuHFxmx2bxAahdDe1cGnjTZGWONpNI='
c_bytes = base64.b64decode(s)
# 将字节串转换为整数
c_int = int.from_bytes(c_bytes, byteorder='big')
# RSA 解密
m_int = pow(c_int, d, n)
# 将解密后的整数转换为字节串
m_bytes = m_int.to_bytes((m_int.bit_length() + 7) // 8, byteorder='big')
# 解码为字符串
try:
plaintext = m_bytes.decode('utf-8')
print("Decrypted plaintext:", plaintext)
except UnicodeDecodeError:
print("Decrypted bytes (not valid UTF-8):", m_bytes)

ez_forensics

使用vol分析拿到压缩包文件和文本
分析文本60=?+?(13+47) 得到

根据题目提示提取hashdump

在线网站爆破一下得到压缩包key

打开7z发现里面是MobaXterm的配置文件 密钥为flag_is_here 需要下载MobaXtermCipher.py
https://github.com/HyperSine/how-does-MobaXterm-encrypt-password/blob/master/python3/MobaXtermCipher.py
接着使用

python .\MobaXtermCipher.py dec -p flag_is_here DLulatnJIPtEF/EMGfysL2F58R4dfQIbQhzwuNqL