Введение в крэкинг с нуля, используя OllyDbg - Глава 5

  • На форуме работает ручное одобрение пользователей. Это значит, что, если Ваша причина регистрации не соответствует тематике форума, а также Вы используете временную почту, Ваша учётная запись будет отклонена без возможности повторной регистрации. В дальнейшем - пожизненная блокировка обоих аккаунтов за создание мультиаккаунта.
  • Мы обновили Tor зеркало до v3!
    Для входа используйте следующий url: darkv3nw2...bzad.onion/
  • Мы вновь вернули telegram чат форуму, вступайте, общайтесь, задавайте любые вопросы как администрации, так и пользователям!
    Ссылка: https://t.me/chat_dark_time

AnGel

Администратор
Команда форума

AnGel

Администратор
Команда форума
27 Авг 2015
3,411
2,025
МАТЕМАТИЧЕСКИЕ ИНСТРУКЦИИ
INC И DEC

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

Идём в Олли и, как обычно, открываем крэкми CrueHead'и и в первой строке пишем:

8acabc4d61f610236c14e933b8014504.png

На моей машине EAX изначально равен нулю. Если у вас это не так, вы можете изменить это вручную.

d46933bd9c2a182835ec0a56d37ccf58.png

Затем нажимаем F7 и выполняем инструкцию INC EAX, увеличивая его на один.

84a48571ad1edd4968e0671c80a941de.png

Таким же образом можем ввести DEC сразу под предыдущей инструкцией.

4abcf2a5fd7c151cac2e3c3e3b91e9a5.png

Нажимаем F7 и выполняем инструкцию INC EAX, которая уменьшает значение регистра на 1, после чего он принимает предыдущее значение - 0.

695dd1c6a72bbe8df40288ada14a4e1b.png

Также можно увеличивать или уменьшать значение ячейки памяти.

52166e9a737ff5ee68ecc14f896e0174.png

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

574e49a608175d2fe9a13302ba969843.png

Что было бы, если бы у секции было выставлено разрешение на запись? Идём в DUMP по адресу 405000.

b13dbf3a6e5ccace24ef465913ffcac5.png

Содержимое, если его прочитать наоборот, будет равно 00001000, значит, если бы оно было увеличено, то было бы 00001001

f7b10b59e1bda4e7d67663d48528f0e5.png

В данном случае для DWORD прибавление 1 производилось к 4 байтам содержимого.

Для WORD суммирование будет применено только к двум последним байтам.

8d6fc0ccc5727bd8b742badf8791e673.png

И при BYTE суммирование будет применено только к последнему байту.

16f81892fc9b53c28ca343a1fb65f19e.png

ADD

ADD, как можно видеть, суммирует оба операнда, сохраняя результат в первом.

ADD EAX, 1 похоже на INC EAX.

Также можем складывать регистры.

Идём в Олли.

b9211637a324e372457f11da1c3796c4.png

До выполнения инструкции:

60218b4b2fccb83e32ca3cc4343e9bec.png

На моейм машине EAX содержит 00000000, а EAX - 12FFB0. У вас данные регистры могут содержать другие значения, также вы можете, если хотите, их изменить, но когда вы нажмёте F7, оба значения будут сложены, а результат помещён в EAX. Смотрим:

ba515238fd3fd7f20e13217de8878e6c.png

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

Также можем сложить регистр с содержимым ячейки памяти.

2ad75266eb582e36be2179aa881613b0.png

В данном случае нет проблем с правами на запись, так как меняется и сохраняет результат регистр EAX, а содержимое [405000] остаётся неизменным. Соответственно, не генерится и никакого исключения.

До нажания F7 видим, что EAX содержит 0, а по адресу 405000 находится значение 00001000.

908860fffef0ce795ac4815b2f90b4b3.png

07d252ff5da18b15c09cc27e1adc9b0f.png

Нажимае F7, после чего вычисляется сумма.

c5ef452a0dbe86cc5eda5792c329d447.png

Так как EAX = 0, то в EAX сохраняется результат, равный 1000.

Если хотим, чтобы результат сохранился в памяти, то пишем:

f13f678a4b748ebf156b849374506f7c.png

В этом случае результат сохранится в 405000, и так как это модифицирует память, то в нашем случае при нажатии на F7 будет сгенерировано исключение об отсутствии прав на запись.

5921aaf861b5a42cdb06c945f38d9ba2.png

ADC (ADD С ПЕРЕНОСОМ)

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

8e86b77d81cb1ec20cf2442aef2eb0e6.png

06b93ed4fb080f3f2e4f5c06059231c5.png

Здесь видим, что здесь будет суммирован EAX, содержащий 21, со числом 3, а также вычислен флаг C, который сейчас равен нулю. Нажимаем F7.

c798786b0a0254fbf4876b029343ab66.png

Видим, что результат равен 24. Теперь повторим эту операцию, но с флагом C равным 1, значение которого мы можем изменить, если дважды кликнем по нему мышью.

087fb3bfc5ca173855e19e42014796ce.png

Сделав это, повторяем выполнение инструкции, изменив значение флага C.

903df37e2ee40d73669355f942f746a3.png

Нажимем F7 и вуаля - результат равен 25.

7523cf78676d767361a1210e6c62a28b.png

Так как сумма EDX (21) с 3 и флагом C, равном 1, равна 25.

SUB

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

ae5b73899aa7ca9eeb4cfaf878a195e1.png

На моей машине регистры до выполнения инструкции содержали следующее:

4e6b41de343a9014526974a3cc2f752e.png

По нажатию F7 инструкция вычтет от EAX, который содержит ноль, значение 2.

695ab1c5a19813f97a1aab960b881542.png

Результатом является -2, что в шестнадцатеричной системе выглядит как FFFFFFFE, в чём мы можем убедиться, если кликнем два раза мышью на данном значении:

c99fb050df7361bf35f293a75b0b1fb2.png

Видим, что в десятеричной системе это равно -2.

Также можно отнимать значение регистров и ячеек памяти примерно таким же образом, как и при использовании инструкции ADD.

SUB EAX,ECX<
То есть EAX-ECX с сохранением результата в EAX.

И

SUB EAX,DWORD PTR DS:[405000]<
Вычитает от EAX содержимое ячейки памяти по адресу 405000, сохраняя результат в EAX.

Обратный случай:

SUB DWORD PTR DS:[405000],EAX<
Так как результата сохраняется .в первый операнд, то, поскольку у нас нет прав на запись в секцию, то получим исключение.

SBB

Это операция является обратной к ADC: она вычисляет разность между операндами, отнимает от того, что получилось, значение флага переноса (флаг C) и сохраняется окончательный результат в первый операнд.

c39aa74d638a38b873d352f4959bc494.png

До выполнения в EDX находилось 21, а флаг переноса был равен 0.

636f3682ab6acc47ed204444b31c17a3.png

Нажатие на F7 вычтет из EDX число 3, а затем ноль, которому равен флаг C.

54e51baece700cebda7b62cc2385ba39.png

Теперь повторим операцию, присвоив флагу C значение 1.

02ea9b03282d1ac24ddcb39307b78923.png

Нажимает на F7 и теперь из EDX вычитается 3, а затем единица, которой равен флаг C.

be4d3b4dbff489368f8932c0d6373b3f.png

В данном случае результат равен 1D.

MUL

Ок, есть две инструкции для выполнения умножения. Первой из них является MUL, которая не учитывает знаки чисел. Она использует только один операнд, а другим всегда является EAX Результат сохраняется в EDX:EAX.

Например:

MUL ECX<
Здесь ECX умножается на EAX без учёта знаков их значений, а результат сохраняется в EDX:EAX.

Рассмотрим следующий пример с помощью OllyDbg:

9aaccea6928ea016d37ff5c852c5e2ca.png

01c626f579587efb227cc6bddc69adc3.png

Поместим в EAX число FFFFFFF7, в ECX - 9, а затем посчитаем результат с помощью стандартного калькулятора Windows:

7e6dd4082dff3553dfb2bc9ec8dfdd5a.png

2936bfaf4ef7e9c20d15bdab14b80abe.png

Получится:

4dfade0d039d351307817b600bd68aed.png

Это не поместится в EAX. Посмотрим, что будет в Олли и нажмём на F7.

8556f9c374baf1f3b21c930a63dd3cc3.png

EDX и EAX выделены красным, так как их значение было изменено, и, как видим, в EAX было сохранено то, что поместилось, а остальное в EDX. В данном случае 8-рка, которую не смог вместить EAX, попала в EDX, поэтому в таких случая говорят, что результат содержится в EDX:EAX, то есть два регистра используются как один двойного размера.

В случае с

MUL DWORD PTR DS:[405000]<
Происходит умножение ячейки памяти по адресу 405000 на EAX, а результат, как обычно, помещается в EDX:EAX без учёта знаков операндов.

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

8993dcb49e747254cfeec0f7c606e5d8.png

Как можно видеть, во втором ряду находится значение со знаком (в данном случае FFFFFFAF это -81, если учитывать знак), но в таких операциях как MUL все числа считаются БЕЗЗНАКОВЫМИ. Третья строка как раз и содержит десятеричное значение без знака. Сейчас видим, что число FFFFFFAF - это 4294967215, если рассматривать его как положительное, то есть беззнаковое.

IMUL (умножение без знака)

Инструция IMUL - это умножение со знаком и употребляется аналогично MUL.

IMUL ECX

Данная операция производит умножение ECX на EAX, а результат сохраняется в EDX:EAX с учётом знака операндов.

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

Из туториала CAOS'а:

Несмотря на использовальние регистров EAX и EDX по умолчанию, можно указать другие источники и приёмники данных вплоть до трёх операндов. Первый - место, куда необходимо поместить результат и которое всегда должно быть регистром, второй и третий - два значения, которые нужно перемножить. В этих примерах увидим применение этой инструкции с двумя или тремя операндами.
F7EB imul ebx EAX x EBX -> EDX:EAX<
Это первый пример, который похож на MUL, не считая того, что здесь учитываются знаки.

696E74020080FF imul ebp, dword ptr [esi+74], FF800002 [ESI+74] x FF800002 -> EBP

Это второй пример, в котором три операнда: содержимое ESI+74 умножается на FF800002, а результат сохраняется в EBP. Мы можем посмотреть его в действии с помощью Олли.

Скопируем строку "imul ebp, dword ptr [esi+74], FF800002" в Олли.

b2b56020e08edf468d083147c426eaf7.png

Видим, что нажатие кнопки "ASSEMBLE" выдаёт ошибку. Это происходит из-за того, что в Олли к числам, которые начинаются с букв, нужно слева приписывать ноль. Исправляем:

66a8a8c1a58530dd758cc9eb164215df.png

Теперь нажатие на ASSEMBLE проходит без ошибок.

c3905e96ba0d9d2257f38a5cd51240bd.png

Изменяем значение ESI на 401000, чтобы быть уверенными, что адрес ESI + 74, из котого будет происходить чтение, существует.

9079a846a606d3584f8c6e9810f832d5.png

Видим в пояснениях:

074ca9bea31db4e55db5c1bc21f4df91.png

Здесь говорится, что ESI + 74 - это адрес 401074, содержимым которого является C7000000. Идём в DUMP с помощью "GOTO EXPRESSION 401074".

301aedf410591dc215659365f0cb0e2a.png

Это значение, которое, если прочитать его наоборот, равно C7000000, будет умножено на FF800002, а результат данной операции будет сохранён в EBP.

imul ebp, dword ptr [esi+74], FF800002<
Нажав F7, видим, что EBP стал красным, так как сейчас он содержит результат.

29cfcdfecc95c1c3eb17eb0501cd3121.png

Калькулятор даёт нам следующий результат операции C7000000 * FF800002:

ca9b1c78f98ca9936ae72470b576766a.png

Но поскольку EBP не может вместить его полностью, то в нём остаётся только то, что поместилось, а остальное отбрасывается.

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

0FAF55E8 imul edx, dword ptr [ebp-18] EDX x [EBP-18] -> EDX<
Как видим, основной способ для умножения больших чисел - использовать IMUL только с одним операндом, так как в этом случае результат сохраняется в EDX:EAX, то есть он может быть двойного размера, чего нельзя добиться при использовании двух или трёх операндах, соответственно, данную возможность следует применять для маленьких чисел.

DIV (Unsigned Divide) / IDIV (Signed Divide)

Это инструкции, обратные по отношении к MUL и IMUL соответственно.

DIV имеет только один операнд, не учитывает знаки и сохраняет результат в EDX:EAX.

IDIV всегда учитывает знаки. Если используется один операнд, то, как и DIV, сохраняет результат в EDX:EAX, в случае двух - делит один на другой и сохраняет результат в первый, а при трёх операндах делит второй на третий и сохраняет то, что получилось, в первый.

Не думаю, что нужно приводить здесь примеры, похожие на те, что были в разделе, посвящённом MUL и IMUL.

XADD (Обменять и сложить)

Как можно догадаться, это смесь XCHG и ADD, то есть если :

XADD EAX,ECX<
bf9e95148dbf7855bb75dc4fa0677957.png

262254bdd39914fa08756bf97f6a217f.png

Видим, что ECX равен 1, а EAX - 9. По нажатию на F7 они обменяются значениям, т.е. в EAX попадёт 1, а в ECX - 9, после чего произойдёт сложение.

1e1a8fa9906962b1a223c05f29c86640.png

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

NEG

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

Пример:

ad8c509cfbd8d7011345c4fcfec89f1f.png

Пишем в Олли NEG EAX и заносим в EAX число 32.

e07f2081f1b2586bb9e33ca5c21880d6.png

После нажатия на F7 в EAX окажется отрицательный вариант числа 32. Смотрим:

9abb3939a6547b3d05913f0e88e7df3c.png

7443632882b74ac1e04f26b14c287220.png

Во втором ряду видим, что результатом является -50 в десятеричной системе (это соответствует -32 в шестнадцатеричной).

0ccb04c857c0a4b93d5c91b377f3f215.png

Если напечатаем в CommandBar'е число -32 в шестнадцатеричной системе, чтобы выяснить, чему оно равно в десятеричной, то получим ответ, что это значение эквивалентно -50, а также пояснение, что это FFFFFFCE.

Так что видим, что NEG меняет знак операнда на обратный.

ЛОГИЧЕСКИЕ ИНСТРУКЦИИ
Далее следуют логические инструкции, принимающие по два операнда, производящие над ними побитовые операции и сохраняющие результат в первый операнд.

AND

Результатом этой операции над двумя битам является 1, если они оба равны 1, и 0 во всех остальных случаях.

  • 1 and 1 = 1
  • 1 and 0 = 0
  • 0 and 1 = 0
  • 0 and 0 = 0
Посмотрим пример в OllyDbg:
AND EAX,ECX<
45a8bc8f8319731a6efda1c6019b5e84.png

Делаем ECX=00001200, а EAX=3500.

81b80cb220fa75762e47a765a0254999.png

Чтобы сделать эту операцию вручную, нужно перевести оба числа в двоичный вид:

  • 1200 в двоичном виде будет равно 01001000000000
  • 3500 в двоичном виде будет равно 11010100000000
Применим вышеприведённую таблицу операции AND побитно, например, к последней цифре:

131a0ad252170b2fb3909c46a54fddb4.png

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

a9e4d38077d7531f7a76d9f51abcba51.png

Если нажмём F7 в Олли, то увидим, что в ECX находится результат 1000, что эквивалентно 01000000000000 в двоичном виде.

b1f1e14286ca4f5a14e2e5ad90446ace.png

OR

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

Получается 1, если один или оба бита равны 1, и 0 во всех остальных случаях.

  • 1 or 1 = 1
  • 1 or 0 = 1
  • 0 or 1 = 1
  • 0 or 0 = 0
XOR

Здесь то же самое, только используем таблицу функции XOR.

Получается 1, если один и только один из двух битов равен 1, и 0 во всех остальных случаях.

  • 1 xor 1 = 0
  • 1 xor 0 = 1
  • 0 xor 1 = 1
  • 0 xor 0 = 0
NOT

Просто инвертирует значение:

  • not 1 = 0
  • not 0 = 1
Пример: not 0110 = 1001

Если у нас, например, EAX=1200, что в двоичном виде равно 1001000000000, то все нули превратятся в 1, а все 1 в 0.

00000000000000000001001000000000<
После применения NOT получим

11111111111111111110110111111111<
что в калькуляторе Windows в шестнадцатеричном виде отобразится как FFFFEDFF.

e4cfe2668b94d4dfc9c38302eb4cfc35.png

В Олли до нажатия на F7 сделаем EAX равным 1200.

ed56f17fbd52939b907a92309e38c7e5.png

Нажимаем F7.

b1e55d3837dfd33f8c39bf532b2b218e.png

Видим, что результат тот же самый.

Ок, здесь мы закончим пятую часть "Введения...". Пока подумайте над тем, что узнали в этой главе, а нам ещё предстоит рассмотреть инструкции сравнения, выходов, call и ret.

Шаг за шагом дорога приведёт нас к цели.
 

О нас

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

    Dark-Time 2015 - 2022

    При поддержке: XenForo.Info

Быстрая навигация

Меню пользователя