Загрузка данных


import requests
import base64
import struct
import json

BASE = "http://<target>:5000"  # замените на адрес

R = 0xE1000000000000000000000000000000
MASK128 = (1 << 128) - 1

def gf128_mul(x, y):
    z = 0
    v = x & MASK128
    for i in range(128):
        if (y >> (127 - i)) & 1:
            z ^= v
        msb = (v >> 127) & 1
        v = ((v << 1) & MASK128)
        if msb:
            v ^= R
    return z & MASK128

def gf128_inv(x):
    # x^(2^128 - 2) = x^{-1} в GF(2^128)
    # Используем возведение в степень
    result = 1
    base = x
    exp = (1 << 128) - 2
    while exp:
        if exp & 1:
            result = gf128_mul(result, base)
        base = gf128_mul(base, base)
        exp >>= 1
    return result

def ghash(H_bytes, aad, ct):
    H = int.from_bytes(H_bytes, "big")
    len_a_bits = len(aad) * 8
    len_c_bits = len(ct) * 8
    len_block = struct.pack(">QQ", len_a_bits, len_c_bits)
    data = aad + ct + len_block
    Y = 0
    for i in range(0, len(data), 16):
        block = data[i:i+16]
        if len(block) < 16:
            block = block + b"\x00" * (16 - len(block))
        X = int.from_bytes(block, "big")
        Y = gf128_mul(Y ^ X, H)
    return Y.to_bytes(16, "big")

def ghash_probe(aad, ct):
    r = requests.post(f"{BASE}/ghash_probe", json={
        "who": "attacker",
        "aad_hex": aad.hex(),
        "ct_b64": base64.b64encode(ct).decode()
    })
    return base64.b64decode(r.json()["ghash_b64"])

# 1. Получаем FLAG_BLOB
r = requests.get(f"{BASE}/flag")
flag_blob = base64.b64decode(r.json()["flag_blob"])
FLAG_IV = flag_blob[:12]
FLAG_CT = flag_blob[12:-16]
FLAG_TAG = flag_blob[-16:]
print(f"FLAG_IV = {FLAG_IV.hex()}")
print(f"FLAG_CT = {FLAG_CT.hex()}")
print(f"FLAG_TAG = {FLAG_TAG.hex()}")

# 2. Восстанавливаем H
# GHASH(H, X, "") = X * H^2 для X = 16 байт
X = b"\x00" * 15 + b"\x01"  # 1
g1 = ghash_probe(X, b"")
H2 = int.from_bytes(g1, "big")
print(f"H^2 = {g1.hex()}")

# GHASH(H, "", Y) = Y * H^2 XOR L * H, где L = len_block(0, 128) = 0x80
Y = b"\x00" * 15 + b"\x02"  # 2
g2 = ghash_probe(b"", Y)
# g2 = Y*H^2 XOR 0x80*H
# => 0x80*H = g2 XOR Y*H^2
# => H = (g2 XOR Y*H^2) * inv(0x80)
Y_int = int.from_bytes(Y, "big")
g2_int = int.from_bytes(g2, "big")
L = 0x80  # len_block для пустого aad и ct длины 16: pack(">QQ", 0, 128) = 0x80
# Подождите, len_block = pack(">QQ", 0, 16*8) = pack(">QQ", 0, 128)
# Это 16 байт: 00...00 00...80. Как int это 0x80.
# Но в GHASH len_block обрабатывается как блок. Да, int = 0x80.
H_times_L = g2_int ^ gf128_mul(Y_int, H2)
H = gf128_mul(H_times_L, gf128_inv(L))
H_bytes = H.to_bytes(16, "big")
print(f"H = {H_bytes.hex()}")

# Проверка: GHASH(H, X, "") должно быть X*H^2
# ghash(H_bytes, X, "") == g1?
assert ghash(H_bytes, X, b"") == g1, "H verification failed"
print("H verified!")

# 3. Получаем E_K(FLAG_J0) через /aes_ecb_tenant
FLAG_J0 = FLAG_IV + b"\x00\x00\x00\x01"
r = requests.post(f"{BASE}/aes_ecb_tenant", json={
    "who": "victim",
    "block_b64": base64.b64encode(FLAG_J0).decode()
})
E_K_J0 = base64.b64decode(r.json()["cipher_b64"])
print(f"E_K(J0) = {E_K_J0.hex()}")

# 4. known = FLAG_TAG XOR E_K(J0) = GHASH(H, AAD_VICTIM, FLAG_CT)
known = bytes(a ^ b for a, b in zip(FLAG_TAG, E_K_J0))
print(f"known = {known.hex()}")

# 5. G0 = GHASH(H, AAD_PREFIX || 0^16, FLAG_CT)
AAD_PREFIX = b"user-aad-prefix:"
G0 = ghash(H_bytes, AAD_PREFIX + b"\x00" * 16, FLAG_CT)
print(f"G0 = {G0.hex()}")

# 6. SECRET_VICTIM = (known XOR G0) * H^{-(N-1)}
# N = 2 + ceil(len(FLAG_CT)/16) + 1
N = 2 + (len(FLAG_CT) + 15) // 16 + 1
# SECRET_VICTIM на позиции 1 (0-индексация), вклад = SECRET_VICTIM * H^(N-1)
# known = G0 XOR SECRET_VICTIM * H^(N-1)
# => SECRET_VICTIM = (known XOR G0) * H^{-(N-1)}
diff = bytes(a ^ b for a, b in zip(known, G0))
diff_int = int.from_bytes(diff, "big")
# H^{-(N-1)} = (H^{-1})^(N-1)
H_inv = gf128_inv(H)
H_inv_pow = 1
for _ in range(N - 1):
    H_inv_pow = gf128_mul(H_inv_pow, H_inv)
SECRET_VICTIM = gf128_mul(diff_int, H_inv_pow).to_bytes(16, "big")
print(f"SECRET_VICTIM = {SECRET_VICTIM.hex()}")

# 7. Отправляем на /verify
r = requests.post(f"{BASE}/verify", json={
    "who": "victim",
    "blob": base64.b64encode(flag_blob).decode(),
    "aad_hex": SECRET_VICTIM.hex()
})
print(r.json())
if "plaintext_b64" in r.json():
    flag = base64.b64decode(r.json()["plaintext_b64"]).decode()
    print(f"FLAG: {flag}")