Введение в крэкинг с нуля, используя OllyDbg - Глава 12

  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

AnGel

Администратор
Команда форума

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
Данная глава посвящена практическому использованию сообщений Windows.

Следующая цитата вкратце описывает назначение сообщений Windows:

Сообщения в Windows широко используются для уведомления о различных событиях. Если Вы хотите заставить какое-либо окно или контрол (элемент пользовательского интерфейса, на самом деле тоже являющийся окном, как то: кнопка, edit, Toolbar, Tree view и т.д.) совершить определённое действие, отправьте ему соответствующее сообщение. Сообщения также могут исходить от других приложений. Система уведомляет о таких событиях как передвижение мыши, нажатие клавиши на клавиатуре и т.д. также посредством сообщений.

Как мы уже рассмотрели ранее, в OllyDbg можно расставлять точки останова BPX на вызовах различных API-функций. Зачастую более эффективным способом "отловить" интересующие нас участки кода являются точки останова на сообщениях. Их ещё называют BMSG в честь одноимённой команды в ядерном отладчике SoftIce.

Оконные приложения имеют по крайней мере один так называемый цикл обработки сообений (англ. - message loop). Этот цикл являет собой вызов определеённых API-функций (чаще всего используются функции GetMessage и DispatchMessage, но встречаются и другие варианты воплощения message loop). Для более глубокого ознакомления с циклом обработки сообщений автор рекомендует статью "Understanding the Message Loop" (C) Brook Miles:

Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


На русском и гораздо более подробно про цикл сообщений можно почитать у братьев Фроловых:

Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


Правда, там речь идёт о Win16, но именно по данной теме особых разногласий с Win32 в тексте не наблюдается. Спасибо IceStudent’у за ссылку!

Давайте рассмотрим простой пример: для того, чтобы выудить серийник из крэкми, мы установим BMSG на сообщение о нажатии кнопки, ведь именно это сообщение должно инициировать проверку введенных данных. Итак, загружаем крэкми CrueHead'а в OllyDbg.

e5d4cb6de2effe7def88de3cebbd8b8b.png

Но сначала попробуем выудить серийник классическим способом, а потом через BMSG и сравним. Для начала проанализируем API-функции, которые импортирует программа, чтобы найти ту, которой скорее всего считывается введенный текст для последующей проверки.

Правый щелчёк в ассемблерном листинге - Search for - Name (label) in current module.

e9ddc70e39f19246b7ee2fd33f2c9633.png

Чаще всего для считывания текста из edit'а используются функции GetDlgItemTextA и GetWindowTextA. Конечно, могут использоваться и юникодовые версии данных функций (с суффиксом W), либо сообщение может посылаться напрямую (тут тоже есть несколько способов различного уровня сложности), либо более экзотический вариант с прямым считыванием буфера edit'а. Короче, и не надейтесь, что в продвинутых крэкми текст из edit'а будет извлекаться банальным вызовом GetDlgItemTextA или GetWindowTextA, но для начала мы рассмотрим именно этот вариант.

e4309431ccfe02281f7e98da406e6d2e.png

В списке видна функция GetDlgItemTextA. Это вовсе не значит, что данная функция используется именно для считывания имени пользователя и серийника (в программе могут быть и другие поля ввода), если вообще используется. Автор крэкми мог намеренно добавить данную функцию в импорт, чтобы ввести нас в заблуждение. Между прочим, функции API можно подгружать динамически (и даже разными способами), т.е. не через импорт. Таким образом, крэкми может на самом деле использовать GetDlgItemTextA, но в списке импорта функции не будет. Не будем пока усложнять и без того нелёгкий материал и предположим, что крэкми действительно использует GetDlgItemTextA для считывания текста из edit'а ;)

Ставим BP на вызов данной функции:

7dad164f78495ddf5d6445da79e3d999.png

Или так:

cef33d1efe377b4f1c077ca7525d8dd7.png

После установки BPX, запускаем программу на выполнение, вводим имя пользователя и серийник:

dc47216308f2000242769bbcc437ae9c.png

Нажимаем OK - "брякаемся" в коде:

fb7c0dc6df8b224f3e9fa451683d5de7.png

Обратите внимание на стек.

7b74c20c7f04d01d331fe1e21488db63.png

Видим, что один из параметров функции является указателем на буфер, в который будет скопировано содержимое edit'а.

Давайте загрузим данный буфер в дамп посредством команды Follow in dump или через Go to - Expression: 40218E.

b0380812a2cdff640687f67533e7487b.png

Сейчас в буфере пусто, ведь функция ещё не выполнилась.

ad771e33a41a1dbeb35a87dbc863fd4f.png

Давайте дадим этой функции возможность выполниться: Debug - Execute till return.

7361c1a7db8695cfe56a1f773e6d3bed.png

Теперь в дампе буфера находится имя, которое Вы ввели для регистрации.

b34678c4380f0023e9bb223b41caab7d.png

Снова задаём команду Run (F9) - опять срабатывает наша точка останова.

36b64af000fa965c57ee27430c3a0e34.png

Теперь параметр буфера указывает на адрес 40217E. Давайте посмотрим в дампе:

10187d7c02688adfc73dc9fb714fec4e.png

Задаём Execute till return.

04d09795cf5aeaa13e9c9f8d47b36721.png

А вот и наш серийник!

Как Вам уже должно быть понятно, для извлечения правильного серийника, первым делом нужно поймать момент доступа приложения к введенным данным (в данном случае - имя и пробный серийник). Дальнейший план действий мы рассмотрим чуть позже, а пока попробуем повторить первый шаг, но с использованием BMSG. Многие алгоритмы проверки специально не используют общепринятые API для считывания полей ввода текста, а посылают сообщения напрямую, чтобы насолить реверсеру.

Снимаем все действующие BPX в окне командой Remove.

88f9bdfe989531021e981a63bda3519f.png

f8684182ea732d9989696c111e778dc1.png

Снова запускаем приложение, вводим имя и серийник, но пока ещё НЕ нажимаем OK.

761ef895f1dbf56ab4773b19de40dcb2.png

Одна из особенностей использования BMSG по сравнению с BPX на API-функции заключается в том, что BPX можно расставлять заранее, ещё до запуска процесса, тогда как BMSG имеет смысл устанавливать только после создания окна, чьи сообщения нужно перехватить.

Открываем окно [W]indows в процессе отладки (не нужно предварительно останавливать процесс, т.е. статус процесса вполне может быть Running).

a33d860dd34b1e3e25c147c24595108d.png

6d4b16e1e0c11f49ef86326b60babcd8.png

Если в списке [W]indows пусто, нужно сделать правый щелчёк мышью и выбрать пункт Actualize.

6a8380077083021cbaf62e19be1e4547.png

Ищем в списке контрол "кнопка"... В колонке Class должно быть значение Button, а в Title - OK. Есть такой контрол!

Правый щелчёк в строчке данного контрола - выбираем Message breakpoint on ClassProc.

3d8279c583ae3a2c3a92dd03c5851d59.png

cfca86dd8e63beeb31a4d2fca2df0951.png

В открывшемся окне нужно указать сообщение, которое мы собираемся поймать. Во всплывающем списке:

ac9aaec0325dbe469cc3538c493ada83.png

Есть тут и стандартные сообщения для статических текстовых контролов и кнопок, и мышиные сообщения, и для буфера обмена и т.д. Если Вы не знаете точно какое сообщение нужно ловить, можете попробовать стандартные группы сообщений (в начале списка). При нажатии левой кнопки мыши система посылает сообщение WM_LBUTTONDOWN (L означает LEFT, т.е. левая). При отжатии посылается сообщение WM_LBUTTONUP. На это последнее сообщение мы и повесим BMSG - оно имеет номер 202.

62aae4b124fd41a607917dda039b3c66.png

Вот как это должно выглядеть:

386e0c1b801f776f8da98fbc1e83d308.png

Мы выбрали сообщение 202 WM_LBUTTONUP. Щёлкаем по "Break on any window" и по "Pause program: On message" чтобы отлаживаемый процесс останавливался при поимке указанного сообщения. Ниже выбираем "Log WinProc arguments: On message" ибо регистрация каких-либо аргументов в логе не бывает лишней.

169e6c1a72c3159a5ddf4c83fae02fa2.png

Данный BMSG будет срабатывать как при нажатии OK, так и Cancel, ведь мы указали, что BMSG вешается на все окна. Щёлкаем левой кнопкой мыши по кнопке OK.

61bcd0b119ac6ca50598760499bc0f2b.png

d50c0f9ed66e83ba8e92dc57110b2f72.png

В этом месте теряются многие новички, т.к. при срабатывании BMSG попадают в незнакомый участок кода, не принадлежащий основному коду процесса. На самом же деле вернуться к основному коду вовсе не сложно.

4f317fc108252983240c2ad67d6fd713.png

Как мы уже знаем, основной код находится в секции, которая начинается по адресу 401000. Ставим BPM on access на данную секцию, чтобы остановиться как только управление попадёт в диапазон адресов этой секции.

fe6a1982dd05044dd434960bb7f734af.png

Жмём на Run и вскоре останавливаемся уже в коде программы.

961daa5cdec4487b2f827041b524df23.png

Не снимая BPM on access продолжаем нажимать F9 - получается пошаговое выполнение инструкций, но только в пределах текущей секции.

2a004417a2515999d50bede05646e5a4.png

Сразу после выхода по 2м RET, попадаем на участок кода с вызовами GetDlgItemTextA, которые считывают имя пользователя и серийник. Таким образом, мы снова очутились на интересующем нас участке кода, но в этот раз мы не использовали BPX на обращения к API.

Если бы приложение не использовало вызовы API для чтения серийника, методом BMSG мы бы всё равно отыскали данный участок. В этом и заключается преимущество последнего.

Если мы хотим отловить нажатие кнопки OK но не мышью, а через клавиатуру, первым делом снимаем BPM on access: правый щелчёк - Remove memory breakpoint.

9b5abb8947a30e2bd93a4cc616b91ddb.png

Открываем список точек останова в окне и удаляем все BMSG опцией Remove.

422d229b7f47357bdf6166f3c4a21017.png

Снова запускаем программу и открываем окно ввода серийника, но пока ничего не вводим.

2af5ee3a789b7ac91c6a76bd71c29d41.png

Открываем закладку [W].

c956f78880b6bc2d868a73842ac5fad1.png

Повторяем уже знакомые действия, но в этот раз выбираем:

ef20db2e6af6ae2e8e1f60fee608e5db.png

Сообщение WM_KEYUP под номером 101 - это сообщение генерируется при отжатии клавиши.

8ef07eaef3672b9ccc42fecb20141356.png

a578abcd42e35a4209016331ec1a94bc.png

Нажимаем и отпускаем какую-либо клавишу для ввода первого символа имени пользователя - BMSG не срабатывает, т.к. чтение данных пользователя осуществляется не посимвольно, а целиком. Некоторые крэкми предпочитают проверять серийник по мере ввода, реагируя именно на клавиатурные сообщения - такую возможность важно учитывать!

Можно ли заставить отладчик показывать сообщения "в живую", при этом не останавливаясь, чтобы потом поставить BMSG на те из них, которые представляют интерес?

Для этого нужно сначала установить BMSG на какое-либо сообщение. В данном случае можно снова использовать сообщение под номером 202, предварительно удалив лишние точки останова в списке , потом спровоцировать его срабатывание нажав и отпустив левую кнопку мыши.

50e77dd7161e211817cba1672345169c.png

Устанавливаем BMSG, нажимаем мышью кнопку OK (в окне регистрации крэкми).

5dbeaf038193458cb4ec5b297864ec6e.png

Срабатывает наш BMSG. Теперь мы его немного переделаем, чтобы ловить все сообщения и сбрасывать в лог.

Открываем список точек останова по закладке .

478e33e987915a49d705889b6899bc3f.png

d4bd64a5f668b5de4edd080a1ae0e305.png

В списке находится наш BMSG: правый щелчёк - Edit condition.

f1d7ef250f98fee26004bdc32aef9974.png

f166e67cb2dc0f5e9487de47a7491313.png

Кстати, обратите внимание на то, что BMSG - это всего лишь условная точка останова, условием которой является значение параметра [ESP+8] - оно должно равняться 202, т.е. WM_LBUTTONUP. Давайте посмотрим на стек:

fe8cadd4611ccbf9ed7dc0f9588a3e2e.png

Там хранится значение 202 по адресу ESP+8, чем и вызвано срабатывание BMSG.

Если Вы уже забыли что собой представляет [ESP+8], сделайте двойной щелчёк:

2fcf05cf14d34f21126f7479aa48b7da.png

По самой верхней ячейке стека.

47d6b51a3d1303e3df60f3e926bbe66d.png

Адресация теперь показана относительно ESP: $+8 в данном случае означает ESP+8.

В общем, в ячейке [ESP+8] находится номер текущего сообщения, которое нам нужно сбрасывать в лог. Изменяем параметры условной точки останова:

0a45051ac4b3cd1ecd59cb29d935910b.png

В настройках указываем, что значение в выражении, т.е. [ESP+8], нужно записывать в лог вместе с другими параметрами функции; чтоб выполнение не останавливалось при срабатывании условного BPX ставим Never в Pause program.

Подтверждаем изменения кнопкой OK, дописываем имя пользователя и серийник, нажимаем OK, смотрим LOG сообщений:

e3d991dd87d13656edd7ef61c6170084.png

Как видно в логе, сначала приходит сообщение 201 WM_LBUTTONDOWN, а потом - 202 WM_LBUTTONUP. Клавиатурные сообщения WM_KEYDOWN и WM_KEYUP не обрабатываются, как мы уже заметили.

Чтобы отловить и записать в лог все сообщения, которые получает программа (кнопки, поля ввода текста и т.д.) можно установить условные точки останова на функции обработки сообщений: TranslateMessage и/или DefWindowProcA.

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

Чтобы побыстрее установить оба BPX, давайте воспользуемся плагином CommandBar: BP TranslateMessage, BP DefWindowProcA.

a64f21fa126190ebdcd2506306c0a351.png

и

a4120b6e34d454695b9851b2871004b7.png

Таким образом мы установили 2 обыкновенных BPX на функции API. Давайте переделаем их в условные. Для этого открываем закладку , правый щелчёк по первому BPX - Follow in disassembler.

d3ad6b0015cd26288a9455b772c72a3f.png

cbbe2e8f11a2a0bb2d37f47f8a146117.png

Уже "на месте" точки останова задаём Breakpoint - Conditional log.

71680a61cc33f716aff9e219167d4b8a.png

В качестве выражения, которое нужно записывать в лог, указываем MSG - это номер сообщения (например, для WM_LBUTTONUP, MSG = 202).

Потом в настройках указываем, что приложение не должно останавливаться и чтобы в лог всё время записывались как текущее выражение так и аргументы функции. Аналогичным образом перенастраиваем второй BPX.

812cf049cf3604e43f16e5003bb9802c.png

Итак, оба BPX уже превратились в условные.

4a73445768c53fa4d2c68343bdd93f93.png

Так-как результатов будет довольно много, лучше всего сохранять их сразу в файл.

78ccf0ef35a583d78343a8ad7e0f5624.png

Закладка [L] - правый щелчёк - Log to file.

98acc3c0fb94fe7eebc60950f1ee0403.png

Задаём имя текстового файла. Жмём Run.

730455af888f7472659decd7e4bf2bc2.png

Теперь в логе находятся все сообщения, полученные и обработанные оконной прецедурой приложения. С помощью этого лога можно составить представление о сообщениях, которые обрабатываются приложением и точнее подобрать кандидатов для последующих BMSG.

Владение различными техниками BMSG бывает очень кстати при снятии NAG'ов и других типичных для реверсинга задач - вот увидите!

В следующей главе мы наконец получим правильный серийник для крэкми CrueHead'а.
 

О нас

  • Наше сообщество существует уже много лет и гордится тем, что предлагает непредвзятое, критическое обсуждение различных тем среди людей разных слоев общества. Мы работаем каждый день, чтобы убедиться, что наше сообщество является одним из лучших.

    Dark-Time 2015 - 2022

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя