2015-02-26 2 views
0
void display(const char *path) 
{ 
    char msg[128]; 
    int8_t size; 
    memset(msg, 0, 128); 

    FILE *file = fopen(path, "r"); 
    size_t n = fread(&size, 1, 1, file); 
    if (n == 0 || size > 128) 
    return; 
    n = fread(msg, 1, size, file); 

    puts(msg); 
} 


int main(int argc, char *argv[]) 
{ 
    if (argc != 2) 
    return 1; 

    display(argv[1]); 
    return 0; 
} 

Как я могу сделать это переполнение буфера? Я имею в виду, что буфер составляет 128 байтов. Но не проверяет ли код, превышает ли размер 128? Если это так, то он просто вернется раньше, а если нет, он будет копировать менее 128 байт из файла в msg?Как я могу сделать это переполнение буфера?

ответ

0

int8_t size; - 8-разрядное знаковое значение, поэтому оно попадает в диапазон [-128,127].

Когда этот код выполняется:

size_t n = fread(&size, 1, 1, file); 
    if (n == 0 || size > 128) 
    return; 

Если размер имеет наиболее значимый бит множество (то есть размер> = 0x80), то он обрабатывается имеет отрицательное число, таким образом, избежать/избегая чек ,

Скажем, код считывает размер со значением 0x8F (это 143 в десятичной форме), но поскольку тип int8_t имеет размер 8 бит и диапазон значений [-128,127], устанавливается самый старший бит и указывает знаковое значение, что означает, что значение равно -113.

Таким образом, size составляет менее 128 в (n == 0 || size > 128) просто потому, что -113 > 128 является ложным.

Это означает, что код будет читать больше байтов, чем размер массива. Он будет читать 143 байта, но размер массива составляет всего 128, что вызывает переполнение буфера на основе стека.

Смежные вопросы