Wolfenstein Modloader Buy me a coffeeKaffee spendieren

In plain wordsIn einfachen Worten

This page is a task description for Wolfenstein II: The New Colossus, not a result. A console command that can run scripts was found, but it only accepts scripts packed as encrypted "cfile" assets inside game archives, not loose files. The worker was asked to find the key derivation in the unpacked game code, decrypt all 10 language files as proof, re-encrypt them byte for byte, and then build a new cfile that loads a custom map. If this works, it would open a route to loading custom maps; the result itself is on a separate report page.

  • The console accepts exactly 34 commands; 'map' is not among them, but 'resourceExec' is.
  • resourceExec refuses loose script files in the retail build, so the script must be an encrypted cfile.
  • Known so far: files are handled by idEncryptedFileResource using AES via Windows CNG.
  • Required proof: decrypt 10/10 language files, byte-exact re-encryption, and failing negative controls.
  • Target: a new cfile containing 'map game/dlc/c02/c2v1_custom', clearly marked as untested in the game.

Diese Seite ist eine Aufgabenbeschreibung für Wolfenstein II: The New Colossus, kein Ergebnis. Es wurde ein Konsolenbefehl gefunden, der Skripte ausführen kann, aber er akzeptiert nur Skripte als verschlüsselte "cfile"-Assets in Spielarchiven, keine losen Dateien. Der Worker sollte die Ableitung des Schlüssels im entpackten Spielcode finden, zum Beweis alle 10 Sprachdateien entschlüsseln, sie byte-genau wieder verschlüsseln und dann eine neue cfile bauen, die eine eigene Karte lädt. Gelingt das, wäre ein Weg zum Laden eigener Karten offen; das Ergebnis steht auf einer eigenen Berichtsseite.

  • Die Konsole nimmt genau 34 Befehle an; 'map' gehört nicht dazu, 'resourceExec' schon.
  • resourceExec lehnt lose Skriptdateien in der Verkaufsversion ab, das Skript muss eine verschlüsselte cfile sein.
  • Bekannt war: Die Dateien laufen über idEncryptedFileResource mit AES über Windows CNG.
  • Geforderter Beweis: 10/10 Sprachdateien entschlüsseln, byte-genaues Neuverschlüsseln und fehlschlagende Gegenproben.
  • Ziel: eine neue cfile mit 'map game/dlc/c02/c2v1_custom', klar als im Spiel ungetestet markiert.

Technical detailsTechnische Details

Der technische Teil ist auf Englisch – so, wie er im Wiki steht. Unterstrichene Begriffe haben eine Erklärung auf Deutsch.

Worker w-cfilekey2-a1; task cfilekey2; research (read-only RE). Read .agent-cache/WORKER.md. Bus: python "%USERPROFILE%/.claude/skills/agent-cache-orchestrator/scripts/acbus.py" Parallel: w-idclwriter-a1 (container writer), w-savestructure-a1.

Objective

Recover the cfile key derivation for Wolfenstein II. This is now the single item on the critical path to loading a custom map.

docs/cfile.md states the reason the earlier attempt failed, and it is the one thing that changed today:

"The key is derived ... exclusively inside the SteamStub-encrypted .text. No ready-to-use key exists in a readable section."

The previous worker only ever had the PACKED executable. re_probes/runtime_87400/module.bin is a read-only capture of the RUNNING, SteamStub-unpacked process - the .text that was unreadable is now plain. Five other format problems fell to exactly this today.

Why it matters - the chain this closes

Measured at runtime today (wolfsdk_dump.txt, console session 15:48):

  • The console dispatches exactly 34 commands. map, devmap, fastmap and toggle are registered but NOT among them. Static prediction and runtime agreed 34/34 with zero deviation.
  • resourceExec IS one of the 34. Per re_probes/agent_reports/cmdtable.md it sets the restriction level to 0 and buffers its script into the unrestricted command buffer - so a script run through it should reach all 234 commands, map included.
  • resourceExec wolfsdk_test.cfg on a LOOSE file answered: WARNING: cfile:wolfsdk_test.cfg:NONE can't generate in production while loading cfile:wolfsdk_test.cfg couldn't exec resource wolfsdk_test.cfg So it resolves its argument as a cfile RESOURCE, and refuses to generate one from a loose file in a production build.
  • com_production and resource_loadLooseAssets are both registered but NOT exposed (re_probes/cvartable/cvars_tnc_v2.json), so no console cvar can change that.

Therefore the script must exist as a cfile asset inside a mounted .resources archive. Building such an archive is solved as of today (re_probes/agent_reports/idclhash.md, datahash.md). Authoring the cfile payload is not - it is encrypted, and that is your task.

Sources / starting points

  • re_probes/runtime_87400/module.bin - virtual RVA layout (file offset == RVA), sections and image base in manifest.json, .pdata for function bounds.
  • docs/cfile.md - the prior analysis. It already located the ground: the handler is idEncryptedFileResource, AES through bcrypt.dll (CNG), and it lists the error strings with their .rdata addresses, e.g. 0x026C9580 "Failed to derive key", 0x026C9688 "could not derive key", and a nearby string describing "Salt erzeugen -> Schluessel ableiten -> verschluesseln". Take the xrefs from those strings into the now-readable .text. That is the shortest path.
  • tools/cfile.py - existing, READ-ONLY for you. It has a working Aes class, PKCS7 unpad, a plaintext scorer (verify_plain, textiness) and a cfile enumerator (cfiles, head). Reuse them; do not edit that file.
  • re_probes/agent_reports/saveverify.md - a sibling worker traced the OTHER bcrypt user in this binary (the save HMAC) and found idSecureHMAC, BCryptCreateHash/HashData/FinishHash, and a key built by SHA256 over a concatenation. The cfile path likely uses the same CNG wrappers - read that report before starting, the call shapes will look familiar.
  • The 10 strings/*.lang cfiles are the corpus the earlier attempt used.
  • capstone 5.0.7 vendored: PYTHONPATH=re_probes/python_deps

Ownership

tools/probe_cfilekey.py (new), re_probes/cfilekey/ (new dir), re_probes/agent_reports/cfilekey2.md (new).

Forbidden / do not touch

No game launch, no process attach, no writes under the Steam install or "%USERPROFILE%/Saved Games". Do not edit tools/cfile.py, wolfsdk/, docs/, config.json, or any other worker's files (tools/probe_idclhash.py, probe_datahash.py, probe_cmdtable.py, probe_saveverify.py, probe_texdbkey.py, probe_cvartable.py, probe_save_structure.py, wolfsdk/idclwrite.py, re_probes/{idclhash,datahash,cmdtable,saveverify,texdbkey,cvartable,idclwriter,save_structure}/). No pip install.

Hard constraints

Python 3.11, stdlib plus vendored capstone. The decryptor must be pure stdlib (tools/cfile.py already implements AES by hand for exactly this reason). Reproducible from the command line, no running game.

Acceptance criteria

  • The derivation read out of the code: which function, what inputs, what salt, what KDF, which AES mode, with the RVAs and the xref chain that got you there.
  • Positive control at today's bar: DECRYPT real retail cfiles and show the plaintext is genuinely plaintext - all 10 strings/*.lang, n/n, verified with a structural check (the existing verify_plain/declen logic), not by eyeballing that it "looks like text".
  • Round-trip: re-encrypt a decrypted cfile and reproduce the original bytes exactly. Without that, authoring a new cfile is guesswork.
  • Negative controls: a wrong key, a flipped salt byte and a wrong mode must each fail the structural check rather than producing plausible-looking output.
  • Then the payoff: produce a NEW, valid cfile whose plaintext is map game/dlc/c02/c2v1_custom and write it to re_probes/cfilekey/. State plainly that it is untested at runtime.

Verification expectations

Every important assurance needs a check that fails if it is false. "Decrypts to something with high textiness" is weak; the round-trip is strong. Keep "key found" and "key confirmed against the corpus" apart.

Failure honesty

If the key turns out to be derived from a runtime value that is not in the image (as happened with the save .verify HMAC today - read that report, it is the cautionary case), say so immediately and name what it depends on. That is a valuable result, not a failure: it would mean the resourceExec route needs a different carrier and we should stop pushing on this one.

Coordination / deliverable

Checkpoint at milestones. Publish a bus fact as soon as you can decrypt retail cfiles, and again when you can round-trip - the container writer worker needs the second one to put your payload into an archive. Concise German report in re_probes/agent_reports/cfilekey2.md. Finish the bus task when done.