#!/usr/bin/env python3
"""
SOLUTION: Based on the insight that keys are already in the extracted data

From the filtered MOSI extraction around "axel_outrun", we got:
  02 92 64 04 64 02 0a 82 08 60 08 16 08 cd 08 33 08 5e 08 31 08 4d 08 4f 08 86 08 34 08 cd 08 1f

This is 38 bytes with a pattern of 0x08 appearing frequently.

The Python code does:
  auth_code = sector_22_hex + key_gen_hex  (where key_gen is 6 bytes)

KEY INSIGHT: The data we extracted might BE:
  - Sector 22 data (10-16 bytes)
  - Followed by/contains the 6-byte keys
  - Sector 34 data
"""
import requests

def lcg_step(seed):
    return (seed * 0x52c6425d + 0xcc52c) % (2**32)

def lcg_inverse(x):
    """Reverse LCG by one step"""
    a = 0x52c6425d
    c = 0xcc52c
    a_inv = pow(a, -1, 2**32)
    return ((x - c) * a_inv) % (2**32)

def crack_passcode_from_keys(key4, key5):
    """Given two consecutive 3-byte LCG outputs, recover the passcode"""
    # We have key4 and key5, which are outputs 4 and 5
    # Work backwards to find the initial seed (passcode)
    
    # These are the results of (state % 0xffffff)
    # So the actual states could have upper bits set
    # Brute force the upper byte
    
    for upper4 in range(256):
        state4 = (upper4 << 24) | key4
        state5_expected = lcg_step(state4) 
        
        if (state5_expected % 0xffffff) == key5:
            # Found valid state4, work backwards 4 steps to get seed
            state = state4
            for _ in range(4):
                state = lcg_inverse(state)
            return state
    
    return None

API = 'http://154.57.164.61:31938/api'

# From our extraction - try different interpretations
print("[*] Extracted data analysis:")
print()

# Raw extracted: 0292640464020a820860 [08 16 08 cd 08 33] 085e0831084d084f0886083408cd081f
#                ^^^^ Sector 22? ^^^^   ^^^ Keys? ^^^    ^^^^^^^ Sector 34? ^^^^^^^

# HYPOTHESIS 1: Remove the 0x08 prefix pattern
# 08 60 08 16 08 cd 08 33 → 60 16 cd 33
# But that's only 4 bytes, not 6

# HYPOTHESIS 2: The 0x08 is a command byte, real data follows
# Commands seen: 08 60, 08 16, 08 cd, 08 33, 08 5e, 08 31, 08 4d, 08 4f, 08 86, 08 34, 08 cd, 08 1f
# Take second byte: 60, 16, cd, 33, 5e, 31, 4d, 4f, 86, 34, cd, 1f (12 bytes)

filtered_6016cd = '6016cd335e31'  # First 6 bytes
print(f"If keys are: {filtered_6016cd}")
print(f"  Key 4: 0x{filtered_6016cd[:6]} = {int(filtered_6016cd[:6], 16)}")
print(f"  Key 5: 0x{filtered_6016cd[6:12]} = {int(filtered_6016cd[6:12], 16)}")

# Try cracking passcode from these
key4 = int(filtered_6016cd[:6], 16)
key5 = int(filtered_6016cd[6:12], 16)

print(f"\n[*] Attempting to crack passcode from keys {key4:06x} and {key5:06x}...")
passcode = crack_passcode_from_keys(key4, key5)

if passcode:
    print(f"\n{'='*70}")
    print(f"POSSIBLE PASSCODE: {passcode}")
    print(f"{'='*70}")
    
    # Verify by generating keys
    def generate_keys(pc):
        seed = pc
        keys = []
        for _ in range(6):
            seed = lcg_step(seed)
            keys.append(seed % 0xffffff)
        return keys
    
    keys = generate_keys(passcode)
    print(f"\nGenerated keys:")
    for i, k in enumerate(keys):
        print(f"  Key {i}: {k:06x}")
    
    print(f"\n[*] Testing with API (if server is up)...")
    
    # Build auth code: sector_22 + keys[4:6]
    sector_22 = '0292640464020a820860'  # 10 bytes
    key_bytes = []
    for key in keys[4:6]:
        key_bytes.extend([key >> 16, (key >> 8) & 0xFF, key & 0xFF])
    key_hex = ''.join(f'{b:02x}' for b in key_bytes)
    
    auth_code = sector_22 + key_hex
    
    data = {
        'uid': '04f6555b',
        'username': '6178656c5f6f757472756e',
        'authorization_code': auth_code,
        'access_level': '085e0831084d084f0886083408cd081f'
    }
    
    try:
        r = requests.post(API, data=data, timeout=3)
        result = r.json()
        
        if result.get('flag') and len(result.get('flag', '')) > 5:
            print(f"\n{'='*70}")
            print(f"SUCCESS!")
            print(f"Passcode: {passcode}")
            print(f"FLAG: {result['flag']}")
            print(f"{'='*70}")
        else:
            print(f"\nResult: {result}")
    except Exception as e:
        print(f"\nAPI Error: {e}")
        print("[!] Server might be down. Save the passcode for later!")
else:
    print("[-] Could not crack passcode from those values")
    print("[!] The keys might be in a different format in the capture")

print("\n[*] Alternative approach: Check all consecutive 6-byte sequences...")
