2015-02-07 2 views
2

Чтобы понять концепцию фрейма стека, я написал небольшую программу для себя. Во-первых, я покажу вам код, немного очерк о нем, а затем я представлю мой вопрос:Локальные переменные в стеке

Таким образом, программа:

int check_pw(char *password){ 
    int valid = 0; 
    char buffer[10]; 

    strcpy(buffer, password); 

    if(strcmp(buffer, "a") == 0){ 
     valid = 1; 
    } 

    return valid; 
} 

int main(int argc, char *argv[]){ 
    if(check_pw(argv[1])){ 
     printf("OK\n"); 
    } 
    else{ 
     printf("Wrong password\n"); 
    } 
} 

Я даю пароль в качестве аргумента командной строки. И если он равен «a», тогда это нормально. Итак, я думаю, это понятно.

Теперь эскиз как кадр стека функции check_pw должна выглядеть следующим образом:

   -------------------------   LOW 
       | buffer    | 
       ------------------------- 
       | valid    | 
       ------------------------- 
       | old EBP   | 
       ------------------------- 
       |  RET    | 
       ------------------------- 
       |  password   | 
       -------------------------  HIGH 

Теперь мой вопрос:

  • Я полагаю, что эскиз является правильным. Итак, тогда первая локальная переменная «valid» должна получить более высокий адрес памяти, чем вторая переменная «buffer», правильно?

  • Но когда я использую GDB как отладчик (я использую Ubuntu Lucid Lynx), установите свои контрольные точки в нужных местах и ​​введите следующее: х/х & действует и х/х & буфер тогда я получаю адрес 0xbffff388 для «valid» и 0xbffff38c для «buffer» Итак, очевидно, что «буфер» имеет более высокий адрес, но почему?

+3

Компилятор может выложить местных жителей в стек стека, но он хочет. –

+1

Возможный дубликат [Порядок размещения локальных переменных в стеке] (http://stackoverflow.com/questions/1102049/order-of-local-variable-allocation-on-the-stack) - похоже, есть другие аналогичные вопросы в соответствующей боковой панели справа –

+0

Может ли это быть также механизм защиты от уязвимости, такой как «переполнение буфера» или что-то в этом роде? Потому что тогда у меня не было бы возможности переполнить «действительную» переменную. – user3097712

ответ

4

В целях защиты от переполнения буфера (например, тот, который может быть эксплуатируемой через STRCPY использования, например), есть такой метод, который заключается в письменной форме заранее определенного значения в конце всех массивов, выделенных на стеке. Когда функция возвращается, значение (обычно называемое канарейкой) проверяется, и программа прерывается, если значение изменено.

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

Вы можете узнать больше об этом на википедии: http://en.wikipedia.org/wiki/Buffer_overflow_protection#A_canary_example

можно отключить, что НКУ. Если вы компилируете ваш код так (скажем, ваша программа имя файла login.c):

gcc -g -fno-stack-protector login.c 

Вы заметите, что переменные больше не переставить.

+0

Канарейка? Как канарейки, которые служили газовой сигнализацией на угольных шахтах? – Quentin

+0

Я подозреваю, что это должно быть происхождение слова, но я не знаю его этимологии: P –

+0

благодарим вас за ответ с трюком «-fno-stack-protector» .... Я не знал, что – user3097712

Смежные вопросы