> 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-03.md).

# Часть 3

[\[Используемые материалы\]](https://github.com/yutewiyof/intro-rev-ida-pro/tree/e1367e11cc661f3d69c02ae5f733b7dd168bc5ab/.gitbook/assets/files/03.zip)

**Загрузчик**

Мы уже видели, что когда в **IDA** мы открываем исполняемый файл, тот же самый файл открывается в **ЗАГРУЗЧИКЕ**, который является статическим анализатором того же самого файла.

Мы будем анализировать его части и характеристики, большая часть того, что мы видели до настоящего времени, будут применимы и к **ЗАГРУЗЧИКУ** и для **ОТЛАДЧИКА**. В случае, если что-то будет отличаться или не похоже на общий случай, я упомяну это.

Очевидно, то, что в **ЗАГРУЗЧИКЕ** программа абсолютно не выполняется, но она анализируется, и создаётся база данных с информацией этого файла, и это значительное отличие относительно **ОТЛАДЧИКА**.

В **ЗАГРУЗЧИКЕ** нет ни окна **РЕГИСТРОВ**, ни окна **СТЕКА**, ни списка модулей, которые загружены в память. Это вещи, существуют при выполнении и отладке программы.

После загрузки **Cruehead Crackme (CRACKME.EXE)**, если мы посмотрим на список процессов , то увидим, что он не работает и никогда не выполняется, пока мы не откроем отладчик **IDA**.

Это очень полезно для определенного использования, например как анализ вредоноса, эксплоита и т.д. , потому что мы не всегда сможем получить доступ к некоторой функции, для этого мы должны изучить отладку, в то время как в **ЗАГРУЗЧИКЕ** мы можем проанализировать любую из функций программы, это не имеет значения, если мы не знаем как её вызывать и пользоваться ей.

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

**Что же такое регистры и для чего они используются?**

Хорошему процессору нужны помощники в его задаче по выполнению программ.

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

**32**-разрядные регистры, которые используются - это: **EAX**, **ECX**, **EDX**, **EBX**, **ESP**, **EBP**, **ESI**, **EDI** и **EIP** . В конце курса будет часть, посвященная **64**-битным.

![](/files/-Ljp9-WmnuUx-TWYqbvt)

**Регистры общего назначения**

**EAX** (Аккумулятор): Аккумулятор используется для таких инструкций как деление, умножение и некоторых инструкций формата, и также как регистр общего назначения.

**EBX** (База): Он может непосредственно работать с памятью, используется как база и также как регистр общего назначения.

**ECX** (Счетчик): **ECX** регистр общего назначения, который может использоваться в качестве счетчика для различных инструкций. Он также может иметь адрес смещения данных в памяти. Инструкции, которые используют счетчик, являются - цепочечные инструкции, инструкции смещения, **ROR** инструкции(циклические) и **LOOP/LOOPD**.

**EDX** (Данные): Это регистр общего назначения, который содержит часть результата умножения или деления. Он может также работать непосредственной с данными памяти.

**EBP** (Указатель на базу стека): **EBP** указывает на место в памяти. Почти всегда как база для аргументов и переменных функции, кроме того, он также регистр общего назначения.

**EDI** (Указатель на назначение): Часто, он указывает на адрес назначение результата в строковых цепочечных инструкциях. Он также регистр общего назначения.

**ESI** (Указатель на источник): Часто, он указывает на адрес источника в строковых цепочечных инструкциях. Как и **EDI**, **ESI** также работает как регистр общего назначения.

**EIP**: Указатель, который указывает на следующую инструкцию, которая будет выполнена.

**ESP**: Указатель, который указывает на верхушку части стека или пачку.

Подведём итог того, что я сказал.

Восемь регистров - **EAX** (аккумулятор), **EBX** (база), **ECX** (счетчик), **EDX** (данные), **ESP** (указатель на вершину стек), **EBP** (указатель на базу стека), **ESI** (указатель на источник данных ) и **EDI**(указатель на назначение данных).

Также там существуют **16**-битные и **8**-битные регистры , которые являются частями предыдущих регистров.

Если **EAX** равно **12345678**

**AX** это последние четыре цифры (**16** бит)

![](/files/-Ljtu_3yVzWfzNMcA0Ya)

**AH** это **5-я** и **6-я** цифра и **AL** две последние цифры (**8** бит каждая)

![](/files/-Ljtu_4BrGL5qSpSrF1j)

Есть **16**-разрядный регистр для младшей части регистра **EAX** называющийся **AX** и два **8**-разрядных регистра называющихся **AH** и **AL**. Не существует специальных регистров для старшей части .

Эти регистры существуют в той же формы для **EBX** (**BX**, **BH** и **BL**), для **ECX** (**CX**, **CH** и **CL**) и это применимо почти ко всем регистрам (только у **ESP** есть 16-бит **SP**, но не **SL** из 8 битов)

![](/files/-Ljtu_4Nc6bt8gCeD29J)

Здесь Вы можете видеть регистры, такие как **EAX**, **EDX, ECX**, и **EBX**, которые имеют регистры из **16** и **8** битов и **EBP**, **ESI**, **EDI** и **ESP**, которые имеют **16-**&#x431;итные подрегистры.

![](/files/-Ljtu_4fM8SFM5mgamEB)

Мы будем рассматривать и другие регистры, один из них важный вспомогательный регистр **EFLAGS**, который активирует свои флаги, которые принимают значения на основе решений в разные моменты выполнения программы, которые мы рассмотрим позже, сегментные регистры указывают на другие части исполняемого файла, такие как **CS=CODE**, **DS=DATA** и т.д.

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

![](/files/-Ljp9-Ww-MdEy3f5nAWk)

**IDA** управляет большим количеством данных, которые мы будем видеть постепенно, чтобы не усложнять обучение, важная вещь состоит в том, чтобы знать, что **BYTE** равен 1 байту в памяти, **WORD** 2 байтам и **DWORD** составляет 4 байта.

**ИНСТРУКЦИИ**

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

**Инструкции перемещения данных**

**MOV**

**MOV dest,src: Она копирует содержимое источника операнда (src) в место назначения (dest)**.

**Операция: dest ← src**

Здесь есть несколько возможностей. Например, нам может понравиться первая возможность переместить значение одного регистра в другой.

**MOV EAX, EDI**

![](/files/-Ljp9-WyJ0R3ertENfV-)

В целом, мы можем перемещать из или в регистр непосредственно, принимая во внимание это **EIP** не может быть **МЕСТОМ НАЗНАЧЕНИЯ** или **ИСТОЧНИКОМ** в любой операции. Мы не можем сделать так

**MOV EIP , EAX**

Это не допустимо.

Другая возможность состоит в том, чтобы переместить константу в регистр, например.

**MOV EAX, 1**

![](/files/-Ljp9-X-D31Ukfc8AU0O)

Другая возможность состоит в том, чтобы переместить значение адреса памяти, а не ее содержимое (Эти инструкции в изображении принадлежат другой программе, не **CRACKME.exe**, потому что они не были там, но есть в **VEViewer.exe**, файл приложен к этой части 3)

![](/files/-Ljp9-X1pzkKp3zYswcP)

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

Или если нажмём **Q** , оно становится таким

![](/files/-Ljp9-X3-HM1ShsE-tl4)

**MOV EAX, 46f038**

Эта ещё одна инструкция как в **OLLY**, но она не дает нам информации о содержимом этого адреса. Если мы щелкаем правой кнопкой по адресу **46F038**, мы можем вернуться к исходной инструкции.

![](/files/-Ljtu_698zf_6RMQ8S10)

И она станет как прежде.

Что говорит мне эта дополнительная информация? Что **IDA** говорит мне о вышеупомянутом адресе памяти?

![](/files/-Ljp9-X7aMA1tG7Rcgfk)

Если я открываю окно **HEX DUMP** и поищу упомянутый выше адрес, я вижу, что первично он равен нулю. Я знаю, что это **DWORD**, но я действительно не знаю что это, потому что он зависит от того, где он использует это значение в программе, что определяет тип этой переменной.

![](/files/-Ljtu_6kr8PRgaXKCuBf)

Если я вернусь к списку и дважды щелкну в этом адресе.

![](/files/-Ljp9-XB6wWT-LTUdl1u)

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

**IDA** говорит мне **dword\_46F038**, это означает, что содержимое ячейки памяти равно **DWORD**, это похоже на разъяснения адреса слева, здесь есть тип данных **dd**, который является знакомым нам **DWORD** и потом значение, которое содержит вышеупомянутая ячейка памяти, является нулём.

**IDA** говорит мне, что программа использует этот адрес как **DWORD** и на правой стороне я вижу ссылки, где этот **DWORD** будет использоваться.

![](/files/-Ljp9-XDl6G9XJarNkmB)

Там есть две ссылки, каждая стрелка, это одна из них и подведя курсор мыши над ней я могу видеть код, также если я нажму **X** на этом адресе, я увижу откуда сюда ссылается программа.

![](/files/-Ljtu_7Oh6Ha6ZAYG08B)

Первая, где читается адрес, где мы были ранее, вторая, записывает **DWORD** по адресу **0x46F038**, вот почему **IDA** в первой инструкции говорит нам, что тот адрес указывает на **DWORD**, потому что тут была другая ссылка, которая получает доступ к ней и записывает этот **DWORD** и сейчас все чисто.

![](/files/-Ljp9-XHdk2_8aQ3MNPS)

Так что, **IDA** в первоначальной инструкции не только сообщила мне, что собирается поместить адрес в регистр, но она также сказала мне, что этот адрес содержит **DWORD**, это что-то вроде бонуса.

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

Как ранее мы видели.

**mov eax, offset dword\_46F908**

Эта инструкция поместит адрес **0x46F908** в **EAX**

**mov eax, dword\_46F908**

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

![](/files/-Ljtu_81akFsTp_L1Mfb)

Эта инструкция, которую помним по **OLLY** с квадратными скобками для, тех кто привык к этому отладчику.

**MOV EAX,DWORD PTR DS:\[46f908]**

Или когда адрес имеет впереди слово **OFFSET**, он ссылается на этот самый адрес, а когда этого слова нет, то ссылается на значение полученное по этому адресу.

Это просто случается, когда мы обращаемся к числовым адресам, если мы работает только с регистрами.

![](/files/-Ljtu_8DhiNYAbK732vG)

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

Конечно, в этом случае, если **EDI** указывает например на **0x10000**, упомянутая выше инструкция будет искать содержимое адреса памяти и оно будет скопировано в **ECX**.

Очень важно понимать, что когда **IDA** использует слово **OFFSET** перед адресом памяти она ссылается на это же числовое значение, а не на его содержимое, давайте рассмотрим ещё один пример.

![](/files/-Ljp9-XNFoS4cPCNP-Po)

Тут мы видим, что в **EAX** помещается значение **0x45f4d0**, потому что впереди есть слово **OFFSET** и также она говорит мне, что упомянутый выше адрес содержит **stru\_**, который является структурой.

![](/files/-Ljp9-XPbyXszoTtAWVP)

В другом случае, в первой помеченной инструкции, перемещается содержимое **0x46fc50**, которое **DWORD** ,а во второй, просто адрес, который равен числу **0x46FC50**.

Мы видим, что значение вышеупомянутого адреса будет помещено в **0x42f302**, если мы кликнем в **0x46fc50**, давайте посмотрим, что там есть.

![](/files/-Ljtu_8uHGTYOPpjiAP6)

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

С помощью нажатия на **X** на ссылки, мы видим все ссылки, видим, что инструкция сохраняет **DWORD** по адресу.

![](/files/-Ljp9-XTMnklWwTsfBmJ)

Инструкция, которая выделена желтым цветом, сохраняет **DWORD** в вышеупомянутый адрес памяти, все другие или читают адрес смещения или читает само значение по адресу, там где нет слова смещение.

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

![](/files/-Ljtu_9JLbTVmQqrU6GV)

Эта инструкция помещает **1** в **AL**, оставляя остальную часть **EAX** со значением, которое было прежде. Тут просто изменяется самый младший байт.

![](/files/-Ljp9-XX9B6E-O2vs43j)

Здесь, инструкция перемещает содержимое адреса памяти **0x459C24** в **AX** и говорит нам, что это **WORD**.

![](/files/-Ljp9-XZ5R6w0uIDm3-o)

И мы видим, что первично здесь ноль, возможно, далее при выполнении программы он может быть изменен.

![](/files/-Ljp9-XajuQUMlBwULeO)

Здесь **AX** помещается в содержимое **EBX**, т. к. это регистр, то не знаем какое значение имеет регистр **AX**, **IDA** не может сказать больше, она использует квадратные скобки, чтобы указать что, записывается в содержимое адреса **EBX**.

![](/files/-Ljtu_A328php0dB-Vl8)

Здесь, инструкция запишет значение **AX** в содержимое **ESI+8**.

Другой пример

![](/files/-Ljtu_AEEVWxlbw7x2vQ)

Если я щелкну на страшное имя, оно приведет меня сюда

![](/files/-Ljp9-XgjDDQIRU7Fkl1)

Мы знаем, что это **IAT** (таблица, которая сохраняет импортированные адреса функции, когда запускается программа), она почти всегда находится в разделе **idata**.

Если я ищу этот адрес в окне **HEX DUMP**, у него всё еще нет указателя на функции, потому что **IAT** заполняется, когда процесс запускается, а тут он ещё не запустился.

![](/files/-Ljtu_AaeGV1vp_Gf4oG)

Если я пойду в **OPTIONS->DEMANGLE NAMES** и выберу **NAMES** будет намного лучше.

![](/files/-Ljtu_An4LS8bdnhFPqG)

Префикс **EXTRN** подразумевает, что это **ВНЕШНЯЯ** импортированная функция.

Если мы прокрутим выше, мы видим, что программа говорит, что есть импортированные функции, которые принадлежат модулю **DVCORE.dll** и выше есть другие, которые принадлежат различным функциям.

![](/files/-Ljtu_AyLhrNcc_zexFm)

Мы видели различные примеры **MOV**, которые Вы можете практиковать и видеть в **IDA** , в той программе, которую я приложил к уроку.

В 4-той части, мы продолжим и разберём больше инструкций.

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

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

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

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

18.02.2017

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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://yutewiyof.gitbook.io/intro-rev-ida-pro/chast-03.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
