# Desbordamiento de enteros {% hint style="success" %} Aprende y practica Hacking en AWS:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\ Aprende y practica Hacking en GCP: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Apoya a HackTricks * ¡Consulta los [**planes de suscripción**](https://github.com/sponsors/carlospolop)! * **Ú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)**.** * **Comparte trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
{% endhint %} ## Información Básica En el corazón de un **desbordamiento de enteros** se encuentra la limitación impuesta por el **tamaño** de los tipos de datos en la programación informática y la **interpretación** de los datos. 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 de vuelta 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**, sumar 1 a 65,535 envolverá el valor de vuelta a 0. 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`). ### Valores máximos Para posibles **vulnerabilidades web** es muy interesante conocer los valores máximos admitidos: {% tabs %} {% tab title="Rust" %} ```rust fn main() { let mut quantity = 2147483647; let (mul_result, _) = i32::overflowing_mul(32767, quantity); let (add_result, _) = i32::overflowing_add(1, quantity); println!("{}", mul_result); println!("{}", add_result); } ``` {% endtab %} {% tab title="C" %} ### Desbordamiento de enteros El desbordamiento de enteros ocurre cuando se intenta almacenar un valor en una variable que es demasiado grande para ser representado en el tipo de dato específico. Esto puede llevar a resultados inesperados, como valores negativos inesperados o incluso vulnerabilidades de seguridad si no se maneja adecuadamente. Es importante tener cuidado al realizar operaciones aritméticas con variables que podrían resultar en desbordamientos de enteros. {% endtab %} ```c #include #include int main() { int a = INT_MAX; int b = 0; int c = 0; b = a * 100; c = a + 1; printf("%d\n", INT_MAX); printf("%d\n", b); printf("%d\n", c); return 0; } ``` {% endtab %} {% endtabs %} ## Ejemplos ### Desbordamiento puro El resultado impreso será 0 ya que hemos desbordado el char: ```c #include int main() { unsigned char max = 255; // 8-bit unsigned integer unsigned char result = max + 1; printf("Result: %d\n", result); // Expected to overflow return 0; } ``` ### Conversión de Firmado a No firmado Considere una situación en la que se lee un entero firmado desde la entrada del usuario y luego se utiliza en un contexto que lo trata como un entero no firmado, sin una validación adecuada: ```c #include int main() { int userInput; // Signed integer printf("Enter a number: "); scanf("%d", &userInput); // Treating the signed input as unsigned without validation unsigned int processedInput = (unsigned int)userInput; // A condition that might not work as intended if userInput is negative if (processedInput > 1000) { printf("Processed Input is large: %u\n", processedInput); } else { printf("Processed Input is within range: %u\n", processedInput); } return 0; } ``` En este ejemplo, si un usuario ingresa un número negativo, será interpretado como un entero sin signo grande debido a la forma en que se interpretan los valores binarios, lo que potencialmente puede llevar a un comportamiento inesperado. ### Otros Ejemplos * [https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html](https://guyinatuxedo.github.io/35-integer\_exploitation/int\_overflow\_post/index.html) * 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 cuando en realidad es de 260 para evadir 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) * Dados un par de números, descubre usando z3 un nuevo número que, multiplicado por el primero, dará el segundo: ``` (((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/) * 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 cuando en realidad es de 260 para evadir la protección de verificación de longitud y sobrescribir en la pila la siguiente variable local y evadir ambas protecciones ## ARM64 Esto **no cambia en ARM64** como se puede ver en [**esta publicación de blog**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).