Overflow di Interi

Reading time: 4 minutes

tip

Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks

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:

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);
}

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

(((argv[1] * 0x1064deadbeef4601) & 0xffffffffffffffff) == 0xD1038D2E07B42569)

ARM64

Questo non cambia in ARM64 come puoi vedere in questo post del blog.

tip

Impara e pratica l'Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica l'Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)

Supporta HackTricks