Атака на QIP. Низкоуровневое исследование популярного интернет-пейджераЛеонид «Cr@wler» Исупов (crawlerhack@rambler.ru) «Топовые» программные продукты, распространяемые на бесплатной основе, зачастую пользуются такой популярностью, что пользователи доверяют их авторам всецело, совершенно забывая о собственной безопасности. Чтобы разрушить весьма распространенный миф о том, что «популярно - значит надежно», мы займемся исследованием раскрученного на территории СНГ интернет-пейджера QIP. Пробиваем «непробиваемую» бронюВ одном из выпусков рубрики «Easyhack» я рассказывал, как модифицировать QIP так, чтобы он выдавал введенный пароль при помощи использования MessageBoxA. Естественно, я не стал раскрывать все карты сразу и описывать обход защитных механизмов – исключительно для того, чтобы разработчики залатали дыры, а хакеры не использовали информацию в корыстных целях, для создания «нового релиза» QIP с функцией воровства аккаунтов. Прошло достаточно времени, и я решил углубиться в увлекательную исследовательскую работу. Вместе с тобой мы попробуем пропатчить qip.exe таким образом, чтобы он записывал введенные пользователем пароли в файл. Все действия будем выполнять при помощи, я думаю, хорошо уже известного тебе отладчика OllyDbg. Итак, вооружаемся отладчиком, релизом QIP и погружаемся в работу. Открываем файл под отладчиком. Если ты помнишь, я уже исследовал QIP и выяснил, что существует некоторая защита от модификации исполняемого файла. Продемонстрировать наличие некоторой функции, проверяющей целостность файла, довольно легко: замени какую - либо инструкцию в середине кода программы на nop и попробуй запустить программу. Вместо привычного окна авторизации появится сообщение о том, что файл поврежден. Попробуем излечить нашего «пациента» от этой «болезни» :). Прежде всего, чтобы интернет-пейджер «принял» добавляемый нами в PE-файл код (а мы его, безусловно, добавим) в качестве своего собственного, необходимо отключить защитные механизмы. После недолгой трассировки кода измененного файла я выяснил, «где собака зарыта»: по адресу 068F4BA располагается процедура проверки целостности PE-файла. Она портит нам настроение, поэтому рекомендую ее исследовать. Пошаговое выполнение программы доводит нас до любопытного места:
Мы не знаем, что именно проверяет доблестный интернет-пейджер внутри вызываемой функции, да это для нас и не столь важно. Ставим точку останова на 00480246 и до умопомрачения жмем на <shift+F9>. Программа запустится и выдаст безрадостное окошко: файл поврежден. Методом «научного тыка» я выяснил, что если четыре раза нажать на <shift+F9> во время прерывания на точке останова, а перед пятым нажатием – занопить вызов «CALL 00404304», программа запустится (при условии, что после пятого прохода мы снова восстановим вызов при помощи команды контекстного меню «Undo Selection»). В отладчике все просто – заменяем вызов на nop после четырех нажатий на <shift+F9>. Затем снова жмем <shift+F9>, щелкаем правой кнопкой по вызову, выбираем «Undo Selection», убираем точку останова и запускаем программу на исполнение. Но как пропатчить код, чтобы он «знал», когда защитная процедура вызывается в четвертый раз? Писать огромные проверки со счетчиками запуска - сложно и долго. Как удалось выяснить, в моем случае содержимое регистра EBX (я взял его, что называется, «от балды»; ты можешь проверять любой другой регистр) перед пятым вызовом защитной функции равно 0064ED7C. Перед тем, как писать код, обходящий защиту, определимся с его местоположением. Будем пихать наш «жучок», начиная с адреса 0068F857. Вызов защитной функции, располагающийся по адресу 00480248, заменим на безусловный переход к нашему коду.
Кстати, заметь, что следующая инструкция располагается по адресу 0048024D – этот факт нам еще пригодится. Вот как будет выглядеть наш код:
Простой код обходит мудреную защиту, и теперь мы можем беспрепятственно творить все, что захотим! Все подводные камни устранены, а широкий путь для творческих походов расчищен: никто и ничто не мешает нам изменять «внутренности» интернет-пейджера. Лирическое отступлениеЕсли ты еще не забыл, наша задача - написать код, который будет сохранять введенный пользователем пароль в файл. Для этого необходимо владеть информацией, как минимум, о двух API-функциях: создающей файл и записывающей в него информацию. Порыскав в MSDN, находим необходимую информацию. Для создания файла будем использовать функцию CreateFileW. Она принимает следующие параметры (расположу их в обратном порядке – в том, в котором мы будем помещать их в стек):
Некоторые параметры можно обнулить (об этом мы поговорим позже). Для записи в файл воспользуемся функцией WriteFile. Вот ее прототип:
Параметры будут следующими:
Условимся, что наш код будет располагаться, начиная с адреса 0068F86E. Теперь необходимо сделать небольшое лирическое отступление. Как было выяснено в результате долгих исследований (если хочешь знать, каких конкретно, почитай колонку EASYHACK за ноябрь 2008 года), после вызова следующего кода, который выполняется при нажатии на кнопку «Подключиться», в стеке (по адресу [ebp-8]) находится пароль:
Как видишь, код, расположенный после CALL-а, проверяет, пусто ли поле для ввода пароля (пара инструкций – «cmp» и «je»). Нам эта проверка не нужна, так что на помойку ее – и заменим на переход к нашему коду:
Три простых шага к краже пароляВнес изменения? Едем дальше. Перейдем к адресу 0068F86E и напишем наш код. 1. Передаем параметры для CreateFileW в стек и вызываем эту функцию. Вызванная API возвратит в EAX хэндл открытого файла.
2. Положим в стек содержимое регистра EAX в качестве единственного параметра для функции закрытия файла CloseHandle, которую вызовем впоследствии.
3. Передадим в стек параметры для функции WriteFile и вызовем ее. К сожалению, есть один нюанс, который не позволит нам использовать стек в качестве буфера для этой API-функции: ее вызов затирает часть необходимых данных, хранящихся там. Поэтому роль буфера будет играть часть секции кода, начиная с адреса 0068F8EB. Но так как секция кода защищена от записи, придется вызвать функцию VirtualProtect с параметром NewProtect = PAGE_EXECUTE_READWRITE. Вызов VirtualProtect с передачей параметров разместим по адресу 0068F8B7 (предварительно сохранив регистры при помощи PUSHAD). После чего при помощи набора инструкций MOV скопируем пароль, расположенный в стеке, в наш буфер - по адресу 0068F8EB. Все вместе это выглядит так:
Ситуация немного изменилась. Раньше мы планировали передавать управление на наш код следующим образом:
Теперь это невозможно, так как нам пришлось использовать дополнительный код в виде вызова VirtualProtect, который должен непременно выполняться раньше остального кода. Так что переходи к адресу 0068F8E9 и меняй расположенный там переход на:
Все готово! Резюмируем все, что было написано выше. Внедренные нами инструкции создают файл в директории программы и при помощи вызова VirtualProtect разрешают запись в секцию кода, часть которой используется в качестве буфера. А затем - вызывают функцию WriteFile, которая записывает в созданный файл полученный пароль, введенный пользователем. Как видишь, код не так сложен. Тем не менее, защитные механизмы отключены, и пароль записан в файл. Разработчики, будьте внимательны!Скажу несколько вещей, не особенно приятных для разработчика интернет-пейджера, но необходимых. Во-первых, механизмы защиты данных учетных записей, находящихся в памяти, нуждаются в доработке. Во-вторых, механизмы контроля целостности файла также нуждаются в дополнительном усовершенствовании. Что важно, мы рассмотрели самый тривиальный способ модификации. Между тем, нужно дописать лишь несколько десятков строк кода, чтобы получить версию QIP, которая будет открывать интернет-соединение и отправлять данные учетных записей по Сети. Только представь ситуацию: раскрученный интернет-портал, на который залита «новая» версия QIP, может быть, содержащая новый пакет смайлов и несколько «модифицированный» код выполнения авторизации. Как следствие - тысячи (возможно, десятки тысяч) украденных аккаунтов. Напоследок - скажу, что многие из популярных программных продуктов имеют не менее шокирующие уязвимости. Посему мы еще не раз встретимся на страницах журнала и распотрошим не один десяток самых скачиваемых программ. Удачи во взломах! DANGERВся информация, которая содержится в статье, предоставляется исключительно для указания на уязвимости и не является руководством к действию. За незаконные действия, выполненные с применением материалов данной статьи, ни редакция, ни автор ответственности не несут. |