@ CassieJade вам нужно посмотреть документацию по этим функциям онлайн.
printf, snpritf
довольно общие функции. И, кстати, эта платформа не для школьных заданий. Добро пожаловать, если вы что-то пробовали и хотите оттуда следовать.
- http://www.cplusplus.com/reference/cstdio/printf/
- http://www.cplusplus.com/reference/cstdio/snprintf/
Следующее прекрасно объясняет вашу озабоченность $.
(GCC) Знак доллара в строке формата printf
Обозначение %2$d
означает то же самое, что и %d
(выходное целое число со знаком), за исключением того, что форматирует параметр с указанным номером, основанным на 1 (в вашем случае это второй параметр, b).
int a = 3, b = 2;
printf("%2$d %1$d", a, b);
Здесь вы ожидаете, что 3 2 будет напечатано, но будет напечатано 2 3, потому что параметр a становится параметром # 1, а b становится параметром # 2, и% 2 $ d печатается первым, поэтому сначала печатается 2, а затем на% 1 $ d, что составляет 3
Возможно, вы захотите взглянуть на справочную страницу printf, это немного сложно для новичков, но это последний источник правды.
Ниже указана ваша оболочка для печати.
char buf[5012];
memcpy(buf, argv[1], 5012);
printWrapper(argv[1]);
return (0);
Ваш сайт говорит: когда злоумышленник может изменить
внешне контролируемая строка формата, это может привести к буферу
переполнения, отказ в обслуживании или проблемы с представлением данных.
Теперь, если этот argv 1 может быть предоставлен кем-то, кому не доверяют, он может предоставить любой ненужный аргумент, который пойдет в printf. Цель вашей задачи - не использовать print () для какой-либо строки, которая контролируется извне.
например argv 1 может быть очень большой строкой (максимально допустимый).
Или, например, я вызываю вашу программу, и я передал argv 1 как "% d Hello World", ваш printWrapper в итоге напечатает какой-то мусор типа "-446798072 Hello World", потому что целое число не передается в качестве аргумента в printf (argv 1 ).
Также memcpy читает фиксированное количество байтов из источника argv 1 , который может иметь строку более короткой длины, в этом случае это будет недопустимое чтение (чтение за границей).
snprintf(buf,128,argv[1]);
Эксплойт здесь очень ясен, argv 1 может быть изменен с включением нескольких спецификаторов, таких как% n, которые могут записать n байтов в ваш буфер, а не запланированную запись. Используя% X в argc 1 , хакер может получить адрес переменной в стеке, которую можно использовать в дальнейшем. Все это уязвимо, потому что внешний ненадежный источник создает строку спецификатора формата, которая используется вашими функциями printf или snprintf, sprintf.
Например, предположим, что хакер дал «% 200d» в argv 1 . sprintf(buf, 128, argv[1]);
выдаст печать 200 байтов, а затем целое число мусора, которое может вообще не предназначаться, так как его snprintf, который является ограниченной функцией, позволит записать только 128 байтов, которые будут пустыми.
Надеюсь, теперь все ясно.