Easy Hack: Java application

от автора

Время от времени пентестерам приходится сталкиваться с Java-приложениями. Это могут быть различные серверы, клиенты или просто десктопные программы. И иногда возникает необходимость «пропатчить» такое приложение. Зачем это нужно? Каждый случай возникновения такой необходимости уникален. К примеру:

  • Сложный протокол общения между сервером и клиентом. Чтобы отправлять произвольные запросы – патчим;
  • Захардкожены настройки. Чтобы поменять – патчим;
  • Для демонстрации последствий проблем типа «race condition» – патчим.

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

Application

Для рассказа нам понадобится подопытное приложение. Конечно, мы напишем его сами. Его структура на рисунке 1.

image
рисунок 1

Как видим, оно достаточно простое: два класса, которые запускают приложение и рисуют GUI. Вот их исходники. Main.java:

1    package com.mycompany;  2      3    public class Main  4    {  5        public static void main(String[] args)  6        {  7            javax.swing.SwingUtilities.invokeLater(new Runnable()  8                {  9                    public void run() {  10                       new Window();  11                   }  12               });  13       }  14   }  15 

Window.java 1    package com.mycompany;  2      3    import com.mycompany.Targets.*;  4    import javax.swing.*;  5      6    public class Window extends JFrame  7    {  8        private JPanel panel1;  9        private JLabel Level1Value;  10       private JLabel Level2Value;  11       private JLabel Level3Value;  12     13       public Window()  14       {  15           super("Simple example");  16     17           Level1Value.setText(new Level1().getText());  18           Level2Value.setText(new Level2().getText());  19           Level3Value.setText(new Level3().getText());  20     21           getContentPane().add(panel1);  22     23           setSize(300,100);  24           setLocationRelativeTo(null);  25     26           setVisible(true);  27           setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);  28       }  29   }  30 

Классы очень простые. Main – создаёт окно Window. Window – печатает текст в 3 поля. Текст он берёт из наших целевых классов, на примере которых мы и будем рассматривать способы модификации. Как выглядит запущенное приложение, смотрите на рисунке 2.

image
рисунок 2

Из инструментов нам понадобится только JDK и JavaDecompiler. Приступаем к патчу.

Level 1

Наше приложение – это jar-архив. Для начала просто вставляем его в JavaDecompiler и получаем исходник интересующего нас класса. Level1.java:

1    package com.mycompany.Targets;  2      3    public class Level1  4    {  5        public String getText()  6        {  7            return "Data";  8        }  9    }  10 

Замечательно, теперь мы копируем этот код в текстовый файл с расширением «java». Это самый простой класс, который только можно придумать. Теперь меняем этот исходник, как пожелаем. Мы заменили возвращаемое значение на «My msg». Далее выполняем команду:

image

В результате мы получим готовый Level1.class. Затем нам нужно просто добавить его в наш jar-архив. Сделаем это следующей командой:

image

Обратим внимание, что мы создали путь, идентичный названию пакета, в котором расположен наш класс, и переложили туда бинарник.
Результат – на рисунке 3.

image
рисунок 3

Рассмотрим случай посложнее.

Level 2

Проделываем всё то же самое и получаем исходник. Level2.java:

1    package com.mycompany.Targets;  2      3    public class Level2  4    {  5        public String getText()  6        {  7            return "Super " + (new Level1().getText());  8        }  9    } 

В нём я поменяю «Super» на «New». И попытаюсь скомпилировать:

image

Не получилось, потому что в классе есть ссылка на другой объект из этого пакета. Но java очень дружелюбна и позволяет указать при компиляции любой путь, где лежат классы. Т.е. можно просто выполнить команду:

image

В результате, у нас опять готовый бинарник. Точно так же обновляем jar-архив и смотрим результат на рисунке 4:

image

image
рисунок 4

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

Level 3

Декомпилируем наш класс. Level3.java:

1    package com.mycompany.Targets;  2      3    import jd.core.CoreConstants;  4      5    public class Level3  6    {  7        public String getText()  8        {  9            return CoreConstants.class.getSimpleName() + " "  10                   + (new Level2().getText());  11       }  12   } 

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

image

И опять же, java выручает своей дружелюбностью. Ей можно просто указать путь, где лежат jar-архивы зависимостей. Делается это так:

image

(да, тут указание пути класса лишнее, т.к. он запакован в архив и лежит в той же директории, но т.к. это не всегда так, я его всё же указал)

И далее всё так же – результат на рисунке 5.

image

image
Рисунок 5

Итог

В итоге мы рассмотрели примеры, как просто и быстро можно модифицировать Java-приложения. Конечно, рассмотрели мы на примере jar-архива, но вы же понимаете, что если классы не запакованы, то всё гораздо проще?

ссылка на оригинал статьи https://habrahabr.ru/post/282934/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *