Files
TeslaSuite/Launcher/assets/MEMORY.md
T
CydandClaude Opus 4.8 548550b312 Initial commit: TeslaSuite monorepo (TeslaConsole + TeslaLauncher)
Co-locate the two cockpit-pod projects into a single repository:

- Console/  : TeslaConsole, the net48 WinForms operator console (decompiled
              reconstruction) plus its differential + catalog test suite.
- Launcher/ : TeslaLauncher, the net6 pod-side Service + Agent rewrite.

Adds a combined TeslaSuite.sln, root README documenting the shared wire
contract (and its current duplication, the main follow-up), and a root
.gitignore. Histories were not preserved per request; this is a fresh start
from the current working state of both projects.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 14:43:28 -05:00

7.7 KiB

TeslaLauncher Project Memory

Project Overview

Simulation cockpit launcher system (BattleTech/laser-tag venue). Original: Windows 2000 app by Elsewhen Studios LLC. Current: Modern .NET 6 rewrite to work around Session 0 isolation (Vista+).

Architecture: 3 components

  1. TeslaLauncherService (Session 0 Windows Service) - TCP 53290, handles Console commands, forwards via Named Pipe
  2. TeslaLauncherAgent (WinForms tray, user desktop session) - Named Pipe server, launches/kills apps
  3. SecureConfig (PodSecureConfigurator) - First-boot network configuration protocol

Key Files

  • TeslaLauncherService.cs + .csproj - Windows Service (net6.0-windows, x86, self-contained)
  • TeslaLauncherAgent.cs + .csproj - Userspace Agent (WinForms, net6.0-windows, x86)
  • LaunchModels_Shared.cs - BinaryFormatter wire types + JSON IPC types
  • SecureConfig.cs - First-boot UDP beacon + AES configuration protocol
  • LaunchApps.xml - Game configs (Red Planet 4.11, BattleTech Firestorm at C:\Games)
  • build.bat / install.bat - Build and install scripts

Assets (original binaries)

  • assets/Tesla Application Launcher/ — original pod-side binaries (TeslaLauncherService.exe, TeslaSecureConfiguration.dll, etc.)
  • assets/Tesla Console/ — original console-side binaries (TeslaConsole.exe, TeslaSecureConfiguration.dll, etc.)
  • assets/configoflc.pcapng — pcap of a SUCCESSFUL pod configuration (used to confirm protocol)
  • assets/pcap.pcapng — pcap of a FAILING configuration (root cause: Console RPLY sent from wrong NIC)

SecureConfig Protocol — CONFIRMED from binary (TeslaSecureConfiguration.dll)

All values below are verified from the original DLL.

UDP Config Phase

  • Port 53291: pod broadcasts RQST, Console listens
  • Port 53292: Console broadcasts RPLY (UDP), pod listens
  • RQST format: RQST(4 plaintext) + MAC(6) + RequestId(3) = 13 bytes PLAINTEXT
  • RPLY format: RPLY(4 plaintext) + AES-256-CBC ciphertext(64 bytes) = 68 bytes
    • CBC ciphertext = IV(16) + PKCS7-padded plaintext(48)
    • AES key = PBKDF2(passphrase, salt, 1000 iter, 32 bytes)
    • Salt (32 bytes): 0x17,0xab,0x51,0xd9,0xec,0xd1,0xd4,0x74,0xa9,0x09,0x4a,0x34,0x27,0xfb,0x1f,0xf2,0xde,0xc4,0xf9,0xf1,0xa6,0xd8,0x9e,0xda,0x15,0x11,0x47,0x65,0x32,0xe7,0xe7,0xef
  • Passphrase alphabet: "23456789ABCDEFGHJKLMNPQRSTUVWXYZ" (32 chars)
  • RequestId length: 3 chars; Passphrase length: 5 chars
  • Temp IP: RANDOM in 172.16.0.0/12 range (byte[0]=172, byte[1]=0x1X random, bytes 2-3 random)
    • Our fixed 172.16.0.100 is fine (Console doesn't connect back to temp IP)
  • Temp mask: 255.240.0.0

TCP Session Phase (port 53292) — CONFIRMED from DLL decompilation (ilspycmd)

  • Console connects TCP to pod's NEW IP:53292 AFTER UDP config
  • Both sides call the SAME NegotiateCryptoStreams static method:
  1. Both write own 16-byte IV (raw), read other's 16-byte IV
  2. OFB setup: outStream keyed from OTHER side's IV, inStream keyed from OWN IV
    • Pod writes with consoleIv, reads with podIv
    • Console writes with podIv, reads with consoleIv
  3. Both write raw "CONF" (4 bytes: 0x43,0x4F,0x4E,0x46) over OFB Both read 4 bytes and verify == "CONF" → key verification handshake If mismatch → returns false → caller retries with new TCP connection
  • After NegotiateCryptoStreams returns true:
  1. Pod → Console: BinaryWriter.Write(string) — RSA-2048 public key XML (~417 bytes)
  2. Console reads RSA XML, generates AES-256 session key, RSA-encrypts it
  3. Console → Pod: BinaryWriter.Write(int len) + BinaryWriter.Write(byte[] ciphertext) (260 bytes = 4-byte int32 (256) + 256-byte RSA PKCS#1 v1.5 ciphertext)
  4. Pod: ReadInt32() + ReadBytes(len) + RSA.Decrypt(enc, Pkcs1) → session key
  • Key derivation: PBKDF2(passphrase, salt, 1000 iter, 32 bytes) — same key both directions
  • OFBCryptoStream: unidirectional, constructor calls NextBuffer() immediately (IV→KS block 0)

Registry / netsh

  • Hostname: SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName
  • netsh: interface ip set address "{adapter}" static {ip} {mask} {gw} with 1 metric
  • DNS: interface ip set dns "{adapter}" static {dns}

BinaryFormatter Cross-Runtime Findings (.NET FW 2.0 → .NET 6)

  • MemberInfoSerializationHolder field names differ: .NET FW 2.0 uses "Name", .NET 6 uses "MemberName"
  • MethodInfoProxy intercepts via binder redirect + ISerializable, reads "Name" field
  • IObjectReference fixup fails for struct fields: InvokeCommand is a struct; fixup doesn't update Function field in boxed value type. Fixed with [ThreadStatic] LastResolvedName fallback.
  • Console checks ICMP reachability before connecting TCP 53290 — Windows Firewall must allow ICMPv4 type 8
  • BindToName must write "TeslaConsoleLaunchLib" as assembly for Tesla.Net types in serialized responses
  • JsonElement not [Serializable]: Agent IPC returns JsonElement via System.Text.Json; must convert to proper Tesla.Net types before BinaryFormatter serialization

Known Bugs Found During Scan

  1. CONFIG_FILE path mismatch: Fixed
  2. IsMachineConfigured in Agent doesn't filter virtual adapters (Service version does) - may false-trigger on Hyper-V machines
  3. new Random() for passphrase/RequestId generation - should use RandomNumberGenerator (security)
  4. Named pipe has no PipeSecurity ACL - any local process can connect and issue commands
  5. Volume control silently fails if nircmd.exe not present - no fallback
  6. _clientTasks list: Fixed with _taskLock

Wire Protocol

  • Console → Service: TCP 53290, OFB-encrypted (NegotiateCryptoStreams + session key), BinaryFormatter RPC
  • Service → Agent: JSON over Named Pipe "TeslaLauncherIPC" with 4-byte length prefix
  • SecureConfig: UDP 53291 (RQST beacon), UDP 53292 (RPLY), TCP 53292 (OFB + RSA key exchange)

Management Port (53290) — confirmed from decompiled TeslaLauncherService.exe

  • Original: ManagePort = 53290, ConfigPort = 53291
  • Every Console connection: NegotiateCryptoStreams(sessionKey) → BinaryFormatter RPC over OFB
  • Session key: 32-byte AES key from RSA exchange during SecureConfig, saved to TeslaKeyStore.key
  • Key file: C:\ProgramData\TeslaLauncher\TeslaKeyStore.key (format: 1-byte length + key bytes)
  • Original Console: PodManagerConnection.Open()NegotiateCryptoStreams()BinaryFormatter.Serialize/Deserialize

Install Product Protocol (confirmed from old pod pcap)

  • Console uses TWO concurrent TCP 53290 connections:
    • Polling connection: GetInstalledApps, then GetOutOfBandProgress polling (~4/sec), then InstallApp
    • Install connection: InitiateInstallProduct → Guid response, then 8-byte Int64 LE file size + raw file bytes, then FIN
  • Service handles InitiateInstallProduct and GetOutOfBandProgress directly (not forwarded to Agent)
  • Progress tracking: receive (0-50%), extract to C:\Games (50-95%), postinstall.bat (96%), complete (100%)
  • Zip-slip protection on extraction; postinstall.bat executed with 60s timeout then deleted
  • FIXED: Console sent file 3x because InstallProductWorker loops for (i=0; i<3; i++) and only breaks on PercentComplete == 99. We were returning 100 → now returns 99.

Fixes Applied (session 2)

  • Agent splash-to-normal transition: form.Close() in timer + Main() falls through to AgentApplication
  • Guid format mismatch: string-first deserialization with TryParse (moot after moving to Service)
  • InitiateInstallProduct: handled directly in Service, returns Guid, triggers ReceiveInstallFile
  • LaunchApps.xml ACL: icacls in install.bat grants Users modify access
  • build.bat /q flag: suppresses pause for non-interactive terminals
  • install.bat: creates C:\Games with Users modify ACL

User Preferences

  • User writes in informal English, technical background
  • Prefers building via build.bat (not direct dotnet publish)