Дети в сугробах шумно играют в Афганистан.
Я через двор не пойду.
Электрики вешают красные гирлянды в саду.
Синие флаги на ветру.
Поутру новый год - все снова.
Снова, снова все танцуют, все играют в снежки.
Взвожу курки -Так я стал предателем...
Аукцион, "Новогодняя песня", альбом "Как я стал предателем", 1989
В этой статье я попытался сделать обзор Linuxа с точки зрения матёрого крякера, для которого нет ничего святого :-). OpenSource, без сомнения, штука хорошая и полезная. Но - отчего-то постоянно хочется кушать, в том числе и программистам и даже жителям Villabajo (как Вы думаете, почему у них постоянно грязная посуда ?). Представим, что
вы потратили кучу времени и ресурсов, разрабатывая последние несколько месяцев неплохую программу, и даже отчего-то имеете версию для Linuxа. Видимо,
вы хотите окупить затраченные усилия - проще говоря, заработать на своей программе кучу денег. И если
вы не опубликовали свой исходный код, в надежде заработать другими способами (кстати, рассказали бы тогда, какими именно), то необходимо как-то защитить
вашу программу от:
- Несанкционированного копирования. Т.е. программа должна работать только у того, кто её купил, и не должна работать (или работать неправильно, или, что бывает чаще всего, иметь функциональные ограничения) у халявщиков и крякеров.
- Плагиата. Или reverse engeneeringа. Проще говоря, чтобы Ваш уникальный алгоритм не смогли своровать.
Если разработке/снятию защит под DOS/Windows посвящено множество сайтов (включая приснопамятную Fravia), то я лично не видел ни одной работы, посвящённой тому же самому, но под Linux. Между тем уже имеется множество коммерческих программ под эту в общем не самую плохую из распространённых OS. С прискорбием должен отметить, что вся их "защита" составляет максимум 1% от их Windows аналогов, и снимается в худшем случае за пару часов. Я постараюсь объяснить, почему происходит именно так, почему под Linuxом не работают многие традиционно используемые для защиты Win32 программ способы, и возможно после прочтения этого шедевра творчества душевнобольных Вы даже сможете придумать что-то действительно эффективное.
"А кто такой автор, чтобы судить о столь высоких материях ?" - вполне справедливо может спросить читатель. А никто, в сущности. Так, сломал пару десятков программ и решил сделать что-нить полезное. См. эпиграф, в общем...
Итак, в чём же главное отличие Linux от прочих OS ? В доступности исходного кода всего (ну, кроме разве что Вашей программы, стоящей мегабаксы), что работает (или не работает) на
вашей машине. Это делает написание защиты под Linux просто кошмаром - Вы не можете быть уверены, что функция strcmp из стандартной C run-time library - это действительно strcmp, а не её изменённый (обычно не в Вашу пользу) эмулятор. Вы не можете доверять ничему в такой операционной системе - вследствие доступности исходного кода любая её часть может быть модифицирована крякером для взлома
вашей программы, включая такие важнейшие компоненты, как ядро и run-time library. Ваша программа работает в самой агрессивной среде, какую только можно себе представить. В самом деле, если бы Вы могли изменить в Windows 9x, скажем, kernel32.dll (я имею в виду не ковыряние в машинном коде с помощью дизассемблера, хотя +tsehp использовал и такой метод - нет, просто редактирование исходного кода и последующая перекомпиляция - намного эффективнее, не правда ли ?) - разве было бы возможно существование защит вроде VBox ? Я настоятельно рекомендую хорошо подумать об этом как-нибудь на досуге.
А пока у меня для вас плохие новости - ваша программа обязательно будет сломана. Это на самом деле "чиста" экономический вопрос. Представим, что Ваш программный продукт стоит 1000 $. Среднемесячная зарплата неплохого программиста из нашей
страны едва ли составляет 200$. Таким образом, если какой-нибудь парнишка из Сибири затратит на слом Вашего творения меньше 5 месяцев - он будет экономически выгоден. Заметьте, что здесь ни слова не было сказано ни об операционной системе, под которой работает Ваш шедевр, ни о сложности и стоимости использованной системы защиты.
Что же делать - идти в монастырь (хотя, в женский иногда наведываться - наверное, неплохая идея 🙂 ? Вы должны рассматривать защиту своего программного продукта не как 100% средство от Ваших головных болей, а всего лишь как средство, затрудняющее жизнь крякеру. Скажем, если Ваша защита остановит 9 крякеров из 10 - это очень неплохой результат. Конечно, не все 9 остановленных купят Вашу программу, но их будет явно больше, чем для случая, когда Ваша защита сломана 9тью из 10. Впрочем, возможно, что я жёстко не прав - я лично никогда не покупал программных продуктов 🙂
Итак, довольно пустых разговоров. Для начала я сделаю краткий обзор применяемых крякерами инструментов (хотя я склонен рассматривать Linux как один большой инструмент крякера).
Отладчики
Странно, но до сих пор никто не переписал SoftIce под Linux - я лично не вижу этому никаких препятствий. Более того, у меня есть веские доказательства, что это не просто возможно сделать, но и что его реализация будет значительно легче и проще, чем под всякие глючные операционные системы от не-будем-показывать-пальцем-кого. Так что пока с отладчиками намного хуже (для крякеров, для авторов защит - наоборот, хотя ведь отлаживаться всё равно как-то нужно), чем под Win32. Итак, что есть/годно к употреблению (см. также раздел Debuggers на
LinuxLinks):
- GDB. Отладчик userlevel mode. Загружает файлы с помощью BFD. Что-то вроде старого недоброго debug из DOSа. Также оформлен как библиотека. К нему есть множество интерфейсов, наиболее удобный для X Windows IMHO DDD (требует LessTif). Также заслуживает отдельного упоминания
SmartGDB. Крайне интересная идея прибить сбоку отладчика script engine. Я не знаю аналогов под Win32, но вещь в результате получилась очень любопытная с точки зрения автоматизации труда крякера -
вы можете написать script (в данной конкретной реализации это TCL; я лично предпочёл бы Perl, или что-либо C-like, но ради такой штуки можно и TCL выучить), который посадить затем как триггер на точку останова. Ваш script смог бы например проверить переменные в отлаживаемой программе, и в зависимости от их значения, например, поставить новую точку останова (с новым scriptом), сбросить кусок памяти в файл, сварить какаву... - Remote host Linux kernel debugger via GDB from SGI
- Kernal level debugger от всё той же SGI. Пока крайне сырая вещь (и требует нестабильной версии кернела), но может служить прототипом для более пригодных к использованию изделий 🙂
Дизассемблеры
Без сомнения IDA Pro. Также иногда можно на скорую руку использовать Biew, objdump (или даже ndisasm, дизассемблер от Netwide Assembler), но это несерьёзно. Мне больше неизвестны инструменты, которые позволяют дописывать к ним новые процессорные модули, загрузчики для нестандартных форматов файлов, а также plugins, облегчающие автоматический/интерактивный анализ. К тому же Ильфак грозился выпустить как раз версию под Linux (как иронично :-). Хит третьего сезона подряд, в общем. Ладно, на этот раз обойдусь без обычных наездов :-).
strace
или truss под UnixWare. Аналог regmon/filemon/BoundsChecker в одном флаконе. Ядро Linuxа имеет поддержку перехвата системных вызовов (функция ptrace). Т.е. можно запустить любой процесс как подлежащий трассировке через ptrace, и Вы сможете отследить все системные вызовы с их параметрами. Более того, после небольшой модификации эта функция (которая имеет доступ к виртуальной памяти трассируемого процесса) может быть использована, например, для run-time patching, внедрения кода в адресное пространство любого процесса, и так далее, и тому подобное. Пусть кинет в меня камень после всего описанного считающий, что Linux написали не крякеры :-). Если же серьёзно, то я пока не смог выдумать способа, как на userlevel противодействовать этой кувалде. Более того, я пока даже не могу узнать, что мой процесс в настоящий момент трассируется ядром ! Впрочем, пару решений можно придумать:
- Можно написать свой модуль ядра, вследствие монолитной структуры Linux kernelа он будет иметь доступ ко всем структурам ядра, в том числе и к отвечающим за
ptrace... - Менее надёжное, но более простое в реализации средство. Можно вызвать ptrace для самого себя. Если вызов был неудачен - значит, нас уже трассируют, нужно сделать что-нть по этому поводу (sys_exit, например, а не то, что Вы подумали :-). Впрочем, ведь если нас уже трассируют, ничего не стоит перехватить данный вызов и вернуть всё что угодно...
Memory dumpers
Ну, здесь даже и писать ничего нужно. Файловая система /proc может использоваться для таких целей. Файл maps используется как карта выделенной процессу виртуальной памяти, а файл mem является её отображением, можно сделать в нём seek на нужный адрес и легко сохранить необходимый участок в файл или куда-вы-там-хотите. Простая программа на Perlе размером 30 строчек может быть использована для снятия дампа памяти Вашей драгоценной программы и сохранения её в файл. Намного проще, чем под Win32 🙂
Шестнадцатеричные редакторы
С этим тоже никогда не было больших проблем. Даже стандартный просмотровщик Midnight (или Mortal его второе имя) Comanderа умеет редактировать в шестнадцатеричном представлении. Для гурманов рекомендую Biew.
Стандартные средства разработки
Это не шутка. Для модификации ядра/runtime библиотек (а также для создания patchей и keygenов) нужен как минимум компилятор
C. Впрочем, я как-то пару раз писал keygenы на Perlе :-).
Способы защиты
Итак, я надеюсь, Вы ещё не уснули и впали в депрессию. Что же можно противопоставить всему вышеописанному ? Явно годятся далеко не все методы, используемые в Win32. Тем не менее, я смог придумать несколько, и я уверен, что это далеко не всё...
Против BFD (GDB, objdump, strings etc)
BFD - это библиотека для манипуляций с бинарными файлами. По счастливому стечению обстоятельств она используется также отладчиком GDB. Но для ELF формата (наиболее распространённый формат исполнимых файлов под всеми современными Unixами) она реализует неправильный алгоритм загрузки, так что фактически Linux программы можно сделать меньше. Для этого можно использовать
sstrip.
Преимущества:
- Очень простой метод. Берёте Вашу готовую отлаженную программу и вместо команды strip (кстати, а Вы знаете о её существовании и что она делает ? Если нет, настоятельно рекомендую почитать man на ночь)
sstrip. - Помимо всего прочего Вы уменьшите размер размер Вашего дистрибутива. Хотя, глядя на размеры современных дистрибутивов Linuxа, этот аргумент кажется просто смешным...
На этом преимущества заканчиваются и начинаются Сплошные недостатки:
- Поскольку исходники BFD публично доступны, теоретически любой может доработать этот замечательный пакет, так что шансы снова будут не в Вашу пользу. Собственно, Вы должны помнить, что в Linuxе это относится ко всему. Но пока этот метод работает (и глядя на ленивых парней с
HCULinux я готов спорить, что он будет работать ещё долго 🙂 - Через пару дней после написания этого замечательного способа, я, почесав репу, написал довольно простой загрузчик для IDA Pro, так что я лично смогу дизассемблировать обработанные таким образом ELFы без каких-либо затруднений. Кстати, он продаётся 🙂
Данный вариант может рассматриваться как очень простая защита от полных ламеров, rating 0.1%.