# Глава 18

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

Но эту тему мы начнём в 19-ой главе, так как среди тех, кто изучает этот курс, нашлись люди, написавшие мне на почту и попросившие разобрать пример крэкми без кнопок как в прошлой части, и рассмотреть применение другой техники, использующей WM\_KEYUP.

Хорошо, используем для этого крэкми, предоставленный мне Stzwei’ем (спасибо ему), который называется \_4stz.exe [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/18/crackme_4stz.7z). Его мы и рассмотрим в данном туториале.

Откроем крэкми в OllyDbg.

![](/files/zK4oyvi5o0eqUaPshxc5)

Находимся на точке входа. Посмотрим, какие здесь есть не запакованные строки.

![](/files/7InheVvw6pzQ9FS9BfAP)

Отображается список строк, используемых программой.

![](/files/KDVUfPtgR5DiG1cMm1El)

Здесь нет ничего интересного, посмотрим API-функции.

![](/files/OfXrAmM68ag5byuHpXVk)

![](/files/eqkSthBQmUXYbtxTlAJf)

Уфф, так много.. Ок, запустим программу и окажемся в окошке, где вводится серийный номер.

![](/files/tBUnOf0Dm4FvGqOSNEtg)

Видим, что кнопки регистрации нет. Введём полное имя.

![](/files/R6PEHnNk0MOiS1A3zJ6s)

И установим BPX CONDITIONAL LOG на TranslateMessage – сначала обычный BPX.

![](/files/TR99EwuTBAnwwlm6UGOc)

А когда вернёмся в крэкми, отредактируем установленный BP.

![](/files/NoGshpCuL4XTmZqwdNF3)

Если кто-то не помнит значение WM-сообщения, которое собираемся использовать, то нужно перейти в окно W, которое показывает, какие окна используются программой.

![](/files/CLn9HSaBl4WMpn6IqtW6)

И отображается список окон, осталось только узнать числовое значение, поэтому кликаем правой кнопкой мыши.

![](/files/O2ONN68MOVvaB7qk6SLv)

И мы попадаем в окно точек останова на сообщения с раскрываемым меню с WM-значениями.

![](/files/yOdHHxOGcdZMXHnGQTu5)

Поищем в списке WM\_KEYUP.

![](/files/x5vOrdcbZfcDXf4hEzKv)

Видим, что это 101, поэтому уберём всё, что мы делали только для того, чтобы узнать это значение, и вернёмся к BREAKPOINT CONDITIONAL LOG в TranslateMessage.

![](/files/qqhcWgQX4Aa6KovcEl8J)

И устанавливаем здесь MSG==101 (обратите внимание на двойной знак равенства), также, если бы не нашли значение, могли бы написать MSG==WM\_KEYUP и это бы сработало, но мне больше нравятся числовые значения. Здесь каждый волен поступать так, как ему это нравится.

Хорошо, точка останова трансформировалась в условную (розовый цвет).

![](/files/hkpIgG8KhNugyj7Ikmpk)

Делаем RUN и вводим первый символ неправильного серийного номера.

![](/files/N53LVqugDPVQbWAQAAZt)

И тут срабатывает условная точка останова.

![](/files/H0KVzxLAv3LRSLLq8Pdi)

Смотрим параметры API-функции, по адресу 12ff78 находится структура, в которой сохранены значения нажатой клавиши, в данном случае это 39, что соответствует цифре 9.

Смотрим через DUMP указанную область памяти – нажимаем правую кнопку мыши на указанном адресе и выбираем FOLLOW IN DUMP.

![](/files/SG20nUR742j4BaeRBdA5)

![](/files/zok9rzAgon7QjnCNovjp)

Видим, что нам удалось узнать, куда помещается байт. Проблема в том, что это программа на Delphi (что мы рассмотрим в другой раз), и если мы установим на него BPM ON ACCESS, программа будет ходить сто раз туда-сюда, прежде чем дойдёт до сравнения, поэтому метод, который мы рассматривали в прошлый раз, работает здесь гораздо лучше, так что его мы и используем. В любом случае, вы уже знаете, как остановить программу по нажатию клавиши и как установить местонахождение байта. Разумеется, в крэкми, не написанном на Delphi, гораздо проще использовать BPM ON ACCESS.

И запускаем.

![](/files/0fu4rl5lU0eICFfHNEJz)

Вводим 9898, идём в окно M и ищем по всей памяти.

![](/files/m6HyEDDDRFTW4cysLPXh)

Нажимаем правую кнопку мыши и выбираем SEARCH.

![](/files/s48YLt9Azd6o9wrpvSx0)

![](/files/ssyCXX0K5M7xfiEStCYu)

И ищем строку 9898.

![](/files/z2ld6rwFDW6McNrgsRJr)

Первое вхождение обнаруживается в стеке. Нажимаем CTRL+L несколько раз, чтобы увидеть, сколько раз оно в нём встречается.

Как только нам внизу отобразится жёлтым цветом слово ITEM NOT FOUND, выходим и возвращаемся в окно M.

![](/files/JxLXFou4U1QEuTOmnZbt)

Оказываемся там, откуда искали, так что идём дальше вниз с помощью CTRL + L.

![](/files/8E6kXA7wLNL6DDJML8aN)

Первый раз в этой секции, нажимаем CTRL + L, чтобы посмотреть, найдётся ли здесь что-либо.

Нет, ничего нет, если посмотрим область, находится вхождение чего-то подозрительного.

![](/files/iqgUR5KiPwfpWq3CFoX3)

Видим возможный серийный номер 418507, установим на это место BMP on ACCESS, чтобы посмотреть, не с ним ли происходит сравнение.

![](/files/fkt8qmEvD7lwswzCgUfR)

Делаем RUN.

![](/files/FU5CBLBZbSAjFhPyUALC)

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

![](/files/85cYKVZbVAoe14nutC3G)

Видим, что каждый раз, когда печатаем, по новой копируется мой неправильный серийный номер, и с каждым следующим символом по новой копируется правильный серийный номер. Как только введём 6 символов, то установим на них BPM (помните, в предполагаемом серийном номере как раз 6 символов? – прим. пер.).

![](/files/az7JEAQhx4489urtGxbT)

Останавливаемся прямо на сравнении.

![](/files/wRPS2EtvJxmSLbT8h06M)

Тут видим, что ESI и EDI указывают на неправильный и правильный серийные номера.

![](/files/eAb3bHIBO41dTDRpiA1H)

Они сравниваются по четыре байта за оборот цикла. Проверим, является ли найденный серийник действительно верным.

![](/files/e0uzQf7SZ3122bVU8Nbd)

*(Сообщение гласит: "Поздравляю, победитель!" - прим. пер.)*

Видим, что не смотря на то, что это сложный крэкми, можно поймать точный момент, когда происходит сравнение, для чего нужно отслеживать местоположение неправильного серийного номера и ставить на него BPM.

Есть и другая возможность. Видим, что в памяти появляются 4 байта неправильного серийного номера.

![](/files/FHC8spplnlaip5YeONVW)

Он же, но уже из 5-ти первых байтов, чуть ниже.

![](/files/J5PPe1gBskpc3tfDOYZW)

Соответственно, можем установить BPM ON WRITE на область, находящуюся ниже, где будет записан следующий символ.

![](/files/CCEl2yliIfNPn7pMAdzV)

Отметим место, куда будет помещён следующий символ, а затем делаем RUN.

![](/files/YCIR1499LPA4l0bbgHo9)

Здесь записываю наиболее возможный серийный номер.

![](/files/jQi8fO0WZpawYJ4NzshA)

Делаем RUN.

![](/files/gNxQypAqsCeoOZL7ekdS)

И далее программа останавливается на том месте, где копируется неправильный серийный номер, и прежде, чем это произойдёт, можем установить на него BPM ON ACCESS, а затем выполнить RUN и снова остановиться точно на сравнении.

![](/files/fcC2hkQD8Qn2cr8HYUmW)

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

Ладно, оставляю домашнее упражнение – крэкми CrueHead’а 2 [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/blob/master/.gitbook/assets/files/18/CRACKME2.7z), а со следующей главы мы переходим к новой теме.

\[C] Рикардо Нарваха, пер. Aquila


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://backoftut.gitbook.io/intro-cracking-with-ollydbg/ch-18.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
