сбой чтения строки формата из стека в c

#c #string #security #format

#c #строка #Безопасность #формат

Вопрос:

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

У меня есть следующий код:

     #include<stdio.h>
    #include<string.h>
    int main(int argc, char** argv){
        char test[1024];
        strcpy(test,argv[1]);
        printf(test);
        //printf(argv[1]); // print without using local variable
    }    
  

Предполагая a.exe это скомпилированный код, следующий ввод возвращает следующую строку.

a.exe "AAAA.x.x.x.x.x"

Мой вывод: AAAA.b8c1fa30.b8c25940.0061de60.41414141.30252e78

Если я раскомментирую следующий printf() , он добавит ту же входную строку

Это то, чего я ожидал. Я вижу AAAA, напечатанный как 41414141, и подтверждаю, что я действительно просматриваю свою строку формата, используя либо локальную переменную, либо непосредственно в качестве аргумента main() .

Однако, если я закомментирую локальную переменную и функцию strcpy() и выведу только аргумент в main() , то я получу следующий вывод.

AAAA.001a13a0.001a4730.00000011.001a13a0.004013c7 // removed both

и если я просто удалю strcpy() и закомментирую оператор print, который использует локальную переменную, я получу этот вывод:

AAAA.00a813a0.00a84730.00000011.000003ff.00000002 // removed strcpy()

Это меня смущает. Почему я не вижу 41414141 для моей строки A и каковы, предположительно, целые числа 0x11 и 0x02?? Почему я никогда не вижу 41414141 в своих выходных данных, если у меня нет локальных переменных?

Я знаю, что я не осведомлен о некоторых аспектах управления стеком, но я чертовски удивлен, если смогу это понять.

Редактировать: удален лишний оператор printf, чтобы успокоить педантиков

Комментарии:

1. Я думаю, что вы не понимаете, как использовать printf . Попробуйте заменить ваши 2 вызова printf на этот: printf("You wrote: %sn", test);

2. Если вы пытаетесь «выловить» то, что находится в стеке, передавая спецификации форматирования printf из пользовательского ввода, ваша территория — неопределенное поведение . Ни один здравомыслящий программист не позволит вам сделать это как пользователю.

3. Это уязвимость формата строки, часто встречающаяся как непреднамеренная ошибка. Этот код является стандартным тарифом для его описания. Мой вопрос касается поведения стека, а не психической устойчивости программиста. 🙂

4. удален printf(«вы ввели:») из кода, чтобы избежать дальнейших комментариев по стилю кода.

5. Вы получаете разные результаты, потому что промежуточные вызовы, которые вы комментируете, оставляют (теперь неиспользуемую часть) стека в другом состоянии, к которому вы обращаетесь «незаконно». Почему это должно быть то же самое?