;в глобальной таблице дескрипторов
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_ds desc_struc
gdt_cs desc_struc
gdt_ss desc_struc
GDT_SIZE=($–GDT_BEG)
END start
Обход резидентных антивирусных мониторов
Обычно все программы используют сервис DOS так:
mov ah,... int 21h
По команде INT управление передается в точку, адрес которой определяется двумя словами, находящимися в таблице векторов прерываний по адресу 0000h:0084h. С этого момента начинается исполнение команд многочисленных обработчиков прерывания INT 21h и не менее многочисленных резидентных программ до тех пор, пока управление, наконец, не получит оригинальный обработчик операционной системы (рис. 5.1):
Читать дальше
Конец ознакомительного отрывка
Купить книгу