cscg is loooong

This commit is contained in:
2026-03-18 05:59:37 +01:00
parent 0c1e63fb3a
commit 7ac813dc0c
1109 changed files with 14511 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
import pyshark
import struct
import zlib
import os
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
# --- Constants ---
SESSION_KEY = bytes.fromhex("fb2ed4f1837a722b149df99a4021177e")
SESSION_ID_LE = struct.pack('<I', 0x392DECAA)
os.makedirs("smm2_streams", exist_ok=True)
print("[*] Loading PCAP via PyShark...")
cap = pyshark.FileCapture('./decrypted_capture.pcapng', display_filter='udp')
success_count = 0
for i, pkt in enumerate(cap):
try:
udp_payload = bytes.fromhex(pkt.udp.payload.replace(':', ''))
if not udp_payload.startswith(b'\x32\xab\x98\x64'):
continue
src_mac_str = pkt.wlan.sa.replace(':', '')
src_mac = bytes.fromhex(src_mac_str)
conn_id = udp_payload[5:6]
header_nonce = udp_payload[8:16]
tag = udp_payload[16:32]
ciphertext = udp_payload[32:]
crc = zlib.crc32(SESSION_ID_LE + src_mac)
decrypted = False
plaintext = b""
for crc_endian in ['>I', '<I']:
crc_bytes = struct.pack(crc_endian, crc)[:3]
iv = crc_bytes + conn_id + header_nonce
try:
cipher_gcm = Cipher(algorithms.AES(SESSION_KEY), modes.GCM(iv, tag))
decryptor = cipher_gcm.decryptor()
plaintext = decryptor.update(ciphertext) + decryptor.finalize()
decrypted = True
break
except Exception:
continue
if decrypted:
# --- PIA Message Parser ---
offset = 0
msg_count = 0
# State variables (inherit from previous message if missing)
msg_flags = 0
payload_size = 0
protocol_type = 0
while offset < len(plaintext):
msg_count += 1
presence_flags = plaintext[offset]
offset += 1
if presence_flags & 1:
msg_flags = plaintext[offset]
offset += 1
if presence_flags & 2:
payload_size = struct.unpack('>H', plaintext[offset:offset+2])[0]
offset += 2
if presence_flags & 4:
protocol_type = plaintext[offset]
offset += 4 # Skip protocol type (1) and port (3)
if presence_flags & 8:
offset += 8 # Skip destination (8)
if presence_flags & 16:
offset += 8 # Skip source constant ID (8)
is_compressed = bool(msg_flags & 0x10)
# Extract the pure application payload
raw_payload = plaintext[offset:offset+payload_size]
if protocol_type != 0x81:
continue
if payload_size >= 0xB:
if is_compressed:
continue
else:
with open(f"smm2_streams/pkt{i}_msg{msg_count}_proto{protocol_type:02x}.bin", "wb") as f:
f.write(raw_payload)
success_count += 1
# PIA Messages are always padded to 4-byte boundaries
offset += payload_size
align = (4 - (offset % 4)) % 4
offset += align
except AttributeError:
continue
except Exception as e:
continue
cap.close()
print(f"\n[+] Finished! Extracted {success_count} payloads to 'smm2_streams' folder.")

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
#!/usr/bin/env python3
"""
LDN Data Frame Key Derivation for Mario Maker 2
Requires: pip install pycryptodome scapy
"""
import hashlib
from Crypto.Cipher import AES
# ── Nintendo key constants ────────────────────────────────────────────────────
MASTER_KEY_00 = bytes.fromhex("c2caaff089b9aed55694876055271c7d")
AES_KEK_GENERATION_SRC = bytes.fromhex("4d870986c45d20722fba1053da92e8a9")
AES_KEY_GENERATION_SRC = bytes.fromhex("89615ee05c31b6805fe58f3da24f7aa8")
DATA_INPUT_KEY = bytes.fromhex("f1e7018419a84f711da714c2cf919c9c")
NINTENDO_OUI = bytes([0x00, 0x22, 0xAA])
# ── Game-specific ─────────────────────────────────────────────────────────────
PASSWORD = b"LunchPack2DefaultPhrase"
# ── AES-ECB helper ───────────────────────────────────────────────────────────
def aes_ecb_decrypt(key: bytes, data: bytes) -> bytes:
return AES.new(key, AES.MODE_ECB).decrypt(data)
# ── Step-by-step key derivation ──────────────────────────────────────────────
def derive_data_key(server_random: bytes, password: bytes) -> bytes:
assert len(server_random) == 16, "server_random must be 16 bytes"
# Step 1: kek_key
kek_key = aes_ecb_decrypt(MASTER_KEY_00, AES_KEK_GENERATION_SRC)
print(f"[1] kek_key: {kek_key.hex()}")
# Step 2: access_key (decrypt the data input key with kek_key)
access_key = aes_ecb_decrypt(kek_key, DATA_INPUT_KEY)
print(f"[2] access_key: {access_key.hex()}")
# Step 3: generation_key
generation_key = aes_ecb_decrypt(access_key, AES_KEY_GENERATION_SRC)
print(f"[3] generation_key: {generation_key.hex()}")
# Step 4: hash input buffer = server_random || password
buf = server_random + password
hash_input = hashlib.sha256(buf).digest()[:16]
print(f"[4] SHA256(buf)[0:16]: {hash_input.hex()}")
# Step 4: final data frame key
data_key = aes_ecb_decrypt(generation_key, hash_input)
print(f"[★] data_frame_key: {data_key.hex()}")
return data_key
# ── Main ─────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
import sys
pcap_path = sys.argv[1] if len(sys.argv) > 1 else "./capture.pcapng"
server_random = bytes.fromhex("aaec2d390000000005180000796265e7")
data_key = derive_data_key(bytes.fromhex("d33f9c317a7f2b77a27b68e40f596f89"), PASSWORD)
print(f"tk: {data_key.hex()}")

Some files were not shown because too many files have changed in this diff Show More