• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Введение в отладку с нуля с использованием x64DBG

Да windbg он больше для ядра)
Виндбг он для всего =) Но соль в пикд, я немного потыкал.., но даже не тыкая ясно что автоматизации штука классная. Просто виндбг реально большой и сложный и его скрипт язык просто ужасен и документация там тоже сложная, но вот возможности по винде серьёзные. Если попадётся что то толковое порадуй ссылкой.
 
Виндбг он для всего =) Но соль в пикд, я немного потыкал.., но даже не тыкая ясно что автоматизации штука классная. Просто виндбг реально большой и сложный и его скрипт язык просто ужасен и документация там тоже сложная, но вот возможности по винде серьёзные. Если попадётся что то толковое порадуй ссылкой.
Ну он больше системный отладчик чем для обычных приложений.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Да windbg он больше для ядра)
Почему же, например в юзермоде пригодится когда нужно дебажить x32/x64 код, то есть если процесс с x32 режима делает переключение в x64 режим, то после этого windbg будет дизасмить x64 код/показывать x64 регистры. За это большой плюс. Хз ещё какие отладчики такое делают
 

Введение в отладку с нуля с использованием x64DBG. Часть 2. Базовые инструкции процессора интел x86​

===========================================================================================
Давайте продолжим наш курс, который мы начали с Вами на прошлом занятии. Напомню, что это курс по реверсингу как мы сказали в предыдущей части, в котором мы будем постепенно учиться и показывать как работать с отладчиком и будем двигаться вперед по курсу не спеша. Этот курс будет, как мы сказали, обновленным курсом "Введения в отладку с нуля с использованием OLLYDBG", но на этот раз мы будем использовать новый отладчик под названием X64DBG и сегодня мы увидим пять базовых инструкций, потому что нам не нужно учить все их сразу, чтобы не запутаться и не создавать нагрузку для нас, а важно понять эти базовые инструкции ассемблера. Начнем с малого, чтобы никого не пугать. Сегодня мы рассмотрим самые простые инструкции. Давайте откроем крекми который мы изучали на прошлом уроке. Как мы сказали у нас есть окно с адресами памяти, байтами, инструкциями или опкодами, окно с регистрами, флагами, стеком и часть памяти которая называется дамп, где отладчик показывает данные формате хекса. Регистры мы рассмотрим позже в следующих курсах, так как их много. И у нас есть определенные регистры, которые несут определенный смысл и функцию.

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

После запуска отладчика и открытия в нем программы ENTRYPOINT или ТОЧКА ВХОДА у меня равна 0x921372.

Чтобы было проще, мы будем нажимать пробел и исправлять инструкции, которые уже существуют. Нажимаем пробел и вводим следующую инструкцию.

MOV EAX, 5

1662614869465.png


Чтобы нам не мешали нижние инструкции, мы зажимаем правую кнопку мыши, выделяем их, вызываем меню, и выбираем BINARYFILL WITH NOPS [C+9]

1662614877682.png


У нас получается такой результат.

1662614887482.png


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

1662614896141.png


Видим, что она никак не влияет на флаги процессора.

Я поделюсь с Вами этой очень классной таблицей. Она находится по этому адресу - http://www.jegerlehner.ch/intel/IntelCodeTable_es.pdf

Не забывайте подглядывать в неё, если что-то забываете.

Сегодня мы разберем следующие четыре инструкции, которые также есть в этой таблице, потому что это базовые инструкции языка ассемблера и процессора ИНТЕЛ — это MOV, XCHG, ADD, SUB. Видно, что эти инструкции принадлежат процессору 80186 и хотя этот процессор вышел в 1982 году и с тех пор прошло 40 лет, процессоры все также используют эти инструкции, потому что это основные команды по работе с данными.

1662614914799.png


Давайте рассмотри как читать эту таблицу. В первой колонке слева идет опкод инструкции, в данном случае это MOV. Далее идет колонка с комментариями. Для инструкции MOV написано, что это команда делает перемещение (копирование). Далее идет пример кода, как мы должны писать эту инструкцию на языке ассемблера - MOV DEST, SOURCE (MOV НАЗНАЧЕНИЕ, ИСТОЧНИК). Далее идет результат. Это значит, что-то, что находится в источнике, будет перемещено в назначение. Самая правая таблица показывает воздействие инструкции на флаги. Видим, что в данном случае эта инструкция не меняет флаги.

То есть, в нашем случае значение 5 помещается в регистр EAX, то есть 5 — это ИСТОЧНИК, а EAX – это НАЗНАЧЕНИЕ.

Теперь нам нужно выполнить эту инструкцию. Как мы разбирали на прошлом уроке это делается с помощью клавиши [F7].

До нажатия клавиши [F7]:

1662614930337.png


После нажатия клавиши [F7]:

1662614939119.png



Видим, что красным пометился только регистр EAX, а все остальные регистры остались черными, то есть они не изменились.

Также видно, что изменился регистр EIP.

1662614954003.png


Сейчас он указывает на следующую инструкцию

1662614967565.png


Давайте посмотрим другие возможности MOV. Для этого мы нажимаем правую кнопку мыши и выбираем такой пункт — SET EIP HERE [C+*]. Мы должны выделить наш адрес 0x921372 (в моем случае), выполнить этот пункт меню и мы вернемся снова на точку входа по адресу 0x921372. То есть этой командой мы принудительно меняем EIP.

1662614978029.png


1662614986937.png


Рассмотрим следующий пример. Сейчас мы будем пересылать данные из одного регистра в другой. Для примера возьмем регистры EAX и EBX. Редактируем команду также через пробел.

1662614995690.png


Здесь мы помещаем значение, которое хранится в регистре EBX в регистр EAX.


Чтобы было нагляднее, давайте поменяем значение EBX на 100, для этого нажимаем правую кнопку мыши и выбираем MODIFY VALUE [ENTER]

1662615012228.png


И меняем на нужное нам значение. В данном случае — 100, нажимаем на [F7] и смотрим результат.

1662615023830.png


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

1662615039366.png


То есть у нас все работает все как отображено в таблице.

Сейчас мы умеем уже помещать в регистр константу и значение из регистра. Давайте попробуем поместить в регистр значение из памяти. Для этого выберем нужный адрес памяти, например — 0x77331000

1662615050496.png


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

Нам снова нужно вернуться обратно на нашу единственную команду, поэтому повторяем операцию — нажимаем на первой строке SET EIP HERE [C+*] и нажимаем снова пробел. Теперь вместо константы и регистра мы должны ввести адрес памяти. Это делается так.

1662615061482.png


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

1662615073928.png


DWORD означает, что мы будем читать в регистр двойное слово, то есть 4 байта. DS говорит о том что мы берем данные с сегмента данных.

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

1662615085078.png


Он показывает нам текущее значение регистра EAX, а также значение по адресу 0x77331000, которое ровно 0x00180016. То есть мы посчитали все верно и не ошиблись. Также отладчик показываем нам, что адрес 0x77331000 принадлежит модулю NTDLL.

Теперь выполняем инструкцию через [F7] и смотрим на результат.

До выполнения инструкции через [F7].

1662615096711.png


После выполнения инструкции через [F7].

1662615104929.png


Как видно в регистр уже попадает нужное значение и ничего не нужно переворачивать, так как формат литл-эндиан применяется только к памяти, а не к регистрам.

Кроме помещения ячейки памяти в регистр, можно поместить сам регистр в ячейку памяти. Для этого нужно выбрать нужную ячейку памяти куда мы будем писать. Я выберу адрес 0x921380. И отредактируя инструкцию, я выполню наш код.

1662615123614.png


Но у нас не получается выполнить эту инструкцию из-за нарушения прав доступа, и у нас срабатывает защита, вызывая исключение. Это можно увидеть по информационному полю внизу

1662615131901.png


Поэтому давайте будем писать в секцию данных.

1662615143299.png


Она находится у нас по адресу 0x93A000. Мы будем писать байты по адресу 0x0093A100.

1662615150490.png


В окне дампа вызовем диалоговое окно через [C+G] и введем нужный нам адрес.

1662615158028.png


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

1662615164690.png


1662615172060.png


Теперь перейдем ко второй инструкции из таблицы. Её опкод пишется так XCHG, или EXCHANGE, то есть обмен данными. Общий вид выглядит так - XCHG ОПЕРАНД1, ОПЕРАНД2. А результатом является следующее - ОПЕРАНДУ #1 присваивается значение ОПЕРАНДА #2, а ОПЕРАНДУ #2, присваивается значение ОПЕРАНДА #1. Также мы видим, что никакие флаги не меняются.

Для примера сделаем обмен между регистрами EAX и EBX, предварительно установив их в 100 и 200.

1662615186159.png


И вводим нашу инструкцию как обычно.

1662615200892.png


Выполняем инструкцию мы смотрим на результаты в окно регистров.

1662615208690.png


Видно, что все соответствует нашей таблице и значения обменялись местами.

Мы также можем сделать обмен между регистром и ячейкой памяти. Я также, как и в прошлый раз выберу адрес памяти разрешенный на запись и помещу туда значение 300. Для этого я выбираю нужный адрес памяти, нажимаю правую кнопку мыши и выбираю пункт BINARY, а затем EDIT [C+E].

1662615223747.png


У нас появляется диалоговое окно. И я ввожу значение 0x12345678.

1662615232399.png


Теперь мы можем сделать обмен данными нажимая [F7].

1662615240730.png


Нажимаем и смотрим результат.

1662615248984.png


1662615252965.png


Все работает как часы.

Следующую инструкцию которую мы рассмотрим согласно таблице — это инструкция ADD, от английского ADDITION, что означает СУММА.

1662615268365.png


Запись опкода выглядит так - ADD НАЗНАЧЕНИЕ, ИСТОЧНИК. Это значит, что ИСТОЧНИК складывается с НАЗНАЧЕНИЕМ и результат также помещается в НАЗНАЧЕНИЕ. Также видно, что эта инструкция меняет много флагов.

1662615275900.png


Видно, что меняются флаги O - переполнения, S - знака, Z- нуля, A - вспомогательного переноса, P - четности, C – переноса. Мы не будем сейчас их рассматривать, но рассмотрим, что это такое позже.

Мы будем складывать регистры EAX, EBX, поэтому наша инструкция будет выглядеть так.

1662615288067.png


И установим значения регистров для примера так. Регистру EBX присвоим значение 90, а EAX9.

1662615295682.png


И выполним нашу инструкцию.

1662615302337.png


Результат будет такой.

1662615309580.png


То есть, EBX + EAX = 90 + 9 = 99 и результат будет помещаться в сам регистр EAX.

Мы можем использовать все регистры из списка, кроме регистра ESP, так как это использование сломает программу.

1662615325275.png


Теперь попробуем сложить регистр EAX со значением памяти. Возьмем все тот же адрес - 0x0093A100 и присвоим ему значение 90, а в регистр EAX поместим 9.

1662615339695.png


1662615344149.png


И выполним нашу инструкцию.

1662615349162.png


Результат будет такой.

1662615358508.png


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

1662615366097.png


Результат будет таким.

1662615377064.png


Теперь разберем последнюю инструкцию для этого урока и задействуем регистр ECX. Наша инструкция выглядит так — SUB, от английского SUBSTRACTION, что означает вычитание.
1662615383804.png

=======================================================================================
Автор текста и картинок: Яша Яшечкин.
Написано специально для форума xss.pro
По мотивам Рикардо Нарвахи и КО.
 
Последнее редактирование:
Она очень похожа на ADD. Запись опкода выглядит так SUB НАЗНАЧЕНИЕ, ИСТОЧНИК. Это значит, что из НАЗНАЧЕНИЯ вычитается ИСТОЧНИК и результат помещается в НАЗНАЧЕНИЕ. Также видно, что эта инструкция меняет много флагов, как и инструкция ADD.

Давайте задействуем наш регистр ECX. Наша полная инструкция будет выглядеть так.

1662615451984.png


Проставим нужные нам значения в регистры. Например, так. ECX будет равен 98, а EAX - 99.

1662615459362.png


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

1662615466473.png


Это значит, что EAX - ECX = 99 - 98 = 1 и результат помещается в EAX.

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

1662615477817.png


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

Подведем итог. В этом уроке мы рассмотрели 5 инструкций.

- Инструкция NOP, которая ничего не делает, а просто занимает процессор на какой-то квант времени.
- Инструкция MOV, которая используется для пересылки данных.
- Инструкция XCHG, которая делает обмен между двумя операндами.
- Инструкция ADD, которая складывает два операнда.
- Инструкция SUB, которая вычитает первый из второго и помещает результат в первый операнд.

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

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

1662615501761.png


1662615507790.png

=========================================================================================
Автор текста и картинок: Яша Яшечкин.
Написано специально для форума xss.pro
По мотивам Рикардо Нарвахи и КО.
 
Последнее редактирование:
Почему то не перенеслось форматирование. 🧐🧐🧐 Поэтому прикладываю исходный файл.
 

Вложения

  • X64DBG-PART2.pdf
    364.6 КБ · Просмотры: 26
Всем привет и добро пожаловать в этот новый урок вводного курса по реверсингу. Мы продолжим работу с x64dbg. Но в этом уроке мы не будет объяснять дополнительные функции отладчика. Мы просто воспользуемся возможностью, чтобы объяснить некоторые мелочи, которые были трудными в предыдущем уроке. Давайте продолжать с тем же упражнением, которое мы видели в предыдущем уроке и сегодня мы разберем что такое регистры.

Что же такое регистр? Это сверх быстрая часть памяти, которая находится в процессоре и служит для обмена данными между другими регистрами, памятью, флагами и т.д. В 32-х битных системах, регистры 32-х битные. Или по другому можно сказать, что они 4-х байтные, а так как каждый байт содержит 8 бит, то. 4 * 8 = 32 бита.

Сейчас я загружаю наш крекми в наш отладчик и регистр EAX у меня в самом начале равен — 0x00B5FBD8.

1667450339024.png


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

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

1667450352421.png


Видно, что следующая инструкция которая будет выполнена находится по адресу — 0x00FB1372. Здесь также есть подсказка. В данном случае программа нам говорит о том какой файл мы выполняем и в какой функции мы находимся. В этом случае это функция — mainCRTStartup. CRT расшифровывается как С RunTime, т.е. это библиотека времени исполнения, которую компилятор добавляет при компиляции к исполняемому файлу.

Сейчас если мы нажмем F8 и выполним инструкцию по адресу 0x00FB1372, то мы попадем на следующую инструкцию за этой инструкцией. Так как сейчас у нас текущая инструкция равна CALL и чтобы сразу выполнить её не заходя во внутрь вызова, мы нажимаем клавишу F8, в отличие от клавиши F7, которая позволяет наоборот зайти в функцию. Это называется СтэпОвэр, т.е. если перевести дословно — Через, а F7 означает СтэпИнто, т.е. во внутрь.

1667450370346.png


Это базовые клавиши для отладки программы.

Сейчас мы нажимаем клавишу F8 и EIP становится равным 0x00FB1377.

Покажем окно отладчика до выполнения F8.

1667450385751.png


И после выполнения F8.

1667450395699.png



1667450403674.png


У этого регистра есть следующее меню:

1667450417709.png


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

Ещё одним из важных регистров является регистр ESP. Этот регистр указывает на вершину стека. Стек по английский это что-то типа стопки или пачки бумаг. Стек работает по принципу LIFO или Last In, First Out.

1667450431579.png


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

1667450442301.png


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

1667450455583.png


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

Т.е. сейчас у меня адрес стека равен — 0x00B5FB80.

1667450473112.png


Или если посмотрим в панель стека, то увидим следующее.

1667450485732.png


Ещё одна важная вещь заключается в том что мы можем переключаться между несколькими режимами. Мы можем показать стек относительно регистра ESP, а можем и относительно регистра EBP. Регистр EBP - это ещё один регистр, который связан со стеком, и в нем хранится база кадра стека.

1667450505393.png


Видно, что более важный регистр, это регистр ESP, так как для него есть горячая клавиша, которая помогает быстро добраться до вершины стека - (*).

Ещё одна фишка которая есть в окне стека — это переключение в режим относительной адресации. Это очень удобно, чтобы убрать абсолютные адреса. Нужно просто сделать двойной щелчок на поле адреса.

1667450519103.png


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

1667450532124.png


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

1667450543859.png


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

1667450559767.png


Т.е. если ещё раз сказать об регистрах ESP и EIP, это очень важные регистры которые влияют на поток выполнения программы.

1667450570426.png


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

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

1667450584229.png


Регистр EAX или Accumulator. Это аккумулятор, в котором в основном хранится результат выполнения функции. Пример выглядит это примерно так.

1667450596027.png

Регистр EBX или Base. Используется в базовой относительной адресации.

Регистр ECX или Counter. Он используется в циклах и хранит значение счетчик. Он может либо увеличиваться, либо уменьшаться. И когда он будет равен нулю, программы выйдет из цикла или перестанет копировать данные с помощью специальных инструкций.

Регистр EDX или Data. Этот регистр для данных. Он используется если значение не помещается в регистре EAX и тогда результат расширяется и хранится сразу в двух регистрах.

Также есть регистры ESI и EDI. ESI — это Source, а EDI – это Destination. Они используются при копировании данных. Регистр ESI указывает на источник данных откуда они будут копироваться, а EDI указывает на назначение данных куда они будут копироваться.

Отдельно существует регистр флагов или EFLAGS. Почему он называется регистром флагов? Потому что он состоит из отельных бит и каждый отдельный бит имеет свое название и назначение, которое влияет на поведение процессора. Т.е. здесь флаг может быть поднят или 1, или опущен — 0. Всё равно как чекбокс в интерфейсе виндовс.

1667450621501.png


Он также является 32-х битным. Префикс E говорит что он расширенный. В ранних версиях процессора он был 16-ти битным и назывался просто FLAGS.

1667450630202.png


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

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

1667450643163.png


Флаг Z включается или будет равен 1-це, когда результат математической операции в регистре равен 0. Если результат будет отличен от нуля, то регистр будет равен 0.

Флаг C будет равен 1-це, когда превышен максимальный возможный размер регистра. И перенос информации будет храниться как отдельный бит в этом регистре. Это флаг работает с беззнаковыми числами. Например, если регистр EAX будет равен 0xFFFFFFFF и мы прибавим в нему 1-цу, то активируется этот флаг, а в регистре будет значение равное 0x00000000

1667450661632.png


Флаг O работает со знакомыми числами, и говорит, о том, что произошло переполнение.

Также есть флаг S, который активируется, когда результат операции стал знаковым.

Здесь нам нужно ещё рассказать о том как процессор представляет у себя в памяти отрицательные значения. Для этого было принято решение, что если весь регистр содержит значение 0xFFFFFFFF, то это максимальное количество беззнаковых чисел. Чтобы существовали и знаковые и беззнаковые, это значение просто поделили пополам. 0xFFFFFFFF/ 2 = 0x7FFFFFFF. Т.е. 0x7FFFFFFF - это максимальное положительное значение. Далее 0x80000000 — это максимальное отрицательное число, а 0xFFFFFFFF – это минимальное отрицательное число или -1.

Как и регистр EFLAGS который состоит из двух регистров по 16 бит, все остальные регистры тоже состоят из частей. Т.е. регистр EAX — это как мы знаем 32-х битный регистр. А его половина - это 16-битный регистр, который называется AX. AX также делится на два регистра по 8 бит каждый, которые называются AH и AL. H говорит о том, что это его верхняя часть, а AL нижняя. Все это связано с тем, что первые процессоры были 8-битные,а следующие поколения процессоров наследовали предыдущие регистры. В данном случае, все нынешние процессоры унаследовали 16-ми битные регистры от процессора 8086, который унаследовал 8-битные регистры от 4004. Поэтому архитектура и называется x86 в отличие от x64.

1667450683873.png


Существуют также такие понятия как BYTE, WORD, DWORD. Это то же самое что и 8, 16, 32 бита, или 1, 2, 4 байта, просто чтобы легче трактовать размер регистра.

Для примера разберем значение с регистра EAX. Оно равно 0x00B5FBD8. Т.е. регистр AX будет равен ровно половине этого значения или 0xFBD8. А регистр AH будет равен — 0xFB, а AL0xD8. Или ещё по другому 0x00B5FBD8 — это DWORD, 0xFBD8 — это WORD, а 0xD8 и 0xFB — это BYTE.

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

В 64-х битной архитектуре, размер регистров ещё больше, так как они 64-х битные и их ещё больше.

1667450707850.png


Серым здесь помечены 64-битные регистры.

Любой регистр можно изменить просто подведя к нему мышку и нажав клавишу Enter.

Появится такое окно.

1667450724515.png


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

Кроме основных флагов Z, O, C, S существуют дополнительные флаги. Давайте рассмотрим их вкратце. Это P, T, A, D, I.

Флаг P или Parity. Это флаг отвечает за четность. Т.е. он считает количество бит и говорит что сумма четная или не четная. Например, если результат операции будет равен 1010, то флаг установится в 1-цу.

Флаг T или Trap. Этот флаг ответственен за трассировку программы при её отладке.

Флаг A или Adjust. Этот флаг используется как дополнительный флаг переноса и в основном применяется при работе с BCD числами.

Флаг D или Direction. Отвечает за направление при работе с адресами памяти при работе со строками. Т.е. адреса могут или увеличиваться или уменьшаться.

Флаг I или Interrupt. Этот флаг отвечает за прерывание от внешних устройств. Если он установлен, то он не реагирует на прерывание от внешних устройств, кроме немаскируемых прерываний.

Выше окна регистров есть кнопка Hide FPU.

1667450755024.png


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

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

1667450768751.png

=========================================================================================
Автор текста и картинок: Яша Яшечкин.
Написано специально для форума xss.pro
По мотивам Рикардо Нарвахи и КО.
 
Последнее редактирование:
Продолжаем наше приключение.

Перед тем как мы рассмотрим ещё больше инструкций, сначала давайте вспомним про то что говорилось на прошлом уроке. Давайте поговорим о флагах. Напомним что у нас есть флаг Z от английского Zero и он активируется когда результат математической операции равен нулю. Давайте посмотрим как он работает. Лучше показать это на примере инструкции SUB. В регистр EAX предварительно поместим значение 9 и выполним такую инструкцию – SUB EAX, 9.

1668755040614.png


1668755048154.png


И будем смотреть на флаг Z. Сейчас до выполнения этой инструкции флаг равен нулю.

1668755054988.png


Давайте выполним эту инструкцию через F8 и посмотрим на результат.

1668755065541.png


Как видно, флаг Z стал равен 1-це, т.е. операция равна нулю.

Давайте снова выполним нашу инструкцию, ничего не меняя во флагах. Нажмем на нашей инструкции — Set EIP Here или нажмем звездочку на цифровой клавиатуре (*), выполним инструкцию через F8 и посмотрим на результат.

1668755077253.png


Флаг поменял свое значение обратно на ноль. А регистр EAX стал равен -3.

1668755089130.png


Надо понимать что если я выполню инструкцию MOV EAX, 0 это уже не математическая операция.

Исполняем нашу команду и смотрим на результат.

1668755098012.png


Видно, что флаг не стал равен единице, хотя мы поместили в регистр EAX ноль.

1668755108133.png


Позже мы рассмотри какие инструкции меняют флаги, а какие нет. Сейчас же важно запомнить что на флаг влияют математические операции, а не перемещение.

Сейчас давайте посмотрим обратную инструкцию, не вычитание, а сложение — ADD EAX, EDX. В регистр EAX мы помещаем значение 10, а в регистр EDX 20.

1668755121300.png


Выполняем нашу инструкцию и посмотрим на результат во флаге Z.

1668755128864.png


Флаг Z равен нулю. А регистр EAX равен 30, потому что в регистр EAX помещается то что было в EAX+EDX.

1668755140768.png


Давайте теперь рассмотрим другой флаг. Флаг переноса или C, от английского Canary. Он активируется когда в результате математической операции в регистре уже не хватает места для записи дополнительного бита, так как регистр состоит из 32 бит и поэтом 33-й бит помещается в этот флаг переноса.

Напомним что для 32-х битных регистров максимальное значение это - 0xFFFFFFFF. И если мы к этому значению прибавим единицу, 33-й бит попадет во флаг переноса.

Давайте посмотрим. Установим регистр EAX в значение 0xFFFFFFFF и выполним такую инструкцию - ADD EAX, 1.

Как видно флаг переноса активировался.

1668755154412.png


А регистр EAX содержит все нули.

1668755165332.png


Все это относится к беззнаковым числам. Для знакомых чисел есть свой флаг. Это флаг переполнения — O от английского Overflow.

Напомним, что ровно половину 32-х битного регистра занимают положительные числа, а другу половину — отрицательные числа. То есть 0x7FFFFFFF - это максимальное положительное значение. Все что больше него считается уже отрицательным для знаковых чисел.

Сейчас также поместим в регистр EAX значение 0x7FFFFFFF и выполним такую инструкцию

1668755177662.png


И давайте посмотрим на наш флаг переполнения.

1668755186501.png


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

Если посмотреть внимательно на картинку можно увидеть, что также активировался флаг S который переводится как знак - Sign. Из картинки мы можем сделать вывод, что одна операция может влиять не на один флаг, а даже на два и три.

1668755195899.png


У нас активировался даже флаг A - Вспомогательный флаг переноса.

Как видно из картинки, все остальные флаги не менялись. Из этого можно сделать вывод чтобы для реверсинга самые важные флаги, это — Z, O, C, S.

Давайте сейчас ещё сделаем один пример. Напишем инструкцию немного по другому.

Сейчас запишем такую инструкцию - add eax, dword ptr ds:[0x00A92000]

Теперь нам нужно перейти в окно дампа и присвоить адресу 0x00A92000 значение 44, а в регистр EAX поместим значение 66.

1668755212428.png


Результат будет равен AA.

Давайте теперь рассмотрит ещё инструкции. Откроем нашу табличку и найдем такие инструкции.

1668755221041.png



1668755234465.png


Как видно из таблицы, у нас есть инструкции связанные с делением — DIV от английского Division и умножением — MUL от английского — Multiplication. Здесь в таблице они идут парами. Это связано с тем, что есть инструкции которые работают со знаковыми числами, и которые работают с беззнаковыми числами. Приставка I говорит, что это работа со знаками.

Рассмотрим эту инструкцию, так как она будет для нас самой простой для объяснения.

1668755243488.png


Описание в таблице говорит нам, что регистр EAX будет умножаться на оператор, а результат будет в два раза больше и уже не поместится в регистр EAX, поэтому тут используются два регистра EDX и EAX, т.е. результат будет 64-ным. Регистр EDX будет хранить старшую часть результата, а регистр EAX – младшую.

Сейчас вернемся в отладчик и введем такую инструкцию — MUL EBX, а в регистры EAX и EBX поместим значение 0xFFFFFFFF. Предварительно посчитаем это выражение в калькуляторе в режиме программиста.

1668755251504.png


Результат будет равен — FFFFFFFE00000001. То же самое должно у нас появится и в отладчике. Давайте выполним нашу инструкцию и посмотрим на регистры.

1668755267435.png


Результат соответствует тому значению которое получилось в калькуляторе.

Сейчас давайте выполним простое умножение, вычислим выражение 2*2 = 4. В регистры поместим нужные нам значения.

1668755278001.png


И выполним нашу инструкцию

1668755285095.png


Результат получился таким.

1668755293026.png


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

Теперь рассмотрим умножение со знаком.

Давайте решать самое простое выражение: -1 * -1 = 1

Поместим эти значения в наши регистры.

1668755305815.png


Выполняем нашу инструкцию и посмотрим результат.

1668755313000.png


Также есть другие формы инструкции умножения.

Например, такая.

1668755321606.png


Заполним наши регистры EBX и EDX.

1668755327980.png


И выполним нашу инструкцию

1668755336474.png


Теперь посмотрим обратную инструкцию умножения — деление или DIV.

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

При выполнении деления результат будет сохраняться в регистр EAX, а остаток от деления в регистр EDX.

Посмотрим самый простой пример. Разделим 8 на 2.

1668755349403.png


Не забываем также обнулить регистр EDX.

Исполняем инструкцию и смотрим на результат.

1668755359621.png


После исполнения инструкции.

1668755367872.png


А сейчас давайте поделим 9 на 2, чтобы у нас получился остаток от деления.

Как видно в регистр EDX попал остаток от деления равный единице.

1668755378422.png


Давайте подведем итог этого занятия. Мы подробно разобрали 4 флага и разобрали две новые инструкции, умножения и деления, каждая из которых умеет работать со знаковыми и беззнаковыми числами. Также у каждой инструкции существует несколько форм записи.
===========================================================================================================
Автор текста и картинок: Яша Яшечкин.
Написано специально для форума xss.pro
По мотивам Рикардо Нарвахи и КО.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх