Прежде чем начать читать этот блог, пожалуйста, прочитайте или, если вы уже знаете об этой теме, вы можете пропустить.

Снова рассмотрим фрагмент кода из предыдущего блога.

void vulnerable_function(int x) {
    int z;
    char str[8];
    z=x+4;
    scanf("%s", str);
    if(z == 10){
        do_something(str);
    }else{ 
        never_to_be_called();
    }
}
void main(){
    ...
    vulnerable_function(6); 
    ... 
}

и кадр стека

            $sp --> 0066    z              [local variable]         
                    0058    str            [local variable]
		    0054    x              [function parameter]
		    0050    0x0004         [return address]
	    $bp --> 0050    0xabcd         [$bp of older frame]

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

Что делать, если нет локальной переменной для перезаписи или эта переменная хранится перед строкой. Как мы можем вызвать переполнение буфера. Ответ прост, да, так как в стеке всегда есть адрес возврата, который может быть перезаписан каким-то конкретным значением, скажем, xyz. После выполнения функции или возникновения ошибки сегментации адрес возврата будет прочитан, и выполнение вернется к xyz.

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

Двоичные коды для шелл-кодов можно скачать здесь.