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

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

AnGel

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

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
В этой главе продолжаем изучать методы, которые мы пытаемся применить, когда всё начинает идти не так, как мы ожидали. В этой главе для этих целей нам послужить прекрасный
Пожалуйста, Вход или Регистрация для просмотра содержимого URL-адресов!
, который называется PATRICK.exe. Оно довольно мощное, и думаю, что прежде, чем углубляться в более сложные упаковщики, необходимо научиться этим альтернативным методом, включая те, о которых я рассказываю, но они не срабатывают, так как во многих случая нам придётся подстраиваться, адаптироваться и искать брешь среди лабиринта защиты, воздвигнутого программой, как, например, с этим крэкми, который мы собираемся распаковать.

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

Хорошо, открываем наш OllyDbg, как обычно используем знакомый нам модифицированный OllyDbg, замаскированный плагинами (патч №4).

Согласно автору, целью является не только распаковть крэкми, но и заставить его запуститься без DLL защиты, которую мы видим рядом с exe-файлом.

f06adfac6b3100e8ff4ff6d667c06cee.png

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

Ок, запускаем крэкми в патче №4.

9794d846f2e097ccb012521367608b3a.png

Видим, что выполнение прекращается ещё до прибытия в точку входа.

78d10b609c8de4249bdfb8f3836cee1b.png

Хорошо, посмотрим, как изменить, что OllyDbg останавливается до точки входа, то есть на системной точке останова, которая находится немного раньше, в которой система может остановиться немного раньше точки останова.

Для этого в настройках OllyDbg меняем в DEBUGGING OPTIONS-EVENTS.

3d0b4a808fa17e7006c45da00c190160.png

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

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

В любом случае, хорошо знать, что все DLL запускаются раньше прибытия в точку входа. Те, через которые проходит выполнение – это нормальные библиотеки и на нас не влияют, и поскольку OllyDbg в них не останавливается, то нам они особенно не интересны. Но посмотрим в программу.

Идём в заголовок с помощью GOTO EXPRESSION-400000.

60cf0c1edd93a369c1890fcd24bb9bf9.png

ffc9eae40c8e28f13161238bfb269f32.png

Меняем режим на SPECIAL- PE HEADER.

f608b010edc646e73dea948aa2207f3e.png

e804a0bc51fd4f33f9af88f6c5748de3.png

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

4a13859b6f734d7e2a9591b7b65bb574.png

Как мы знаем, это указатель на IMPORT TABLE или IT (не путайте с IMPORT ADDRESS TABLE, которая IAT, к сожалению, это делают довольно многие, хе-хе).

Ок, как мы уже видении, если пойдём сюда в 6F3C + база образа (400000), то увидим IT.

20f8a893ef4661fcc4521733816d7752.png

Выходим из специального режима.

b38ba4cdde597911ae0c2b1664981889.png

Если помним, первые пять DWORD’ов соответствуют первой DLL, следующие пять – второй, и так в порядке, в котором они загружаются в IAT.

Чтобы узнать имя первой DLL, нужен 4-ый DWORD, который является указателем на имя, то есть по адресу 407712e будет находится имя первой DLL, загружаемой в IAT. Посмотрим, что это за библиотека.

fde23b203c16efc8e22803dd465cb72c.png

Там находится WINMM.dll – это первая DLL. Но запускается ли она раньше прибытия в точку входа, в которой останавливается OllyDbg?

Открываем её и то место, где сработал SYSTEM BREAKPOINT.

837696d2cbd543ad0317aeffcffde08a.png

46843fec0a875485ebe74c78ddec4363.png

Останавливаемся здесь. Теперь знаем, что этот крэкми не доходит до EP, потому что завершается раньше в какой-то из DLL, который загружаются до неё. Это, не иначе как, происходит в библиотеке, прилагающейся к крэкми, но всё равно посмотрим, какие библиотеки запускаются раньше OEP, так что идём в карту памяти M и устанавливаем BPM ON ACCESS на секцию CODE вышеупомянутой DLL.

1953ae887eedb4085f34fe3a3a181772.png

fba75ddcedb58409ba95e60e32827995.png

Ок, устанавливаем точку останова сюда, чтобы посмотреть, сработает ли она, делаем RUN несколько раз и смотрим в низ OllyDbg, фиксируя, происходит ли выполнение или чтение/запись. Продолжаем нажимать RUN.

71ffe3f7fb8709e6a5f42110eabf6b2d.png .

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

09b363ab5cde018c0ce337d7d19955df.png

Останавливаемся здесь, когда начинается выполнение DLL.

211ae48ebddba23794a8401407e29920.png

Это значит, что ничего странного в том, что эти DLL выполняются, нет. Теперь повторим это способ, но с DLL, которую хотим исследовать. Пеерзапустим OllyDbg и когда остановимся, то идём в M и устанавливаем BPM ON ACCESS на секцию кода в AntidebugDll.dll.

c88aa4b8f12347cdd34a3da44c3d4c98.png

Делаем RUN и останавливаемся на выполнении DLL.

632df8db3df6821bbf371e0964380104.png

97d16bdf54be791ea3b0ee9e549aa0af.png

Хе-хе, тут начинаются проблемы.

Нам нужно, чтобы программа работала под OllyDbg, поэтому прежде всего посмотрим кое-что.

9191ffd060a6eb6c52f42f7785e32a9b.png

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

cfcc3e0992bdb8b639e4d7d2c5d3ea67.png

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

То, из-под какого процесса он запустился, крэкми узнаёт с помощью API-функции Process32Next, так что устанавливаем BP на него и смотрим.

1072806f7f21af6b30d4935bde8e1afa.png

Делаем RUN.

92c1ae28ea41324fb9f01a29306b9d9c.png

Здесь у нас результат работы функции, на моей машине он равен 12EEC8, и это адрес на отчёт.

f31b681a9e02e641f0b2667f42d63915.png

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

d440af0836736b1ff8378d443535e04e.png

Первый процесс здесь имеет PID равный нулю, и если глянем в WINAPI32:

e4f8f844f116a1b67273599c21c77a89.png

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

9a3b77284aa1f5182bd52c240c947807.png

Здесь видим, что 3-ий DWORD – это PID изучаемого процесса, а 7-ой – это PID процесса, который его запустил, в данном случае оба равны нулю, то есть оба были запущенны системой.

0ba269860d16081c17e02ede1198003d.png

Розовым выделен PID процесса и зелёным – кто его запустил. Ничего особенного здесь нет, делаем RUN заново.

3469abcb26debc8082fd401d40a3fb99.png

6d28ca7d39672d07a4e71db6104da36e.png

Эй, уже прекратила работу, но только изучая системный процесс, определить в чём причина закрытия нельзя. Попробуем отключить защиту HIDEOD, чтобы не возникали никакие конфликты. Снимаем в HIDEOD галочку, относящуюся к Process32Next и повторяем:

6dab3ba8eb83735d82e0a34229476775.png

Теперь при перезапуске не нужно останавливать BPM заново на секцию кода, потому что можно использовать BP на API-функцию.

06a3b7d40499d194baf54949f83d8f98.png

Теперь останавливаемся и смотри отчёт, в котором раньше было два PID’а равных нулю.

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

88f1f17db9a1bc9965badf5846740ab3.png

Ок, без галочки мы можем дойти до второго процесса в снимке процессов. Им является SYSTEM с PID’ом 4, который отмечен розовым цветом. Этот процессом был запущен процессом с нулевым PID’ом, то есть предыдущим.

fa8e191391aeff3fdc29d7cda9a80ebc.png

Хорошо, нам будет удобнее снять BP с начала API-функции и установить его на её RET, чтобы точно узнать, когда возвращается отчёт PATRICK’а при его завершении, и изменить его до того, как программа его прочтёт.

df0c8620d7fc49136e7ab37088e5316e.png

Теперь подолжим до того, как в PATRICK.exe появится отчёт.

684488bc132cb642817ef7f7c5c1daff.png

Здесь видим PID patrick’а, который равен AE4, и он был запущен процессом с PID’ом 8AC. Смотрим в PUPE, вспоминаем, что если перезапускали крэкми, то нужно обновить информацию в этой утилите, так что нажимаем кнопку “Actualizar”.

736223930bb06121eaff25b8399ba8db.png

Patrick с PID’ом AE4 был запущен parcheado4 с PID’ом 8AC.

Вот истинная причина, почему крэкми, запущенный не из-под EXPLORER.exe завершает работу. Устанавливаем BPM ON ACCESS на PID parcheado 4, чтобы узнать, где происходит сравнение.

6b70448629823c9d39c1a46213098af4.png

Делаем RUN и останавливаемся здесь.

0295f7c6898c4404b420ab31240b3685.png

Где считывается PID и сохраняется в другое место. Смотрим, куда имеет, чтобы можно было установить туда HBP ON ACCESS.

335382f48f7b8cf0f759ca6be12a0a5d.png

Нажимаем F7, чтобы сохранить по другому адресу.

e3bf638b36fa058af68e4affa77160a4.png

Так что установим HBP ON ACCESS туда и будем наблюдать за тем, когда там произойдёт чтение.

719c03ac4b163563b68e08165b9d6ee9.png

Если нажмём RUN, то увидим, что начальное значение отчёта стирается, но сохраняется куда-то, а куда именно мы должны выяснить с помощью HBP.

2f2d303aaac0dad5622e7e24f454625f.png

По нажатию на F7 останавливаемся на BPM ON WRITE, где оно стирается, что означает, что нам здесь BPM уже не нужен, так как уникальное значение защищается HBP в другом месте. Снимаем BPM.

a11a1e8515e9d03bf3d0a2c8eb1e8a03.png

Делаем снова RUN и доходим до сравнения – здесь сравнивается 08AC, что является PID’ом parcheado4 или программы, которая запустила крэкми, и сравнивается он с C7C.

5b0a945784625a1d338b4de38d71fab8.png

Как и можно было предположить, это PID Explorer’а.

622b676fdd32736f7cbb18ff02263c69.png

Видим, что если PID’ы запустившей крэкми программы и explorer’а равны, то происходит переход, чтобы обойти ExitProcess, а если различны, то перехода не проиходит и крэкми завершает выполнение. Проблема в том, что если изменить DLL и сохранить эти изменения, то в ней есть другие проверки, из-за которых она не запустится. Так что лучшее, что мы можем сделать, чтобы не менять ничего – это снять предыдущий HBP и установить HBP ON EXECUTION на эту строку со сравнением.

43cf2314723fb012c5d8b20d3d4a53e7.png

Таким образом, каждый раз, когда будем доходить до сравнения здесь, сможем вручную изменить PID parcheado 4 на PID explorer’а, чтобы они были равны и не было проблем.

На самом деле будет более удобным установить его строку, предшествующую сравнению, так как именно там считывается PID parcheado 4 и помещается в EAX.

afc1901f4a6a4a845499d7f827b30776.png

Теперь перезапускаем и смотрим, можем ли мы напрямую отредактировать PID без того, чтобы устанавливать Process32Nex и проходить через API-функции одну за другой. Стираем точки останова и перезапускаем.

49b0e210ef454ea4b05e8ae7a3900408.png

Останавливаемся здесь, и у нас есть информация, где надо редактировать. На моей машине это 12eeb8 – идём туда и меняем PID 8AC на C7C.

8da27ea6aba93c69798178e659aec6b0.png

Если теперь нажмём F7, то раз оба PID’а равны – произойдёт переход, и программа продожит своё выполнение.

8857be3768747b334b44e090f1442026.png

Это только первый из трюков, которые нам необходимо обойти. С помощью установленного HBP это легко сделав, заменив здесь PID и продолжив выполнение.

552bdf6e2def458c1074bd6c07c9a8a5.png

Немного оттрасировав отсюда, видим, что теперь крэкми хочет сделать снимок процесса с PID’ом C7C (на моей машине), чтобы убедиться, что это эксплорер, проверив другие его характеристики. Поскольку C7C на самом деле является эксплорером, то ничего странного он не замечается. Этот приём предназначается для противодействия попыткам переименовать другую программу в EXPLORER.exe, чтобы запустить из-под неё крэкми.

6b46bda66970a85d7188894c860d711b.png

И если ещё немного оттрасируем, то увидим Module32First, которая служит для проверки модуля процесса.

0426b8fe359223d61fcbd6e8edc16e4c.png

Ок, здесь у нас отчёт, в данном случае – это информация о модулях. Точно мы не знаем, что проверяется, но так как ищется информация об explorer.exe, то знаем, что всё верно. Здесь мы видим данные о первом модуле, которым является сам исполняемый файл.

87cfb5f001c17a631a3b73b0cb2eef8f.png

Самые важные данные следующие: роэовым выделен идентификатор 01, который имеет значение только внутри снимка и идентифицирует модули внутри процесса. Этот внутренний номер в снимке, который не слишком важен. Затем зелёным отмечен PID процесса, которому принадлежит модуль, а потом голубым цветом – адрес базы модуля, который в моём случае равен 1000000, то есть это база образа данного модуля. Жёлтым цветом – размер модуля. Кроме того, видим, что показывается имя модуля, а ниже идёт путь к нему.

eefc791bede144408801f0aa2478f2c4.png

Хорошо, это даёт нам достаточно информации, так что посмотрим, что мы с этим сможем сделать.

fa851e1df45de279d70e01f57c5ea8fd.png

Оттрасировав немного, видим, что считывается C7C и сравнивается, что находится в этом отчёте, чтобы убедиться, что модули также относятся к explorer.exe.

76ef72bc64e8a96ee68c8111a088015b.png

Продолжаем шаг за шагом.

43dbd46fc14a5f43577a746d7dbe63f0.png

Здесь видим обращение к GetWindowsDirectory. Эта функция возвращает путь, по которому находится директория Windows, то есть куда установлена система, и explorer.exe всегда должен находится в ней, так что, как мы видим, путь из отчёта сравнивается с тем, что возвращает API-функция.

749b36b8cad307efe9b51608d75a8aed.png

Смотрим в буфере, куда сохраняется путь.

dfad0902254497edfaef8ab0483b51e6.png

Сохраняется сюда, так что он готов для сравнения с путём в отчёте. В нашем случае проблем не будет, потому что в отчёте содержится путь до explorer.exe, так что спокойно продолжаем.

22e1f1554b8428f0fde611af1b4c437f.png

Видим, что чуть ниже к «C:/WINDOWS» добавляется «/», а затем «explorer.exe», чтобы можно было осуществить сравнение.

497ae09dac6ba8b5583e740f4e6ea7c7.png

Здесь читаем и доформировываем путь.

c912719e68eaf6c97496dead56e5443c.png

Хех, прекрасно. Посмотрим, что тут делается.

4056575e6ebd83926302b43125acee17.png

И подходим к сравнению. Здесь начинается считывание пути из отчёта.

0aecb294759021fb7ce7a74d6a567791.png

Доходим до CharUpperBuffA.

Эта API-функция преобразует строку, которая находится в BUFFER, в верхний регистр

65db194a95e3f966ceec4a3c3638e297.png

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

74391c282ccc30678016b077547e2e3e.png

Доходим до CALL'а, который сравнивает обе строки, очевидно, что на выходе будет ноль в EAX. Ноль или единица означают, что строки равны/не равны соответственно.

fb54c73e3fe8f11eaca92001dc0ddaed.png

Здесь видим строку, где стравниваются оба пути, так что если кто-то переименует OllyDbg в explorer.exe, то он должен запускать отладчик из директории WINDOWS, куда установлена система, и проблема заключается в том, что там находится настоящий запущенный EXPLORER.exe, так что с этим методом могут возникнуть сложности.

Продолжаем и проходим через этот CALL с помощью F8.

908998d38096cd542c02e444eaf8c57c.png

Видим, что EAX содержит ноль, поэтому на JE происходит переход.

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

ac8282fcb6f311761cd23e3dad8a65e0.png

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

d6f68bd71ea8f818073974c9a226f9bc.png

В данном случае это ntdll.dll. Видим, что те же данные, что и в прошлом случае. Идентификатор 01, который используется для определения всех модулей одного процесса, затем PID процесса (равный в моём случае 0C7C) и другие данные, такие как база и размер.

c3cffbec5e0b704be7b8149fe81f6dc6.png

7164bc9ebbf416e7c027b867cd395fa3.png

Продолжается сравнение, принадлежат ли все модули explorer.exe. Этого парня сложно убедить!

b6f5eea0bd457210a5b06105dda83963.png

Уф, теперь GetWindowsDirectoryA.

9565bd8bf60081aed36a2cf5d4579806.png

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

601ade0ce54f97b70af5b86d610ab3f7.png

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

6c545a1e6cc5f9a46ccf73e89a6ca883.png

Добравшись туда, видим, что сравнивается путь к Эксплореру с путём к DLL. Они, естественно, не равны, так как системные библиотеки находятся в другой директории, так что они никоим образом не равны.

a21805be93aade1e3df0e6ed3c3ed57b.png

Поэтому после возвращения из вызова в EAX находится 1, так как они не равны и перехода не происходит.

fec6cf0ca8912694e043c04192e6b0e8.png

Продолжив, становится видна обфускация для запутывания кода.

05ff7f8f07a91fb1559b6226cbdd8765.png

Как видим, здесь в EAX помещается константа, которая затем сравнивается с другой, и они никогда не будут равны, поэтому переход JE не срабатывается. Затем идёт MOV EAX, XXXXX, помещающий в регистр адреса (отмечены красным), а следом за этим – JMP NEAR EAX, который совершает переход по этому адресу, конечно, если будем трассировать, то увидим весь код. Обфускация не может предотвратить того, что мы будем трассировать и найдём настоящий код. Если не будем трассировать, а хотим быстро просмотреть запутанный код, направляем курсор на один из отмеченных MOV’ов, делаем щелчок правой кнопкой мыши и выбираем FOLLOW INMEDIATE CONSTANT.

9f8f468b9e717591e959c9d2b777cec5.png

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

48e6a697204df9413e3ffcafc518ffea.png

Здесь всё ясно видно без запуска, и если хотим посмотреть на следующий MOV, находящийся ниже, то повторяем.

bedc52b28184f73bdfdbe2f784e03b64.png

5246e98724ceb28d37cae5ccb485b2b5.png

И видим обфусцированный код без необходимости его запускать.

Это информационный уровне, пока продолжаем трассировать.

54a5509952eaa81aecef8211e7322806.png

Продолжаем трассировать и видим, что игра с путями продолжается, в этот раз это SYSTEM32\NTDLL.DLL. Идём следом.

f5f3974b73947db7e7424970c137328d.png

Снова считывается имя EXPLORER.exe.

56aeecf68f3e3c3053f6ebfdee3cd2f5.png

Затем видим, что E из EXPLORER.exe сравнивается с N из NTDLL.DLL.

890b318afdffb6a99ba9a4d720b30eac.png

Затем идёт переход на ExitProcess, видим, что никакой проблемы нет и мы его минуем, так как очевидно, что эти два имени не равны, так что идём дальше.

e8ffa95eef1005836c95bc41c5a6e358.png

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

Но ладно, это прояснится по мере того, как продолжим трассировку, терпение.

Трассируем до сравнения.

10a3c9b38eb1dc691061f3f6d4a51289.png

d0a2b32d282cbd46cff98b88235e0869.png

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

Ладно, чтобы сэкономить на трассировке, устанавливаем HBP ON EXECUTION на CALL COMPARADOR, так нам удастся быстрее пройти через сравнения.

2a75a14ab863edb40e18f06a46143b41.png

В PUPE у нас также есть список модулей Explorer’а, поэтому можем пройти один за другим, пока не закончится сравнение каждого из них. В PUPE входим в CAJA DE HERRAMIENTAS (Коробка с инструментами), смотрим модули.

59b5520b7164d2e88010ba6bdaa8ce24.png

937ea4e170aff8b0dd5f79e7abc42cdf.png

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

4dcef4d0f402f871ea771a6d4aa3920f.png

Последним в моём случае идёт idle.dll.

933e32dd2d0dc7c4fc1d3b18d20a51d9.png

Так что нужно пройти все остальные, пока не встретим этот.

198c9ddbba59655757f860c38236ca37.png

Мы уже почти у цели.

da8a8d58097febf903920709afac13ac.png

Здесь прибываем в последний. Теперь можем продолжить трассировку, чтобы видеть, что происходит.

1beea94223088dc2d6e1f5082a92367d.png

Видим, что продолжаем проскакивать ExitProcess и снова идём в Module32Next.

74dd6ed7872675ee8fb1d22c90e8591a.png

Здесь считывается последний. Если видите, то изменился PID explorer’а, это потому что в середине туториала перегружал машину, и PID изменился, но всё идёт точно таким же образом, только PID другой.

dbee3a89fb69b3e6ad4e20fc79ae6da4.png

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

17582737232a46aff0af91e23c0b7012.png

Ок, похоже, что крэкми устал повторяться, и начинается что-то иное. Доходим до API-функции GetModuleFileNameA.

cefb158cd33fac264eeaad95cc95c1c9.png

С помощью которого получаем путь до крэкми.

b967c698abdc61c2390f97779eef500a.png

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

bc235e1c14eda4b69d1f20db6f91887a.png

Вот параметры функции.

73e65f623af31af2263ee4518652185a.png

Пройдя API-функцию с помощью F8, видим, что система предоставляет хэндл, равный 50, а также OllyDbg нам сообщает об “ERROR SUCCESS”, что на русский можно перевести как удачное создание мутекса, то есть успех.

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

97381e399b5970d7a327722192d767a5.png

Один был очевидно создан в начале части, которую мы не трассировали, но вот она:

8a1758f2fc29c3b843f81c7234198c1c.png

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

Как видим, после возврата из API-функции EAX содержит ноль, который в данном случае как раз и обозначает успешное выполнение.

de1c5e538babfab60570de6601ecb276.png

51a73963683e9e9bf035397a4523fb76.png

Здесь мы видим ловушку и предполагаем, что она называется WAIT. Первый из двух мутексов называется MY FIRST INSTANCE, и он решает, является ли этот процесс первым или вторым запущенным, и иногда вызывается WAIT, видим, что в этом случае в результате SUCCESS’а программа не идёт на ExitProcess, но в случае со вторым процессом, если здесь проверяется мутекс, а существует ранее запущенный процесс, то результат будет равен не нулю, а B7, что приведёт к завершению программы. Выполнение продолжится только, если это первый экземпляр крэкми. Пока что запомним, что если это первый экземпляр процесса, то мутекс будет равен SUCCESS, а если нет, то ERROR ALREADY EXISTS, и таким образом в большинстве случаев и выясняется, является ли этот экземпляр программы первым или нет.

Продолжаем дальше.

e8e4a2c15507d80886dae3e8e418a115.png

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

a91ab66b239a5a152609c42026124c09.png

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

Очевидно, что если это делается, когда запущенна программа, этот первый процесс создаёт второй и немедленно его закрывает, гораздо раньше, чем второй начнёт проверять все модули и дойдёт до проверки MUTEX WAIT.

То есть нажатие на F8 не поможет нам, так как другой процесс азкроется. Мы может сделать немногое, попробуем его заморозить, для чего поменяем параметр CreationFlags на 4.

16e07028345c808960d94614cd431e0c.png

Смотрим, что произойдёт.

Как видим, при запуске второй процесса было возвращено EAX=0, и это означает, что создать его было невозможно. Это озадачивает.

Устанавливаем HBP ON EXECUTION на вызов CreateProcessA, и идём пробовать, почему не создаётся второй процесс, то есть требуется два HBP, один раз, чтобы изменить PID parcheado 4 на PID эксплорера, а изменив его, а второй HBP здесь на CreateProcessA.

А, снова HideOD, возможно, что он каким-то образом меняет права доступа крэкми, не давая ему создать другой процесс.

На картинке показано, какие галочки убираем в HideOD. Теперь смотрим, создастся ли второй процесс.

a3db5e052500d4899e7b77c1ef05cb0e.png

Установив галочки указанным образом, проходим API-функцию с помощью F8, и в EAX помещается EAX=1, так что мы на правильном пути.

e9fed57d5962faea12054f5d3948cfdb.png

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

79497c6704d6e98008528e1eca7c2fd6.png

Посмотрим в Pupe.

12c23acb84dfcd41f75fd994b9b2e41d.png

У нас есть два созданных patrick.exe, и второй заморожен, хе-хе.

Теперь пойдёт сложная тема – как остановить и приаттачиться к процессу, так как видим, что проверяется всё, а если что-то находится, то программа завершает выполнение. Это сделать не слишком просто.

Попробуем следующий метод. Перезапускаем parcheado 4 и когда останавливаемся на системной точке останова, устанавливаем BPM ON ACCESS на секции кода antidebug.dl. Когда останавливаемся на её EP, смотрим это значение на нашей машине.

b19c6a6f10316e587265e80622aad9da.png

Здесь нам необходимо найти место, где останавливать выполнение второго процесса до того, как запустится DLL, но DLL ещё не загружена, можно сделать бесконечный цикл в этом же адресе, но во втором процессе, так что смотрим стек, чтобы выяснить, откуда попадаем в EP.

c102a2d101c50b8e6de0bc040ced4af3.png

Идём, посмотрим эту область.

767c014f1e8fca008a853f7ccaf7c80c.png

То есть этот вызов и есть тот, откуда совершается переход на точку входа DLL. Теперь здесь есть адреса, которые относятся к NTDLL.dll, той, которая запускается всегда, так что возвращаемся сюда, создаём замороженный процесс, и когда он заморожен, устанавливаем на этот вызов бесконечный цикл, чтобы когда он будет запущен снова, здесь было зациклено.

d6d4610d20ccf01e7f18fd39105468ac.png

Так что отмечаем адрес. На моей машине для цикла он 7с9111a4, оригинальные байты равны FF 55.

Снова доходим до CreateProcessA, помним, что до остановки на HBP ON EXECUTION надо изменить PID эксплорера, чтобы нас не выкинуло.

d5684fd5cb9965b29c5190ac2d348591.png

Меняем PID parcheado 4 на PID эксплорера, а затем доходим до CreateProcessA.

af386dc39cedcb0ad36bd8b90998e517.png

Заменяем 20 на 4 (CREATE_SUSPENDED).

Нажимаем F8, и успешно создаётся второй процесс.

39d009665f8d2d761a29b0fcdeab5732.png

Вот оба процесса в PUPE.

Теперь выше открываем тот, что второй и выбираем “PARCHEAR” (патчить).

fed72d76cc517c06ecd918218264afa6.png

f4b54291b7c598423730dc53c2786b5a.png

Пишем адрес, куда хотим добавить ЦИКЛ, и меняем оригинальные байты на EB FE, которые означают бесконечный цикл.

45c0a7617c5288daa6bbcd2889eabac1.png

Затем нажимаем PARCHEAR, и в нужном месте установлен ЦИКЛ. Теперь до того, как приаттачиться к процессу, нужно снять задержку с процесса, чтобы он запустился и был зациклен.

Для этого используем прекрасную утилиту ARAPUMK’а, которая называется ESTRICNINA.

fd0562ff4980193f7cd65cbfe43a4d5a.png

Хорошо, ищем по PID’у второй процесс, в данном случае вот он, и так как они здесь не по порядку, то нужно точно убедиться, какой из них является вторым. Делаем щелчок правой кнопкой мыши и выбираем “INFO THREADS”.

e9efda2dfa91c839646ef3e664421139.png

76aeb414e960b3e92f559e310ae60a55.png

И нажимаем “REANUDAR”.

Теперь замороженный процесс запустился и зациклился, так что может присоединиться к нему.

Для этого можно попробовать присоединиться напрямую с помощью функции attach отладчика, но когда я так делал, мне не отображались модули и не завершалось выполнение, может что-то с моим компьютером или с HideOD, поэтому используем следующий способ для присоединения. Установим PARCHEADO 4 как JIT, сделаем CTRL +ALT+DEL и выберем второй процесс patrick’а. Обратите внимание, что PID’ы не показываются, поэтому надо сделать так, чтобы отображалась колонка с ними.

f161bcfc4c90b1b60e790acd65b0576f.png

e60c23bdd8522825329f40f3b765cd81.png

Теперь PID’ы видны, плохо то, что эти PID’ы в десятеричной системе, но ладно, в PUPE просто посмотрим, какой из двух больше, чтобы найти второй процесс.

559a142273539dd4967dc3ae77cc337f.png

В моём случае у второго процесса PID больше, так что ищем самый высокий PID в списке процессов и выбираем DEPURAR («очистить»).

c90b96afbdb05c0bdce043d94b46cceb.png

Здесь остаётся запущенным, затем делаем паузу.

3c803075a2885fb7fc618fc0b8a4fd09.png

Похоже, что в OllyDbg ничего нет, но не пугайтесь, идём в T, то есть THREADS.

53c5ce9e4ff08a0085e4f4264067c9c8.png

И делаем двойной щелчок на одной из двух ветвей. Находимся в бесконечном цикле, созданном нами ранее. Сделаем на нём щёлчок и не находимся в цикле. Попробуем по-другому.

b78c1de2be81414914d3e4def1f292cb.png

Аа, находимся здесь, теперь посмотрим эту часть в дампе, чтобы выйти из ЦИКЛА.

a37bb96c545112f986733decd9bd6b24.png

Оригинальные байты равны FF 55. Восстановим их.

4f0605052f9f6a169a7425b772d1048c.png

Если присоединились нормально, то смотрим в окне E (для исполняемых файлов) какие уже загруженны. Если там пусто, то возможно, что не удалось подсоединиться.

1c61b571f89e7cb7594aa7bc0e09c5a4.png

Видим, что хотя даже нет перехода на DLL, поэтому видно, что несколько раз происходит остановка на одном и том же адресе, так что устанавливаем BP и делаем RUN.

a368bc5681d73b1ae5000146e6bd8a64.png

Каждый раз, когда происходит остановка, смотрим, не появилась ли antidebugdll.dll в списке модуле. Сейчас её видим, так что можем установить BPM ON ACCESS на её секцию кода.

ff16b66e8557e8314ddb396fcb324c73.png

Устанавливаем BP и делаем RUN.

ec5be66869230b5f6dd4e34bec52714f.png

И останавливаемся на точке входа DLL. Уф, какой дикий напряг знать, что ничего из этого не нужно для решения этого крэкми, хе-хе, но всё это является практикой, которая нужна для овладения мастерством.

Попробуем поставить BP CreateMutexA, чтобы понять, что там происходит с мутексами и к какому процессу всё это относится.

0a96181b6c7b14ef1115e11adde4ab93.png

И делаем RUN.

d783994edb306c5c5c320114bbaf8ac4.png

Видим, что останавились на создании мутекса “MY FIRST INSTANCE”, но это так как он уже был создан первым процессом, так что идём до RET.

8228314bf9eb107efe409dba826b8286.png

Здесь видим, что когда первый процесс создавал MUTEX, который не существовал, результатом было ERROR_SUCCESS, а значение было равно нулю. Здесь же результат равен ERROR_ALREADY_EXISTS, то есть “уже существует” и возвращаемое значение равно B7.

1c0e578f8ed0ed056b871dfa5c776ac7.png

Конечно, далее идёт API-функция, которая считывает последнюю ошибку, и после её срабатывания видим, что EAX = B7.

65acf307dbc864a37b86d17c0007946b.png

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

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

О нас

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

    Dark-Time 2015 - 2022

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

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

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