Ассемблер. Инструкции стека и перемещения данных. Крэкинг ч.4

Обсудить статью на форуме


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

ИНСТРУКЦИИ



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

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

NOP (NO OPERATION)

Это инструкция, которая при запуске не производит никаких изменений в регистрах, стеке или памяти, поэтому по-английски её название расшифровывается "NO OPERATION", то есть у неё нет никакого специального анзначения, и поэтому её можно использовать, например, если нужно заменить одну инструкцию на другую, более короткую. Чтобы процессор не столкнулся с ошибками, лишнее место заполняется NOP'ами.

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

Снова откроем крэкми CrueHead'а.

Взлом программ отладчиком OllyDbg

В самом начале видим оригинальный код. Чтобы занопать первую инструкцию PUSH 0, которая имеет размер 2 байта, отмечаем соответствую строку листинга с помощью мыши, а затем нажимаем клавишу "пробел" или же правая кнопка мышь - ASSEMBLE.

Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

Пишем NOP и нажимаем ASSEMBLE.

Взлом программ отладчиком OllyDbg

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

Теперь на месте, где был "PUSH 0", находятся два NOP'а, которые при исполнении ничего не делают, в чём мы можем убедиться, нажав два раза F7, чтобы стала отмеченной инструкция CALL. Увидим, что изменился только регистр EIP, содержащий адрес инструкции, которая должна выполнится следующей, но ничего больше не изменило своего значения: ни другие регистры, ни стек, ни флаги, ни память.

Теперь нам нужно посмотреть эти два новых байта в DUMP, и для того, чтобы найти их там, нам нужен их адрес в памяти, и это 401000 и 401001.

Взлом программ отладчиком OllyDbg

Идём в окно DUMP, правая кнопка мыши - "Go to" - "Expression", после чего нужно будет ввести адрес, где располагаются требуемые нам байты.

Взлом программ отладчиком OllyDbg

Вводим 401000.

Взлом программ отладчиком OllyDbg

Видим, что:

Взлом программ отладчиком OllyDbg

Красным выделены изменённые Олли байты. Первым идут два 90, а затем E8, FF и все остальные байты, относящиеся к следующей за NOP'ами инструкцией, которой является CALL.

Может Олли вернуть обратно изменённые нами байты?

Хе-хе, да, может.

В любом из двух окон - DUMP или листинге, отмечаем оба байта.

Взлом программ отладчиком OllyDbg

Потом кликаем на правую кнопку мыши и выбираем "UNDO SELECTION"

Взлом программ отладчиком OllyDbg

И затем снова появляется изначальный PUSH.

Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

Это всё, что касается инструкции NOP.

ИНСТРУКЦИИ СТЕКА



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

Далее следуют инструкции для помещения или удаления "писем".

PUSH

Инструкция PUSH - типичная инструкция для помещения "письма" или значения на стек. Мы можем видеть, что первая инструкция в крэкми CrueHead'а - это PUSH.

Взлом программ отладчиком OllyDbg

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

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

Взлом программ отладчиком OllyDbg

Это стек на моей машине. Адрес 12FFC4 может отличеаться у вас, так как стек каждый раз может располагаться по разному адресу, и его начальное содержимое также может отличаться, то есть у вас может быть значение, отличное от 7c816d4f. По нажатию F7 на самый верх попадёт ноль, а всё остальное окажется внизу него. Нажмём F7.

Взлом программ отладчиком OllyDbg

Видим, что по нажатию F7, ноль словно присоединился сверху того, что мы уже видели. Внизу по адресу 12ffc4 по-прежнему находится значение 7c816d4f, и ни одного из других значений в стеке также не изменилось.

Главным отличием является то, что самое верхнее значение стека находится теперь по адресу 12ffc0 (именно там и неаохдится ноль, который мы поместили с помощью инструкции PUSH), это действительно как положить поверх пачки писем новое, которое окажется на самом верху, а остальные - под ним, но ничего в них не изменится.

Также видим, что ESP, в котором находится адрес самого верхнего значения стека, теперь содержит 12FFc0.

Взлом программ отладчиком OllyDbg

Конечно, инструкция PUSH имеет несколько вариантов, позволяющих помещать в стек не только числа:

PUSH EAX помещает значение EAX на верх стека. Подобным образом мы можем поместить в стек значение любого регистра, числа и т.п.

Также можно поместить значение, находящееся в памяти по определённому адресу:
PUSH [401008]


Обратите внимание, что это будет интерпретироватиться отличным образом от следующего:
PUSH 401008


(Без квадратных скобок)

Если выполним 'PUSH 401008', то в стек будет помещено число 401008.

Взлом программ отладчиком OllyDbg

После выполнения имеем следующее:

Взлом программ отладчиком OllyDbg

Если заменить на 'PUSH [401008]'

Взлом программ отладчиком OllyDbg

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

С помощью "GOTO EXPRESSION 401008" видим:

Взлом программ отладчиком OllyDbg

В этих четырёх байтах находятся CA 20 40 00. Запускаем PUSH с помощью F7.

Взлом программ отладчиком OllyDbg

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

Это одно из свойств процессора: при чтении или записи содержимого из/в память байты всегда переворачиваются. Жалуйтесь по этому поводу производителю процессора, хе-хе.

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

Теперь видим, что Олли, когда пишем 'PUSH [401000]' интерпретирует и отображает

Взлом программ отладчиком OllyDbg
PUSH DWORD PTR DS:[401008]


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

POP

Инструкция POP является обратной по отношению к PUSH: она достаёт первое письмо или первое значение из стека и помещает его в указанное параметром инструкции место назначения. Например, POP EAX берёт первое значение из стека и помещает его в EAX, после чего то значение, которое шло следующим, станосится верхним.

Видимо, что в начале крэкми CrueHead'а есть следующая инструкция:

Взлом программ отладчиком OllyDbg

Заменим данную инструкцию на 'POP EAX', отметив первую строку и нажав "пробел":

Взлом программ отладчиком OllyDbg

Взлом программ отладчиком OllyDbg

Вот что будет содержать стек до выполнения этой инструкции:

Взлом программ отладчиком OllyDbg

А ESP указывает на 12FFc4, что является адресом верхнего значения, содержащегося в стеке.

Взлом программ отладчиком OllyDbg

И видим что в EAX содержится ноль (в моём случае).

Нажимаем F7.

Взлом программ отладчиком OllyDbg

Видим, что в стеке исчезло наше первое "письмо", а ESP указывает на 12ffc8.

Взлом программ отладчиком OllyDbg

Но куда делось наше "письмо"? Так как инструкция был 'POP EAX', то видим, что сейчас EAX содержит значение 7c816d4f - это в моём случае, а в вашем там будет то занчение, которое лежало сверху стека.

Таким же образом, если бы была инструкция 'POP ECX' то верхнее значение было бы помещено в ECX или иной регистр, который был бы указан.

Итак, мы рассмотрели инструкции, которые помещают или берут из стека значения по одному за раз.

PUSHAD

PUSHAD помещает содержимое регистров в стек в определённом порядке, то есть PUSHAD эквивалентно 'push EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI'.

Посмотрим, правда ли то, что нам говорит камрад CAOS REPTANTE в своём туториале про ассемблер, хе-хе.

Загрузим снова крэкми CrueHead'а, вызовем меню для замены инструкции и напишем PUSHAD.

Взлом программ отладчиком OllyDbg

Взлом программ отладчиком OllyDbg

Это мой начальный стек и состояние регистров до выполнения регистров.

Взлом программ отладчиком OllyDbg

Нажимаем F7 и видим, что теперь находится в стеке:

Взлом программ отладчиком OllyDbg

Видим, что все регистры были подвергнуты PUSH'у. По адресу 12ffc4 находится значение, которое лежало сверху стека до выполнения инструкции, а сейчас после него лежит ноль (PUSH EAX), затем содержимое ECX, а в 12ffb0 - то, что находилось в ECX. Дальше находится содержимое регистров от ESP до EDI.

POPAD

Обратной по отношению к PUSHAD инструкцией является POPAD, которая берёт значения из стека и помещает их в соответствующие регистры. POPAD эквивалентна 'pop EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX'.

Как и в предыдущем примере введём инструкцию POPAD:

Взлом программ отладчиком OllyDbg
Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

Комбинация PUSHAD-POPAD часто используется, когда нужно за раз сохранить содержимое всех регистров, потом совершить какие-то другие операции, меняющие значение регистра и стека, а затем восстановить их изначальное состояние с помощью POPAD.

Существуют также следующие варианты:

PUSHA и POPA похожи на своих сестёр PUSHAD и POPAD, не считая того, что используются в 16-ти битных программах, поэтому нас они не интересуют, так как OLLYDBG - это отладчик для 32-х битных программ.

ИНСТРУКЦИИ ДЛЯ ПЕРЕМЕЩЕНИЯ ДАННЫХ



MOV

Эта инструкция перемещает второй операнд в первый, например:
MOV EAX, EBX


Здесь идёт перемещение значения EBX в EAX. Смотрим в Олли и наше старое доброе крэкми от CrueHead'а.

Взлом программ отладчиком OllyDbg

Уже не буду повторять, как ввести нужную нам инструкцию, просто смотрим регистры:

Взлом программ отладчиком OllyDbg

На моей машине EAX содержит 0, а ECX 7c91eb94. Эти начальные значения могут у вас отличаться, но важно то, что по нажатию F7 значение EBX переместиться в EAX, так что нажмём на эту клавишу.

Взлом программ отладчиком OllyDbg

Понятно?

У MOV есть разные варианты, например:
MOV AL, CL


Это перемещает содержимое CL в AL. Напишем эту инструкцию в Олли.

Взлом программ отладчиком OllyDbg

Регистры:

Взлом программ отладчиком OllyDbg

Помните, что AL - это две последних цифры EAX и CL - две последних цифры ECX. Нажмём F7.

Взлом программ отладчиком OllyDbg

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

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

Взлом программ отладчиком OllyDbg

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

Идём в DUMP и делаем GOTO EXPESSION 405000.

Взлом программ отладчиком OllyDbg

Взлом программ отладчиком OllyDbg

Видим, что содержимое ячейки памяти - 00 10 00 00. Так как в памяти содержимое хранится в перевёрнутом виде, то в EAX попадёт 00 00 10 00. Нажимаем F7 и смотрим, что получилось.

Взлом программ отладчиком OllyDbg

Вот значение 1000, которое было прочитано из памяти. Теперь если хотим записать значение по данному адресу:
MOV DWORD PTR DS:[400500],EAX


Введём эту инструкцию.

Взлом программ отладчиком OllyDbg

С помощью DUMP видим по адресу 405000:

Взлом программ отладчиком OllyDbg

Однако по нажатию на F7 происходит облом:

Взлом программ отладчиком OllyDbg Вылетает исключение, и это происходит из-за того, что хотим записать в секцию, в которую писать, то есть изменять в ней байты, запрещено.Ок, как менять права на работу с секциями мы узнаем потом, пока важно изучить инструкции. Очевидно, что если для перемещания 4 байтов испольется слово DWORD, то для перемещения двух байтов используем WORD, а слово BYTE - для перемещения одного.

Смотрим.
MOV AX,WORD PTR DS:[405008]


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

С помощью DUMP смотрим, что находится по адресу 405000.

Взлом программ отладчиком OllyDbg

Взлом программ отладчиком OllyDbg

По нажатию F7 должны переместить только эти два байта в AX. Проверяем:

Взлом программ отладчиком OllyDbg

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

Таким же образом испольуется BYTE.
MOV AL, BYTE PTR DS:[405008]


В данном случае в AL перемещается только последний байт, то есть 08.

Взлом программ отладчиком OllyDbg

MOVSX (Move with Sign-Extension)

Копирует содержимое второго операнда, который может быть регистром или адресом памяти, в первый (который должен быть в два раза больше, чем второй), заполняя остальные биты слева значением самого значимого бита второго операнда. Далее идёт пример.

Определение взято из туториала CAOS'а. Сейчас мы попробуем тестовый пример в OllyDbg, для чего используем нашего друга CrueHead'а.

Взлом программ отладчиком OllyDbg

Не буду здесь много говорить, так как хочу, чтобы вы всё сделали сами и поискали значения операнда самостоятельно, хе-хе. В OllyDbg есть окошко с поясненениям прямо снизу листинга и сверху окна DUMP.

Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

И также видим, что EAX содержит ноль, так что OllyDbg нам всегда помогает интерпретировать инструкцию, которая будет выполнена (надеюсь, что вы освоили концепцию того, где и что нужно искать, хе-хе).

Нажимаем F7.

Взлом программ отладчиком OllyDbg

Видим, что в AX скопировался BX, который содержал F000, и что остальное место заполнилось FFFF, так как F000 - отрицательное 16-ти битное число. Если бы BX содержал 1234, то EAX был бы равен 00001234, то есть левые байты были бы забиты нулями, так как 1234 - положительное 16-ти битное число.

Концепция положительных и отрицательных чисел в 16-ти битах работает так же как и для 32-х битных, только в интервале от 0000 до FFFF. Числа от 0000 до 7FFF являются положительными, а все, что выше до FFFF - отрицательными. Давайте посмотрим, что будет, если мы изменим BX на 7FFF, а EAX на ноль и снова выполним инструкцию.

Взлом программ отладчиком OllyDbg

В AX было скопировано 7FFF, а остальное - забито нулями, так как 7FFF является положительным числом. Проделаем то же самое с BX=8000 (отрицательное).

Взлом программ отладчиком OllyDbg

Выполним инструкцию по-новой с помощью F7.

Взлом программ отладчиком OllyDbg

В BX было скопировано 8000, а в остальное FFFF, так как 8000 является отрицательным числом.

MOVZX (Move with Zero-Extend)

MOVZX похож на предыдущую инструкцию, но в данном случае свободное место просто заполняется нулями и не зависит от того, является ли второй оператор положительным или нет. Не будем приводить примеры для этой инструкции, так как они похожи на те, что выше, за исключением того, что в верхней части EAX всегда будет 0000. В AX же будет копироваться BX.

LEA (Load Effective Address)

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

Введём в OllyDbg следующую инструкцию:

Взлом программ отладчиком OllyDbg

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

В моём случае ECX равен 12FFb0.

Взлом программ отладчиком OllyDbg

И в это примере LEA прибавит к значению ECX 38 и полученное значение поместит в EAX.

В окне пояснений будут отображены оба операнда.

Взлом программ отладчиком OllyDbg

Оно показывает, что операнд равен 12Ffe8, что является суммой ECX+38, а EAX до выполнения инструкции содержит ноль.

Нажимаем F7.

Взлом программ отладчиком OllyDbg

Указанный адрес был помещён в EAX, хотя квадратные скобки могли заставить нас подумать, что туда должно было быть помещено содержимое, находящееся по этому адресу, как бы это сделала инструкция MOV, но LEA просто поместила адрес в первый операнд, а не его содержимое.

XCHG (Exchange Register/Memory with Register)

Эта инструкция обменивает содержимое двух операндов, например:
XCHG EAX,ECX


Значение EAX будет помещено в ECX и наоборот. Проверим это в Олли.

Взлом программ отладчиком OllyDbg

На моей машине до выполнения EAX содержал ноль, а ECX - 12FFb0.

Взлом программ отладчиком OllyDbg

Нажав F7, увидим, что они обменялись значениями.

Взлом программ отладчиком OllyDbg

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

Взлом программ отладчиком OllyDbg

По нажатию на F7:

Взлом программ отладчиком OllyDbg

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

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

  [C] Рикардо Нарваха, пер. Aquila

Обсуждение статьи: Ассемблер. Инструкции стека и перемещения данных. Крэкинг ч.4 >>>


При перепечатке ссылка на https://exelab.ru обязательна.



Видеокурс ВЗЛОМ