Типичным вектором атаки для программного обеспечения, написанного на C ++, является перезапись индикатора V-таблицы. Когда объекты C ++ размещаются в куче, например, когда используется ключевое слово «new», они часто помещаются рядом с другими объектами также в куче. Если существует неограниченная запись в один из объектов в куче перед объектом с использованием таблиц V, этот тип атаки возможен.
Windows имеет ограничения в управлении стеками в пространстве пользователя, что может затруднить угадывание, какие объекты будут находиться рядом друг с другом в куче. Это означает, что даже если злоумышленник знает, что объект находится в куче без ограничений, злоумышленник не будет знать, какой объект находится непосредственно в куче, что значительно затрудняет надежное использование.
В следующем примере кода используются виртуальные функции, которые предлагают использовать таблицу V во время компиляции с использованием компилятора Microsoft Visual C ++:
/ *
Следующие определения классов были изменены из пояснительной статьи в таблице виртуальных функций Википедии.
* /
#include
usingnamespace std;
classB1 // базовый класс
{
общественности:
виртуальная пустота f0 () {}
виртуальная пустота f1 () {}
};
classB2 // базовый класс
{
общественности:
виртуальная пустота f2 () {}
виртуальная пустота f3 () {}
};
classD: public B1, public B2 {// производный класс наследует оба базовых класса
общественности:
void d () {}
void f0 () {} // переопределить B1 :: f0 ()
void f1 () {} // переопределение B1 :: f1 ()
void f2 () {} // переопределить B2 :: f2 ()
void f3 () {} // переопределяет B2 :: f3 ()
};
intmain (int argc, char * argv [])
{
B2 * b2 = новый B2 ();
D * d = новый D ();
d-> f0 (); // поиск в таблице
d-> f1 (); // поиск в таблице
d-> f2 (); // поиск в таблице
d-> f3 (); // поиск в таблице
}
Общая формула во всех этих поисках виртуальных функций выглядит следующим образом:
- Разыменование указателя объекта, содержащего таблицу V.
- Отличите соответствующий индикатор V-таблицы в объекте от шага 1.
- Отличите соответствующий функциональный индикатор в Таблице V от шага 2.
- Вызовите функцию, найденную в шаге 3.
В Windbg мы можем проверить, действительно ли d назначен в куче, потому что наши локальные переменные:
0: 000> DV
argc = 0n1
argv = 0x00574660
d = 0x00574720
b2 = 0x005746e0
Больше информации о том, где находится наш объект:
0: 000>! Куча -p -a 0x00574720
адрес 00574720 найден в
_HEAP @ 570000
HEAP_ENTRY Размер Предыдущий Флаг UserPize UserSize — статус
005746f8 0009 0000 [00] 00574700 0002c — (занят)
Весь приведенный выше код был скомпилирован с использованием компилятора Microsoft Visual Studio 2010 C ++. Это компилятор по умолчанию, который можно загрузить с помощью интегрированной среды разработки Visual Studio. Другие компиляторы, такие как gcc в Linux, имеют схожие структуры памяти объектов.