> For the complete documentation index, see [llms.txt](https://backoftut.gitbook.io/intro-cracking-with-ollydbg-2/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://backoftut.gitbook.io/intro-cracking-with-ollydbg-2/ch-20.md).

# Глава 20

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

Если перейдём в DEBUGGING OPTIONS-SECURITY:

![](/files/-LmvTvbvruiBL5QZDxN9)

Здесь находится три галочки. Если мы их все отметим, то увидим, что установив BPX на API-функцию, и если переинициализируем OllyDbg (Restart), то BPX останутся установленными, что позволяет нам избежать повторение всего процесса каждый раз, когда мы делаем рестарт.

Строго говоря, я не знаю, как именно работает OllyDbg "внутри", но на практике достаточно просто отметить эти три галочки, чтобы установленные на API-функции BPX оставались установленными после перезапуска.

![](/files/-LmvTvc79KnJ9Oe3uzHS)

Именно так, как мне кажется, без особых проблем и хлопот, мы и начинаем изучение темы антиотладки по имени процесса.

Обнаружение OllyDbg по имени процесса

Запустив OllyDbg, мы можем посмотреть список процессов с помощью CTRL + ALT + SUPR.

![](/files/-LmvTvcMCHCDJZ_9pXAt)

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

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

Приложенный к статье крэкми называется DAXXOR [\[ссылка\]](https://github.com/yutewiyof/intro-cracking-with-ollydbg/tree/3679d233f4d394747f712e9b6b09bc9c2a3cad80/.gitbook/assets/files/20/daxxor.7z). Если запустим его и OllyDbg по отдельности, то увидим, что крэкми запускается, но закрывает отладчик, а если загрузим программу в OllyDbg, то закроются оба.

Изучим, как это происходит. Откроем крэкми в OllyDbg.

![](/files/-LmvTvccFmWfq9IH-OJT)

Оказавшись в точке входа, посмотрим, какие API-функции используются.

![](/files/-LmvTvcki1OKF68VJbeP)

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

Почти в каждом таком случае, когда программа не запакована, как здесь, используется API-функция GetProcAddress.

![](/files/-LmvTvcsEg-tlEiqzwDF)

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

![](/files/-LmvTvcznIXXBSR0v-Ea)

И делаем RUN.

![](/files/-LmvTvd861TSiKlWVd0z)

Каждый раз, останавливаясь на ней, видим, что именно запрашивается, в данном случае первой запрашивается функция \_\_CPPdebugHook, не связанная с защитой, которую мы изучаем, поэтому снова жмём RUN.

![](/files/-LmvTvdHwHYu_V995k8H)

Таким образом, с помощью F9 доходим до API-функций, относящихся к защите. Здесь видим, что используется функция EnumProcesses, так что после того, как дойдём до RET в GetProcAddress, в EAX будет возвращен адрес функции, действительный для конкретной машины, и туда мы установим BPX, после чего выполним RET с помощью EXECUTE TILL RETURN.

![](/files/-LmvTvdUnhbE_2EQ5FCx)

Здесь в EAX возвращается адрес указанной функции для конкретной машины, в моём случае это 76BB3A9A (он может отличаться у вас).

![](/files/-LmvTvdb84bUIuMP8BBb)

С другой стороны, видим, что OllyDbg не обнаружила эту API-функцию, и её нет в списке NAMES, поэтому мы не можем установить BP напрямую по имени функции, и поэтому устанавливаем точку останова на адрес.

![](/files/-LmvTvdnXt9iuyFVOxVs)

Вот она установилась.

![](/files/-LmvTvdvfx1AvLb0OGrg)

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

![](/files/-LmvTve0TkbfGxYHNWbI)

Хм, перебираются модули процесса, дойдём до RET и установим BPX на адрес, который будет возвращён в EAX.

Чтобы много не печатать, то находясь на RET, можем сделать так:

![](/files/-LmvTve6VYCUL_UhEnzs)

Так я устанавливаю BPX на все API-функции, когда нахожусь на RET.

![](/files/-LmvTveCI67FffJE6HTL)

Ещё одна подозрительная API-фукнция, устанавливаем на неё BP таким же образом, что и в прошлые разы, делаем и останавливаемся на EnumProcesses.

![](/files/-LmvTveJUv0ifSR71GyD)

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

![](/files/-LmvTvePIE6osTcjfVJZ)

![](/files/-LmvTveWKQIFiwoDJVmN)

![](/files/-LmvTveftueVNBwSXcIi)

Все эти функции, загруженные программой, не были увидены OllyDbg и не были отражены в списке, также она не даёт по ним какую-либо информацию.

Поищем в гугле, что это за функция "EnumProcess".

![](/files/-LmvTveowBTi1pQ2KthH)

Находим её на сайте Микрософта, адрес страницы:

<http://msdn2.microsoft.com/en-us/library/ms682629.aspx>

![](/files/-LmvTveynW-8nffSh7C0)

Хорошо, здесь говорится, что вышеупомянутая функция возвращает нам идентификатор или PID каждого запущенного процесса, ок, рассмотрим что такое этот PID, хе-хе.

Каждому запущенному процессу присвоен идентификатор – число, меняющееся каждый раз при запуске процесса. Посмотрим на список процессов.

![](/files/-LmvTvf7x1Iuy3eY7EyK)

Видим, что в данном случае OllyDbg присвоен PID 724 – в десятеричной системе счисления, так как программа просмотра процессов работает именно с ней. Переведём вышеуказанное число в шестнадцатиричную систему с помощью калькулятора Windows.

![](/files/-LmvTvfEJNHpOiwbUf-j)

Нажимаем на кнопку HEX, чтобы перейди в шестнадцатеричную систему.

![](/files/-LmvTvfJBkEqOcTNbgEt)

PID OllyDbg в шестнадцатеричной системе равен 2D4. Можем закрыть и запустить по новой OllyDbg, и увидим, что PID изменился. Каждый раз, когда процесс запускается заново – PID меняется.

Также нам не повезло с отображением параметров функции, так как для OllyDbg она не существует.

![](/files/-LmvTvfPEKhX8Ay05nUM)

Из страницы на сайте Микрософта, знаем, что у неё три параметра.

![](/files/-LmvTvfXSzyeDWUtSeKL)

То есть в 12EDE4 сохраняется список PID’ов всех процессов, запущенных на моей машине, делаем EXECUTE TILL RETURN, чтобы вернуться из API-функции и смотрим через DUMP, что там лежит.

![](/files/-LmvTvfehd3Gmbb7uasq)

Там находится список PID’ов, а среди них и PID OllyDbg, хнык, хнык.

Ставим здесь BPM ON ACCESS, чтобы посмотреть, где он используется.

![](/files/-LmvTvfkUVxnwwlt91Az)

Теперь делаем RUN.

![](/files/-LmvTvg-x74IRrJfVOFv)

Видим, что остановились там, где будет применена функция OpenProcess, которая проверяет, работает ли процесс, и если да, то возвращает его хэндл (логический номер).

Какая разница между PID и хэндлом? Это очень просто – PID – это общий идентификатор – на всей машине, в какой угодно программе PID OllyDbg остаётся одним и тем же, пока процесс не будет перезапущена, в моём случае это 2d4, а хэндл – это номер, который позволяет позволяет вашей программе управлять процессом и который будет отличаться в другой программе. Это своего рода заявка на контролирование процесса, без номера не сможете им управлять, а чтобы получить номер, нужно попросить систему, которая вернёт вам хэндл. Тогда сможете и управлять и подстроить какую-нибудь гадость, хе-хе.

Вот более подробное определение OpenProcess в WinApis32, у неё тоже много параметров, но нам они не интересны.

![](/files/-LmvTvg8O9cXRE9L-IXY)

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

Трассируем с помощью F8, пока не остановимся на API-функции.

![](/files/-LmvTvgFLfzHlxONp0_L)

В EAX возвращается логический номер OllyDbg, который в моём случае равен 58.

Тот же OllyDbg умеет показывать логические номера, с которыми программа работает в настоящее время, с помощью окна H.

![](/files/-LmvTvgNZvcuwiGF8ou8)

Видим, что здесь есть 58 и TYPE или тип является PROCESS, т.е. процесс, таким образом, у программы есть логический номер 58, действительный в процессе OllyDbg.

Если другой процесс использует EnumProcess, чтобы получить PID, то для OllyDbg, если она не будет перезапущена, он будет равен 2d4, а если потом попросить логический номер данного процесса, то он будет каким-нибудь другим, так как хэндлы для каждого процесса, их запрашивающих, уникальны.

В данном случае, опасность для OllyDbg заключается в том, что у программы уже есть логический номер, с которым она может делать всё, что хочет. Хотя она и не знает, что выполняется из под OllyDbg, она может проверить имя процесса, чтобы определить, не называется ли он OllyDbg, и очевидно, что для этого будут перебираться все PID’ы, полученные в списке процессов, поэтому бросаем всё и отправляемся туда, где это будет происходить, для чего установим BPM ON ACCESS на соответствующий PID.

Продолжаем трассировать с помощью F8.

![](/files/-LmvTvgVW0JI-n3Te2w0)

Дошли до ещё одной API-функции, которую от нас пытались скрыть, – EnumProcessModules. Посмотрим её описание на том же сайте, что и ранее.

![](/files/-LmvTvg_jEaxU0CiA9Td)

То есть будет проводиться поиск в исследуемом процессе, получаем список модулей, используемых им. Продолжаем трассировать с помощью F7.

![](/files/-LmvTvgfWfQJTnV5QyUE)

В стеке видим параметры:

![](/files/-LmvTvglbehnsVHHHe45)

Список хэндлов всех модулей сохранён по выделенному адресу, а первым параметром, как мы видим, является логический номер процесса OllyDbg.

Здесь нужно прояснить одну вещь: когда запрашиваем логические номера модулей, система возвращает нам адресную базу или откуда начинается указанный процесс в памяти. В данном случае нам было возвращёно 400000, так как именного отсюда начинается процесс OllyDbg.

![](/files/-LmvTvgqsofR_HOK0f0I)

Продолжаем трассировать и находим ещё одну API-функцию.

![](/files/-LmvTvgxwWx-v203LEEd)

GetModuleBaseNameA

![](/files/-LmvTvh6nzR6vNaXvZmX)

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

![](/files/-LmvTvhEAWl_NZkMxIIg)

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

![](/files/-LmvTvhPjK92UyfIm4Al)

58 – это логический номер OllyDbg, 400000 – это база главного модуля, а буфер располагается по адресу 12ECE0, так что смотрим эту область памяти через дамп.

![](/files/-LmvTvhYxU55uyvNmX7M)

Хе-хе, уже понятно, что эта операция будет проведена для каждого процесса, который запущен в машине, чтобы узнать, не является ли его именем ‘OLLYDBG.exe’.

![](/files/-LmvTvhg7Y66zEnfwGor)

Доходим до CloseHandle, где закрывается логический номер, то есть 58 исчезает из их списка.

![](/files/-LmvTvhq0EMOKaaY5i5H)

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

![](/files/-LmvTvhxQw7RIQ96JW-Q)

Дошли до CALL, входим в него, нажав F7.

![](/files/-LmvTvi2acXQjK7S1O2l)

![](/files/-LmvTvi8SRdlMPi9KpyE)

Здесь считывается первая буква "OLLYDBG" (4F) и помещается в стек с помощью PUSH, затем идёт новый CALL, в который мы также заходим.

Видим, что в этом вызове не происходит ничего особенно важного, поэтому выходим и оказываемся рядом со следующим CALL'ом.

![](/files/-LmvTviGiEPkoV5q3DDr)

Заходим в него.

![](/files/-LmvTviP4G1hfiy9UuFB)

![](/files/-LmvTviZANR21CMk1vfX)

Ах, где-то здесь сравнивается полученное имя процесса с ‘OLLYDBG.EXE’, и если они равны, то всё, капут.. хе-хе, сейчас они равны, посмотрим, что случится. Возвращаемся через RET.

![](/files/-LmvTviixWPGK1n283qg)

Если бы они не были равны, то EAX должен был бы отличаться от нуля, и был бы совершён переход, чего не происходит, если EAX равен нулю, как в данном случае.

![](/files/-LmvTviru5jbK8xdzvuZ)

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

![](/files/-LmvTvj-U8IDJmaqhb6N)

![](/files/-LmvTvjAxkoWqGY5Dkq_)

Если выполним с помощью F8.

![](/files/-LmvTvjI-Z3hznkpeBH7)

Система возвращает номер 58, так что продолжаем.

![](/files/-LmvTvjNCq0uoisdmOfw)

Как видим, API-функция TerminateProcess, которой передаётся логический номер 58, служит для того, чтобы убить OllyDbg.

![](/files/-LmvTvjTfr6QI5ztFJSM)

И по нажатию F8 – до свиданья, Олли. Всё закрывается. Вот так мы и исследовали, как работает обнаружение по имени.

Ладно, я слегка устал от роли убийцы, хе-хе, перезапускаем OllyDbg и устанавливаем BP на OpenProcess.

![](/files/-LmvTvjaWnNoZc2rIPIp)

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

![](/files/-LmvTvjhySp-G4Me3fd4)

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

![](/files/-LmvTvjo6AAwdQh63YEr)

Пока что просто отметьте все опции, чтобы программы перепрыгивала через все исключения, так как их очень много (для прохождения через них надо нажимать SHIFT+F9, а вышеуказанная конфигурация позволяет миновать их автоматически). Делаем RUN.

![](/files/-LmvTvjyFC5b0M0cBpcc)

И вот она выполняется без проблем, но вот ещё, что можно сделать:

![](/files/-LmvTvk7PRCon_SzpIDi)

Меняем JNZ на JMP, чтобы избежать выполнения кода защиты.

Программа запускается и показывает нам окно, которое исчезает после нажатия на TRY.

![](/files/-LmvTvkG7wTJC_WZRFAi)

Выскакивает сообщение об ошибке. Прекрасно, потому что это говорит о том, что защита против отладки была побеждена.

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

![](/files/-LmvTvkOoipaEnJfv20n)

Важно помнить, что переименованный файл необходимо держать в той же папке, что и исходный, во избежание проблем с плагинами.

![](/files/-LmvTvkXIvKvc-AvIsNH)

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

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