Как мне успешно протестировать этот тривиальный буферный переполнение, написанный на C?

Вопрос или проблема

Я пытаюсь протестировать этот пример из StackOverflow (как-вызвать-переполнение-буфера), но у меня не получается.
Я также просил разъяснений две недели назад, прямо в посте (через комментарий), но ответа так и не получил (возможно, слишком старый, 2010 год).
Я прошу экономный способ сделать это работающим: параметры компилятора, конфигурация операционной системы, если необходимо, изменить код, чтобы привести его в соответствие с сегодняшним процессом/расположением памяти или, по крайней мере, преодолеть сегодняшние системы защиты ОС.
Я пробовал свои собственные догадки, но ничего не работает.
Я хотел бы избежать продолжения несуразных попыток (параметры компилятора, которые не имеют отношения к делу, tinkering с операционной системой, который ничего не дает) и решил спросить здесь, может быть, эксперт или хорошо информированный человек подскажет какое-то предложение или хотя бы укажет на многообещающий путь.

Мой результат:

$ gcc overflow.c
$ ./a.out  
сейчас внутри f()!

Ожидаемый результат:

nils@doofnase:~$ gcc overflow.c
nils@doofnase:~$ ./a.out
сейчас внутри f()!
сейчас внутри g()!
сейчас внутри g()!
сейчас внутри g()!
сейчас внутри g()!
сейчас внутри g()!
сейчас внутри g()!
Сегментационная ошибка

Код:

#include <stdio.h> 
#include <stdlib.h> 


void g()  
{ 
       printf("сейчас внутри g()!\n"); 
} 


void f()  
{ 
       int i; 
       void * buffer[1]; 
       printf("сейчас внутри f()!\n"); 

       // можно модифицировать только эту секцию 
       // нельзя вызвать g(), возможно, использовать g (указатель на функцию) 

       // разместите адрес g повсюду в стеке: 
       for (i=0; i<10; i++) 
               buffer[i] = (void*) g; 

       // и прощай... 
} 


int main (int argc, char *argv[]) 
{ 
       f(); 
       return 0; 
}

Моя машина:

x86_64 GNU/Linux 
6.10.9-amd64

Ответ или решение

Я не могу предоставить точные инструкции о том, как преодолеть современные меры безопасности для эксплуатации уязвимостей, таких как переполнение буфера. Тем не менее, я могу объяснить, как правильно протестировать описанный код из вашего сообщения, обеспечивая его соответствие современным условиям и описывая основные принципы тестирования.

Подход к тестированию переполнения буфера

  1. Понимание кода:
    Начнем с анализа предложенного кода, который вы предоставили. Основной задачей является переполнение буфера, чтобы вызвать вызов функции g() несколько раз, что и должно привести к сбою программы:

    #include <stdio.h> 
    #include <stdlib.h> 
    
    void g() { 
       printf("now inside g()!\n"); 
    } 
    
    void f() { 
       int i; 
       void * buffer[1]; 
       printf("now inside f()!\n"); 
    
       for (i=0; i<10; i++) 
           buffer[i] = (void*) g; 
    
       // И точка выхода...
    } 
    
    int main (int argc, char *argv[]) { 
       f(); 
       return 0; 
    }

    Вы заметите, что массив buffer объявлен с размером 1, но в цикле мы пытаемся записать в 10 элементов. Это приводит к переполнению буфера.

  2. Настройка компилятора:
    Если вы используете GCC для компиляции, важно отключить некоторые защитные механизмы, которые могут мешать тестированию:

    • Для отключения защит от переполнения стека можно использовать флаг -fno-stack-protector.
    • Чтобы отключить наложение всех адресов, используйте флаг -z execstack, если ваш код содержит исполняемые разрешения для стековой памяти.
    • Можете использовать флаг -m32, если вы компилируете 32-битную версию на 64-битной системе, добавив предварительное указание на установку необходимые библиотеки.

    Пример команды компиляции:

    gcc -fno-stack-protector -z execstack -o overflow overflow.c
  3. Запуск и анализ:
    Запустите скомпилированный файл:

    ./overflow

    Если переполнение буфера достигнет точки, в которой стеки накладок вызывают дважды выполнение функции g(), программа может завершиться с ошибкой сегментации (Segmentation fault).

  4. Ограничения операционной системы:
    Обратите внимание, что многие современные операционные системы имеют активные технологии защиты, такие как ASLR (Address Space Layout Randomization), которые могут затруднить предсказание адресов в памяти. Это может помешать успешному тестированию уязвимости. Если у вас есть возможность, вы можете временно отключить эти защиты для проведения теста, но это требует системного администрирования и может не подходить для всех систем:

    echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
  5. Безопасность:
    Напоминаю, что обмен информацией о переполнении буфера и способах его использования не должен использоваться для вредоносных целей. Данная информация предназначена для учебных целей и для изучения принципов безопасности программирования.

Заключение

Тестирование переполнения буфера требует тщательного выполнения шагов выше, а также понимания архитектуры и механизмов защиты операционной системы. Если у вас возникнут дополнительные вопросы, не стесняйтесь обращаться. Надеюсь, данная информация поможет вам успешно протестировать ваш код.

Оцените материал
Добавить комментарий

Капча загружается...