Как стать автором
Обновить

Комментарии 24

Надо было ещё через proguard прогнать. Тогда расшифровка дала бы не слишком много.
Почему именно proguard? Это далеко не лучший обфускатор для java. Но целью ставилось обойти именно эту защиту, а работа с обфусцированными классами это уже вообще другая история.
Ну я и имею в виду, что защита куцая. При том, что заморочились с шифрованием, не провели простейшую обфускацию.

Кстати, а какой лучший обфускатор, по вашему мнению?
Сам пользуюсь yGuard, если нормально настроить, он обеспечивает приемлемую степень защиты. И zelix, как по мне — один из самых лучших, но он платный.
И я бы не сказал, что защита куцая. Минусы обфускаторов налицо — снижение производительности, слабый thread-safe, сложности с диагностикой ошибок на конечном релизе.
Типа у вас вскочил NPE в методе s_$aa012q43 класса QClassQ123. Офигенно понятно.

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

Есть решения с отличной криптостойкостью, они вообще не передают байткод клиенту, а исполняют все по RMI/CORBA. Т.е. у клиента — скелетоны, а серванты с кодом — на сервере разработчика.
> Типа у вас вскочил NPE в методе s_$aa012q43 класса QClassQ123. Офигенно понятно.

Вообще, для этого существует детрейс логов, есть у всех нормальных обфускаторов.
Только в таком случаее надо точно знать версию сборки и хранить карты преобразований для каждой сборки.
Поразительное удобство. А с остальным что делать?
А я ничего не говорил про удобство, просто некоторые личности, используя обфускатор, даже не знают о детрейсе. А потом сами себе голову ломают, где какая фигня отвалилась.
К сожалению, не знаю что там делают yGuard и zelix, но proguard никак производительность не уменьшает, а наоборот, может, даже слегка увеличивает за счет более коротких имен. Собственно, всё, что он делает — это просто убирает (заменяет) информацию об исходном коде, которая во время выполнения совершенно не нужна. Мало того, по полученным «непонятным» стектрейсам легко восстановить исходный стектрейс, так что всё именно офигенно понятно.

А вот понимание декомпилированного кода с бессмысленными именами переменных и функций — занятие значительно более трудозатратное, чем готового исходного кода. Сколько усилий надо потратить, чтобы найти класс Ranger, если все классы теперь называются aa, ab, ac и тд.? Так что замена имен переменных это, можно сказать, естественный и необходимый шаг, если вы не хотите открывать свой код. А в описанной вами защите этот шаг сделан не был.

А насчет клиента-сервера — тут уже неважно на чем написан сервер и вообще, зашифрован ли его код, код сервера вы никак получить не сможете (без физического доступа к нему и при реализации без ошибок, разумеется).
НЛО прилетело и опубликовало эту надпись здесь
В java названия переменных используются и в байткоде. Например, загрузка класса происходит по его имени. Длиннее имя класса — слегка дольше надо сравнивать строки. Разумеется, это всё очень маленькие накладные расходы, но тем не менее, они есть.
В этом смысле производительность, наоборот, возрастет, т.к. обычно обфускаторы сокращают имена переменных и классов: a, aa, aA (зависит от конкретного обфускатора и настроек). Заодно и размер сократится.
Производительность ухудшается по другой причине — если включены агрессивные опции, то во flow добавляются ложные/холостые условия, методы и т.д.
Сильно сомневаюсь, что длина идентификатора играет хоть какую-нибудь роль в производительности на современных JVM.
Возможно, в топик заглянет TheShade и и авторитетно разъяснит, как оно на самом деле.
НЛО прилетело и опубликовало эту надпись здесь
А как же Reflection?
Сколько усилий надо потратить, чтобы найти класс Ranger, если все классы теперь называются aa, ab, ac и тд.?
Любая библиотека для работы с байт-кодом (например, BCEL) + немного времени и вот уже эти непонятные aa, ab и ac превратились в Class_12, Interface_23, Exception_34.

Ещё немного времени + IDE с поддержкой рефакторинга — и вот уже интересующие нас участки вполне себе читаемы.

Может мы и не узнаем никогда, что в юности Class_42 звался Ranger, но так ли нам важна его девичья фамилия?

Если обфускатор занимается только переименованием идентификаторов, он ни на что серьёзное не годен. Правильный обфускатор должен корёжить граф наследования, тасовать методы и поля, запутывать алгоритм непрозрачными вычислениями. Последнее, правда, влияет на быстродействие.
Да зачем библиотека? На это годен и ProGuard со специальными словарями имен (как раз из Class_N и Member_N). Локалы приводятся в нормальный вид простым гроханьем их таблицы.
Специализированная утилита может произвести более интеллектуальное переименование, чем просто замена одних случайных имён на другие, чуть менее случайные.
Например, явно разделить интерфейсы, классы, enum-ы, классы-наследники Exception и RuntimeException облегчив таким образом дальнейший анализ.
Пользуясь случаем, поздравляю всех с Новым Годом!

А теперь по делу, описанный подход известен довольно давно: blogs.oracle.com/sundararajan/entry/retrieving_class_files_from_a, еще одна статья — www.javaworld.com/javaworld/javaqa/2003-05/01-qa-0509-jcrypt.html

Метод не является универсальным, т.к., например, zenofx ClassGuard попытки подключения через Agent блокирует. Здесь, на Хабре, я публиковал статью с хорошим методом обхода подобной защиты: Против лома нет приёма: OpenJDK hack vs. Class Encryption
В немного измененной версии защиты я запретил запуск с не-oracle JVM. Тем более, что этот метод (а точнее, уже существующая утилита) делает это намного быстрее, проще и удобнее.

И по поводу блокирования подключения агента. Один мой знакомый колдовал над усовершенствованием данной защиты, сказал, что в нативной части запретил подключения агента. Не знаю, как и что он там делал, но утилита беспрепятственно сдампила все классы приложения без остатка.
Это все конечно клево. Но в чем поинт? Если бы вы научились классы релоадить как это делает JRebel — меня бы это если честно больше впечатлило, чем перевод простенького туториала под Java Agant'у +ClassLoader'у и дописывания 10 строк кода.
Где Вы тут видите перевод туториала? А в чем понт написано в самом начале статьи, прочтите внимательнее.
Раз: docs.oracle.com/javase/tutorial/ext/basics/load.html
Два: dhruba.name/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/

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

Публикации

Истории