Нет, вы поняли неправильно. Во-первых, эксплуатация переполнения буфера зависит от того, где расположен буфер. Скорей всего вы имеете ввиду переполнение стекового буфера aka stack overrun.
При "классической" прямой эксплуатации переполнения буфера в стеке "по aleph1" в буфере размещается шел-код, затем сохраненный в стеке адрес возврата перезаписывается адресом, указывающим внутрь буфера (на шелкод), при возврате из функции выполняется шелкод.
Однако, такие приемы работали до того, как появились технологии защиты стека, неисполняемой памяти и рандомизации размещения в адресном пространстве. Сейчас для эксплуатации переполнений стека на практике обычно требуются приемы ROP (return oriented programming), т.е. ваши знания очень сильно устарели.
Написать программу и вставить ее код в чистом виде нереально даже в случае классической эксплуатации, т.к. шел-код должен быть привязан к определенному состоянию адресного пространства эксплуатируемого приложения, и попадает в адресное пространство минуя стандартные механизмы загрузки и динамической линковки. Обычно шел-код пишется на ассемблере, либо под определенные фиксированные адреса, либо так, чтобы не иметь привязки к адресному пространству или с учетом необходимых дополнительных операций (например получения адресов вызываемых функций) для привязки к адресному пространству.
ROP представляет из себя в принципе иной подход к программированию, для разработки шел-кода предварительно необходимо собрать доступные фрагменты кода ("гаджеты"), возможность написания шел-кода зависит от собранных гаджетов и фактически требует трансляции кода в последовательность вызова гаджетов, обычные подходы к разработке кода здесь неприменимы (по крайней мере до того момента, как получен полный контроль над страницами памяти процесса).