Android маленький вопрос

В настоящее время я занимаюсь исследованием smali/"обфускатора кода" и сейчас пытаюсь ознакомиться с декомпилированными исходными кодами. Для этого я создал простое приложение и декомпилировал его с помощью smali.

Сейчас я пытаюсь понять декомпилированный исходный код, чтобы улучшить и сравнить безопасность (против декомпиляции) после использования обфускатора кода позже. Хотя большая часть исходного кода smali не так уж сложна, у меня все еще иногда возникают проблемы с преобразованием формата цифр.

Не могли бы вы объяснить мне, например. следующую строку. Я предполагаю, что оно должно иметь значение пять, но я не уверен, что это за двоичный формат. Как его посчитать 0x4014=5???

const-wide/high16 v0, 0x4014       // 100000000010100        (5 = 101)

Прилагаются полные исходные коды java и smali этой тестовой функции:

Источник Java:

 boolean test(int a, double d) {
        if (a < 5 && d < 5)
            return true;
        else 
            return false;
    }

Смалийский источник:

.method test(ID)Z
    .locals 2
    .parameter "a"
    .parameter "d"

    .prologue
    .line 28
    const/4 v0, 0x5

    if-ge p1, v0, :cond_0

    const-wide/high16 v0, 0x4014

    cmpg-double v0, p2, v0

    if-gez v0, :cond_0

    .line 29
    const/4 v0, 0x1

    .line 31
    :goto_0
    return v0

    :cond_0
    const/4 v0, 0x0

    goto :goto_0
.end method

person Nils    schedule 04.12.2010    source источник
comment
Должен ли я использовать декомпилированный исходный код для повторного запуска в разработке Android?   -  person    schedule 29.02.2012
comment
Откатил стороннее редактирование, которое существенно не соответствовало заданному вопросу - на самом деле это не вопрос обфускации (пока), и он касается представления с плавающей запятой в smali.   -  person Chris Stratton    schedule 20.05.2013


Ответы (3)


К сожалению, байт-код dalvik не делает различий между целочисленными типами (short/integer/long/etc.) и типами с плавающей запятой (float/double). Таким образом, baksmali не может знать, отображать ли такую ​​константу как число с плавающей запятой или целое число, поэтому по умолчанию используется целое число.

Это еще более осложняется наличием инструкций, подобных той, о которой вы упомянули. Со страницы dalvik-bytecode из документации dalvik:

«Переместить заданное литеральное значение (правый-ноль-расширенный до 64 бит) в указанную пару регистров».

Таким образом, эта инструкция фактически загрузит значение 0x4014000000000000 в регистры v0 и v1. Это стандартное 64-битное представление с плавающей запятой IEEE-754. Первый (самый значащий) бит — это бит знака, следующие 11 бит — показатель степени (по основанию 2), а последние 52 бита — мантисса. В этом случае мы имеем бинарное представление

0100000000010100000000000000000000000000000000000000000000000000
SEEEEEEEEEEEMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

Для бита знака 0 положительный, а 1 отрицательный.

В качестве показателя степени вы берете целое значение 11 бит (в данном случае 1025) и вычитаете 1023, чтобы получить показатель степени 2.

А для мантиссы имеется подразумеваемая «1» впереди, в разряде 2^0, а следующими цифрами являются обычные 2^-1, 2^-2 и т. д. Итак, в этом случае мы имеем двоичное число 1,01, или 1*2^0 + 1*2^-2, или 1,25.

Общая форма расчета, используемая для значения:

-1^(2+S) * M * 2^E

Где S, M и E — знак, мантисса и показатель степени.

В этом случае у нас есть -1 ^ (2 + 0) * 1,25 * 2 ^ 2 = 1 * 1,25 * 4 = 5

Если вы не хотите каждый раз делать этот расчет вручную, существуют различные онлайн-калькуляторы, которые могут сделать это за вас. http://babbage.cs.qc.edu/IEEE-754/64bit.html кажется одним из лучших.

person JesusFreke    schedule 05.12.2010
comment
На самом деле у меня есть еще один вопрос в настоящее время. Откуда вы знаете, что используются v0 и v1 (ср. const-wide/high16 v0, 0x4014)? В этой команде нет v0, не так ли? - person Nils; 23.06.2015
comment
эээ.. посмотри еще раз? Я определенно вижу v0 там :) - person JesusFreke; 23.06.2015
comment
эм, простите опечатка. Я конечно имел в виду v1. const-wide/high16 v0, 0x4014 .... v1 нет ... откуда я могу это знать? От стоимости как-то? - person Nils; 29.06.2015
comment
двойные и длинные всегда хранятся в последовательных регистрах. И вы ссылаетесь на них по нижнему регистру. - person JesusFreke; 29.06.2015

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

100000000010100
smmmmmmmmmmmmee

s = знак, m = мантисса, e = показатель степени. Итак, в вашем случае знак должен быть 1 или положительным, мантисса равна 5, а показатель степени равен нулю:

+5 x 2^0 = 5

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

person ptomato    schedule 04.12.2010

По-видимому, это подходящая двоичная кодировка «5» как двойная для сравнения с вашим вторым параметром этого типа с плавающей запятой.

person Chris Stratton    schedule 04.12.2010
comment
Вы знаете, как его рассчитать? Я не уверен, как преобразовать 0x4014 в значение 5. Может быть, есть где-нибудь документация по этой теме? - person Nils; 04.12.2010