System loadlibrary android so

Отладка приложений для Android без исходных кодов: native методы

О чем эта статья

В двух предыдущих статьях я рассказывал как отлаживать приложения для Android без исходного кода на Java и о некоторых особенностях установки breakpoints. Если уважаемый читатель ещё не ознакомился с этими статьями — я настоятельно рекомендую начать с них, а уже потом читать эту статью.

Так уж вышло что до сих пор я рассказывал исключительно об отладке байткода Dalvik и ни словом не обмолвился об отладке native методов. А ведь именно в native методах часто скрывается самое вкусное — хитрые защиты, интересные malware фичи, уязвимости нулевого дня. Поэтому сегодня я сжато, без «воды», расскажу как отлаживать native методы без исходного кода на C/C++ (ну или на чем, уважаемый читатель, они у вас там написаны).

Что бы извлечь пользу из моего рассказа нужно быть уже немного «в теме». В частности желательно что бы читатель

  • понимал синтаксис Smali, мог вписывать в .smali файлы свой код и мог отличить декларации и вызовы native методов от обычных методов, умел пересобирать .apk файлы используя Apktool;
  • представлял себе что такое Java Native Interface (JNI) и как это работает;
  • знал для чего используются методы System.load(. ) и System.loadLibrary(. ), как они работают в Android, и по аргументам этим методов в Smali коде мог самостоятельно определить в каких .so библиотеках находятся JNI функции соответствующие тем или иным native методам;
  • умел найти эти JNI функции в .so библиотеках;
  • хотя бы на начальном уровне знал ассемблер ARM (в статье предполагается что отладка будет выполняться на устройстве с архитектурой ARM либо на эмуляторе который эту архитектуру эмулирует);
  • имел какой-то опыт работы с gdb и gdbserver;
Читайте также:  Как почистить память андроида внутренняя память заполнена

Вот пожалуй и все знания и навыки которые будут нужны читателю. Перейдём к инструментам.

Инструменты

Сегодня нам понадобится:

  • gdb и gdbserver для ARM из последней версии Android NDK. Установка описана тут.
  • Утилита adb из последней версии Android SDK. Установка описана здесь.
  • Если отладка идёт на реальном Android-устройстве — на нём нужны права root.

Перейдём к подготовке.

Подготовка

Предполагается что читатель достаточно опытен что бы самостоятельно выполнить следующие подготовительные действия:

  • Дизассемблировать .apk файл приложения с помощью Apktool, исследовать файлы в поддиректории папка/куда/дизассемблировали/приложение/smali и выяснить:
    • какие native методы вызываются из байткода Dalvik;
    • в какой .so библиотеке находятся соответствующие этим методам JNI функции;

  • Вытащить эту .so библиотеку из поддиректории папка/куда/дизассемблировали/приложение/lib либо с устройства на котором будет производиться отладка, исследовать её и узнать как называются JNI функции которые соответствуют тем или иным native методам вызываемым из байткода Dalvik.
  • Пересобрать .apk приложение с помощью Apktool с оцпией -d и загнать под отладку в NetBeans как написано в этой моей статье.
  • Сделать так, что бы отладка в NetBeans остановилась после вызовов System.loadLibrary(. ) или System.load(. ) , которые загружают .so с интересующими нас JNI функциями, но до первого вызова какого-либо из native методов. Можно использовать трюк о котором я писал тут.
  • Запихнуть gdbserver на устройство или эмулятор на котором отлаживаем.

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

Отладка

Идея в том, что бы загнать наше приложение сразу под два отладчика: под отладчик встроенный в NetBeans — что бы отлаживать байткод Dalvik, и под gdb — исключительно что бы отлаживать вызовы native методов. Звучит слегка странно, но на практике вполне себе работает. Хотя и не всегда — см. следующий раздел «Подводные камни».

Итак, если читатель выполнил все подготовительные действия из предыдущего раздела «Подготовка», то сейчас у него на устройстве или эмуляторе наверняка запущено пересобранное приложение, на компьютере открыт NetBeans и отладка стоит где-нибудь после вызова System.load(. ) или System.loadLibrary(. ) , но ещё до первого вызова native метода. Причем читатель уже в курсе в какой библиотеке какие JNI функции каким native методам соответствуют. С этого мы и начнём.

Дальше идёт пошаговая инструкция. Она писалась для Windows, но думаю будет работать и для Linux и MacOS. Пожалуйста, следуйте инструкции в точности:

  1. Командной abd shell откройте ADB консоль вашего устройства или эмулятора. Найдите PID процесса вашего приложения воспользовавшись командой ps в ADB консоли. В этой же консоли выполните команду:
    где %PID% и есть PID процесса вашего приложения. В ответ gdbserver должен вывести что-то вроде:
    Начиная с этого момента отладка в NetBeans «замёрзнет». Т.е. вы конечно сможете там кликать на кнопки, но это бесполезно т.к. приложение которое вы пытаетесь отлаживать в NetBeans в данный момент остановлено под отладчиком GDB. Не паникуйте, всё так и должно быть!
  2. Откройте новую консоль на вашем компьютере, выполните команду
  3. В этой же консоли запустите gdb из Android NDK:
    где libMyNativeLibrary.so — та самая .so библиотека в которой находятся интересующие нас JNI функции. Библиотека должна лежать на вашем компьютере в каталоге который для gdb является текущим при старте. В результате откроется консоль gdb.
  4. В консоли gdb наберите следующие команды:
    После этих манипуляций в консоли gdb должно появится сообщение наподобии
    а в консоли ADB (она у нас ещё открыта, помните?) что-то типа
  5. В консоли gdb выполните
    что бы увидеть список функций. В списке среди прочих функций должны быть и интересующие вас JNI функции, что-то типа:
  6. В консоли gdb поставте breakpoints на адреса интересующих вас JNI функций, в нашем случае это
  7. Возобновите выполнение вашего приложения с помощью команды c в gdb консоли. После выполнения этой команды, отладка в NetBeans «размёрзнется» и вы снова сможете отлаживать байткод Dalvik.

Теперь, каждый раз когда в байткоде Dalvik будет встречаться вызов native метода вроде
отладка в NetBeans будет «замерзать», зато gdb будет вас радовать сообщениями вроде

Вот это собственно оно и есть. Дальше x/i $pc , stepi — в общем вперёд отлаживать одну ARM-инструкцию за другой (помните я говорил в начале что ARM ассемблер будет нужен? — ну вот. )

Подводные камни

О, их тут много. Целый сад подводных камней. Вот наиболее запоминающиеся глюки, которые попались мне при использовании GNU gdb (GDB) 7.4.1 в связке с GNU gdbserver (GDB) 7.4.1 на Android 4.0.3 в устройстве Ainol Aurora (той, старой ещё):

Источник

Читайте также:  Teac плеер для андроид
Оцените статью