воскресенье, 26 июля 2009 г.

Виртуальная машина в keygenme от Ms-Rem

Введение:

Те кто в теме, кто знает и слышал никнэйм Ms-Rem думаю слышали и о его детище-головоломке игрушке кейгенми цель, которого предоставить реверсеру офигенный навык по работе с виртуальными машинами. Итак все по порядку:


Цель кейгенми:
Разработать приложение которое на заданное имя пользователя сгенерирует последовательность цифр,называемую серийным номером. Введя эти данные в Edit'ы кейгенми получить "Congratiolations"

Уровни защиты:
1. Уровень защиты это небольшая и не сложная полиморфная паковка, снимаемая на глаз.
2. Алгоритм работы скрыт в командах придуманого разработаного интерпретатора этих команд, т.е.виртуальной машины.Именно в логике этих команд и скрыт механизм генерации фраз поздравления или посыла крякера, а также проверке введенных данных.

Краткое описание виртуальной машины:

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

Обозначения:

eax - выступает в роли указателя на команду
lpVMMem - указатель на виртуальную память
lpInput - указатель на введенные пользователем данные
lpOutput - указатель на то куда будет ложиться результирующая строка, о результате сверки, затем толи вас пошлют, либо поздравят )

Описание:

Размер виртуальной программы - 0x3DA2 байт!
  • 0 - увеличение на 1 численного значения указателя на виртуальную память
  • 1 - уменьшение на 1 численного значения указателя на виртуальную память
  • 2 - увеличение на 1 численного значения байта по указателю на виртуальную память
  • 3 - уменьшение на 1 численного значения байта по указателю на виртуальную память
  • 4 - копирование одного байти из входной последовательности в позицию виртуальной памяти куда указывает указатель на вирт. память. После увеличиваем на 1 указатель входных данных
  • 5 - копирование одного байта из вирт.памяти в память по указателю выходных данных. Затем увеличение на 1 указателя выходных данных
  • 6 - В случае если по указателю вирт. памяти хроанится 0, то вычисляется новое смещение и осуществляется переход
  • 7- В случае если по указателю вирт. памяти байт не равен 0, то вычисляется новое смещение и осуществляется переход

Выводы:

При просмотре кода вирт программы можно сделать выводы:
  1. Существует одна инструкция "5" значит и выполняется несколько роза, т.е. ЦИКЛ. Тоже самое с "4" !
  2. Из-за обилия инструкций "2" и двух "0" можно сделать вывод что это генерация юникод-строк с фразами результата в вирт. памяти.
  3. Нет проверки аналогично cmp в привычной нам хакерам свято верящих в x86-64 архитектуру и следовательно защита может только проверить какие-то байты введенных байт, командами "6" или "7"
  4. В силу. п3 защита может вычислеть такое значение значение указателя на вирт. память, где хранится строка с результатом!

Все! ;) Остается пожелать удачи тем, кто хочет попробовать силы и найти ответ на вопрос : "Как именно защита вычесляет значение указателя на строку с правильным результатом ?

суббота, 25 июля 2009 г.

Virtual Machine of RLPack v1.20.1full

Цель:
Показать устройство виртуального процессора , который используется в опции "Виртуализация кода" RLPack v1.20.1f

Описание:

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


typedef struct _RLPK_VM_INSTR {
DWORD Type;
DWORD Field_4;
DWORD Field_8;
} RLPK_VM_INSTR, *PRLPK_VM_INSTR;

Условием завершения потока виртуальных иструкций является значение 0 в очередном экземпляре RLPK_VM_INSTR.

Всего имеется 27 различных видов инструкций и 24 кода для регистров.

Кодировка регистров и их соответствие в нашей "родной" x86-архитектуре:

  • ESI - 0x06, 0x15
  • EDI - 0x05, 0x16
  • EBP - 0x07, 0x17
  • ESP - 0x08, 0x18
  • EAX - 0x01, 0x09, 0x0A, 0x0B
  • EBX - 0x02, 0x0C, 0x0D, 0x0E
  • ECX - 0x03, 0x0F, 0x10, 0x11
  • EDX - 0x04, 0x12, 0x13, 0x14

Кодировка инструкций и их соотвествие в нашей привычной и родной нам x86-архитектуре:

  • 0x1 - MOV EBP,ESP
  • 0x2 - PUSH NUM // NUM - Field_4
  • 0x3 - PUSH REG // REG - Field_4
  • 0x4, 0x5 - ADD REG, NUMBER // REG - Field_4, NUM - Field_8
  • 0x6 - MOV REG,NUM // REG - Feld_4, NUM - Field_8
  • 0x8 - MOV REG,FS:[0] // REG - Field_4
  • 0x9 - MOV FS:[0],REG // REG - Field_4
  • 0xA - MOV REG2,[REG] // REG - Field_4, REG2 - Field_8
  • 0xB - MOV [ADDR],REG // REG - Field_8, ADDR - Field_4
  • 0xC - CALL ADDR // ADDR - Field_4
  • 0xD - MOV REG,[ADDR] // REG - Field_4, ADDR - Field_8
  • 0x10 - MOV REG2, REG1 // REG1 - Field_4, REG2 - Field_8
  • 0x11 - CALL [ADDR] // Address - Field_4
  • 0x12 - PUSH DWORD[FS:0] // no comments :)
  • 0x14 - POP REG // REG - Field_4
  • 0x17 - MOV [REG2],REG // REG - Field_4, REG2 - Field_8
  • 0x18 - VM_RET // Детализация будет позже ;)
  • 0x19, 0x1A - MOV [ADDR],NUM // ADDR - Field_4 ,NUM - Field_8
  • 0x1B - MOV REG,[REG2+NUM] // REG - Field_4, REG2 = Field_8 >> 2, NUM = Field_8 & 0xFFFF
--- Есть еще команды, опишу в следующий раз, ждите продолжения )))

Виртуализация:

Работа пакера делится:

  • виртуализация вызова функций напрямую
  • виртуализация подряд идущего, т.е. аналогично INLINE применяемого компиляторами.

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