TL;DR: Wir haben eine weitere verzögerte RCE-Schwachstelle in MECCHA CHAMELEON entdeckt. Beim Spielen auf der Karte eines Angreifers kann dieser eine exponierte Funktion ausnutzen, um beliebige Dateien auf das System des Opfers zu schreiben. Dies kann nach einem Neustart zur Remote-Code-Ausführung auf dem System des Opfers führen. Wir haben das Problem den Betreibern des Spiels gemeldet, und diese haben die Sicherheitslücke im Update 4.0.0 behoben. Dieses Update wird automatisch installiert, bevor das Spiel gestartet wird.
Wenn du ein Gamer bist, hast du wahrscheinlich schon von MECCHA CHAMELEON gehört. Das Online-Versteckspiel hat weltweit für Furore gesorgt und im ersten Monat 15 Millionen Exemplare verkauft!
Als Spieler hast du eine ganz alberne Aufgabe: Such dir ein gutes Versteck und bemale eine leere weiße Figur so, dass sie sich der Umgebung anpasst. Dann wird einer deiner Freunde dich jagen. Du gewinnst, wenn der Jäger dich nicht finden kann. So einfach ist das!

Von der Community erstellte Karten machen einen großen Teil des Reizes aus. Jeder kann eine neue Karte erstellen, in der sich die Spieler verstecken können, und diese über den Steam Workshop veröffentlichen. Diese neuen Karten können beispielsweise eine Kunstgalerie oder nostalgische Schauplätze aus anderen Spielen sein.

Ein bestimmtes Feature ist uns besonders aufgefallen: Wenn man auf einem Server spielt, wählt der Lobby-Host die Karte aus, und anschließend werden alle Spieler in dieser Lobby aufgefordert, diese Karte herunterzuladen (auf dem Bildschirm wird man darauf hingewiesen, wenn man sie noch nicht heruntergeladen hat und dadurch das Spiel aufhält!). Das ist sehr praktisch, bedeutet aber auch, dass man beim Beitritt zu einem Match möglicherweise eine Karte laden muss, die von jemandem erstellt wurde, den man noch nie getroffen hat. Wir wollten herausfinden, was diese heruntergeladene Karte eigentlich alles darf.
In der Vergangenheit war MECCHA CHAMELEON bereits beim Laden der Karte von einer RCE betroffen, wie in diesem Blogbeitrag ausführlich beschrieben. Dieser spezielle Fehler wurde inzwischen behoben, aber wurden dadurch alle Möglichkeiten für eine RCE beseitigt?
Was ist eine MECCHA CHAMELEON-Karte eigentlich?
Man könnte meinen, eine Karte bestehe lediglich aus einigen Assets: Modellen für die Umgebung und Texturen, damit alles richtig aussieht. So funktioniert eine Karte in vielen Spielen, bei denen die heruntergeladene Datei das Level beschreibt, während das Spiel selbst die Logik steuert.
Die Karten von „MECCHA CHAMELEON“ bieten noch mehr Steuerungsmöglichkeiten. Das Spiel wurde mit der Unreal Engine 5.6.1 entwickelt, und seine Karten können Blueprints enthalten. Blueprint ist das visuelle Programmiersystem von Unreal. Man kann Knoten miteinander verbinden, um bestimmte Ereignisse auszulösen, wenn ein Spieler einen Knopf drückt, einen Bereich betritt oder einfach nur die Karte lädt.

Natürlich kann eine Karte nicht jede Funktion innerhalb von Unreal oder MECCHA CHAMELEON aufrufen. Eine native Funktion muss zunächst für Blueprint freigegeben werden. Wenn die Karte gestartet wird, werden ihre Graphen innerhalb des MECCHA CHAMELEON-Prozesses ausgeführt. Ruft ein Graph eine freigegebene Funktion auf, führt das Spiel diese Aktion unter Verwendung des Spielerkontos und der Berechtigungen des Spielers aus.
Das bedeutet, dass benutzerdefinierte Karten eine interessante Angriffsfläche darstellen:
- Ein Lobby-Host kann jeden anderen Spieler dazu auffordern, eine Karte herunterzuladen und auszuführen.
- Diese Karte kann dann Blueprint-Graphen innerhalb des Spiels ausführen.
Also fing ich an, auf die Motorfunktionen zu achten, die ich erreichen konnte.
Aufrufbare Funktionen finden
Glücklicherweise müssen wir nicht raten, welche Funktionen Unreal zur Verfügung stellt. Wir können einen Blueprint-Graphen öffnen und mit der rechten Maustaste auf einen leeren Bereich klicken. Nun zeigt Unreal ein durchsuchbares Menü mit Knoten an, die diesem Graphen hinzugefügt werden können.

Aus Sicherheitssicht interessierten mich vor allem Funktionen, die in irgendeiner Weise mit dem Betriebssystem interagierten. Deshalb suchte ich nach solchen, die Folgendes enthielten: speichern, Export, schreiben, Aufzeichnung, open, Start, und load. Wir haben die riesige Liste an APIs auf eine überschaubare Liste reduziert, die ich mir genauer ansehen konnte.
Also habe ich diese Funktionen nacheinander untersucht, bis ich auf Folgendes stieß: Aufnahme beenden. Diese Funktion stach besonders hervor, da sie eine Datei im Dateisystem mit einem absoluten oder relativen Pfad erstellen kann. Außerdem speichert sie die Audioausgabe, die wir wahrscheinlich auf irgendeine Weise steuern können.

Dateien an beliebigen Orten schreiben
Um also die Aufnahme beenden Funktion: Ein Kartenersteller sollte eine Aufnahme starten, einen Ton abspielen und anschließend die Aufnahme beenden. Anschließend geben wir einen Namen und einen Speicherpfad an. Die Funktion ist näher dokumentiert hier.

Das ist also ein eindeutiger Fall von „Gib einfach ein beliebiges Verzeichnis und einen beliebigen Dateinamen an, und wir können diese Dateien an einer beliebigen Stelle im System speichern“, richtig?
Na ja, schon. Man kann einfach C:/Benutzer/Öffentlich/ als Dateipfad angeben und die Dateien dort speichern, oder Sie können einen relativen Pfad angeben. Das standardmäßig verwendete Verzeichnis ist C:\Users\<user>\AppData\Local\Chameleon\Saved\BouncedWavFiles, also durch Angabe eines Pfads, der mit ../../../../../, könnten wir auf den Home-Ordner des Benutzers zugreifen, ohne dessen Benutzernamen zu kennen.
Nun könnten wir also Dateien an beliebiger Stelle im Dateisystem schreiben. Der einfachste Weg, dies zu einer verzögerten Remote-Codeausführung auszunutzen, besteht darin, eine ausführbare Datei in C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. Bei jedem Start Ihres Geräts werden automatisch alle Dateien in diesem Ordner ausgeführt.
Also haben wir diesen Wert als Aufnahmetitel angegeben:
../../../../Roaming/Microsoft/Windows/Startmenü/Programme/Autostart/poc.exeUnd als wir unsere Karte zusammengestellt und umgesetzt hatten, fiel uns auf, dass …

Es hat funktioniert, irgendwie? Wir haben tatsächlich eine Datei in den Autostart-Ordner geschrieben. Aber unsere .exe-Endung wurde nicht beibehalten. Die Unreal Engine fügt die Endung .wav zu jedem von uns angegebenen Dateinamen hinzu, weshalb Windows die Datei weiterhin als WAV-Datei und nicht als ausführbare Datei behandelt.
Entfernen der Dateiendung .wav
Ich habe ein wenig darüber nachgedacht, wie wir das umgehen könnten. Wir haben es hier mit einem klassischen Fall zu tun, bei dem zwei verschiedene Systeme von bestimmten Annahmen ausgehen. Die Unreal Engine hat ihre eigene Art, einen Pfad zu verarbeiten, und Windows hat seine eigene Art, einen Pfad zu interpretieren. Ich musste nur eine Diskrepanz zwischen beiden finden.
Bei der Unreal Engine ist das unglaublich einfach: Sie erkennt einfach eine Zeichenkette und hängt daran an .wav dazu. Bei Windows ist es etwas komplexer. Unter Windows gibt es maximale Längen für Dateinamen und Zeichen, die in einem Pfad nicht zulässig sind, wie beispielsweise das Nullzeichen (U+0000).
Was passiert aber, wenn wir versuchen, eine Datei zu erstellen, deren Name ein Nullzeichen enthält? Nun, in den meisten Fällen erhält man eine Fehlermeldung:

Allerdings lösen nicht alle APIs einen Fehler aus. Einige APIs auf niedrigerer Ebene erkennen die Null-Bytes tatsächlich als Abschlusszeichen und verwerfen alles, was danach folgt:

Was wäre also, wenn wir versuchen würden, unsere bösartige Karte zu nutzen, um eine Aufzeichnung unter folgender Adresse zu speichern:
POC.exe\u0000IGNORED
Wir sehen, dass es funktioniert hat! Wir können nun Dateien mit beliebigen Namen an beliebigen Orten im Dateisystem speichern!
Ein großes Problem bleibt jedoch bestehen. Wir schreiben lediglich die Bytes einer WAV-Audioaufnahme mit einem .exe Dateiendung. Wir müssen irgendwie auch den Inhalt dieser Datei anpassen, damit sie ausführbar ist!

Schädliche Bytes in einer Audioaufnahme
Nun standen wir vor einer neuen Herausforderung. Wir speicherten eine echte Audioaufnahme als WAV-Datei an einem beliebigen Speicherort. Damit dieser Exploit jedoch funktioniert, müssen wir auch kontrollieren können, was in diese Datei geschrieben wird.
Dazu verwenden wir eine unkomprimierte PCM-WAV-Datei. WAV ist das Datei container, das zunächst einige Metadaten und anschließend Audiodaten enthält. WAV-Dateien können Audiodaten in verschiedenen Formaten speichern, daher ist die .wav Die Dateiendung allein gibt keinen Aufschluss darüber, wie die Samples kodiert sind.
PCM steht für „Pulse-Code Modulation“ (Impuls-Code-Modulation). Bei PCM wird jeder Messwert der Schallwelle direkt als Zahl gespeichert. In unserem Proof-of-Concept wurde 16-Bit-PCM verwendet, sodass jedes Sample genau zwei Bytes belegte. „Unkomprimiert“ bedeutet, dass diese Zahlen geschrieben wurden, ohne sie durch einen Codec wie MP3 zu leiten.
Eine unkomprimierte PCM-WAV-Datei besteht aus Audio-Abtastwerten. Wenn wir diese Zahlen präzise steuern, steuern wir damit auch die Bytes, die zu ihrer Speicherung verwendet werden.
Das ist sehr wichtig, da bei der normalen Audiokomprimierung versucht wird, die Wahrnehmung eines Klangs beizubehalten, und nicht die exakten Bytes jedes einzelnen Samples. Daher kann eine komprimierte Version identisch klingen, obwohl sie ganz andere Bytes enthält.
Ein vereinfachtes WAV sieht so aus:
+-------------------------------+
| RIFF/WAVE-Header | Erstellt von Unreal
| Format, Kanäle, Abtastrate |
| Größe des Datenabschnitts |
+-------------------------------+
| PCM-Abtastwert 0 | Wird durch die Schallwelle gesteuert
| PCM-Sample 1 |
| PCM-Sample 2 |
| ... |
Unreal steuert den Header, einschließlich des RIFF und WAVE Bezeichner. Diese können wir nicht ändern, da unsere Kontrolle über die Datei erst im PCM-Datenbereich beginnt. Das schließt viele ausführbare Dateien für unseren Exploit aus. Wir können keine normale .exe oder .dll, da beide einen gültigen PE-Header benötigen, um ausgeführt zu werden.
Wir benötigten daher einen Dateityp, dessen Parser nicht darauf bestand, den Header bereits am ersten Byte zu finden. Windows-HTML-Anwendungen erwiesen sich als ideale Lösung.
Ein HTML-Anwendung ist ein altes Windows-Format mit dem .hta Dateiendung. Die Datei ähnelt stark einer Webseite: Sie kann HTML, CSS und entweder JScript oder VBScript enthalten. Windows öffnet sie mit mshta.exe (Microsoft HTML Application Host).
Der wesentliche Unterschied zu einer normalen Webseite besteht darin, wo dieses Skript ausgeführt wird. Eine HTA wird als Desktop-Anwendung behandelt und nicht als Seite innerhalb der Browser-Sandbox. Ihr Skript kann Windows-COM-Objekte erstellen, darunter WScript.Shell, wodurch ein weiterer Prozess gestartet werden kann.
Eine vereinfachte Version unserer Proof-of-Concept-Nutzlast sieht wie folgt aus:
[RIFF/WAVE header ...]
<html>
<head>
<hta:application />
<script>
new ActiveXObject("WScript.Shell").Run("calc.exe");
</script>
</head>
</html>
Wenn diese Datei geöffnet wird, mshta.exe ignoriert die WAV-Metadaten am Anfang und führt das Skript aus. Dann WScript.Shell startet den Taschenrechner.
Die verbleibende Herausforderung bestand darin, diesen HTML-Code und das Skript in die PCM-Samples der WAV-Datei einzubetten.
Our payload used 16-bit PCM. Each sample is a 16-bit number stored in little-endian order, meaning the least significant byte is written first. Take the sample value 0x683C: it appears in the WAV as 3C 68, which also happens to be the ASCII text <h.
The same conversion works for a longer string. The text <html> has these ASCII bytes:
3C 68 74 6D 6C 3EWenn wir sie zu Paaren zusammenfassen, erhalten wir drei 16-Bit-Abtastwerte:
Bytes: 3C 68 | 74 6D | 6C 3E
Beispiele: 0x683C 0x6D74 0x3E6C
Wenn diese Samples wieder in eine Little-Endian-WAV-Datei geschrieben werden, tauchen die ursprünglichen Bytes wieder auf. In Wirklichkeit war es ziemlich mühsam, das zum Laufen zu bringen, aber letztendlich ist es uns gelungen, eine echte WAV-Datei zu erstellen, die unsere hta Nutzlast.

Die Karte zusammenstellen
Zu diesem Zeitpunkt funktionierte jedes Teil für sich genommen. Nun galt es nur noch, alles in eine Karte zu integrieren, die den gesamten Angriff auf einmal ausführen konnte, sobald das Level geladen war.
Also fügen wir Folgendes hinzu: BeginPlay und gehen Sie wie folgt vor:
StartRecordingOutputauf einem separaten Submix (um Störungen durch den üblichen Spielton zu vermeiden)PlaySound2Dmit unserem vorbereiteten, unkomprimierten PCMAufnahmeausgabe beendenVerwenden../../../../Roaming/Microsoft/Windows/Startmenü/Programme/Autostart/poc.exe\u0000IGNOREDals Dateiname

Wir haben die Karte erstellt und sie (privat!) auf Steam hochgeladen.

Und so ist dieses Proof-of-Concept-Video entstanden:
Ist MECCHA CHAMELEON nun also sicher?
Die von uns gemeldete Sicherheitslücke wurde behoben und kann nicht mehr ausgenutzt werden. Die Aufnahmeausgabe beenden Die Funktion erstellt keine Dateien mehr (auch keine beabsichtigten).
Wir haben außerdem alle Steam-Workshop-Karten überprüft, um festzustellen, ob diese Schwachstelle bereits ausgenutzt wurde, konnten jedoch keine entsprechenden Fälle feststellen.
Während wir jedoch an diesem PoC arbeiteten, haben sich mehrere Personen an uns gewandt, um uns darauf hinzuweisen, dass es möglicherweise weitere Sicherheitslücken in MECCHA CHAMELEON gibt. Sie haben keine Einzelheiten genannt, und diese Angaben wurden von uns weder bestätigt noch überprüft.
Wir bitten Sie daher dringend, beim Spielen mit benutzerdefinierten Karten Vorsicht walten zu lassen und wachsam zu sein. Wir empfehlen, ausschließlich auf den offiziellen Karten von MECCHA CHAMELEON zu spielen.
Zeitplan für die Offenlegung
- 11. August 2026: Ich habe versucht, über Twitter Kontakt aufzunehmen
- 12. August 2026: Ich habe versucht, über Discord Kontakt aufzunehmen
- 13. August 2026: Ich habe versucht, Kontakt zum Steam-Support und über die E-Mail-Adresse des Entwicklers aufzunehmen
- 17. August 2026: Ich konnte sie erneut über Twitter erreichen. Der Entwickler antwortete, dass er das Problem beheben werde.
- 20. August 2026: MECCHA CHAMELEON 4.0.0 wurde mit einem Patch für diese Sicherheitslücke veröffentlicht

