La programación orientada a retorno ( ROP ) es una técnica de explotación de seguridad informática que permite a un atacante ejecutar código en presencia de defensas de seguridad [1] como la protección del espacio ejecutable y la firma de código . [2]
En esta técnica, un atacante obtiene el control de la pila de llamadas para secuestrar el flujo de control del programa y luego ejecuta secuencias de instrucciones de la máquina cuidadosamente seleccionadas que ya están presentes en la memoria de la máquina, llamadas "gadgets". [3] Cada gadget normalmente termina en una instrucción de retorno y está ubicado en una subrutina dentro del programa existente y / o código de biblioteca compartido. Encadenados, estos dispositivos permiten a un atacante realizar operaciones arbitrarias en una máquina que emplea defensas que frustran ataques más simples.
Fondo
La programación orientada al retorno es una versión avanzada de un ataque de aplastamiento de pila . Generalmente, este tipo de ataques surgen cuando un adversario manipula la pila de llamadas aprovechando un error en el programa, a menudo un desbordamiento del búfer . En una saturación del búfer, una función que no realiza la verificación de límites adecuada antes de almacenar los datos proporcionados por el usuario en la memoria aceptará más datos de entrada de los que puede almacenar correctamente. Si los datos se escriben en la pila, el exceso de datos puede desbordar el espacio asignado a las variables de la función (por ejemplo, "locales" en el diagrama de pila a la derecha) y sobrescribir la dirección de retorno. Esta dirección será utilizada más tarde por la función para redirigir el flujo de control de regreso a la persona que llama . Si se ha sobrescrito, el flujo de control se desviará a la ubicación especificada por la nueva dirección de retorno.
En un ataque de desbordamiento de búfer estándar, el atacante simplemente escribiría el código de ataque (la "carga útil") en la pila y luego sobrescribiría la dirección de retorno con la ubicación de estas instrucciones recién escritas. Hasta finales de la década de 1990, los principales sistemas operativos no ofrecían ninguna protección contra estos ataques; Microsoft Windows no proporcionó protecciones de desbordamiento de búfer hasta 2004. [4] Finalmente, los sistemas operativos comenzaron a combatir la explotación de errores de desbordamiento de búfer marcando la memoria donde los datos están escritos como no ejecutables, una técnica conocida como protección de espacio ejecutable . Con esto habilitado, la máquina se negaría a ejecutar cualquier código ubicado en áreas de memoria en las que el usuario puede escribir, evitando que el atacante coloque la carga útil en la pila y salte a ella mediante una sobrescritura de la dirección de retorno. Posteriormente, se dispuso de soporte de hardware para fortalecer esta protección.
Con la prevención de ejecución de datos, un adversario no puede ejecutar instrucciones inyectadas maliciosamente porque un desbordamiento de búfer típico sobrescribe el contenido de la sección de datos de la memoria, que está marcada como no ejecutable. Para vencer esto, un ataque de programación orientado al retorno no inyecta código malicioso, sino que utiliza instrucciones que ya están presentes, llamadas "gadgets", manipulando las direcciones de retorno. Una prevención de ejecución de datos típica no puede defenderse de este ataque porque el adversario no utilizó código malicioso, sino que combinó instrucciones "buenas" cambiando las direcciones de retorno; por lo tanto, el código utilizado no se marcaría como no ejecutable.
Técnica de retorno a la biblioteca
La implementación generalizada de la prevención de ejecución de datos hizo que las vulnerabilidades tradicionales de desbordamiento de búfer fueran difíciles o imposibles de explotar de la manera descrita anteriormente. En cambio, un atacante estaba restringido al código que ya estaba en la memoria marcado como ejecutable, como el código del programa en sí y las bibliotecas compartidas vinculadas . Dado que las bibliotecas compartidas, como libc , a menudo contienen subrutinas para realizar llamadas al sistema y otras funciones potencialmente útiles para un atacante, son los candidatos más probables para encontrar código para armar un ataque.
En un ataque de retorno a la biblioteca, un atacante secuestra el flujo de control del programa explotando una vulnerabilidad de saturación del búfer, exactamente como se discutió anteriormente. En lugar de intentar escribir una carga útil de ataque en la pila, el atacante elige una función de biblioteca disponible y sobrescribe la dirección de retorno con su ubicación de entrada. Luego, se sobrescriben las ubicaciones de pila adicionales, obedeciendo las convenciones de llamadas aplicables , para pasar cuidadosamente los parámetros adecuados a la función para que realice funciones útiles para el atacante. Esta técnica fue presentada por primera vez por Solar Designer en 1997, [5] y luego se extendió al encadenamiento ilimitado de llamadas a funciones. [6]
Fragmentos de código prestados
El auge de los procesadores x86 de 64 bits trajo consigo un cambio en la convención de llamadas a subrutinas que requería que el primer argumento de una función se pasara en un registro en lugar de en la pila. Esto significaba que un atacante ya no podía configurar una llamada a la función de la biblioteca con los argumentos deseados simplemente manipulando la pila de llamadas a través de un exploit de saturación del búfer. Los desarrolladores de bibliotecas compartidas también comenzaron a eliminar o restringir las funciones de la biblioteca que realizaban acciones particularmente útiles para un atacante, como los envoltorios de llamadas del sistema . Como resultado, los ataques de retorno a la biblioteca se volvieron mucho más difíciles de montar con éxito.
La siguiente evolución llegó en forma de un ataque que utilizaba fragmentos de funciones de biblioteca, en lugar de funciones completas en sí mismas, para explotar vulnerabilidades de saturación de búfer en máquinas con defensas contra ataques más simples. [7] Esta técnica busca funciones que contengan secuencias de instrucciones que muestren valores de la pila en registros. La selección cuidadosa de estas secuencias de código permite a un atacante colocar valores adecuados en los registros adecuados para realizar una llamada de función bajo la nueva convención de llamada. El resto del ataque procede como un ataque de regreso a la biblioteca.
Ataques
La programación orientada al retorno se basa en el enfoque de fragmentos de código prestados y lo amplía para proporcionar la funcionalidad completa de Turing al atacante, incluidos los bucles y las ramas condicionales . [8] [9] Dicho de otra manera, la programación orientada al retorno proporciona un "lenguaje" completamente funcional que un atacante puede usar para hacer que una máquina comprometida realice cualquier operación deseada. Hovav Shacham publicó la técnica en 2007 [10] y demostró cómo todas las construcciones de programación importantes se pueden simular utilizando programación orientada a retorno contra una aplicación de destino vinculada con la biblioteca estándar C y que contiene una vulnerabilidad de saturación de búfer explotable.
Un ataque de programación orientado al retorno es superior a los otros tipos de ataque discutidos tanto en el poder expresivo como en la resistencia a las medidas defensivas. Ninguna de las técnicas de contraexplotación mencionadas anteriormente, incluida la eliminación de funciones potencialmente peligrosas de las bibliotecas compartidas, es eficaz contra un ataque de programación orientado al retorno.
En la arquitectura x86
Aunque los ataques de programación orientados al retorno se pueden realizar en una variedad de arquitecturas, [10] el artículo de Shacham y la mayoría del trabajo de seguimiento se centran en la arquitectura Intel x86 . La arquitectura x86 es un conjunto de instrucciones CISC de longitud variable . La programación orientada al retorno en el x86 aprovecha el hecho de que el conjunto de instrucciones es muy "denso", es decir, es probable que cualquier secuencia aleatoria de bytes sea interpretable como un conjunto válido de instrucciones x86.
Por lo tanto, es posible buscar un código de operación que altere el flujo de control, más notablemente la instrucción de retorno (0xC3) y luego mirar hacia atrás en el binario para los bytes precedentes que forman instrucciones posiblemente útiles. Estos conjuntos de "gadgets" de instrucciones se pueden encadenar sobrescribiendo la dirección de retorno, mediante un exploit de saturación de búfer, con la dirección de la primera instrucción del primer gadget. La primera dirección de los siguientes dispositivos se escribe sucesivamente en la pila. Al final del primer gadget, se ejecutará una instrucción de retorno, que sacará la dirección del siguiente gadget de la pila y saltará a él. Al finalizar ese gadget, la cadena continúa con el tercero, y así sucesivamente. Al encadenar las pequeñas secuencias de instrucciones, un atacante puede producir un comportamiento de programa arbitrario a partir del código de biblioteca preexistente. Shacham afirma que dada una cantidad suficientemente grande de código (incluida, entre otros, la biblioteca estándar de C), existirán suficientes dispositivos para la funcionalidad completa de Turing. [10]
Se ha desarrollado una herramienta automatizada para ayudar a automatizar el proceso de localización de dispositivos y la construcción de un ataque contra un binario. [11] Esta herramienta, conocida como ROPgadget, busca en un binario dispositivos potencialmente útiles e intenta ensamblarlos en una carga útil de ataque que genera un shell para aceptar comandos arbitrarios del atacante.
En la aleatorización del diseño del espacio de direcciones
La aleatorización del diseño del espacio de direcciones también tiene vulnerabilidades. Según el artículo de Shacham et al, [12] el ASLR en arquitecturas de 32 bits está limitado por el número de bits disponibles para la aleatorización de direcciones. Solo 16 de los 32 bits de dirección están disponibles para la aleatorización, y 16 bits de la aleatorización de direcciones pueden ser derrotados por un ataque de fuerza bruta en minutos. Para arquitecturas de 64 bits, 40 bits de 64 están disponibles para la aleatorización. En 2016, el ataque de fuerza bruta para la aleatorización de 40 bits es posible, pero es poco probable que pase desapercibido. Además, la aleatorización se puede derrotar mediante técnicas de desaleatorización.
Incluso con una aleatorización perfecta, si hay alguna fuga de información del contenido de la memoria, ayudaría a calcular la dirección base de, por ejemplo, una biblioteca compartida en tiempo de ejecución. [13]
Sin uso de la instrucción de devolución
Según el artículo de Checkoway et al, [14] es posible realizar programación orientada al retorno en arquitecturas x86 y ARM sin utilizar una instrucción de retorno (0xC3 en x86). En su lugar, utilizaron secuencias de instrucciones cuidadosamente diseñadas que ya existen en la memoria de la máquina para comportarse como una instrucción de retorno. Una instrucción de retorno tiene dos efectos: en primer lugar, busca el valor de cuatro bytes en la parte superior de la pila y establece el puntero de la instrucción en ese valor, y en segundo lugar, aumenta el valor del puntero de la pila en cuatro. En la arquitectura x86, las secuencias de instrucciones jmp y pop pueden actuar como una instrucción de retorno. En ARM, las secuencias de instrucciones de carga y bifurcación pueden actuar como una instrucción de retorno.
Dado que este nuevo enfoque no utiliza una instrucción de retorno, tiene implicaciones negativas para la defensa. Cuando un programa de defensa comprueba no solo varios retornos sino también varias instrucciones de salto, este ataque puede detectarse.
Defensas
Libre de G
La técnica G-Free fue desarrollada por Kaan Onarlioglu, Leyla Bilge, Andrea Lanzi, Davide Balzarotti y Engin Kirda. Es una solución práctica contra cualquier forma posible de programación orientada a retornos. La solución elimina todas las instrucciones de rama libre no alineadas (instrucciones como RET o CALL que los atacantes pueden usar para cambiar el flujo de control) dentro de un ejecutable binario y protege las instrucciones de rama libre para que no las utilice un atacante. La forma en que G-Free protege la dirección de retorno es similar al canario XOR implementado por StackGuard. Además, verifica la autenticidad de las llamadas a funciones agregando un bloque de validación. Si no se encuentra el resultado esperado, G-Free hace que la aplicación se bloquee. [15]
Aleatorización del diseño del espacio de direcciones
Se han propuesto varias técnicas para subvertir los ataques basados en la programación orientada al retorno. [16] La mayoría confía en aleatorizar la ubicación del código del programa y la biblioteca, de modo que un atacante no puede predecir con precisión la ubicación de las instrucciones que podrían ser útiles en los dispositivos y, por lo tanto, no puede montar una cadena de ataque de programación orientada al retorno exitosa. Una implementación bastante común de esta técnica, la aleatorización del diseño del espacio de direcciones (ASLR), carga bibliotecas compartidas en una ubicación de memoria diferente en cada carga de programa. Aunque ampliamente implementado por los sistemas operativos modernos, ASLR es vulnerable a los ataques de fuga de información y otros enfoques para determinar la dirección de cualquier función de biblioteca conocida en la memoria. Si un atacante puede determinar con éxito la ubicación de una instrucción conocida, se puede inferir la posición de todas las demás y se puede construir un ataque de programación orientado al retorno.
Este enfoque de aleatorización se puede llevar más allá reubicando todas las instrucciones y / u otro estado del programa (registros y objetos de pila) del programa por separado, en lugar de solo ubicaciones de biblioteca. [17] [18] [19] Esto requiere un amplio soporte en tiempo de ejecución, como un traductor dinámico de software, para reconstruir las instrucciones aleatorias en tiempo de ejecución. Esta técnica tiene éxito en hacer que los dispositivos sean difíciles de encontrar y utilizar, pero conlleva una sobrecarga significativa.
Otro enfoque, adoptado por kBouncer, modifica el sistema operativo para verificar que las instrucciones de retorno realmente desvíen el flujo de control a una ubicación inmediatamente después de una instrucción de llamada. Esto evita el encadenamiento de dispositivos, pero conlleva una fuerte penalización de rendimiento, [ aclaración necesaria ] y no es eficaz contra ataques de programación orientados a saltos que alteran los saltos y otras instrucciones de modificación del flujo de control en lugar de los retornos. [20]
Aleatorización de código binario
Algunos sistemas modernos como Cloud Lambda (FaaS) y las actualizaciones remotas de IoT utilizan la infraestructura de la nube para realizar una compilación sobre la marcha antes de la implementación del software. Una técnica que introduce variaciones en cada instancia de un software en ejecución puede aumentar drásticamente la inmunidad del software a los ataques ROP. La fuerza bruta de Cloud Lambda puede resultar en el ataque de varias instancias del software aleatorizado, lo que reduce la efectividad del ataque. Asaf Shelly publicó la técnica en 2017 [21] y demostró el uso de la aleatorización binaria en un sistema de actualización de software. Para cada dispositivo actualizado, el servicio basado en la nube introdujo variaciones en el código, realiza la compilación en línea y distribuye el binario. Esta técnica es muy eficaz porque los ataques ROP se basan en el conocimiento de la estructura interna del software. El inconveniente de la técnica es que el software nunca se prueba completamente antes de su implementación porque no es factible probar todas las variaciones del software aleatorizado. Esto significa que muchas técnicas de aleatorización binaria son aplicables para interfaces de red y programación de sistemas y son menos recomendadas para algoritmos complejos.
SEHOP
La protección de sobrescritura del controlador de excepciones estructurado es una función de Windows que protege contra los ataques de desbordamiento de pila más comunes, especialmente contra los ataques a un controlador de excepciones estructurado.
Contra los ataques de control de flujo
A medida que proliferan los pequeños sistemas integrados debido a la expansión del Internet de las cosas , también aumenta la necesidad de protección de dichos sistemas integrados. Con el control de acceso a memoria basado en instrucciones (IB-MAC) implementado en el hardware, es posible proteger los sistemas integrados de bajo costo contra el flujo de control malicioso y los ataques de desbordamiento de pila. La protección se puede proporcionar separando la pila de datos y la pila de retorno. Sin embargo, debido a la falta de una unidad de gestión de memoria en algunos sistemas integrados, la solución de hardware no se puede aplicar a todos los sistemas integrados. [22]
Contra rootkits orientados al retorno
En 2010, Jinku Li et al. propuso [23] que un compilador adecuadamente modificado podría eliminar completamente los "gadgets" orientados al retorno reemplazando cada uno con la secuencia de instrucciones y cada uno con la secuencia de instrucciones , donde representa una tabulación inmutable de todas las direcciones de retorno "legítimas" en el programa y representa una índice específico en esa tabla. Esto evita la creación de un gadget orientado al retorno que regresa directamente desde el final de una función a una dirección arbitraria en el medio de otra función; en cambio, los gadgets solo pueden regresar a direcciones de retorno "legítimas", lo que aumenta drásticamente la dificultad de crear gadgets útiles. Li y col. afirmado que "nuestra técnica indirecta de retorno esencialmente de-generaliza vuelven programación orientada de nuevo al viejo estilo de vuelta-en-libc." [23] Su compilador de prueba de concepto incluyó una fase de optimización de mirilla para lidiar con "ciertas instrucciones de máquina que contienen el código de operación de retorno en sus códigos de operación u operandos inmediatos", [23] como .call f
pushl $index
; jmp f
ret
popl %ebx
; jmp table(index)
table
index
movl $0xC3, %eax
Códigos de autenticación de puntero (PAC)
La arquitectura ARMv8.3-A introduce una nueva característica a nivel de hardware que aprovecha los bits no utilizados en el espacio de direcciones del puntero para firmar criptográficamente las direcciones del puntero utilizando un cifrado de bloque modificable especialmente diseñado [24] [25] que firma el valor deseado (normalmente, una dirección de retorno) combinada con un valor de "contexto local" (por ejemplo, el puntero de pila).
Antes de realizar una operación sensible (es decir, volver al puntero guardado), se puede verificar la firma para detectar manipulación o uso en el contexto incorrecto (por ejemplo, aprovechando una dirección de retorno guardada de un contexto de trampolín de explotación).
En particular, los chips Apple A12 utilizados en los iPhones se han actualizado a ARMv8.3 y utilizan PAC. Linux obtuvo soporte para la autenticación de punteros dentro del kernel en la versión 5.7 lanzada en 2020; En 2018 se añadió soporte para aplicaciones de espacio de usuario. [26]
Ver también
- Programación orientada al retorno ciego
- Desbordamiento de enteros
- Pulverización JIT
- Programación orientada a Sigreturn (SROP)
- Código enhebrado: la programación orientada al retorno es un redescubrimiento del código enhebrado
Referencias
- ^ Vázquez, Hugo (1 de octubre de 2007). "Hack de plataforma segura de Check Point" (PDF) . Pentest . Barcelona, España: Pentest Consultores. pag. 219. Resumen de laicos .
- ^ Shajam, Hovav; Buchanan, Erik; Roemer, Ryan; Salvaje, Stefan. "Programación orientada al retorno: exploits sin inyección de código" . Consultado el 12 de agosto de 2009 .
- ^ Buchanan, E .; Roemer, R .; Shacham, H .; Savage, S. (octubre de 2008). "Cuando las buenas instrucciones van mal: generalización de la programación orientada al retorno a RISC" (PDF) . Actas de la 15ª conferencia de la ACM sobre seguridad informática y de las comunicaciones - CCS '08 . págs. 27–38. doi : 10.1145 / 1455770.1455776 . ISBN 978-1-59593-810-7.
- ^ Prevención de ejecución de datos de Microsoft Windows XP SP2
- ^ Diseñador solar, exploits Return-into-lib (c) , Bugtraq
- ^ Nergal, Phrack 58 Artículo 4, exploits return-into-lib (c)
- ^ Sebastian Krahmer, exploits de desbordamiento de búfer x86-64 y técnica de explotación de fragmentos de código prestados , 28 de septiembre de 2005
- ^ Abadi, MN; Budiu, M .; Erlingsson, Ú .; Ligatti, J. (noviembre de 2005). "Integridad de flujo de control: principios, implementaciones y aplicaciones". Actas de la 12ª conferencia de la ACM sobre seguridad informática y de las comunicaciones - CCS '05 . págs. 340–353. doi : 10.1145 / 1102120.1102165 . ISBN 1-59593-226-7.
- ^ Abadi, MN; Budiu, M .; Erlingsson, Ú .; Ligatti, J. (octubre de 2009). "Principios, implementaciones y aplicaciones de integridad del flujo de control". Transacciones ACM sobre seguridad de la información y del sistema . 13 : 1–40. doi : 10.1145 / 1609956.1609960 .
- ^ a b c Shacham, H. (octubre de 2007). "La geometría de la carne inocente en el hueso: volver a libc sin llamadas a funciones (en el x86)". Actas de la 14ª conferencia de la ACM sobre seguridad informática y de las comunicaciones - CCS '07 . págs. 552–561. doi : 10.1145 / 1315245.1315313 . ISBN 978-1-59593-703-2.
- ^ Jonathan Salwan y Allan Wirth, ROPgadget - Buscador de gadgets y auto-roper
- ^ [Shacham et al., 2004] Hovav Shacham, Matthew Page, Ben Pfaff, Eu-Jin Goh, Nagendra Modadugu y Dan Boneh. Sobre la efectividad de la aleatorización del espacio de direcciones. En Actas de la 11a conferencia de ACM sobre seguridad informática y de comunicaciones (CCS), 2004.
- ^ [Bennett et al., 2013] James Bennett, Yichong Lin y Thoufique Haq. El número de la bestia, 2013. https://www.fireeye.com/blog/threat-research/2013/02/the-number-of-the-beast.html
- ^ CHECKOWAY, S., DAVI, L., DMITRIENKO, A., SADEGHI, A.-R., SHACHAM, H. Y WINANDY, M. 2010. Programación orientada al retorno sin retornos. En Proceedings of CCS 2010, A. Keromytis y V. Shmatikov, Eds. ACM Press, 559–72
- ^ ONARLIOGLU, K., BILGE, L., LANZI, A., BALZAROTTI, D., Y KIRDA, E. 2010. G-Free: Derrotando la programación orientada al retorno a través de binarios sin gadget. En Actas de ACSAC 2010, M. Franz y J. McDermott, Eds. ACM Press, 49–58.
- ^ Skowyra, R .; Casteel, K .; Okhravi, H .; Zeldovich, N .; Streilein, W. (octubre de 2013). "Análisis sistemático de las defensas contra la programación orientada al retorno" (PDF) . Investigación en Ataques, Intrusiones y Defensas . Apuntes de conferencias en informática. 8145 . págs. 82-102. doi : 10.1007 / 978-3-642-41284-4_5 . ISBN 978-3-642-41283-7. Archivado desde el original (PDF) el 22 de febrero de 2014.
- ^ Venkat, Ashish; Shamasunder, Sriskanda; Shajam, Hovav; Tullsen, Dean M. (1 de enero de 2016). "HIPStR: Reubicación del estado del programa heterogéneo-ISA". Actas de la vigésimo primera conferencia internacional sobre soporte arquitectónico para lenguajes de programación y sistemas operativos . ASPLOS '16. Nueva York, NY, EE. UU.: ACM: 727–741. doi : 10.1145 / 2872362.2872408 . ISBN 9781450340915.
- ^ Hiser, J .; Nguyen-Tuong, A .; Co, M .; Hall, M .; Davidson, JW (mayo de 2012). "ILR: ¿Dónde fueron mis gadgets?". 2012 Simposio IEEE sobre seguridad y privacidad . págs. 571–585. doi : 10.1109 / SP.2012.39 . ISBN 978-1-4673-1244-8.
- ^ [1] , Venkat, Ashish; Arvind Krishnaswamy & Koichi Yamada, "Reubicación estatal del programa impulsado por traductores binarios"
- ^ Vasilis Pappas. kBouncer: Mitigación de ROP eficiente y transparente . Abril de 2012.
- ^ [2] , "Métodos y sistemas de seguridad por mutación de código", publicado el 4 de mayo de 2017
- ^ FRANCILLON, A., PERITO, D., Y CASTELLUCCIA, C. 2009. Defendiendo sistemas embebidos contra ataques de control de flujo. En Proceedings of SecuCode 2009, S. Lachmund y C. Schaefer, Eds. ACM Press, 19-26.
- ^ a b c Jinku LI, Zhi WANG, Xuxian JIANG, Mike GRACE y Sina BAHRAM. Derrotar a los rootkits orientados al retorno con kernels "sin retorno". En Proceedings of EuroSys 2010 , editado por G. Muller. ACM Press, 195-208.
- ^ Avanzi, Roberto (2016). La familia de cifrado de bloques QARMA (PDF) . Transacciones IACR sobre criptología simétrica (ToSC) . vol. 17 iss. 1 (publicado el 8 de marzo de 2017). págs. 4-44. doi : 10.13154 / tosc.v2017.i1.4-44 . Archivado desde el original (PDF) el 13 de mayo de 2020.
|volume=
tiene texto extra ( ayuda ) - ^ Seguridad del producto Qualcomm. "Autenticación de puntero en ARMv8.3" (PDF) . Qualcomm Technologies Inc. Archivado (PDF) desde el original el 6 de junio de 2020 . Consultado el 16 de junio de 2020 .
Por lo tanto, diseñamos QARMA, una nueva familia de cifrados de bloque ajustables y ligeros.
- ^ "Linux 5.7 para ARM de 64 bits trae autenticación de puntero en el kernel, monitores de actividad - Phoronix" . www.phoronix.com . Consultado el 31 de marzo de 2020 .
enlaces externos
- "Los informáticos toman el control de la máquina de votación electrónica con una nueva técnica de programación" . Ciencia diaria. 11 de agosto de 2009.
- "Video de demostración de ataque de programación orientado al retorno" .
- AntiJOP: un programa que elimina las vulnerabilidades de JOP / ROP del código en lenguaje ensamblador