После защиты StackGuard'ом перед адресом возврата располагается константа 000AFF0Dh (в терминологии StackGuard'а — canary word), целостность которой проверяется перед выходом из функции. Суть в том, что комбинацию символов, слагающие canary word – \x00\x0A\xFF\x0D, очень трудно "воспроизвести" с помощью строковых функций, поскольку в языке Си символ нуля трактуется как "конец строки". Функция gets – одна из тех немногих, что обрабатывает ноль как обыкновенный символ, поскольку в качестве завершителя строки использует символ "возврата каретки".
При работе с ASCIIZ-строками "подделать" canary word невозможно! Адрес возврата можно считать надежно защищенным. Ведь, чтобы "дотянуться" до него, переполняющемуся буферу необходимо пересечь (и затереть) canary word! Разработчики торжествуют, а хакеры рвут себе вены и вешаются. Или… все-таки нет? Начнем с того, что на уникод все эти ограничения не распространяются и canary word подделывается без труда (кстати говоря, плотная версия Stack Guard'а в качестве сторожевого слова использовала 00000000h, что уникодом уже не воспроизводится, но может быть введено с помощью функции gets, которая сегодня практически никем и нигде не используется). К тому же, приложения, обрабатывающие двоичные данные функциями типа memcpy, так же остаются беззащитными.
Локальные переменные и указатель кадра стека вообще никак не защищены и могут быть беспрепятственно атакованы. Если среди этих переменных присутствует хотя бы один указатель на функцию, вызываемую после переполнения, хакер сможет подменить его адрес, передавая управление на свой shell-код. Конструкция типа "int *x; int a; … x = a;", которая к числу экзотических никак не относится, позволяет атакующему модифицировать любые указатели на функции, в том числе и адрес возврата (правда, в этом случае необходимо знать точное положение вершины стека на момент атаки, что не всегда возможно, поэтому хакеры предпочитают модифицировать таблицу импорта в Windows, а в UNIX – секцию got).