> For the complete documentation index, see [llms.txt](https://yutewiyof.gitbook.io/intro-rev-ida-pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-11.md).

# Часть 11

Перед тем как продолжить, давайте посмотрим сможем ли мы убрать баг, который присутствует в **IDA** версии **6.8**, и который был исправлен в версии **6.9**, и которой у нас нет **:"(** , чтобы увидеть присутствует ли у нас этот **БАГ**, откройте **IDA**, и на любой инструкции нажмите **ALT + M**, что равносильно размещению метки (**JUMP → MARK POSITION**), а затем на той же инструкции сделайте правый щелчок.

![](/files/-Ljtu7AUgoQndV5GrzOP)

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

![](/files/-Ljpb5nVsXYTfIaziJBt)

Давайте сперва найдём файл **IDA.WLL** и откроем его с помощью **HEX** редактора, например такого как **HXD**, с правами администратора.

![](/files/-Ljtu7BGXWlbpzIPftCa)

Мы меняем байты **80 3D** по смещению **0x3C3F6** на байты **EB 30**.

![](/files/-Ljpb5nZBwFreDRd85XL)

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

Другой файл это файл **IDA64.WLL** и мы делаем с ним то же самое, только теперь по адресу **0x41606** байты **80 3D** меняем на байты **EB 30**.

Давайте посмотрим присутствует ли сейчас наш **БАГ**.

Мы пробуем туже самую комбинацию **ALT + M** на инструкции, а затем делаем правый щелчок, **VOILA**, **IDA** не падает, я надеюсь, что всё будет продолжать функционировать без побочных эффектов.

Я не хотел перегружать вас всей теорией с самого начала, вот почему я смешал её с некоторыми упражнениями, но прежде чем продолжать, нам нужно увидеть определение ещё нескольких флагов, которые очень важны.

## ФЛАГИ

### ФЛАГ ПЕРЕНОСА

Мы уже узнали кое-что о ФЛАГЕ CARRY в предыдущей главе, он также активируется в операциях с беззнаковыми числами, когда результат отрицательный как в предыдущем случае или превышает в сумме максимальное возможное значение регистра, давайте посмотрим примеры в отладчике.

Если мы запустим **CRACKME.EXE** в **IDA** в режиме отладчика, то остановимся на **EP** и теперь мы изменим инструкцию на **ADD EAX, 1**.

![](/files/-Ljpb5naero2wfRl9KyD)

Давайте сделаем **EAX** равным **0xFFFFFFF** c помощью щелчка на пункте **MODIFY VALUE**.

Если блок функции испортится, то мы можем сделать правый щелчок на пункте **CREATE FUNCTION** в самом начале для того, чтобы всё было в порядке.

И трассируем инструкцию с помощью **F8**, для того, чтобы она исполнилась, мы видим, что флаг **CF** активируется когда превышается максимальное возможное значение.

![](/files/-Ljpb5ncjxLh6DX6uLE7)

То же самое случится, если мы напишем ниже **SUB EAX, EDX**.

![](/files/-Ljpb5ne7sAaUMQxkcV5)

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

![](/files/-Ljtu7D27WUn2uLGwTQJ)

Измените **EAX** на **0x25**, а **EDX** на **0x40**, и трассируем с помощью **F8**, чтобы видеть как активируется флаг **CF**.

![](/files/-Ljpb5niWwd6ikkSPKMc)

Был активирован флаг **CF**, чтобы выполнить снова это вычитание, нужно изменить **EIP**, для этого делаем правый клик и выбираем - **SET IP** на инструкции **SUB EAX, EDX** и меняем **EAX** на **0x100**.

![](/files/-Ljtu7DsS6M2-gBEmsah)

Я выполняю инструкцию с помощью **F8**.

![](/files/-Ljpb5nmYEty1-jjUjX8)

Флаг не был активирован. Как общее заключение, мы можем прийти к выводу, если активируется флаг **CF** в операции с беззнаковыми числами, это означает, что произошла ошибка любого типа.

### ФЛАГ ПЕРЕПОЛНЕНИЯ

Это похоже на предыдущий случай, но только для операций СО ЗНАКАМИ, мы меняем EIP на адрес инструкции ADD EAX,1 и вводим в EAX значение 0x7FFFFFFF.

![](/files/-Ljpb5noeA1sAuwv23aV)

Если нажмём сейчас **F8**.

![](/files/-Ljtu7ERtDl0u-N6ro6z)

Мы видим, что был активирован **ФЛАГ OVERFLOW**, так как в операции со знаком происходит сложение единицы с максимальным положительным числом **0x7FFFFFFF**, поэтому результат получился максимально-отрицательным и результат суммы ложный.

![](/files/-Ljtu7EdN-sn-SFHRBbw)

Если я вычитаю **EAX** и **EDX** с использованием этих значений.

![](/files/-Ljpb5nupRWrGLFR5PRz)

Флаг также активируется, потому что максимальное отрицательное число **0x80000000** минус **0x40** даёт нам очень большое положительное число, а это даёт ошибочный результат операции.

Следовательно, мы можем сделать заключение, что если **ФЛАГ OVERFLOW** активирован, это означает, что произошла ошибка при работе с операцией **СО ЗНАКОМ**.

### ФЛАГ ЗНАКА

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

![](/files/-Ljpb5nwdHGnQRDFba9Y)

**0x8000000 + 0x1** находится в диапазоне отрицательных чисел, результат сложения равен **0x8000001**, поэтому активируется флаг **SF**, также мы видим, что флаг **OF** и флаг **CF** не активируются, когда нет ошибки в **БЕЗЗНАКОВОЙ** или **ЗНАКОВОЙ** операции.

![](/files/-Ljpb5ny-xGjhTjG3aY2)

Очевидно, что когда процессор выполняет инструкцию, которая работает с двумя регистрами, он не знает, **ЗНАКОВЫЕ** они или **НЕ ЗНАКОВЫЕ**, но мы знаем это за него, потому что мы видим следующие условные переходы, но процессор не знает об этом, поэтому в любой операции он будет оценивать инструкцию как если бы они были **БЕЗ ЗНАКА** и **СО ЗНАКОМ** в одно и тоже время и будет изменять необходимые флаги, поскольку условные переходы зависят от флагов, программа будет смотреть на результат флага **CF БЕЗ ЗНАКА** или флага **OF СО ЗНАКОМ** в соответствии с переходом, который существует, если например это **JB**, что есть переход **БЕЗ ЗНАКА** то будет учитываться только флаг **CF** и не будет учитываться флаг **OF** хотя они оба были изменены.

### ФЛАГ НУЛЯ

Он не зависит от знака.

![](/files/-Ljpb5o-yhKa84dfMTlw)

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

Мы можем проверить.

![](/files/-Ljpb5o1NPPPoxYRbN86)

Я меняю **EAX** на значение **0xFFFFFFFF** и если я добавлю число **1** к нему, что тогда произойдёт?

![](/files/-Ljtu7G5LapxC72yznLS)

Мы видим, что активируется флаг **ZF** так как результат операции нуль и если мы рассмотрим оба регистра как беззнаковые, также будет активирован флаг **CF**, так как превышено максимальное положительное значение, а флаг **OF** не будет активирован, потому что если оба регистра **ЗНАКОВЫЕ**, то **-1 + 1** даёт нам нуль и нет никаких ошибок, также флаг **SF** не был активирован, так как результат не был отрицательным.

Эти флаги очень важны, давайте посмотрим, что случится если мы изменим следующий условный переход.

![](/files/-Ljtu7GM2MwGZ5ajvlnB)

Я меняю инструкцию так, чтобы получилась инструкция **SUB EAX, EDX** и ниже пишу инструкцию **JB 0x401018**.

![](/files/-Ljpb5o78cPsV6quckXG)

Я делаю **EAX** равным **0x40**, а **EDX** равным **0x2** и исполняю инструкцию **SUB** с помощью **F8**.

Красная стрелка начинает мигать, потому что **EAX** больше чем **EDX**, следовательно переход не будет выполнен, но давайте посмотрим на флаги.

![](/files/-Ljtu7GqedBfV8gKa4vp)

![](/files/-Ljtu7H2p9muhItp2__y)

**JB** это **БЕЗЗНАКОВЫЙ** переход и он сработает если **ФЛАГ CF** активирован, так как флаг не был активирован, потому что операция была правильная между двумя положительными числами и результат оказался положительный, это означает, что первый операнд больше чем второй, следовательно, переход не произойдёт.

![](/files/-Ljpb5oDtlVnvK4Uk8DH)

Но если мы изменим **EAX** на **0x40**, а **EDX** на **0x80** и я снова повторю вычитание.

![](/files/-Ljtu7HQpJEcVW8XE-XE) ![](/files/-Ljtu7Hert1KJzX_As41)

В этом случае, поскольку **EAX** меньше чем **EDX**, переход не будет совершен, но будет совершен переход на зеленую стрелку.

![](/files/-Ljpb5oJY5iHqrBpGFfs)

Так как **JB** смотрит на флаг **CF**, он будет осуществлять переход, потому что флаг активирован, если результат операции **БЕЗ ЗНАКА** дает отрицательное значение, то будет выдаваться ошибка.

Также активируется флаг **SF**, потому что получается отрицательный результат и флаг **OF** не активируется, потому что оба значения **БЕЗЗНАКОВЫЕ**, операция не выдаст такую ошибку, и **0x40** – **0x80**даёт отрицательный результат.

![](/files/-Ljpb5oLVxa-fsnInd3x)

Переход **JB** зависит от состоянием флаг **CF**, но если я изменю его на **JL**.

![](/files/-Ljtu7IcLMDOP7gO-nHO)

В этом случае он изменяется и идёт на зелёную стрелку, потому что первое значение меньше чем второе, но на какой флаг смотрит переход **JL?**

![](/files/-Ljpb5oPDdZrMQypmnpK)

Мы видим, что переход **JL** сработает, если флаг **SF** не будет равен нулю, а в нашем случае он равен единице, поэтому он также не будет совершать переход, что логично, так как первый член меньше чем второй и инструкция **SUB** похожа на инструкцию сравнения **CMP**, только она сохраняет результат в отличие от **CMP**, таким образом если первый член меньше чем второй, то будет осуществлён переход.

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

Автор оригинального текста — Рикардо Нарваха.

Перевод и адаптация на английский язык — IvinsonCLS.

Перевод и адаптация на русский язык — Яша Яшечкин.

Перевод специально для форума системного и низкоуровневого программирования - WASM.IN

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/11-INTRODUCCION%20AL%20REVERSING%20CON%20IDA%20PRO%20DESDE%20CERO.docx)
