Почему следующий код подвержен атаке переполнения кучи - PullRequest
1 голос
/ 16 апреля 2019

Я новичок в кибербезопасности и пытаюсь понять, почему следующий код подвержен атаке переполнения кучи ...

struct data {
 char name[128];
};
struct fp {
 int (*fp)();
};
void printName() {
 printf("Printing function...\n");
}
int main(int argc, char **argv) {
 struct data *d;
 struct fp *f;
 d = malloc(sizeof(struct data));
 f = malloc(sizeof(struct fp));
 f->fp = printName;
 read(stdin,d->name,256);

 f->fp();
}

Это из-за read(stdin, d->name, 256) какчитает больше, чем выделенный размер буфера 128 для char name в struct data?

Любая помощь будет отличной

1 Ответ

1 голос
/ 16 апреля 2019

A атака переполнения кучи аналогична атака переполнения буфера , за исключением того, что вместо перезаписи значений в стеке злоумышленник вытесняет данные в куче.

Обратите внимание, что в вашем коде есть два динамически распределяемых значения:

d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));

Итак, d теперь содержит адрес 128-байтового куска памяти в куче, а f содержит адрес8-байтовый (при условии 64-битной машины) кусок памяти.Теоретически, эти два адреса могут быть далеко друг от друга, но, поскольку они оба относительно малы, вполне вероятно, что ОС выделяет один большой кусок непрерывной памяти и дает вам указатели, которые находятся рядом друг с другом.

Поэтому после запуска f->fp = printName; ваша куча выглядит примерно так:

Примечание. Каждая строка имеет ширину 8 байт

     |                        |
     +------------------------+
f -> | <Address of printName> |
     +------------------------+
     |           ▲            |
     |      11 more rows      |
     |       not shown        |
     |                        |
d -> |  <Uninitialized data>  |
     +------------------------+
     |                        |

Ваша первоначальная оценка того, гдеуязвимость исходит от правильно.d указывает на 128 байтов памяти, но вы позволяете пользователю записать 256 байтов в эту область.В C нет механизма проверки границ, поэтому компилятор с радостью разрешает вам писать за границу памяти d.Если f находится рядом с d, вы упадете за край d и в f.Теперь злоумышленник может изменить содержимое f, просто записав в d.

Чтобы воспользоваться этой уязвимостью, злоумышленник передает адрес некоторого кода, который был написан для * 1032.* повторяя это для всех 256 байтов ввода.Если злоумышленник сохранил некоторый вредоносный код по адресу 0xbadc0de, он подает 0xbadc0de в стандартный ввод 32 раза (256 байт), так что куча перезаписывается.

     |  0xbadc0de  |
     +-------------+
f -> |  0xbadc0de  |
     +-------------+
     |     ...     |
     |  0xbadc0de  |
     |  0xbadc0de  |
d -> |  0xbadc0de  |
     +-------------+
     |             |

Затем ваш код достигаетстрока

f->fp();

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

...