hacktricks/binary-exploitation/integer-overflow.md

5.6 KiB

Prekoracenje celih brojeva

{% hint style="success" %} Naucite i vežbajte hakovanje AWS-a:HackTricks Training AWS Red Team Expert (ARTE)
Naucite i vežbajte hakovanje GCP-a: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks
{% endhint %}

Osnovne informacije

U srcu prekoracenja celih brojeva je ogranicenje koje namecu velicine podataka u programiranju i interpretacija podataka.

Na primer, 8-bitni neoznaceni ceo broj može predstavljati vrednosti od 0 do 255. Ako pokusate da sacuvate vrednost 256 u 8-bitnom neoznacenom celom broju, ona se obavija nazad na 0 zbog ogranicenja njegove kapaciteta za cuvanje. Na isti nacin, za 16-bitni neoznaceni ceo broj, koji može držati vrednosti od 0 do 65,535, dodavanje 1 na 65,535 ce obaviti vrednost nazad na 0.

Pored toga, 8-bitni označeni ceo broj može predstavljati vrednosti od -128 do 127. To je zato što se jedan bit koristi za predstavljanje znaka (pozitivan ili negativan), ostavljajuci 7 bitova za predstavljanje velicine. Najnegativniji broj je predstavljen kao -128 (binarno 10000000), a najpozitivniji broj je 127 (binarno 01111111).

Maksimalne vrednosti

Za potencijalne web ranjivosti veoma je zanimljivo znati maksimalne podržane vrednosti:

{% tabs %} {% tab title="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" %} Integer overflow occurs when an arithmetic operation results in a value that exceeds the maximum size that the data type can hold. This can lead to unexpected behavior in the program, such as wrapping around to a minimum value or causing a buffer overflow. Integer overflow can be exploited by an attacker to manipulate the program's behavior and potentially execute malicious code. {% endtab %}

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

Primeri

Čisti prekoračaj

Odštampani rezultat će biti 0 jer smo prekoračili karakter:

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

Konverzija potpisanog u nepotpisani broj

Razmotrite situaciju u kojoj se potpisani ceo broj čita iz korisničkog unosa, a zatim koristi u kontekstu koji ga tretira kao nepotpisani broj, bez odgovarajuće validacije:

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

U ovom primeru, ako korisnik unese negativan broj, biće tumačen kao veliki neoznačeni broj zbog načina tumačenja binarnih vrednosti, što potencijalno može dovesti do neočekivanog ponašanja.

Ostali Primeri

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

ARM64

Ovo se ne menja u ARM64 kao što možete videti u ovom blog postu.