Локализация кода модуля защиты посредством отлова WinAPI-функций в режиме отладки

Задача локализации кода модуля защиты ПО достаточно легко может быть решена злоумышленником с помощью современных средств отладки путем отслеживания вызовов WinAPI функций, используемых разработчиком. Использование стандартных WinAPI функций в настоящее время является неотъемлемым стилем программирования Windows-приложений. Практически любое из них для реализации стандартных действий (вывод на экран сообщений, доступ к тексту редактируемого окна, доступ к файлам и т.д.) использует вызовы данных функций. Основная проблема для разработчиков средств защиты заключается в том, что современные отладчики позволяют без существенных проблем установить точки прерывания по условию вызова известных им функций. Используя данный факт, злоумышленник может получить доступ к программному коду, расположенному вблизи места данного вызова, после чего продолжить изучение кода с помощью средств отладки.

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

Наиболее распространенными Win32 API функциями, используемыми производителями для выполнения стандартных действий, являются следующие.

1. MessageBoxA(hWnd,lpText,LpCaption,uType) – вывод на экран стандартного окна сообщения (например, сообщения об ошибочной регистрации).

2. MessageBoxIndirectA(lpMsgBoxParams) – вывод вариантов окна, с различными кнопками (retry, abort, ignore).

3. GetDlgItemTextA(hDlg,nIDDlgItem,lpString,nMaxCount) – чтение информации, введенной пользователем в окне TEdit.

4. GetWindowTextA(hWnd,lpString,nMaxCount) – чтение информации, введённой пользователем в окне TEdit.

Функции GetDlgItemTextA или GetWindowTextA могут использоваться разработчиком в модуле защиты для чтения ключевой информации, введенной пользователем в окне ввода. Многие модули защиты вслед за этим производят сравнение введенной информации с эталонной.

В качестве менее распространенной функции, выполняющей чтение информации из окна TEdit, можно привести следующую.

5. hmemcpy(lpMemTarget,lpMemSource,nBytes) – используется Windows для копирования участков памяти, а значит, может использоваться и при чтении ключевой информации из введенного окна.

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

ЗАМЕЧАНИЯ. В некоторых случаях, пока пользователь не введёт верную ключевую информацию, кнопка подтверждения ввода неактивна. Тогда использование прерываний по функциям MessageBoxA, MessageBoxIndirectA, GetDlgItemTextA, GetWindowTextA бесполезно. В данном случае злоумышленник вынужден пользоваться hmemcpy.

6. GetTickCount() – возвращает число миллисекунд со времени запуска системы.

Данная функция часто используется разработчиками для реализации защиты, заключающейся в том, что в незарегистрированной версии программы через определённые промежутки времени появляется информация, убрать которую невозможно в течение некоторого время (nag screen). Отловив вызов данной функции, злоумышленник выходит на процедуру реализации данной защиты и отключает её.

7. GetDriveTypeA(lpRootPathName) – возвращает тип диска (например, 3-HDD, 5-CD).

Разработчик ПО может использовать данную функцию для привязки своей программы к CD (для предотвращения запуска с винчестера). Отловив вызов данной функции, злоумышленник может проставить тип диска вручную либо отключить механизм проверки.

8. RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition) – создание ключа в системном реестре.

Данная функция достаточно часто используется производителями ПО для сохранения в реестре служебной информации (пароля, даты установки программы, количества запусков и т.д.). Отловив вызов данной функции, злоумышленник может раскрыть и получить доступ к конфиденциальной информации либо отключить механизм проверки ключа.

9. Функция SetTimer() и сообщения WM_Timer. Их отлавливание может использоваться злоумышленником для взлома программ, защищённых выводом nag-screen.

10. FindFirstFile(lpFileName,lpFindFileData) – осуществляет поиск в директории файла с заданным именем.

Функция может использоваться злоумышленником для взлома программ, сохраняющих конфиденциальную информацию в служебных, системных, скрытых файлах, файлах инициализации и т.д. Для этих же целей может использоваться отлов функции FindNextFile(hFindFile,lpFindFileData). Злоумышленник, отловив данные функции, может выяснить информацию о файлах, где хранится ключевая информация.