# Глава 21

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

Это крэкми buggers3 [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/21/buggers3.7z), в котором были сделаны некоторые изменения, чтобы можно было объяснить нахождение имени процесса с помощью других API-функций, использующихся в этом крэкми, и обнаружение OllyDbg по имени окна или его класса, которое также применяется здесь.

Откроем крэкми в оригинальном OllyDbg, не переименованном, потому что также будем изучать разновидность метода, применённого в 20-й главе, и поэтому необходимо, чтобы файл OllyDbg назывался ollydbg.exe. Тогда защита сработает, и мы сможем её изучить.

После того, как загрузили его в OllyDbg, настроим HideDebugger 1.23f [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/19/HideDebugger124.7z) против использования программой API-функции IsDebuggerPresent.

![](/files/-LmvTviKNIl81JBZiIVN)

Посмотрим текущую конфигурацию плагина HideDebugger:

![](/files/-LmvTviXcx5JagQtM3G6)

Пусть он защищает только от IsDebuggerPresent. Также откроем список процессов и убедимся, что используем не переименованный файл, то есть имя процесса ‘OLLYDBG.exe’.

![](/files/-LmvTvimD5Pdqeh8I0Nj)

Ок, возвращаемся к buggers3. Посмотрим, какие API-функции он использует.

![](/files/-LmvTvj00oq4-E6I7Be-)

![](/files/-LmvTvjEXXCht_-vF5_1)

Опа! Единственная функция в списке – это ExitProcess, всё остальное грузится через GetProcAddress, но и сама она в списке не присутствует.

![](/files/-LmvTvjPIOZ5gyru-5Gz)

Поставим BP, и что будет, если сделаем RUN?

![](/files/-LmvTvjZ77QNI-ZFfc9l)

Видим загружающиеся API-функции, конечно, если находим такую, что нам интересна, идём до RET, чтобы узнать её адрес, и также можем сделать BP EAX, так как именно в EAX будет находится возвращаемый GetProcAddress адрес.

В данном случае ничего интересного нет, поэтому продолжаем, нажав F9.

![](/files/-LmvTvjigfFRhj6Zcbsz)

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

Ок, делаем EXECUTE TILL RETURN, чтобы дойти до RET.

![](/files/-LmvTvjrC__Itwvsvole)

![](/files/-LmvTvk07NQC3jtrMRyI)

Доходим до RET, и конечно, в EAX находится адрес загружаемой API-функции на моей машине, в данном случае это CreateToolhelp32SnapShot. Чтобы узнать, когда эта функция используется, установим точку останова с помощью BP EAX.

![](/files/-LmvTvkBESg0WRiCsLiL)

Здесь осталось установить BP на API-функцию.

![](/files/-LmvTvkNWj3OwsEI7k_x)

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

![](/files/-LmvTvkZlbGrgX9X38Fg)

Хорошо, уже знаем, чем это рискованно – для того, чтобы принудительного завершить процесс нужно получить логический номер (о чём мы говорили в главе 20), а это делается с помощью OpenProcess, так что дойдём до RET и установим BP EAX также и на эту функцию.

![](/files/-LmvTvkkOG_2SMgR_6-k)

Другая подозреваемая в убийстве процессов, хе-хе, пока что таким же образом установим на неё и её сестрёнку Process32Next.

![](/files/-LmvTvks6TxJobBxtdY6)

Дальше идёт TerminateProcess.

![](/files/-LmvTvl-NR-DTNt5RLxS)

Мы уже знаем, что эта функция закрывает OllyDbg. Пока что не будем устанавливать BP, но эта функция всегда является кандидатом на точку останова, хе-хе.

![](/files/-LmvTvl96VxdWlpvLw1r)

Другая преступница, хе-хе, устанавливаем на неё BP вышеописанном способом.

В следующий раз мы останавливаемся на API-функции CreateToolhelp32SnapShot.

![](/files/-LmvTvlI3Z2O6Xn1RWHu)

Стек:

![](/files/-LmvTvlRbYeFpBpdjuQ9)

Посмотрим описание этой функции.

![](/files/-LmvTvl_AP74nVMkD1TK)

То есть эта функция делает "фотографию" (моментальный снимок) процессов, которые запущены на машине, но возвращается нам только логический номер, и в параметрах нет никакого буфера, где должен быть сохранён список процессов. Выполняем до RET.

![](/files/-LmvTvlo7lfYKJbXR67j)

![](/files/-LmvTvm--tvYxpDfgX2u)

И в EAX получаем логический номер.

![](/files/-LmvTvmCeI0UruP6kCIM)

Который в моём случае равен 2C. Мы можем посмотреть информацию о нём с помощью Олли.

![](/files/-LmvTvmNNvrK92VzwbMi)

Нажмём кнопку H, что откроет окно логических номеров.

![](/files/-LmvTvmZ_lDzU8IJMPPw)

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

![](/files/-LmvTvmgIvJHj0E7B30v)

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

![](/files/-LmvTvmpYwm3Hq7gZFjT)

Ок, вот описание этой функции.

![](/files/-LmvTvmxSt3A1XzyPKyH)

Здесь говорится, что функция получает информацию о первом процессе, записанном в моментальном снимке, чей логический номер передаётся в первом параметре (в моём случае это 2C). Вторым параметром является адрес буфера, куда собственно помещается информация.

![](/files/-LmvTvn5rZgt3_NXBP5G)

Эта API-функция возвращает информацию только о первом процессе в списке, а для остальных надо использовать Process32Next.

![](/files/-LmvTvnEfVTNDT-xqn2f)

Буфер, куда сохраняется информация о первом процессе, виден через DUMP, так что делаем "Execute till RET", чтобы она там появилась.

![](/files/-LmvTvnTpguE0eCzFPdi)

Видим имя первого процесса, которое всегда будет "SYSTEM PROCESS". Делаем RUN и продолжаем.

![](/files/-LmvTvndhZvzE8cnmvyy)

Ха-ха, а здесь другой трюк, использующий FindWindowA. Окно OllyDbg относится к одноимённому классу, так что можно искать отладчик по имени окна. В данном случае запрашивается класс окна, являющимся главным по отношению к текущему, которым, очевидно, является OllyDbg.

Класс окна можно узнать с помощью утилиты WinDowse [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/21/WindowseGREATIS5setup.7z).

Я знаю, что существуют плагины для OllyDbg, которые позволяют выяснить класс и другую информацию об окне, но, по правде говоря, эта программа предоставляет куда более подробные сведения, так что установим и запустим её.

![](/files/-LmvTvnpGl62KUX2BnHA)

Видим, что во вкладке "Window" выводится имя окна OllyDbg, а во вкладе "Class" - его класс.

![](/files/-LmvTvo0dQSI2c6juZzv)

Как видим это OllyDbg.

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

![](/files/-LmvTvoAEFG6MH1teOo8)

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

![](/files/-LmvTvoMWx6EoUYsIwSR)

Хорошо, доходим до RET в API-функции, чтобы посмотреть, вернёт ли она логический номер окна.

![](/files/-LmvTvoUEPRf4eXhzPHh)

![](/files/-LmvTvocyCG7Qjyn1pJ8)

Конечно, он совпадает с тем, который отображается в Windowse.

Ладно, трассируем дальше, чтобы посмотреть, что программа делает с окном.

![](/files/-LmvTvoktwFNrS_mEzty)

То есть, сравнивает полученный номер с нулём, и если он ему равен, то значит, нет окна с классом OllyDbg, а значит и такого процесса нет. Если же было возвращено значение отличное от нуля, то значит, существует окно с таким классом, и программа вызывает ExitProcess.

![](/files/-LmvTvou3K3lfNVhMK_e)

Переход сразу ведёт к выходу программ без отображения каких-либо сообщений.

![](/files/-LmvTvp5RsadcgC07Rwt)

То есть суть в том, что нам нужно, чтобы FindWindowA вернула в EAX ноль.

Ок, плагин HideDebugger 1.23f позволяет не делать это вручную. Откроем его настройки.

![](/files/-LmvTvpGyP1vx5_pS3YK)

Если отметим вторую опцию, то плагин станет защищать нас от обнаружения с помощью FindWindow и EnumWindows (это другая функция, с помощью которой можно узнать имя окна), но нам нужно научиться избегать этих функции вручную и понимать, как это работает, поэтому пока что галочку ставить не будем, так как надо будет перезапустить OllyDbg, чтобы это оказало необходимый эффект. Сделаем так, чтобы переход, который отправляет нас к функции ExitProcess, не был совершён, и выполнение программы продолжилось.

![](/files/-LmvTvpRuNluoTmL_bFo)

Кликаем два раза на флаге Z, меняем его значение на 1, после чего JNZ не должен совершить переход.

![](/files/-LmvTvpc5ZoHtVdZJEIz)

И правда, JNZ не срабатывает.

![](/files/-LmvTvpo7kUD7-_J_ddL)

И доходим до JMP, перепрыгивающего через вызов ExitProcess.

![](/files/-LmvTvpzOi0IeZydw_DR)

Ок, продолжаем, мы изучили как предотвратить приём с FindWindowA, а теперь продолжим изучать метод, использующий имена процессов. Делаем RUN.

![](/files/-LmvTvqAdnnmsC-v2qT0)

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

Делаем EXECUTE TILL RETURN и смотрим, что было сохранено.

![](/files/-LmvTvqHmmVl16T1lYs5)

Здесь находится имя "System" и его PID, равный 4. Посмотрим список процессов.

![](/files/-LmvTvqPdiOZqSrzuvxE)

Здесь видим, что программа делает с каждым процессом. Трассируем.

![](/files/-LmvTvqY00uHGiHQT8uO)

Видим, что здесь вызывается API-функция lstrcmpA, с помощью которой сравнивается строка "System", являющейся именем процесса, с "buggers3.exe", т.е. именем процесса самого крэкми. Если они равны, то вызывается MessageBoxA, сообщающий "NOT DEBUGGED". Но в данном случае мы сюда не попадём, так что продолжаем трассировать.

![](/files/-LmvTvqhD9Zx2rsJ4IaY)

Если строки не равны, то результатом сравнения является FFFFFFFF.

![](/files/-LmvTvqq1SL7wZqquTq8)

И так как это не ноль, то переходим в 40119f.

![](/files/-LmvTvr1mdeDunGzAcUr)

Здесь видим насыщенную действием часть программы: сравнивается имя первого процесса с "OLLYDBG.EXE", и если они равны, тогда результатом является ноль и перехода не происходит, в следствии чего вызывается OpenProcess, чтобы узнать логический номер процесса, а потом – TerminateProcess, закрывающий его, как это мы уже видели в главе 20-ой.

![](/files/-LmvTvr9QmgjQKYL5BzJ)

Видим, что первый процесс не является OllyDbg.exe, поэтому переходим на Process32Next, чтобы найти второй процесс.

![](/files/-LmvTvrLI2209aThpMaE)

![](/files/-LmvTvrW7G8XJ_gufn3Y)

В то же место сохраняется имя второго процесса. Делаем EXECUTE TILL RETURN.

![](/files/-LmvTvrhTuRQuVTZGcQa)

Второй процесс – это smss.exe, чей PID равен 026C. Заглянем в список процессов.

![](/files/-LmvTvrsL0NNn7byweig)

Вот PID, равный 620 в десятеричной системе, то есть 026C в шестнадцатеричной.

Хорошо, похоже, что все выполняющиеся процессы сравниваются один за другим c "OLLYDBG.EXE".

![](/files/-LmvTvs0A66O2IRQGaU7)

И каждый раз условный переход будет переносить нас на 4011B1, до тех пор, пока не встретиться процесс OLLYDBG.exe. Тогда перехода не произойдёт и Олли будет закрыта, так что если мы заменим JNZ на JMP, то избежим этого.

![](/files/-LmvTvs9z-DVDP5GfsrY)

Теперь убираем все точки останова и делаем RUN.

![](/files/-LmvTvsKeaCrqU7Nl6UF)

Таким образом, защита была побеждена. Сейчас мы уже знаем, что плагин HideDebugger позволяет спрятать окно OllyDbg от обнаружения с помощью FindWindowA. Также можно попробовать избежать обнаружения процесса и выполнить программу, используя упомянутый ранее способ переименования OllyDbg в PIRULO.exe.

Откроем PIRULO.exe.

![](/files/-LmvTvsUct-wahMDfTPk)

Отметим галочкой опцию, включающей защиту от FindWindowA, и нажмём SAVE.

![](/files/-LmvTvsgw7XDkPvskagM)

Потом перезапустим OllyDbg.

![](/files/-LmvTvsrK8jcYkfYkMb0)

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

![](/files/-LmvTvt1E7xRu94t7fj2)

Видим, что имя OLLYDBG не отображается в заголовке окна, а класс?

![](/files/-LmvTvtCqEPO4fj1PxUH)

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

Утилита, которая должна помочь нам с тем, что не смог сделать плагин, называется Repair 0.6. Это патчер OllyDbg, и его можно скачать отсюда [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/21/repair0.6.7z).

Скачаем, а потом закроем OllyDbg и запустим патчер.

![](/files/-LmvTvtLvz6-qyIt5gIg)

![](/files/-LmvTvtXs3_4YkLFfOF3)

![](/files/-LmvTvtihndxyKDowNnP)

![](/files/-LmvTvtq6Apv2hBZCIj2)

Так что теперь у нас есть третий файл OllyDbg, который называется NVP11.exe. Заглянем в папку, где он находится.

![](/files/-LmvTvu-_GCpU_KnpkUc)

Запустим его и посмотрим, какой у него класс окна.

![](/files/-LmvTvuA1Ta9i8zCCtAf)

Видим, что класс окна – это "Nvp11", так же как и имя процесса, а значит, buggers3 теперь должен выполняться превосходно, не требуя каких-либо изменений в нём. Пробуем.

![](/files/-LmvTvuLDvaJBGgMPCeC)

Делаем RUN и…

![](/files/-LmvTvuVAdiNrtkg9k8l)

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

\[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-2/ch-21.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.
