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

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

AnGel

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

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!


Прежде всего я собираюсь объяснить, как решается крэкми, над которым мы начали работать в главе 13.

3607b59659c42f9e4c1e2f15f648d419.png

Это mielecrackme, загруженный в OllyDbg, и его точка входа. Посмотрим, какие функции API используются с помощью SEARCH FOR-NAME (LABEL) IN CURRENT MODULE.

d811ea73e8e97fd8c44b6b560324df37.png

Вот список найденных api-функций.

8357955ce266e859928b512b2d0ff679.png

Среди них указаны самые важные: GetWindowTextA, использующаяся при вводе серийного номера, lstrcmpA, которая встречалась в предыдущей главе и используется для сравнения строк, и MessageBoxA, отображающая сообщение о том, верен ли серийный номер или нет.

Мы можем установить BPX на эти функции, чтобы произошла остановка, когда будет введён неверный серийный номер, но в данном случае, который весьма прост, можно сделать всё гораздо быстрее, если посмотреть СТРОКИ, используемые программой.

84d719fc8485666ff4c8ad95c9616185.png

Выполнение SEARCH FOR – ALL REFERENCED TEXT STRINGS даёт нам список строк, которые использует крэкми.

604d1e6fc15905b2024296e41335b9f2.png

Здесь видим как строку, отображающуюся как в успешном случае, так и строку, показывающуюся в случае неудачи. Если сделаем на какой-нибудь из них двойной клик мышью, то окажемся в окрестностях MessageBoxA. Попробуем сделать двойной клик на “YOU ENTERED THE RIGHT PASSWORD” («Вы ввели правильный пароль»).

3f6ec5bf61be64aa801bbeaa99be59ea.png

Оказались в соответствующем месте.

Сначала идёт GetWindowTextA, считывающая серийный номер, который мы напечатали, затем lstrcmpA, сравнивающая считанный номер с правильным, а затем, если они верны, MessageBoxA показывает «YOU ENTERED THE RIGHT PASSWORD», а если нет, то происходит переход к другому MessageBoxA, отображающему «YOU SHOULD TRY AGAIN, IT'S SO EASY» («Попробуй ещё раз, это же так просто»).

Установи BPX на вызове lstrcmpA, чтобы посмотреть, что она сравнивает.

024641f8e14a11707009731c0c3577e7.png

Запустим программу с помощью F9.

a5ca3c954cbea7dadb09fa07cf042ec6.png

Выскочило окно ввода серийного номера. Введём в него что-нибудь вроде 989898.

f85dad45b994a6608a4591576d04fe66.png

Нажмём кнопку CHECK, чтобы сработал установленный нами BPX.

04cfa95bdd614e4530dac4cedc670480.png

Видим, что OLLY показывает и параметры функции, которые являются двумя сравниваемыми строками, в данном случае сравниваются строки «989898» и «cannabis».

Чтобы выполнить вызов этой API-функции, нажмём F8.

058a94198346b721b89abbf876377daf.png

В EAX помещается результат, равный FFFFFFFF или -1, а это означает, что строки не одинаковые.

6717bd594f0ae48a20a4fa1fde6b66a9.png

В результате этого сравнения флаг Z неактивен и инструкция JNZ выполняет переход, т.к. флаг Z равен нулю (вспомним, что JNZ совершает переход, если флаг Z равен нулю, а JZ, наоборот, если флаг Z активен, т.к. равен 1).

c7e82923892cf33ab86b69e7f134ac8c.png

Раз мы делаем переход, то получаем сообщение с ошибкой, но зато теперь мы знаем, что сравнение происходит со словом «cannabis», то есть это и есть верный серийный номер. Снова продолжим выполнение программы.

10648fc4eef85cdef4be91b7f0827fac.png

Нажав на «ОК», снова вернёмся в окно ввода серийного номера и напечатаем правильный – «cannabis».

0ff2ead581f089987a1ff124eaaab4e4.png

Нажмём кнопку CHECK, и срабатывает BPX.

2bcd328c9665721959e5a945b94bd082.png

Видим, что будут сравниваться две одинаковые строки. Жмём F8, чтобы выполнить вызов API-функции..

57201d8818a1f5fc8e9b0b83684677ba.png

Обе строки были равны, и в EAX был сохранён результат функции – ноль, что активирует флаг Z.

829cfbef9f66667218e75807dbea47d1.png

И поэтому JNZ не будет совершать переход.

cc141424b2acf0d0a27bd7104829eb2c.png

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

173d0b68199592e6fefb3a62d7f5635f.png

Это и есть решение крэкми из главы 13. Хе-хе, серийным номером является слово «каннабис».

Продолжим дальше и рассмотрим более сложный случаи жёстко заданных серийных номером, чем те, что мы рассматривали ранее.

В следующем случае уже не производится прямого сравнения серийного номера с введённой строкой. Откроем крэкми crackmeeasy в OllyDbg.

a7cb20028314b7c925887ab11e87048b.png

Мы уже знаем, как посмотреть используемые API-функции. В списке также есть GetDlgItemTextA, на который мы и установим BPX.

b04800a4b8af7a0ce2b1128c591a6948.png

В commandbar’е напечатаем:

0c18a98fb00a504cdf119dc18466667a.png

Теперь запустим программу с помощью F9, и откроется окно ввода серийного номера.

bd8beb6722194800fe5cdf9f2085b06c.png

Напечатаем неверный серийный номер.

5fff86ba993525826c0a3ce7b7edc1d2.png

Кликнем по кнопке “Check” и попадём на вызов нужной нам функции.

0e0c4833b5dc8bf0f66683db0a0726cc.png

Посмотрим, какие параметры в стеке.

c27bf993fdfcbbed470d0a2f19e92cbf.png

Здесь видим буфер, в котором сохраняется неправильный серийный номер, отметим эту строку, затем правый клик мышью и FOLLOW IN DUMP.

7b488f213a0a4d13be685f4fafada183.png

Буфер пуст, так как функция ещё не запустилась, поэтому выберем DEBUG-EXECUTE TILL RETURN.

5bb82fb8e40fb649f741613ad94ef755.png

Это приведёт к выполнению функции, которое остановится на инструкции RET.

744dfe8ebb6cbda9e558dd44075f47cb.png

Нажмём F7, чтобы вернуться в программу.

c7ddd9a3cc46e522c8b8d7a201348261.png

И видим, что в буфере окажется введенный нами неверный серийный номер.

2bac2fffc3aeaa2fa2524c213fc1d87f.png

Здесь мы также видим большую процедуру, делающую что-то с какой-то строкой в виде числа. Кому-нибудь пришла мысль, что это правильный серийный номер? Я знаю, что нет, хе-хе.

e6c2fc7c1609a4cf25be03253cca43f9.png

Здесь в EAX помещается число 401222, которое является адресом, указывающем на строку, содержащую число-константу.

b46b28d5a519e076dddf03cc35d7de7c.png

3748413a8b4ac34ba6ae0fb2917e668e.png

На следующей строке, где EAX равен 401222:

MOV EDX,DWORD PTR DS:[EAX]

Это, на самом деле, всё равно, что:

MOV EDX,DWORD PTR DS:[401222]

d49df15ffecdd0c6463f0d7d2a21185c.png

То есть содержимое памяти по адресу 401222 перемещается в 401222.

Олли показывает, что это первые 4 байта числа 10445678951.

cafa5e6227e6e03bb2e1ab625ba148a1.png

Выполнение строки с помощью F7 перемещает их в EDX (они всегда перемещаются в регистр в порядке, обратном тому, как они располагались в памяти).

5791680d1ee56257e6e8c95800224566.png

На следующей строке байты, находящиеся в EDX, перемещаются в [EBP-30].

b83f24be0bd63ec1f2caf45e2d590722.png

Из пояснений Олли видно, что [EBP-30] на моей машине – это 240f9e4. Поищем это значение в DUMP’е.

00f4e5dab2166fec591201ac14c132e3.png

f7f9a31154ed74b7a1c47a406838a4b9.png

F7 копирует байты, находящиеся в EDX.

f818229ad326ac5076950d5d2819d4be.png

После чего

77eefc1f20d5bc9d4046bd52865eec45.png

в EDX перемещаются следующие 4 байта числа-константы.

ee0a2bf79cd831d9173d5bc463231eee.png

Пояснения Олли показывают, что [eax+4] содержат 401226, и выполнение инструкции с помощью F7 перемещает следующие 4 байта в EDX.

a384b436a728f4b67009429b95630bb3.png

И копируется продолжение того, что копировалось ранее.

ee3efa622fa16e18a769da89a71c0d5d.png

В действительности происходит вот что: этот номер копируется по 4 байта в другую часть памяти.

7cdb8934b3f5fb53acaec17bc4dd0f95.png

И наконец копируются последние 4 байта.

3b1981007aef1ea84fedf8f9b6229f49.png

Наконец-то номер скопирован полностью.

Видим, что чуть ниже находится вызов функции memset. Посмотрим её параметры с помощью OllyDbg.

002390eec5a4838db42f40104b27fc99.png

Здесь три значение (n, c и s).

  • s – начальный адрес
  • n – количество байтов, которых нужно заполнить требуемым значением
  • c – значение, которым будет заполняться указанная область памяти
ddd41ec40c459bc2d9c9c2148dabbb2e.png

В стеке находятся вышеуказанные параметры: область памяти по адресу 240f9f0 продолжительностью в 8 байт должна быть заполнена нулями.

f303bfee0d5250fa10c10a1ed233f232.png

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

Ещё ниже находится вызов lstrlen, которая считает длину строки, адрес которой задаётся непосредственно до вызова самой функции.

536abe2897cd8100f4c7fc391e2bc20b.png

В стеке находятся следующие параметры:

475713605bcd29d33081636dd7f43066.png

То есть будет вычислена длина строки, которая начинается по адресу 240f9E4, что является адресом уже известного нам числа, хех.

F8, и происходит выполнение strlen, а в EAX возвращается длина строки.

62ac39eeb7a664906b1442d8271c249a.png

Видим, что размер равен 0B, то есть 11 в десятиричной системе, что является длиной нашего номера.

2b9a00eaee7e41f7253b7dc4f6088e30.png

Здесь LEA перемещает в EDX значение EAX минус 1, то есть 0A.

На следующей строке происходит сравнение 0A с содержимым [EBX-10], то есть с нулём.

a408b6a59256fb59f0a25a85b00415ef.png

И раз ноль меньше чем 0A, то переходим на 40135C.

dfba41a433d963321cd04f397559fe6e.png

На следующей строке в EAX помещается указатель на наш неверный серийный номер, и поэтому когда нажмём на F7, то EAX будет указывать на “98989898”.

c1af234e0e4b79adde1098b7f7f59199.png

На следующей строке перемещаем в EDX ноль.

92a0b55ab1f94a2c06667b4027486803.png

98b4eabf856387165f546fcf75323235.png

На следующей строке

bef5eed019cddc1e4d30496fe08b2c44.png

Так как EAX указывает на начало неверного серийного номер, прибавляем к нему EDX (который изначально равен нулю) для создания цикла, каждый увеличивая значение EDX на 1 (1, 2, 3 и т.п.), чтобы получить все байты неверного серийного номера по одном в указанном цикле.

0e428a322303ab4108cabc842bc7d974.png

Как мы уже знаем, MOVSX переместит байт в EDX и если он положителен, то заполняет остаток регистра нулями, а если отрицателен – ‘F’.

В данном случае первый байт неверного серийного номера переместится в EDX и выполнение строки покажет, что EDX стал равным 39.

70a675d4188350702381df479758094f.png

Следующая строка с LEA.

ab09bebcaa1cea1d947746f255be4744.png

EDX равен 39, вычитаем из него 14 и с помощью LEA помещаем результат непосредственно в EAX.

6baa13fe9207101f2e2952be704c088f.png

То есть в результате произведённых операций получили 39 (шестнадцатиричное значение первого символа моего серийного номера), отняли от него 14 и результат, равный 25, поместили в EAX.

707589e0257ef1aeec0febc9b5019040.png

Следующая строка перемещает значение, находящееся по адресу EBP-30 (на моей машине равное 240f9E4, и оно указывает на начало номера-константы), в EDX.

43585c446361e1c0b73d24be0fa68204.png

Нажмём F7.

98a71f4ffd97b70dbd4bd18c4a96dfbf.png

EDX указывает на начало номера-константы.

3bf69f7b169f3123e70ebe7806e9ec73.png

Далее видим, что в ECX перемещается сначала значение равное нулю, а затем при каждом новом проходе оно увеличивается, чтобы ECX+EDX указываели на разные байты номера-константы.

17c3b8f57b13b6b1bc605a78da7d5f08.png

Здесь видим, что ECX теперь содержит ноль, а EDX указывает на начало номер, поэтому в данном случае в EDX будет помещён первый байт номера, дополнительная информация о котором выводится в пояснении OllyDbg.

4cd015efc956370bf029f1dfe3cc6fc8.png

Пояснение говорит, что 31 соответствует ‘1’ в кодировке ASCII, что является первой цифрой номера-константы.

93486c388e2df73cc4327fdc48c8beec.png

Здесь мы дошли до сравнение, где участвуют:

4d518469d6f9279a77dd9fdf6beee092.png

В EAX находится значение 25 (значение первого байта неверного серийного номера (39), от которого было отнято значение 14), а в EDX первый байт номера-константы или 31.

А потому видим, что

CMP EAX,EDX

на самом деле является

CMP (ПЕРВЫЙ БАЙТ НЕПРАВИЛЬНОГО СЕРИЙНИКА– 14), ПЕРВЫЙ БАЙТ НОМЕРА-КОНСТАНТЫ

CMP 25,31

И поскольку разность между этими двумя операндами равна нулю, то флаг Z не активируется и выхолняется переход JNZ.

Мы вводили неверный серийный номер, а сравнение может дать верный результат, если будет введён правильный серийный номер, чтобы сравниваемые значения были верны.

CMP (ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА– 14), 31

Это и есть условие, при котором сравниваемые значения будут равны.

ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА-14 = ПЕРВЫЙ БАЙТ НОМЕРА-КОНСТАНТЫ

Поэтому

ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = ПЕРВЫЙ БАЙТ НОМЕРА-КОНСТАНТЫ + 14

2fc9eccc213a09308d1ed06d61c6be95.png

ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = 31 + 14

ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = 45, что соответствует “E” в ASCII.

То есть первая буква серийного номера равна E.

Эта побайтовая проверка повторяется в цикле до конца.

ПЕРВЫЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = ПЕРВЫЙ БАЙТ НОМЕРА-КОНСТАНТЫ + 14

ВТОРОЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = ВТОРОЙ БАЙТ НОМЕРА-КОНСТАНТЫ +14

ТРЕТИЙ БАЙТ ПРАВИЛЬНОГО СЕРИЙНИКА = ТРЕТИЙ БАЙТ НОМЕРА-КОНСТАНТЫ +14

Вот таким образом.

Применим этот алгоритм для каждого байта, прибавляя 14 и получая значение байта, соответствующее верному серийному номеру.

31 30 34 34 35 36 37 38 10445678
39 35 31 00 00 00 00 00 951.....
  • 31 + 14 = 45 это буква E в ASCII
  • 30 + 14 = 44 это буква D в ASCII
  • 34 + 14 = 48 это буква H в ASCII
  • 34 + 14 = 48 это буква H в ASCII
  • 35 + 14 = 49 это буква I в ASCII
  • 36 + 14 = 4A это буква J в ASCII
  • 37 + 14 = 4B это буква K в ASCII
  • 38 + 14 = 4C это буква L в ASCII
  • 39 + 14 = 4D это буква M в ASCII
  • 35 + 14 = 48 это буква I в ASCII
  • 31 + 14 = 45 это буква E в ASCII
Поэтому правильный серийный номер следующий:

EDHHIJKLMIE

Введём его в окне серийного номера, убрав предварительно все точки останова.

8504c56c161b2cb1c0024d84c40a6cb6.png

Нажмём “Check”.

221100b7ca73f92e78795bf26f123476.png

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

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

Ок, прилагаю к этой части крэкми «Splish», попробуйте найти серийный номер, захардкоженный в нём.
 

О нас

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

    Dark-Time 2015 - 2022

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

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

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