Kutumia vibaya Media Pipelines za Android & Image Parsers

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Uwasilishaji: Apps za ujumbe ➜ MediaStore ➜ Wachambua wenye ruhusa za juu

Mabuild ya kisasa ya OEM mara kwa mara huendesha indexers za media zilizo na ruhusa za juu ambazo zinazorudi kuskani MediaStore kwa ajili ya vipengele vya “AI” au kushiriki. Kwenye firmware ya Samsung kabla ya patch ya Aprili 2025, com.samsung.ipservice inapakia Quram (/system/lib64/libimagecodec.quram.so) na huichambua kiotomatiki faili yoyote ambayo WhatsApp (au apps nyingine) huweka ndani ya MediaStore. Kivitendo mshambuliaji anaweza kutuma DNG iliyofichwa kama IMG-*.jpg, kusubiri mwathiri kubofya “download” (1-click), na service yenye ruhusa za juu itachambua payload hata kama mtumiaji hakufungua gallery.

$ 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], ...

Vidokezo muhimu

  • Usambazaji unategemea re-parsing ya media ya mfumo (sio chat client) na kwa hivyo unapata ruhusa za mchakato huo (ufikiaji kamili wa kusoma/kuandika kwenye galeri, uwezo wa kuongeza media mpya, n.k.).
  • Parser yoyote ya picha inayoweza kufikiwa kupitia MediaStore (vision widgets, wallpapers, AI résumé features, n.k.) inakuwa inaweza kufikiwa kwa mbali ikiwa mshambuliaji anaweza kumshawishi mhusika kuokoa media.

Njia ya 0-click DD+/EAC-3 ya decoding (Google Messages ➜ mediacodec sandbox)

Staki za ujumbe za kisasa pia hufasiri kwa otomatiki audio kwa ajili ya transcription/uchunguzi. Kwenye Pixel 9, Google Messages itapeana sauti zinazoingia za RCS/SMS kwa Dolby Unified Decoder (UDC) ndani ya /vendor/lib64/libcodec2_soft_ddpdec.so kabla ya mtumiaji kufungua ujumbe, ikipanua uso wa 0-click hadi media codecs.

Vizuizi muhimu vya parse

  • Kila DD+ syncframe ina hadi 6 blocks; kila block inaweza kunakili hadi 0x1FF bytes za mshambuliaji-kudhibitiwa skip data ndani ya skip buffer (≈ 0x1FF * 6 bytes kwa frame).
  • Skip buffer inachambuliwa kwa ajili ya EMDF: syncword (0xX8) + emdf_container_length (16b) + field za urefu wa kubadilika. emdf_payload_size inaparsiwa kwa kutumia loop isiyo na mipaka variable_bits(8).
  • Bytes za EMDF payload zinatengwa ndani ya custom per-frame “evo heap” bump allocator na kisha zinakiliwa byte kwa byte kutoka kwa bit-reader uliojengwa na mipaka ya emdf_container_length.

Integer-overflow → heap-overflow primitive (CVE-2025-54957)

  • ddp_udc_int_evo_malloc inalinganisha alloc_size+extra hadi 8 bytes kupitia total_size += (8 - total_size) % total_size bila wrap detection. Thamani karibu na 0xFFFFFFFFFFFFFFF9..FF zinapunguza total_size kuwa ndogo kwenye AArch64.
  • Loop ya kunakili bado inatumia logical payload_length kutoka emdf_payload_size, hivyo bytes za mshambuliaji zinaandika juu ya data za evo-heap nyuma ya chunk iliyopunguzwa.
  • Urefu wa overflow umewekwa kwa usahihi na emdf_container_length iliyochaguliwa na mshambuliaji; bytes za overflow ni data za EMDF payload zinazoongozwa na mshambuliaji. Slab allocator inarejeshwa kila syncframe, ikitoa ujirani unaoweza kutabirika.

Secondary read primitive Ikiwa emdf_container_length > skipl, parsing ya EMDF inasoma zaidi ya skip bytes zilizowekwa (OOB read). Pekee yake ina leak zeros/known media, lakini baada ya kuharibu metadata ya heap jirani inaweza kusoma tena eneo lililoharibika kuthibitisha exploit.

Exploitation recipe

  1. Tengeneza EMDF na emdf_payload_size kubwa (kwa variable_bits(8)) ili padding ya allocator izunguke na kuingia kwenye chunk ndogo.
  2. Weka emdf_container_length kwa urefu wa overflow unaotaka (≤ bajeti ya jumla ya skip data); weka bytes za overflow ndani ya EMDF payload.
  3. Panga evo heap ya kila-frame ili allocation ndogo iwe kabla ya miundo lengwa ndani ya static buffer ya decoder (≈693 KB) au dynamic buffer (≈86 KB) iliyotengwa mara moja kwa kila instance ya decoder.
  4. Hiari: chagua emdf_container_length > skipl ili kusoma tena data zilizoandikwa juu kutoka skip buffer baada ya uharibifu.

Mende za Quram DNG Opcode Interpreter

Faili za DNG zinaorodhesha orodha tatu za opcode zinazotumika katika hatua tofauti za decode. Quram inanakili API ya Adobe, lakini handler yake ya Stage-3 kwa DeltaPerColumn (opcode ID 11) inaamini mipaka ya plane inayotolewa na mshambuliaji.

Mipaka ya plane isiyofaa katika DeltaPerColumn

  • Washambuliaji wanaweka plane=5125 na planes=5123 ingawa picha za Stage-3 zinaonyesha planes 0–2 (RGB) tu.
  • Quram huhesabu opcode_last_plane = image_planes + opcode_planes badala ya plane + count, na haitoi ukaguzi kama safu ya planes itawiana ndani ya picha.
  • Kwa hivyo loop inaandika delta kwenye raw_pixel_buffer[plane_index] kwa offset iliyodhibitiwa kabisa (mfano, plane 5125 ⇒ offset 5125 * 2 bytes/pixel = 0x2800). Kila opcode inaongeza thamani ya 16-bit float (0x6666) kwenye eneo lengwa, ikitoa primitive ya heap OOB add sahihi.

Turning increments into arbitrary writes

  • Exploit kwanza inaharibu Stage-3 QuramDngImage.bottom/right kwa kutumia 480 operesheni za DeltaPerColumn zilizofomwa vibaya ili opcodes za baadaye zichukulie kuratibu kubwa kama zilivyo ndani ya mipaka.
  • MapTable opcodes (opcode 7) kisha zinalengwa kwa mipaka bandia hiyo. Kwa kutumia jedwali la uingizaji lenye sifuri zote au DeltaPerColumn na deltas za -Inf, mshambuliaji anaweka sifuri eneo lolote, kisha anatumia deltas za ziada kuandika thamani sahihi.
  • Kwa sababu parameta za opcode ziko ndani ya metadata ya DNG, payload inaweza kubandika mamia ya maelfu ya maandishi bila kugusa kumbukumbu ya mchakato moja kwa moja.

Kupanga Heap chini ya Scudo

Scudo huweka allocations katika buckets kwa ukubwa. Quram inatengeneza vitu vifuatavyo kwa ukubwa sawa wa chunk wa 0x30-byte, kwa hivyo vinaishia katika eneo hilo (upangaji wa 0x40-byte kwenye heap):

  • QuramDngImage descriptors kwa Stage 1/2/3
  • QuramDngOpcodeTrimBounds na vendor Unknown opcodes (ID ≥14, ikiwa ni pamoja na ID 23)

Exploit inapanga mfululizo wa allocations ili kuweka chunks kwa utabiri:

  1. Stage-1 Unknown(23) opcodes (entry 20,000) spray 0x30 chunks ambazo baadaye zinafutwa.
  2. Stage-2 inafuta zile opcodes na kuweka QuramDngImage mpya ndani ya eneo lililofutwa.
  3. Entries 240 za Stage-2 Unknown(23) zinafutwa, na Stage-3 mara moja inatenga QuramDngImage yake pamoja na raw pixel buffer mpya ya ukubwa uleule, ikitumia tena nafasi hizo.
  4. Opcode ya kuundwa TrimBounds iliyotengenezwa inakwea kwanza kwenye orodha 3 na inatenga raw pixel buffer nyingine kabla ya kufuta state ya Stage-2, kuhakikisha ujirani “raw pixel buffer ➜ QuramDngImage”.
  5. Entries 640 za ziada za TrimBounds zimetajwa minVersion=1.4.0.1 hivyo dispatcher huwaachwa, lakini vitu vya nyuma vinabaki vimetengwa na baadaye vinageuka malengo ya primitive.

Mchoro huu unaweka raw buffer ya Stage-3 moja kwa moja kabla ya QuramDngImage ya Stage-3, hivyo overflow ya plane huharibu nyanja ndani ya descriptor badala ya kusababisha crash ya state isiyoeleweka.

Reusing Vendor “Unknown” Opcodes as Data Blobs

Samsung inaacha bit kubwa imewekwa kwenye vendor-specific opcode IDs (mfano, ID 23), ambayo inaelekeza interpreter kutenga muundo lakini kuruka utekelezaji. Exploit inatumia vitu hizo zenye usingizi kama heaps zinazodhibitiwa na mshambuliaji:

  • Orodha za opcode 1 na 2 Unknown(23) entries hutumika kama scratchpads zilizo mfululizo za kuhifadhi bytes za payload (JOP chain kwa offset 0xf000 na amri ya shell kwa 0x10000 ikilinganishwa na raw buffer).
  • Kwa sababu interpreter bado inachukulia kila kitu kama opcode wakati orodha 3 inatumiwa, kutawala vtable ya kitu kimoja baadaye inatosha kuanza kutekeleza data ya mshambuliaji.

Crafting Bogus MapTable Objects & Bypassing ASLR

Vitu vya MapTable ni kubwa kuliko TrimBounds, lakini mara tu muundo unapoharibika, parser hufurahia kusoma parameta zaidi nje ya mipaka:

  1. Tumia linear write primitive kuishika sehemu ya pointer ya vtable ya TrimBounds na kuibadilisha kwa jedwali la uingizaji la MapTable lililotengenezwa ambalo linamapisha bytes 2 za chini kutoka vtable jirani ya TrimBounds hadi vtable ya MapTable. Bytes za chini pekee ndizo tofauti kati ya builds mbalimbali za Quram zinazoungwa mkono, hivyo jedwali moja la 64K linaweza kushughulikia matoleo saba ya firmware na kila slide ya ASLR ya 4 KB.
  2. Maboresha sehemu nyingine za TrimBounds (top/left/width/planes) ili kitu kionekane kama MapTable halali wakati kitakapotekelezwa baadaye.
  3. Tekeleza opcode bandia juu ya kumbukumbu iliyowekwa sifuri. Kwa sababu pointer ya jedwali la uingizaji inarejea kwa vtable ya opcode nyingine, output bytes zinakuwa leaked low-order addresses kutoka libimagecodec.quram.so au GOT yake.
  4. Tumia ziara za ziada za MapTable kubadilisha leaks ambazo ni bytes mbili kuwa offsets kuelekea gadgets kama __ink_jpeg_enc_process_image+64, QURAMWINK_Read_IO2+124, qpng_check_IHDR+624, na entry ya libc __system_property_get. Washambuliaji kwa ufanisi wanajenga tena anuani kamili ndani ya eneo lao la opcode lililospray bila kutumia APIs za native memory disclosure.

Triggering the JOP ➜ system() Transition

Mara gadget pointers na amri ya shell vimepangwa ndani ya spray ya opcode:

  1. Mawimbi ya mwisho ya maandishi ya DeltaPerColumn yanaongeza 0x0100 kwenye offset 0x22 ya Stage-3 QuramDngImage, kubadilisha pointer ya raw buffer kwa 0x10000 hivyo sasa inarejea kamba ya amri ya mshambuliaji.
  2. Interpreter inaanza kutekeleza sehemu ya mwisho ya Unknown(23) opcodes 1040. Entry iliyoharibika ya kwanza ina vtable yake iliyobadilishwa na jedwali bandia kwenye offset 0xf000, hivyo QuramDngOpcode::aboutToApply inarejea qpng_read_data (ingizo la 4) kutoka kwenye jedwali bandia.
  3. Gadgets zilizofungwa zinafanya: kupakia pointer ya QuramDngImage, kuongeza 0x20 kuonyesha pointer ya raw buffer, kuirejea, kunakili matokeo ndani ya x19/x0, kisha kuruka kupitia slot za GOT zilizorekebishwa hadi system. Kwa kuwa pointer ya raw buffer sasa ni kamba ya mshambuliaji, gadget ya mwisho inatekeleza system(<shell command>) ndani ya com.samsung.ipservice.

Vidokezo kuhusu Tofauti za Allocator

Kuna familia mbili za payload: moja iliyoboreshwa kwa jemalloc, nyingine kwa scudo. Zinatofautiana jinsi blocks za opcode zinavyopewa mpangilio ili kupata ujirani lakini zinashiriki primitives za kimantiki zile zile (DeltaPerColumn bug ➜ MapTable zero/write ➜ bogus vtable ➜ JOP). Scudo bila quarantine huifanya ureuse wa freelist wa 0x30-byte uwe wa kibinadamu kabisa, wakati jemalloc inategemea udhibiti wa size-class kupitia sizing ya tile/subIFD.

References

Tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks