Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #65, АПРЕЛЬ 2006 г.

штурм зимнего .net'а

N|M{INT3 TEAM} (NIM@INT3.RU)

Спецвыпуск: Хакер, номер #065, стр. 065-042-4


наш главный пример

посвящен обфускатору Decompiler.NET $550 с гордой надписью в документации: «Decompiler.NET protects itself». Наверное, автор этой записи был или очень храбрый, или очень глупый ;). Почему же я выбрал именно этот обфускатор? Объяснение очень простое: мне очень не понравился дизайн сайта (www.junglecreatures.com), хотя и его название мне понравилось не больше. Тем не менее, по моему требованию на главную роль в главном примере статьи был приглашен именно обфускатор Dotfuscator Professional Edition for .NET $1495. Во-первых, потому что его цена великовата, во-вторых, потому что вот уже целый месяц я не могу получить его trial-версию. Чтобы добыть trial, ты заполняешь специальную форму, после чего появляется надпись: «Note: Acceptance of registration is not guaranteed.». Вот оно что! Посмотреть trial могут только избранные. На самом деле причина, конечно, другая: они не уверены в своем обфускаторе :).

вернемся к decompiler.NET.

Этот обфускатор по совместительству является дизассемблером, декомпилятором, оптимизатором, рефактором и Show MSIL :). Автор защиты — один из тех, кто верит, что если устроить настоящее MSIL-шоу, никто ни в чем не разберется. Однако первое, что ты видишь, когда открыл файл в Reflector'е, — это два необфусцированных name space'а (jungle.Deploy.NET.Launcher и jungle.Deploy.NET.Launcher.Licensing). Хм, само по себе очень подозрительно и привлекает внимание, как оазис в пустыне. Вот почему я не стал поддаваться на провокации/заниматься почитанием традиций и начал исследование с метода, помеченного атрибутом .entrypoint. В нем не было ничего интересного. Через определенное количество вызовов функций (.entrypoint->ab.a3::ah1(string[])->ab.a3::ah0(string[])) мы попадаем в ag0. В данном методе есть вызов метода string a4.a8::aba(int32). После просмотра кода стало ясно, что эта функция извлекает из коллекции зашифрованную строку под номером int32, переданном в параметре, и расшифровывает ее. Соответственно, я сделал функцию (DumpCryptedStrings), которая перебирает все строки в коллекции, расшифровывает их и печатает в отладчике в окошке Output. Эту функцию ты сможешь посмотреть в файле Decompiler.NET.h на диске к журналу. Ее вызов закомментирован в .entrypoint, а файл содержит более подробные комментарии относительно анализа кода.

Далее мы попадаем в функцию ab.az::ag2(string, bool, string, object[]). Первое, что привлекает внимание здесь, — это создание дополнительных доменов приложения System.AppDomain::CreateDomain (читаем матчасть). Ага! Код обфусцирован. Кроме того, мы имеем дело еще и с пакером/криптером: динамическое создание доменов предполагает динамическую загрузку сборок. А какие еще сборки необходимо загрузить динамически, если не распакованные? Схема простая: в определенный момент ресурс программы расшифровывается, потом распаковывается и динамически загружается в память. Наша задача — выяснить, когда наступает такой момент, и сделать дамп. Кроме того, в этой функции наблюдается вызов: L_00e9: callvirt instance bool jungle.Deploy.NET.Launcher.IConfiguration::get_CheckLicenseSignature(). Данный вызов нужно закомментировать, а далее — исправить L_00ee: brfalse.s L_0126 на L_00ee: brtrue.s L_0126.

Назад на стр. 065-042-3  Содержание  Вперед на стр. 065-042-5