hacktricks/binary-exploitation/integer-overflow.md

7.4 KiB

Estouro de Inteiro

Aprenda hacking na AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks:

Informações Básicas

No cerne de um estouro de inteiro está a limitação imposta pelo tamanho dos tipos de dados na programação de computadores e a interpretação dos dados.

Por exemplo, um inteiro sem sinal de 8 bits pode representar valores de 0 a 255. Se você tentar armazenar o valor 256 em um inteiro sem sinal de 8 bits, ele volta a 0 devido à limitação de sua capacidade de armazenamento. Da mesma forma, para um inteiro sem sinal de 16 bits, que pode conter valores de 0 a 65.535, adicionar 1 a 65.535 fará com que o valor volte a 0.

Além disso, um inteiro com sinal de 8 bits pode representar valores de -128 a 127. Isso ocorre porque um bit é usado para representar o sinal (positivo ou negativo), deixando 7 bits para representar a magnitude. O número mais negativo é representado como -128 (binário 10000000), e o número mais positivo é 127 (binário 01111111).

Valores Máximos

Para potenciais vulnerabilidades web, é muito interessante saber os valores máximos suportados:

{% 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

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 and security vulnerabilities in software.

Example

#include <stdio.h>

int main() {
    unsigned int x = 4294967295; // Maximum value for an unsigned int
    x = x + 1;
    
    printf("Value of x: %u\n", x);

    return 0;
}

In this example, x is an unsigned integer with a maximum value of 4294967295. When 1 is added to x, it overflows and the value becomes 0 due to the limited size of the data type.

Mitigation

To prevent integer overflow, always check the result of arithmetic operations to ensure that the value does not exceed the maximum limit of the data type. Using larger data types or libraries that handle overflow conditions can also help mitigate this issue. {% 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;
}

Exemplos

Overflow puro

O resultado impresso será 0, pois ocorreu um overflow no char:

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

Conversão de Assinado para Não Assinado

Considere uma situação em que um inteiro assinado é lido a partir da entrada do usuário e depois usado em um contexto que o trata como um inteiro não assinado, sem uma validação adequada:

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

Neste exemplo, se um usuário inserir um número negativo, ele será interpretado como um grande inteiro não assinado devido à forma como os valores binários são interpretados, potencialmente levando a comportamentos inesperados.

Outros Exemplos

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

ARM64

Isso não muda no ARM64 como você pode ver neste post de blog.

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Outras maneiras de apoiar o HackTricks: