2013-09-10 4 views
1

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

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 

int chk_perm(){ 
     printf("\n Check Perm \n"); 
     return 2; 
} 
int main(int argc,char* argv[]){ 
     int fg; 
     char filename[16]; 

     if(argc != 2){ 
       fprintf(stderr,"Usage : %s filename\n",argv[0]); 
       exit(1); 
     } 

     fg = chk_perm(); 
     strcpy(filename,argv[1]); 
     if(fg == 0xdeadbeef){ 
       //execute as root or deposit million dollars in bank account 
     } 
     else{ 
       //execute as a normal user , deduct $10 from an account 
     } 

     return 0; 
} 

ARGV [1] прошло, может изменить значение фг. Сказано, что коррупция произойдет, если argv [1] передал целый двоичный код, который может вызвать нежелательные результаты, может быть передан как аргумент вместе с обратным адресом.

Я не мог понять, как strcpy повреждает стек check_perm таким образом, что значение fg изменяется.

Мое предположение о программе,

Когда программа начинает работу, он создает стек для основной функции и положить свои аргументы, обратный адрес, локальные переменные на Int фг stack.So будет занимать 4 байта (08567500 loc) стека и имени файла [16] будут занимать следующие 16 байт (08567504). Даже если имя файла переполнено более чем 16 байтами, оно может испортиться, если после него появилась какая-либо локальная переменная.

Так как fg получает повреждение из-за strcpy (имя файла, argv [1]);

ответ

3

Если на вашей архитектуре стек растет вниз (как это обычно бывает), fg будет занимать память сразу после filename. Это означает, что когда вы пишете минус filename, вы разбиваете fg.

+0

Это единственный ответ, который правильно учитывает направление роста стекол, а также –

+0

@NPE: Спасибо. Я проверил адрес fg и имя файла. fg помещается под именем файла. Но у меня есть сомнения. когда стек загружается, параметры, адрес возврата, локальные переменные сохраняются в стек в порядке. Поэтому локальные переменные fg должны получить наивысший адрес, чем имя файла. И имя файла массива растет от более низкого к более высокому sddress. Почему имя файла имеет самый высокий адрес, чем fg. – Angus

+0

@Angus: Возможно, тот, кто написал пример, говорил о системе с нисходящим стеком, но система, на которую вы протестировали, использует верхний стек. – aschepler

2

fg находится на стеке. Точно так же filename. Когда вы strcpy() что-то до filename, которое больше 16, оно перезапишет fg.

1

Как уже указывалось, вы пишете буфер filename. Когда вы это сделаете, следующий элемент в строке в стеке - это переменная fg, поэтому она получит байты, записанные в нее, если имя входного файла имеет длину более 15 символов (а затем включен еще один байт: нулевой терминатор).

Вам необходимо либо сделать filename достаточно большим, чтобы держать все, что пользователь мог бы дать вам за argv[1], или предотвратить копирование слишком большого количества байтов. Но лучше выделить место, вы должны в этом случае:

char filename[PATH_MAX+1]; 

Если вы хотите сделать это динамически:

char *filename; 

if (!(filename = malloc(strlen(argv[1]) + 1)))) { 
    ... (failure leg) 
} 

Ограничение длины имени файла 16 байт (фактически 15 плюс нулевой терминатор) крайне непрактично для пользователя, тем более, что они могут предоставить полное имя пути для параметра файла. Использование такой функции, как strncpy, приводит к усечению имени файла пользователя и генерированию ошибки открытия файла или, что еще хуже, к открытию неправильного файла.

+0

strncpy() - плохой совет. Очень плохой совет. – joop

+0

@joop да, я согласен. Я бы даже не использовал этот метод сам. Я только показал это на практике, поскольку другие предложили его и хотели сделать его более «видимым». Я удалил его. – lurker

+0

Почему strncpy() плохой совет? –

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