Введение в реверсинг с нуля используя IDA PRO. Часть 6

Дата публикации 12 мар 2017 | Редактировалось 15 апр 2017
Давайте продолжим с арифметическими и логическими инструкциями.

ADD A, B

Инструкция складывает значение B и A, и помещает результат в A.

A может быть регистром или содержимым ячейки памяти, B может быть регистром, константой или содержимым ячейки памяти (A и B не должны быть в памяти в одно и то же время, в одной и той же инструкции)

Рассмотрим несколько примеров инструкции ADD ища текст ADD через VEVIEWER.

1.png

Здесь мы видим много примеров сложений, где первый член регистр, а второй - константа, как мы знаем, инструкция будет складывать значения регистра в этот момент, со значением константы и будет сохранять результат в регистр.

2.png

В этом примере, если ECX равно 10000, то константа 4 складывается с ним и результат 10004 сохраняется в тот же ECX.

3.png

В этом случае, инструкция добавит 0xFFFFFFFF к значению ECX, которое получено на предыдущем шаге, т.е. содержимое адреса будет указывать сейчас на ECX + 30, если этот адрес имеет разрешение на запись, инструкция сложит значения и будет сохранять результат там.

Если содержимое ECX, для примера, равно 0x10000, то по адресу 0x10030 содержимое этого адреса равно значению 1 и когда мы прибавляем к этому значению 0xFFFFFFFF, что то же самое, что и -1, следовательно, результат был бы равен нулю и будет сохраняться по адресу 0x10030.

В нашем CRACKME.EXE есть несколько примеров суммы двух регистров.

4.png

В этом случае, оба регистра будут сложены и сохранены в EDI.

Конечно, мы можем также складывать 16-битные и 8-битные регистры.

ADD AL, 8
ADD AX, 8
ADD BX, AX
ADD BYTE PTR DS: [EAX], 7

Инструкция будет складывать байт содержимого на которое указывает EAX, и значение 7, и будет сохранять результат в то же самое место.

И все возможные комбинации сумм между регистрами, содержимым ячеек памяти и константами, как мы видели все комбинации действительны, если только EAX не является константой и содержимым адреса памяти в одно и то же время в той же инструкции.

SUB A, B

Эта инструкция действует так же как и ADD за исключением того, что вместо операции сложения в данном случае вычитается целое число и сохранит результат в A, возможные комбинации те же самые.

5.png

INC A и DEC A

Инструкция увеличивает или уменьшает регистр, или содержимое ячейки памяти на 1, на самом деле это частный случай сложения и вычитания.

6.png

Оба используются для примера, чтобы увеличить или уменьшить счётчик на 1.

IMUL

Это инструкция умножения со знаком и существует две её формы.

IMUL A, B
IMUL A, B, C

Первая инструкция выполняет целочисленное умножение A на B, и результат сохраняется в A, а вторая инструкция выполняет умножение B на C, и результат сохраняется в A.

В обоих случаях A может быть только регистром, B может быть регистром или содержимым ячейки памяти и C может быть только константой.

IMUL EAX, [ECX]
IMUL ESI, EDI, 25


Давайте рассмотрим пример в VEVIEWER

7.png

Мы видим, что есть только примеры для первой инструкции, в обоих случаях будет производиться целочисленное умножение обоих членов и будет сохраняться результат в первый член - ECX.

Для второго случая примеров нет.

IMUL EAX, EDI, 25

Здесь инструкция умножает EDI на 25 и сохраняет результат в EAX, это очень легко.

IDIV A

В этом случае A определяет только ДЕЛИТЕЛЬ операции, делимое же как и частное не определяются, потому что они всегда используют одинаковые регистры.

8.png

Эта операция создаёт большое 64-битное число, старшая часть которого находится в EDX, а младшая часть в EAX. Инструкция делит значение на A и сохраняет результат в EAX, а остаток значение в EDX.

9.png

Если EAX для примера равно 5, EDX равно нулю и ECX равно 2 инструкция выполнит целочисленное деление, результат деления 5 на 2 будет равен 2 и он будет сохранён в EAX, а остаток сохранён в EDX.

То же самое произойдёт, если A - это содержимое ячейки памяти, EDX:EAX будет разделено на это значение и результат сохранится в EAX, а остаток в EDX.

ЛОГИЧЕСКИЕ ОПЕРАЦИИ

AND
, OR или XOR

AND A, B

Инструкция выполняет логическую операцию И между двумя значениями и будет сохранять результат в A, то же самое происходит с инструкциями ИЛИ или XOR, каждая инструкция имеет свою таблицу истинности, которая применяется к каждому члену и результат будет сохранён в A.

A и B могут быть регистрами или содержимым ячеек памяти, но запрещено, чтобы оба были содержимым ячейки памяти в одной и той же инструкции.

Самые используемые случаи - это применение XOR к одному и тому же регистру, чтобы легко и быстро изменить его в ноль.

XOR EAX, EAX для примера при любом значение EAX поместит в результате ноль, так как таблица истинности для XOR такая.

10.png

В этому случае результат - это последняя колонка и мы видим, что если XORИМ число против себя , это может случиться только, когда в двочином виде оба биты равны нулю или оба бита равны единице, так как это то же самое число, A и B равны и побитовый результат всегда даёт ноль в обоих случаях.

11.png
12.png
Записывая значения как бинарные данные в PYTHON строке и используя символ ^, который является операцией XOR в PYTHON, я вижу, что применяя операцию XOR два одинаковых числа всегда дают 0.

Конечно, можно использовать десятичные и шестнадцатеричные значения, я просто использовал двоичный режим чтобы увидеть как бит влияет на бит.

13.png

Другое простое использование для примера.

AND EAX, 0F

0F
это 1111 в двоичной системе счисления.
14.png
15.png
Мы видим, что второй член равен 1, результат не изменится, он останется равным как был первоначально, в то время как все другие биты станут равны нулю.

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

16.png

Там мы видим, что AND в PYTHON записывается символом & и результатом является 0B0111, а это последние четыре первоначальные биты.

В случае OR в PYTHON он записывается как вертикальная черта.

17.png

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

NOT A

Инструкция инвертирует все биты A и сохраняется затем в A.

Инструкция NOT не существует в PYTHON, но это очень просто, если Вы имеете число 0101 и Вы применяете к нему операцию NOT.

18.png

Результатом будет инверсия каждого бита.

19.png

Мы видим, что все нули изменились в один и наоборот.

NEG A

NEG A
превращает A в -A.

Это не то же, что операция ~ в PYTHON, потому что тут ещё вычитается единица.

20.png

Чтобы получить NEG в Python мы должны добавить к результату 1.

21.png

SHL, SHR
SHL A, B
SHR A, B

A
может быть регистром или ячейкой в памяти, а B константой или 8-бит. регистром.

Эти инструкции сдвигают байты влево(SHL) и вправо (SHR), байты которые исчезают с одной стороны, заменяются нулями с другой стороны, давайте рассмотрим пример.

Предположим, что у нас есть -1, для примера.

22.png

И если я сделал SHL 2, я получу.

23.png

При перемещении битов влево два бита исчезли в левой части, и теперь заполнены двумя нулями биты в правой части.

24.png
То же самое произойдёт, если мы используем SHR, биты сдвинутся к правой стороне. Те биты которые исчезнут с правой стороны, будут заменены на 0 с левой стороны.

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

25.png

До встрече в 7 главе.

11 11.102
yashechka

yashechka
Ростовский фанат Нарвахи

Регистрация:
2 янв 2012
Публикаций:
90

Комментарии


      1. virtuha 23 май 2017
        3. Конспирация прям какая-то :B)
        Окей, все понял, спасибо)
      2. yashechka 23 май 2017
      3. virtuha 23 май 2017
        Спасибо за ссылку. Я там был и не обратил внимание на раздел EN INGLES.
        Еще пару вопросов.
        1. Что за книга памяти К.К.?
        2. Не в тему :)) Но что бы определиться в будущем, вы девушка или парень? Просто ник женский, а комментарии мужские :))
      4. yashechka 22 май 2017
        Странно, ведь я проверяю тексты на спел.ру :scratch_one-s_head:
      5. yashechka 20 май 2017
      6. galenkane 20 май 2017
        Вы не пробовали записывать видео?
      7. Mikl___ 20 мар 2017
        А где же третья форма IMUL A? где A может быть и регистром и ячейкой памяти?
        AX=AL*A
        DX:AX=AX*A
        EDX:EAX=EAX*A
        RDX:RAX=RAX*A
      8. yashechka 19 мар 2017
        Готово. Увидел ошибку - напиши.
      9. yashechka 22 май 2017
        virtuha нравится это.
      10. virtuha 22 май 2017
        В этому случае результат - это последняя колонка и мы видим, что если XORИМ число против себя , это может случиться только, когда в двочином виде оба биты равны нулю или оба бита равны единице, так как это то же самое число, A и B равны и побитовый результат всегда даёт ноль в обоих случаях.
        ---
        "В этому случае..." - ну это наверно машинный перевод и не считается :)
        а вот в слове "двочином" ошибка :)
        yashechka нравится это.
      11. virtuha 22 май 2017
        Привет.
        А где можно найти перевод оригинала на английском? И много там статей переведено (на английский)?
        yashechka нравится это.