#!/usr/bin/env python3
"""
Try to crack the LCG passcode from extracted sector data
The data might contain LCG outputs
"""
import requests

def lcg_step(seed):
    return (seed * 0x52c6425d + 0xcc52c) % (2**32)

def generate_keys(passcode):
    seed = passcode
    keys = []
    for _ in range(6):
        seed = lcg_step(seed)
        keys.append(seed % 0xffffff)
    return keys

def lcg_inverse(x):
    """Reverse one LCG step"""
    # x_{n+1} = (a*x_n + c) mod 2^32
    # x_n = (x_{n+1} - c) * a^{-1} mod 2^32
    a = 0x52c6425d
    c = 0xcc52c
    mod = 2**32
    
    # Compute modular inverse of a
    a_inv = pow(a, -1, mod)
    
    return ((x - c) * a_inv) % mod

# The sector 22/34 data we extracted (10 visible bytes each)
# cd335e314d4f8634cd1f
# 5e4ce0a703078634cd1f

# Notice both end with "8634cd1f" - that might be significant!

# Let's try: maybe these are LCG outputs mixed with other data
# Or maybe the USERNAME data we saw is the clue

# We saw "axel_outrun" in MOSI which decodes as:
# 61 78 65 6c 5f 6f 75 74 72 75 6e

print("[*] Extracted data analysis:\n")

# Sector data
s22 = bytes.fromhex('cd335e314d4f8634cd1f')
s34 = bytes.fromhex('5e4ce0a703078634cd1f')

print(f"Sector 22: {s22.hex()}")
print(f"Sector 34: {s34.hex()}")
print()

# Try interpreting as 3-byte LCG outputs
print("As 3-byte chunks:")
for name, data in [("S22", s22), ("S34", s34)]:
    for i in range(0, len(data)-2, 3):
        val = (data[i] << 16) | (data[i+1] << 8) | data[i+2]
        print(f"  {name}[{i}]: {val:06x} = {val}")
print()

# Let's assume the last 6 bytes are key_gen (keys 4 and 5)
# From sector 34's pattern: last 10 bytes visible
# Maybe: 5e4ce0a703 07 8634cd1f
#        ^^^^^^^^^^ ^^  ^^^^^^^^^
#        ? ?   key5   key6    ?

# Or simpler: cd335e314d4f might BE keys 4-5!
test_key_bytes = bytes.fromhex('cd335e314d4f')
val1 = (test_key_bytes[0] << 16) | (test_key_bytes[1] << 8) | test_key_bytes[2]
val2 = (test_key_bytes[3] << 16) | (test_key_bytes[4] << 8) | test_key_bytes[5]

print(f"[*] If 'cd335e314d4f' are keys 4-5:")
print(f"  Key 4: {val1:06x} = {val1}")
print(f"  Key 5: {val2:06x} = {val2}")
print()

# Try to reverse LCG from these values
print("[*] Attempting to reverse LCG...")

# If val2 is the 5th LCG output, work backwards
state_after_5 = val2  # This is the RESULT of % 0xffffff
# But we need the full 32-bit state!

# The actual LCG state could be any value where (state % 0xffffff) == val2
# Try all possibilities for the upper bits
print()
print("[*] Testing different key interpretations with API...")
print()

username = '6178656c5f6f757472756e'  # axel_outrun
uid = '04f6555b'

# Test 1: Use sector_22 data + cd335e314d4f as keys
s22_hex = 'cd335e314d4f8634cd1f0e0000000000'  # 16 bytes
key_hex = 'cd335e314d4f'  # 6 bytes

auth = s22_hex + key_hex
s34_hex = '5e4ce0a703078634cd1f0e0000000000'

data = {
    'uid': uid,
    'username': username,
    'authorization_code': auth,
    'access_level': s34_hex
}

try:
    r = requests.post('http://154.57.164.61:31938/api', data=data, timeout=3)
    result = r.json()
    print(f"Test 1: {result}")
    
    if result.get('flag') and len(result.get('flag', '')) > 5:
        print(f"\n{'='*70}")
        print(f"SUCCESS! FLAG: {result['flag']}")
        print(f"{'='*70}")
        exit(0)
except Exception as e:
    print(f"Test 1: Error - {e}")

# Test 2: Try different key combinations from the visible data
for key_hex in ['cd335e314d4f', '5e4ce0a703', '314d4f8634', '8634cd1f00', '4d4f8634cd']:
    auth = s22_hex + key_hex
    data['authorization_code'] = auth
    
    try:
        r = requests.post('http://154.57.164.61:31938/api', data=data, timeout=2)
        result = r.json()
        
        if result.get('flag') and len(result.get('flag', '')) > 5:
            print(f"\nSUCCESS with key {key_hex}!")
            print(f"FLAG: {result['flag']}")
            exit(0)
        else:
            print(f"  Key {key_hex}: {result.get('door_status', 'Unknown')}")
    except:
        pass

print("\n[!] None worked. Need to find the actual LCG keys in the capture...")
