mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
116 lines
4.4 KiB
Markdown
116 lines
4.4 KiB
Markdown
# Overflow di Interi
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|
|
|
|
## Informazioni di Base
|
|
|
|
Al centro di un **overflow di interi** c'è la limitazione imposta dalla **dimensione** dei tipi di dati nella programmazione informatica e dall'**interpretazione** dei dati.
|
|
|
|
Ad esempio, un **intero senza segno a 8 bit** può rappresentare valori da **0 a 255**. Se si tenta di memorizzare il valore 256 in un intero senza segno a 8 bit, esso torna a 0 a causa della limitazione della sua capacità di memorizzazione. Allo stesso modo, per un **intero senza segno a 16 bit**, che può contenere valori da **0 a 65.535**, aggiungere 1 a 65.535 riporterà il valore a 0.
|
|
|
|
Inoltre, un **intero con segno a 8 bit** può rappresentare valori da **-128 a 127**. Questo perché un bit è utilizzato per rappresentare il segno (positivo o negativo), lasciando 7 bit per rappresentare la grandezza. Il numero più negativo è rappresentato come **-128** (binario `10000000`), e il numero più positivo è **127** (binario `01111111`).
|
|
|
|
### Valori massimi
|
|
|
|
Per le potenziali **vulnerabilità web** è molto interessante conoscere i valori massimi supportati:
|
|
|
|
{{#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 <stdio.h>
|
|
#include <limits.h>
|
|
|
|
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}}
|
|
|
|
## Esempi
|
|
|
|
### Overflow puro
|
|
|
|
Il risultato stampato sarà 0 poiché abbiamo sovraccaricato il char:
|
|
```c
|
|
#include <stdio.h>
|
|
|
|
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;
|
|
}
|
|
```
|
|
### Conversione da Firmato a Non Firmato
|
|
|
|
Considera una situazione in cui un intero firmato viene letto dall'input dell'utente e poi utilizzato in un contesto che lo tratta come un intero non firmato, senza una corretta validazione:
|
|
```c
|
|
#include <stdio.h>
|
|
|
|
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;
|
|
}
|
|
```
|
|
In questo esempio, se un utente inserisce un numero negativo, verrà interpretato come un grande intero senza segno a causa del modo in cui i valori binari vengono interpretati, portando potenzialmente a comportamenti imprevisti.
|
|
|
|
### Altri Esempi
|
|
|
|
- [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 1B è utilizzato per memorizzare la dimensione della password, quindi è possibile sovraccaricarlo e farlo pensare che la sua lunghezza sia 4 mentre in realtà è 260 per bypassare la protezione del controllo della lunghezza
|
|
- [https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html](https://guyinatuxedo.github.io/35-integer_exploitation/puzzle/index.html)
|
|
|
|
- Dati un paio di numeri, scopri usando z3 un nuovo numero che moltiplicato per il primo darà il secondo:
|
|
|
|
```
|
|
(((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 1B è utilizzato per memorizzare la dimensione della password, quindi è possibile sovraccaricarlo e farlo pensare che la sua lunghezza sia 4 mentre in realtà è 260 per bypassare la protezione del controllo della lunghezza e sovrascrivere nello stack la successiva variabile locale e bypassare entrambe le protezioni
|
|
|
|
## ARM64
|
|
|
|
Questo **non cambia in ARM64** come puoi vedere in [**questo post del blog**](https://8ksec.io/arm64-reversing-and-exploitation-part-8-exploiting-an-integer-overflow-vulnerability/).
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|