Понимание разборки кода Dalvik?
Я играю с smali и baksmali в небольшом Android-приложении Hello World, которое я написал. Мой исходный код:
package com.hello;
import android.app.Activity;
import android.os.Bundle;
public class Main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
который затем был разобран на:
.class public Lcom/hello/Main;
.super Landroid/app/Activity;
.source "Main.java"
# direct methods
.method public constructor <init>()V
.locals 0
.prologue
.line 6
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
return-void
.end method
# virtual methods
.method public onCreate(Landroid/os/Bundle;)V
.locals 1
.parameter "savedInstanceState"
.prologue
.line 10
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
.line 11
const/high16 v0, 0x7f03
invoke-virtual {p0, v0}, Lcom/hello/Main;->setContentView(I)V
.line 12
return-void
.end method
Я понимаю, что это какое-то промежуточное представительство, но я не уверен, что это такое. Как я понимаю, должна быть некоторая спецификация о том, как понимать это представление, но я не могу понять, как его искать. Итак, учитывая файл apk, может ли кто-нибудь объяснить в терминах непрофессионала, как используется спецификация кода операции Dalvik для получения этого представления? Мое нынешнее понимание таково:
- Имея APK, я мог бы извлечь AndroidManifest.xml в двоичном формате XML и использовать инструмент, такой как axml2xml.pl, чтобы получить "текстовую" версию манифеста, которая не завершена, ИЛИ я мог бы использовать apktool, чтобы получить более читабельный форма. Но я все еще не уверен, какую спецификацию они используют для преобразования двоичного XML в текст.
- Дизассемблеры каким-то образом используют спецификацию кода операции Dalvil для чтения файлов d ex и преобразования их в вышеприведенное представление.
Любая информация (возможно, с некоторыми простыми примерами) о двух вышеупомянутых шагах очень поможет мне в правильном понимании концепций.
Обновление 1 (опубликовано после ответа Криса):
По сути, я бы сделал следующее, чтобы получить байт-код Dalvik:
- Возьмите apk и распакуйте его, чтобы получить файлы classes.dex.
Затем дизассемблер читает файл classes.dex и определяет все классы, присутствующие в apk. Можете ли вы дать мне некоторую информацию о том, как это делается? Он анализирует файл в шестнадцатеричном режиме и ищет спецификацию Dalvik, а затем разрешает соответствующим образом? Или что-то еще происходит? Например, когда я использовал hexdump на classes.dex, он дал мне что-то вроде этого:
64 65 78 0a 30 33...
Используются ли они сейчас для поиска кода операции?
- Предполагая, что инструмент смог разделить входящий байт-код на отдельные классы, он затем продолжает сканировать шестнадцатеричные коды из файла classes.dex и использует спецификацию Davlik для вывода соответствующего имени кода операции из таблицы?
На самом деле, короче говоря, мне интересно знать, как делается вся эта "магия". Так, например, если бы я научился писать этот инструмент, какой дорожной карте высокого уровня я должен придерживаться?
2 ответа
То, на что вы смотрите, это байт-код davlik. Код Java переводится в байт-код Dalvik с помощью инструмента dx. Манифест - это отдельная проблема, к которой я вернусь через минуту. Фактически, когда вы компилируете свое приложение Android, инструмент dx преобразует ваш код Java в байт-код (так же, как javac преобразует байт-код Java в Java для стандартного приложения JVM) с использованием 256 кодов операций dalvik.
Например, invoke-super
это код операции, который инструктирует dvm (виртуальная машина dalvik) вызывать метод суперкласса. Так же, invoke-interface
инструктирует dvm для вызова метода интерфейса.
Так что вы можете видеть, что
super.onCreate(savedInstanceState);
переводит на
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)
В этом случае, invoke-super
принимает два параметра, {p0,p1
группа и Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)
параметр, который представляет собой спецификацию метода, которую он использует для поиска и разрешения метода при необходимости.
Тогда есть invoke-direct
вызов в области конструктора.
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
Каждый класс имеет init
метод, который используется для инициализации членов данных класса, также известный как конструктор. Когда вы создаете класс, виртуальная машина также должна вызывать конструктор суперкласса. Это объясняет, почему конструктор для вашего класса вызывает Activity
конструктор.
Что касается манифеста, то, что происходит (это все в спецификациях Dalvik, если вы проверяете исходный код), это то, что компилятор (который генерирует файл apk) преобразует манифест в более сжатый формат (двоичный xml) для целей экономии места. Манифест не имеет ничего общего с кодом, который вы разместили, он больше инструктирует dvm о том, как обрабатывать приложение целиком в отношении Activities
, Services
и т.д. То, что вы опубликовали, - это то, что на самом деле исполняется.
Это ответ высокого уровня на ваш вопрос. Если вам нужно больше, дайте мне знать, и я сделаю все возможное.
Вы в основном правы. Декомпилятор считывает двоичные данные как поток байтов из файла dex. Он понимает, каким должен быть формат, и способен извлекать такую информацию, как константы, классы и т. Д. Что касается кодов операций, это именно то, что он делает. Он понимает, каково значение байта для каждого кода операции (или как оно представлено в файле dex), и может преобразовать его в удобочитаемую строку. Если бы вы собирались реализовать это, помимо понимания общих основ компиляторов, я бы начал с глубокого понимания структуры файла dex. Оттуда вам нужно будет создать таблицу, которая сопоставляет значения кода операции с удобочитаемой строкой. С этой информацией и некоторой дополнительной информацией о строковых константах и т. Д. Вы можете создать представление скомпилированного класса в текстовом файле. Имеет ли это смысл?
Спецификация кода операции описывает только инструкции. Формат файла dex - это нечто большее: он содержит все метаданные, необходимые для Dalvik VM (и дизассемблера) для интерпретации файла - строки, классы, типы, методы и так далее. Смотрите также официальную спецификацию кода операции, она более полная и подробная, чем та, на которую вы ссылались.
<plug>
Кстати, следующая версия IDA Pro будет поддерживать разборку.dex файлов</plug>