# Przepełnienie całkowite {{#include ../banners/hacktricks-training.md}} ## Podstawowe informacje W sercu **przepełnienia całkowitego** leży ograniczenie narzucone przez **rozmiar** typów danych w programowaniu komputerowym oraz **interpretację** danych. Na przykład, **8-bitowa liczba całkowita bez znaku** może reprezentować wartości od **0 do 255**. Jeśli spróbujesz przechować wartość 256 w 8-bitowej liczbie całkowitej bez znaku, zostanie ona zawinięta do 0 z powodu ograniczenia pojemności. Podobnie, dla **16-bitowej liczby całkowitej bez znaku**, która może przechowywać wartości od **0 do 65,535**, dodanie 1 do 65,535 spowoduje zawinięcie wartości z powrotem do 0. Ponadto, **8-bitowa liczba całkowita ze znakiem** może reprezentować wartości od **-128 do 127**. Dzieje się tak, ponieważ jeden bit jest używany do reprezentacji znaku (dodatniego lub ujemnego), pozostawiając 7 bitów do reprezentacji wartości bezwzględnej. Najbardziej ujemna liczba jest reprezentowana jako **-128** (binarne `10000000`), a najbardziej dodatnia liczba to **127** (binarne `01111111`). ### Maksymalne wartości Dla potencjalnych **luk w zabezpieczeniach w sieci** bardzo interesujące jest poznanie maksymalnych wspieranych wartości: {{#tabs}} {{#tab name="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 name="C"}} ```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}} ## Przykłady ### Czyste przepełnienie Wydrukowany wynik będzie równy 0, ponieważ przepełniliśmy 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; } ``` ### Signed to Unsigned Conversion Rozważ sytuację, w której podpisana liczba całkowita jest odczytywana z wejścia użytkownika, a następnie używana w kontekście, który traktuje ją jako liczbę całkowitą bez znaku, bez odpowiedniej walidacji: ```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; } ``` W tym przykładzie, jeśli użytkownik wprowadzi liczbę ujemną, zostanie ona zinterpretowana jako duża liczba całkowita bez znaku z powodu sposobu interpretacji wartości binarnych, co może prowadzić do nieoczekiwanego zachowania. ### Inne przykłady - [https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/int_overflow_post/index.html) - Tylko 1B jest używane do przechowywania rozmiaru hasła, więc możliwe jest jego przepełnienie i sprawienie, że myśli, iż ma długość 4, podczas gdy w rzeczywistości ma 260, aby obejść ochronę sprawdzania długości - [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html) - Mając kilka liczb, znajdź za pomocą z3 nową liczbę, która pomnożona przez pierwszą da drugą: ``` (((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/) - Tylko 1B jest używane do przechowywania rozmiaru hasła, więc możliwe jest jego przepełnienie i sprawienie, że myśli, iż ma długość 4, podczas gdy w rzeczywistości ma 260, aby obejść ochronę sprawdzania długości i nadpisać w stosie następną zmienną lokalną oraz obejść obie ochrony ## ARM64 To **nie zmienia się w ARM64**, jak można zobaczyć w [**tym wpisie na blogu**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/). {{#include ../banners/hacktricks-training.md}}