Cobertura binaria por el camino difícil: instrumentar ramas con INT3 sobre KVM

Fuentes: Binary Coverage the Wrong Way

El artículo describe un método poco ortodoxo para obtener cobertura precisa de código en binarios sin código fuente (black-box), inspirado en la necesidad del autor de construir un fuzzer propio sin dynamic recompilation ni un portátil con Intel PT. Explica primero la evolución del fuzz testing: desde los fuzzers ciegos que solo detectaban crashes, hasta American Fuzzy Lop (AFL), que introdujo la cobertura guiada registrando los bloques básicos alcanzados mediante un pase de instrumentación en Clang. Para binarios sin fuente, AFL++ emplea QEMU en modo usuario, que instrumenta el IR intermedio de TCG con un coste de 3-5x frente a ejecución nativa. La opción más eficiente es Intel PT, que delega el trazado al hardware con apenas un 10% de overhead, pero está limitada a procesadores Intel y AMD no ofrece una alternativa equivalente bien documentada.

Ante la ausencia de Intel PT, el autor propone instrumentar el código invitado sustituyendo todas las instrucciones de salto (Jcc) por INT3, una instrucción de un solo byte que transfiere el control al hipervisor sin alterar registros de propósito general. En Linux, capturar INT3 vía ptrace sería prohibitivamente lento por los múltiples cambios de anillo de privilegio. La solución pasa por KVM y las extensiones de virtualización VT-x: el binario se ejecuta dentro de una máquina virtual a velocidad casi nativa y cada INT3 provoca un VMExit barato al hipervisor, donde el fuzzer registra la rama alcanzada y reanuda la ejecución. Se trata, en palabras del autor, del camino incorrecto para resolver un problema clásico, pero viable para experimentar con cobertura precisa sin recompilación dinámica.