Дерни printf за хвост Крис Касперски aka мыщъх Спецвыпуск Xakep, номер #045, стр. 045-032-4 .rdata:004053B4 aMicrosoftVisua db 'Microsoft Visual C++ Runtime Library',0 Дизассемблер утверждает, что по адресу 004053B4h в нашей демонстрационной программе расположен копирайт фирмы Microsoft. Давай выведем его на экран. Как мы помним, начало буфера соответствует шестому спецификатору. Каждый спецификатор занимает два байта и снимает со стека четыре. Еще два байта уходят на спецификатор "%s", выводящий строку. Так сколько всего надо передать спецификаторов программе? Составляем простенькое линейное уравнение и сходу решаем его, получая в ответе двенадцать. Одиннадцать из них выгребают со стека все лишнее, а двенадцатый выводит содержимое расположенного за ним указателя. Указатель формируется тривиально: открываем ASCII-таблицу символов (как вариант – запускаем HIEW) и переводим 4053B4h в символьное представление. Выворачиваем его наизнанку и вводим в программу, при необходимости используя цифровую клавиатуру и клавишу >ALT<. Получилось! Мы сделали это! Действуя и дальше таким макаром, мы сможем просмотреть практически всю доступную память программы. Реализация poke Спецификатор "%n" записывает в парный ему указатель количество выведенных на данный момент байт, тем самым позволяя нам модифицировать содержимое указателей по своему усмотрению. Обрати внимание: модифицируется не сам указатель, а то, на что он указывает! Перед демонстрацией нам необходимо найти в стековом хламе подходящий указатель, предварительно прочитав его содержимое строкой типа "%X %X %X", как мы уже делали. Выберем 12FF3Ch, указатель на буфер пользовательского ввода buf_in. Чтобы его достать, нужно снять со стека два двойных слова; этим у нас займутся спецификаторы "%c%c". Теперь определимся с числом, которое мы хотим записать. Записывать можно только маленькие числа – на большие просто не хватит размера буфера. Сойдемся на числе 0Fh (это нечетное число, четные приносят несчастье :). Считаем: два символа выводят спецификаторы, снимающие лишние двойные слова с верхушки стека, семь приходится на строку "hello, " (да-да, она тоже в доле), тогда у нас остается: 0Fh – 02h – 07h == 06h. Шесть символов, которые мы должны ввести самостоятельно. Они могут быть любыми, например, "qwerty" или что-то в этом роде. Остается добавить спецификатор "%n", и сформированную строку можно передать программе: введи имя: qwerty%c%c%n hello, qwerty\ ! Поскольку модификация буфера осуществляется после его вывода на экран, доказательства перезаписи памяти приходится добывать в отладчике. Загрузив подопытную программу в Microsoft Visual Studio (или любой другой отладчик на твой вкус), установи точку останова по адресу 401000 (адрес функции main) или, подогнав к ней курсор (Ctrl+G, Address, "401000", >Enter<), нажми Ctrl+F10 для пропуска инструкций стартового кода, совершенно не интересующего нас в настоящий момент. |