Особенности анализа графических программ Windows

Консольные программы имеют всего одну точку входа. С момента запуска программы и до момента ее завершения управление никогда не передается другим программам (за исключением системных вызовов и параллельных потоков). Программа возвращает управление операционной системе только после завершения. Графическая программа Windows возвращает управление в Windows сразу же по окончании инициализации и создания главного окна. В дальнейшем программа получает управление лишь тогда, когда в одно из ее окон приходит сообщение. При этом управление передается в ту точку входа программы, которая связана с данным окном, — в оконную или диалоговую функцию. С помощью классической схемы метода Step-Trace, описанной выше, можно трассировать только главную точку входа в программу (функцию WinMain) и функции, непосредственно вызываемые из нее. Для того чтобы применить этот метод к оконным и диалоговым функциям, а также функциям программы, вызываемым из оконных или диалоговых функций, метод Step-Trace необходимо модифицировать. При использовании модифицированного метода Step-Trace для анализа оконных функций и функций, вызываемых из них, следует вначале выбрать точку входа в программу, из которой имеется прямая передача управления в интересующую нас функцию х. Другими словами,

нужно получить адрес оконной функции окна, в котором пользователь дает команду выполнить действие, ведущее к вызову функции х. Проще всего сделать это, воспользовавшись утилитой Spy++, поставляемой в составе пакета Microsoft Visual Studio. Данная утилита позволяют, указав мышью окно, получить практически полную информацию об этом окне, в том числе и адрес его оконной функции. Использование утилиты Spy++ иллюстрирует рис. 7. В данном случае утилита Spy++ применена для получения адреса оконной функции главного окна калькулятора Windows. Этот адрес

указан в строке Window Ргос и равен 01006118. После того как адрес оконной функции получен, нужно поставить в нее точку останова. Не следует ставить точку останова в самое начало функции — в этом случае программа будет останавливаться на

ней при приходе в окно любых сообщений, в том числе и сообщений, совершенно не интересных с точки зрения анализа программы (например, сообщения о том, что окно необходимо перерисовать).

Обычно оконная функция начинает свою работу с анализа идентификатора

пришедшего сообщения (это второй параметр оконной

Рисунок. 7 Окно свойств окна, выдаваемое утилитой Spy++

функции, он располагается в стеке по адресу [ebp + 0Сh]). В подавляющем большинстве случаев аналитика интересует лишь реакция оконной функции на сообщение WM_COMMAND (111h), приходящего в окно, когда пользователь выбирает пункт меню, нажимает специальную комбинацию клавиш, например [Ctrl-Ins], или выполняет

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

mov еах, [ebp + ОС]

cmp еах,lllh

jne. . .

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

После того как в нужную оконную функцию установлена точка

останова, можно начинать трассировку программы. В качестве исходной точки для трассировки берется эта точка останова. В остальном применение метода Step-Trace в этом случае ничем не отличается от его применения в консольных приложениях.

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

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

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

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

Предположим, что интересующее нас диалоговое окно создано с помощью функции DialogBoxParamW. Мы запускаем анализируемую программу под отладчиком, устанавливаем точку останова на функцию DialogBoxParamW и даем программе команду на создание диалогового окна. Программа останавливается на только что установленной точке останова. Четвертым параметром функции DialogBoxParamW является указатель на диалоговую функцию создаваемого окна, этот адрес размещается в стеке по адресу [ebp + 14h]. После того как адрес диалоговой функции окна стал известен, нам остается лишь поставить точку останова в диалоговую функцию и дальше действовать так же, как в случае, когда функция х относится ко второму классу.

Особым случаем является анализ диалоговых функций программ, написанных в среде MFC. Для этих программ не только оконная функция диалогового окна, но и диалоговая функция являются стандартными системными функциями, не имеющими никакого отношения к анализируемой программе. Как правило, программа получает данные, введенные пользователем в диалоговое окно, непосредственно из полей объекта C + + , соответствующего диалоговому окну (этот объект принадлежит дочернему классу класса CDialog). Если диалоговое окно является модальным, оно вначале создается как немодальное, а затем для окна вызывается функция CDialog :: DoModal, преобразующая его в модальное диалоговое окно.

Для анализа того, какие данные поступают из диалогового окна в программу, необходимо найти в программе вызовы соответствующих методов класса CDialog, а затем внимательно изучить код, следующий за интересующими аналитика вызовами. Следует иметь в виду, что хотя по возвращении управления из функции CDialog :: DoModal

диалоговое окно уже не существует как объект графического интерфейса, но соответствующий объект CDialog все еще существует и именно он обычно используется программой для получения данных из диалогового окна. Несмотря на кажущуюся сложность описанной процедуры анализ путей получения данных из диалоговых окон для MFC-программ в среднем выполняется даже быстрее, чем для обычных программ Windows.

Защита программ от анализа

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

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

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

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

За последние 20 — 30 лет в данной области было проведено множество исследований, в результате которых был разработан целый ряд средств и методов, позволяющих увеличить трудоемкость анализа защищаемой программы в десятки раз. В конце 1980-х и начале 1990-х гг. защита программ от анализа применялась очень широко. Доходило до того, что отсутствие в программе средств защиты от анализа рассматривалось как проявление непрофессионализма разработчиков. Однако в первой половине 1990-х гг.

ситуация кардинально изменилась, большинство разработчиков программного обеспечения перестали включать в свои программы средства защиты от анализа. Это обусловлено следующими факторами:

• наличие в программе средств защиты от анализа заметно усложняет

отладку программы и тем самым снижает ее надежность.

Очевидно, что философский вопрос «Кто будет отлаживать защиту

от отладки?» не имеет удовлетворительного ответа;

• защита от анализа может давать ложные срабатывания при запуске

защищенной программы в необычной программноаппаратной

среде: на новой модели процессора, в новой версии

операционной системы, в эмуляторе и т.п. Многим памятна

история о том, как с появлением процессора Pentium I около половины программ, защищенных от анализа, стали обнаруживать

отладчик при любом запуске на этом процессоре;

• механизмы юридической защиты авторских прав за прошедшие годы

сильно усовершенствовались. Для большинства программ необходимость

в защите от анализа программными средствами отпала;

• операционная система реального режима MS-DOS стала вытесняться

операционными системами защищенного режима Windows,

OS/2 и UNIX, в которых защита от анализа реализуется заметно

сложнее.

Сейчас защита от анализа включается в программы довольно

редко, в основном в следующие виды программного обеспечения:

• программы, оснащенные защитой от несанкционированного

копирования, — обычно очень дорогие программы либо программы,

предназначенные для обработки строго конфиденциальной

информации;

• программные закладки, в том числе и компьютерные вирусы.

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

защиты от анализа не оправдывает себя. Пожалуй, самым известным примером чрезмерного увлечения разработчиков программного обеспечения защитой от анализа являются системы защиты от копирования, разработанные компанией StarForce.

До 40 % пользователей программ, защищенных с помощью StarForce, испытывают те или иные проблемы, связанные с системой защиты от копирования [20]. Автору лично приходилось неоднократно сталкиваться с ситуациями, когда лицензионная компьютерная игра, оснащенная защитой StarForce, воспринимает себя как контрафактную копию и отказывается запускаться. Кроме того, некоторые источники

[25] отмечают наличие до августа 2006 г. программных уязвимостей StarForce, позволяющих непривилегированному пользователю несанкционированно получать административные полномочия в операционной системе. Интересно, что CNET начиная с 2006 г. Классифицирует StarForce как вредоносное программное обеспечение.

Существуют специальные программные средства StarFuck и StarForce Nightmare, отключающие защиту от копирования StarForce. Известныи методы обхода некоторых систем StarForce, не использующие специально разработанное программное обеспечение, а использующие лишь широко распространенные программные продукты Alcohol 120 % и Daemon Tools [23].

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

Видимо, Skype защищали от анализа специалисты высочайшей квалификации. Другой пример удачной реализации защиты от анализа — вирус Sober, алгоритм функционирования которого удалось полностью восстановить лишь спустя четыре месяца после начала распространения вируса. Допустим, разработчик, оценив все последствия своего шага, все же решил включить в разрабатываемую программу средства защиты от анализа. Технически это может быть сделано одним из двух способов.

1. Встроенная защита. Средства защиты от анализа включаются

непосредственно в исходный текст программы в ходе ее разработки.

Данный подход позволяет реализовывать наиболее мощную защиту,

практически непробиваемую за приемлемое время. С другой стороны,

проектирование и кодирование встроенной защиты весьма трудоемко

и сильно затрудняет отладку и сопровождение программного продукта.

2. Пристыковочная защита. Средства защиты от анализа пристыковываются

к готовому программному модулю с использованием

«вирусных» алгоритмов уже после компиляции модуля. В этом случае

защита от анализа не оказывает никакого влияния на отладку и сопровождение

программного продукта. Разработка защитных функций

выполняется отдельной группой программистов, никак не связанной

с программистами, разрабатывающими основную функциональность

защищаемого продукта. Часто создание пристыковочной защиты от

анализа поручается отдельным фирмам, есть даже фирмы, специализирующиеся

на создании пристыковочных защит, например упомянутая

выше StarForce. Если к мощности защиты от анализа не предъявляются

повышенные требования, то для защиты программы может

быть применена типовая система, ранее разработанная для другого

программного продукта или вообще универсальная, способная пристыковаться

практически к любому программному модулю заданного

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

сделана очень мощной — как только аналитик сумеет «прорваться»

через барьер, создаваемый пристыковочной защитой, дальнейший

анализ программы не вызывает никаких проблем.

Далее мы рассмотрим типовые методы защиты программ от анализа. Сразу отметим, что ни один из этих методов, примененный по отдельности, не дает заметного эффекта. Для построения по-настоящему мощной защиты следует применить в одной программе не

менее 10 —15 различных методов защиты от анализа. Классифицировать методы защиты от анализа весьма сложно. Существующие классификации имеют множество недостатков и в настоящем пособии мы не будем пытаться строить стройную классификацию, а просто перечислим методы подряд, в более-менее произвольном порядке.

Наши рекомендации