Ljava lang string android

Русские Блоги

Обратный путь Android: глубокое понимание инструкций байт-кода Davilk и файлов Smali

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

Вы можете следить за моим блогом, чтобы узнавать о моем настроенииРеки и озера называют маленьким белым братом

Дескриптор Davilk

Подобно JVM, байт-код Davilk также имеет набор методов для описания типов, методов и полей. Эти методы в сочетании с инструкциями Davilk образуют полный ассемблерный код.

Байт-код и тип данных

Байт-код Davilk имеет только два типа: базовые типы и ссылочные типы. Объекты и массивы являются ссылочными типами. Описание типов байт-кода в Davilk согласуется с правилами дескриптора в JVM: для базовых типов и void без возвращаемого значения Тип представлен заглавная буква, а тип объекта представлен буквой L плюс полное имя объекта. Массив представлен символом [, и конкретные правила таковы:

Какое полное имя
В качестве примера возьмем String, ее полное имя — java.lang.String, тогда его полное имя — java/lang/String; , То есть «.» В java.lang.String заменяется на «/», а точка с запятой «;» добавляется в конце как терминатор.

тип java Дескриптор типа
boolean Z
byte B
short S
char C
int I
long J
float F
double D
void V
Тип объекта L
Тип массива [

Здесь мы сосредоточимся на объяснении типов объектов и типов массивов:

Тип объекта

L может представлять любой класс в java-типе. На него ссылается package.name.ObjectName в java-коде, а его описание в Davilk Lpackage/name/ObjectName; Форма представления. L — это тип класса java, определенный выше, что означает, что следует полное имя усталого объекта. Например, описание, соответствующее java.lang.String в java, выглядит следующим образом: Ljava/lang/String; .

Тип массива

[Типы используются для представления массивов всех основных типов, за которыми следуют дескрипторы базовых типов. Каждое измерение использует начальное значение [.
Например, int [] в java представлен ассемблерным кодом. [I; . Двумерный массив int [] [] равен [[I; , Использование трехмерных массивов [[[I; Сказал.

Для массива объектов за [следует полный квалификатор соответствующего класса. Например, String [] в java соответствует [java/lang/String; .

Описание поля

Описание поля в Davilk разделено на два типа: описание поля базового типа и описание ссылочного типа, но формат описания у них одинаковый:
Дескриптор типа объекта -> имя поля: дескриптор типа;
Например, есть поле имени типа String и поле возраста типа int в классе com.sbbic.Test, тогда его описание выглядит следующим образом:

Описание метода

Сигнатура метода в java включает имя метода, параметры и возвращаемое значение. Соответствующее правило описания в Davilk:
Дескриптор типа объекта -> имя метода (дескриптор типа параметра) дескриптор типа возвращаемого значения

Для иллюстрации воспользуемся несколькими примерами, например java.lang.String:

Набор инструкций Davilk

Освоив описание вышеуказанных полей и методов, мы можем только сказать, что мы понимаем, как описывать поле и метод, а для конкретной логики в методе нам необходимо понимать набор инструкций в Dalvik. Поскольку Dalvik основан на Архитектура на основе регистров, набор инструкций Он сильно отличается от набора инструкций в JVM, но больше похож на инструкции сборки в x86.

Инструкции по определению данных

Инструкции определения данных используются для определения констант, классов и других данных, используемых в коде. Основная инструкция — const.

инструкция описание
const/4 vA,#+B Присвойте значение регистру vA после расширения знака до 32
const-wide/16 vAA,#+BBBB Знак — расширить значение до 64 бит и назначить регистровую пару vAA
const-string vAA,[email protected] Присвойте значение строки регистру vAA через индекс строки
const-class vAA,[email protected] Получить ссылку на класс через указатель типа и присвоить ее регистру vAA

Инструкции по работе с данными

Команда перемещения используется для операций с данными, что означает перемещение пункта назначения, источника, то есть данные данных перемещаются из регистра источника (регистр источника) в регистр назначения (регистр источника), который может понимать операцию присваивания между переменными в java. • В зависимости от байт-кода и типа «Другой» за командой перемещения будет следовать другой суффикс.

инструкция описание
move vA,vB Назначьте значение регистра vB регистру vA, регистры vA и vB имеют 4 бита
move/from16 vAA,VBBBB Присвойте значение регистра vBBBB (16 бит) регистру vAA (7 бит), from16 указывает, что исходный регистр vBBBB составляет 16 бит
move/16 vAAAA,vBBBB Назначьте значение регистра vBBBB регистру vAAAA, 16 означает, что регистр источника vBBBB и регистр назначения vAAAA являются 16-битными.
move-object vA,vB Назначьте ссылку на объект в регистре vB регистру vA, регистр vA и регистр vB имеют 4 бита.
move-result vAA Назначьте одиночный (32-битный) не объектный результат предыдущей операции вызова инструкции (вызова метода) регистру vAA.
move-result-wide vAA Назначьте двойное слово (64-битный) не объектный результат предыдущей операции вызова инструкции регистру vAA
mvoe-result-object vAA Назначьте объектный результат предыдущей операции вызова инструкции регистру vAA
move-exception vAA Сохраните исключение, возникшее во время последнего запуска, в регистр vAA.

Инструкции по эксплуатации объекта

Операции, связанные с экземплярами объекта, такие как создание объекта, проверка объекта и т. Д.

инструкция описание
new-instance vAA,[email protected] Создайте объект указанного типа и назначьте ссылку на устройство регистру vAA. Объекты массивов сюда не включаются.
instance-of vA,vB,[email protected] Определите, имеет ли ссылка на объект в регистре vB указанный тип, если это так, присвойте v1 значение 1, в противном случае присвойте ему значение 0
check-cast vAA,[email protected] Преобразуйте ссылку на объект в регистре vAA в указанный тип и присвойте результат vAA в случае успеха, в противном случае будет выброшено исключение ClassCastException.

Инструкции по работе с массивом

В примере инструкций по работе мы не нашли инструкции по созданию объекта, Davilk устанавливает специальную инструкцию для операций с массивами.

инструкция Описание
new-array vA,vB,[email protected] Создайте массив указанного типа и размера (заданного регистром vB) и назначьте его регистру vA.
fill-array-data vAA,+BBBBBBBB Заполните массив указанными данными, vAA представляет собой ссылку на массив (адрес первого элемента массива)

Инструкции по работе с данными

Операции с данными в основном бывают двух типов: арифметические операции и логические операции.
1. Инструкции по арифметическим операциям

инструкция Описание
add-type Инструкция по добавлению
sub-type Инструкция по вычитанию
mul-type Инструкция умножения
div-type Инструкция по разделу
rem-type попрошайничество

2. Инструкции по расчету логического элемента.

инструкция Описание
and-type И инструкция
or-type ИЛИ инструкция
xor-type Инструкция по вычислению элемента XOR

3. Инструкции по перемещению

инструкция Описание
shl-type Подписанная инструкция сдвига влево
shr-type Подписанная инструкция сдвига вправо
ushr-type Беззнаковая инструкция сдвига вправо

-Type выше указывает тип данных в управляемом регистре, который может быть -int, -float, -long, -double и т. Д.

Сравните инструкции

Инструкция сравнения используется для сравнения размера значения в двух регистрах, и ее основной формат: cmp+kind-type vAA,vBB,vCC , type представляет тип данных сравнения, например -long, -float и т. д .; kind представляет тип операции, поэтому есть cmpl,cmpg,cmp Три вида инструкций сравнения. Coml — это сокращение от compare less, cmpg — это сокращение от compare больше, поэтому cmpl указывает, является ли условие vBB меньше, чем значение в vCC, истинно, если это так, оно возвращает 1, в противном случае возвращает -1 и 0, если оно равно; cmpg означает vBB. Если условие больше значения в vCC, оно вернет 1, в противном случае оно вернет -1, и оно вернет 0, если оно равно.
cmp и cmpg имеют одинаковое семантическое значение, что означает, что vBB больше, чем значение в регистре vCC. Если это правда, вернуть 1, если это правда, иначе вернуть -1, и вернуть 0, если он равен.
Давайте посмотрим на инструкции в Davilk:

инструкция Описание
cmpl-float vAA,vBB,vCC Сравните два числа с плавающей запятой одинарной точности. Если значение в регистре vBB больше, чем значение в регистре vCC, он возвращает -1 в vAA и возвращает 0, если оно равно, и возвращает 1, если оно меньше, чем
cmpg-float vAA,vBB,vCC Сравните два числа с плавающей запятой одинарной точности, если значение в регистре vBB больше, чем значение vCC, оно возвращает 1, равное 0, и меньше -1.
cmpl-double vAA,vBB,vCC Сравните два числа с плавающей запятой двойной точности, если значение в регистре vBB больше, чем значение vCC, верните -1, верните 0, если оно равно, и верните 1, если оно меньше
cmpg-double vAA,vBB,vCC Сравните числа с плавающей запятой двойной точности в соответствии с семантикой cmpl-float
cmp-double vAA,vBB,vCC Эквивалентен инструкциям cmpg-double vAA, vBB, vCC

Инструкции по эксплуатации в полевых условиях

Инструкции по работе с полями представляют собой установку и выборку полей объекта, как и ваши более длинные методы set и get в коде. Основные инструкции: iput-type, iget-type, sput-type, sget-type.type Представляет тип данных.

Операции чтения и записи обычных полей

Инструкции iput-type и iget-type с префиксом i используются для операций чтения и записи полей.

инструкция Описание
iget-byte vX,vY,filed_id Считайте значение поля filed_id в объекте в регистре vY и назначьте его регистру vX
iput-byte vX,vY,filed_id Установите значение поля filed_id в объекте в регистре vY равным значению регистра vX
iget-boolean vX,vY,filed_id
iput-boolean vX,vY,filed_id
iget-long vX,vY,filed_id
iput-long vX,vY,filed_id

Операции чтения и записи статического поля

Инструкции типа sput и sget с префиксом s используются для операций чтения и записи статических полей.

инструкция Описание
sget-byte vX,vY,filed_id
sput-byte vX,vY,filed_id
sget-boolean vX,vY,filed_id
sput-boolean vX,vY,filed_id
sget-long vX,vY,filed_id
sput-long vX,vY,filed_id

Инструкция по вызову метода

Большинство инструкций методов в Davilk очень похожи на инструкции в JVM. В настоящее время существует пять наборов инструкций:

инструкция Описание
invoke-direct,methodtocall Прямой метод вызова экземпляра, то есть частный измененный метод. В это время вам необходимо отметить, что первый элемент в () представляет текущий объект экземпляра, то есть this и следующие являются реальными параметрами. Например, инструкция invoke-virtual
invoke-static,methodtocall Вызвать статический метод экземпляра, в это время () — все параметры метода.
invoke-super,methodtocall Вызов родительского метода
invoke-virtual,methodtocall Вызвать виртуальный метод экземпляра, то есть открытый и защищенный измененные методы.
invoke-interface,methodtocall Вызов метода интерфейса

Эти пять инструкций являются базовыми. Кроме того, вы также встретите инструкции invoke-direct / range, invoke-static / range, invoke-super / range, invoke-virtual / range, invoke-interface / range. Единственная разница между Тип и приведенные выше инструкции заключаются в том, что последние могут устанавливать диапазон регистров, который могут использовать параметры метода, который используется, когда имеется более четырех параметров.

Опять же, для нестатических методов структура () имеет вид (текущий объект-экземпляр, параметр 1, параметр 2, . параметр n), а для статических методов это

Следует отметить, что если вы хотите получить возвращаемое значение выполнения метода, вам необходимо получить результат выполнения через указанную выше инструкцию move-result.

Инструкция возврата метода

В Java во многих случаях нам нужно вернуть результат выполнения метода через Return, а также инструкция возврата, предоставленная в Davilk, чтобы вернуть результат выполнения:

инструкция Описание
return-void Ничего не вернуть
return vAA Возвращает 32-битное значение не объектного типа.
return-wide vAA Возвращает 64-битное значение не объектного типа.
return-object vAA Ссылка на тип объекта

Инструкция по синхронизации

Синхронизация последовательности инструкций обычно представлена ​​блоком операторов synchronized в java. JVM поддерживает семантику ключевого слова synchronized посредством инструкций monitorenter и monitorexit, а Davilk также предоставляет две аналогичные инструкции для поддержки синхронизированной семантики .:

инструкция Описание
monitor-enter vAA Получить операцию блокировки для указанного объекта
monitor-exit vAA Отменить операцию блокировки для указанного объекта

Инструкция по исключению

Давным-давно виртуальная машина также использовала инструкции jsr и ret для реализации исключений, но теперь JVM выбросила исходный метод и вместо этого использует таблицы исключений для реализации исключений. Davilk по-прежнему использует инструкции для реализации:

инструкция Описание
throw vAA Бросить исключение указанного типа в регистр vAA

Инструкция по прыжкам

Инструкции перехода используются для перехода от текущей адресной строки к указанному смещению и в основном используются в ветвях if и switch. Davilk предоставляет инструкции goto, Packaging-Switch и if-test для реализации операций перехода.

инструкция действующий
goto +AA Безусловный переход к указанному смещению (AA — смещение)
packed-switch vAA,+BBBBBBBB Инструкция перехода по переходу.Значение в регистре vAA должно оцениваться в ветви переключения, а BBBBBBBB — это значение индекса в таблице смещения (упакованная полезная нагрузка переключения).
spare-switch vAA,+BBBBBBBB Команда перехода на переход похожа на упакованное переключение, за исключением того, что значение индекса в таблице смещения BBBBBBBB (резервное переключение-полезная нагрузка)
if-test vA,vB,+CCCC Команды условного перехода используются для сравнения значений в регистрах vA и vB. Если условия выполняются, переход к указанному смещению (СССС — смещение), test представляет правило сравнения, которое может быть eq.lt и т. Д. .

В условном сравнении тест в if-test представляет собой правило сравнения. Эта инструкция используется часто, поэтому мы просто садимся и объясняем:

инструкция Описание
if-eq vA,vB,target Регистры vA и vB равны, что эквивалентно if (a == b) в java. Например, if-eq v3, v10, 002c означает, что если условие истинно, переход к текущей позиции + 002c. Остальное похож
if-ne vA,vB,target Эквивалентно if (a! = B) в java
if-lt vA,vB,target Значение в регистре vA меньше vB, что эквивалентно if (a b)
if-gt vA,vB,target Эквивалентно if (a > b)
if-ge vA,vB,target Эквивалентно if (a >= b)
if-le vA,vB,target Эквивалентно if (a b)

В дополнение к приведенным выше инструкциям Davilk также предоставляет условную инструкцию с нулевым значением, которая используется для сравнения с 0, что можно понимать как установку значения регистра vB в приведенной выше инструкции на 0.

инструкция Описание
if-eqz vAA,target Эквивалентно if (a == 0) или if (! A) в java
if-nez vAA,target Эквивалентно if (a! = 0) или if (a) в java
if-ltz vAA,target Эквивалентно if (a 0)
if-gtz vAA,target Эквивалентно if (a > 0)
if-lez vAA,target Эквивалентно if (a 0)
if-gtz vAA,target Эквивалентно if (a >= 0)

Прикрепил:
Выше мы сказали, что есть две таблицы смещения, упакованные-переключатели-полезные данные и запасные-переключатели-полезные данные. Единственная разница между ними заключается в том, в порядке ли значения в таблице. Мы сделаем это позже Подробное объяснение.

Инструкции по преобразованию данных

Преобразование типов данных хорошо знакомо любому разработчику Java и используется для реализации взаимного преобразования двух разных типов данных. Базовый формат инструкции: unop vA, vB, что означает работу с медианным значением регистра vB и результатом. Хранится в реестре vA.

инструкция Описание
int-to-long Преобразование в длинное целое число
float-to-int Преобразование типа с плавающей запятой одинарной точности в целое число
int-to-byte Преобразование в байтовый тип
neg-int Инструкция дополнения, дополнить целое число
not-int Инструкция отрицания, отрицать целое число

До сих пор мы сделали краткое описание инструкций в Davilk. Инструкции Davilk в значительной степени объединены с инструкциями x86, а также структурой и семантикой инструкций JVM, поэтому в целом инструкции в Davilk по-прежнему очень легко изучить. Подробнее Подробнее подробные инструкции, пожалуйста, обратитесь к:Полный комплект инструкций Davilk

Подробный файл smali

Выше мы представили соответствующие инструкции Davilk, давайте познакомимся с файлом smali.Хотя мы используем java для написания приложений Android, Davilk не загружает файл .class напрямую, а оптимизирует файл .class до .dex с помощью инструмента dx. Затем файл загружается с помощью Davilk. Таким образом, мы не можем напрямую анализировать файл apk путем анализа .class, но нам нужно использовать инструмент baksmali.jar для декомпиляции файла dex для получения соответствующего файла smali. Файл smali может можно рассматривать как файл кода раздела слова Davilk, но они не полностью эквивалентны.

Каждый .smali декомпилируется с помощью baksmali.jar, который соответствует классу в java. Каждый файл smali состоит из инструкций Davilk и следует определенной структуре. В smali есть много ключевых слов для описания соответствующей java. В файле все ключевые слова начинаются с «.» обычно используются следующие ключевые слова:

Ключевые слова Описание
.filed Определить поля
.method. end method Метод определения
.annotation Аннотация к определению
.implements Определите инструкции интерфейса
.local Задает количество используемых локальных переменных
.registers Укажите количество используемых локальных регистров
.prologue Указывает начало кода в методе
.line Представляет указанную строку в исходном файле Java
.paramter Параметры метода указаны.

Многие люди здесь не понимают .local и .register. Если вы тоже, пожалуйста, ознакомьтесь с приведенными выше пунктами о регистрах.

Ниже мы кратко объясним структуру файла smali:

  1. Описание заголовка файла

Первые три строки файла smali описывают текущую информацию о классе:

Содержимое в <> означает обязательное, а [] означает необязательное.
Модификаторы доступа — это так называемые общедоступные, защищенные и закрытые по умолчанию. Модификаторы без привилегий относятся к final, abstract.
Например:

После заголовка файла идет тело файла, то есть основная часть класса, включая четыре части описания интерфейса, описания аннотации, описания поля и описания метода, реализованного классом. Давайте посмотрим на структуру полей и методов соответственно. (Не забывайте. (Представление методов и полей мы сказали в Davilk)

Описание интерфейса

Если класс реализует интерфейс, он будет определен в .implements и имеет следующий формат:

smali добавил к нему аннотацию #Interface

Описание аннотации

Если в классе используется аннотация, она будет определена с помощью .annotation: ее формат следующий:

Описание поля

Поля описаны в smali. Мы знаем, что Java делится на статические поля (атрибуты класса) и обычные поля (атрибуты экземпляра). Их представление в smali выглядит следующим образом:

1. Общие поля:

Модификаторы доступа вам уже хорошо знакомы, а модификаторы без привилегий здесь — final, volidate и transient.
Например:

2. Статические поля
Знание статических полей добавляет статику к определению общих полей и имеет следующий формат:

Примечание: файлы smali также являются статическими полями, а обычные поля добавляются с комментариями #static field и #instan filed соответственно.

Описание метода

.Method используется в smali для описания метода. Конкретный формат определения выглядит следующим образом:

1. Прямой метод
Прямой метод — это так называемые прямые методы. Вы все еще помните инструкцию вызова метода invoke-direct в Davilk? Забытые детские туфли смотрят на нее сами по себе, поэтому я не буду объясните это здесь.

Сосредоточьтесь на объяснении параметра:
Количество параметров соответствует количеству параметров метода, то есть есть несколько параметров .parameter , По умолчанию начинается с 1, то есть p1, p2, p2 .
Детская обувь, знакомая с java, помнит, что этот тип метода имеет параметр по умолчанию, указывающий на текущий объект. В smali параметр объекта по умолчанию для метода представлен как p0.

Следует отметить, что smali добавил к нему аннотацию метода #direct

2. Виртуальный метод
Единственное различие между определением виртуального метода и прямого метода — это комментарий: #virtual methods, формат следующий:

  1. Файловая структура smali внутреннего класса

Файл smali внутреннего класса немного отличается, и конкретное проявление состоит в том, что имя файла файла smali, соответствующего внутреннему классу, — [имя внешнего класса $ имя внутреннего класса.smali], более подробное описание см. Ниже.

Структура файла smali также очень ясна и понятна. Его также очень удобно читать после знакомства. Давайте взглянем на простой файл smali. Чтобы облегчить понимание, мы сначала вставляем фрагмент java-кода:

Давайте проанализируем smali, который декомпилирован из этого фрагмента кода. В коде

Заключительные замечания

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

Источник

Читайте также:  Информация про робота андроида
Оцените статью