Welcome to ROOTPWN!

Реверс софта на Java. Уровень первый - пересобираем JAR файл.

Регистрация
10 Дек 2018
Сообщения
9
Симпатии
22
#1
Привет. В этой статье я подробно опишу как пересобирать джарники, запиливая туда свой код.

Нам понадобится:
- JDK (конкретно для этой статьи нужна будет восьмая мажорная версия, дальше поймёте почему)
- IDE с детектом ошибок (в моём случае это NetBeans)
- Браузер
- grep
- Любой архиватор, поддерживающий ZIP
- Знание самого языка Java (уровень зависит от сложности приложения, которое вы разбираете)
- Программа-донор (в статье я издеваюсь над Maltego 4.1.6, вы можете использовать что угодно)

Ахтунг! Статья предназначена для опытных домохозяек со стажем мытья посуды не менее двух сезонов сериала! Если описываемые здесь действия для вас слишком сложные, то подучите Java и перед ознакомлением с нижеизложенным материалом прочтите вот эту статью.

Немного разъяснений перед тем, как я начну. Во-первых, описываемый алгоритм не обязательно должен быть одинаковым для всего софта, написанного на Java. Этот, казалось бы, очевидный нюанс тем не менее вызывал у меня поначалу боль в анусе, так как приходилось постоянно тратить кучу времени на копание вообще в каком-то говне, вместо того, чтобы читать код на блюдечке. Это решается углублением в изучение Java, в особенности т.н. Java Core, про который можно узнать, гугля вопросы с собеседований по этой теме.
Далее, программа Maltego была выбрана мною не зря - я уже расковыривал версию 4.0.0 XL, и поэтому у меня не занял много времени поиск нужной инфы и участков кода. С нуля делать всё это, конечно, достаточно заморочно.

Ну а теперь...
Погнали!

Итак, начнём с того, что запустим сам мальтего. Приветствовать он нас будет красивым загрузочным экраном с прогрессбаром, а когда все приготовления будут окончены, он порадует нас симпатичным окошком, предлагающим вам на выбор аж целых четыре стула:
1544618832431.png

Теперь у нас есть примерное представление о том, что программа делает прежде всего (ну, помимо запуска фотонных торпед, разумеется), и мы можем приступить к поиску нужных JAR-файлов для последующего вскрытия.
Начнём с запуска. Команда терминала maltego приводит нас к /usr/bin/maltego:

Посмотрим что же там внутри... Ага:
Bash:
#!/bin/sh

cd /usr/share/maltego/bin/
exec ./maltego --jdkhome /usr/lib/jvm/java-8-openjdk-$(dpkg --print-architecture)/jre/ "[email protected]" 2>/dev/null
Значит, у нас запускается /usr/share/maltego/bin/maltego. Очевидно, это либо бинарь, либо такой же баш скрипт, как и /usr/bin/maltego. Что ж, заглянем в него. Делаем geany /usr/share/maltego/bin/maltego и ууух ё!
1544619390047.png
Итак, хорошая новость - это таки баш скрипт. Плохая - придётся в нём копаться. Ну да ладно, почему бы и нет.
Дабы не заставлять вас проделывать все те же операции, что и я, сразу скажу, что скрипт делает кучу проверок на разную нужную хрень (включая то, что JRE у вас не выше восьмой версии, хз почему), первым запускается у нас maltego/platform/lib/boot.jar
Декомпилируем файл на уже знакомом нам по первому мануалу (кто не читал - ссылка в шапке) сайте, https://javadecompilers.com
Внутри всего один пакет - org.netbeans, но в нём дофига классов:
1544629832217.png
Вот тут уже понадобится IDE. Дело в том, что зачастую в таком сраче идут многочисленные ссылки на другие классы, перекрёстные ссылки, ссылки "через посредника", ссылки друг на друга и на самого себя, ссылки на вложенные классы... В этом бедламе разобраться в простом редакторе не выйдет, нужна специальная IDE. Подойдут Eclipse, NetBeans и IntelliJ IDEA, я уже привык работать в бобах, поэтому воспользуюсь ими.
Перед этим grep-аем весь пакет на наличие точки входа. В Java это public static void main(String[] args). Таких методов может быть несколько, в этом случае в компиль-тайме задаётся один из них. Переключаться между несколькими точками входа после компиляции и сборки нельзя. Итак, вывод grep в нашем случае будет следующий:
1544631335520.png
Ага, три класса. Что-то мне подсказывает, что, во-первых, их три не просто так, а во-вторых, что в Main как раз расположена точка входа, но нет кода.
Проверяем:
Java:
package org.netbeans;

import java.util.ResourceBundle;
import javax.swing.JOptionPane;
import org.netbeans.MainImpl;

public final class Main {
    private Main() {
    }

    public static void main(String[] args) throws Exception {
        try {
            Class.forName("java.lang.ReflectiveOperationException");
        }
        catch (ClassNotFoundException ex) {
            JOptionPane.showMessageDialog(null, ResourceBundle.getBundle("org.netbeans.Bundle").getString("MSG_InstallJava7"), ResourceBundle.getBundle("org.netbeans.Bundle").getString("MSG_NeedsJava7"), 2);
            System.exit(10);
        }
        MainImpl.main(args);
    }

    public static void finishInitialization() {
        MainImpl.finishInitialization();
    }
}
И да, я оказался прав - кода тут не было и в помине. Ну да ладно, на данном этапе нас это не особо должно волновать. Наша цель сейчас - пересобрать джарник с изменённым кодом, а уж что там дальше в коде - дело десятое. Вставим сразу после объявления метода main() такую строчку:
Java:
JOptionPane.showMessageDialog(null, "Recompiled by Sonic", "Success!", 1);
И сохраним файл.
Теперь, когда у нас есть отредактированный код, нам надо как-то пропихнуть его в собранный JAR-файл. Делать это можно двумя способами, оба используют утилиту jar из JDK. Первый способ заключается в использовании jar --update, а второй, который я и опишу, - в разархивировании джарника и сборке его по новой. Зачем это делать? Отвечаю. Прежде всего, распаковка и упаковка будет производиться штатными средствами JDK, а не архиватором, во-вторых, после JDK ваш JAR-файл будет валиден и будет содержать всю необходимую информацию, т.е. после пересборки нужных частей и переупаковки джарника с подменёнными классами не будет нарушаться целостность файла.
Итак, разберём наш boot.jar:
1544632070160.png
В принципе, хватит и jar -xf boot.jar, но -v даёт более подробный вывод, который можно потом отследить при помощи, например, less. Для тех, кто в танке, команда получится такой:
Код:
jar -xvf boot.jar | less
Итак, мы разобрали JAR-файл и морально готовы к тому, чтобы, злорадно хохоча, варварским образом заменить православный исходный код нашим пахакирским. Скомпилированный изменённый класс кладём вместо исходного в папку, после чего собираем JAR обратно:
1544637162805.png
Здесь, думаю, нужно дать немного пояснений. Для утилиты jar в режиме create(-c или --create) -M будет означать "не генерировать манифест" (он у нас есть от исходного файла), а -C <dir> <file> говорит, что надо взять в директории ./ файл . и добавить его в JAR на выходе, что равносильно "взять всё".
Теперь кидаем наш новый boot.jar на место старого (не забудьте забэкапить старый!) и, скрестив пальцы, пишем в терминале maltego...

Получилось!
Что ж, статья вышла довольно длинной, поэтому спасибо тем кто сумел таки это дочитать, я искренне надеюсь, что вам было интересно. В следующий раз мы будем бороться с обфускацией кода и пробовать восстанавливать неправильно декомпилированные участки.
 

Вложения

Сверху Снизу