Print This Post Патчим байт-код Java на лету

Вторник, 23. Декабрь 2014
Раздел: Java, автор:

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

Речь пойдет о правке байт-кода Java, как видно из названия статьи. Когда-то давно я уже писал подобную статью про модификацию официального приложения VK под Android, но там я просто патчил байт-код, содержащийся в .class-файле. Теперь мы сделаем примерно то же самое, но на лету, без внесения изменений в файлы.

Начну с небольшой предыстории, зачем мне это вообще понадобилось (многие из моих статей все-таки связаны с какой-то реальной проблемой, которая у меня внезапно возникла). Итак: мне написал человек и попросил "помочь" с программой Lazy SSH. На первый взгляд программа ничем не выделялась, обычный .exe, определяемый PEiD, как: Microsoft Visual C++ 6.0 [Overlay]. Однако, наличие секции экспортов у исполняемого файла меня насторожило, а ее содержимое подсказало, с чем я имею дело: все экспортируемые функции обладали префиксом _Java_com_regexlab_j2e_, который недвусмысленно намекает, что программа на Java была чем-то преобразована в .exe. Google подсказал, что для этого был использован Jar2Exe от RegExLab. Также Google подсказал способ получения .jar-файла из исполняемого файла, по крайней мере для этого случая. Перейдем к делу.


Поместим файл e2j-agent.jar в директорию с Lazy SSH и установим переменную окружения в соответствии с мануалом:

Теперь запускаем Lazy SSH. Мы получили .jar-файл. Беглый просмотр содержимого в JD-GUI показывает, что файл дополнительно ничем не защищен и реализация лицензионного механизма довольно тривиальна.

jd-gui
Сначала возникает мысль поправить .jar-файл, но по неизвестной мне причине (я не знаток Java, да и разбираться не было желания), этот файл не запускается, выдавая ошибку: Error: Invalid or corrupt jarfile.

Что ж, давайте воспользуемся тем же способом, что и e2j, который, судя по всему, имеет доступ к исполняемому байт-коду. Способ называется Java Agents и эта небольшая статья описывает необходимые основы для использования его в своих целях. Теперь нам нужно понять, как именно мы будем править байт-код. Пролистав содержимое метода formWindowOpened, можно отметить, что его квинтэссенция состоит в выполнении этих строк при удачной проверке лицензии:

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

tail
Теперь давайте определим байт-код, соответствующий интересующим нас строкам кода. Мы его используем для замены кода в хвосте метода. Для определения я использовал IDA, хотя можно было бы воспользоваться, например, radare2.

ida

Несколько минут, и у нас есть следующие соответствия:

А заменяемому фрагменту кода:

Соответствует следующая последовательность:

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

И еще один класс, реализующий интерфейс ClassFileTransformer:

На мой взгляд код не нуждается в особом комментировании, но идея такова: в методе transform мы проверяем имя загружаемого класса, далее ищем сигнатуру, соответствующую байт-коду в конце интересующего нас метода, если находим, то производим замену и возвращаем измененный байт-код. Ну а hexToByteArray, findPattern, computeFailure - это вообще вспомогательные методы, взятые из Google. Как вы могли заметить, байт-код, которым заменяется оригинальный код, дополнен нулями, 0x00 - это NOP для JVM (список инструкций JVM), конечно, можно было бы поставить RET (0xB1), но опять же, во время тестов что-то не срослось и я решил оставить замену в текущем виде.

Еще нам потребуется Manifest для нашего jar-файла:

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

source и target - для совместимости с более ранними версиями Java (так как я собирал с помощью JDK 8), директория jagent содержит .java-файлы, состоящие из кода, который я привел выше, ну а manifest.txt, естественно, содержит текст манифеста.
Протестируем получившийся Hook.jar, поместив его в директорию с программой Lazy SSH. Для удобства запуска я сделал простой .bat-файл:

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

Скачать: исходный код из статьи + Lazy SSH.

 Обсудить на форуме


Получать обновления на почту:     

Метки: , , , .

Комментариев: 51 к “Патчим байт-код Java на лету”

  1. Рад нескольким вещам, что блог не пустует и как всегда радует интересными статьями. И ещё, что упомянули radare2 :) Thx! Есть отдельная презентация, посвященная анализу Java - http://radare.org/get/radare_java.pdf

    [Ответить]


  2. zloid :

    В таком духе побольше бы статей. Спасибо.

    [Ответить]


  3. Cronus :

    Дай тебе бог здоровья, Каими. С рождеством

    [Ответить]

    Kaimi:

    Спасибо, дядя

    [Ответить]


  4. CHE :

    Это кто там такой тебя просил, что ты так углубился в проблему? (=

    [Ответить]

    Kaimi:

    Кто-то. Имена не сообщают, да и я все равно не запоминаю.

    [Ответить]


  5. Андрей :

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

    [Ответить]

    Kaimi:

    Это было актуально 5 лет назад.

    [Ответить]


  6. Игорь :

    Большое спасибо за статью.
    Но скачав Lazy SSH. Запустив его, начал проверять аккаунт, и вылезли ошибки, мол типа аккаунт не корректный, ну и естественно треды не разморозились.

    [Ответить]

    Kaimi:

    А какие были ожидания? В конце статьи приложен оригинальный Lazy SSH. Чтобы его запустить в "особом" режиме необходимо в соответствии со статьей воспроизвести все этапы (кроме написания кода).

    [Ответить]


  7. Игорь :

    Благодарю, Kaimi.

    [Ответить]


  8. Lamin :

    Помоги разобраться,скачал,так же вылезли ошибки, какие этапы надо воспроизвести,непонял (

    [Ответить]

    Kaimi:

    Код собрать в jar, сделать bat-файл и запустить...

    [Ответить]


  9. yanik :

    Привет.

    Собрал jar, кинул его в каталог с lazy, пробую запустить батник появляется черное окно консоли и сразу же закрывается. При этом запуск lazy не происходит. Можешь подсказать почему так происходит?

    [Ответить]

    Kaimi:

    Не могу, надо через консоль запускать и смотреть, что происходит

    [Ответить]


  10. yanik :

    Не могу почему то ответить на коммент.
    Открыть cmd.exe и написать сначала set JAVA_TOOL_OPTIONS=-javaagent:Hook.jar
    , а потом "путь\Lazy SSH.exe"?

    [Ответить]

    Kaimi:

    В статье Hook.jar и Lazy SSH находились в одной директории, плюс текущая рабочая директория в cmd была той же.
    В противном случае видимо везде пути нужны полные.

    [Ответить]


  11. yanik :

    Пробовал по-разному писать в батнике пути:

    и как у вас в статье
    и с полным путем

    Сам lazy запускается только если в батнике написано вот так:

    start "" "полный_путь\Lazy SSH.exe"

    А со строкой
    set JAVA_TOOL_OPTIONS=-javaagent:Hook.jar
    уже не запускается.

    Еще пробовал первую строку писать так:
    set JAVA_TOOL_OPTIONS=-javaagent:путь\Hook.jar
    Но наверно это не правильно

    [Ответить]

    Kaimi:

    Может быть, в любом случае я не знаток Java, может есть какие-то особенности...

    [Ответить]


  12. FlexSDK :

    Как этот jar собрать из java файлов?
    Пробовал с помощью Java Development Kit через командную строку, но никак не могу понять, как перепрыгнуть на новую строку с пустым полем... Нажимаю Enter - копируется старая строка. А вот, чтобы так получилось (http://pad3.whstatic.com/images/thumb/3/31/Create-JAR-File-Step-5.jpg/670px-Create-JAR-File-Step-5.jpg), какую команду надо юзать?

    [Ответить]

    Kaimi:

    Google -> как скомпилировать java в jar

    [Ответить]

    FlexSDK:

    @Kaimi, я нашел как скомпилировать java в jar. У меня вопрос совсем в другом.
    Как сделать, чтобы с каждой новой строки были новые пути, как на скришоте?
    http://pad3.whstatic.com/images/thumb/3/31/Create-JAR-File-Step-5.jpg/670px-Create-JAR-File-Step-5.jpg

    [Ответить]

    Kaimi:

    Я не понимаю, что значит новые пути с каждой строки. Может человек набрал путь в консоли, нажал enter и сделал скриншот.


  13. FlexSDK :

    Ну вот я компилирую жабу в jar по этой инструкции
    http://ru.wikihow.com/создать-JAR-файл
    Для компиляции используется Java Development Kit (JDK) и командная строка.
    Инструкция более, чем понятна, но не могу понять, как сделать эти пути в одной и той же консоли.
    p.s. гугл не помог.

    [Ответить]

    Kaimi:

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

    [Ответить]


  14. FlexSDK :

    Ну да, я не АС в программировании.
    Но и ваша статья уж извините не рассчитана на опытных реверсеров =))

    [Ответить]

    Kaimi:

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

    [Ответить]


  15. Ramyx :

    Kaimi подскажите с вами есть какая то связь, хотелось бы предложить вам небольшую работу за вознаграждение.

    [Ответить]

    Kaimi:

    В разделе О Блоге все указано

    [Ответить]


  16. Pop :

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

    [Ответить]

    Kaimi:

    Идешь на exelab и заказываешь отвязку софта, если приспичило.

    [Ответить]


  17. Pop :

    Да не то чтобы приспичило, я готов подождать, главное скажи что ты его скинешь))) Есть у кого получилось что и у Kaimi ??

    [Ответить]

    Kaimi:

    У меня его нет. Я сделал то, что хотел, написал статью и удалил.

    [Ответить]


  18. Artur :

    Kaimi у меня вопрос есть. Можно на javascript написать спамбот как на basic? вот на подобии такого: Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Timer1.Start()
    Timer1.Enabled = True
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    Timer1.Stop()
    Timer1.Enabled = False
    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    Timer1.Interval = TextBox4.Text
    If CheckBox1.Checked Then
    SendKeys.Send(TextBox1.Text)
    SendKeys.Send("({enter})")
    Я не знаю как реализовать на java:( Заранее большое спасибо за ответ.

    [Ответить]

    Kaimi:

    Java != JavaScript. Без разницы на чем писать, если есть возможность использовать необходимые вещи. Если весь смысл бота на VB сводился к вставке текста в форму и нажатии клавиши enter, то для этого даже готовый софт найти можно настраиваемый.

    [Ответить]

    Artur:

    Ок. Ну я обобщил про Java и enter:D Мне это надо на смартфон андроид реализовать. Просто готовые работы в play markete не работают на новой os marshmallow 6.0.1:( Вот я и хочу приложение для андроид написать на java.

    [Ответить]

    Kaimi:

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


Оставьте ваш комментарий