Reversing de Buffer Overflow y Format String
1. Creación de un programa vulnerable a Buffer Overflow y reversing.
A continuación, se muestra el código fuente en C/C++ del programa con los comentarios que detallan su operación. Se compila en 32 bits para sistemas Windows, bajo el IDE “DevC++ 5.11” y compilador “GCC v.4.9.2”.

A continuación, se puede observar en la siguiente captura cómo se presenta el código desensamblado en IDA PRO.

A continuación, podemos observar el código que nos arroja IDA PRO con su reconstructor de código de ASM a C/C++.

Como se puede observar, prácticamente el código reconstruido por IDA PRO a través del código generado ASM, es el mismo que el original programado en el IDE “Dev-C++”.
2. Reversing o análisis de la vulnerabilidad BoF en tiempo de ejecución.
Para mostrar la vulnerabilidad en tiempo de ejecución (análisis dinámico), hemos optado por el uso de la herramienta “x32dbg”, ya que la aplicación a analizar la hemos compilado en 32 bits para sistemas Windows. Puntualmente empleamos IDA PRO para realizar un análisis estático y poder observar de manera más organizada y visual las distintas funciones que conforman y estructuran el programa.
Los trabajos se van a realizar bajo un entorno virtualizado con Windows 7 con la intención de desactivar el Address Space Layout Randomization (ASLR) y el Data Execution Prevention (DEP), que son dos mecanismos de seguridad implementados en sistemas operativos modernos para dificultar la explotación de vulnerabilidades en el software, ya que ambos mecanismos añaden capas adicionales de protección contra ataques como desbordamientos de buffer (BoF).
Sobre la vulnerabilidad que presenta el programa, viene dada porque este hace uso de la función “strcpy ()” para copiar una cadena de caracteres de un buffer a otro, ambos definidos en el código del programa, como bien hemos visto en el punto anterior. La vulnerabilidad que presenta es un desbordamiento de búfer (Buffer Overflow), que ocurre durante la ejecución del programa cuando se copia una cadena más larga de lo que el búfer puede contener.
Como se puede observar en la siguiente captura, el programa crashea (deja de funcionar) al alcanzar una excepción provocada por un BoF, observando como el campo de “Desplazamiento de excepción” está sobrescrito por el valor hexadecimal (“41”) correspondiente al carácter “A” con el que se ha desbordado el búfer.

A continuación, se desensambla con la herramienta “x32dbg” el programa y se da paso a su ejecución para poderlo debuggear. El objetivo en este momento es realizar la primera fase de “exploración” o “reconocimiento” para poder estudiarlo posteriormente más detenidamente. En la siguiente captura se observa cómo el usuario introduce su nombre, apellidos y varias “A” para llegar a provocar el BoF.

Sin haber colocado ningún punto de interrupción (breakpoint), se puede observar cómo tras pulsar “enter” el flujo del programa llega a su fin reportando la excepción producida por el BoF. Se marcan en rojo los valores sobrescritos (“41”) correspondientes al valor hexadecimal del carácter ASCII “A”, así como la excepción alcanzada con la que el proceso crashea.

Con lo que hemos podido ver hasta el momento, se puede sacar la conclusión de que el código proporcionado tiene una vulnerabilidad de Buffer Overflow (BoF) evidente y potencialmente una segunda, dependiendo de cómo “scanf()” se maneje en la práctica.
- Vulnerabilidad clara de Buffer Overflow que explotaremos en el ejercicio.
- strcpy(buffer, entradausuario);: Esta función es claramente vulnerable a Buffer Overflow porque “strcpy()” no realiza ninguna comprobación de longitud y simplemente copiará la cadena de “entradausuario” a “buffer” sin importar su tamaño, siempre y cuando no exceda los 99 caracteres que “scanf()” permite leer. Dado que “buffer” solo tiene espacio para 20 caracteres, cualquier entrada que exceda este tamaño sobrescribirá la memoria adyacente a “buffer”.
- Potencial segunda vulnerabilidad de Buffer Overflow.
- scanf(«%99s», entradausuario);: Aunque esta función parece segura porque limita la lectura a 99 caracteres, dejando espacio para el carácter nulo, podría ser vulnerable si el compilador o la plataforma en cuestión no manejan correctamente el especificador de ancho de campo “%99s”. Además, aunque “scanf()” está limitado a 99 caracteres, y asumiendo que este límite se respeta, cualquier entrada que exceda el tamaño del “buffer” en “strcpy()” resultará en un BoF. Por lo tanto, la principal vulnerabilidad aquí es el uso de “strcpy()” sin comprobar la longitud de la cadena de entrada en relación con el tamaño del “buffer” de destino.
Continuando con el análisis, reiniciamos el proceso de debug y examinamos el proceso que tiene lugar desde que el usuario introduce una cadena de caracteres hasta que se produce el desbordamiento de búfer (BoF). En el punto donde el programa se detiene para solicitar el nombre y apellidos del usuario, estamos presenciando la invocación de la función “scanf()” en C/C++. Esta función es la que recoge la entrada del usuario y es visible en la captura junto con las otras funciones que componen el programa.

La captura proporcionada muestra el momento en el que el usuario introduce una cadena de texto que supera la capacidad prevista del búfer, creando las condiciones para un desbordamiento de búfer. Además, se aprecia que después de que el usuario presiona «enter», la ejecución del programa se detiene en la función “strcpy”, lugar en el que se ha establecido un punto de interrupción (breakpoint) para permitir un análisis detallado de la función paso a paso.

Así pues, en la siguiente captura se muestra el código correspondiente a la función vulnerable “strcpy()”, la cual vamos a analizar detenidamente a continuación.

Llegados a este punto, vamos a definir las acciones del código ASM por bloques de instrucciones y a explicar qué hace cada instrucción cuando se le pasa a la función “strcpy()” por argumento el buffer origen[100] = «AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA» (variable “entradausuario[100]”) y debe copiarlo en el buffer destino[20] (variable buffer[20]).
- Configuración inicial y salto al bucle.
- push edi: Guarda el valor actual de “edi” en la pila.
- mov edi, dword ptr ss:[esp+8]: Carga la dirección del buffer de destino (buffer[20]) en “edi”.
- jmp msvcrt.75E38DAC: Salta directamente al comienzo del bucle principal.
(Las siguientes instrucciones no se ejecutan debido al salto directo al bucle).
- Bucle principal de copia.
- mov ecx, dword ptr ss:[esp+C]: Carga la dirección del buffer de origen (entradausuario[100]) en “ecx”.
- test ecx, 3: Verifica si “ecx” está alineado a un límite de 4 bytes.
- jne msvcrt.75E38E17: Si “ecx” no está alineado, salta a la dirección 75E38E17. Aquí se maneja la copia de caracteres individuales, en lugar de bloques de 4 bytes.
- mov edx, 7EFEFEFF: Prepara “edx” para la operación de detección de fin de cadena.
- mov eax, dword ptr ds:[ecx]: Carga 4 bytes del buffer de origen en “eax”.
- add edx, eax: Suma “eax” a “edx”.
- xor eax, FFFFFFFF: Invierte los bits de “eax”.
- xor eax, edx: Realiza una operación XOR entre “eax” y “edx”.
- mov edx, dword ptr ds:[ecx]: Carga 4 bytes del buffer de origen en “edx”.
- add ecx, 4: Avanza el puntero de origen.
- test eax, 81010100: Verifica si hay un byte cero en “eax”.
- jne msvcrt.75E38DD9: Si no hay byte cero, continúa la copia.
- mov dword ptr ds:[edi], edx: Copia 4 bytes en “edx” al buffer de destino.
- add edi, 4: Avanza el puntero de destino.
- jmp msvcrt.75E38DB8: Repite el bucle.
- Manejo de caracteres no alineados (en «75E38E17»). Ver explicación más adelante.
- mov dl, byte ptr ds:[ecx]: Carga el siguiente byte del buffer de origen en “dl”.
- add ecx, 1: Avanza el puntero de origen.
- test dl, dl: Verifica si “dl”es cero (fin de cadena).
- je msvcrt.75E38E0F: Si es cero, termina la copia.
- mov byte ptr ds:[edi], dl: Copia el byte en “dl” al buffer de destino.
- add edi, 1: Avanza el puntero de destino.
- test ecx, 3: Verifica nuevamente la alineación.
- je msvcrt.75E38DB8: Si está alineado, vuelve al bucle de copia de bloques.
- jmp msvcrt.75E38E17: Continúa con la copia de caracteres individuales.
- Finalización de la copia.
- test dl, dl, test dh, dh, y test edx, FF0000: Verifican los distintos bytes de “edx” para determinar cuántos bytes restan por copiar.
- mov word ptr ds:[edi], dx: Copia los últimos 2 bytes si es necesario.
- mov eax, dword ptr ss:[esp+8]: Carga la dirección del buffer de destino en “eax” nuevamente.
- mov byte ptr ds:[edi+2], 0: Establece el siguiente byte a cero, asegurando que la cadena de destino termine con un carácter nulo.
- Restauración de registros y salida.
- pop edi: Restaura el valor original de “edi”.
- ret: Retorna de la función y continua su flujo de ejecución.
El desbordamiento de búfer (BoF) ocurre porque el buffer de origen (entradausuario[100]) tiene una mayor capacidad que el buffer de destino (buffer[20]). La función “strcpy” transfiere caracteres desde el origen hasta el destino hasta que encuentra un carácter nulo (“\0”), sin realizar una verificación del tamaño del buffer de destino. Como resultado, si la cadena de origen es más extensa que el destino, la función termina escribiendo más allá del límite del buffer de destino. Este exceso de escritura sobrescribe la memoria adyacente, provocando un desbordamiento de búfer (BoF).
Llegados a este punto, el flujo sale de la función “strcpy” y continúa con la función “printf”, la cual no vamos a detallar ya que no presenta interés sobre la vulnerabilidad que nos atañe. Posteriormente, el flujo procede al punto esperado donde ocurrirá la excepción de violación de acceso fruto del BoF.
En la captura que se muestra a continuación, se observa cómo el registro “EIP” es sobrescrito con los valores en hexadecimal “41” correspondientes al carácter ASCII “A”, al apuntar “ESP” a la dirección 0028FED0 del stack (la pila) que los contiene debido al BoF sufrido durante el proceso de ejecución de la función “strcpy”.
Esta sobreescritura del EIP con el valor «41414141» ocurre tras la ejecución de la instrucción “ret”, y como resultado, el proceso intenta saltar a la dirección «41414141», que no es válida, provocando una excepción de violación de acceso. Este error se produce inmediatamente después de la ejecución de la instrucción “ret”, mostrando cómo un desbordamiento de búfer puede conducir a un control no intencionado del flujo del programa y a errores críticos de ejecución.


En referencia al «manejo de caracteres no alineados» (punto 3 del análisis de la función “strcpy”) se refiere a cómo el código gestiona situaciones en las que las direcciones de memoria de los caracteres de una cadena no caen en límites de memoria que son múltiplos exactos de cierto tamaño (en arquitecturas de 32 bits, estos límites son múltiplos de 4 bytes, y en arquitecturas de 64 bits son múltiplos de 8 bytes). Así pues, cuando los caracteres de una cadena no están «alineados» a estos límites de memoria (es decir, las direcciones de memoria no son múltiplos exactos de 4 o 8 bytes), el código evita leer o escribir bloques enteros de 4 bytes, y en lugar de eso, maneja la cadena byte por byte para evitar errores o ineficiencias que podrían surgir al tratar de acceder a direcciones de memoria no alineadas.
En referencia a la explicación de por qué el programa analizado es vulnerable, se puede concluir que se debe a los siguientes puntos:
-
- Falta de comprobación de límites: La principal razón por la que “strcpy” es vulnerable es que no verifica si el búfer de destino es lo suficientemente grande para contener la cadena de origen. Esto es un problema inherente al diseño de la función.
- Control del atacante sobre los datos: Dado que la cadena de origen proviene de la entrada del usuario (argumentos de línea de comandos), un atacante puede explotar esta vulnerabilidad proporcionando deliberadamente una entrada más larga de lo esperado.
En referencia a las consecuencias de la vulnerabilidad, se pueden indicar las siguientes:
-
- Ejecución de código arbitrario: Un atacante podría diseñar una entrada que no solo cause un desbordamiento de búfer, sino que también inserte código malicioso en la memoria y altere el flujo de control del programa para ejecutar ese código. Esta parte no se ha llevado a cabo en esta PEC debido a que no es el objetivo de la mismo. No obstante, se llevará a cabo en la PRAC1 de esta misma asignatura.
- Denegación de servicio: Como mínimo, un desbordamiento de búfer puede hacer que el programa crashee (como se ha mostrado al principio del punto 1.2), lo que podría ser explotado para un ataque de Denegación de Servicio (DoS).
En referencia a cómo mitigar la vulnerabilidad presentada, se proponen los siguientes puntos:
-
- Evitar “strcpy” : Usar funciones alternativas que realizan comprobaciones de límites, como “strncpy”.
- Validación de entradas: Se aconseja adoptar prácticas de programación defensiva que asuman que las entradas pueden ser maliciosas y que siempre verifiquen y limiten las entradas del usuario. Esta medida es extrapolable a todo tipo de aplicaciones, ya que siempre se debe desconfiar de los parámetros de entrada procedentes de un usuario final.
3. Vulnerabilidad de tipo Format String.
Se puede afirmar que las vulnerabilidades de tipo «Format String» ocurren en un programa cuando las funciones de entrada/salida que procesan cadenas de formato (como “printf”, “sprintf”, “fprintf”, etc., en C/C++) son utilizadas de manera insegura. Así pues, estas vulnerabilidades se presentan cuando una función que espera una cadena de formato fija recibe una cadena controlada por el usuario, que puede contener especificadores de formato (como “%s”, “%d”, “%x”, etc.).
A continuación, se muestra un código de ejemplo de una vulnerabilidad de tipo Format String:
char entrada_usuario [100];
scanf(«%s», entrada_usuario);
printf(entrada_usuario); // Vulnerable si entrada_usuario contiene especificadores de formato
En este caso, “entrada_usuario” es una cadena proporcionada por el usuario. Si “entrada_usuario” contiene especificadores de formato (por ejemplo, “%s”), la función “printf” intentará acceder a la dirección de memoria correspondiente y tratará de imprimir el contenido de esa dirección como una cadena, lo que puede llevar a varios tipos de comportamientos inseguros y no deseados.
En referencia a los peligros que presenta este tipo de vulnerabilidad, se indican los siguientes:
- Lectura de memoria arbitraria: Un atacante puede usar especificadores de formato para leer datos de la memoria del programa que no estaban destinados a ser accesibles, lo que puede llevar a la exfiltración de información sensible.
- Escritura en memoria arbitraria: Ciertos especificadores de formato permiten escribir en direcciones de memoria específicas, por lo que un atacante podría explotar esto para sobrescribir valores críticos en el programa, como direcciones de retorno de funciones, con el objetivo de redirigir el flujo de ejecución y llegar a ejecutar código arbitrario, entre otras cosas.
- Crashes y comportamiento indefinido: El uso inadecuado de cadenas de formato puede llevar a fallos del programa (crashes), comportamientos impredecibles y corrupción de datos. De esta manera un atacante podría llegar a realizar una Denegación de Servicio (DoS).
En referencia a medidas de subsanación (mitigación) y buenas prácticas, se indican las siguientes:
- Nunca usar entradas no verificadas – validación de entradas: No se deben usar cadenas proporcionadas por el usuario directamente en funciones como las indicadas anteriormente (“printf”, “sprintf”, “fprintf”, etc.), y en su lugar usar una cadena de formato fija, como por ejemplo printf(«%s», entrada_usuario);. Del mismo modo, hay que asegurarse de que las entradas del usuario se validen adecuadamente y se limpien de posibles especificadores de formato peligrosos antes de usarlas.
- Usar funciones seguras: Se debe evitar usar funciones conocidas por ser vulnerables a ataques de cadenas de formato y hay que optar por alternativas más seguras que no interpretan la entrada como una cadena de formato.
- Herramientas de análisis estático: Se aconseja hacer uso de herramientas de análisis estático de código para identificar posibles vulnerabilidades de cadenas de formato en las etapas de desarrollo y prueba del software.
4. Reversing y análisis de una vulnerabilidad tipo Format String.
Un «Format String Bug» puede ser explotado de varias formas, dependiendo de la naturaleza del error y del contexto en el que se encuentra. Así pues, cabe destacar que los atacantes pueden utilizar estos errores para causar daños que van desde la lectura de datos sensibles hasta la ejecución de código arbitrario, como se muestra en los siguientes puntos.
- Un atacante puede usar especificadores de formato como “%s” para leer datos de la memoria del programa. Esto puede revelar información sensible que no estaba destinada a ser accesible, como contraseñas, claves de cifrado, o datos de usuarios.
- Algunos especificadores de formato permiten escribir en direcciones de memoria específicas, lo cual podría ser aprovechado por un atacante para sobrescribir valores críticos en el programa, como direcciones de retorno de funciones o punteros a funciones (igual que se ha visto en el análisis de la vulnerabilidad BoF). Esto puede ser utilizado para alterar el flujo de control del programa y ejecutar código arbitrario, a menudo inyectando y ejecutando un “shellcode”.
- Un atacante podría explotar un error de cadena de formato para causar un crash en el programa, lo que podría ser utilizado en un ataque de denegación de servicio (DoS).
Como ejemplo de explotación se propone el siguiente código vulnerable:
- printf(entrada_usuario);
Si entrada_usuario es controlado por un atacante, podría contener una cadena como:
- «%x %x %x %s»
Esto provocaría que la función “printf” mostrase datos de la pila, posiblemente llegando a revelar información sensible.
Para ejecutar una explotación más sofisticada, el atacante requeriría un conocimiento detallado de la estructura de la memoria del programa, así como de las técnicas para manipular la pila y los registros mediante la cadena de formato. Esto implica entender cómo el programa almacena y accede a los datos en la memoria, y cómo se pueden utilizar las secuencias de formato para alterar el comportamiento del programa de manera específica y controlada.
En la siguiente imagen se muestran algunos parámetros que pueden ser empleados para realizar este tipo de explotaciones.
|
Parámetro |
Salida |
Pasado como |
|
%d |
decimal (int) |
valor |
|
%u |
decimal sin signo (unsigned int) |
valor |
|
%x |
hexadecimal (unsigned int) |
valor |
|
%s |
cadena ((const) (unsigned) char *) |
referencia |
|
%n |
número de bytes escritos hasta ahora, (int *) |
referencia |
|
%p |
dirección de puntero (void *) en hexadecimal |
valor |
5. Format String vs Stack Overflow.
Como ya hemos visto, las vulnerabilidades de «Format String» y «Stack Overflow» presentan distintas características y métodos de explotación, pero comparten similitudes como tipos de fallos de seguridad, las cuales se detallan a continuación.
- En cuanto a las similitudes se encuentran las siguientes:
- Corrupción de memoria: Tanto los errores de Format String como los desbordamientos de pila implican la corrupción de la memoria. En ambos casos, esta corrupción puede alterar el flujo de control normal del programa.
- Ejecución de código arbitrario: Ambos tipos de vulnerabilidades pueden ser explotados para ejecutar código arbitrario. En el caso de un desbordamiento de pila, esto suele ocurrir sobrescribiendo la dirección de retorno de una función en la pila. En un error de “Format String”, puede ocurrir mediante la escritura en direcciones de memoria arbitrarias.
- Dependencia del layout de la memoria: La explotación exitosa de ambas vulnerabilidades a menudo requiere conocimiento sobre el layout de la memoria del programa, como la ubicación de ciertas variables, direcciones de retorno, o la disposición de la pila.
En cuanto a las diferencias se encuentran las siguientes:
- Mecanismo de vulnerabilidad:
-
- Buffer Overflow (BoF): Ocurre cuando los datos exceden el espacio asignado en la pila, típicamente debido a la copia de datos a un búfer más pequeño de lo requerido. Se puede afirmar que es una vulnerabilidad directa en la gestión de la memoria.
- Error de Format String: Ocurre cuando una función que procesa cadenas de formato recibe una cadena controlada por el usuario que contiene especificadores de formato inesperados. Se puede afirmar que se trata más de una vulnerabilidad en la interpretación de la entrada que en la gestión de la memoria.
-
- Tipo de funciones afectadas:
-
- Los desbordamientos de pila están generalmente asociados con funciones que manipulan cadenas o búferes, como “strcpy”, strcat, etc.
- Los errores de Format String están asociados con funciones de formateo de cadenas, como “printf”, “sprintf”, “fprintf”, etc.
-
- Control del atacante:
-
- En un desbordamiento de pila, el atacante generalmente tiene un control más directo sobre los datos que se escriben en la memoria, aunque está limitado por el tamaño y la ubicación del búfer.
- En un error de Format String, el atacante puede tener un control más sofisticado, como leer o escribir en direcciones de memoria específicas, pero esto requiere un conocimiento más profundo de la estructura de la memoria del programa y el uso creativo de los especificadores de formato.
-
- Complejidad de la explotación:
-
- Los desbordamientos de pila suelen ser más directos de explotar, aunque las medidas de seguridad como NX (No Execute) y ASLR (Address Space Layout Randomization) han aumentado su dificultad.
- Los errores de Format String pueden ser más complejos de explotar, ya que requieren un entendimiento detallado de cómo las funciones de formato interpretan los especificadores de formato y cómo esto afecta la memoria.
-
De todo lo anterior se concluye que, aunque ambos tipos de vulnerabilidades implican la manipulación indebida de la memoria y pueden tener consecuencias graves, difieren en sus mecanismos subyacentes y en las técnicas requeridas para su explotación.
6. Realización de un programa vulnerable a Format String y reversing o análisis en tiempo de ejecución.
A continuación, se muestra el código fuente comentado en detalle de un ejemplo sencillo de un programa en C/C++ que contiene una vulnerabilidad de tipo Format String. Este programa utilizará la función “printf” de manera que pueda ser explotada si se le proporciona una entrada específica. Como se muestra en la captura, se ha empleado el mismo compilador que en caso del ejercicio del BoF. Del mismo modo, también se empleará el mismo entorno de trabajo para realizar el análisis dinámico.

La vulnerabilidad se produce cuando “printf” se llama con “buffer” como su único argumento, ya que interpreta el contenido de “buffer” como una cadena de formato, por lo que si “buffer” contiene especificadores de formato (como “%s”, “%d”, “%x”, etc.), “printf” intentará procesarlos. Esto quiere decir que si un usuario introduce una cadena que contiene especificadores de formato, “printf” intentará acceder a la memoria según lo dictado por estos especificadores, lo que puede llevar a la divulgación de información sensible, corrupción de memoria, o incluso fallos del programa, como se muestra en la siguiente captura.

Para verificar cómo se manifiesta esta vulnerabilidad durante la ejecución del programa, emplearemos nuevamente el debugger “x32dbg”. Una vez cargado el programa estableceremos un punto de interrupción (breakpoint) justo antes de la ejecución de la función vulnerable printf().
Para esta Prueba de Concepto (PoC), el usuario ingresará distintas cadenas (tipo “%x%x%x”, “%d%d”, etc.), lo que permitirá observar cómo el programa, al interpretar esta entrada como especificadores de formato, imprime datos desde la pila, considerados información sensible. En una siguiente PoC veremos cómo con una secuencia adecuada de especificadores de formato se podrá escribir en direcciones de memoria específicas.
En este punto, podemos ver cómo las direcciones que serán impresas por la función “printf()” se disponen de forma contigua en la pila. Esto se debe a que el comportamiento estándar de “printf()” implica realizar un PUSH de sus argumentos en la pila antes de proceder a imprimirlos.

En la siguiente captura se puede observar cómo la función “printf()” imprime por pantalla los valores almacenados en la pila, las cuales hemos marcado en rojo para una mejor comprensión visual.

Del mismo modo, si ahora empleamos “%d %d” la función “printf()” devuelve el valor decimal entero equivalente al número hexadecimal de los valores almacenados en la pila, como se puede observar en la siguiente captura.

Llegados a este punto vamos a observar cómo también es de gran utilidad emplear el parámetro “%p” para obtener direcciones de punteros de la pila. De esta manera, realizando ensayo y error podemos observar cómo nuestro parámetro controlado (AAAABBBB, en hexadecimal 4141414142424242) se encuentra en la séptima y octava posición. Esto es útil para llegar a realizar la explotación de sobreescritura de memoria.

Ahora, si intentamos acceder al contenido que se encuentra en las posiciones séptima y octava, veremos que al no encontrarse nada el programa devolverá un “segmentation fault”, lo que se traduce en un crasheo de la aplicación.

En la siguiente captura de “x32dbg”, podemos ver cómo los valores introducidos por el usuario se han escrito en la pila, ubicándose específicamente en la séptima y octava posiciones. Si bien el propósito de este ejercicio no es demostrar una explotación completa que culmine en la ejecución de código arbitrario, es importante señalar que, en teoría, si se proporciona una dirección precisa/adecuada/correcta de una instrucción tipo “jmp esp” encontrada dentro del binario en ejecución o en una de sus librerías vinculadas (como “msvcrt.dll”), y si el puntero de la pila (“esp”) se ha ajustado para apuntar a un shellcode diseñado por un atacante, la ejecución de dicho shellcode sería posible, llevando a una ejecución de código arbitrario.

Por lo tanto, para resumir, se indica que para explotar esta vulnerabilidad un atacante podría diseñar un «payload» que incluya especificadores de formato cuidadosamente seleccionados con el fin de llevar a cabo acciones malintencionadas, tales como la lectura o la escritura de datos en la memoria, que pueden comprometer la confidencialidad e integridad de los datos, así como la disponibilidad del aplicativo mediante una denegación de servicio.


