Взлом VMProtect защиты. Инлайн патчинг на примере программы Movienizer (Глава 3)

Обсудить статью на форуме


Массу свежих 2020 года крэкерских инструментов, видеоуроков и статей вы сможете найти на видеокурсе от нашего сайта. Подробнее здесь.

Из чего состоит этот туториал


Давайте немного поговорим о том, как построен этот туториал. Он состоит из 3 глав:
1. В первой главе даются общие подробности о самом протекторе, о его опциях и способах
защиты этим протектором. Также здесь рассматривается список литературы, который
желательно прочитать, если Вы хотите хорошо разобраться в распаковке этого протектора.
Во второй части первой главы мы познакомимся с собственноручно написанным
unpackme, узнаем о том, что он из себя представляет и как его "обезвредить".
Ссылка на главу: Взлом VMProtect защиты. Знакомство, подготовка крэкми (Глава 1)

2. Вторая глава туториала предназначена для самых маленьких :-) . Здесь мы попробуем
распаковать unpackme, но практически полностью автоматизируем эту работу с помощью
скрипта от LCF-AT . Поначалу я не хотел включать эту главу в туториал, но учитывая, что у
новичков возникает очень много вопросов по работе со скриптом, да и сам скрипт не
лишён недостатков, то всё-таки было решено показать, как работать с отладчиком и его
скриптовым языком. Так же попробуем разобраться, что делать, если файл не запускается
после распаковки. Опытные crackers могут пропустить эту главу.
Ссылка на главу: Взлом VMProtect защиты. Полная распаковка программы скриптом + доработка (Глава 2)

3. Третья глава, пожалуй, самая интересная. Она посвящена инлайн патчингу VMProtect. В
этой главе немного поговорим о теории инлайн патчинга VMProtect-а, попробуем
пропатчить наш unpackme, а также посмотрим, как немного можно ускорить этот процесс.
Вторая часть этой главы будет посвящена реальной коммерческой программе - Movienizer
6.3 . Здесь мы рассмотрим как можно пропатчить заблокированный ключ к программе, и
убрать онлайн проверку регистрации.
Ссылка на главу: Взлом VMProtect защиты. Инлайн патчинг на примере программы Movienizer (Глава 3)

В заключении хочу добавить, что все инструменты, а также программы, использующиеся в
качестве подопытных приложены к этому туториалу. Ссылка на архив (пароль: www.exelab.ru): Взлом VMProtect защиты.

Глава 3


Немного теории об инлайн патче VMProtect


А теперь, наконец-то десерт :-) . Инлайн патч придуман уже очень давно, и в некоторых случаях,
действительно спасает кучу времени. Лично я не очень жалую эту технику взлома программ,
потому как мне процесс распаковки доставляет куда больше удовольствия. Но в некоторых
случаях этот способ оказывается намного проще. Вместо того чтобы вылавливать разного рода
ошибки при запуске, намного легче пропатчить файл при исполнении. Конечно, тут нужно
учитывать количество пропатченного кода, потому как может быть действительно стоит
распаковать файл, но если нужно сделать всего несколько изменений, то инлайн это то, что
нужно.
Итак, для того, чтобы сделать инлайн патч VMProtect нам нужно понимать следующие вещи.
1) Место (или места, если их несколько) где нужно патчить;
2) Найти место, где протектор проверяет файл на наличие изменений;
3) Понять, как происходит проверка, и научиться её обходить. При этом придётся немного
потрейсить обфусцированный код VMProtect, чтобы понять, как он считывает хеши и
сравнивает их;
4) Найти в файле свободное место, и добавить туда наш патч. Если его нету, то необходимо
будет добавить дополнительную секцию в файл.
Скажу честно, со своим анпакми я намучился вдоволь :-) . Запаковал так, что сам инлайнил его
несколько дней! Честно говоря, не ожидал, что возникнет столько проблем, вроде бы инлайнил
несколько программ, но такого геморроя нигде не видел. А дело здесь в самой обычной упаковке
кода программы протектором. Вроде бы такая обыденная вещь, а столько проблем... Так, что для
себя я выбрал два направления:
1) Если код программы не сжат (а таких большинство, т.к. авторы боятся больших тормозов
при запуске), то патчим программу, как обычную, сохраняем изменения, ищем свободное
место в файле и там патчим CRC проверку. Всё, наслаждаемся. Пример такой программы
Вы увидите чуть ниже, когда будем патчить Movienizer .
2) Если код сжат, то готовимся к бою основательно. Добавляем секцию к нашему файлу
(размером, например 1000 байт), там патчим CRC проверку, изменяем атрибуты секции с
кодом и наконец, патчим сам файл. Изменение атрибутов секции связано с тем, что
загрузчик VMProtect-а при запуске выставляет этой секции атрибут "Только для чтения" и
естественно, если его не изменить на "Чтение и Запись", то при доступе к этой секции Вы
словите исключение. В принципе, логика автора протектора понятна - какая никакая, а
защита.
Забегая вперёд, немного расскажу, как протектор проверяет файл на наличие изменений. В
начале, для получения имени файла и полного пути запущенного приложения вызывается API
функция GetModuleFileName A\W . Затем для чтения файла вызывается CreateFile A\W . Для
получения размера файла вызывается GetFileSize . Хотя зачем получается размер файла, для меня


так и осталось загадкой. Интересно, что если размер файла равен или больше оригинала, то всё
нормально, но если размер меньше оригинала хоть на байт, то привет ExitProccess. Где здесь
логика? Функцией CreateFileMapping A\W создаётся неименованный (MapName = NULL) объект
для проецирования его в память. Причём создаётся он с атрибутом "Только для чтения".
MapViewOfFile размещает подготовленный объект в памяти и возвращает адрес, по которому
файл будет теперь доступен. Доступен он также "Только для чтения". Далее протектор мелкими
порциями считывает хеши кусков кода. Причём адреса идут не подряд, а в разброс. То есть
сначала может проверяться несколько кусков в секции кода, потом один кусок в секции
протектора, затем опять секция кода и т.д. Псевдо код может выглядеть примерно так:
If CRCCheck(адрес, размер_блока) = оригинальный_хеш then
begin
проверяем следующий блок
end
else
begin
File Corrupted!
Выход из программы
end;
После своих махинаций протектор вызывает UnmapViewOfFile для удаления файла из памяти, а
затем освобождает хендл с помощью CloseHandle .
Функция MapViewOfFile является для нас ключевой! Если мы поймаем момент, когда система
загрузит файл в память, то считай половина дела сделано. Сама функция расчёта хеша выглядит
так (после деобфускации):

Рисунок 42. Цикл расчёта хешей



Команда mov dword ptr [ebp], eax , сохраняет значение хеша. Это место является идеальным для
патча, т.к. хеш уже подготовлен, а в регистрах имеется вся необходимая для нас информация:


Итак, наш план такой. Находим место, где сохраняется хеш, прыгаем оттуда на наш патч,
подсовываем в eax верный хеш и прыгаем обратно. Вроде всё просто посмотрим, как это всё
обстоит на деле.


Инлайн патч Unpackme


Чтобы инлайн патч прошёл, как можно легче, нужно основательно подготовиться. Для начала
давайте посмотрим упакована ли секция с кодом. Для этого нажимаем Alt+M и выбираем секцию
с кодом:

Рисунок 43. Упакованная секция с кодом

Если бы код программы не был упакован, то нашему взору открылся бы "чистый" код. Обратите
внимание на секции .UPX0 и .UPX1 . Это секции самого протектора, их названия можно
произвольно менять при защите программы. В большинстве случаев названия секций авторы
программ не меняют, видимо лень :-) . Итак, видим, что код упакован, соответственно придётся
помучиться с доступом к этому коду. Со сжатием разобрались, будем создавать новую секцию.
Дальше нужно будет найти места, которые надо пропатчить. Я сейчас не буду дословно объяснять,
как я эти места нашёл (Вы же реверсер или кто? :-) ), покажу лишь, что это за места и как их
патчить. Как раз посмотрим, как НЕ НУЖНО защищать программы :-) . Самое смешное, что авторы
постоянно совершают при защите своих программ одни и те же ошибки. Как патчить код при
исполнении я надеюсь, Вы уже знаете.
1) Адреса 46CD44 и 469F30 . Здесь находится заблокированный ключ на моё имя (он
находится в файле Key.txt). Его нужно "разбанить", чтобы анпакми успешно
зарегистрировался с этим ключом:

Рисунок 44. Stolen Key

Код для патча этого места выглядит так:


MOV BYTE PTR [46CD44], 0
MOV BYTE PTR [469F30], 0
2) 46C81A - место для патчинга проверки CRC. После инлайн патчинга анпакми вы можете
зайти в меню Additional -> Valid Image CRC , и проверить образ программы на наличие
изменений. Многие авторы делают такие проверки примерно таким способом:
if CheckCRC = True then
continue;
В ассемблерном виде это выглядит вот так:

Рисунок 45. Проверка CRC в программе Unpackme

Первый Call на рисунке, не что иное, как процедура проверки. Опытные люди знают, для того
чтобы пройти эту проверку нужно вернуть программе значение 0 (ОК = 0; программа изменена =
1). Конечно лучше патчить саму проверку, но здесь нам достаточно поменять прыжок на
безусловный (JNZ на JMP). Код для патча такой:
MOV BYTE PTR [46C81A], 0EB
3) 0046C773 проверка виртуальной машины. Схема практически та же:

Рисунок 46. Проверка виртуальной среды



Здесь запатчим саму проверку, дабы убедиться, что VMProtect не такой уж и злой :-) . Заходим в
Call по адресу 0046С773 и видим:

Рисунок 47. Код проверки VM (VMware, VBox...)

Можно, конечно поисследовать обфусцированный код и найти саму проверку, но не проще ли
сделать так:

Рисунок 48. Патч проверки VM

Мне кажется наша проверка куда красивей, чем протектора :-) . Придумают же шароварщики....
Код для этого патча:
MOV DWORD PTR [4697E4], 90C300B0
4) Активация подменю Additional -> InlineMe (Mutation) . Выше, при распаковке анпакми мы
уже находили место, где нужно пропатчить для, того чтобы этот пункт активировался:

Рисунок 49. Активация подменю в обфусцированном коде

Обфусцированный код VMProtect даёт патчить без всяких последствий, поэтому просто нопим эти
прыжки:
MOV DWORD PTR [585B39], 90909090
MOV WORD PTR [585B3D], 9090
MOV DWORD PTR [585B44], 90909090
MOV WORD PTR [585B48], 9090
5) Последнее и самое сложное это активировать другое подменю Additional -> InlineMe
(VM) . Проверка на активацию этого подменю абсолютно такая же, как и предыдущего. Но
основная проблема здесь заключается в том, что просто так прыжки Вы не занопите, т.к.
эта проверка под ВМ, а там, как известно, сравнения происходят неявно. Так что нужно


думать как патчить. Покопавшись в самой ВМ я не нашёл способа для патча. Поэтому
предлагаю ход конём: учитывая, что предыдущая проверка должна быть идентичной
нашей, рипнем оттуда основной код и подставим его вместо ВМ:
Было так:

Рисунок 50. Старый код

Сделаем вот так:

Рисунок 51. Код после патча

Понимаю, что некрасиво и выглядит по ламерски, но к сожалению другого выхода пока не нашёл
? . Код патча:
MOV DWORD PTR [587D8A], 8BFC458B
MOV DWORD PTR [587D8E], 32C80
MOV DWORD PTR [587D92], E801B200
MOV DWORD PTR [587D96], FFEBF15A
MOV DWORD PTR [587D9A], EE4F11E9
MOV WORD PTR [587D9E], 90FF
MOV BYTE PTR [587DA0], 90
Подводим итоги. Имеем следующий код для инлайн патча:
// разблокировка ключа
MOV BYTE PTR [46CD44], 0
MOV BYTE PTR [469F30], 0
// CRC проверка образа программы
MOV BYTE PTR [46C81A], 0EB
// обнаружение виртуальных машин
MOV DWORD PTR [4697E4], 90C300B0
// активация подменю Additional -> InlineMe (Mutation)
MOV DWORD PTR [585B39], 90909090
MOV WORD PTR [585B3D], 9090
MOV DWORD PTR [585B44], 90909090
MOV WORD PTR [585B48], 9090
// активация подменю Additional -> InlineMe (VM)
MOV DWORD PTR [587D8A], 8BFC458B
MOV DWORD PTR [587D8E], 32C80


MOV DWORD PTR [587D92], E801B200
MOV DWORD PTR [587D96], FFEBF15A
MOV DWORD PTR [587D9A], EE4F11E9
MOV WORD PTR [587D9E], 90FF
MOV BYTE PTR [587DA0], 90
Заканчиваем подготовительные действия. Копируем файл Unpackme_vmp.exe и даём ему новое
название - Unpackme_Inline.exe . Добавляем, с помощью PETools к файлу дополнительную
секцию:

Рисунок 52. Добавление секции в файл

Вводим название секции, размер и выставляем Fill with 0x00 , чтобы секция была заполнена
нулями. С размером советую не экономить, т.к. в дальнейшем это может осложнить жизнь.
Нажимаем Add и всё, секция добавлена в файл. C этого момента при запуске наш файл будет
выдавать вот такое сообщение:

Рисунок 53. Обнаружение изменений

Говорит, что файл взломан или инфицирован, и никак больше работать не может! Учитывая, что
код программы упакован, то нам будет необходимо выставить ей нужные атрибуты. Как это
сделать я покажу чуть позже, а сейчас сделаем одну вещь, для того чтобы облегчить себе жизнь на
будущее.
Открываем наш файл в отладчике и переходим в самое начало созданной нами секции. У меня
она находится по адресу 00794000 :



Рисунок 54. Начало нашей секции

Наживаем ПКМ -> Binary Edit или Ctrl+E и в появившемся окне вводим:

Рисунок 55. Вводим название библиотеки и функцию

Не забудьте между названием библиотеки и названием функции вставить разделитель (00)! Это
"телодвижение" позднее понадобится нам для того, чтобы подгрузить VirtualProtect и изменить
атрибуты секции с кодом.
Ну и самое последнее: выделим некоторый диапазон адресов (например, с 00794101 по
00794302) и ПКМ -> Binary -> Fill with NOPs . Выделяем все изменения и сохраняем их ПКМ -> Copy
to executable -> Selection .
Всё вышеописанное мы проделывали лишь с одной целью: как можно больше сделать изменений
в тех местах, где мы будем патчить и писать код. В противном случае хеши будут меняться часто, и
Вы просто устанете их патчить.
Теперь ищем, где проверяются хеши. Грузим нашу программу в отладчик, в окне CommandBar
ставим брекпоинт на MapViewOfFile и нажимаем Enter (проверьте, чтобы не стояли другие
брекпоинты):

Рисунок 56. Брекпоинт на API функцию

Запускаем программу ( F9 ) и мы оказываемся тут:

Рисунок 57. Наша точка останова сработала



Убираем брекпоинт, проходим до конца функции ( Debug -> Execute till return или Ctrl+F9 ) и
смотрим регистры:

Рисунок 58. Окно регистров

В регистре EAX лежим адрес памяти, по которому система разместила образ нашей программы. У
меня он равен 00D00000 . У Вас он может быть такой же или отличаться.
Открываем карту памяти ( Alt+M ) и находим наш образ в памяти:

Рисунок 59. Наш образ в памяти

Ставим брекпоинт на память по этому адресу и запускаем программу ( F9 ):

Рисунок 60. Остановка в коде протектора

Мы остановились по адресу 0078C598. По-моему мы где-то уже видели команду XOR AL, BYTE PTR
[EDX] . Не помните? Я Вам напомню:

Рисунок 61. Расчёт хеша

Мы попали в самую середину расчёта хеша! По идеи сейчас должна быть команда inc edx
(увеличение адреса на единицу). Трейсим по F7 :



Рисунок 62. Следующая команда

Да, так и есть. Просто этот код разбавлен мусором. Идём по F7 дальше:

Рисунок 63. Переход на начало цикла

Видите прыжок по адресу 0078BE6A ? Это прыжок в начало цикла. Снимите все установленные
брекпоинты и поставьте аппаратную точку останова ( hardware breakpoint ) на Pushfd ниже прыжка.
Сделаем это заранее, чтобы потом не искать это место, а сами немного потрейсим цикл. Цикл
проходим ТОЛЬКО по F7 . Выполняем прыжок, попадаем в начало цикла и смотрим:

Рисунок 64. Начало цикла

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

Рисунок 65. Получение адреса блока

Пролистываем немного вверх и видим:

Рисунок 66. Получение адреса блока. Обфусцированный код

Жёлтым выделены наши команды, а всё остальное просто мусор. Он для того, чтобы ввести нас в
заблуждение. Если Вы потрейсите это место, то увидите, как формируется сам хеш. Этот цикл
бывает очень большим, поэтому мы раньше и поставили аппаратный брекпоинт на команду ниже
цикла. Запускаем по F9, и мы должны попасть на наш хардварный брекпоинт:

Рисунок 67. Конец цикла



У нас всё подготовлено, чтобы проверять хеш! В EAX находится хеш блока кода, в ECX длина этого
кода, а в EDX адрес. Если сейчас Вы перейдёте на адрес находящийся в EDX (00E9CE00), то
увидите:

Рисунок 68. Проверка нашей секции

Так это же наша добавленная секция! Осталось только чуть потрейсить по F7, и найти команду
сохранения значения хеша в память. Трейсим после PUSHFD прям чуть-чуть и натыкаемся на этот
код:

Рисунок 69. Сохранение хеша

Запишите куда-нибудь этот адрес (0078AE19), чтобы потом не искать это место. Убираем все ранее
установленные брекпоинты и ставим новый (можно и обычный INT3) на команду MOV DWORD
PTR [EBP], EAX . Теперь позапускаем программу и посмотрим, как много хешей у нас есть. После
четвёртого запуска получим сообщение, что файл изменён. Если проделать все эти манипуляция с
оригинальным файлом, то Вы заметите, как много хешей нам предстоит увидеть. У Вас, скорее
всего, устанет рука нажимать на F9 , прежде чем Вы просмотрите все хеши!
Как обойти эту проверку способов много. Можно, например, найти место, где мы собственно и не
проходим эту проверку и пропатчить его. Но это не так-то и легко. Зато легче "подсунуть"
протектору в EAX нужное значение. Но для начала нам нужно всё-таки узнать все ОРИГИНАЛЬНЫЕ
хеши. Их можно вытащить из оригинального файла Unpackme_vmp.exe . Рипать все эти хеши
вручную изнурительно (я бы даже сказал не реально), поэтому я написал простейший скрипт,
который сделает эту работу за нас. Принцип его работы прост как три копейки. Здесь я код этого
скрипта приводить не буду для экономии места, если хотите его посмотреть, то Вам нужен файл
под названием Read_CRC.osc , открывайте его и изучайте.
Итак, открываем ОРИГИНАЛЬНЫЙ и не изменённый файл в отладчике, запускаем скрипт
Read_CRC.osc. Когда скрипт попросит ввести адрес, где происходит сохранение хеша, введите
адрес, который мы нашли ранее вручную (0078AE19):



Рисунок 70. Ввод адреса

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

Рисунок 71. Состояние стека

Ну вот, всё готово и скрипт отрапортовал об успешной работе. Теперь в папке с программой Вы
сможете найти файл Original_CRC.txt . Откройте его в каком-нибудь редакторе текста и...
ужаснитесь какое количество хешей нам предстоит патчить:

Рисунок 72. Все хеши и адреса

Мать моя женщина. Более 9000 хешей!!! Теперь понятно, почему VMProtect так тормозит при
запуске :-) . Интересно, у Вас ещё не отпало желание сохранять эти хеши вручную?
Рассмотрим небольшую схему проверки хешей. Она не претендует на оригинальность и
достоверность, но общую схему работы проверки показывает:

Таким образом, получается, что сначала рассчитываются хеши для 4 блоков кода, потом они
сравниваются с оригиналом (не в открытом виде) и если всё нормально, то распаковывается часть
кода и цикл повторяется. Итак до того момента пока не проверятся все блоки. Это для нас
вызывает определённые трудности. Дело в том, что в пропатченном файле хеши мы просто так не
получим. А нам их как-то надо сравнить, чтобы понять какие из них патчить. Вручную? Нет, уж
извольте батюшка, у меня есть дела и поважнее :-) .
Чтобы не проверять все хеши вручную я состряпал ещё один скрипт, который называется
CRC_Patched.osc . Всю изнурительную работу по проверке хешей он выполнит за нас. Скрипт
писался на "коленке", так что за чудо-код извините. Сам принцип скрипта немного посложнее
предыдущего, но вроде работает. Принцип таков:
1) Загружаете в отладчике ПАТЧЕННЫЙ файл.
2) Запускаете скрипт CRC_Patched.osc.
3) При запуске скрипт ищет файл с оригинальными хешами (Original_CRC.txt).
4) Если он его найдёт, то запросит у Вас адрес, где происходит сохранение хешей. Нам он уже
известен и равен 0078AE19. Если фай с хешами не найден, то скрипт заканчивает работу, а
Вам нужно сначала получить эти хеши из оригинального файла с помощью скрипта
Read_CRC.osc.
5) Далее скрипт сравнивает каждый полученный протектором хеш с оригинальным из файла
Original_CRC.txt. Если он равен, то продолжает работу. Если хеш не равен, то скрипт
заносит в EAX оригинальный хеш (для того, чтобы протектор не показал нам ошибку) и
записывает в файл Patched_CRC.txt информацию о проделанном изменении. Файл отчёта
Вы можете найти в папке с программой.
Вроде всё логично. Итак, грузим патченный файл в отладчик, запускаем скрипт CRC_Patched.osc и
указываем ему адрес сохранения хеша. Идём курить.
После того, как скрипт отработает, в папке с программой появится файл Patched_CRC.txt . Так же
обратите внимание, что если после работы скрипта Вы запустите патченную программу под
отладчиком (продолжите её выполнение после работы скрипта), то она прекрасно запустится. Это


произошло потому, что скрипт уже пропатчил все хеши. Давайте посмотрим, что он там напатчил.
Открываем файл Patched_CRC.txt в блокноте и видим:

Рисунок 73. Информация об изменённых хешах

В автоматическом режиме мы получили всю нужную нам информацию. Как видите патчить
придётся всего 4 хеша. Не так уж и много.
Последняя задача, которую нам придётся решить, как пропатчить эти 4 хеша. Посмотрим на
примере первого хеша. Если патчить таким образом:
cmp EDX, E84892 // адрес проверки
jne XXXXXXXX // если не тот адрес, то не патчим
mov eax, 3408D059
...............................патчим следующие хеши
То на нашей системе всё будет прекрасно. А что если программа загрузится по другой ImageBase?
Всё верно ничего не пропатчится. Резонно возникает желание делать проверку не по полному
адресу, а по его половине. Например, так:
cmp DX, 4892 // адрес проверки
jne XXXXXXXX // если не тот адрес, то не патчим
mov eax, 3408D059
...............................патчим следующие хеши
Тоже один из вариантов. Но теперь посмотрите как Вы будете патчить следующие два хеша. Мы
имеем два адреса:
D0 0158
40 0158
Адреса разные, но патчить мы будем один и тот же хеш! Поэтому остаётся только один вариант -
делать проверку по хешу:
cmp EAX, XXXXXXXX
jne XXXXXXXX // если не тот хеш, то не патчим
mov eax, 3408D059
...............................патчим следующие хеши


Конечно, существует вариант, когда мы изменим программный код, и хеш блока изменится.
Поэтому, пожалуй, самый правильный вариант это делать "двойную" проверку:
cmp DX, 4892 // адрес проверки
jne XXXXXXXX // если не тот адрес, то не патчим
cmp EAX, XXXXXXXX // значение хеша
jne XXXXXXXX // если не тот хеш, то не патчим
mov eax, 3408D059
...............................патчим следующие хеши
Именно поэтому я по максимуму подготовился перед инлайном - максимально изменил код
программы. Так мы обезопасим себя от постоянного изменения хешей. Теперь перейдём
непосредственно к патчу хешей в нашей программе. Открываем файл Unpackme_Inline.exe в
отладчике, переходим в нашу добавленную секцию и идём на адрес, который мы заранее
подготовили для патча:

Рисунок 74. Место для патча

Теперь патчим таким образом:

Рисунок 75. Код патча хешей

Сохраняем изменения ПКМ -> Copy to executable -> Selection . Перезапускаем программу в
отладчике. Теперь нужно дописать конец патча. Переходим по адресу, где VMProtect сохраняет
хеш:

Рисунок 76. Место сохранения хеша

Я выделил байты, где мы сможем прыгнуть на наш патч, как раз 5 байт. Возврат из нашего патча в
код протектора должен будет происходить по адресу 0078AE1D. Запомните эти три команды


сохранения хеша (потому, что сейчас мы изменим их) для того, чтобы вписать их в конец нашего
патча. Меняем это место таким образом:

Рисунок 77. Переход на наш код

Опять сохраняемся, перезапускаемся и дописываем в нашей секции конец патча:

Рисунок 78. Конец нашего патча

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

Рисунок 79. Проверка не пройдена

Опять это зловещее окно ? . Дело в том, что когда мы перенаправляли код протектора на наш
патч, то изменили какие-то хеши. Загружаем программу в отладчике и запускаем наш скрипт
CRC_Patched.osc . Только теперь при запросе адреса сохранения хеша указывать надо не старый
адрес, а тот который находится в нашем патче:

Рисунок 80. Новый адрес

Опять идём курить :-) . После того, как скрипт отработал, открываем файл Patched_CRC.txt и
смотрим, что там изменилось:

Рисунок 81. Изменённый хеш

Видим, что изменился всего один хеш. Дописываем его в наш патч:

Рисунок 82. Патчим последний хеш

Сохраняемся, пробуем запустить нашу программу и....



Рисунок 83. Проверка пройдена

Ура! Наш патченный файл прекрасно запустился.
Наконец-то проверка CRC побеждена и файл прекрасно работает. Но радоваться рано, т.к. нам
нужно ещё пропатчить код программы. Как это сделать? Можно найти место, где происходит
прыжок на OEP(как и делают в классических случаях), а там дописать код нашего патча. Но это
место нужно ещё найти. Да и если мы изменим там код то, скорее всего опять изменится какой-
нибудь хеш. А его придётся патчить... Поэтому предлагаю способ попроще. Нам нужно поймать
момент, когда весь код будет распакован протектором, изменить доступ к секции и написать код
патча. Возникает вопрос: когда же весь код будет распакован в памяти? Тогда, когда VMProtect
будет проверять последний хеш! Открываем файл Original_CRC.txt и в самом конце этого файла
смотрим последний хеш и его адрес:

Рисунок 84. Адрес последнего блока кода

Открываем наш файл и после последней правки хеша пишем:

Рисунок 85. Ищем последний блок кода

Обратите внимание, что здесь присутствует "двойная" проверка, чтобы мы не пропатчили
лишнего и не в тот момент. Теперь нужно дать нужной секции доступ на запись. Сделать это
можно так:
1) Подгрузить библиотеку kernel32.dll ;
2) Функцией GetProcAddress получить адрес функции VirtualProtect ;
3) С помощью функции VirtualProtect дать секции нужные атрибуты.
Основная проблема здесь заключается в том, как нам использовать функцию VirtualProtect . Ведь,
как известно напрямую "забивать" функцию нам нельзя, т.к. на другой системе адрес этой
функции может быть другой. Нужно использовать переходники. Можно, конечно подгрузить эту
функцию через LoadLibrary GetProcAddress , но где взять эти функция, ведь нам известно, что
VMProtect прячет таблицу импорта. Но не всё так плохо. Как раз две нужные нам функция
протектор держит в открытом виде для своей работы, и мы можем этим воспользоваться.


Нажимаем там, где мы сейчас стоим ПКМ -> Search for -> Name (label) in current module или Ctrl+N
и видим:

Рисунок 86. Нужные нам функции

Запомним эти адреса и воспользуемся ими чуть позднее. Итак, поехали.
Примечание : Перевод API функций является вольным. Для
подробностей смотрите MSDN

LoadLibrary


Функция размещает указанный исполняемый файл в адресное пространство вызываемого
процесса.
HINSTANCE LoadLibrary(
LPCTSTR lpLibFileName
);
Параметры
lpLibFileName
Путь к файлу .exe или .dll.
Возвращаемое значение
Если функция успешно выполнена, то возвращаемое значение - хендл модуля. В противном
случае значение равно NULL.
С этой функцией ничего сложного. Пишем код:

Рисунок 87. Подгружаем библиотеку



Первыми двумя командами мы сохранили все регистры и состояние всех флагов. Далее
"затолкали" в стек название библиотеки. Её название мы прописали заранее в начале нашей
секции. Адрес самой функции мы подсмотрели у протектора (63E058, пишется как CALL DWORD
PTR [63E058]). Теперь надо получить адрес VirtualProtect .

GetProcAddress


Функция GetProcAddress получает адрес функции в указанной библиотеке.
GetProcAddress(
HMODULE hModule , // хендл DLL библиотеки
LPCSTR lpProcName // название функции
);
Параметры
hModule
Хендл библиотеки. Его можно получить функцией LoadLibrary или GetModuleHandle .
lpProcName
Указатель на нуль-содержащую строку с названием функции.
Возвращаемое значение
Если функция выполнится успешно, то в регистре EAX будет адрес искомой функции.
Если выполнится неудачно, то NULL.
Пишем дальше. Только не забудьте, что параметры нужно заносить в стек в обратном порядке!

Рисунок 88. Получаем адрес VirtualProtect

Первая команда заносит в стек название API функции (её мы тоже прописали заранее), вторая
заносит хендл библиотеки, загруженной LoadLibraryA . Теперь если всё ок, мы можем менять
доступ к секции.

VirtualProtect


Функция изменяет доступ к защищённой странице памяти в виртуальном адресе вызываемого
процесса.
BOOL VirtualProtect(
LPVOID lpAddress , // адрес региона
DWORD dwSize , // размер региона
DWORD flNewProtect , // требуемый доступ
PDWORD lpflOldProtect // переменная для сохранения старого значения доступа
);
Параметры
lpAddress
Указатель на адрес региона, где требуется изменить доступ.
dwSize
Размер этого региона.


flNewProtect
Новое значение доступа. Все доступные значения можно посмотреть в MSDN.
lpflOldProtect
Переменная для сохранения старого значения доступа. Если не указать этот параметр, то функция
вернёт нуль.
Возвращаемое значение
Если функция выполнится успешно, то возвращаемое значение не равно нулю.
Если выполнится неудачно, то NULL.
Здесь нам нужно указать немного побольше параметров :-) . Адрес и размер региона нужной
секции можно посмотреть в отладчике открыв карту памяти ( Alt+M ):

Рисунок 89. Получение адреса и размера

Итак, адрес у нас 00401000, а размер 0006D000. Доступ нам нужен как минимум
PAGE_READWRITE. Что как константа соответствует числу 40. И последнее нужно найти свободное
место в качестве переменной. Сюда система запишет старое значение. Я указал место чуть ниже
нашего патча. Имеем следующий код:

Рисунок 90. Изменяем доступ к секции

Ещё раз обращаю Ваше внимание, что все параметры в стеке - в обратном порядке. Сначала
указываем переменную для сохранения старого значения, затем значение нового доступа, размер
и адрес страницы памяти и в конце вызываем функцию VirtualProtect , он у нас уже должен
находиться в EAX. В конце восстанавливаем все регистры и флаги. Осталось дописать только сам
код, где нужно пропатчить. В итоге имеем следующее:



Рисунок 91. Последний патч кода

Запускаем анпакми, проверяем, чтобы все, что мы патчили прекрасно работало и прыгаем от
удовольствия: мы только, что удачно пропатчили программу не распаковывая её.
Порадовались и попрыгали от удовольствия? Это ещё не всё...


Хочу ещё быстрее


Как-то раз попросил меня друг посмотреть одну программку. Посмотрел ничего особенного:
запакована VMProtect, код не упакован, патчить вроде немного. Думаю, ну делов-то на пять
минут. Хрен там! Пропатчил в одном месте, подправил хеши, запустил, посмотрел. Нашлось ещё
одно место. Опять пропатчил хеши, запустил, посмотрел... Ещё одна проверка. И так раз
пятнадцать. То одна скрытая проверка, то другая, то через некоторое время третья появилась.
Замучался я эти хеши патчить, обматерился и ушёл жутко злой на кухню пить кофе. И вот пью я это
кофе и думаю: можно было бы затолкать протектору сразу все оригинальные хеши. И меня
осенило, а почему нельзя? Нужно всего лишь эти хеши сохранить в программе, а затем немного
"продолжить" процедуру протектора для получения хешей.
Для этого дела я написал скрипт, который называется Save_CRC.osc . Указываете ему при запросе
адрес, где протектор производит сохранение хешей, он считывает все эти хеши, а в конце своей
работы сохраняет их в файле dump.bin , который будет находиться рядом с программой.
Копируем файл Unpackme_vmp.exe и переименовываем его в Unpackme_Inline_Method2.exe .
Опять отладчик, запуск скрипта, указание адреса и... курить, опять курить :-) . Когда скрипт
отработает, видим рядом с программой нужный файл:

Рисунок 92. Здесь хранятся все хеши

Загружаем файл Unpackme_Inline_Method2.exe в PETools и добавляем секцию:

Рисунок 93. Добавляем файл с хешами

Указываем имя секции, выбираем Load from binary file , указав в качестве файла наш файл с
хешами. Нажимаем Add . Всё с этого момента файл опять перестал запускаться. Грузим файл в
отладчике, открываем карту памяти, и смотрим под каким адресом загрузилась наша секция:

Рисунок 94. Наша добавленная секция

У меня этот адрес 00794000. Смотрим этот адрес в окне дампа и видим, что все хеши прекрасно
сохранены:



Рисунок 95. Хеши в окне дампа

Крутим это окно вниз до того момента пока не закончатся наши хеши, затем немного пропустив
место впишем туда указатель на первый хеш (в нашем случае это начало секции):

Рисунок 96. Указатель на первый хеш

Будьте предельно внимательны, отступите немного вниз, чтобы не затереть последний хеш, т.к.
он может быть равен нулю. Запоминаем адрес на указатель. Сохраняем изменения и
перезапускаемся. Идём туда, где сохраняются хеши (0078AE19) и прыгаем на наш патч:

Рисунок 97. Переход на наш код

Опять сохраняемся и перезагружаем программу в отладчике. Там где должен быть наш патч
делаем "фиктивную" процедуру получения хешей ( vnekrilov бы назвал это прививкой :-) ):
0079CFA0 A1 90CF7900 MOV EAX, DWORD PTR [79CF90] // получаем указатель на хеш
0079CFA5 8B00 MOV EAX, DWORD PTR [EAX] // получаем оттуда хеш
0079CFA7 8305 90CF7900 04 ADD DWORD PTR [79CF90], 4 // увеличиваем указатель
Дополняем это кодом протектора для сохранения хешей и прыгаем обратно в секцию VMProtect.
В итоге имеем:

Рисунок 98. Фиктивная процедура получения хешей

Запускаем программу и видим, что всё прекрасно работает. Мы воспользовались тем, что
протектор не меняет расположение хешей (т.е. они идут в определённом порядке). Несомненным
преимуществом является то, что теперь Вы можете хоть "оппатчиться" и не менять больше
никаких хешей! Теперь программа будет запускаться всегда.


Единственное, что не радует, так это размер файла:

Рисунок 99. Размер файлов

Эстеты будут в гневе :-) . Виноват я и скрипт, который дампил хеши. Кстати размер Вы можете
выбирать сами, нужно только отредактировать скрипт:

mov SECTION_SIZE, 80000 // размер секции
mov FILE_NAME, “dump.bin” // название файла с хеш-кодами
Но, чтобы не гадать с размером секции проще поправить это дело в файле. Считаем сколько на
самом деле содержится "полезного" кода в нашей секции:
Начало секции: 00794000
Конец нашего патча: примерно 0079CFBC
Полезный код: конец-начало = 00008FBC
Открываем наш файл Unpackme_Inline_Method2.exe в PETools , идём в Sections . Выбираем нашу
секцию ПКМ -> Edit Section Header . Указываем в Virtual Size и Raw Size размер полезного кода:

Рисунок 100. Меняем размер секции

Нажимаем ОК. И последний штрих: закрываем все окна и в PETools выбираем Tools -> Rebuild PE ->
Указываем наш файл. И....

Вот теперь получше. Идём отдыхать и радуемся, что мы одолели VMProtect второй раз :-)


Может быть, что-то ещё?


Что, есть ещё способ пропатчить проверку? Спросите Вы. А как же, мы что пальцем сделаны? Этот
способ подсказал вездесущий LCF-AT . Давайте посмотрим, как он работает. Скопируем файл
Unpackme_vmp.exe в Unpackme.exe . В любом редакторе ресурсов изменим в нём самый
последний байт с 00 на 01 и сохраним изменение. Загружаем файл в отладчик и запускаем его:

Рисунок 101. Обнаружение изменений

Кто бы сомневался, что нас запалят :-) . Теперь перезагрузим файл в отладчике и поставим
брекпоинт на API функцию CreateFileW . Запускаем и мы остановились на нашем брекпоинте.
Смотрим в стек:

Рисунок 102. Чтение файла

Видим, что в качестве одного из параметров функции передаётся имя файла. Нажимаем на нём
ПКМ -> Follow in Dump . Смотрим в дампе:



Рисунок 103. Имя нашего файла в дампе

Рядом с этим файлом у нас лежит не изменённый файл Unpackme_vmp.exe . Попробуем заменить
имя файла на оригинальный:

Рисунок 104. Меняем имя файла

Проверим, что у нас в стеке:

Рисунок 105. Подмена имени файла

Продолжаем выполнение файла и видим, что он прекрасно запустился. Полное имя файла
получается с помощью API функции GetModuleHandleW . Так вот, LCF-AT предлагает "ловить" эту
функцию и изменять путь на ОРИГИНАЛЬНЫЙ файл. Лично мне такой метод не нравится, потому
что, во-первых всегда придётся держать рядом с патченным оригинальный файл. Во-вторых,
придётся довольно много писать кода, чтобы подменить название файла. Данный способ хорош,
пожалуй, только тогда, когда используется лоадер. Тем более, мне попадалось несколько
программ явно запакованных последними версиями VMProtect и там, к сожалению, эта методика
уже не прокатывает. Выбирать этот метод патча или нет, решать Вам. Я всего лишь показал, что он
существует.


Инлайн патч Movienizer 6.3


Вот мы и дошли до последней части этой главы. В этой части я хотел бы показать Вам, как можно
сделать инлайн патч реальной коммерческой программы, которая называется Movienizer . Это
программа для тех, кто любит коллекционировать фильмы. Я думаю таких людей предостаточно.
Программа в своём сегменте, пожалуй, одна из самых лучших и самых дешёвых. Поначалу про эту
программу рассказывать я не хотел. Не хотел говорить про неё и по той причине, что автор этой
программы в юности был одним из наших :-) . Но затем за копеечку продался шароварщикам и
теперь зарабатывает на жизнь коммерческим софтом. Естественно довольно хорошо разбираясь в
дебрях кода, автор сумел защитить свою программу довольно грамотно, а в качестве навесного
упаковщика выбрал как раз наш старый, добрый VMProtect. Почему я всё-таки решился написать
об исследовании этой программы здесь? На то есть несколько причин:
1) Авторы сами выложили последнюю версию программы в интернете. Ею можно бесплатно
пользоваться до первой переустановки системы;
2) Потому что об этом настойчиво просили посетители форума exelab . Видимо этой
программой пользуется довольно большое количество человек;
3) Программу практически не взламывают, наверное, по причине сложности упаковщика;
4) Автор видать зажрался, т.к. программа практически перестала развиваться, она просто
потихоньку начинает вымирать. Ну и правда, что рвать то пятую точку, когда денежка
исправно течёт в карман, а реверсы не поджимают сзади :-) .
Всё это и несколько других причин побудили меня к написанию этой части статьи. Это ни в коем
случаем не говорит о том, что я испытываю к автору программы какие-то негативные чувства или
отвращения. Как бывший коллега, автор должен понять, что это спорт и ничего больше :-) .
Итак, давайте оценим, что нам предстоит сделать. К последним английским версиям программы в
сети "гуляет" ключ на имя Armands Augstkalns . Он находится рядом с программой в файле Key.txt
и имеет такой вид:
Name: Armands Augstkalns
Code: 4RWEY-TDZAD-23P68-DH6YW-EA2GP
Этот ключ забанен. Если Вы зарегистрируете программу этим ключом, то на первый взгляд всё
будет прекрасно:

Рисунок 106. Успешная регистрация программы



Но это только на первый. При каждом запуске программы Вас постоянно будет выкидывать на
сайт программы. Дальше, при добавление фильма, опять будет открываться страничка
программы, а регистрация сбрасываться. При этом повторно зарегистрировать её Вам не удастся,
пока Вы не зайдёте под своим профилем заново (перезагружать компьютер не обязательно). Так
же в программе присутствует проверка регистрационного номера на сайте. Ну и апогей всего
этого, онлайн активация ключа. Она появилась, начиная с 6 версии программы, и теперь даже при
всём желании Вы не сможете её пройти с забаненным ключом.
Исследование программы начнём с того, что я расскажу Вам об одном "подлом" приёме авторов
этой программы. Дело в том, что если Вы даже и удалите программу со своего компьютера, то
программа все равно оставляет свои следы в реестре системы. Причём не просто оставляет, а
делает это в зашифрованном виде. Никогда не любил шароварщиков, которые действуют
подобным образом. Вы бы хоть честно об этом предупреждали, как это делают многие
уважающие себя авторы программного обеспечения. Почему у меня в системе должен находиться
мусор? Если Вы хотите удалить регистрацию программы, то это можно сделать только с помощью
удаления этого мусора. Найти это место можно с помощью очень известной программы Process
Monitor (или ProcMon). Запускаем его, указываем в качестве фильтра нашу программу:

Рисунок 107. Настройка фильтра

Жмём Ок. Далее отключаем всё кроме наблюдения за реестром:

Рисунок 108. Следим только за реестром

Включаем наблюдение и запускаем программу. После того, как она загрузится, смотрим не
далеко от запуска программы:



Рисунок 109. Что-то подозрительное считывается с реестра

Видим, что программа, зачем то лезет в реестр по пути HKEY_CLASSES_ROOT\CLSID\{CD00D596-
DEFC-FDF5-0C4B-CB4E82E16A5C}\InProcServer32 . Посмотрим, что там находится:

Рисунок 110. Шифрованные данные

Это и есть те самые зашифрованные данные. Удаляем весь ключ реестра и видим, что регистрация
программы "слетела". После того, как Вы запустите программу ещё хоть раз, то этот ключ
появится вновь.
Но это всё лирика, давайте перейдём непосредственно к инлайн патчу. Копируем файл
movienizer.exe с новым именем movienizer_patched.exe . Открываем оба файла в отладчике и
ищем что патчить. Открываем карту памяти ( Alt+M ) и переходим в секцию с кодом:

Рисунок 111. Смотрим секцию с кодом

Видим, что секция не упакована:



Рисунок 112. Код не сжат

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

Рисунок 113. Регистрация программы

1) Заблокированный ключ
Там где мы сейчас находимся, нажимаем ПКМ -> Follow in Dump -> Selection . В окне дампа
производим поиск ПКМ -> Search for -> Binary string (Ctrl+B) . В открывшемся окне вводим в
Unicode формате первые пять символов нашего заблокированного ключа:

Рисунок 114. Поиск Unicode строки

Нажимаем Ок. Наш ключ нашёлся здесь:

Рисунок 115. Заблокированный ключ

Переходим во второй отладчик, там находим этот адрес и патчим всего один символ:



Рисунок 116. Патчим Stolen Key

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

Рисунок 117. Передача регистрационных данных

Нужно убрать это. Можно, конечно поставить брекпоинт на API функцию ShellExecuteW , но
проще произвести поиск строки. Ищем в строках программы строку
bin/registered . Находим одно место вот здесь:

Рисунок 118. Строка нашлась здесь

Самое простое для нас это прокрутить немного вверх до адреса 00DD1BC2...:

Рисунок 119. Патчим здесь

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

Рисунок 120. Патчим так

Сохраняем изменения. Больше мы окна браузера не увидим.
3) Отправка регистрационных данных на сайт
После того, как Вы зарегистрируетесь Ваше регистрационное имя, код, версия и язык
программы, а также тип лицензии отправляются на сайт. Не хорошо товарищи... Как найти это
место и пропатчить его? Произведём поиск строки checkcode :



Рисунок 121. Ищем строку

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

Рисунок 122. Процедура проверки кода на сайте

Смысл данной процедуры таков: если программа зарегистрирована (в буфере имеется
серийный номер), то собирается вся нужная информация и отправляется на сайт автора. Если
регистрационной информации нет, то ничего не отправляется. Что ж логично, зачем
отправлять пустые данные. На рисунке выше за это отвечает переход по адресу 00A05F38.
Поправим его в патченном файле таким образом:

Рисунок 123. Патчим процедуру

Всё, больше наши регистрационные данные никуда не отправляются.
4) Онлайн активация ключа
И последнее, что нам нужно найти это как пройти онлайн активацию регистрационного ключа.
Ставим точку останова на функции ShowWindow и запускаем программу. Смотрим в стек и
ждём пока там не появится окно с ошибкой активации:

Рисунок 124. Ошибка активации

Снимаем брекпоинт, возвращаемся в код программы ( Alt+F9 ) и жмём Debug -> Animate Over
( Ctrl+F8 ). Теперь мы должны зациклиться на процедуре создания окна:



Рисунок 125. Создание окна

Теперь останавливаем трейсинг (нажав, например F8 ). Чтобы пройти этот цикл ставим брекпоинт
на RET в конце всей процедуры, запускаем программу ( F9 ), снимаем брекпоинт и начинаем
выходить из вложенных функций до того момента пока не попадём на этот код:

Рисунок 126. Виртуальная машина

Мы в виртуальной машине. Чтобы её не трейсить смотрим в стек и находим, откуда она
вызывается:

Рисунок 127. Состояние стека

Вроде ничего интересного. Но понятно, что мы уже в конце процедуры активации ключа. Об этом
свидетельствует код возврата функции (можно увидеть в стеке значение -100, означающее
ошибку соединения с сервером). Покрутим немного вверх, чтобы поискать адрес возврата:

Рисунок 128. Состояние стека чуть выше

Видим, что есть переход в код программы. Нажимаем ПКМ -> Follow in Disassembler . Видим:



Рисунок 129. Код программы

Действительно, это уже самый конец онлайн проверки. Прокрутим вверх, и по адресу 00A054E0
Вы увидите начало этой функции. Патчить её можно множеством способов, но самый правильный
и быстрый это вернуть по выходу из этой функции значение равное единице, что будет означать
для программы, что мы успешно прошли активацию. Переходим в патченном файле на адрес
00 054E0 и патчим функцию:

Рисунок 130. Патчинг онлайн активации

Вот и всё, программа полностью функциональна. Осталось только пропатчить CRC проверку.
5) Патчинг хешей
Чтобы не создавать отдельную секцию в файле, давайте посмотрим, есть ли в нём немного
свободного места. Я нашёл его здесь:

Это секция VMProtect. Если Вам нужно пропатчить немного кода, то это место как раз
подойдёт. Запомним его. Теперь найдём, где идёт сохранение хешей. Делаем это точно так
же, как делали с анпакми (брекпоинт на MapViewOfFile и т.д.). Я нашёл это место здесь:

Рисунок 131. Место сохранения хешей

Практически, как и в нашем анпакми. Запоминаем первые три команды, а вместо них пишем
прыжок на наше место, где будет патч:

Рисунок 132. Прыжок на наш патч



Идём на адрес нашего патча, оставляем себе немного места и в конце патча пишем:

Запоминаем наше новое место сохранения хешей (00FAE7DB), сохраняем сделанные
изменения и закрываем все отладчики. Осталось совсем чуть-чуть: посмотреть какие хеши
изменились. Для оригинала запускаем скрипт Read_CRC.osc , а для пропатченного
CRC_Patched.osc . Делаем всё по аналогии с тем, как делали для анпакми. Обратите внимание,
как быстро отработали оба скрипта. Наверное, хешей относительно немного. И действительно
их "всего" 72 штуки. Это произошло потому, что код нашей программы не упакован. Смотрим
в файле Patched_CRC.txt , какие хеши нужно пропатчить:

Рисунок 133. Отчёт изменённых хешей

Всего 4 хеша. Патчим их:

Рисунок 134. Код патча хешей

Запускаем программу и...

Рисунок 135. Окно ошибки

Какой упёртый протектор :-) . Опять запускаем патченный файл и скрипт Patched_CRC.txt . Смотрим,
что изменилось:



Рисунок 136. Ещё один хеш

Изменился один хеш. Но не спешите дописывать его патч. Это ничего не изменит! Каждый раз
меняя команды в области нашего патча мы будем менять и сам хеш. Этот хеш как раз и отвечает
за наш участок кода. Поэтому здесь надо патчить другим методом, например, так:

Рисунок 137. Патч по адресу

Адрес можно посмотреть в файле Patched_CRC.txt . Только убедитесь, что этот адрес больше не
присутствует в файле. Вот это именно тот случай, когда проще прилепить все хеши к файлу (как в
методе № 2) и не мучиться с их патчингом. Подводим итоги и имеем окончательный патч такого
вида:

Рисунок 138. Законченный вид патча

Сохраняем все изменения и запускаем программу:



Рисунок 139. Программа успешно запустилась

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


Заключение


Вот мы и рассмотрели, как патчить CRC проверку VMProtect. Я показал Вам три способа, которыми
можно это сделать. Какой из них лучше? Пусть на этот вопрос каждый ответит себе сам.
Возникают случаи, когда проще патчить одним способом, иногда другим. А бывают ситуации,
когда приходится использовать оба сразу. Должен сказать, что наверняка есть ещё способы для
патчинга хешей, но как мне кажется, пока это неактуально. Наверняка автор протектора скоро
прикроет эту "лавочку" и нам придётся искать другие пути. Ну а пока будем довольны тем, что у
нас есть на сегодняшний день.
Надеюсь, Вам понравился этот туториал. Конечно, здесь не рассмотрено множество вопросов,
например таких как: ручная распаковка, исследование виртуальной машины протектора,
обнаружение виртуальных сред и т.д. Но в контексте данного туториала этого и не требовалось. А
на главный вопрос: как пропатчить хеши, я думаю, мы с Вами ответили. Вот и всё!

Обсуждение статьи: Взлом VMProtect защиты. Инлайн патчинг на примере программы Movienizer (Глава 3) >>>


При перепечатке ссылка на https://exelab.ru обязательна.



Видеокурс ВЗЛОМ