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

# Часть 4

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

Мы продолжаем рассматривать инструкции обмена данными в **IDA**.

**XCHG A, B**

Эта инструкция обменивает значение **A** со значением **B**, давайте рассмотрим пример.

![](/files/-LjtttyaRmoneHecSqCG)

В файле **VEVIEWER** нет такой инструкции, поэтому я загружаю **СRACKME.EXE Cruehead**, и меняю инструкцию по адресу **0x4013D8**.

Я помещаю курсор на строку адреса и перехожу в меню **EDIT->PATCH PROGRAM->ASSEMBLE**.

![](/files/-Ljp8xcTvKnuHapnd4Fu)

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

![](/files/-Ljp8xcVN-k8GLmS_uem)

Мы уже видели, что, если инструкция не существует, эта область показывается, как область данных. В этом случае тут один байт, поскольку нет никаких ссылок ни в какую часть программы, то и нет никакой информации на правой стороне окна. Затем тип данных, становится **DB**, здесь только один байт и его значением является **0xC0**.

Таким образом, если мы запишем инструкцию **NOP**, что означает **NO OPERATION** или инструкция заполнения, которая ничего не делает, то так заменим байт **0xC0**.

![](/files/-Ljtttz0K-HnQM8HcM3W)

Поставим по этому адресу **NOP**.

![](/files/-Ljtttz6517TZ3zjVUi0)

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

![](/files/-Ljp8xcaQG1NZBO8o-41)

И это меняет префикс **loc\_**, который означает "локальная метка" на префикс **sub\_**, который означает, "начало подпрограммы или функции".

![](/files/-LjtttzJ8tcDuX6XgASL)

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

![](/files/-Ljp8xce5IgX_6jKp55S)

Теперь намного лучше и сейчас здесь есть наш **XCHG**.

Мы видели, что если **EAX** равняется **12345678** и **ESI** равняется **55**, то когда выполняется **XCHG**, регистр **EAX** будет равняться **55** и **ESI** будет равняться **12345678**.

Мы видим, что в меню **PATCH** есть элемент под названием **PATCHED BYTES**, который показывает изменения, и он может вернуть к исходному неизменному коду.

![](/files/-Ljp8xcgdYKk2aZzntkB)

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

![](/files/-LjtttzagXsRjX2dnJVZ)

В этом случае, значение **ESI** будет искать содержимое по этому адресу памяти и оно будет обмениваться со значением **EAX**, которое будет сохранено в той же ячейке памяти, если есть разрешение на запись.

Например, если значение **EAX** равно **55** и значение **ESI** равно **0x10000**.

Инструкция будет проверять, что находится здесь, в этой ячейке памяти и если она доступна на запись, она сохранит туда значение **55** и прочитает значение по адресу памяти **0x10000** и сохранит его в **EAX**.

Что произойдет, если мы сделаем то же самое, но вместо того, чтобы использовать регистр мы используем адрес в памяти, как мы сделали в **MOV** ?

Поскольку команда **ASSEMBLE** не работает полноценно для всех инструкций, мы должны изменить байты в меню где написано **PATCH BYTES**, но лучше загрузить плагин, такой как **Keystone**, который позволяет нам записать все инструкции намного проще.

<https://github.com/keystone-engine/keypatch> <https://drive.google.com/file/d/0B13TW0I0f8O2eU1VdUJzVjdYTWs/view?usp=sharing>

Во второй ссылке находится файл **keypatch.py**, который мы должны скопировать в каталог плагинов **IDA** и затем можно установить **keystone-0.9.1-python-win32.msi**.

Кроме того, необходимо установить **Microsoft VC ++**, библиотеку времени исполнения.

<http://www.keystone-engine.org/keypatch/>

![](/files/-Ljp8xckjDkm5Ka2OG-U)

![](/files/-Ljp8xcmpEvbBLX7brUz)

В **Keypatch** выберите **PATCHER**.

Когда мы выбираем **PATCHER**, мы видим что, если запишем инструкцию в простой форме и со скобками, он запишет её и преобразует в синтаксис **IDA**.

![](/files/-Ljp8xcoIwWo2u8fDaJh)

И я получаю такой результат.

![](/files/-Ljp8xcqREkjRVwuVVkz)

Как и в **MOV**, когда показывается префикс **dword\_** без **СМЕЩЕНИЯ** в начал&#x435;**\*\*, это будет означать, что обменивается содержимое** 0x4020DC **со значением** EAX\*\*.

**СПЕЦИАЛЬНЫЕ ИНСТРУКЦИИ ПЕРЕСЫЛКИ ОСНОВАННЫЕ НА РАБОТЕ СО СТЕКОМ**

**ЧТО ТАКОЕ СТЭК?**

Стэк, это область в памяти, которая работает по принципу **LIFO**.

Для обработки данных предоставляется две основные операции: положить или **PUSH**, которая помещает объект в стек и обратная операция, чтобы забрать последнее значение или **POP**.

В каждый момент времени, есть доступ только к верхушке стека, то есть к последнему сохраненному объекту. Операция **POP** получает обратно этот элемент, который вытолкнут со стека, разрешая доступа к тому, который находится ниже (положен ранее) и он становится последним доступным объектом.

В **CRACKME.EXE** мы видим примеры обеих инструкций.

![](/files/-Ljp8xcs4SPy0vjbKKA-)

Обычно, в **32**-битных приложениях, **PUSH** используется, чтобы передать аргументы функции в стек, прежде, чем вызвать функцию с помощью **CALL**, на картинке выше мы видим это по адресу **0x40104F**.

**PUSH 64** кладет **dword 64** в верхнюю часть стека, затем **PUSH EAX** кладет значение **EAX**, на предыдущее значение в стеке, оставляя внизу это предыдущее значение, и поэтому оно будет последним на верхушке стэка.

**ESP ->значение EAX -> 0x64**

Ниже мы видим другой вид **PUSH**, мы можем также сохранять константы, но и также мы можем сохранить адрес памяти, как в этом случае.

![](/files/-Ljttu-9wFL1thQIj61T)

Мы видим слово **СМЕЩЕНИЕ** перед символьным **ТЭГОМ**, соответствующее строке символов, здесь будет положен в стэк адрес начала строки или строковый массив.

Если мы дважды щёлкнем на этот тэг, который представляет название строки **WindowName**.

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

**char mystring\[] = "Hello WASM.IN";**

![](/files/-Ljttu-WHp9jd2o94UTR)

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

Здесь записано **char WindowName\[]**, потому что **IDA** обнаружила функцию **API CreateWindow**.

![](/files/-Ljp8xcyH5vMm8Dp3SsR)

В любом случае, это массив символов или байтов, только **IDA** добавляет немного полезной информации, которая получена от **API** функции, мы видим, что после адреса **0x4020E7** следующий адрес в списке **0x4020F4**, здесь есть некоторая последовательность байт, которые принадлежат символам строки **"Crackme v1.0"** и ноль, который говорит о конце строки.

![](/files/-MX3mIkKTGPEWOk2zgLc)

Если мы нажмём кнопку **D**, чтобы изменить тип данных на **WindowName**.

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

![](/files/-Ljp8xd1sLaQdoaBayv8)

Это те же самые байты, которые соответствуют последовательности **crackme v1.0**.

Мы видим, что оригинальная инструкция изменилась, очевидно слово **offset** впереди говорит о том, что будет заталкиваться значение **0x4020E7**, но сейчас, содержимое прекратило быть символьным массивом и теперь стало байтом и инструкция изменилась на

![](/files/-Ljttu-rlKGxpHJZPuiG)

**push offset byte\_4020e7**

![](/files/-Ljp8xd5K8kG-Oxrx8YF)

Нажмём кнопку **A** и последовательности станет снова как и раньше строкой **ASCII** символов.

![](/files/-Ljp8xd7GiwEIN6IJbdd)

Также, когда мы работаем, мы можем видеть некоторую последовательность, такую как нулевые байты.

![](/files/-Ljttu0JTGmOQ1FtIVHb)

Передвигаемся в начало последовательности байт и нажимаем **A**, теперь смотрится намного лучше.

![](/files/-Ljttu0Rzk6J2ZjTHM1T)

В этом случае, мы видим, что эта строка не определена в двух строчках, как предыдущая, **IDA** даже не говорит, что она **CHAR\[]**, но она определена с помощью тэга, который начинается с буквы **a**, для того, чтобы быть **ASCII** строкой, в предыдущем случае **IDA** показывает дополнительную информацию, потому что **IDA** обнаружила, что это был аргумент **API** или функция системы и **IDA**предупредила, что аргумент должен быть **CHAR\[]** и вот почему она добавил это там, но нормальная строка будет похожа на эту последнюю строку.

Здесь мы видим другую строку.

![](/files/-Ljp8xdDk-jyrsj3OfDN)

По адресу **0x402110** начинается первый байт строки, она может быть расщеплёна на байты, чтобы их видеть отдельно, просто нажатием клавиши **D** на строке **aMenu**.

![](/files/-Ljttu0aB7VqPZIlYLGs)

Если мы нажмём **A**, мы отменим сделанные изменения.

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

Мы видим, что тут сохраняется адрес **0x402110**, потому что стоит слово **СМЕЩЕНИЕ**.

![](/files/-Ljp8xdHUa61jcDobl-5)

Обычно, когда аргументы передаются к функциям, мы всегда будем видеть **PUSH offset xxxxx**, потому что ищется адрес строки, чтобы передать его функции, если инструкция не имеет слово **OFFSET**,мы бы заталкивали содержимое адреса **0x402110**, байты **55 4E 45 4D** которого являются той же строкой и API не будет работает, API всегда передаётся указатель на начало или адрес где начинается строка.

В этом случае, в этой инструкции, которую мы видим выше, префикс **DS:TAG** указывает, что она собирается сохранить его в адрес памяти секции данных (**DS=DATA**), когда мы будем рассматривать структуры, мы изучим этот случай, сейчас важно запомнить, что инструкция сохраняет адрес начала строки в секции **DATA**.

**POP**

![](/files/-Ljttu0nNrgyCA0B1M8U)

Эта операция, которая читает вершину стэка и перемещает значение с этой вершины в регистр назначения, в этом случае мы видим, что **POP EDI** будет читать первое значение или **ВЕРШИНУ СТЭКА** и скопирует его в **EDI**, а затем **ESP** будет указывать на значение, которое было ниже и теперь оно станет **ВЕРШИНОЙ** стэка.

Если мы ищем текст, а именно слово **POP**, мы видим, что вариантов используется не так много, несмотря на то, что там есть возможность вытолкунуть **POPEAR(wtf amigos???)** в адрес памяти вместо регистра, эта опция не является очень используемой.

![](/files/-Ljttu0ySD-gLUt0bnPK)

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

Пока пока.

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

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

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

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

24.02.2017

[**Источник: ricardonarvaja.info**](http://ricardonarvaja.info/WEB/IDA%20DESDE%20CERO/CURSO%20DE%20IDA%20TUTES/4-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-04.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.
