16 Июня, 2010

ESET CrackMe – CONFidence 2o1o

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


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

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

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

Вернемся к нашей виртуальной машине, которая имеет в своем распоряжении 8 псевдорегистров, назовем их условно: rA, rB, rC, rD, rE, rF, rG, rH. Каждый регистр имеет размер 1 бит. Набор поддерживаемых команд является следующим:

ret - завершение работы виртуальной машины;

set [имя_регистра] – установить значение регистра в единичное состояние;

jz [имя_регистра] – команда условной передачи управления (если содержимое регистра равно 0, то осуществляется передача управления следующей процедуре (процедуры расположены в памяти последовательно));

and [имя_регистра1], [ имя_регистра2] – логическая операция , результат сохраняется в первом регистре;

mov [имя_регистра1], [имя_регистра2] – скопировать содержимое второго регистра в первый;

mov [имя_регистрa, [адрес] – скопировать содержимое памяти (бит) по заданному адресу в заданный регистр;

mov [адрес], [имя_регистра] – скопировать содержимое заданного регистра (бит) по заданному адресу в памяти


Размер инструкции виртуальной машины имеет фиксированный размер и равен 2 байтам. Принцип кодирования инструкций можно изобразить в виде следующей схемы:



Данная виртуальная машина осуществляет преобразование содержимого памяти, в соответствии с управляющей последовательностью (которую как раз и нужно найти), которая так же располагается в памяти:

начало памяти + 0x00: управляющая последовательность (16 байт)

начало памяти + 0x10: хэш-значение от введённого имени(16 байт)

начало памяти + 0x20: зашифрованное хэш-значение (16 байт)

начало памяти + 0x30: результат преобразования функции виртуальной машины (16 байт)

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



Для более удобного разбора байт-кода команд выполняемых виртуальной машиной мы написали процессорный модуль для дизассемблера IDA Pro, который сильно упростил нам дальнейший анализ. Вот так вот выглядит набор команд до их преобразования нашим процессорным модулем:


А на картинке ниже представлен вариант обработки процессорным модулем:



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



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

Но мы все-таки в качестве примера приведем несколько правильных комбинации:

Name: habrahabr
Registration Code: 984116e52ad86d6bd144b11b975a595e

Name:SVH
Registration Code:271a300e1174f46f944c5c67dc59dd57

Name:CONFidence
Registration Code: 24a2b8dc7c1578de64f8e8e114c2bf00
или введите имя

CAPTCHA