|
|||||||||||||||||||||||||||||||||||||||||||||||||
Автор: GPcH. Дата публикации: 15.09.2004 |
Руководство по исследованию программ, написанных на Visual Basic 6.0[Вступление] Многие почему то считают, что Visual Basic самый плохой язык программирования, который не может компилировать программы, работать с адресами переменных в памяти и не позволяющий вставлять ассемблерные процедуры в код. Так вот, все это неправда. Начиная с версии 5.0 данный язык позволяет компилировать программы в Native Code, а также имеется возможность работы с адресами переменных в памяти (для этого существует функция varptr). Ассемблерные процедуры вставлять тоже можно, но не так просто. Для этого я написал уже 2 части статьи по вставке ассемблерных процедур в код на Visual Basic. Эти статьи можно найти на сайте www.dotfix.net. Как видите, недостатков у VB не так уж и много, а преимуществ настолько много, что я расскажу лишь о самых очевидных и важных: Так вот, начинающие исследователи программ почему то считают, что программы, написанные на VB невозможно исследовать. Если программа скомпилирована в pcode - я частично с ними соглашусь, но даже для этого вида компиляции уже написано множество отладчиков, способных понимать псевдокодовые инструкции. Что же касается Native Code, то тут все исследуется также, как и любая другая программа, написанная например на C++ или Delphi. Но есть ряд особенностей. Все операции, которые выполняет программа выполняются с использованием узкоспециализированных функций из библиотеки MSVBVM60.DLL. Имена этих функций напоминают операторы Visual Basic'а, поэтому глядя на названия большинства из них, можно понять, какие операции они позволяют выполнять. Но есть и такие, которые не поддаются логике. О них я и расскажу в данной статье. [Функции] Самые непонятные исследователям функции - функции для преобразования данных из одного типа в другой. Чуть ниже я для удобства приведу существующие типы данных, используемых в Visual Basic 6.0 и функции для работы с ними. bool - boolean str - string i2 - integer (2 битный integer) ui2 - unsigned integer (2 битный unsigned integer) i4 - long (4 битный integer) r4 - single (4 битный real) r8 - double (8 битный real) cy - currency var - variant (VB) или variable (OLEAUT) fp - число с плавающей точкой cmp - сравнение comp - сравнение __vbaI2Str 'преобразует String в Integer __vbaI4Str 'преобразует String в Long __vbar4Str 'преобразует String в Single __vbar8Str 'преобразует String в Double VarCyFromStr 'преобразует String в Currency VarBstrFromI2 'преобразует Integer в String __vbaStrCopy 'копирует строку в память - аналог API функции HMEMCPY __vbaVarCopy 'копирует переменный тип (variant) в память __vbaVarMove 'копирует переменный тип (variant) в память __vbavaradd 'сложение двух переменных типа Variant __vbavarsub 'деление двух переменных типа Variant __vbavarmul 'умножение двух переменных типа Variant __vbavaridiv 'сложение двух переменных типа Variant 'с выводом результата в переменную типа Integer __vbavarxor 'XOR __vbavarfornext 'используется в конструкциях For... Next... (Loop) __vbafreestr 'удаление переменной __vbafreeobj 'удаление объекта __vbastrvarval 'получения численного значения из строки multibytetowidechar 'преобразование кодировки rtcMsgBox 'показывает сообщение - аналог API messagebox/a/exa __vbavarcat 'объединяет две переменные типа Variant __vbafreevar 'удаляет переменную типа Variant __vbaobjset 'создает объект __vbaLenBstr 'определяет длину строки rtcInputBox 'показывает форму с полем ввода (используются также API функции getwindowtext/a, GetDlgItemtext/a) __vbaNew 'аналог API функции Dialogbox __vbaNew2 'аналог API функции Dialogboxparam/a rtcTrimBstr 'удаляет пробелы вначале и в конце строки __vbastrcomp 'сравнивает 2 строковые переменные - аналог API функции lstrcmp __vbastrcmp 'сравнивает 2 строковые переменные - аналог API функции lstrcmp __vbavartsteq 'сравнивает 2 Variant переменные __vbaFpCmpCy 'сравнивает значение с плавающей точкой с Currency значением [Разблокирование элементов управления] Любой элемент управления на форме может быть видимым или невидимым, доступным или заблокированным. Для установки свойств объектов существует функция __vbaObjSet. Именно с помощью нее можно заблокировать или разблокировать элемент управления и изменить любое из его свойств. Поэтому нам необходимо отлавливать вызов именно этой функции. Откроем например Olly Debugger, найдем эту функцию среди вызываемых программой и поставим на нее бряк нажав кнопку F2. Затем запустим исследуемую программу. Когда бряк сработает - посмотрите окружающий код. Если он напоминает
то вы на верном пути. Как вы думаете, что это за "push 00"? 00h в VB означает FALSE, а FFh TRUE, из этого следует, что данная команда устанавливает свойство в FALSE, то есть возможно это и есть блокировка элемента управления на форме. Но это может быть и установка любого другого свойства формы в TRUE. Так как синтаксис один и тот же, что принадлежность данной команды к изменению свойства блокировки можно установить только анализом окружающего кода, но думаю с этой мелочью вы справитесь сами. [Методика анализа простейших проверок пароля] Нижеследующий текст - мой вольный перевод статьи How to Research Visual Basic с одного из зарубежных сайтов infonegocio.com. За английскую версию текста спасибо ее авторам. Что нам может понадобиться? Любой дизассемблер/отладчик. Подойдет Win32Dasm или Olly Debugger Если вы используете W32Dasm, то функции, используемые программой вы можете посмотреть в меню "Functions" -> "Imports". Если вы будете исследовать базу данных Jet, то помните, что названия функции не говорят сами за себя и вам будет трудно узнать действие, которое выполняет та или иная функция. в данном случае Вам остается только смотреть рекомендации к функциям, которые любезно оставлены программистами. Дыр же в этих драйверах практически нет, поэтому исследовать программы для работы с базами данных довольно сложно. Рассмотрим пример защиты программы паролем. Для удобства поиска нужного кода поставим MessageBox. Откройте Visual Basic, добавьте на форму текстовое поле и кнопку, затем в обработчике щелчка по кнопке напишите следующий код:
Теперь откроем Olly Debugger, загрузим в него прогу (предварительно прогу нужно откомпилировать) и ищем вызов функции rtcMsgBox.
Чтобы отключить проверку пароля - нужно изменить переход по адресу 00401FF9 с условного на абсолютный. Для этого меняем JE на JMP (то есть 74h на EBh). Как видите - такие простенькие защиты VB программ также малоэффективны как и их анвлоги на Delphi или C++ [Взлом паролей в виде разных типов данных] Нижеследующий тест - мой вольный перевод статей с уже указанного выше сайта: infonegocio.com. За английские версии этих статей спасибо их авторам. Когда VB копирует строку в память - Вы ее можете отловить. Для этого нужно поставить бряк на функцию __vbaStrCopy и когда бряк сработает, посмотрите код после je 66047B00 (он содержится в библиотеке и един для всех программ). вам нужно посмотреть содержимое edx-04 (в SoftICE нужно ввести команду d edx-04). При этом вы увидите строчку, с которой работает в данный момент функция.
Поставьте бряк на функцию __vbaStrComp и чуть выше ее вызова будут два push'а - они заносят в стек две Variant переменные для сравнения. Посмотрите содержимое EAX чтобы просмотреть адрес теста. Просмотрите, что лежит по этому адресу, наверняка это правильный пароль.
Поставьте бряк на функцию __vbai4str. Эта функция используется программой для перевода введенной текстовой строки в 4х байтовое число. Когда бряк сработает - посмотрите код ниже - там наверняка будет проца сравнения паролей. Но значение пароля будет в HEX виде (например десятичное число 987654321 равно шестнадцатеричному 3ADE68B1).
Тут мы можем узнать верный пароль или отключить проверку пароля (для этого нужно JNZ заменить на NOP (то есть в данном случае менять нужно байты по адресу 00401B97 с 7520 на 9090) Отличие от предыдущего примера в том, что нужно ставить бряк на функцию __vbaI2Str. Но иногда предварительно производится преобразование строки сначала в 4х байтовое число посредством функции __vbaI2I4, а затем 4х байтовое число преобразуется в двухбайтовое. Эту проверку обойти довольно просто. Ставьте бряк на функцию __vbaR4Str и когда он сработает - пролистните код вниз. Вы увидите переход после проверки. Просто измените условие перехода на обратное.
Замените инструкцию по адресу 00401C38 на 9090 (чтобы в данном месте не выполнялось никаких операций) или измените условный переход на противоположный. На Visual Basic нельзя проверить то, что вы заменили эти байты на два NOP'а (9090). Если у Вас все же возникают опасения, что программа перестанет работать при отсутствии команд, просто введите команды, которые ничего не поменяют, например:
Эти команды однобайтовые и как раз впишутся на место условного перехода Это также сделать очень просто. Ставьте бряк на функцию __vbaR8Str и пролистните ком чуть ниже бряка, Вы увидите процедуру сравнения (FCOMP REAL8 PTR [Address]), после нее идет TEST и jump. Измените условие перехода на противоположное.
Замените инструкцию по адресу 00401C78 на 9090 (чтобы в данном месте не выполнялось никаких операций) или измените условный переход на противоположный. На Visual Basic нельзя проверить то, что вы заменили эти байты на два NOP'а (9090). Если у Вас все же возникают опасения, что программа перестанет работать при отсутствии команд, просто введите команды, которые ничего не поменяют, например:
Эти команды однобайтовые и как раз впишутся на место условного перехода Алгоритм работы бейсиковской процедуры таков. Введенный пароль посимвольно переводится в ASCII коды, которые по очереди XORятся. Затем производится обратный перевод, возможно с предварительными математическими манипуляциями с ASCII кодами. ANSI коды могут XORиться со случайным или фиксированным числом.
Ставим бряк на 00401E8A 51 PUSH ECX и отслеживаем изменение содержимого регистра ECX при прохождении цикла. Когда программа пройдет весь цикл - вы получите полный пароль.
В этом случае ниже скорее всего будет сравнение и переход, при этом CALL [MSVBVM60!__vbaStrComp] может быть использован для сравнения строк. Если не производится обращение к MSVBVM60!rtcBstrFromAnsi тогда с паролем производятся определенные математические манипуляции, при этом он может быть представлен как 2х или 4х байтное число или число с плавающей точкой. Об этих случаях было сказано выше. [Заключение] Надеюсь, что прочитав данную статью Вас уже больше не пугает исследование VB кода. Чтобы потренироваться советую поисследовать мои крякми (лежат на www.dotfix.net в разделе "Разное"), об анализе первого из которых написана статья (лежит на www.dotfix.net в разделе "Статьи"). Второй мой крякми еще никто не осилил ;) Еще раз благодарю авторов сайта infonegocio.com, так как если бы не их туториалы на английском, то этой статьи возможно и не было бы. Удачи и спасибо за то, что дочитали статью до конца
|
|
| ||||||||||||||||||||||||||||||||||||||||||||||