Missbrauch von Android-Media-Pipelines & Image-Parsern
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
Zustellung: Messaging-Apps ➜ MediaStore ➜ Privilegierte Parser
Moderne OEM-Builds führen regelmäßig privilegierte Media-Indexer aus, die MediaStore für “AI”- oder Sharing-Funktionen neu scannen. Auf Samsung-Firmware vor dem Patch vom April 2025 lädt com.samsung.ipservice Quram (/system/lib64/libimagecodec.quram.so) und parst automatisch jede Datei, die WhatsApp (oder andere Apps) in MediaStore ablegt. In der Praxis kann ein Angreifer eine DNG senden, die als IMG-*.jpg getarnt ist, darauf warten, dass das Opfer auf “download” tippt (1-click), und der privilegierte Dienst parst die Nutzlast, selbst wenn der Benutzer die Galerie nie öffnet.
$ file IMG-2025-02-10.jpeg
TIFF image data ...
$ exiftool IMG-2025-02-10.jpeg | grep "Opcode List"
Opcode List 1 : [opcode 23], [opcode 23], ...
Wichtigste Erkenntnisse
- Die Auslieferung beruht auf dem erneuten Parsen von System-Medien (nicht dem Chat-Client) und erbt daher die Berechtigungen dieses Prozesses (voller Lese/Schreib-Zugriff auf die Galerie, Möglichkeit, neue Medien abzulegen usw.).
- Jeder Image-Parser, der über
MediaStoreerreichbar ist (vision widgets, wallpapers, AI résumé features, etc.), wird aus der Ferne erreichbar, wenn ein Angreifer ein Ziel dazu bringt, Medien zu speichern.
Quram’s DNG Opcode Interpreter Fehler
DNG-Dateien betten drei Opcode-Listen ein, die in verschiedenen Decode-Stufen angewendet werden. Quram kopiert Adobes API, aber sein Stage-3-Handler für DeltaPerColumn (opcode ID 11) vertraut attacker-supplied plane bounds.
Fehlerhafte Ebenengrenzen in DeltaPerColumn
- Angreifer setzen
plane=5125undplanes=5123, obwohl Stage-3-Bilder nur Ebenen 0–2 (RGB) ausliefern. - Quram berechnet
opcode_last_plane = image_planes + opcode_planesanstattplane + countund prüft nie, ob der resultierende Ebenenbereich ins Bild passt. - Die Schleife schreibt daher ein Delta in
raw_pixel_buffer[plane_index]mit einem vollständig kontrollierten Offset (z. B. plane 5125 ⇒ Offset5125 * 2 bytes/pixel = 0x2800). Jeder Opcode addiert einen 16-Bit-Float-Wert (0x6666) an die Zieladresse und ergibt damit ein präzises heap OOB add-Primitive.
Inkremente in beliebige Writes verwandeln
- Der Exploit korruptiert zuerst
QuramDngImage.bottom/rightvon Stage-3 mittels 480 fehlerhafterDeltaPerColumn-Operationen, sodass zukünftige Opcodes riesige Koordinaten als in-bounds behandeln. MapTable-Opcodes (opcode 7) zielen dann auf diese gefälschten Grenzen. Mit einer Substitutionstabelle aus Nullen oder einemDeltaPerColumnmit-Inf-Deltas nullt der Angreifer beliebige Regionen und wendet anschließend weitere Deltas an, um exakte Werte zu schreiben.- Weil die Opcode-Parameter innerhalb der DNG-Metadaten leben, kann das Payload Hunderte von Tausenden von Writes kodieren, ohne direkt in den Prozessspeicher zu schreiben.
Heap Shaping Under Scudo
Scudo bucktet Allocations nach Größe. Quram allokiert zufällig die folgenden Objekte mit identischen 0x30-Byte-Chunks, so dass sie im selben Bereich landen (0x40-Byte-Abstand auf dem heap):
QuramDngImagedescriptors für Stage 1/2/3QuramDngOpcodeTrimBoundsund vendorUnknownopcodes (ID ≥14, einschließlich ID 23)
Der Exploit sequenziert Allokationen, um Chunks deterministisch zu platzieren:
- Stage-1
Unknown(23)opcodes (20.000 Einträge) sprayen 0x30-Chunks, die später freigegeben werden. - Stage-2 freed diese opcodes und platziert ein neues
QuramDngImagein der freigegebenen Region. - 240 Stage-2
Unknown(23)-Einträge werden freed, und Stage-3 allokiert sofort seinQuramDngImageplus einen neuen raw pixel buffer derselben Größe, wodurch diese Plätze wiederverwendet werden. - Ein konstruiertes
TrimBounds-Opcode läuft zuerst in Liste 3 und allokiert noch einen raw pixel buffer, bevor Stage-2-State freigegeben wird, und garantiert so die Adjazenz “raw pixel buffer ➜ QuramDngImage”. - 640 zusätzliche
TrimBounds-Einträge sind mitminVersion=1.4.0.1markiert, sodass der Dispatcher sie überspringt, ihre Backing-Objekte jedoch alloziert bleiben und später als primitive Ziele dienen.
Diese Choreographie platziert den Stage-3 raw buffer unmittelbar vor dem Stage-3 QuramDngImage, sodass der ebenenbasierte Overflow Felder innerhalb des Descriptors umschreibt, anstatt zufällige States abstürzen zu lassen.
Vendor “Unknown” Opcodes als Data Blobs wiederverwenden
Samsung lässt das high bit in vendor-spezifischen opcode IDs gesetzt (z. B. ID 23), was den Interpreter anweist, die Struktur zu allocaten, aber die Ausführung zu überspringen. Der Exploit missbraucht diese ruhenden Objekte als vom Angreifer kontrollierte Heaps:
- Opcode-Listen 1 und 2
Unknown(23)-Einträge dienen als zusammenhängende Scratchpads zum Speichern von Payload-Bytes (JOP chain bei Offset 0xf000 und ein Shell-Kommando bei 0x10000 relativ zum raw buffer). - Weil der Interpreter jedes Objekt beim Verarbeiten von Liste 3 weiterhin als Opcode betrachtet, reicht es, später die vtable eines Objekts zu übernehmen, um die Ausführung von Angreifer-Daten zu starten.
Gefälschte MapTable-Objekte konstruieren & ASLR umgehen
MapTable-Objekte sind größer als TrimBounds, aber sobald die Layout-Korruption sitzt, liest der Parser gerne zusätzliche Parameter OOB:
- Verwende das lineare Write-Primitive, um teilweise einen
TrimBounds-vtable-Pointer mit einer gefälschtenMapTable-Substitutionstabelle zu überschreiben, die die unteren 2 Bytes von einer benachbartenTrimBounds-vtable auf dieMapTable-vtable abbildet. Nur die low bytes unterscheiden sich zwischen unterstützten Quram-Builds, sodass eine einzige 64K-Lookuptabelle sieben Firmware-Versionen und jede 4 KB ASLR-Slide abdecken kann. - Patch die restlichen
TrimBounds-Felder (top/left/width/planes), sodass das Objekt sich später wie eine gültigeMapTableverhält. - Führe den gefälschten Opcode über nullisierten Speicher aus. Weil der Substitutionstabelle-Pointer tatsächlich auf die vtable eines anderen Opcodes referenziert, werden die Output-Bytes zu leaked low-order addresses aus
libimagecodec.quram.sooder dessen GOT. - Wende zusätzliche
MapTable-Durchläufe an, um diese Zwei-Byte-Leaks in Offsets zu Gadgets wie__ink_jpeg_enc_process_image+64,QURAMWINK_Read_IO2+124,qpng_check_IHDR+624und libc’s__system_property_get-Eintritt zu konvertieren. Die Angreifer bauen damit effektiv vollständige Adressen innerhalb ihrer gesprayten Opcode-Region ohne native Memory-Disclosure-APIs zusammen.
Triggering the JOP ➜ system() Transition
Sobald Gadget-Pointer und Shell-Kommando im Opcode-Spray platziert sind:
- Eine letzte Welle von
DeltaPerColumn-Writes addiert0x0100an Offset 0x22 des Stage-3QuramDngImageund verschiebt dessen raw buffer pointer um 0x10000, sodass er nun auf den Angreifer-Command-String zeigt. - Der Interpreter beginnt, die Tail von 1040
Unknown(23)-Opcodes auszuführen. Der erste korrumpierte Eintrag hat seine vtable durch die gefälschte Tabelle bei Offset 0xf000 ersetzt, sodassQuramDngOpcode::aboutToApplyqpng_read_data(den 4. Eintrag) aus der Fake-Tabelle auflöst. - Die verketteten Gadgets führen aus: Laden des
QuramDngImage-Pointers, Addieren von 0x20, um auf den raw buffer pointer zu zeigen, Dereferenzieren desselben, Kopieren des Ergebnisses inx19/x0, dann Springen durch GOT-Slots, die aufsystemumgeschrieben wurden. Weil der raw buffer pointer jetzt gleich dem Angreifer-String ist, führt das finale Gadgetsystem(<shell command>)innerhalb voncom.samsung.ipserviceaus.
Hinweise zu Allocator-Varianten
Es existieren zwei Payload-Familien: eine auf jemalloc abgestimmt, eine andere auf scudo. Sie unterscheiden sich darin, wie Opcode-Blöcke angeordnet werden, um Adjazenz zu erreichen, teilen aber dieselben logischen Primitiven (DeltaPerColumn bug ➜ MapTable zero/write ➜ bogus vtable ➜ JOP). Scudos deaktivierte Quarantine macht die Wiederverwendung von 0x30-Byte-Freelists deterministisch, während jemalloc auf Size-Class-Control via tile/subIFD-Sizing angewiesen ist.
References
Tip
Lernen & üben Sie AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Lernen & üben Sie Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
HackTricks

