Pull to refresh

2 x 2 = 3 или сказ о том, как я Visual Basic реверсил

Level of difficultyMedium
Reading time3 min
Views3.4K

Жив еще Visual Basic: программы еще живы. Байт-код VB выполняется виртуальной машиной msvbvm60.dll , которая до сих пор живет в каталоге C:\Windows .

Задача - разгадать алгоритм проверки ключей.
zira's ZittoKeygenme https://crackmes.one/crackme/648b452233c5d4393891390d

Борьба с упаковщиком

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

ASPack мешает дизассемблеру распознавать команды. Дизассемблер читает байты последовательно, но, когда встречает команду call, встает перед выбором:

  • Пойти по адресу вызова, дизассемблировать процедуру, вернуться и продолжить работу после call

  • Оставить разбор процедуры на потом и дизассемблировать следующую за call команду

IDA оставляет разбор процедуры на потом, поэтому следующей командой прочтет E9 EB 04 5D 45 jmp. Процессор же сперва выполнит call, а за ним и другой код: 5D pop ebp.

Команда call толкает в стек адрес следующей инструкции .aspack:00405007 и передает управление loc_40500A. Код снимает со стека адрес, увеличивает на 1 и возвращает управление на .aspack:00405008: jmp short loc_40500E. Вот так лишний байт E9 в потоке инструкций ослепляет дизассемблер.

Распаковщик вычисляет ImageBase - адрес начала кода в памяти, а затем и точку входа программы, записывает адрес OEP в инструкцию push. Теперь знаем, где остановить отладчик, чтобы сделать снимок программы.

Дизассемблирование Visual Basic кода

Отладчик показывает, что программа передает управление msvbvm60.ThunRTMain - запускает виртуальную машину Visual Basic. Программа передает msvbvm60.ThunRTMain структуру VBHeader, что описывает проект Visual Basic. Visual Basic компилируется в P-код, который исполняется виртуальной машиной, либо в Native машинный код процессора, который обращается к некоторым API виртуальной машины. VBDec помогает разметить структуры, объекты и процедуры Visual Basic в IDA.

Размер обработчиков Form1_Command1_Click и Form1_Command2_Click подсказывает, что Command1 - кнопка Register. Form1_Command1_Click обращается и к строкам "Thank you for registering this keygenme" и "Incorrect registration information", что выдает и защитный механизм.

Упаковщик скрыл импорты функций из msvbvm60.dll , поэтому дизассемблер вместо имен функций показывает call ds:dword_*** . Отладчик сохранил адреса DLL-функций в памяти на момент взятия снимка программы, а по адресам найдем имена.

Последовательность вызовов __vbaI4Var, rtcMidCharVar, rtcUpperCaseVar, rtcAnsiValueBstr подсказывает что цикл работает с каждой буквой строки. Отладчик подтверждает: строка - UserName.

Интуиция подсказывает, что следующие __vbaVarMul и __vbaVarAdd работают с кодом символа, однако в дизассемблере следы переменной var_E0 с кодом символа к этим функциям не ведут. Отладчик показывает, что __vbaVarMul принимает значения 2 и 2, а возвращает 3. Что за...

Арифметические функции msvbvm60.dll работают со структурами типа VARIANT и передают работу библиотеке oleaut32.dll . __vbaVarMul вызывает oleaut32.VarMul . Документация к oleaut32.dll говорит: VarMul работает с аргументами типа VARIANT. "OAIdl.h" из Windows SDK описывает структуру VARIANT, а "wtypes.h" определяет константы VT_I2 = 2, VT_I4 = 3 для VARTYPE vt. Умножение двух VARIANT типа VT_I2 дает VARIANT типа VT_I4.

struct tagVARIANT
    {
    union 
        {
        struct __tagVARIANT
            {
            VARTYPE vt;
            WORD wReserved1;
            WORD wReserved2;
            WORD wReserved3;
            union 
                {
                LONGLONG llVal;
                LONG lVal;
                BYTE bVal;
				/*...*/

Среди стандартных структур в IDA найдем VARIANT и объединим переменные dword на стеке.

Программа вычисляет хеш User Name так:

int32_t accum = 0;
int32_t hash = 0;
for (char c: name) {
  accum += (0x1749 * toupper(c));
  hash = accum - name.length();
}

а за ним - ключ регистрации:

string reg_number = "Zitto - "s + to_string(hash);

Ссылки

http://sandsprite.com/vbdec/
https://learn.microsoft.com/en-us/windows/win32/api/oleauto/nf-oleauto-varmul
https://hex-rays.com/products/ida/support/tutorials/unions/

Tags:
Hubs:
Total votes 10: ↑10 and ↓0+10
Comments2

Articles