Share
## https://sploitus.com/exploit?id=FF9E5EF7-2243-5D51-BA97-775A8B72F3BA
# CVE-2025-5915 โ€” libarchive RAR v4 heap over-read (with on-device iOS 18.5 proof)

A controlled **heap over-read / memory-disclosure** in libarchive's RAR v4 filter path
(`copy_from_lzss_window`). This repo reproduces it end to end: local ASan, a from-scratch
RAR v4 encoder that dials the leak size, and an **on-device** demonstration on iOS 18.5
using the phone's own system `libarchive.2.dylib`.

- **Bug**: `parse_filter()` reads a filter `blocklength` (RAR-VM bytecode, up to 32 bits)
  and `copy_from_lzss_window()` `memcpy`s that many bytes out of the LZSS window without
  checking it fits `dictionary_size`. Window size is `rar_fls(unp_size)  rar->dictionary_size) return 0;`
  (plus a wrap-around fix in `copy_from_lzss_window`).
- **iOS**: 18.5 (22F76) ships libarchive 3.7.4 and is vulnerable; 18.6 (22G86) has the
  backport. Both report `3.7.4` โ€” the version string doesn't distinguish them (see writeup ยง7โ€“8).

See the full write-up: [`writeup/cve-2025-5915.en.md`](writeup/cve-2025-5915.en.md)
(Italian: [`writeup/cve-2025-5915.it.md`](writeup/cve-2025-5915.it.md)).

## One memcpy, two CVEs
The same unchecked `blocklength` is the length of one `memcpy` with two ends:
| side | missing bound | CVE | fix |
|---|---|---|---|
| source (LZSS window) | `blocklength โ‰ค dictionary_size` | **CVE-2025-5915** (read) | `a612bf62`, v3.8.0 |
| dest (`vm->memory`, 0x40000) | `blocklength โ‰ค VM_MEMORY_SIZE` | CVE-2024-26256 (write) | `b7b0c7c4`, v3.7.5 |

On iOS 18.5 the write-side cap (26256) is already backported but the read-side guard (5915)
is not โ€” so on iOS this is a **read** only (`analysis/two_cve_unification.md`).

## Repository layout
```
writeup/       full technical article (EN + IT)
poc/
  build_bigleak.py     shrink unp_size in a real archive + repair header CRC-16
  build_encoder.py     from-scratch RAR v4 encoder; dials blocklength (leak size)
  plant.c              macOS realloc interpose to plant a secret after the window
  *.rar                proof-of-concept archives (see poc/README.md)
  RARLeak/             on-device iOS harness (Xcode project)
analysis/      ASan logs, iOS patch-diff (disassembly), notes, isolated guard patch
device-proof/  output of the on-device run (iPhone, iOS 18.5)
```

## Reproduce (local, macOS/Linux)
```sh
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
```
Craft your own: `python3 poc/build_encoder.py out.rar   [e8e9]`.

## Reproduce (on-device, iOS โ‰ค 18.5)
`poc/RARLeak` is an iOS app that sprays its heap, `dlopen`s the system libarchive, feeds a
crafted RAR, and counts how much of its own heap comes back in the output. Set your signing
team and build:
```sh
cd poc/RARLeak && ./build.sh         # set DEVELOPMENT_TEAM first (see build.sh)
```
Expected: a 16-byte-declared file yields ~196 KB of output, ~150 KB of it the planted
`LK5915!!` marker read out of bounds. Result is written to the app's `Documents/`.

## Note on the iOS binaries
Apple's `libarchive.2.dylib` (18.5 / 18.6) is **not** included (proprietary). Only their
SHA-1s (`analysis/SHA1SUMS.ios-dylibs`) and the relevant disassembly excerpts are. Extract
your own with `ipsw dyld extract  libarchive.2.dylib`.

## Credits & ethics
N-day, fixed in libarchive 3.8.0 / iOS 18.6. Everything was tested on the author's own
hardware. Bug reported by JJLeo (libarchive issue #2565), research by Yifan Zhang (PLL,
Peking University), fix by Tobias Stoeckmann and Tim Kientzle. CVE-2024-26256 fix by
Tobias Stoeckmann. For research and defensive use only.