Исследователь и разработчик по жизни

Overflow

В этой небольшой статье Андрей Соколов расскажет об одной достаточно распространенной уязвимости называемой переполнением буфера. Будет написана небольшая программа, в которой будет присутствовать уязвимость. Все эксперименты проводяться в OS Solaris.

Вот программа, демонстрирующая хак через переполнение буфера.

#include <stdio.h> 

#include <stdlib.h> void funcException(){

    printf("Overflow!!!!\n");

    exit(0);

}

int funcRead(){

    int buf[10];

    int i = 0;

    for(;;)

        if(!fread(&buf[i++],sizeof(buf[i++]),1,stdin))

            break;

    return 0;

}

int main(int argc, char** argv) {

    if(funcRead())

       funcException();

    else

       printf("No overflow\n");

    return (EXIT_SUCCESS);

}

Если анализировать код, то можно сделать вывод, что управление на функцию funcException никогда не должно быть передано: funcRead всегда возвращает 0, а конструкция if в функции main в этом случае передает управление по ветке else. Однако первое впечатление обманчиво. Обратим внимание на то, что в функции funcRead при чтении данных в массив buf не выполняется проверка на переполнение массива. Значит запись может быть выполнена за границы данного массива.

Данная программа была написана в Sun Studio 12 и скомпилирована в отладочном варианте со всеми параметрами по умолчанию. Стек внутри funcRead выглядит так:

i
buf[0]
buf[1]
.....
buf[9]
возвращаемое значение
ebp
адрес возврата

Для ознакомления со структурой стека рекомендую поглядеть ассемблерный листинг, формируемый по исходнику командой: cc -S <исходник>.

Таким образом, если в buf[12] будет записан адрес функции funcException, то управление будет передано на нее. Значит надо подать на стандартный ввод программы файл, в котором 13-ое двойное слово содержит этот адрес.

Чтобы узнать адрес используем отладчик mdb:

mdb <имя исполняемого файла>

выполняем в отладчике команду просмотра соответствия символьных имен адресам (::nm). Вот часть ее вывода:

> ::nm
Value Size Type Bind Other Shndx Name
0x00000000|0x00000000|NOTY |LOCL |0x0 |UNDEF |
0x0805095c|0x00000000|FUNC |GLOB |0x0 |UNDEF |printf
0x08050990|0x0000008e|FUNC |GLOB |0x0 |12 |_start
0x0805094c|0x00000000|FUNC |GLOB |0x0 |UNDEF |_exit
0x08050aa0|0x00000022|FUNC |GLOB |0x0 |12 |funcException
0x08060bf0|0x00000000|OBJT |GLOB |0x0 |18 |_DYNAMIC
0x00000000|0x00000000|NOTY |WEAK |0x0 |UNDEF |__1cG__CrunMdo_exit_code6F_v_
0x08050bc5|0x00000000|OBJT |GLOB |0x0 |16 |_etext

Итак, 13-ое двойное слово должно содержать значение 0x08050aa0.

Создаем файл из 52 байт, а потом при помощи двоичного редактора ghex2 заменяем последние 4 байта, не забывая про то, что младший байт располагается по младшему адресу. Этот файл, будучи поданным на стандартный ввод обеспечит вывод на консоль сообщения "Overflow!"

Ваши замечания и предложения можно оставлять тут.

Андрей Соколов (keremet[собачка]bk.ru)

 

Коротко о сайте

В жизни очень много всего интересного. И думаю у каждого человека есть огромне стремление все познать. Этот сайт о моей жизни, о моих разработках и просто об интересных событиях.