El código presentado es vulnerable a un ataque de buffer overflow. Aquí tienes una explicación paso a paso, ideal para un write up técnico y claro sobre el funcionamiento, la vulnerabilidad y cómo se explota para leer la flag en lugar de causar un segmentation fault.
Análisis del Código#
int __fastcall main(int argc, const char **argv, const char **envp)
{
_QWORD buf[5]; // [rsp+0h] [rbp-30h] BYREF
char v5; // [rsp+2Fh] [rbp-1h]
memset(buf, 0, 32);
v5 = 1;
read(0, buf, 0x40u);
if ( v5 == 1 )
{
fwrite("Not scary enough.. Boo! :(", 1u, 0x1Au, stdout);
fflush(stdout);
}
else
{
read_flag();
}
return 0;
}
Paso a paso del funcionamiento#
- Se declara un buffer
bufcomo un arreglo de 5 elementos tipo_QWORD, que equivale a 5 x 8 = 40 bytes (en sistemas de 64 bits). - Se declara una variable local
char v5. - El buffer se inicializa en cero con
memset. - Luego,
v5se establece en 1. - La función
read(0, buf, 0x40u);lee hasta 64 bytes desde la entrada estándar y los coloca en el bufferbuf. - El programa luego consulta si
v5sigue siendo igual a 1; si es así, imprime un mensaje. Si no, llama aread_flag()(que asume lee y muestra la flag).
Identificación de la Vulnerabilidad#
- El tamaño del buffer es de 40 bytes, pero el
readpermite escribir hasta 64 bytes. Cualquier dato que sobrepase los primeros 40 bytes sobrescribirá variables que estén a continuación en la pila (stack), comov5. - En la estructura del stack, “buf” está antes en memoria que “v5”. Así, los bytes extra sobreescriben “v5” y potencialmente variables más allá.
Aprovechamiento del Buffer Overflow#
- Si el atacante escribe 41 bytes (40 para llenar el buffer y 1 byte más), ese byte adicional sobrescribirá el valor de
v5. - Si el nuevo valor de
v5es distinto de 1 (por ejemplo, 0x00 o cualquier otro valor), se ejecutará la rama del else, provocando la llamada aread_flag()en vez de imprimir el mensaje. - De esta forma, es posible controlar el flujo del programa y acceder a la flag: simplemente proporciona como entrada 40 bytes de “padding” (cualquier valor) y el byte 41 debe ser diferente de 1.
