
Prueba de concepto de exploit para una sobrelectura de heap en el filtro RAR v4 de libarchive (CVE-2025-5915) con reproducción en ASan, codificador y demostración en dispositivo iOS 18.5.
Una lectura fuera de límites de heap / divulgación de memoria controlada en la ruta del filtro RAR v4 de libarchive
(copy_from_lzss_window). Este repositorio la reproduce de principio a fin: ASan local, un
codificador RAR v4 desde cero que ajusta el tamaño de la fuga, y una demostración en dispositivo en iOS 18.5
usando la libarchive.2.dylib del propio sistema del teléfono.
parse_filter() lee un blocklength de filtro (bytecode RAR-VM, hasta 32 bits)
y copy_from_lzss_window() hace memcpy de esa cantidad de bytes fuera de la ventana LZSS sin
comprobar que cabe en dictionary_size. El tamaño de la ventana es — el atacante
controla ambos. Declara → ventana de 32 bytes, pide → lee
~240 KB del heap adyacente hacia la salida descomprimida.rar_fls(unp_size) << 1unp_size=16blocklength=0x3C000a612bf62 (libarchive 3.8.0) añade if (blocklength > rar->dictionary_size) return 0;
(además de un fix de wrap-around en copy_from_lzss_window).3.7.4 — la cadena de versión no los distingue (ver writeup §7–8).Consulta el artículo completo: writeup/cve-2025-5915.en.md
(italiano: writeup/cve-2025-5915.it.md).
El mismo blocklength sin comprobar es la longitud de un memcpy con dos extremos:
| lado | límite faltante | CVE | fix |
|---|---|---|---|
| origen (ventana LZSS) | blocklength ≤ dictionary_size | CVE-2025-5915 (lectura) | a612bf62, v3.8.0 |
destino (vm->memory, 0x40000) | blocklength ≤ VM_MEMORY_SIZE | CVE-2024-26256 (escritura) | b7b0c7c4, v3.7.5 |
En iOS 18.5 el límite del lado de escritura (26256) ya está backporteado, pero la protección del lado de lectura (5915)
no — así que en iOS esto es solo de lectura (analysis/two_cve_unification.md).
writeup/ artículo técnico completo (EN + IT)
poc/
build_bigleak.py reduce unp_size en un archivo real + repara el CRC-16 de la cabecera
build_encoder.py codificador RAR v4 desde cero; ajusta blocklength (tamaño de la fuga)
plant.c interposición de realloc en macOS para plantar un secreto tras la ventana
*.rar archivos de prueba de concepto (ver poc/README.md)
RARLeak/ harness iOS en dispositivo (proyecto Xcode)
analysis/ registros de ASan, diff de parche de iOS (desensamblado), notas, parche de protección aislado
device-proof/ salida de la ejecución en dispositivo (iPhone, iOS 18.5)
git clone https://github.com/libarchive/libarchive && cd libarchive && git checkout v3.7.4
CC=clang CFLAGS="-fsanitize=address -g -O1" LDFLAGS="-fsanitize=address" \
cmake -B build-asan -DENABLE_TEST=OFF . && cmake --build build-asan --target bsdtar
ASAN_OPTIONS=detect_leaks=0 build-asan/bin/bsdtar -xOf poc/enc_0x40000.rar >/dev/null
# -> AddressSanitizer: heap-buffer-overflow READ of size 262112
Crea el tuyo propio: python3 poc/build_encoder.py out.rar <unp_size> <blocklength> [e8e9].
poc/RARLeak es una app iOS que inunda su heap, hace dlopen de la libarchive del sistema, le pasa un
RAR manipulado y cuenta cuánto de su propio heap vuelve en la salida. Configura tu equipo de firma y compila:
cd poc/RARLeak && ./build.sh <device-udid> # configura DEVELOPMENT_TEAM primero (ver build.sh)
Esperado: un archivo declarado con 16 bytes produce ~196 KB de salida, ~150 KB de ellos son el marcador
LK5915!! plantado y leído fuera de límites. El resultado se escribe en Documents/ de la app.
La libarchive.2.dylib de Apple (18.5 / 18.6) no está incluida (propietaria). Solo sus
SHA-1 (analysis/SHA1SUMS.ios-dylibs) y los extractos de desensamblado relevantes. Extrae la tuya
con ipsw dyld extract <dyld_shared_cache> libarchive.2.dylib.
N-day, corregido en libarchive 3.8.0 / iOS 18.6. Todo fue probado en hardware propio del autor. Bug reportado por JJLeo (issue #2565 de libarchive), investigación de Yifan Zhang (PLL, Universidad de Pekín), fix de Tobias Stoeckmann y Tim Kientzle. Fix de CVE-2024-26256 de Tobias Stoeckmann. Solo para uso investigativo y defensivo.